Exemplo n.º 1
0
void CallConnectSignal(duk_context* ctx, void* signal)
{
    int numArgs = duk_get_top(ctx);
    duk_push_number(ctx, (size_t)signal);
    duk_insert(ctx, 0);
    duk_push_global_object(ctx);
    duk_get_prop_string(ctx, -1, "_ConnectSignal");
    duk_remove(ctx, -2); // Global object
    duk_insert(ctx, 0);
    duk_pcall(ctx, numArgs + 1);
    duk_pop(ctx);
}
Exemplo n.º 2
0
static void duk__call_errhandler(duk_hthread *thr) {
	int call_flags;
	int rc;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);

	if (!thr->heap->lj.errhandler) {
		DUK_DDDPRINT("no errhandler, return");
		return;
	}

	/* FIXME: assert/require for valstack space */

	/* [ ... errval ] */

	DUK_DDDPRINT("errhandler is %p", (void *) thr->heap->lj.errhandler);
	DUK_DDDPRINT("errhandler dump: %!O", (duk_heaphdr *) thr->heap->lj.errhandler);

	duk_push_hobject((duk_context *) thr, thr->heap->lj.errhandler);
	duk_insert((duk_context *) thr, -2);  /* -> [ ... errhandler errval ] */
	duk_push_undefined((duk_context *) thr);
	duk_insert((duk_context *) thr, -2);  /* -> [ ... errhandler undefined(= this) errval ] */

	/* [ ... errhandler undefined errval ] */

	/*
	 *  DUK_CALL_FLAG_IGNORE_RECLIMIT causes duk_handle_call() to ignore C
	 *  recursion depth limit (and won't increase it either).  This is
	 *  dangerous, but useful because it allows an errhandler to run even
	 *  if the original error is caused by C recursion depth limit.  Because
	 *  errhandler is NULL in the errhandler call, the errhandler call
	 *  can't cause the same situation to occur again.
	 *
	 *  We ignore errors now: a success return and an error value both
	 *  replace the original error value.  (This would be easy to change.)
	 */

	call_flags = DUK_CALL_FLAG_PROTECTED |
	             DUK_CALL_FLAG_IGNORE_RECLIMIT;  /* protected, ignore reclimit, not constructor */

	rc = duk_handle_call(thr,
	                     1,          /* num args */
	                     call_flags, /* call_flags */
	                     NULL);      /* errhandler */
	DUK_UNREF(rc);  /* no need to check now: both success and error are OK */

	/* [ ... errval ] */
}
Exemplo n.º 3
0
/* Shared helper to implement Object.getPrototypeOf and the ES6
 * Object.prototype.__proto__ getter.
 *
 * https://people.mozilla.org/~jorendorff/es6-draft.html#sec-get-object.prototype.__proto__
 */
duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx) {
	duk_hobject *h;

	/* magic: 0=getter call, 1=Object.getPrototypeOf */
	if (duk_get_current_magic(ctx) == 0) {
		duk_push_this_coercible_to_object(ctx);
		duk_insert(ctx, 0);
	}

	h = duk_require_hobject(ctx, 0);
	DUK_ASSERT(h != NULL);

	/* XXX: should the API call handle this directly, i.e. attempt
	 * to duk_push_hobject(ctx, null) would push a null instead?
	 * (On the other hand 'undefined' would be just as logical, but
	 * not wanted here.)
	 */

	if (h->prototype) {
		duk_push_hobject(ctx, h->prototype);
	} else {
		duk_push_null(ctx);
	}
	return 1;
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
0
DUK_INTERNAL duk_ret_t duk_bi_function_prototype_call(duk_context *ctx) {
	duk_idx_t nargs;

	/* Step 1 is not necessary because duk_call_method() will take
	 * care of it.
	 */

	/* vararg function, thisArg needs special handling */
	nargs = duk_get_top(ctx);  /* = 1 + arg count */
	if (nargs == 0) {
		duk_push_undefined(ctx);
		nargs++;
	}
	DUK_ASSERT(nargs >= 1);

	/* [ thisArg arg1 ... argN ] */

	duk_push_this(ctx);  /* 'func' in the algorithm */
	duk_insert(ctx, 0);

	/* [ func thisArg arg1 ... argN ] */

	DUK_DDD(DUK_DDDPRINT("func=%!iT, thisArg=%!iT, argcount=%ld, top=%ld",
	                     (duk_tval *) duk_get_tval(ctx, 0),
	                     (duk_tval *) duk_get_tval(ctx, 1),
	                     (long) (nargs - 1),
	                     (long) duk_get_top(ctx)));
	duk_call_method(ctx, nargs - 1);
	return 1;
}
Exemplo n.º 6
0
/* Shared helper to implement ES6 Object.setPrototypeOf and
 * Object.prototype.__proto__ setter.
 *
 * https://people.mozilla.org/~jorendorff/es6-draft.html#sec-get-object.prototype.__proto__
 * https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.setprototypeof
 */
duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx) {
	duk_hthread *thr = (duk_hthread *) ctx;
	duk_hobject *h_obj;
	duk_hobject *h_new_proto;
	duk_hobject *h_curr;
	duk_ret_t ret_success = 1;  /* retval for success path */

	/* Preliminaries for __proto__ and setPrototypeOf (E6 19.1.2.18 steps 1-4);
	 * magic: 0=setter call, 1=Object.setPrototypeOf
	 */
	if (duk_get_current_magic(ctx) == 0) {
		duk_push_this_check_object_coercible(ctx);
		duk_insert(ctx, 0);
		if (!duk_check_type_mask(ctx, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT)) {
			return 0;
		}

		/* __proto__ setter returns 'undefined' on success unlike the
		 * setPrototypeOf() call which returns the target object.
		 */
		ret_success = 0;
	} else {
		duk_require_object_coercible(ctx, 0);
		duk_require_type_mask(ctx, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT);
	}
	h_obj = duk_get_hobject(ctx, 0);
	if (!h_obj) {
		goto skip;
	}
	h_new_proto = duk_get_hobject(ctx, 1);
	DUK_ASSERT(h_obj != NULL);
	/* h_new_proto may be NULL */

	/* [[SetPrototypeOf]] standard behavior, E6 9.1.2 */
	/* NOTE: steps 7-8 seem to be a cut-paste bug in the E6 draft */
	/* TODO: implement Proxy object support here */

	if (h_new_proto == h_obj->prototype) {
		goto skip;
	}
	if (!DUK_HOBJECT_HAS_EXTENSIBLE(h_obj)) {
		goto fail_nonextensible;
	}
	for (h_curr = h_new_proto; h_curr != NULL; h_curr = h_curr->prototype) {
		/* Loop prevention */
		if (h_curr == h_obj) {
			goto fail_loop;
		}
	}
	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h_obj, h_new_proto);
	/* fall thru */

 skip:
	duk_set_top(ctx, 1);
	return ret_success;

 fail_nonextensible:
 fail_loop:
	return DUK_RET_TYPE_ERROR;
}
Exemplo n.º 7
0
DUK_INTERNAL duk_ret_t duk_bi_array_prototype_to_string(duk_context *ctx) {
	(void) duk_push_this_coercible_to_object(ctx);
	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_JOIN);

	/* [ ... this func ] */
	if (!duk_is_callable(ctx, -1)) {
		/* Fall back to the initial (original) Object.toString().  We don't
		 * currently have pointers to the built-in functions, only the top
		 * level global objects (like "Array") so this is now done in a bit
		 * of a hacky manner.  It would be cleaner to push the (original)
		 * function and use duk_call_method().
		 */

		/* XXX: 'this' will be ToObject() coerced twice, which is incorrect
		 * but should have no visible side effects.
		 */
		DUK_DDD(DUK_DDDPRINT("this.join is not callable, fall back to (original) Object.toString"));
		duk_set_top(ctx, 0);
		return duk_bi_object_prototype_to_string(ctx);  /* has access to 'this' binding */
	}

	/* [ ... this func ] */

	duk_insert(ctx, -2);

	/* [ ... func this ] */

	DUK_DDD(DUK_DDDPRINT("calling: func=%!iT, this=%!iT",
	                     (duk_tval *) duk_get_tval(ctx, -2),
	                     (duk_tval *) duk_get_tval(ctx, -1)));
	duk_call_method(ctx, 0);

	return 1;
}
Exemplo n.º 8
0
static duk_ret_t my_print(duk_context *ctx) {
	duk_push_string(ctx, " ");
	duk_insert(ctx, 0);
	duk_join(ctx, duk_get_top(ctx) - 1);
	printf("%s\n", duk_safe_to_string(ctx, -1));
	return 0;
}
Exemplo n.º 9
0
/* Shared helper to implement Object.getPrototypeOf and the ES6
 * Object.prototype.__proto__ getter.
 *
 * https://people.mozilla.org/~jorendorff/es6-draft.html#sec-get-object.prototype.__proto__
 */
DUK_INTERNAL duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx) {
	duk_hobject *h;
	duk_hobject *proto;

	/* magic: 0=getter call, 1=Object.getPrototypeOf */
	if (duk_get_current_magic(ctx) == 0) {
		duk_push_this_coercible_to_object(ctx);
		duk_insert(ctx, 0);
	}

	h = duk_require_hobject_or_lfunc(ctx, 0);
	/* h is NULL for lightfunc */

	/* XXX: should the API call handle this directly, i.e. attempt
	 * to duk_push_hobject(ctx, null) would push a null instead?
	 * (On the other hand 'undefined' would be just as logical, but
	 * not wanted here.)
	 */

	if (h == NULL) {
		duk_push_hobject_bidx(ctx, DUK_BIDX_FUNCTION_PROTOTYPE);
	} else {
		proto = DUK_HOBJECT_GET_PROTOTYPE(h);
		if (proto) {
			duk_push_hobject(ctx, proto);
		} else {
			duk_push_null(ctx);
		}
	}
	return 1;
}
Exemplo n.º 10
0
// Given a module and js code, compile the code and execute as CJS module
// return the result of the compiled code ran as a function.
static duk_ret_t duv_mod_compile(duk_context *ctx) {
  // Check the args
  const duv_schema_entry schema[] = {
    { "code", dschema_is_data },
    { NULL, NULL }
  };

  dschema_check(ctx, schema);

  duk_to_string(ctx, 0);

  duk_push_this(ctx);
  duk_get_prop_string(ctx, -1, "id");

  // Wrap the code
  duk_push_string(ctx, "function(){var module=this,exports=this.exports,require=this.require.bind(this);");
  duk_dup(ctx, 0);
  duk_push_string(ctx, "}");
  duk_concat(ctx, 3);
  duk_insert(ctx, -2);

  // Compile to a function
  duk_compile(ctx, DUK_COMPILE_FUNCTION);

  duk_push_this(ctx);
  duk_call_method(ctx, 0);

  return 1;
}
Exemplo n.º 11
0
DUK_INTERNAL duk_ret_t duk_bi_string_prototype_concat(duk_context *ctx) {
	/* duk_concat() coerces arguments with ToString() in correct order */
	(void) duk_push_this_coercible_to_string(ctx);
	duk_insert(ctx, 0);  /* this is relatively expensive */
	duk_concat(ctx, duk_get_top(ctx));
	return 1;
}
Exemplo n.º 12
0
/* Prepare value stack for a method call through an object property.
 * May currently throw an error e.g. when getting the property.
 */
DUK_LOCAL void duk__call_prop_prep_stack(duk_context *ctx, duk_idx_t normalized_obj_idx, duk_idx_t nargs) {
	DUK_ASSERT_CTX_VALID(ctx);

	DUK_DDD(DUK_DDDPRINT("duk__call_prop_prep_stack, normalized_obj_idx=%ld, nargs=%ld, stacktop=%ld",
	                     (long) normalized_obj_idx, (long) nargs, (long) duk_get_top(ctx)));

	/* [... key arg1 ... argN] */

	/* duplicate key */
	duk_dup(ctx, -nargs - 1);  /* Note: -nargs alone would fail for nargs == 0, this is OK */
	duk_get_prop(ctx, normalized_obj_idx);

	DUK_DDD(DUK_DDDPRINT("func: %!T", (duk_tval *) duk_get_tval(ctx, -1)));

	/* [... key arg1 ... argN func] */

	duk_replace(ctx, -nargs - 2);

	/* [... func arg1 ... argN] */

	duk_dup(ctx, normalized_obj_idx);
	duk_insert(ctx, -nargs - 1);

	/* [... func this arg1 ... argN] */
}
Exemplo n.º 13
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);
}
Exemplo n.º 14
0
duk_ret_t duv_setup_request(duk_context *ctx, uv_req_t* req, int callback) {
  // Create a new container object for the request with request methods
  duk_push_object(ctx);
  duk_push_heap_stash(ctx);
  duk_get_prop_string(ctx, -1, "req-prototype");
  duk_remove(ctx, -2);
  duk_set_prototype(ctx, -2);

  // Set buffer as uv-data internal property.
  duk_insert(ctx, -2);
  duk_put_prop_string(ctx, -2, "\xff""uv-data");

  // Store the request type.
  duk_push_int(ctx, req->type);
  duk_put_prop_string(ctx, -2, "\xff""req-type");

  // Store a reference to the lua callback
  duk_dup(ctx, callback);
  duk_put_prop_string(ctx, -2, "\xff""uv-callback");

  // Store this object in the heap stack keyed by the request's pointer address.
  // This will prevent it from being garbage collected and allow us to find
  // it with nothing more than the request's address.
  duv_store_handle(ctx, req);

  // Store the context in the handle so it can use duktape APIs.
  req->data = ctx;

  // TODO: is this still on the stack?
  return 1;
}
Exemplo n.º 15
0
DUK_EXTERNAL void duk_call(duk_context *ctx, duk_idx_t nargs) {
	duk_hthread *thr = (duk_hthread *) ctx;
	duk_small_uint_t call_flags;
	duk_idx_t idx_func;

	DUK_ASSERT_CTX_VALID(ctx);
	DUK_ASSERT(thr != NULL);

	idx_func = duk_get_top(ctx) - nargs - 1;
	if (idx_func < 0 || nargs < 0) {
		/* note that we can't reliably pop anything here */
		DUK_ERROR_TYPE_INVALID_ARGS(thr);
	}

	/* XXX: awkward; we assume there is space for this, overwrite
	 * directly instead?
	 */
	duk_push_undefined(ctx);
	duk_insert(ctx, idx_func + 1);

	call_flags = 0;  /* not protected, respect reclimit, not constructor */

	duk_handle_call_unprotected(thr,           /* thread */
	                            nargs,         /* num_stack_args */
	                            call_flags);   /* call_flags */
}
Exemplo n.º 16
0
void CallDisconnectSignal(duk_context* ctx, void* signal)
{
    int numArgs = duk_get_top(ctx);
    duk_push_number(ctx, (size_t)signal);
    duk_insert(ctx, 0);
    duk_push_global_object(ctx);
    duk_get_prop_string(ctx, -1, "_DisconnectSignal");
    duk_remove(ctx, -2); // Global object
    duk_insert(ctx, 0);
    duk_pcall(ctx, numArgs + 1);
    if (duk_get_boolean(ctx, -1)) // Last receiver disconnected
    {
        HashMap<void*, SharedPtr<SignalReceiver> >& signalReceivers = JavaScriptInstance::InstanceFromContext(ctx)->SignalReceivers();
        signalReceivers.Erase(signal);
    }
    duk_pop(ctx); // Result
}
Exemplo n.º 17
0
/*
 * Fulfill a libuv request.
 */
void
mn_fulfill_req(duk_context *ctx, uv_req_t *req, int nargs) {
	mn_req_t *data = req->data;
	if (data->callback_ref) {
		mn_push_ref(ctx, data->callback_ref);
		if (nargs) {
			duk_insert(ctx, -1 - nargs);
		}
		mn_push_ref(ctx, data->context);
		if (nargs) {
			duk_insert(ctx, -1 - nargs);
		}
		duk_call_method(ctx, nargs);
		duk_pop(ctx);
	} else if (nargs) {
		duk_pop_n(ctx, nargs);
	}
}
Exemplo n.º 18
0
DUK_LOCAL void duk__get_this_regexp(duk_hthread *thr) {
	duk_hobject *h;

	duk_push_this(thr);
	h = duk_require_hobject_with_class(thr, -1, DUK_HOBJECT_CLASS_REGEXP);
	DUK_ASSERT(h != NULL);
	DUK_UNREF(h);
	duk_insert(thr, 0);  /* prepend regexp to valstack 0 index */
}
Exemplo n.º 19
0
// Default Duktape.modLoad implementation
// return Duktape.modCompile.call(module, loadFile(module.id));
//     or load shared libraries using Duktape.loadlib.
static duk_ret_t duv_mod_load(duk_context *ctx) {
  const char* id;
  const char* ext;

  const duv_schema_entry schema[] = {
    { NULL, NULL }
  };

  dschema_check(ctx, schema);

  duk_get_global_string(ctx, "Duktape");
  duk_push_this(ctx);
  duk_get_prop_string(ctx, -1, "id");
  id = duk_get_string(ctx, -1);
  if (!id) {
    duk_error(ctx, DUK_ERR_ERROR, "Missing id in module");
    return 0;
  }

  // calculate the extension to know which compiler to use.
  ext = id + strlen(id);
  while (ext > id && ext[0] != '/' && ext[0] != '.') { --ext; }

  if (strcmp(ext, ".js") != 0) {
    duk_pop(ctx);
    std::string s = std::string(id) + ".js";
    duk_push_string(ctx, s.c_str());
  }

  // Stack: [Duktape, this, id]
  duk_push_c_function(ctx, duv_loadfile, 1);
  // Stack: [Duktape, this, id, loadfile]
  duk_insert(ctx, -2);
  // Stack: [Duktape, this, loadfile, id]
  duk_call(ctx, 1);
  // Stack: [Duktape, this, data]
  duk_get_prop_string(ctx, -3, "modCompile");
  // Stack: [Duktape, this, data, modCompile]
  duk_insert(ctx, -3);
  // Stack: [Duktape, modCompile, this, data]
  duk_call_method(ctx, 1);
  // Stack: [Duktape, exports]
  return 1;
}
Exemplo n.º 20
0
DUK_INTERNAL duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx) {
	duk_idx_t len;
	duk_idx_t i;

	DUK_ASSERT_TOP(ctx, 2);  /* not a vararg function */

	duk_push_this(ctx);
	if (!duk_is_callable(ctx, -1)) {
		DUK_DDD(DUK_DDDPRINT("func is not callable"));
		goto type_error;
	}
	duk_insert(ctx, 0);
	DUK_ASSERT_TOP(ctx, 3);

	DUK_DDD(DUK_DDDPRINT("func=%!iT, thisArg=%!iT, argArray=%!iT",
	                     (duk_tval *) duk_get_tval(ctx, 0),
	                     (duk_tval *) duk_get_tval(ctx, 1),
	                     (duk_tval *) duk_get_tval(ctx, 2)));

	/* [ func thisArg argArray ] */

	if (duk_is_null_or_undefined(ctx, 2)) {
		DUK_DDD(DUK_DDDPRINT("argArray is null/undefined, no args"));
		len = 0;
	} else if (!duk_is_object(ctx, 2)) {
		goto type_error;
	} else {
		DUK_DDD(DUK_DDDPRINT("argArray is an object"));

		/* XXX: make this an internal helper */
		duk_get_prop_stridx(ctx, 2, DUK_STRIDX_LENGTH);
		len = (duk_idx_t) duk_to_uint32(ctx, -1);  /* ToUint32() coercion required */
		duk_pop(ctx);

		duk_require_stack(ctx, len);

		DUK_DDD(DUK_DDDPRINT("argArray length is %ld", (long) len));
		for (i = 0; i < len; i++) {
			duk_get_prop_index(ctx, 2, i);
		}
	}
	duk_remove(ctx, 2);
	DUK_ASSERT_TOP(ctx, 2 + len);

	/* [ func thisArg arg1 ... argN ] */

	DUK_DDD(DUK_DDDPRINT("apply, func=%!iT, thisArg=%!iT, len=%ld",
	                     (duk_tval *) duk_get_tval(ctx, 0),
	                     (duk_tval *) duk_get_tval(ctx, 1),
	                     (long) len));
	duk_call_method(ctx, len);
	return 1;

 type_error:
	return DUK_RET_TYPE_ERROR;
}
Exemplo n.º 21
0
void* duv_require_this_handle(duk_context *ctx, duv_type_mask_t mask) {
  duk_push_this(ctx);
  if (!duv_is_handle_of(ctx, -1, mask)) {
    duk_pop(ctx);
    duk_error(ctx, DUK_ERR_TYPE_ERROR, "this must be %s", duv_mask_to_string(mask));
  }
  void *handle = duv_get_handle(ctx, -1);
  duk_insert(ctx, 0);
  return handle;
}
Exemplo n.º 22
0
void duv_emit(uv_handle_t* handle, const char* key, int nargs, int cleanup) {
  duk_context *ctx = handle->data;
  duv_push_handle(ctx, handle);
  // stack: args... this
  duk_get_prop_string(ctx, -1, key);
  // stack: args... this fn
  if (cleanup) duk_del_prop_string(ctx, -2, key);
  // stack: args... this fn
  if (!duk_is_function(ctx, -1)) {
    duk_pop_n(ctx, 2 + nargs);
    return;
  }
  duk_insert(ctx, -(nargs + 2));
  // stack: fn args... this
  duk_insert(ctx, -(nargs + 1));
  // stack: fn this args...
  duk_call_method(ctx, nargs);
  // stack: result
  duk_pop(ctx);
}
Exemplo n.º 23
0
int duk_bi_error_prototype_to_string(duk_context *ctx) {
	/* FIXME: optimize with more direct internal access */

	duk_push_this(ctx);
	if (!duk_is_object(ctx, -1)) {
		goto type_error;
	}

	/* [ ... this ] */

	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_NAME);
	if (duk_is_undefined(ctx, -1)) {
		duk_pop(ctx);
		duk_push_string(ctx, "Error");
	} else {
		duk_to_string(ctx, -1);
	}

	/* [ ... this name ] */

	/* FIXME: Are steps 6 and 7 in E5 Section 15.11.4.4 duplicated by
	 * accident or are they actually needed?  The first ToString()
	 * could conceivably return 'undefined'.
	 */
	duk_get_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE);
	if (duk_is_undefined(ctx, -1)) {
		duk_pop(ctx);
		duk_push_string(ctx, "");
	} else {
		duk_to_string(ctx, -1);
	}

	/* [ ... this name message ] */

	if (duk_get_length(ctx, -2) == 0) {
		/* name is empty -> return message */
		return 1;
	}
	if (duk_get_length(ctx, -1) == 0) {
		/* message is empty -> return name */
		duk_pop(ctx);
		return 1;
	}
	duk_push_string(ctx, ": ");
	duk_insert(ctx, -2);  /* ... name ': ' message */
	duk_concat(ctx, 3);

	return 1;

 type_error:
	return DUK_RET_TYPE_ERROR;
}
Exemplo n.º 24
0
void
mn_emit_event(
	duk_context *ctx,
	mn_handle_t *data,
	mn_cb_id_t type,
	int nargs
) {
	int fn_ref = data->callbacks[type];
	if (fn_ref) {
		mn_push_ref(ctx, fn_ref);
		if (nargs) {
			duk_insert(ctx, -1 - nargs);
		}
		mn_push_ref(ctx, data->context);
		if (nargs) {
			duk_insert(ctx, -1 - nargs);
		}
		duk_call_method(ctx, nargs);
		duk_pop(ctx);
	} else if (nargs) {
		duk_pop_n(ctx, nargs);
	}
}
Exemplo n.º 25
0
DUK_INTERNAL duk_ret_t duk_bi_object_prototype_defineaccessor(duk_hthread *thr) {
	duk_push_this(thr);
	duk_insert(thr, 0);
	duk_to_object(thr, 0);
	duk_require_callable(thr, 2);

	/* [ ToObject(this) key getter/setter ] */

	/* ToPropertyKey() coercion is not needed, duk_def_prop() does it. */
	duk_def_prop(thr, 0, DUK_DEFPROP_SET_ENUMERABLE |
	                     DUK_DEFPROP_SET_CONFIGURABLE |
	                     (duk_get_current_magic(thr) ? DUK_DEFPROP_HAVE_SETTER : DUK_DEFPROP_HAVE_GETTER));
	return 0;
}
Exemplo n.º 26
0
DUK_INTERNAL void duk_regexp_create_instance(duk_hthread *thr) {
    duk_context *ctx = (duk_context *) thr;
    duk_hobject *h;
    duk_hstring *h_bc;
    duk_small_int_t re_flags;

    /* [ ... escape_source bytecode ] */

    h_bc = duk_get_hstring(ctx, -1);
    DUK_ASSERT(h_bc != NULL);
    DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(h_bc) >= 1);          /* always at least the header */
    DUK_ASSERT(DUK_HSTRING_GET_CHARLEN(h_bc) >= 1);
    DUK_ASSERT((duk_small_int_t) DUK_HSTRING_GET_DATA(h_bc)[0] < 0x80);  /* flags always encodes to 1 byte */
    re_flags = (duk_small_int_t) DUK_HSTRING_GET_DATA(h_bc)[0];

    /* [ ... escaped_source bytecode ] */

    duk_push_object(ctx);
    h = duk_get_hobject(ctx, -1);
    DUK_ASSERT(h != NULL);
    duk_insert(ctx, -3);

    /* [ ... regexp_object escaped_source bytecode ] */

    DUK_HOBJECT_SET_CLASS_NUMBER(h, DUK_HOBJECT_CLASS_REGEXP);
    DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[DUK_BIDX_REGEXP_PROTOTYPE]);

    duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_INT_BYTECODE, DUK_PROPDESC_FLAGS_NONE);

    /* [ ... regexp_object escaped_source ] */

    duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_SOURCE, DUK_PROPDESC_FLAGS_NONE);

    /* [ ... regexp_object ] */

    duk_push_boolean(ctx, (re_flags & DUK_RE_FLAG_GLOBAL));
    duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_GLOBAL, DUK_PROPDESC_FLAGS_NONE);

    duk_push_boolean(ctx, (re_flags & DUK_RE_FLAG_IGNORE_CASE));
    duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_IGNORE_CASE, DUK_PROPDESC_FLAGS_NONE);

    duk_push_boolean(ctx, (re_flags & DUK_RE_FLAG_MULTILINE));
    duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_MULTILINE, DUK_PROPDESC_FLAGS_NONE);

    duk_push_int(ctx, 0);
    duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LAST_INDEX, DUK_PROPDESC_FLAGS_W);

    /* [ ... regexp_object ] */
}
Exemplo n.º 27
0
DUK_EXTERNAL duk_bool_t duk_put_global_string(duk_context *ctx, const char *key) {
	duk_hthread *thr = (duk_hthread *) ctx;
	duk_bool_t ret;

	DUK_ASSERT_CTX_VALID(ctx);
	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);

	/* XXX: direct implementation */

	duk_push_hobject(ctx, thr->builtins[DUK_BIDX_GLOBAL]);
	duk_insert(ctx, -2);
	ret = duk_put_prop_string(ctx, -2, key);  /* [ ... global val ] -> [ ... global ] */
	duk_pop(ctx);
	return ret;
}
Exemplo n.º 28
0
DUK_INTERNAL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx) {
	/* XXX: optimize with more direct internal access */

	duk_push_this(ctx);
	(void) duk_require_hobject_promote_mask(ctx, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);

	/* [ ... this ] */

	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_NAME);
	if (duk_is_undefined(ctx, -1)) {
		duk_pop(ctx);
		duk_push_string(ctx, "Error");
	} else {
		duk_to_string(ctx, -1);
	}

	/* [ ... this name ] */

	/* XXX: Are steps 6 and 7 in E5 Section 15.11.4.4 duplicated by
	 * accident or are they actually needed?  The first ToString()
	 * could conceivably return 'undefined'.
	 */
	duk_get_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE);
	if (duk_is_undefined(ctx, -1)) {
		duk_pop(ctx);
		duk_push_string(ctx, "");
	} else {
		duk_to_string(ctx, -1);
	}

	/* [ ... this name message ] */

	if (duk_get_length(ctx, -2) == 0) {
		/* name is empty -> return message */
		return 1;
	}
	if (duk_get_length(ctx, -1) == 0) {
		/* message is empty -> return name */
		duk_pop(ctx);
		return 1;
	}
	duk_push_string(ctx, ": ");
	duk_insert(ctx, -2);  /* ... name ': ' message */
	duk_concat(ctx, 3);

	return 1;
}
Exemplo n.º 29
0
Arquivo: vm.c Projeto: joegen/sjs
DUK_EXTERNAL int sjs_vm_eval_code(const sjs_vm_t* vm,
                                  const char* filename,
                                  const char* code,
                                  size_t len,
                                  FILE* foutput,
                                  FILE* ferror,
                                  bool use_strict) {
    int r;

    assert(vm);
    duk_context* ctx = vm->ctx;

    duk_push_boolean(ctx, use_strict);
    duk_push_pointer(ctx, (void *) code);
    duk_push_uint(ctx, len);
    duk_push_string(ctx, filename);

    r = duk_safe_call(ctx, sjs__compile_execute, 4 /*nargs*/, 1 /*nret*/);
    if (r != DUK_EXEC_SUCCESS) {
        if (ferror) {
            duk_safe_call(ctx, sjs__get_error_stack, 1 /*nargs*/, 1 /*nrets*/);
            fprintf(ferror, "%s\n", duk_safe_to_string(ctx, -1));
            fflush(ferror);
        }
    } else {
        if (foutput) {
            /* TODO: make this optional with a parameter? */
            /* beautify output */
            duk_eval_string(ctx, "(function (v) {\n"
                                 "    try {\n"
                                 "        return Duktape.enc('jx', v, null, 4);\n"
                                 "    } catch (e) {\n"
                                 "        return String(v);\n"
                                 "    }\n"
                                 "})");
            duk_insert(ctx, -2);
            duk_call(ctx, 1);

            fprintf(foutput, "= %s\n", duk_safe_to_string(ctx, -1));
            fflush(foutput);
        }
    }

    duk_pop(ctx);
    return r;
}
Exemplo n.º 30
0
int invoke_java_method_call(duk_context *ctx) {
    int num = duk_get_top(ctx);
	const char * method = duk_to_string(ctx, 0);
	DEBUG_LOG("ScriptEngine","invoke_java_method call, method name %s  args num %d",  method, (num - 1));
	duk_push_this(ctx);
	if(duk_get_prop_string(ctx, -1, JAVA_OBJECT_MARK)){
		jobject  ref = duk_to_pointer(ctx, -1);
		JNIEnv*  env =  get_java_jni_env();
		DEBUG_LOG("ScriptEngine","invoke_java_method call, method  new String  %s", method);
		jstring methodName = (*env)->NewStringUTF(env, method);
	    jobjectArray args = duk_to_java_object_array(ctx, 1, num-1, env);
	    DEBUG_LOG("ScriptEngine","invoke_java_method call, with args %p   %p", java_api_class,  java_function_method);
		jobject value =  (*env)->CallStaticObjectMethod(env, java_api_class, java_function_method, ref, methodName, args);
		jthrowable exp = ( *env)->ExceptionOccurred(env);
        if(exp != NULL){
        	      ( *env)->ExceptionClear(env);
        	      jstring exceptionMessage = (*env)->CallStaticObjectMethod(env, java_api_class, java_exception_get_stack_trace_method, exp);
              jboolean isCopy = JNI_FALSE;
        	      const char* cstrMessage = (*env)->GetStringUTFChars(env, exceptionMessage, &isCopy);
        	      duk_push_error_object(ctx, DUK_ERR_EVAL_ERROR, "invoke java method  %s exception \n %s",  method, cstrMessage);
        	      (*env)->ReleaseStringUTFChars(env, exceptionMessage, cstrMessage);
        	      ( *env)->DeleteLocalRef(env , exceptionMessage);
        	      (*env)->DeleteLocalRef(env, args);
        	      (*env)->DeleteLocalRef(env, methodName);
        	      duk_throw(ctx);
        	      return 0;
        }
		duk_push_java_object(ctx, env, value);
	    (*env)->DeleteLocalRef(env, value);
	    (*env)->DeleteLocalRef(env, args);
	    (*env)->DeleteLocalRef(env, methodName);
	    DEBUG_LOG("ScriptEngine","invoke_java_method call with args success ");
		return 1;
	}else{
		duk_pop(ctx);
		duk_insert(ctx, 0);
		DEBUG_LOG("ScriptEngine","invoke_script_prop call, with args  num %d ", duk_get_top(ctx));
		if(duk_pcall_prop(ctx, 0, num - 1) != DUK_EXEC_SUCCESS){
			LOGE("ScriptEngine","ScriptEngine call %s method %s error %s", duk_to_string(ctx, 0), method, duk_js_error_to_string(ctx, -1));
			duk_pop(ctx);
			duk_push_null(ctx);
		}
		DEBUG_LOG("ScriptEngine","invoke_script_prop call, duk_get_prop_string with args  num %d ", duk_get_top(ctx));
		return 1;
	}
}