/* Uint8Array, "partial slice" */ static duk_ret_t test_uint8array_indexed_1b(duk_context *ctx, void *udata) { (void) udata; duk_push_dynamic_buffer(ctx, 150); setup_typedarray_slice(ctx, -1, "Uint8Array", 30, 100); shared_read_write_index(ctx, 30 + 95); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
/* ArrayBuffer, "full slice" */ static duk_ret_t test_arraybuffer_indexed_1a(duk_context *ctx, void *udata) { (void) udata; duk_push_dynamic_buffer(ctx, 100); setup_arraybuffer(ctx, -1); shared_read_write_index(ctx, 95); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
/* Node.js Buffer, "partial slice" */ static duk_ret_t test_nodejs_buffer_indexed_1b(duk_context *ctx, void *udata) { (void) udata; duk_push_dynamic_buffer(ctx, 150); setup_nodejs_buffer_slice(ctx, -1, 30, 130); shared_read_write_index(ctx, 30 + 95); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static duk_ret_t test_basic(duk_context *ctx) { duk_idx_t i, n; duk_push_undefined(ctx); duk_push_null(ctx); duk_push_true(ctx); duk_push_false(ctx); duk_push_string(ctx, ""); duk_push_string(ctx, "foo"); duk_push_int(ctx, 123); duk_push_object(ctx); duk_push_fixed_buffer(ctx, 0); duk_push_fixed_buffer(ctx, 1024); duk_push_dynamic_buffer(ctx, 0); duk_push_dynamic_buffer(ctx, 2048); duk_eval_string(ctx, "(function () { return new ArrayBuffer(16); })()"); duk_eval_string(ctx, "(function () { return new Uint32Array(16); })()"); duk_eval_string(ctx, "(function () { return new DataView(new ArrayBuffer(16)); })()"); duk_eval_string(ctx, "(function () { return new Uint32Array(16).subarray(3, 6); })()"); duk_eval_string(ctx, "(function () { return new Buffer('ABCDEFGH'); })()"); duk_eval_string(ctx, "(function () { return new Buffer('ABCDEFGH').slice(3, 6); })()"); n = duk_get_top(ctx); printf("top: %ld\n", (long) n); for (i = 0; i < n; i++) { void *buf; duk_size_t len; len = (duk_size_t) 0xdeadbeefUL; buf = duk_get_buffer_data(ctx, i, &len); if (len == 0) { /* avoid printing 'buf' if len is zero, as it is not predictable */ printf("index %ld: length 0\n", (long) i); } else { printf("index %ld: length %lu, ptr-is-NULL %d\n", (long) i, (unsigned long) len, (buf == NULL ? 1 : 0)); } } printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static duk_ret_t test_1(duk_context *ctx, void *udata) { duk_idx_t i, n; (void) udata; duk_set_top(ctx, 0); duk_push_undefined(ctx); duk_push_null(ctx); duk_push_true(ctx); duk_push_false(ctx); duk_push_int(ctx, 0); duk_push_int(ctx, 1); duk_push_nan(ctx); duk_push_number(ctx, INFINITY); duk_push_string(ctx, ""); duk_push_string(ctx, "foo"); duk_push_object(ctx); duk_push_number(ctx, 123.456); duk_to_object(ctx, -1); /* Number(123.456) */ duk_push_thread(ctx); duk_push_fixed_buffer(ctx, 0); duk_push_fixed_buffer(ctx, 1024); duk_push_dynamic_buffer(ctx, 0); duk_push_dynamic_buffer(ctx, 1024); duk_push_pointer(ctx, (void *) NULL); duk_push_pointer(ctx, (void *) 0xdeadbeef); n = duk_get_top(ctx); printf("top: %ld\n", (long) n); for (i = 0; i < n; i++) { duk_int_t t1, t2; t1 = duk_get_type(ctx, i); duk_to_primitive(ctx, i, DUK_HINT_NONE); t2 = duk_get_type(ctx, i); printf("index %ld, ToString(result): '%s', type: %ld -> %ld\n", (long) i, duk_to_string(ctx, i), (long) t1, (long) t2); } return 0; }
void test(duk_context *ctx) { duk_idx_t i, n; duk_push_undefined(ctx); duk_push_null(ctx); duk_push_boolean(ctx, 0); duk_push_boolean(ctx, 123); duk_push_number(ctx, 234); duk_push_string(ctx, "foo"); duk_push_object(ctx); duk_push_array(ctx); duk_push_c_function(ctx, my_c_func, DUK_VARARGS); duk_push_fixed_buffer(ctx, 1024); duk_push_dynamic_buffer(ctx, 1024); duk_push_pointer(ctx, (void *) 0xdeadbeefUL); n = duk_get_top(ctx); for (i = 0; i < n + 1; i++) { /* end on invalid index on purpose */ duk_int_t typeval, typemask; typeval = duk_get_type(ctx, i); typemask = duk_get_type_mask(ctx, i); printf("stack[%ld] --> type=%ld mask=0x%08lx ", (long) i, (long) typeval, (long) typemask); switch(duk_get_type(ctx, i)) { case DUK_TYPE_NONE: printf("none"); break; case DUK_TYPE_UNDEFINED: printf("undefined"); break; case DUK_TYPE_NULL: printf("null"); break; case DUK_TYPE_BOOLEAN: printf("boolean"); break; case DUK_TYPE_NUMBER: printf("number"); break; case DUK_TYPE_STRING: printf("string"); break; case DUK_TYPE_OBJECT: printf("object"); break; case DUK_TYPE_BUFFER: printf("buffer"); break; case DUK_TYPE_POINTER: printf("pointer"); break; default: printf("unknown(%d)", (int) duk_get_type(ctx, i)); break; } printf(" bool=%d num=%lf str=%s buf-is-null=%d ptr=%p", (int) duk_get_boolean(ctx, i), (double) duk_get_number(ctx, i), duk_get_string(ctx, i), (duk_get_buffer(ctx, i, NULL) == NULL ? 1 : 0), duk_get_pointer(ctx, i)); printf(" isobj=%d isarr=%d isfunc=%d", (int) duk_is_object(ctx, i), (int) duk_is_array(ctx, i), (int) duk_is_function(ctx, i)); printf("\n"); } }
static duk_ret_t test_typedarray_set_1(duk_context *ctx, void *udata) { int i, dst, src; unsigned char *data; (void) udata; data = (unsigned char *) duk_push_dynamic_buffer(ctx, 10); /* index 0 */ for (i = 0; i < 10; i++) { data[i] = 0x40 + i; } /* Some combinations are not set() compatible and cause a RangeError * (source longer than target). But this set should exercise byte copy, * fast copy, and slow copy code paths. */ setup_typedarray(ctx, 0, "Uint8Array"); /* index 1, length 10 */ setup_typedarray_slice(ctx, 0, "Uint8Array", 2, 5); /* index 2, length 5 */ setup_typedarray(ctx, 0, "Uint16Array"); /* index 3, length 5 */ setup_typedarray_slice(ctx, 0, "Uint16Array", 2, 3); /* index 4, length 3 */ duk_eval_string(ctx, "[ 1, 2, 3, 4, 5 ]"); /* index 5, length 5 */ for (i = 10; i >= 0; i--) { duk_resize_buffer(ctx, 0, i); /* Various copy combinations. Resulting buffer is omitted; * when both dst and src are typedarrays they share the same * underlying buffer. so the results are a bit confusing (and * not important to memory safety). */ for (dst = 1; dst <= 4; dst++) { for (src = 1; src <= 5; src++) { printf("%d %d %d\n", i, dst, src); duk_eval_string(ctx, "(function (dst, src) {\n" " for (var i = 0; i < dst.length; i++) { dst[i] = 0x11; }\n" " try { dst.set(src); } catch (e) { print(e.name); }\n" "})\n"); duk_dup(ctx, dst); duk_dup(ctx, src); duk_call(ctx, 2); duk_pop(ctx); } } } printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
int test_1(duk_context *ctx) { void *ptr; size_t sz; int i; duk_set_top(ctx, 0); duk_push_fixed_buffer(ctx, 1024); duk_push_fixed_buffer(ctx, 0); duk_push_dynamic_buffer(ctx, 1024); duk_push_dynamic_buffer(ctx, 0); for (i = 0; i < 4; i++) { sz = (size_t) 0xdeadbeef; ptr = duk_require_buffer(ctx, i, &sz); printf("buffer: ptr-is-NULL=%d, sz=%d\n", (sz == 0 ? -1 : (ptr == NULL ? 1 : 0)), (int) sz); sz = (size_t) 0xdeadbeef; ptr = duk_require_buffer(ctx, i, NULL); printf("buffer\n"); } return 0; }
static duk_ret_t test_basic(duk_context *ctx, void *udata) { duk_uint_t test[] = { 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]; (void) udata; 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; }
static duk_ret_t test_nodejs_buffer_write_1(duk_context *ctx, void *udata) { int i, dst, src; unsigned char *data; (void) udata; data = (unsigned char *) duk_push_dynamic_buffer(ctx, 10); /* index 0 */ for (i = 0; i < 10; i++) { data[i] = 0x40 + i; } setup_nodejs_buffer(ctx, 0); /* index 1 */ setup_nodejs_buffer_slice(ctx, 0, 1, 4); /* index 2 */ setup_nodejs_buffer_slice(ctx, 0, 3, 7); /* index 3 */ setup_nodejs_buffer_slice(ctx, 0, 6, 9); /* index 4 */ duk_push_string(ctx, ""); /* index 5 */ duk_push_string(ctx, "fo"); /* index 6 */ duk_push_string(ctx, "bar"); /* index 7 */ duk_push_string(ctx, "quux"); /* index 8 */ for (i = 10; i >= 0; i--) { duk_resize_buffer(ctx, 0, i); /* The resulting buffers are not printed here; they're not very * intuitive because both the source and the destination share * the same underlying buffer. */ for (dst = 1; dst <= 4; dst++) { for (src = 5; src <= 8; src++) { printf("%d %d %d\n", i, dst, src); duk_eval_string(ctx, "(function (dst, src) {\n" " for (var i = 0; i < dst.length; i++) { dst[i] = 0x11; }\n" " dst.write(src);\n" " for (var i = 0; i < dst.length; i++) { dst[i] = 0x11; }\n" " dst.write(src, 1);\n" "})"); duk_dup(ctx, dst); duk_dup(ctx, src); duk_call(ctx, 2); duk_pop(ctx); } } } printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static duk_ret_t test_json_serialize_1(duk_context *ctx, void *udata) { unsigned char *data; int i; duk_uarridx_t arridx = 0; (void) udata; data = (unsigned char *) duk_push_dynamic_buffer(ctx, 20); for (i = 0; i < 20; i++) { data[i] = 0x40 + i; } duk_push_array(ctx); /* index 1 */ setup_duktape_buffer(ctx, 0); duk_put_prop_index(ctx, 1, arridx++); setup_nodejs_buffer(ctx, 0); duk_put_prop_index(ctx, 1, arridx++); setup_nodejs_buffer_slice(ctx, 0, 3, 5); duk_put_prop_index(ctx, 1, arridx++); setup_arraybuffer(ctx, 0); duk_put_prop_index(ctx, 1, arridx++); setup_typedarray(ctx, 0, "Uint8Array"); duk_put_prop_index(ctx, 1, arridx++); setup_typedarray_slice(ctx, 0, "Uint8Array", 2, 6); duk_put_prop_index(ctx, 1, arridx++); setup_typedarray(ctx, 0, "Uint32Array"); duk_put_prop_index(ctx, 1, arridx++); setup_typedarray_slice(ctx, 0, "Uint32Array", 4, 1); duk_put_prop_index(ctx, 1, arridx++); /* Serialize with a full backing buffer first. */ for (i = 20; i >= 0; i--) { printf("resize to %d\n", i); duk_resize_buffer(ctx, 0, i); duk_dup(ctx, 1); duk_json_encode(ctx, -1); printf("%s\n", duk_to_string(ctx, -1)); duk_pop(ctx); duk_eval_string(ctx, "(function (v) { print(Duktape.enc('jx', v)); })"); duk_dup(ctx, 1); duk_call(ctx, 1); duk_pop(ctx); } printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
/* Underlying buffer doesn't cover logical slice. */ static duk_ret_t test_uncovered_buffer(duk_context *ctx) { unsigned char *p; duk_size_t sz; duk_push_dynamic_buffer(ctx, 64); /* 16x4 elements */ duk_eval_string(ctx, "(function (plain_buffer) {\n" " var b = new ArrayBuffer(plain_buffer);\n" " return new Uint32Array(b).subarray(1,5);\n" "})"); duk_dup(ctx, 0); duk_call(ctx, 1); /* -> [ plain_buffer Uint32Array ] */ /* Initially OK. */ sz = (duk_size_t) 0xdeadbeefUL; p = duk_get_buffer_data(ctx, -1, &sz); if (p) { printf("p is not NULL, sz=%ld\n", (long) sz); } else { printf("p is NULL\n"); } /* Resize; slice still covered. */ duk_resize_buffer(ctx, 0, 20); /* 5x4 = 20, subarray is [1*4, 5*4[ */ sz = (duk_size_t) 0xdeadbeefUL; p = duk_get_buffer_data(ctx, -1, &sz); if (p) { printf("p is not NULL, sz=%ld\n", (long) sz); } else { printf("p is NULL\n"); } /* Resize; no longer covered. */ duk_resize_buffer(ctx, 0, 19); sz = (duk_size_t) 0xdeadbeefUL; p = duk_get_buffer_data(ctx, -1, &sz); if (p) { printf("p is not NULL, sz=%ld\n", (long) sz); } else { printf("p is NULL\n"); } printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static int test_nodejs_buffer_copy_1(duk_context *ctx) { int i, dst, src; unsigned char *data; data = (unsigned char *) duk_push_dynamic_buffer(ctx, 10); /* index 0 */ for (i = 0; i < 10; i++) { data[i] = 0x40 + i; } setup_nodejs_buffer(ctx, 0); setup_nodejs_buffer_slice(ctx, 0, 1, 4); setup_nodejs_buffer_slice(ctx, 0, 3, 7); setup_nodejs_buffer_slice(ctx, 0, 6, 9); for (i = 10; i >= 0; i--) { duk_resize_buffer(ctx, 0, i); /* The resulting buffers are not printed here; they're not very * intuitive because both the source and the destination share * the same underlying buffer. */ for (dst = 1; dst <= 4; dst++) { for (src = 1; src <= 4; src++) { printf("%d %d %d\n", i, dst, src); duk_eval_string(ctx, "(function (dst, src) {\n" " for (var i = 0; i < dst.length; i++) { dst[i] = 0x11; }\n" " for (var i = 0; i < src.length; i++) { src[i] = 0x22; }\n" " src.copy(dst);\n" " for (var i = 0; i < dst.length; i++) { dst[i] = 0x11; }\n" " for (var i = 0; i < src.length; i++) { src[i] = 0x22; }\n" " src.copy(dst, 4, 1);\n" "})"); duk_dup(ctx, dst); duk_dup(ctx, src); duk_call(ctx, 2); duk_pop(ctx); } } } printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static duk_ret_t test_typedarray_constructor_copy_1(duk_context *ctx, void *udata) { int i; unsigned char *data; (void) udata; data = (unsigned char *) duk_push_dynamic_buffer(ctx, 10); /* index 0 */ for (i = 0; i < 10; i++) { data[i] = 0x40 + i; } setup_typedarray(ctx, 0, "Uint8Array"); /* index 1 */ for (i = 10; i >= 0; i--) { duk_resize_buffer(ctx, 0, i); /* Compatible copy, uses byte copy when buffer is covered. */ duk_eval_string(ctx, "(function (src) {\n" " var buf = new Uint8Array(src);\n" " print(Duktape.enc('jx', buf));\n" "})\n"); duk_dup(ctx, 1); duk_call(ctx, 1); duk_pop(ctx); /* Incompatible copy, uses "fast copy" when buffer is covered. * Endian specific output. */ duk_eval_string(ctx, "(function (src) {\n" " var buf = new Uint16Array(src);\n" " print(Duktape.enc('jx', buf));\n" "})\n"); duk_dup(ctx, 1); duk_call(ctx, 1); duk_pop(ctx); } printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static void create_escaped_source(duk_hthread *thr, int idx_pattern) { duk_context *ctx = (duk_context *) thr; duk_hstring *h; duk_hbuffer_dynamic *buf; const duk_uint8_t *p; duk_size_t i, n; duk_uint_fast8_t c_prev, c; h = duk_get_hstring(ctx, idx_pattern); DUK_ASSERT(h != NULL); p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h); n = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h); if (n == 0) { /* return '(?:)' */ duk_push_hstring_stridx(ctx, DUK_STRIDX_ESCAPED_EMPTY_REGEXP); return; } duk_push_dynamic_buffer(ctx, 0); buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1); DUK_ASSERT(buf != NULL); c_prev = (duk_uint_fast8_t) 0; for (i = 0; i < n; i++) { c = p[i]; if (c == (duk_uint_fast8_t) '/' && c_prev != (duk_uint_fast8_t) '\\') { /* Unescaped '/' ANYWHERE in the regexp (in disjunction, * inside a character class, ...) => same escape works. */ duk_hbuffer_append_byte(thr, buf, (duk_uint8_t) '\\'); } duk_hbuffer_append_byte(thr, buf, (duk_uint8_t) c); c_prev = c; } duk_to_string(ctx, -1); /* -> [ ... escaped_source ] */ }
/* source: dynamic buffer, target: dynamic buffer */ static duk_ret_t test_2b(duk_context *ctx) { unsigned char *p; void *q; duk_size_t sz; duk_set_top(ctx, 0); p = (unsigned char *) duk_push_dynamic_buffer(ctx, 16); p[0] = 1; p[15] = 2; dump_buffer(ctx); q = duk_to_dynamic_buffer(ctx, -1, &sz); printf("q is NULL: %d\n", (q == NULL ? 1 : 0)); printf("p == q: %d\n", (p == q ? 1 : 0)); printf("sz=%lu\n", (unsigned long) sz); dump_buffer(ctx); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static duk_ret_t test_nodejs_buffer_compare_1(duk_context *ctx, void *udata) { int i, dst, src; unsigned char *data; (void) udata; /* There are two relevant methods: Buffer.compare and Buffer.prototype.compare() */ data = (unsigned char *) duk_push_dynamic_buffer(ctx, 10); /* index 0 */ for (i = 0; i < 10; i++) { data[i] = 0x40 + i; } setup_nodejs_buffer(ctx, 0); setup_nodejs_buffer_slice(ctx, 0, 1, 4); setup_nodejs_buffer_slice(ctx, 0, 3, 7); setup_nodejs_buffer_slice(ctx, 0, 6, 9); for (i = 10; i >= 0; i--) { duk_resize_buffer(ctx, 0, i); for (dst = 1; dst <= 4; dst++) { for (src = 1; src <= 4; src++) { printf("%d %d %d\n", i, dst, src); duk_eval_string(ctx, "(function (dst, src) {\n" " print(Buffer.compare(dst, src), dst.compare(src));\n" "})"); duk_dup(ctx, dst); duk_dup(ctx, src); duk_call(ctx, 2); duk_pop(ctx); } } } printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
/* * Read data from a file. Args: * - 0: FILE * - 1: nread (a number or a Buffer-ish object) */ static duk_ret_t io_fread(duk_context* ctx) { FILE* f; size_t nread, r; char* buf; int create_buf = 0; f = duk_require_pointer(ctx, 0); if (duk_is_number(ctx, 1)) { nread = duk_require_int(ctx, 1); buf = duk_push_dynamic_buffer(ctx, nread); create_buf = 1; } else { buf = duk_require_buffer_data(ctx, 1, &nread); if (buf == NULL || nread == 0) { duk_error(ctx, DUK_ERR_TYPE_ERROR, "invalid buffer"); return -42; /* control never returns here */ } } r = fread(buf, 1, nread, f); if (ferror(f)) { if (create_buf) { duk_pop(ctx); } clearerr(f); SJS_THROW_ERRNO_ERROR2(EIO); return -42; /* control never returns here */ } if (create_buf) { /* return the string we read */ duk_resize_buffer(ctx, -1, r); } else { /* the data was written to the buffer, return how much we read */ duk_push_int(ctx, r); } return 1; }
static duk_ret_t test_nodejs_buffer_concat_1(duk_context *ctx, void *udata) { int i; unsigned char *data; (void) udata; data = (unsigned char *) duk_push_dynamic_buffer(ctx, 10); /* index 0 */ for (i = 0; i < 10; i++) { data[i] = 0x40 + i; } setup_nodejs_buffer(ctx, 0); setup_nodejs_buffer_slice(ctx, 0, 1, 6); setup_nodejs_buffer_slice(ctx, 0, 3, 7); setup_nodejs_buffer_slice(ctx, 0, 6, 9); setup_nodejs_buffer_slice(ctx, 0, 1, 8); for (i = 10; i >= 0; i--) { duk_resize_buffer(ctx, 0, i); printf("%d\n", i); duk_eval_string(ctx, "(function (arg1, arg2, arg3, arg4, arg5) {\n" " var res = Buffer.concat([ arg1, arg2, arg3, arg4, arg5 ]);\n" " print(Duktape.enc('jx', res));\n" "})"); duk_dup(ctx, 1); duk_dup(ctx, 2); duk_dup(ctx, 3); duk_dup(ctx, 4); duk_dup(ctx, 5); duk_call(ctx, 5); duk_pop(ctx); } printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
void test(duk_context *ctx) { duk_idx_t i, n; duk_push_undefined(ctx); duk_push_null(ctx); duk_push_boolean(ctx, 0); duk_push_boolean(ctx, 123); duk_push_number(ctx, 234); duk_push_string(ctx, "foo"); duk_push_object(ctx); duk_push_array(ctx); duk_push_c_function(ctx, my_c_func, DUK_VARARGS); duk_push_fixed_buffer(ctx, 1024); duk_push_dynamic_buffer(ctx, 1024); duk_push_pointer(ctx, (void *) 0xdeadbeefUL); n = duk_get_top(ctx); for (i = 0; i < n + 1; i++) { /* end on invalid index on purpose */ printf("stack[%ld] --> DUK_TYPE_NUMBER=%ld DUK_TYPE_NONE=%ld\n", (long) i, (long) duk_check_type(ctx, i, DUK_TYPE_NUMBER), (long) duk_check_type(ctx, i, DUK_TYPE_NONE)); } }
duk_ret_t duk_bi_string_constructor_from_char_code(duk_context *ctx) { duk_hthread *thr = (duk_hthread *) ctx; duk_hbuffer_dynamic *h; duk_idx_t i, n; duk_ucodepoint_t cp; /* XXX: It would be nice to build the string directly but ToUint16() * coercion is needed so a generic helper would not be very * helpful (perhaps coerce the value stack first here and then * build a string from a duk_tval number sequence in one go?). */ n = duk_get_top(ctx); duk_push_dynamic_buffer(ctx, 0); /* XXX: initial spare size estimate from 'n' */ h = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1); for (i = 0; i < n; i++) { cp = duk_to_uint16(ctx, i); duk_hbuffer_append_cesu8(thr, h, cp); } duk_to_string(ctx, -1); return 1; }
void test(duk_context *ctx) { char *buf1, *buf2, *buf3; duk_idx_t i, j, n; duk_push_undefined(ctx); duk_push_null(ctx); duk_push_true(ctx); duk_push_false(ctx); duk_push_number(ctx, -INFINITY); duk_push_number(ctx, -123.0); duk_push_number(ctx, -0.0); duk_push_number(ctx, +0.0); duk_push_number(ctx, +123.0); duk_push_number(ctx, +INFINITY); duk_push_number(ctx, NAN); duk_push_string(ctx, ""); duk_push_string(ctx, "foo"); duk_push_string(ctx, "bar"); duk_push_object(ctx); duk_push_array(ctx); (void) duk_push_fixed_buffer(ctx, 0); buf1 = (char *) duk_push_fixed_buffer(ctx, 3); buf1[0] = 'f'; buf1[1] = 'o'; buf1[2] = 'o'; buf2 = (char *) duk_push_dynamic_buffer(ctx, 3); buf2[0] = 'f'; buf2[1] = 'o'; buf2[2] = 'o'; buf3 = (char *) duk_push_dynamic_buffer(ctx, 3); buf3[0] = 'b'; buf3[1] = 'a'; buf3[2] = 'r'; duk_push_pointer(ctx, NULL); duk_push_pointer(ctx, (void *) 0xdeadbeef); n = duk_get_top(ctx); for (i = 0; i < n; i++) { duk_dup(ctx, i); printf("index %ld -> type %d, value '%s'\n", (long) i, (int) duk_get_type(ctx, i), duk_to_string(ctx, -1)); duk_pop(ctx); } for (i = 0; i <= n + 1; i++) { for (j = 0; j <= n + 1; j++) { duk_idx_t idx1, idx2; duk_bool_t eq, seq; /* Note: i and j run up to 'n + 1' (invalid index) on purpose. */ idx1 = (i == n + 1 ? DUK_INVALID_INDEX : i); idx2 = (j == n + 1 ? DUK_INVALID_INDEX : j); eq = duk_equals(ctx, i, j); seq = duk_strict_equals(ctx, i, j); /* Print nothing if neither equality is true */ if (!eq && !seq) { continue; } if (idx1 == DUK_INVALID_INDEX) { printf("DUK_INVALID_INDEX"); } else { printf("%ld", (long) idx1); } printf(" vs. "); if (idx2 == DUK_INVALID_INDEX) { printf("DUK_INVALID_INDEX"); } else { printf("%ld", (long) idx2); } printf(" -> equals=%d, strict_equals=%d\n", (int) eq, (int) seq); } } }
//void *duk_push_dynamic_buffer(duk_context *ctx, duk_size_t size); void *aperl_duk_push_dynamic_buffer(duk_context *ctx, duk_size_t size) { void *ret = duk_push_dynamic_buffer(ctx, size); return ret; }
int test_1(duk_context *ctx) { int i, n; duk_set_top(ctx, 0); duk_push_undefined(ctx); duk_push_null(ctx); duk_push_true(ctx); duk_push_false(ctx); duk_push_int(ctx, 0); duk_push_int(ctx, 1); duk_push_number(ctx, 123.456); duk_push_number(ctx, -123.456); duk_push_number(ctx, 123.999); duk_push_number(ctx, -123.999); duk_push_nan(ctx); duk_push_number(ctx, INFINITY); duk_push_string(ctx, ""); duk_push_string(ctx, "foo"); duk_push_string(ctx, "123"); duk_push_string(ctx, "123.456"); duk_push_string(ctx, "123.456e3"); duk_push_string(ctx, " -123.456e+3 "); duk_push_string(ctx, "NaN"); duk_push_string(ctx, "-Infinity"); duk_push_string(ctx, "+Infinity"); duk_push_string(ctx, "Infinity"); duk_push_string(ctx, "Infinityx"); duk_push_string(ctx, "xInfinity"); duk_push_string(ctx, " Infinity "); duk_push_object(ctx); duk_push_thread(ctx); duk_push_fixed_buffer(ctx, 0); duk_push_fixed_buffer(ctx, 1024); duk_push_dynamic_buffer(ctx, 0); duk_push_dynamic_buffer(ctx, 1024); duk_push_pointer(ctx, (void *) NULL); duk_push_pointer(ctx, (void *) 0xdeadbeef); n = duk_get_top(ctx); printf("top: %d\n", n); for (i = 0; i < n; i++) { double dval_pre; double dval_post; int ival; dval_pre = duk_get_number(ctx, i); /* number before ToInteger() coercion */ ival = duk_to_int(ctx, i); dval_post = duk_get_number(ctx, i); /* number after ToInteger() coercion */ printf("index %d, ", i); if (ival == INT_MIN) { printf("int: INT_MIN"); } else if (ival == INT_MAX) { printf("int: INT_MAX"); } else { printf("int: %d", ival); } printf(", number before: %lf, number after: %lf\n", dval_pre, dval_post); } return 0; }
void duk_regexp_compile(duk_hthread *thr) { duk_context *ctx = (duk_context *) thr; duk_re_compiler_ctx re_ctx; duk_lexer_point lex_point; duk_hstring *h_pattern; duk_hstring *h_flags; duk_hbuffer_dynamic *h_buffer; DUK_ASSERT(thr != NULL); DUK_ASSERT(ctx != NULL); /* * Args validation */ /* TypeError if fails */ h_pattern = duk_require_hstring(ctx, -2); h_flags = duk_require_hstring(ctx, -1); /* * Create normalized 'source' property (E5 Section 15.10.3). */ /* [ ... pattern flags ] */ create_escaped_source(thr, -2); /* [ ... pattern flags escaped_source ] */ /* * Init compilation context */ duk_push_dynamic_buffer(ctx, 0); h_buffer = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, -1); DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h_buffer)); /* [ ... pattern flags escaped_source buffer ] */ DUK_MEMSET(&re_ctx, 0, sizeof(re_ctx)); DUK_LEXER_INITCTX(&re_ctx.lex); /* duplicate zeroing, expect for (possible) NULL inits */ re_ctx.thr = thr; re_ctx.lex.thr = thr; re_ctx.lex.input = DUK_HSTRING_GET_DATA(h_pattern); re_ctx.lex.input_length = DUK_HSTRING_GET_BYTELEN(h_pattern); re_ctx.buf = h_buffer; re_ctx.recursion_limit = DUK_RE_COMPILE_RECURSION_LIMIT; re_ctx.re_flags = parse_regexp_flags(thr, h_flags); DUK_DDPRINT("regexp compiler ctx initialized, flags=0x%08x, recursion_limit=%d", (unsigned int) re_ctx.re_flags, (int) re_ctx.recursion_limit); /* * Init lexer */ lex_point.offset = 0; /* expensive init, just want to fill window */ lex_point.line = 1; DUK_LEXER_SETPOINT(&re_ctx.lex, &lex_point); /* * Compilation */ DUK_DPRINT("starting regexp compilation"); append_u32(&re_ctx, DUK_REOP_SAVE); append_u32(&re_ctx, 0); (void) parse_disjunction(&re_ctx, 1); /* 1 = expect eof */ append_u32(&re_ctx, DUK_REOP_SAVE); append_u32(&re_ctx, 1); append_u32(&re_ctx, DUK_REOP_MATCH); DUK_DPRINT("regexp bytecode size (before header) is %d bytes", (int) DUK_HBUFFER_GET_SIZE(re_ctx.buf)); /* * Check for invalid backreferences; note that it is NOT an error * to back-reference a capture group which has not yet been introduced * in the pattern (as in /\1(foo)/); in fact, the backreference will * always match! It IS an error to back-reference a capture group * which will never be introduced in the pattern. Thus, we can check * for such references only after parsing is complete. */ if (re_ctx.highest_backref > re_ctx.captures) { DUK_ERROR(thr, DUK_ERR_SYNTAX_ERROR, "invalid backreference(s)"); } /* * Emit compiled regexp header: flags, ncaptures * (insertion order inverted on purpose) */ insert_u32(&re_ctx, 0, (re_ctx.captures + 1) * 2); insert_u32(&re_ctx, 0, re_ctx.re_flags); DUK_DPRINT("regexp bytecode size (after header) is %d bytes", (int) DUK_HBUFFER_GET_SIZE(re_ctx.buf)); DUK_DDDPRINT("compiled regexp: %!xO", re_ctx.buf); /* [ ... pattern flags escaped_source buffer ] */ duk_to_string(ctx, -1); /* coerce to string */ /* [ ... pattern flags escaped_source bytecode ] */ /* * Finalize stack */ duk_remove(ctx, -4); /* -> [ ... flags escaped_source bytecode ] */ duk_remove(ctx, -3); /* -> [ ... escaped_source bytecode ] */ DUK_DPRINT("regexp compilation successful, bytecode: %!T, escaped source: %!T", duk_get_tval(ctx, -1), duk_get_tval(ctx, -2)); }
void test(duk_context *ctx) { int i, n; /* 0 */ duk_push_string(ctx, "foo"); /* 1 */ duk_push_string(ctx, "\xe1\x88\xb4xyz"); /* 4 chars, first char utf-8 encoded U+1234 */ /* 2 */ duk_push_object(ctx); /* no length property */ /* 3 */ duk_push_object(ctx); /* length: 123 */ duk_push_int(ctx, 123); duk_put_prop_string(ctx, -2, "length"); /* 4 */ duk_push_object(ctx); /* length: "bar" */ duk_push_string(ctx, "bar"); duk_put_prop_string(ctx, -2, "length"); /* 5 */ duk_push_object(ctx); /* length: 123.9, fractional number */ duk_push_number(ctx, 123.9); duk_put_prop_string(ctx, -2, "length"); /* 6 */ duk_push_object(ctx); /* length: negative but within 32-bit range after ToInteger() */ duk_push_number(ctx, -0.9); duk_put_prop_string(ctx, -2, "length"); /* 7 */ duk_push_object(ctx); /* length: negative, outside 32-bit range */ duk_push_number(ctx, -1); duk_put_prop_string(ctx, -2, "length"); /* 8 */ duk_push_object(ctx); /* length: outside 32-bit range but within range after ToInteger() */ duk_push_number(ctx, 4294967295.9); duk_put_prop_string(ctx, -2, "length"); /* 9 */ duk_push_object(ctx); /* length: outside 32-bit range */ duk_push_number(ctx, 4294967296); duk_put_prop_string(ctx, -2, "length"); /* 10 */ duk_push_object(ctx); /* length: nan */ duk_push_nan(ctx); duk_put_prop_string(ctx, -2, "length"); /* 11 */ duk_push_object(ctx); /* length: +Infinity */ duk_push_number(ctx, INFINITY); duk_put_prop_string(ctx, -2, "length"); /* 12 */ duk_push_object(ctx); /* length: -Infinity */ duk_push_number(ctx, -INFINITY); duk_put_prop_string(ctx, -2, "length"); /* 13 */ duk_push_fixed_buffer(ctx, 1234); /* 14 */ duk_push_dynamic_buffer(ctx, 2345); /* 15 */ duk_push_undefined(ctx); /* 16 */ duk_push_null(ctx); /* 17 */ duk_push_true(ctx); /* 18 */ duk_push_false(ctx); n = duk_get_top(ctx); printf("top: %d\n", n); for (i = 0; i < n; i++) { printf("index %d: length %u\n", i, (unsigned int) duk_get_length(ctx, i)); } }
duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx) { duk_hthread *thr = (duk_hthread *) ctx; duk_hstring *h_input; duk_hstring *h_repl; duk_hstring *h_match; duk_hstring *h_search; duk_hobject *h_re; duk_hbuffer_dynamic *h_buf; #ifdef DUK_USE_REGEXP_SUPPORT duk_small_int_t is_regexp; duk_small_int_t is_global; #endif duk_small_int_t is_repl_func; duk_uint32_t match_start_coff, match_start_boff; #ifdef DUK_USE_REGEXP_SUPPORT duk_small_int_t match_caps; #endif duk_uint32_t prev_match_end_boff; duk_uint8_t *r_start, *r_end, *r; /* repl string scan */ DUK_ASSERT_TOP(ctx, 2); h_input = duk_push_this_coercible_to_string(ctx); DUK_ASSERT(h_input != NULL); duk_push_dynamic_buffer(ctx, 0); h_buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1); DUK_ASSERT(h_buf != NULL); DUK_ASSERT_TOP(ctx, 4); /* stack[0] = search value * stack[1] = replace value * stack[2] = input string * stack[3] = result buffer */ h_re = duk_get_hobject_with_class(ctx, 0, DUK_HOBJECT_CLASS_REGEXP); if (h_re) { #ifdef DUK_USE_REGEXP_SUPPORT is_regexp = 1; is_global = duk_get_prop_stridx_boolean(ctx, 0, DUK_STRIDX_GLOBAL, NULL); if (is_global) { /* start match from beginning */ duk_push_int(ctx, 0); duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX); } #else /* DUK_USE_REGEXP_SUPPORT */ return DUK_RET_UNSUPPORTED_ERROR; #endif /* DUK_USE_REGEXP_SUPPORT */ } else { duk_to_string(ctx, 0); #ifdef DUK_USE_REGEXP_SUPPORT is_regexp = 0; is_global = 0; #endif } if (duk_is_function(ctx, 1)) { is_repl_func = 1; r_start = NULL; r_end = NULL; } else { is_repl_func = 0; h_repl = duk_to_hstring(ctx, 1); DUK_ASSERT(h_repl != NULL); r_start = DUK_HSTRING_GET_DATA(h_repl); r_end = r_start + DUK_HSTRING_GET_BYTELEN(h_repl); } prev_match_end_boff = 0; for (;;) { /* * If matching with a regexp: * - non-global RegExp: lastIndex not touched on a match, zeroed * on a non-match * - global RegExp: on match, lastIndex will be updated by regexp * executor to point to next char after the matching part (so that * characters in the matching part are not matched again) * * If matching with a string: * - always non-global match, find first occurrence * * We need: * - The character offset of start-of-match for the replacer function * - The byte offsets for start-of-match and end-of-match to implement * the replacement values $&, $`, and $', and to copy non-matching * input string portions (including header and trailer) verbatim. * * NOTE: the E5.1 specification is a bit vague how the RegExp should * behave in the replacement process; e.g. is matching done first for * all matches (in the global RegExp case) before any replacer calls * are made? See: test-bi-string-proto-replace.js for discussion. */ DUK_ASSERT_TOP(ctx, 4); #ifdef DUK_USE_REGEXP_SUPPORT if (is_regexp) { duk_dup(ctx, 0); duk_dup(ctx, 2); duk_regexp_match(thr); /* [ ... regexp input ] -> [ res_obj ] */ if (!duk_is_object(ctx, -1)) { duk_pop(ctx); break; } duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INDEX); DUK_ASSERT(duk_is_number(ctx, -1)); match_start_coff = duk_get_int(ctx, -1); duk_pop(ctx); duk_get_prop_index(ctx, -1, 0); DUK_ASSERT(duk_is_string(ctx, -1)); h_match = duk_get_hstring(ctx, -1); DUK_ASSERT(h_match != NULL); duk_pop(ctx); /* h_match is borrowed, remains reachable through match_obj */ if (DUK_HSTRING_GET_BYTELEN(h_match) == 0) { /* This should be equivalent to match() algorithm step 8.f.iii.2: * detect an empty match and allow it, but don't allow it twice. */ duk_uint32_t last_index; duk_get_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX); last_index = duk_get_int(ctx, -1); /* FIXME: duk_get_uint32() */ DUK_DDD(DUK_DDDPRINT("empty match, bump lastIndex: %d -> %d", last_index, last_index + 1)); duk_pop(ctx); duk_push_int(ctx, last_index + 1); duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX); } match_caps = duk_get_length(ctx, -1); } else { #else /* DUK_USE_REGEXP_SUPPORT */ { /* unconditionally */ #endif /* DUK_USE_REGEXP_SUPPORT */ duk_uint8_t *p_start, *p_end, *p; /* input string scan */ duk_uint8_t *q_start; /* match string */ duk_size_t q_blen; #ifdef DUK_USE_REGEXP_SUPPORT DUK_ASSERT(!is_global); /* single match always */ #endif p_start = DUK_HSTRING_GET_DATA(h_input); p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input); p = p_start; h_search = duk_get_hstring(ctx, 0); DUK_ASSERT(h_search != NULL); q_start = DUK_HSTRING_GET_DATA(h_search); q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_search); p_end -= q_blen; /* ensure full memcmp() fits in while */ match_start_coff = 0; while (p <= p_end) { DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input)); if (DUK_MEMCMP((void *) p, (void *) q_start, (size_t) q_blen) == 0) { duk_dup(ctx, 0); h_match = duk_get_hstring(ctx, -1); DUK_ASSERT(h_match != NULL); #ifdef DUK_USE_REGEXP_SUPPORT match_caps = 0; #endif goto found; } /* track utf-8 non-continuation bytes */ if ((p[0] & 0xc0) != 0x80) { match_start_coff++; } p++; } /* not found */ break; } found: /* stack[0] = search value * stack[1] = replace value * stack[2] = input string * stack[3] = result buffer * stack[4] = regexp match OR match string */ match_start_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff); duk_hbuffer_append_bytes(thr, h_buf, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, (size_t) (match_start_boff - prev_match_end_boff)); prev_match_end_boff = match_start_boff + DUK_HSTRING_GET_BYTELEN(h_match); if (is_repl_func) { duk_idx_t idx_args; duk_hstring *h_repl; /* regexp res_obj is at index 4 */ duk_dup(ctx, 1); idx_args = duk_get_top(ctx); #ifdef DUK_USE_REGEXP_SUPPORT if (is_regexp) { duk_int_t idx; duk_require_stack(ctx, match_caps + 2); for (idx = 0; idx < match_caps; idx++) { /* match followed by capture(s) */ duk_get_prop_index(ctx, 4, idx); } } else { #else /* DUK_USE_REGEXP_SUPPORT */ { /* unconditionally */ #endif /* DUK_USE_REGEXP_SUPPORT */ /* match == search string, by definition */ duk_dup(ctx, 0); } duk_push_int(ctx, match_start_coff); duk_dup(ctx, 2); /* [ ... replacer match [captures] match_char_offset input ] */ duk_call(ctx, duk_get_top(ctx) - idx_args); h_repl = duk_to_hstring(ctx, -1); /* -> [ ... repl_value ] */ DUK_ASSERT(h_repl != NULL); duk_hbuffer_append_hstring(thr, h_buf, h_repl); duk_pop(ctx); /* repl_value */ } else { r = r_start; while (r < r_end) { duk_int_t ch1; duk_int_t ch2; #ifdef DUK_USE_REGEXP_SUPPORT duk_int_t ch3; #endif duk_size_t left; ch1 = *r++; if (ch1 != (duk_int_t) '$') { goto repl_write; } left = r_end - r; if (left <= 0) { goto repl_write; } ch2 = r[0]; switch ((duk_small_int_t) ch2) { case (duk_int_t) '$': { ch1 = (1 << 8) + (duk_int_t) '$'; goto repl_write; } case (duk_int_t) '&': { duk_hbuffer_append_hstring(thr, h_buf, h_match); r++; continue; } case (duk_int_t) '`': { duk_hbuffer_append_bytes(thr, h_buf, DUK_HSTRING_GET_DATA(h_input), match_start_boff); r++; continue; } case (duk_int_t) '\'': { duk_uint32_t match_end_boff; /* Use match charlen instead of bytelen, just in case the input and * match codepoint encodings would have different lengths. */ match_end_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff + DUK_HSTRING_GET_CHARLEN(h_match)); duk_hbuffer_append_bytes(thr, h_buf, DUK_HSTRING_GET_DATA(h_input) + match_end_boff, DUK_HSTRING_GET_BYTELEN(h_input) - match_end_boff); r++; continue; } default: { #ifdef DUK_USE_REGEXP_SUPPORT duk_int_t capnum, captmp, capadv; /* FIXME: optional check, match_caps is zero if no regexp, * so dollar will be interpreted literally anyway. */ if (!is_regexp) { goto repl_write; } if (!(ch2 >= (duk_int_t) '0' && ch2 <= (duk_int_t) '9')) { goto repl_write; } capnum = ch2 - (duk_int_t) '0'; capadv = 1; if (left >= 2) { ch3 = r[1]; if (ch3 >= (duk_int_t) '0' && ch3 <= (duk_int_t) '9') { captmp = capnum * 10 + (ch3 - (duk_int_t) '0'); if (captmp < match_caps) { capnum = captmp; capadv = 2; } } } if (capnum > 0 && capnum < match_caps) { DUK_ASSERT(is_regexp != 0); /* match_caps == 0 without regexps */ /* regexp res_obj is at offset 4 */ duk_get_prop_index(ctx, 4, capnum); if (duk_is_string(ctx, -1)) { DUK_ASSERT(duk_get_hstring(ctx, -1) != NULL); duk_hbuffer_append_hstring(thr, h_buf, duk_get_hstring(ctx, -1)); } else { /* undefined -> skip (replaced with empty) */ } duk_pop(ctx); r += capadv; continue; } else { goto repl_write; } #else /* DUK_USE_REGEXP_SUPPORT */ goto repl_write; /* unconditionally */ #endif /* DUK_USE_REGEXP_SUPPORT */ } /* default case */ } /* switch (ch2) */ repl_write: /* ch1 = (r_increment << 8) + byte */ duk_hbuffer_append_byte(thr, h_buf, (duk_uint8_t) (ch1 & 0xff)); r += ch1 >> 8; } /* while repl */ } /* if (is_repl_func) */ duk_pop(ctx); /* pop regexp res_obj or match string */ #ifdef DUK_USE_REGEXP_SUPPORT if (!is_global) { #else { /* unconditionally; is_global==0 */ #endif break; } } /* trailer */ duk_hbuffer_append_bytes(thr, h_buf, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, (size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff)); DUK_ASSERT_TOP(ctx, 4); duk_to_string(ctx, -1); return 1; } /* * split() */ /* FIXME: very messy now, but works; clean up, remove unused variables (nomimally * used so compiler doesn't complain). */ int duk_bi_string_prototype_split(duk_context *ctx) { duk_hthread *thr = (duk_hthread *) ctx; duk_hstring *h_input; duk_hstring *h_sep; duk_uint32_t limit; duk_uint32_t arr_idx; #ifdef DUK_USE_REGEXP_SUPPORT duk_small_int_t is_regexp; #endif duk_small_int_t matched; /* set to 1 if any match exists (needed for empty input special case) */ duk_uint32_t prev_match_end_coff, prev_match_end_boff; duk_uint32_t match_start_boff, match_start_coff; duk_uint32_t match_end_boff, match_end_coff; DUK_UNREF(thr); h_input = duk_push_this_coercible_to_string(ctx); DUK_ASSERT(h_input != NULL); duk_push_array(ctx); if (duk_is_undefined(ctx, 1)) { limit = 0xffffffffUL; } else { limit = duk_to_uint32(ctx, 1); } if (limit == 0) { return 1; } /* If the separator is a RegExp, make a "clone" of it. The specification * algorithm calls [[Match]] directly for specific indices; we emulate this * by tweaking lastIndex and using a "force global" variant of duk_regexp_match() * which will use global-style matching even when the RegExp itself is non-global. */ if (duk_is_undefined(ctx, 0)) { /* The spec algorithm first does "R = ToString(separator)" before checking * whether separator is undefined. Since this is side effect free, we can * skip the ToString() here. */ duk_dup(ctx, 2); duk_put_prop_index(ctx, 3, 0); return 1; } else if (duk_get_hobject_with_class(ctx, 0, DUK_HOBJECT_CLASS_REGEXP) != NULL) { #ifdef DUK_USE_REGEXP_SUPPORT duk_push_hobject(ctx, thr->builtins[DUK_BIDX_REGEXP_CONSTRUCTOR]); duk_dup(ctx, 0); duk_new(ctx, 1); /* [ ... RegExp val ] -> [ ... res ] */ duk_replace(ctx, 0); /* lastIndex is initialized to zero by new RegExp() */ is_regexp = 1; #else return DUK_RET_UNSUPPORTED_ERROR; #endif } else { duk_to_string(ctx, 0); #ifdef DUK_USE_REGEXP_SUPPORT is_regexp = 0; #endif } /* stack[0] = separator (string or regexp) * stack[1] = limit * stack[2] = input string * stack[3] = result array */ prev_match_end_boff = 0; prev_match_end_coff = 0; arr_idx = 0; matched = 0; for (;;) { /* * The specification uses RegExp [[Match]] to attempt match at specific * offsets. We don't have such a primitive, so we use an actual RegExp * and tweak lastIndex. Since the RegExp may be non-global, we use a * special variant which forces global-like behavior for matching. */ DUK_ASSERT_TOP(ctx, 4); #ifdef DUK_USE_REGEXP_SUPPORT if (is_regexp) { duk_dup(ctx, 0); duk_dup(ctx, 2); duk_regexp_match_force_global(thr); /* [ ... regexp input ] -> [ res_obj ] */ if (!duk_is_object(ctx, -1)) { duk_pop(ctx); break; } matched = 1; duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INDEX); DUK_ASSERT(duk_is_number(ctx, -1)); match_start_coff = duk_get_int(ctx, -1); match_start_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff); duk_pop(ctx); if (match_start_coff == DUK_HSTRING_GET_CHARLEN(h_input)) { /* don't allow an empty match at the end of the string */ duk_pop(ctx); break; } duk_get_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX); DUK_ASSERT(duk_is_number(ctx, -1)); match_end_coff = duk_get_int(ctx, -1); match_end_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_end_coff); duk_pop(ctx); /* empty match -> bump and continue */ if (prev_match_end_boff == match_end_boff) { duk_push_int(ctx, match_end_coff + 1); duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX); duk_pop(ctx); continue; } } else { #else /* DUK_USE_REGEXP_SUPPORT */ { /* unconditionally */ #endif /* DUK_USE_REGEXP_SUPPORT */ duk_uint8_t *p_start, *p_end, *p; /* input string scan */ duk_uint8_t *q_start; /* match string */ duk_size_t q_blen, q_clen; p_start = DUK_HSTRING_GET_DATA(h_input); p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input); p = p_start + prev_match_end_boff; h_sep = duk_get_hstring(ctx, 0); DUK_ASSERT(h_sep != NULL); q_start = DUK_HSTRING_GET_DATA(h_sep); q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sep); q_clen = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_sep); p_end -= q_blen; /* ensure full memcmp() fits in while */ match_start_coff = prev_match_end_coff; if (q_blen == 0) { /* Handle empty separator case: it will always match, and always * triggers the check in step 13.c.iii initially. Note that we * must skip to either end of string or start of first codepoint, * skipping over any continuation bytes! * * Don't allow an empty string to match at the end of the input. */ matched = 1; /* empty separator can always match */ match_start_coff++; p++; while (p < p_end) { if ((p[0] & 0xc0) != 0x80) { goto found; } p++; } goto not_found; } DUK_ASSERT(q_blen > 0 && q_clen > 0); while (p <= p_end) { DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input)); DUK_ASSERT(q_blen > 0); /* no issues with empty memcmp() */ if (DUK_MEMCMP((void *) p, (void *) q_start, (size_t) q_blen) == 0) { /* never an empty match, so step 13.c.iii can't be triggered */ goto found; } /* track utf-8 non-continuation bytes */ if ((p[0] & 0xc0) != 0x80) { match_start_coff++; } p++; } not_found: /* not found */ break; found: matched = 1; match_start_boff = (duk_uint32_t) (p - p_start); match_end_coff = match_start_coff + q_clen; match_end_boff = match_start_boff + q_blen; /* empty match (may happen with empty separator) -> bump and continue */ if (prev_match_end_boff == match_end_boff) { prev_match_end_boff++; prev_match_end_coff++; continue; } } /* if (is_regexp) */ /* stack[0] = separator (string or regexp) * stack[1] = limit * stack[2] = input string * stack[3] = result array * stack[4] = regexp res_obj (if is_regexp) */ DUK_DDD(DUK_DDDPRINT("split; match_start b=%d,c=%d, match_end b=%d,c=%d, prev_end b=%d,c=%d", (int) match_start_boff, (int) match_start_coff, (int) match_end_boff, (int) match_end_coff, (int) prev_match_end_boff, (int) prev_match_end_coff)); duk_push_lstring(ctx, (const char *) (DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff), (size_t) (match_start_boff - prev_match_end_boff)); duk_put_prop_index(ctx, 3, arr_idx); arr_idx++; if (arr_idx >= limit) { goto hit_limit; } #ifdef DUK_USE_REGEXP_SUPPORT if (is_regexp) { duk_size_t i, len; len = duk_get_length(ctx, 4); for (i = 1; i < len; i++) { duk_get_prop_index(ctx, 4, i); duk_put_prop_index(ctx, 3, arr_idx); arr_idx++; if (arr_idx >= limit) { goto hit_limit; } } duk_pop(ctx); /* lastIndex already set up for next match */ } else { #else /* DUK_USE_REGEXP_SUPPORT */ { /* unconditionally */ #endif /* DUK_USE_REGEXP_SUPPORT */ /* no action */ } prev_match_end_boff = match_end_boff; prev_match_end_coff = match_end_coff; continue; } /* for */ /* Combined step 11 (empty string special case) and 14-15. */ DUK_DDD(DUK_DDDPRINT("split trailer; prev_end b=%d,c=%d", (int) prev_match_end_boff, (int) prev_match_end_coff)); if (DUK_HSTRING_GET_CHARLEN(h_input) > 0 || !matched) { /* Add trailer if: * a) non-empty input * b) empty input and no (zero size) match found (step 11) */ duk_push_lstring(ctx, (const char *) DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, (size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff)); duk_put_prop_index(ctx, 3, arr_idx); /* No arr_idx update or limit check */ } return 1; hit_limit: #ifdef DUK_USE_REGEXP_SUPPORT if (is_regexp) { duk_pop(ctx); } #endif return 1; } /* * Various */ #ifdef DUK_USE_REGEXP_SUPPORT static void duk__to_regexp_helper(duk_context *ctx, duk_idx_t index, int force_new) { duk_hthread *thr = (duk_hthread *) ctx; duk_hobject *h; /* Shared helper for match() steps 3-4, search() steps 3-4. */ DUK_ASSERT(index >= 0); if (force_new) { goto do_new; } h = duk_get_hobject_with_class(ctx, index, DUK_HOBJECT_CLASS_REGEXP); if (!h) { goto do_new; } return; do_new: duk_push_hobject(ctx, thr->builtins[DUK_BIDX_REGEXP_CONSTRUCTOR]); duk_dup(ctx, index); duk_new(ctx, 1); /* [ ... RegExp val ] -> [ ... res ] */ duk_replace(ctx, index); } #endif /* DUK_USE_REGEXP_SUPPORT */ #ifdef DUK_USE_REGEXP_SUPPORT duk_ret_t duk_bi_string_prototype_search(duk_context *ctx) { duk_hthread *thr = (duk_hthread *) ctx; /* Easiest way to implement the search required by the specification * is to do a RegExp test() with lastIndex forced to zero. To avoid * side effects on the argument, "clone" the RegExp if a RegExp was * given as input. * * The global flag of the RegExp should be ignored; setting lastIndex * to zero (which happens when "cloning" the RegExp) should have an * equivalent effect. */ DUK_ASSERT_TOP(ctx, 1); (void) duk_push_this_coercible_to_string(ctx); /* at index 1 */ duk__to_regexp_helper(ctx, 0 /*index*/, 1 /*force_new*/); /* stack[0] = regexp * stack[1] = string */ /* Avoid using RegExp.prototype methods, as they're writable and * configurable and may have been changed. */ duk_dup(ctx, 0); duk_dup(ctx, 1); /* [ ... re_obj input ] */ duk_regexp_match(thr); /* -> [ ... res_obj ] */ if (!duk_is_object(ctx, -1)) { duk_push_int(ctx, -1); return 1; } duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INDEX); DUK_ASSERT(duk_is_number(ctx, -1)); return 1; } #else /* DUK_USE_REGEXP_SUPPORT */ duk_ret_t duk_bi_string_prototype_search(duk_context *ctx) { DUK_UNREF(ctx); return DUK_RET_UNSUPPORTED_ERROR; }
static duk_ret_t test_1(duk_context *ctx) { duk_int_t i, j, n; char *ptr; duk_set_top(ctx, 0); duk_push_undefined(ctx); duk_push_null(ctx); duk_push_true(ctx); duk_push_false(ctx); duk_push_int(ctx, 1); duk_push_number(ctx, -123.456); duk_push_nan(ctx); duk_push_number(ctx, INFINITY); duk_push_number(ctx, -INFINITY); duk_push_string(ctx, ""); duk_push_string(ctx, "foo"); duk_push_lstring(ctx, "foo\0bar", 7); duk_push_object(ctx); duk_push_thread(ctx); (void) duk_push_fixed_buffer(ctx, 0); ptr = (char *) duk_push_fixed_buffer(ctx, 16); for (i = 0; i < 16; i++) { ptr[i] = (char) ('a' + i); } (void) duk_push_dynamic_buffer(ctx, 0); ptr = (char *) duk_push_dynamic_buffer(ctx, 16); for (i = 0; i < 16; i++) { ptr[i] = (char) ('a' + i); } duk_push_pointer(ctx, (void *) NULL); duk_push_pointer(ctx, (void *) 0xdeadbeef); n = duk_get_top(ctx); printf("top: %ld\n", (long) n); for (i = 0; i < n; i++) { const unsigned char *p; duk_size_t sz; duk_dup(ctx, i); sz = (duk_size_t) 0xdeadbeef; p = (const unsigned char *) duk_to_lstring(ctx, -1, &sz); printf("index %ld, string: '", (long) i); for (j = 0; j < sz; j++) { if (p[j] >= 0x20 && p[j] <= 0x7e) { printf("%c", (int) p[j]); } else { printf("\\x%02x", (int) p[j]); } } printf("', length %lu\n", (unsigned long) sz); duk_pop(ctx); duk_dup(ctx, i); sz = (duk_size_t) 0xdeadbeef; p = (const unsigned char *) duk_to_lstring(ctx, -1, NULL); printf("index %ld, string: '%s'\n", (long) i, (const char *) p); duk_pop(ctx); } return 0; }
static duk_ret_t test_func(duk_context *ctx, void *udata) { (void) udata; if (ctx) { printf("dummy - return here\n"); fflush(stdout); return 0; } /* Up-to-date for Duktape 1.3.0, alphabetical order: * $ cd website/api; ls *.yaml */ (void) duk_alloc_raw(ctx, 0); (void) duk_alloc(ctx, 0); (void) duk_base64_decode(ctx, 0); (void) duk_base64_encode(ctx, 0); (void) duk_buffer_to_string(ctx, 0); (void) duk_call_method(ctx, 0); (void) duk_call_prop(ctx, 0, 0); (void) duk_call(ctx, 0); (void) duk_char_code_at(ctx, 0, 0); (void) duk_check_stack_top(ctx, 0); (void) duk_check_stack(ctx, 0); (void) duk_check_type_mask(ctx, 0, 0); (void) duk_check_type(ctx, 0, 0); (void) duk_compact(ctx, 0); (void) duk_compile_lstring_filename(ctx, 0, "dummy", 0); (void) duk_compile_lstring(ctx, 0, "dummy", 0); (void) duk_compile_string_filename(ctx, 0, "dummy"); (void) duk_compile_string(ctx, 0, "dummy"); (void) duk_compile(ctx, 0); (void) duk_concat(ctx, 0); (void) duk_config_buffer(ctx, 0, NULL, 0); (void) duk_copy(ctx, 0, 0); (void) duk_create_heap_default(); (void) duk_create_heap(NULL, NULL, NULL, NULL, NULL); (void) duk_debugger_attach(ctx, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); (void) duk_debugger_cooperate(ctx); (void) duk_debugger_detach(ctx); (void) duk_debugger_notify(ctx, 0); (void) duk_debugger_pause(ctx); (void) duk_decode_string(ctx, 0, NULL, NULL); (void) duk_def_prop(ctx, 0, 0); (void) duk_del_prop_index(ctx, 0, 0); (void) duk_del_prop_string(ctx, 0, "dummy"); (void) duk_del_prop(ctx, 0); (void) duk_destroy_heap(ctx); (void) duk_dump_function(ctx); (void) duk_dup_top(ctx); (void) duk_dup(ctx, 0); (void) duk_enum(ctx, 0, 0); (void) duk_equals(ctx, 0, 0); duk_error_va(ctx, 0, NULL, NULL); duk_error(ctx, 0, "dummy"); /* (void) cast won't work without variadic macros */ (void) duk_eval_lstring_noresult(ctx, "dummy", 0); (void) duk_eval_lstring(ctx, "dummy", 0); (void) duk_eval_noresult(ctx); (void) duk_eval_string_noresult(ctx, "dummy"); (void) duk_eval_string(ctx, "dummy"); (void) duk_eval(ctx); (void) duk_fatal(ctx, "dummy"); (void) duk_free_raw(ctx, NULL); (void) duk_free(ctx, NULL); (void) duk_gc(ctx, 0); (void) duk_get_boolean(ctx, 0); (void) duk_get_buffer_data(ctx, 0, NULL); (void) duk_get_buffer(ctx, 0, NULL); (void) duk_get_c_function(ctx, 0); (void) duk_get_context(ctx, 0); (void) duk_get_current_magic(ctx); (void) duk_get_error_code(ctx, 0); (void) duk_get_finalizer(ctx, 0); (void) duk_get_global_string(ctx, 0); (void) duk_get_heapptr(ctx, 0); (void) duk_get_int(ctx, 0); (void) duk_get_length(ctx, 0); (void) duk_get_lstring(ctx, 0, NULL); (void) duk_get_magic(ctx, 0); (void) duk_get_memory_functions(ctx, NULL); (void) duk_get_number(ctx, 0); (void) duk_get_pointer(ctx, 0); (void) duk_get_prop_index(ctx, 0, 0); (void) duk_get_prop_string(ctx, 0, "dummy"); (void) duk_get_prop(ctx, 0); (void) duk_get_prototype(ctx, 0); (void) duk_get_string(ctx, 0); (void) duk_get_top_index(ctx); (void) duk_get_top(ctx); (void) duk_get_type_mask(ctx, 0); (void) duk_get_type(ctx, 0); (void) duk_get_uint(ctx, 0); (void) duk_has_prop_index(ctx, 0, 0); (void) duk_has_prop_string(ctx, 0, "dummy"); (void) duk_has_prop(ctx, 0); (void) duk_hex_decode(ctx, 0); (void) duk_hex_encode(ctx, 0); (void) duk_insert(ctx, 0); (void) duk_instanceof(ctx, 0, 0); (void) duk_is_array(ctx, 0); (void) duk_is_boolean(ctx, 0); (void) duk_is_bound_function(ctx, 0); (void) duk_is_buffer(ctx, 0); (void) duk_is_callable(ctx, 0); (void) duk_is_c_function(ctx, 0); (void) duk_is_constructor_call(ctx); (void) duk_is_dynamic_buffer(ctx, 0); (void) duk_is_ecmascript_function(ctx, 0); (void) duk_is_error(ctx, 0); (void) duk_is_eval_error(ctx, 0); (void) duk_is_fixed_buffer(ctx, 0); (void) duk_is_function(ctx, 0); (void) duk_is_lightfunc(ctx, 0); (void) duk_is_nan(ctx, 0); (void) duk_is_null_or_undefined(ctx, 0); (void) duk_is_null(ctx, 0); (void) duk_is_number(ctx, 0); (void) duk_is_object_coercible(ctx, 0); (void) duk_is_object(ctx, 0); (void) duk_is_pointer(ctx, 0); (void) duk_is_primitive(ctx, 0); (void) duk_is_range_error(ctx, 0); (void) duk_is_reference_error(ctx, 0); (void) duk_is_strict_call(ctx); (void) duk_is_string(ctx, 0); (void) duk_is_syntax_error(ctx, 0); (void) duk_is_thread(ctx, 0); (void) duk_is_type_error(ctx, 0); (void) duk_is_undefined(ctx, 0); (void) duk_is_uri_error(ctx, 0); (void) duk_is_valid_index(ctx, 0); (void) duk_join(ctx, 0); (void) duk_json_decode(ctx, 0); (void) duk_json_encode(ctx, 0); (void) duk_load_function(ctx); (void) duk_map_string(ctx, 0, NULL, NULL); (void) duk_new(ctx, 0); (void) duk_next(ctx, 0, 0); (void) duk_normalize_index(ctx, 0); (void) duk_pcall_method(ctx, 0); (void) duk_pcall_prop(ctx, 0, 0); (void) duk_pcall(ctx, 0); (void) duk_pcompile_lstring_filename(ctx, 0, "dummy", 0); (void) duk_pcompile_lstring(ctx, 0, "dummy", 0); (void) duk_pcompile_string_filename(ctx, 0, "dummy"); (void) duk_pcompile_string(ctx, 0, "dummy"); (void) duk_pcompile(ctx, 0); (void) duk_peval_lstring_noresult(ctx, "dummy", 0); (void) duk_peval_lstring(ctx, "dummy", 0); (void) duk_peval_noresult(ctx); (void) duk_peval_string_noresult(ctx, "dummy"); (void) duk_peval_string(ctx, "dummy"); (void) duk_peval(ctx); (void) duk_pnew(ctx, 0); (void) duk_pop_2(ctx); (void) duk_pop_3(ctx); (void) duk_pop_n(ctx, 0); (void) duk_pop(ctx); (void) duk_push_array(ctx); (void) duk_push_boolean(ctx, 0); (void) duk_push_buffer_object(ctx, 0, 0, 0, 0); (void) duk_push_buffer(ctx, 0, 0); (void) duk_push_c_function(ctx, NULL, 0); (void) duk_push_c_lightfunc(ctx, NULL, 0, 0, 0); (void) duk_push_context_dump(ctx); (void) duk_push_current_function(ctx); (void) duk_push_current_thread(ctx); (void) duk_push_dynamic_buffer(ctx, 0); (void) duk_push_error_object_va(ctx, 0, NULL, NULL); (void) duk_push_error_object(ctx, 0, "dummy"); (void) duk_push_external_buffer(ctx); (void) duk_push_false(ctx); (void) duk_push_fixed_buffer(ctx, 0); (void) duk_push_global_object(ctx); (void) duk_push_global_stash(ctx); (void) duk_push_heap_stash(ctx); (void) duk_push_heapptr(ctx, NULL); (void) duk_push_int(ctx, 0); (void) duk_push_lstring(ctx, "dummy", 0); (void) duk_push_nan(ctx); (void) duk_push_null(ctx); (void) duk_push_number(ctx, 0.0); (void) duk_push_object(ctx); (void) duk_push_pointer(ctx, NULL); (void) duk_push_sprintf(ctx, "dummy"); (void) duk_push_string(ctx, "dummy"); (void) duk_push_this(ctx); (void) duk_push_thread_new_globalenv(ctx); (void) duk_push_thread_stash(ctx, NULL); (void) duk_push_thread(ctx); (void) duk_push_true(ctx); (void) duk_push_uint(ctx, 0); (void) duk_push_undefined(ctx); (void) duk_push_vsprintf(ctx, "dummy", NULL); (void) duk_put_function_list(ctx, 0, NULL); (void) duk_put_global_string(ctx, NULL); (void) duk_put_number_list(ctx, 0, NULL); (void) duk_put_prop_index(ctx, 0, 0); (void) duk_put_prop_string(ctx, 0, "dummy"); (void) duk_put_prop(ctx, 0); (void) duk_realloc_raw(ctx, NULL, 0); (void) duk_realloc(ctx, NULL, 0); (void) duk_remove(ctx, 0); (void) duk_replace(ctx, 0); (void) duk_require_boolean(ctx, 0); (void) duk_require_buffer_data(ctx, 0, NULL); (void) duk_require_buffer(ctx, 0, NULL); (void) duk_require_c_function(ctx, 0); (void) duk_require_callable(ctx, 0); (void) duk_require_context(ctx, 0); (void) duk_require_function(ctx, 0); (void) duk_require_heapptr(ctx, 0); (void) duk_require_int(ctx, 0); (void) duk_require_lstring(ctx, 0, NULL); (void) duk_require_normalize_index(ctx, 0); (void) duk_require_null(ctx, 0); (void) duk_require_number(ctx, 0); (void) duk_require_object_coercible(ctx, 0); (void) duk_require_pointer(ctx, 0); (void) duk_require_stack_top(ctx, 0); (void) duk_require_stack(ctx, 0); (void) duk_require_string(ctx, 0); (void) duk_require_top_index(ctx); (void) duk_require_type_mask(ctx, 0, 0); (void) duk_require_uint(ctx, 0); (void) duk_require_undefined(ctx, 0); (void) duk_require_valid_index(ctx, 0); (void) duk_resize_buffer(ctx, 0, 0); (void) duk_safe_call(ctx, NULL, NULL, 0, 0); (void) duk_safe_to_lstring(ctx, 0, NULL); (void) duk_safe_to_string(ctx, 0); (void) duk_set_finalizer(ctx, 0); (void) duk_set_global_object(ctx); (void) duk_set_magic(ctx, 0, 0); (void) duk_set_prototype(ctx, 0); (void) duk_set_top(ctx, 0); (void) duk_steal_buffer(ctx, 0, NULL); (void) duk_strict_equals(ctx, 0, 0); (void) duk_substring(ctx, 0, 0, 0); (void) duk_swap_top(ctx, 0); (void) duk_swap(ctx, 0, 0); (void) duk_throw(ctx); (void) duk_to_boolean(ctx, 0); (void) duk_to_buffer(ctx, 0, NULL); (void) duk_to_defaultvalue(ctx, 0, 0); (void) duk_to_dynamic_buffer(ctx, 0, NULL); (void) duk_to_fixed_buffer(ctx, 0, NULL); (void) duk_to_int32(ctx, 0); (void) duk_to_int(ctx, 0); (void) duk_to_lstring(ctx, 0, NULL); (void) duk_to_null(ctx, 0); (void) duk_to_number(ctx, 0); (void) duk_to_object(ctx, 0); (void) duk_to_pointer(ctx, 0); (void) duk_to_primitive(ctx, 0, 0); (void) duk_to_string(ctx, 0); (void) duk_to_uint16(ctx, 0); (void) duk_to_uint32(ctx, 0); (void) duk_to_uint(ctx, 0); (void) duk_to_undefined(ctx, 0); (void) duk_trim(ctx, 0); (void) duk_xcopy_top(ctx, NULL, 0); (void) duk_xmove_top(ctx, NULL, 0); printf("never here\n"); fflush(stdout); return 0; }
static duk_ret_t test_1(duk_context *ctx, void *udata) { duk_size_t i, n; char *buf; (void) udata; duk_set_top(ctx, 0); duk_push_undefined(ctx); duk_push_null(ctx); duk_push_true(ctx); duk_push_false(ctx); duk_push_nan(ctx); duk_push_number(ctx, -INFINITY); duk_push_number(ctx, +INFINITY); duk_push_number(ctx, -0.0); duk_push_number(ctx, +0.0); duk_push_int(ctx, 123); duk_push_string(ctx, "foo"); duk_push_lstring(ctx, "foo\0bar", 7); /* internal NULs are kept */ duk_push_object(ctx); buf = (char *) duk_push_fixed_buffer(ctx, 0); buf = (char *) duk_push_fixed_buffer(ctx, 16); for (i = 0; i < 16; i++) { buf[i] = i; } buf = (char *) duk_push_dynamic_buffer(ctx, 0); buf = (char *) duk_push_dynamic_buffer(ctx, 16); for (i = 0; i < 16; i++) { buf[i] = i; } duk_push_pointer(ctx, (void *) NULL); duk_push_pointer(ctx, (void *) 0xdeadbeef); n = duk_get_top(ctx); printf("top: %ld\n", (long) n); for (i = 0; i < n; i++) { duk_int_t t1, t2; void *ptr; duk_size_t sz; duk_dup(ctx, i); t1 = duk_get_type(ctx, -1); sz = (duk_size_t) 0xdeadbeef; ptr = duk_to_buffer(ctx, -1, &sz); t2 = duk_get_type(ctx, -1); printf("index %ld, type %ld -> %ld, ptr-is-NULL %d, size %lu\n", (long) i, (long) t1, (long) t2, (sz == 0 ? -1 : (ptr == NULL ? 1 : 0)), (unsigned long) sz); dump_buffer(ctx); duk_pop(ctx); /* just check that this doesn't break */ duk_dup(ctx, i); ptr = duk_to_buffer(ctx, -1, NULL); duk_pop(ctx); } return 0; }