Esempio n. 1
0
/* Arguments object still works after dump/load, relies on e.g. _Formals. */
static duk_ret_t test_arguments_object(duk_context *ctx) {
	duk_eval_string(ctx,
		"(function () {\n"
		"    var f = function test(x,y) {\n"
		"        print(typeof arguments, Object.prototype.toString.call(arguments));\n"
		"        print(arguments[0], arguments[1]);\n"
		"        arguments[0] = 123;\n"
		"        print(x, y);\n"
		"    };\n"
		"    return f;\n"
		"})()");
	duk_dup_top(ctx);
	duk_push_string(ctx, "foo");
	duk_push_string(ctx, "bar");
	duk_call(ctx, 2);
	duk_pop(ctx);
	duk_dump_function(ctx);
	duk_load_function(ctx);
	duk_push_string(ctx, "foo");
	duk_push_string(ctx, "bar");
	duk_call(ctx, 2);
	duk_pop(ctx);

	printf("final top: %ld\n", (long) duk_get_top(ctx));
	return 0;
}
/* 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, void *udata) {
	(void) udata;

	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;
}
Esempio n. 3
0
/* Strictness status is preserved. */
static duk_ret_t test_strict(duk_context *ctx) {
	duk_compile_string(ctx, DUK_COMPILE_FUNCTION,
		"function () {\n"
		"    var strict = (function () { return !this; })();\n"
		"    print('strict: ' + strict);\n"
		"}");
	duk_dump_function(ctx);
	duk_load_function(ctx);
	duk_call(ctx, 0);
	duk_pop(ctx);

	duk_compile_string(ctx, DUK_COMPILE_FUNCTION,
		"function () {\n"
		"    'use strict';\n"
		"    var strict = (function () { return !this; })();\n"
		"    print('strict: ' + strict);\n"
		"}");
	duk_dump_function(ctx);
	duk_load_function(ctx);
	duk_call(ctx, 0);
	duk_pop(ctx);

	printf("final top: %ld\n", (long) duk_get_top(ctx));
	return 0;
}
Esempio n. 4
0
/* Test serialization of Eval (instead of function) code:
 *
 * - Bindings established via Eval code are configurable; bindings
 *   established from program and function code are not.  (E5 Section
 *   10.5 step 2).
 *
 * Here we bytecode dump an eval function that is then loaded and executed
 * in the global scope.
 */
static duk_ret_t test_eval_code(duk_context *ctx) {
	/* Demonstrate behavior without dump/load. */
	duk_compile_string(ctx, DUK_COMPILE_EVAL,
		"var testEval1 = 123;"
	);
	duk_call(ctx, 0);
	duk_pop(ctx);
	duk_eval_string_noresult(ctx,
		"print(JSON.stringify(Object.getOwnPropertyDescriptor(this, 'testEval1')));"
	);

	/* Same with dump/load. */
	duk_compile_string(ctx, DUK_COMPILE_EVAL,
		"var testEval2 = 234;"
	);
	duk_dump_function(ctx);
	duk_load_function(ctx);
	duk_call(ctx, 0);
	duk_pop(ctx);
	duk_eval_string_noresult(ctx,
		"print(JSON.stringify(Object.getOwnPropertyDescriptor(this, 'testEval2')));"
	);

	printf("final top: %ld\n", (long) duk_get_top(ctx));
	return 0;
}
Esempio n. 5
0
/* _Varmap is preserved if function needs it. */
static duk_ret_t test_varmap(duk_context *ctx) {
	/* Get access to _Varmap by creating a function that provides
	 * an 'eval service' in a function scope.
	 */
	duk_compile_string(ctx, DUK_COMPILE_FUNCTION,
		"function (code) {\n"
		"    var foo = 123;\n"
		"    eval(code);\n"
		"}");
	duk_dump_function(ctx);
	duk_load_function(ctx);

	duk_dup(ctx, -1);
	duk_push_string(ctx, "print('hello world');");
	duk_call(ctx, 1);
	duk_pop(ctx);

	/* Eval code will use GETVAR to read 'foo', and _Varmap is
	 * needed for that.
	 */

	duk_dup(ctx, -1);
	duk_push_string(ctx, "print(foo);");
	duk_call(ctx, 1);
	duk_pop(ctx);

	duk_pop(ctx);

	printf("final top: %ld\n", (long) duk_get_top(ctx));
	return 0;
}
Esempio n. 6
0
/* Name binding for function expressions is preserved, it is important
 * for recursive functions.
 */
static duk_ret_t test_name_binding_funcexpr(duk_context *ctx) {
	duk_eval_string(ctx,
		"(function () {\n"
		"    var f = function test() { print('i am a ' + typeof test); };\n"
		"    return f;\n"
		"})()");
	duk_dup_top(ctx);
	duk_call(ctx, 0);  /* undumped */
	duk_pop(ctx);
	duk_dump_function(ctx);
	duk_load_function(ctx);
	duk_call(ctx, 0);  /* dump/load */
	duk_pop(ctx);

	duk_eval_string(ctx,
		"(function () {\n"
		"    var f = function test(n) { print(n); if (n > 0) { test(n - 1); } };\n"
		"    return f;\n"
		"})()");
	duk_dup_top(ctx);
	duk_push_int(ctx, 5);
	duk_call(ctx, 1);  /* undumped */
	duk_pop(ctx);
	duk_dump_function(ctx);
	duk_load_function(ctx);
	duk_push_int(ctx, 7);
	duk_call(ctx, 1);  /* dump/load */
	duk_pop(ctx);

	printf("final top: %ld\n", (long) duk_get_top(ctx));
	return 0;
}
Esempio n. 7
0
static duk_int_t duk__eval_module_source(duk_context *ctx, void *udata) {
#else
static duk_int_t duk__eval_module_source(duk_context *ctx) {
#endif
	/*
	 *  Stack: [ ... module source ]
	 */

#if DUK_VERSION >= 19999
	(void) udata;
#endif

	/* Wrap the module code in a function expression.  This is the simplest
	 * way to implement CommonJS closure semantics and matches the behavior of
	 * e.g. Node.js.
	 */
	duk_push_string(ctx, "(function(exports,require,module,__filename,__dirname){");
	duk_dup(ctx, -2);  /* source */
	duk_push_string(ctx, "})");
	duk_concat(ctx, 3);

	/* [ ... module source func_src ] */

	(void) duk_get_prop_string(ctx, -3, "filename");
	duk_compile(ctx, DUK_COMPILE_EVAL);
	duk_call(ctx, 0);

	/* [ ... module source func ] */

	/* Set name for the wrapper function. */
	duk_push_string(ctx, "name");
	duk_push_string(ctx, "main");
	duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_FORCE);

	/* call the function wrapper */
	(void) duk_get_prop_string(ctx, -3, "exports");   /* exports */
	(void) duk_get_prop_string(ctx, -4, "require");   /* require */
	duk_dup(ctx, -5);                                 /* module */
	(void) duk_get_prop_string(ctx, -6, "filename");  /* __filename */
	duk_push_undefined(ctx);                          /* __dirname */
	duk_call(ctx, 5);

	/* [ ... module source result(ignore) ] */

	/* module.loaded = true */
	duk_push_true(ctx);
	duk_put_prop_string(ctx, -4, "loaded");

	/* [ ... module source retval ] */

	duk_pop_2(ctx);

	/* [ ... module ] */

	return 1;
}
static duk_ret_t havefile1_helper_2(duk_context *ctx) {
	duk_push_string(ctx,
		"(function () {\n"
		"    var fn = function haveFileName(v) { v(); return 123; };\n"
		"    return fn;\n"
		"})()");
	duk_push_string(ctx, "dummy_filename.js");
	duk_compile(ctx, DUK_COMPILE_EVAL);
	duk_call(ctx, 0);

	duk_push_c_function(ctx, target_func_hack, 0);
	duk_call(ctx, 1);
	return 0;
}
Esempio n. 9
0
void test(duk_context *ctx) {
	duk_idx_t i, funcidx, argcount;
	duk_ret_t rc;

	/* test C function arg count variants */

	duk_push_c_function(ctx, my_int_adder, 0);              /* [0] = c func with 0 args */
	duk_push_c_function(ctx, my_int_adder, 1);              /* [1] = c func with 1 arg */
	duk_push_c_function(ctx, my_int_adder, 2);              /* [2] = c func with 2 args */
	duk_push_c_function(ctx, my_int_adder, DUK_VARARGS);    /* [3] = c func with varargs */

	for (funcidx = 0; funcidx < 4; funcidx++) {
		for (argcount = 0; argcount < 5; argcount++) {
			duk_dup(ctx, funcidx);
			for (i = 0; i < argcount; i++) {
				duk_push_int(ctx, i + 1);   /* 1, 2, 3, ... */
			}

			/* [ ... func <args> ] */
			duk_call(ctx, argcount);

			printf("funcidx=%ld, argcount=%ld -> result=%ld\n",
			       (long) funcidx, (long) argcount, (long) duk_to_int(ctx, -1));
			duk_pop(ctx);
		}
	}

	/* test C function return value 0 and negative */

	duk_set_top(ctx, 0);
	duk_push_c_function(ctx, my_zero_ret, 0);
	duk_call(ctx, 0);
	printf("top after calling my_zero_ret: %ld, retval='%s'\n",
	       (long) duk_get_top(ctx), duk_to_string(ctx, -1));
	duk_pop(ctx);

	duk_set_top(ctx, 0);
	duk_push_c_function(ctx, my_neg_ret, 0);
	rc = duk_pcall(ctx, 0);
	printf("top after calling my_neg_ret: %ld, rc=%d, retval='%s'\n",
	       (long) duk_get_top(ctx), (int) rc, duk_to_string(ctx, -1));
	duk_pop(ctx);

	duk_set_top(ctx, 0);
	duk_push_c_function(ctx, my_type_error_ret, 0);
	rc = duk_pcall(ctx, 0);
	printf("top after calling my_type_error_ret: %ld, rc=%d, retval='%s'\n",
	       (long) duk_get_top(ctx), (int) rc, duk_to_string(ctx, -1));
	duk_pop(ctx);
}
Esempio n. 10
0
/* Dump/load mandelbrot.  No inner functions but a bit more code. */
static duk_ret_t test_mandel(duk_context *ctx) {
	unsigned char *p;
	duk_size_t i, sz;

	printf("Mandelbrot source length: %ld\n", (long) strlen(MANDELBROT));

	/* Compiled as a function; force source filename. */

	duk_push_string(ctx, MANDELBROT);
	duk_push_string(ctx, "mandel.js");
	duk_compile(ctx, DUK_COMPILE_FUNCTION);
	duk_dump_function(ctx);
	p = (unsigned char *) duk_get_buffer(ctx, -1, &sz);
	for (i = 0; i < sz; i++) {
		printf("%02x", (int) p[i]);
	}
	printf("\n");
	fflush(stdout);

	/* Load test function from dump and execute it. */
	duk_load_function(ctx);
	duk_call(ctx, 0);
	printf("call result: %s\n", duk_safe_to_string(ctx, -1));

	printf("final top: %ld\n", (long) duk_get_top(ctx));
	return 0;
}
Esempio n. 11
0
static duk_ret_t duk__console_log_helper(duk_context *ctx, const char *error_name) {
	duk_idx_t i, n;

	n = duk_get_top(ctx);

	duk_get_global_string(ctx, "console");
	duk_get_prop_string(ctx, -1, "format");

	for (i = 0; i < n; i++) {
		if (duk_check_type_mask(ctx, i, DUK_TYPE_MASK_OBJECT)) {
			/* Slow path formatting. */
			duk_dup(ctx, -1);  /* console.format */
			duk_dup(ctx, i);
			duk_call(ctx, 1);
			duk_replace(ctx, i);  /* arg[i] = console.format(arg[i]); */
		}
	}

	duk_pop_2(ctx);

	duk_push_string(ctx, " ");
	duk_insert(ctx, 0);
	duk_join(ctx, n);

	if (error_name) {
		duk_push_error_object(ctx, DUK_ERR_ERROR, "%s", duk_require_string(ctx, -1));
		duk_push_string(ctx, "name");
		duk_push_string(ctx, error_name);
		duk_def_prop(ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_VALUE);  /* to get e.g. 'Trace: 1 2 3' */
		duk_get_prop_string(ctx, -1, "stack");
	}

	printf("%s\n", duk_to_string(ctx, -1));
	return 0;
}
Esempio n. 12
0
static duk_ret_t test_modsearch_module(duk_context *ignored_ctx, void *udata) {
	duk_context *ctx;

	(void) udata;

	ctx = duk_create_heap_default();
	if (!ctx) {
		printf("Failed to create heap\n");
		return 0;
	}

	/* Dummy print() binding. */
	duk_push_c_function(ctx, my_print, 1);
	duk_put_global_string(ctx, "print");

	/* Register Duktape.modSearch. */
	duk_eval_string(ctx, "(function (fun) { Duktape.modSearch = fun; })");
	duk_push_c_function(ctx, my_modsearch, 4 /*nargs*/);
	duk_call(ctx, 1);
	duk_pop(ctx);

	/* Require test. */
	duk_eval_string_noresult(ctx, "var mod = require('my_module'); print(mod.FLAG_FOO); mod.func1();");

	printf("final top: %ld\n", (long) duk_get_top(ctx));
	duk_destroy_heap(ctx);
	return 0;
}
Esempio n. 13
0
void
_gum_duk_create_subclass (duk_context * ctx,
                          const gchar * parent,
                          const gchar * name,
                          duk_c_function constructor,
                          gint constructor_nargs,
                          duk_c_function finalize)
{
  duk_push_global_object (ctx);
  duk_get_prop_string (ctx, -1, "Object");
  duk_get_prop_string (ctx, -1, "create");

  duk_get_prop_string (ctx, -3, parent);
  duk_get_prop_string (ctx, -1, "prototype");
  duk_dup (ctx, -3);
  duk_dup (ctx, -2);
  duk_call (ctx, 1);

  if (constructor != NULL)
    duk_push_c_function (ctx, constructor, constructor_nargs);
  else
    duk_push_object (ctx);

  duk_dup (ctx, -2);
  if (finalize != NULL)
  {
    duk_push_c_function (ctx, finalize, 2);
    duk_set_finalizer (ctx, -2);
  }
  duk_put_prop_string (ctx, -2, "prototype");
  duk_put_prop_string (ctx, -7, name);
  duk_pop_n (ctx, 6);
}
Esempio n. 14
0
// Assumes nargs are the top of the stack.  Rest comes from request
// Return value is not left on the stack.
void duv_resolve(uv_req_t* req, int nargs) {
  duk_context *ctx = req->data;
  duv_push_handle(ctx, req);
  // stack: args... obj
  duk_get_prop_string(ctx, -1, "\xff""uv-callback");
  // stack: args... obj callback
  duk_del_prop_string(ctx, -2, "\xff""uv-callback");
  // stack: args... obj callback

  if (!duk_is_function(ctx, -1)) {
    // stack: args... obj callback
    duk_pop_n(ctx, 2 + nargs);
    return;
  }
  duk_remove(ctx, -2);
  // stack: args... callback
  duk_insert(ctx, -(nargs + 1));
  // stack: callback args...
  duk_call(ctx, nargs);
  // stack: result
  duk_pop(ctx);

  // Remove the request from the GC roots
  duv_remove_handle(ctx, req);
}
static duk_ret_t test_1(duk_context *ctx, void *udata) {
	(void) udata;

	duk_eval_string(ctx, "(function (x) { print(Duktape.enc('jx', x)); })");

	duk_push_object(ctx);

	/* Ordinary property */
	duk_push_int(ctx, 1);
	duk_put_prop_string(ctx, -2, "foo");  /* obj.foo = 1 */

	/* Internal property \xFF\xFFabc, technically enumerable (based on
	 * property attributes) but because of internal property special
	 * behavior, does not enumerate.
	 */

	duk_push_int(ctx, 2);
	duk_put_prop_string(ctx, -2, "\xff\xff" "abc");  /* obj[\xff\xffabc] = 2, internal property */

	/* Another property with invalid UTF-8 data but doesn't begin with
	 * \xFF => gets enumerated and JX prints out an approximate key.
	 */
	duk_push_int(ctx, 3);
	duk_put_prop_string(ctx, -2, " \xff" "bar");  /* obj[ \xffbar] = 3, invalid utf-8 but not an internal property */
	duk_call(ctx, 1);

	printf("final top: %ld\n", (long) duk_get_top(ctx));
	return 0;
}
static duk_ret_t test_basic(duk_context *ctx, void *udata) {
	(void) udata;

	duk_push_c_function(ctx, dummy_func, 1);
	duk_push_string(ctx, "length");
	duk_push_int(ctx, 3);
	duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE |
	                      DUK_DEFPROP_CLEAR_WRITABLE |
	                      DUK_DEFPROP_CLEAR_ENUMERABLE |
	                      DUK_DEFPROP_SET_CONFIGURABLE);

	printf("added own .length\n");

	duk_eval_string(ctx,
		"(function (fn) {\n"
		"    print(typeof fn);\n"
		"    var desc = Object.getOwnPropertyDescriptor(fn, 'length');\n"
		"    print(desc.writable);\n"
		"    print(desc.enumerable);\n"
		"    print(desc.configurable);\n"
		"    print(desc.value);\n"
		"})");
	duk_dup(ctx, -2);
	duk_call(ctx, 1);

	printf("final top: %ld\n", (long) duk_get_top(ctx));
	return 0;
}
static duk_ret_t test_ecma_call_success(duk_context *ctx) {
	duk_idx_t i;

	/* Ensure stack space for a lot of elements. */
	duk_require_stack(ctx, STACK_REQUIRE + 1);

	/* Make a function call.  Call handling resizes the value stack
	 * back and forth.  At the end, the value stack guaranteed size
	 * must include the STACK_REQUIRE checked above.
	 */

	duk_eval_string(ctx, "(function () { print('hello from ecma func'); return 123 })");
	duk_call(ctx, 0 /*nargs*/);
	printf("duk_call: %s\n", duk_safe_to_string(ctx, -1));

	/* It would be quite awkward for user code to have no stack
	 * guarantees at this point, i.e. require the user code to
	 * call duk_require_stack(ctx, STACK_REQUIRE) again here.
	 */

	for (i = 0; i < STACK_REQUIRE; i++) {
		duk_push_int(ctx, 123);
	}

	printf("final top: %ld\n", (long) duk_get_top(ctx));
	return 0;
}
Esempio n. 18
0
DUK_LOCAL duk_ret_t duk__finalize_helper(duk_context *ctx, void *udata) {
	duk_hthread *thr;

	DUK_ASSERT(ctx != NULL);
	thr = (duk_hthread *) ctx;
	DUK_UNREF(udata);

	DUK_DDD(DUK_DDDPRINT("protected finalization helper running"));

	/* [... obj] */

	/* XXX: Finalizer lookup should traverse the prototype chain (to allow
	 * inherited finalizers) but should not invoke accessors or proxy object
	 * behavior.  At the moment this lookup will invoke proxy behavior, so
	 * caller must ensure that this function is not called if the target is
	 * a Proxy.
	 */

	duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_FINALIZER);  /* -> [... obj finalizer] */
	if (!duk_is_callable(ctx, -1)) {
		DUK_DDD(DUK_DDDPRINT("-> no finalizer or finalizer not callable"));
		return 0;
	}
	duk_dup_m2(ctx);
	duk_push_boolean(ctx, DUK_HEAP_HAS_FINALIZER_NORESCUE(thr->heap));
	DUK_DDD(DUK_DDDPRINT("-> finalizer found, calling finalizer"));
	duk_call(ctx, 2);  /* [ ... obj finalizer obj heapDestruct ]  -> [ ... obj retval ] */
	DUK_DDD(DUK_DDDPRINT("finalizer finished successfully"));
	return 0;

	/* Note: we rely on duk_safe_call() to fix up the stack for the caller,
	 * so we don't need to pop stuff here.  There is no return value;
	 * caller determines rescued status based on object refcount.
	 */
}
static duk_ret_t test_1(duk_context *ctx, void *udata) {
	(void) udata;

	/* Lightfunc, must sanitize the address for the expect string. */
	duk_eval_string(ctx,
		"(function (v) {\n"
		"    print(String(v).replace(/light_[0-9a-fA-f_]+/, 'light_PTR'));\n"
		"})");
	duk_push_c_lightfunc(ctx, dummy_func, 0 /*nargs*/, 0 /*length*/, 0 /*magic*/);
	duk_call(ctx, 1);
	duk_pop(ctx);

	/* Function with a .name containing invalid characters.
	 *
	 * This is not currently handled very well: the .toString() output
	 * uses the name as is, which can make the output technically
	 * incorrect because it won't parse as a function.  However, the
	 * only way to create such functions is from C code so this is a
	 * minor issue.
	 */

	duk_push_c_function(ctx, dummy_func, 0 /*nargs*/);
	duk_push_string(ctx, "name");
	duk_push_string(ctx, "dummy {");
	duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_FORCE);
	printf("%s\n", duk_to_string(ctx, -1));
	duk_pop(ctx);

	printf("final top: %ld\n", (long) duk_get_top(ctx));
	return 0;
}
Esempio n. 20
0
/* Basic dump/load test which exercises all constant types and has an inner
 * function.  Hex dumping the bytecode provides an exact test case dependency
 * to the dump format so that any accidental changes break the test.
 */
static duk_ret_t test_basic(duk_context *ctx) {
	unsigned char *p;
	duk_size_t i, sz;

	/* Integer constants generate LDINT now so also use a fractional
	 * constant to exercise number constants.
	 *
	 * Compiled as a program; force source filename.
	 */
	duk_push_string(ctx, "print('hello', (function adder(x,y) { return x+y; })(1, 2), 3.14);");
	duk_push_string(ctx, "fakeFilename.js");
	duk_compile(ctx, 0);
	duk_dump_function(ctx);
	printf("dump result type: %d\n", (int) duk_get_type(ctx, -1));
	fflush(stdout);
	p = (unsigned char *) duk_get_buffer(ctx, -1, &sz);
	for (i = 0; i < sz; i++) {
		printf("%02x", (int) p[i]);
	}
	printf("\n");
	fflush(stdout);

	/* Load test function from dump and execute it. */
	duk_load_function(ctx);
	printf("load result type: %d\n", (int) duk_get_type(ctx, -1));
	fflush(stdout);
	duk_call(ctx, 0);
	printf("call result type: %d\n", (int) duk_get_type(ctx, -1));
	fflush(stdout);
	printf("call result: %s\n", duk_safe_to_string(ctx, -1));

	printf("final top: %ld\n", (long) duk_get_top(ctx));
	return 0;
}
static duk_ret_t deep_helper_2(duk_context *ctx) {
	duk_push_string(ctx,
		"(function () {\n"
		"    var fn = function noFileName(n, v) { if (n > 0) { noFileName(n - 1, v); } else { v(); } return 123; };\n"
		"    print('delete: ' + delete fn.fileName);\n"
		"    return fn;\n"
		"})()");
	duk_push_string(ctx, "dummy_filename.js");
	duk_compile(ctx, DUK_COMPILE_EVAL);
	duk_call(ctx, 0);

	printf("target depth: %d\n", (int) depth_hack);
	duk_push_int(ctx, depth_hack - 3);  /* account for: one func already in callstack; first call into the helper; final call to target */
	duk_push_c_function(ctx, target_func_hack, 0);
	duk_call(ctx, 2);
	return 0;
}
static void setup_arraybuffer(duk_context *ctx, duk_idx_t idx) {
	idx = duk_require_normalize_index(ctx, idx);
	duk_eval_string(ctx,
		"(function (plain_buffer) {\n"
		"    return new ArrayBuffer(plain_buffer);\n"
		"})\n");
	duk_dup(ctx, idx);
	duk_call(ctx, 1);
}
static void dump_prop(duk_context *ctx) {
	duk_eval_string(ctx,
		"(function (obj) {\n"
		"    print(Duktape.enc('jx', Object.getOwnPropertyDescriptor(obj, 'prop')));\n"
		"})");
	duk_dup(ctx, -2);
	duk_call(ctx, 1);
	duk_pop(ctx);
}
static duk_ret_t havefile2_helper_2(duk_context *ctx) {
	duk_push_string(ctx,
		"(function () {\n"
		"    var fn = function noFileName(v) { v(); return 123; };\n"
		"    print('delete: ' + delete fn.fileName);\n"
		"    return fn;\n"
		"})()");
	duk_push_string(ctx, "dummy_filename.js");
	duk_compile(ctx, DUK_COMPILE_EVAL);
	duk_call(ctx, 0);

	duk_push_c_function(ctx, target_func_hack, 0);
	duk_push_string(ctx, "fileName");
	duk_push_string(ctx, "dummy_filename.c");
	duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_SET_WRITABLE | DUK_DEFPROP_SET_CONFIGURABLE);
	duk_call(ctx, 1);
	return 0;
}
static duk_ret_t test_instanceof(duk_context *ctx, void *udata) {
	(void) udata;

	prep(ctx);

	/* For 'a instanceof b', the [[HasInstance]] algorithm looks up
	 * b.prototype and then walks the internal prototype chain of 'a'
	 * looking for b.prototype.  The rvalue must also be a Function.
	 * So we need a temporary object wrapping one of the objects
	 * created by prep().
	 */

	/* obj0 instanceof { prototype: obj0 } -> true, found */

	duk_eval_string(ctx, "(function (a,b) { print(typeof a, typeof b); print(a instanceof b); })");
	duk_dup(ctx, 0);
	duk_eval_string(ctx, "(function() {})");
	duk_dup(ctx, 0);
	duk_put_prop_string(ctx, -2, "prototype");
	duk_call(ctx, 2);
	duk_pop(ctx);

	/* obj0 instanceof { prototype: obj1 } -> true, found */

	duk_eval_string(ctx, "(function (a,b) { print(typeof a, typeof b); print(a instanceof b); })");
	duk_dup(ctx, 0);
	duk_eval_string(ctx, "(function() {})");
	duk_dup(ctx, 0);
	duk_put_prop_string(ctx, -2, "prototype");
	duk_call(ctx, 2);
	duk_pop(ctx);

	/* obj0 instanceof { prototype: dummy } -> error, loop */

	duk_eval_string(ctx, "(function (a,b) { print(typeof a, typeof b); print(a instanceof b); })");
	duk_dup(ctx, 0);
	duk_eval_string(ctx, "(function() {})");
	duk_push_object(ctx);
	duk_put_prop_string(ctx, -2, "prototype");
	duk_call(ctx, 2);
	duk_pop(ctx);

	return 0;
}
static void setup_typedarray(duk_context *ctx, duk_idx_t idx, const char *name) {
	idx = duk_require_normalize_index(ctx, idx);
	duk_push_sprintf(ctx,
		"(function (plain_buffer) {\n"
		"    return new %s(new ArrayBuffer(plain_buffer));\n"
		"})\n", name);
	duk_eval(ctx);
	duk_dup(ctx, idx);
	duk_call(ctx, 1);
}
static void shared_read_write_index(duk_context *ctx, duk_size_t resize_to) {
	/* [ plain_buffer buffer ] */

	duk_eval_string(ctx,
		"(function (buf) {\n"
		"    print('length', buf.length);\n"
		"    print(buf[0] = 1);\n"
		"    print(buf[99] = 2);\n"
		"    print(buf[100] = 3);\n"   /* outside 'limit', not virtual -> becomes concrete property */
		"    print(0, buf[0]);\n"      /* in buffer */
		"    print(99, buf[99]);\n"    /* in buffer */
		"    print(100, buf[100]);\n"  /* outside duk_hbufferobject 'limit', not virtual */
		"})\n");
	duk_dup(ctx, 1);
	duk_call(ctx, 1);
	duk_pop(ctx);

	/* Resize to fewer number of bytes. */

	duk_resize_buffer(ctx, 0, resize_to);

	/* Reads inside the duk_hbufferobject limit but outside the underlying
	 * buffer return zero; writes are ignored.
	 */

	duk_eval_string(ctx,
		"(function (buf) {\n"
		"    print('length', buf.length);\n"
		"    print(buf[0] = 10);\n"
		"    print(buf[94] = 11);\n"
		"    print(buf[95] = 12);\n"
		"    print(buf[99] = 13);\n"
		"    print(buf[100] = 14);\n"
		"    print(0, buf[0]);\n"     /* in buffer */
		"    print(94, buf[94]);\n"   /* in buffer */
		"    print(95, buf[95]);\n"   /* inside duk_hbufferobject 'limit', but outside buffer */
		"    print(99, buf[99]);\n"   /* inside duk_hbufferobject 'limit', but outside buffer */
		"    print(100, buf[100]);\n"  /* outside duk_hbufferobject 'limit', not virtual */
		"})\n");
	duk_dup(ctx, 1);
	duk_call(ctx, 1);
	duk_pop(ctx);
}
static duk_ret_t test_1(duk_context *ctx, void *udata) {
	(void) udata;

	duk_eval_string_noresult(ctx,
		"this.myFinalizer = function myfin(o) {\n"
		"    print('finalizer, rescuing object', JSON.stringify(o));\n"
		"    var global = new Function('return this')();\n"
		"    global.rescued = o;\n"
		"}\n"
	);

	/* First call; object gets finalized when call returns and call
	 * handling does a duk_set_top() call.  The object is rescued and
	 * later reused.
	 */
	duk_push_c_function(ctx, my_func, 3 /*nargs*/);
	duk_push_null(ctx);
	duk_eval_string(ctx,
		"(function () {\n"
		"    var res = { name: 'my object' };\n"
		"    Duktape.fin(res, myFinalizer);\n"
		"    return res;\n"
		"})()\n");
	duk_push_null(ctx);
	printf("calling\n");
	duk_call(ctx, 3);
	printf("returned\n");
	duk_pop(ctx);

	/* Object is reused for another call, and rescued again. */
	duk_push_c_function(ctx, my_func, 3 /*nargs*/);
	duk_push_null(ctx);
	duk_eval_string(ctx, "rescued");
	duk_eval_string_noresult(ctx, "rescued = null;");
	duk_push_null(ctx);
	printf("calling\n");
	duk_call(ctx, 3);
	printf("returned\n");
	duk_pop(ctx);

	printf("final top: %ld\n", (long) duk_get_top(ctx));
	return 0;
}
static duk_ret_t my_thrower_1(duk_context *ctx) {
	/* When an error is thrown during compilation, the source file/line
	 * is always blamed.
	 */
	duk_push_string(ctx, "\n\n\nfoo=");
	duk_push_string(ctx, "dummy_source.js");
	duk_compile(ctx, DUK_COMPILE_EVAL);
	duk_call(ctx, 0);
	return 0;
}
Esempio n. 30
0
void test(duk_context *ctx) {
	duk_int_t rc;

	/* From API doc */
	duk_push_string(ctx, "print('Hello world!'); 123;");
	duk_eval(ctx);
	printf("return value is: %lf\n", duk_get_number(ctx, -1));
	duk_pop(ctx);

	/* Function expression */
	duk_push_string(ctx, "(function adder(x,y) { return x+y; })");
	duk_eval(ctx);  /* [ func ] */
	duk_push_int(ctx, 123);
	duk_push_int(ctx, 234);
	duk_call(ctx, 2);  /* [ func 123 234 ] -> [ result ] */
	printf("adder(123, 234) -> %lf\n", duk_get_number(ctx, -1));
	duk_pop(ctx);

	/* Protected eval with success */
	duk_push_string(ctx, "print('Hello world!'); 123;");
	rc = duk_peval(ctx);
	printf("return value is: %s (rc=%d)\n", duk_safe_to_string(ctx, -1), (int) rc);
	duk_pop(ctx);

	/* Protected eval with failure */
	duk_push_string(ctx, "throw new Error('eval error');");
	rc = duk_peval(ctx);
	printf("return value is: %s (rc=%d)\n", duk_safe_to_string(ctx, -1), (int) rc);
	duk_pop(ctx);

	/* Protected eval with syntax error */
	duk_push_string(ctx, "obj = {");
	rc = duk_peval(ctx);
	printf("return value is: %s (rc=%d)\n", duk_safe_to_string(ctx, -1), (int) rc);
	duk_pop(ctx);

	/* Plain eval with no result */
	printf("top=%ld\n", (long) duk_get_top(ctx));
	duk_push_string(ctx, "print('doing eval');");
	duk_eval_noresult(ctx);

	/* Protected eval with no result, no error */
	printf("top=%ld\n", (long) duk_get_top(ctx));
	duk_push_string(ctx, "print('doing peval');");
	rc = duk_peval_noresult(ctx);
	printf("rc=%d\n", (int) rc);

	/* Protected eval with no result, syntax error */
	printf("top=%ld\n", (long) duk_get_top(ctx));
	duk_push_string(ctx, "print('doing peval'); obj = {");
	rc = duk_peval_noresult(ctx);
	printf("rc=%d\n", (int) rc);

	printf("top: %ld\n", (long) duk_get_top(ctx));
}