mirror of https://github.com/svaarala/duktape.git
Browse Source
Add duk_push_buffer_object() API for pushing buffer objects (e.g. Node.js Buffer, ArrayBuffer) and buffer views (e.g. Uint32Array) directly from C code.cyclic-jx-gh331
Sami Vaarala
9 years ago
9 changed files with 653 additions and 54 deletions
@ -0,0 +1,422 @@ |
|||
/*
|
|||
* duk_push_buffer_object() API call |
|||
*/ |
|||
|
|||
static void register_dump_buffer_info(duk_context *ctx) { |
|||
duk_eval_string_noresult(ctx, |
|||
"function dumpBufferInfo (v) {\n" |
|||
" var p = Object.getPrototypeOf(v);\n" |
|||
" var instof = [];\n" |
|||
" var prot = [];\n" |
|||
|
|||
" if (v instanceof Duktape.Buffer) { instof.push('Duktape.Buffer'); }\n" |
|||
" if (v instanceof Buffer) { instof.push('Buffer'); }\n" |
|||
" if (v instanceof ArrayBuffer) { instof.push('ArrayBuffer'); }\n" |
|||
" if (v instanceof DataView) { instof.push('DataView'); }\n" |
|||
" if (v instanceof Int8Array) { instof.push('Int8Array'); }\n" |
|||
" if (v instanceof Uint8Array) { instof.push('Uint8Array'); }\n" |
|||
" if (v instanceof Uint8ClampedArray) { instof.push('Uint8ClampedArray'); }\n" |
|||
" if (v instanceof Int16Array) { instof.push('Int16Array'); }\n" |
|||
" if (v instanceof Uint16Array) { instof.push('Uint16Array'); }\n" |
|||
" if (v instanceof Int32Array) { instof.push('Int32Array'); }\n" |
|||
" if (v instanceof Uint32Array) { instof.push('Uint32Array'); }\n" |
|||
" if (v instanceof Float32Array) { instof.push('Float32Array'); }\n" |
|||
" if (v instanceof Float64Array) { instof.push('Float64Array'); }\n" |
|||
|
|||
" if (p === Duktape.Buffer.prototype) { prot.push('Duktape.Buffer.prototype'); }\n" |
|||
" if (p === Buffer.prototype) { prot.push('Buffer.prototype'); }\n" |
|||
" if (p === ArrayBuffer.prototype) { prot.push('ArrayBuffer.prototype'); }\n" |
|||
" if (p === DataView.prototype) { prot.push('DataView.prototype'); }\n" |
|||
" if (p === Int8Array.prototype) { prot.push('Int8Array.prototype'); }\n" |
|||
" if (p === Uint8Array.prototype) { prot.push('Uint8Array.prototype'); }\n" |
|||
" if (p === Uint8ClampedArray.prototype) { prot.push('Uint8ClampedArray.prototype'); }\n" |
|||
" if (p === Int16Array.prototype) { prot.push('Int16Array.prototype'); }\n" |
|||
" if (p === Uint16Array.prototype) { prot.push('Uint16Array.prototype'); }\n" |
|||
" if (p === Int32Array.prototype) { prot.push('Int32Array.prototype'); }\n" |
|||
" if (p === Uint32Array.prototype) { prot.push('Uint32Array.prototype'); }\n" |
|||
" if (p === Float32Array.prototype) { prot.push('Float32Array.prototype'); }\n" |
|||
" if (p === Float64Array.prototype) { prot.push('Float64Array.prototype'); }\n" |
|||
|
|||
" print(typeof v, Object.prototype.toString.call(v), v.length, v.byteOffset, v.byteLength, v.BYTES_PER_ELEMENT, typeof v.buffer);\n" |
|||
" print(v instanceof Duktape.Buffer, v instanceof Buffer, v instanceof ArrayBuffer, v instanceof DataView, v instanceof Int8Array, v instanceof Uint8Array, v instanceof Uint8ClampedArray, v instanceof Int16Array, v instanceof Uint16Array, v instanceof Int32Array, v instanceof Uint32Array, v instanceof Float32Array, v instanceof Float64Array, '->', instof.join(','));\n" |
|||
" print(p === Duktape.Buffer.prototype, p === Buffer.prototype, p === ArrayBuffer.prototype, p === DataView.prototype, p === Int8Array.prototype, p === Uint8Array.prototype, p === Uint8ClampedArray.prototype, p === Int16Array.prototype, p === Uint16Array.prototype, p === Int32Array.prototype, p === Uint32Array.prototype, p === Float32Array.prototype, p === Float64Array.prototype, '->', prot.join(','));\n" |
|||
"}"); |
|||
} |
|||
|
|||
/*===
|
|||
*** test_basic (duk_safe_call) |
|||
object [object Buffer] 32 128 32 1 undefined |
|||
true false false false false false false false false false false false false -> Duktape.Buffer |
|||
true false false false false false false false false false false false false -> Duktape.Buffer.prototype |
|||
object [object Buffer] 32 128 32 1 undefined |
|||
false true false false false false false false false false false false false -> Buffer |
|||
false true false false false false false false false false false false false -> Buffer.prototype |
|||
object [object ArrayBuffer] 32 128 32 1 undefined |
|||
false false true false false false false false false false false false false -> ArrayBuffer |
|||
false false true false false false false false false false false false false -> ArrayBuffer.prototype |
|||
object [object DataView] 32 128 32 1 object |
|||
false false false true false false false false false false false false false -> DataView |
|||
false false false true false false false false false false false false false -> DataView.prototype |
|||
object [object Int8Array] 32 128 32 1 object |
|||
false false false false true false false false false false false false false -> Int8Array |
|||
false false false false true false false false false false false false false -> Int8Array.prototype |
|||
object [object Uint8Array] 32 128 32 1 object |
|||
false false false false false true false false false false false false false -> Uint8Array |
|||
false false false false false true false false false false false false false -> Uint8Array.prototype |
|||
object [object Uint8ClampedArray] 32 128 32 1 object |
|||
false false false false false false true false false false false false false -> Uint8ClampedArray |
|||
false false false false false false true false false false false false false -> Uint8ClampedArray.prototype |
|||
object [object Int16Array] 16 128 32 2 object |
|||
false false false false false false false true false false false false false -> Int16Array |
|||
false false false false false false false true false false false false false -> Int16Array.prototype |
|||
object [object Uint16Array] 16 128 32 2 object |
|||
false false false false false false false false true false false false false -> Uint16Array |
|||
false false false false false false false false true false false false false -> Uint16Array.prototype |
|||
object [object Int32Array] 8 128 32 4 object |
|||
false false false false false false false false false true false false false -> Int32Array |
|||
false false false false false false false false false true false false false -> Int32Array.prototype |
|||
object [object Uint32Array] 8 128 32 4 object |
|||
false false false false false false false false false false true false false -> Uint32Array |
|||
false false false false false false false false false false true false false -> Uint32Array.prototype |
|||
object [object Float32Array] 8 128 32 4 object |
|||
false false false false false false false false false false false true false -> Float32Array |
|||
false false false false false false false false false false false true false -> Float32Array.prototype |
|||
object [object Float64Array] 4 128 32 8 object |
|||
false false false false false false false false false false false false true -> Float64Array |
|||
false false false false false false false false false false false false true -> Float64Array.prototype |
|||
final top: 0 |
|||
==> rc=0, result='undefined' |
|||
===*/ |
|||
|
|||
static duk_ret_t test_basic(duk_context *ctx) { |
|||
duk_uint_t test[] = { |
|||
DUK_BUFOBJ_DUKTAPE_BUFFER, |
|||
DUK_BUFOBJ_NODEJS_BUFFER, |
|||
DUK_BUFOBJ_ARRAYBUFFER, |
|||
DUK_BUFOBJ_DATAVIEW, |
|||
DUK_BUFOBJ_INT8ARRAY, |
|||
DUK_BUFOBJ_UINT8ARRAY, |
|||
DUK_BUFOBJ_UINT8CLAMPEDARRAY, |
|||
DUK_BUFOBJ_INT16ARRAY, |
|||
DUK_BUFOBJ_UINT16ARRAY, |
|||
DUK_BUFOBJ_INT32ARRAY, |
|||
DUK_BUFOBJ_UINT32ARRAY, |
|||
DUK_BUFOBJ_FLOAT32ARRAY, |
|||
DUK_BUFOBJ_FLOAT64ARRAY, |
|||
}; |
|||
int i; |
|||
unsigned char extbuf[256]; |
|||
|
|||
for (i = 0; i < sizeof(test) / sizeof(duk_uint_t); i++) { |
|||
switch (i % 3) { |
|||
case 0: |
|||
duk_push_fixed_buffer(ctx, 256); |
|||
break; |
|||
case 1: |
|||
duk_push_dynamic_buffer(ctx, 256); |
|||
break; |
|||
case 2: |
|||
duk_push_external_buffer(ctx); |
|||
duk_config_buffer(ctx, -1, (void *) extbuf, 256); |
|||
break; |
|||
} |
|||
|
|||
duk_push_undefined(ctx); /* dummy */ |
|||
|
|||
duk_push_buffer_object(ctx, -2, 128, 32, test[i]); |
|||
|
|||
duk_eval_string(ctx, "dumpBufferInfo"); |
|||
duk_dup(ctx, -2); |
|||
duk_call(ctx, 1); |
|||
|
|||
/* ... plain undefined bufferobject result */ |
|||
duk_pop_n(ctx, 4); |
|||
} |
|||
|
|||
printf("final top: %ld\n", (long) duk_get_top(ctx)); |
|||
return 0; |
|||
} |
|||
|
|||
/*===
|
|||
*** test_view_buffer_prop (duk_safe_call) |
|||
[object Uint8Array] |
|||
object [object Uint8Array] 22 16 22 1 object |
|||
false false false false false true false false false false false false false -> Uint8Array |
|||
false false false false false true false false false false false false false -> Uint8Array.prototype |
|||
22 |
|||
16 |
|||
22 |
|||
1 |
|||
[object ArrayBuffer] |
|||
[object ArrayBuffer] false false false |
|||
[object ArrayBuffer] |
|||
object [object ArrayBuffer] 22 16 22 1 undefined |
|||
false false true false false false false false false false false false false -> ArrayBuffer |
|||
false false true false false false false false false false false false false -> ArrayBuffer.prototype |
|||
22 |
|||
16 |
|||
22 |
|||
1 |
|||
undefined |
|||
123 123 |
|||
extbuf[16 + 3] = 123 |
|||
final top: 1 |
|||
==> rc=0, result='undefined' |
|||
===*/ |
|||
|
|||
/* The basic test ensures all typed array views get a .buffer property.
|
|||
* Test the .buffer reference in more detail: check that property |
|||
* attributes are correct, check that it backs to the same slice, etc. |
|||
*/ |
|||
static duk_ret_t test_view_buffer_prop(duk_context *ctx) { |
|||
unsigned char extbuf[256]; |
|||
|
|||
duk_push_external_buffer(ctx); |
|||
duk_config_buffer(ctx, -1, (void *) extbuf, 256); |
|||
duk_push_buffer_object(ctx, -1, 16, 22, DUK_BUFOBJ_UINT8ARRAY); |
|||
|
|||
duk_eval_string(ctx, |
|||
"(function (v) {\n" |
|||
" var pd;\n" |
|||
" print(Object.prototype.toString.call(v));\n" |
|||
" dumpBufferInfo(v);\n" |
|||
" print(v.length);\n" |
|||
" print(v.byteOffset);\n" |
|||
" print(v.byteLength);\n" |
|||
" print(v.BYTES_PER_ELEMENT);\n" |
|||
" print(v.buffer);\n" |
|||
" pd = Object.getOwnPropertyDescriptor(v, 'buffer');\n" |
|||
" print(pd.value, pd.writable, pd.enumerable, pd.configurable);\n" |
|||
" print(Object.prototype.toString.call(v.buffer));\n" |
|||
" dumpBufferInfo(v.buffer);\n" |
|||
" print(v.buffer.length);\n" /* some of these are Duktape custom */ |
|||
" print(v.buffer.byteOffset);\n" |
|||
" print(v.buffer.byteLength);\n" |
|||
" print(v.buffer.BYTES_PER_ELEMENT);\n" |
|||
" print(v.buffer.buffer);\n" |
|||
" v[3] = 123; /* check that backing buffer and slice matches */\n" |
|||
" print(v[3], new Uint8Array(v.buffer)[3]);\n" |
|||
"})"); |
|||
duk_dup(ctx, -2); |
|||
duk_call(ctx, 1); |
|||
duk_pop_2(ctx); |
|||
|
|||
printf("extbuf[16 + 3] = %d\n", (int) extbuf[16 + 3]); |
|||
|
|||
printf("final top: %ld\n", (long) duk_get_top(ctx)); |
|||
return 0; |
|||
} |
|||
|
|||
/*===
|
|||
*** test_unaligned (duk_safe_call) |
|||
object [object Uint32Array] 16 7 64 4 object |
|||
false false false false false false false false false false true false false -> Uint32Array |
|||
false false false false false false false false false false true false false -> Uint32Array.prototype |
|||
final top: 0 |
|||
==> rc=0, result='undefined' |
|||
===*/ |
|||
|
|||
/* Normally typed array constructors require that the slice begin at a multiple
|
|||
* of the element size (e.g. 4 bytes for Uint32Array) and that the slice ends |
|||
* evenly. The C API doesn't pose such restrictions. |
|||
*/ |
|||
static duk_ret_t test_unaligned(duk_context *ctx) { |
|||
duk_push_fixed_buffer(ctx, 256); |
|||
duk_push_buffer_object(ctx, -1, 7, 64, DUK_BUFOBJ_UINT32ARRAY); |
|||
|
|||
duk_eval_string(ctx, "dumpBufferInfo"); |
|||
duk_dup(ctx, -2); |
|||
duk_call(ctx, 1); |
|||
duk_pop(ctx); |
|||
|
|||
duk_pop_n(ctx, 2); |
|||
|
|||
printf("final top: %ld\n", (long) duk_get_top(ctx)); |
|||
return 0; |
|||
} |
|||
|
|||
/*===
|
|||
*** test_unaligned_uneven (duk_safe_call) |
|||
object [object Uint32Array] 15 7 63 4 object |
|||
false false false false false false false false false false true false false -> Uint32Array |
|||
false false false false false false false false false false true false false -> Uint32Array.prototype |
|||
final top: 0 |
|||
==> rc=0, result='undefined' |
|||
===*/ |
|||
|
|||
/* Normally typed array constructors require that the slice begin at a multiple
|
|||
* of the element size (e.g. 4 bytes for Uint32Array) and that the slice ends |
|||
* evenly. The C API doesn't pose such restrictions; the .length (number of |
|||
* elements) will become the number of full elements allowed by the slice. |
|||
* The .byteOffset and .byteLength will reflect the call arguments, e.g. |
|||
* .byteLength is 63 here, which means that .length x .BYTES_PER_ELEMENT |
|||
* won't match .byteLength in this case. |
|||
*/ |
|||
static duk_ret_t test_unaligned_uneven(duk_context *ctx) { |
|||
/* Start at an unaligned offset, with slice length NOT a multiple
|
|||
* of 4. |
|||
*/ |
|||
duk_push_fixed_buffer(ctx, 256); |
|||
duk_push_buffer_object(ctx, -1, 7, 63, DUK_BUFOBJ_UINT32ARRAY); |
|||
|
|||
duk_eval_string(ctx, "dumpBufferInfo"); |
|||
duk_dup(ctx, -2); |
|||
duk_call(ctx, 1); |
|||
duk_pop(ctx); |
|||
|
|||
duk_pop_n(ctx, 2); |
|||
|
|||
printf("final top: %ld\n", (long) duk_get_top(ctx)); |
|||
return 0; |
|||
} |
|||
|
|||
/*===
|
|||
*** test_uncovered (duk_safe_call) |
|||
object [object Uint32Array] 128 7 512 4 object |
|||
false false false false false false false false false false true false false -> Uint32Array |
|||
false false false false false false false false false false true false false -> Uint32Array.prototype |
|||
final top: 0 |
|||
==> rc=0, result='undefined' |
|||
===*/ |
|||
|
|||
/* It's not an error for the underlying plain buffer to be too small to
|
|||
* cover the slice. This is allowed because it may happen for dynamic |
|||
* and external buffers at run time anyway. In any case, no memory |
|||
* unsafe behavior happens. |
|||
*/ |
|||
static duk_ret_t test_uncovered(duk_context *ctx) { |
|||
duk_push_fixed_buffer(ctx, 256); |
|||
duk_push_buffer_object(ctx, -1, 7, 512, DUK_BUFOBJ_UINT32ARRAY); |
|||
|
|||
duk_eval_string(ctx, "dumpBufferInfo"); |
|||
duk_dup(ctx, -2); |
|||
duk_call(ctx, 1); |
|||
duk_pop(ctx); |
|||
|
|||
duk_eval_string(ctx, |
|||
"(function (v) {\n" |
|||
" for (var i = 0; i < v.length; i++) { v[i] = 123; }\n" |
|||
" for (var i = 0; i < v.length; i++) { var ignore = v[i]; }\n" |
|||
"})"); |
|||
duk_dup(ctx, -2); |
|||
duk_call(ctx, 1); |
|||
duk_pop(ctx); |
|||
|
|||
duk_pop_n(ctx, 2); |
|||
|
|||
printf("final top: %ld\n", (long) duk_get_top(ctx)); |
|||
return 0; |
|||
} |
|||
|
|||
/*===
|
|||
*** test_invalid_index1 (duk_safe_call) |
|||
==> rc=1, result='TypeError: unexpected type' |
|||
*** test_invalid_index2 (duk_safe_call) |
|||
==> rc=1, result='TypeError: unexpected type' |
|||
===*/ |
|||
|
|||
static duk_ret_t test_invalid_index1(duk_context *ctx) { |
|||
duk_push_fixed_buffer(ctx, 256); |
|||
duk_push_buffer_object(ctx, -2, 7, 512, DUK_BUFOBJ_UINT32ARRAY); |
|||
printf("final top: %ld\n", (long) duk_get_top(ctx)); |
|||
return 0; |
|||
} |
|||
|
|||
static duk_ret_t test_invalid_index2(duk_context *ctx) { |
|||
duk_push_fixed_buffer(ctx, 256); |
|||
duk_push_buffer_object(ctx, DUK_INVALID_INDEX, 7, 512, DUK_BUFOBJ_UINT32ARRAY); |
|||
printf("final top: %ld\n", (long) duk_get_top(ctx)); |
|||
return 0; |
|||
} |
|||
|
|||
/*===
|
|||
*** test_invalid_bufferobject (duk_safe_call) |
|||
==> rc=1, result='TypeError: unexpected type' |
|||
*** test_invalid_string (duk_safe_call) |
|||
==> rc=1, result='TypeError: unexpected type' |
|||
*** test_invalid_null (duk_safe_call) |
|||
==> rc=1, result='TypeError: unexpected type' |
|||
===*/ |
|||
|
|||
/* A bufferobject is -not- accepted as the underlying buffer. This also
|
|||
* prevents issues like a slice being applied to a sliced view. |
|||
*/ |
|||
static duk_ret_t test_invalid_bufferobject(duk_context *ctx) { |
|||
duk_eval_string(ctx, "new Uint16Array(123);"); |
|||
duk_push_buffer_object(ctx, -1, 7, 512, DUK_BUFOBJ_UINT32ARRAY); |
|||
printf("final top: %ld\n", (long) duk_get_top(ctx)); |
|||
return 0; |
|||
} |
|||
|
|||
/* A string is not allowed (although this might be useful). */ |
|||
static duk_ret_t test_invalid_string(duk_context *ctx) { |
|||
duk_push_string(ctx, "foobar"); |
|||
duk_push_buffer_object(ctx, -1, 7, 512, DUK_BUFOBJ_UINT32ARRAY); |
|||
printf("final top: %ld\n", (long) duk_get_top(ctx)); |
|||
return 0; |
|||
} |
|||
|
|||
static duk_ret_t test_invalid_null(duk_context *ctx) { |
|||
duk_push_null(ctx); |
|||
duk_push_buffer_object(ctx, -1, 7, 512, DUK_BUFOBJ_UINT32ARRAY); |
|||
printf("final top: %ld\n", (long) duk_get_top(ctx)); |
|||
return 0; |
|||
} |
|||
|
|||
/*===
|
|||
*** test_invalid_flags1 (duk_safe_call) |
|||
final top: 2 |
|||
==> rc=0, result='undefined' |
|||
*** test_invalid_flags2 (duk_safe_call) |
|||
==> rc=1, result='TypeError: invalid call args' |
|||
*** test_invalid_flags3 (duk_safe_call) |
|||
==> rc=1, result='TypeError: invalid call args' |
|||
===*/ |
|||
|
|||
/* If 'flags' is given as zero, it will match a DUK_BUFOBJ_DUKTAPEBUFFER.
|
|||
* So this test succeeds which is intentional. |
|||
*/ |
|||
static duk_ret_t test_invalid_flags1(duk_context *ctx) { |
|||
duk_push_fixed_buffer(ctx, 256); |
|||
duk_push_buffer_object(ctx, -1, 7, 512, 0 /* no type given, but matches DUK_BUFOBJ_DUKTAPEBUFFER */); |
|||
printf("final top: %ld\n", (long) duk_get_top(ctx)); |
|||
return 0; |
|||
} |
|||
|
|||
static duk_ret_t test_invalid_flags2(duk_context *ctx) { |
|||
duk_push_fixed_buffer(ctx, 256); |
|||
duk_push_buffer_object(ctx, -1, 7, 512, (duk_uint_t) 0xdeadbeef /* ERROR: bogus type */); |
|||
printf("final top: %ld\n", (long) duk_get_top(ctx)); |
|||
return 0; |
|||
} |
|||
|
|||
/* Boundary case. */ |
|||
static duk_ret_t test_invalid_flags3(duk_context *ctx) { |
|||
duk_push_fixed_buffer(ctx, 256); |
|||
duk_push_buffer_object(ctx, -1, 7, 512, (duk_uint_t) (DUK_BUFOBJ_FLOAT64ARRAY + 1) /* ERROR: bogus type, right after last defined */); |
|||
printf("final top: %ld\n", (long) duk_get_top(ctx)); |
|||
return 0; |
|||
} |
|||
|
|||
/*
|
|||
* Main |
|||
*/ |
|||
|
|||
void test(duk_context *ctx) { |
|||
register_dump_buffer_info(ctx); |
|||
|
|||
TEST_SAFE_CALL(test_basic); |
|||
TEST_SAFE_CALL(test_view_buffer_prop); |
|||
TEST_SAFE_CALL(test_unaligned); |
|||
TEST_SAFE_CALL(test_unaligned_uneven); |
|||
TEST_SAFE_CALL(test_uncovered); |
|||
TEST_SAFE_CALL(test_invalid_index1); |
|||
TEST_SAFE_CALL(test_invalid_index2); |
|||
TEST_SAFE_CALL(test_invalid_bufferobject); |
|||
TEST_SAFE_CALL(test_invalid_string); |
|||
TEST_SAFE_CALL(test_invalid_null); |
|||
TEST_SAFE_CALL(test_invalid_flags1); |
|||
TEST_SAFE_CALL(test_invalid_flags2); |
|||
TEST_SAFE_CALL(test_invalid_flags3); |
|||
/* XXX: could test for more errors */ |
|||
} |
@ -0,0 +1,65 @@ |
|||
name: duk_push_buffer |
|||
|
|||
proto: | |
|||
void duk_push_buffer_object(duk_context *ctx, duk_idx_t idx_buffer, duk_uint_t byte_offset, duk_uint_t byte_length, duk_uint_t flags); |
|||
|
|||
stack: | |
|||
[ ... buffer! ... ] -> [ ... buffer! ... bufobj! ] |
|||
|
|||
summary: | |
|||
<p>Push a new buffer object or a buffer view object. An underlying plain |
|||
buffer is provided at index <code>idx_buffer</code>. The type of the buffer |
|||
or view is given in <code>flags</code> (e.g. <code>DUK_BUFOBJ_UINT16ARRAY</code>). |
|||
The active range or "slice" used from the underlying buffer is indicated by |
|||
<code>byte_offset</code> and <code>byte_length</code>.</p> |
|||
|
|||
<p>The available buffer types are:</p> |
|||
<table> |
|||
<tr><th>Define</th><th>Buffer/view type</th></tr> |
|||
<tr><td>DUK_BUFOBJ_DUKTAPE_BUFFER</td><td>Duktape.Buffer</td></tr> |
|||
<tr><td>DUK_BUFOBJ_NODEJS_BUFFER</td><td>Buffer (Node.js)</td></tr> |
|||
<tr><td>DUK_BUFOBJ_ARRAYBUFFER</td><td>ArrayBuffer</td></tr> |
|||
<tr><td>DUK_BUFOBJ_DATAVIEW</td><td>DataView</td></tr> |
|||
<tr><td>DUK_BUFOBJ_INT8ARRAY</td><td>Int8Array</td></tr> |
|||
<tr><td>DUK_BUFOBJ_UINT8ARRAY</td><td>Uint8Array</td></tr> |
|||
<tr><td>DUK_BUFOBJ_UINT8CLAMPEDARRAY</td><td>Uint8ClampedArray</td></tr> |
|||
<tr><td>DUK_BUFOBJ_INT16ARRAY</td><td>Int16Array</td></tr> |
|||
<tr><td>DUK_BUFOBJ_UINT16ARRAY</td><td>Uint16Array</td></tr> |
|||
<tr><td>DUK_BUFOBJ_INT32ARRAY</td><td>Int32Array</td></tr> |
|||
<tr><td>DUK_BUFOBJ_UINT32ARRAY</td><td>Uint32Array</td></tr> |
|||
<tr><td>DUK_BUFOBJ_FLOAT32ARRAY</td><td>Float32Array</td></tr> |
|||
<tr><td>DUK_BUFOBJ_FLOAT64ARRAY</td><td>Float64Array</td></tr> |
|||
</table> |
|||
|
|||
<p>The underlying plain buffer should cover the range indicated by the |
|||
<code>byte_offset</code> and <code>byte_length</code> arguments. Even |
|||
if that is not the case, memory safety is guaranteed; e.g. attempt to |
|||
read values outside the underlying buffer will return zero. The underlying |
|||
buffer size is intentionally not checked when creating a buffer object: |
|||
even if the buffer fully covered the byte range during creation, it might |
|||
be resized later.</p> |
|||
|
|||
example: | |
|||
/* Map byte range [100,150[ of plain buffer at idx_plain_buf into a |
|||
* Uint16Array object which will have the following properties: |
|||
* |
|||
* - length: 25 (length in Uint16 elements) |
|||
* - byteLength: 50 (length in bytes) |
|||
* - byteOffset: 100 (byte offset to start of slice) |
|||
* - BYTES_PER_ELEMENT: 2 (Uint16) |
|||
*/ |
|||
|
|||
duk_push_buffer_object(ctx, idx_plain_buf, 100, 50, DUK_BUFOBJ_UINT16ARRAY); |
|||
|
|||
tags: |
|||
- stack |
|||
- bufferobject |
|||
- experimental |
|||
|
|||
seealso: |
|||
- duk_push_buffer |
|||
- duk_push_fixed_buffer |
|||
- duk_push_dynamic_buffer |
|||
- duk_push_external_buffer |
|||
|
|||
introduced: 1.3.0 |
Loading…
Reference in new issue