Esempio n. 1
0
DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code, const char *msg, const char *filename, duk_int_t line) {
#else
DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code) {
#endif
	duk_context *ctx = (duk_context *) thr;
	duk_bool_t double_error = thr->heap->handling_error;

#ifdef DUK_USE_VERBOSE_ERRORS
	DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld, msg=%s, filename=%s, line=%ld",
	                   (long) code, (const char *) msg,
	                   (const char *) filename, (long) line));
#else
	DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld", (long) code));
#endif

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

	thr->heap->handling_error = 1;

	if (!double_error) {
		/* Allow headroom for calls during error handling (see GH-191).
		 * We allow space for 10 additional recursions, with one extra
		 * for, e.g. a print() call at the deepest level.
		 */
		DUK_ASSERT(thr->callstack_max == DUK_CALLSTACK_DEFAULT_MAX);
		thr->callstack_max = DUK_CALLSTACK_DEFAULT_MAX + DUK_CALLSTACK_GROW_STEP + 11;
	}

	DUK_ASSERT(thr->callstack_max == DUK_CALLSTACK_DEFAULT_MAX + DUK_CALLSTACK_GROW_STEP + 11);  /* just making sure */

	/* Sync so that augmentation sees up-to-date activations, NULL
	 * thr->ptr_curr_pc so that it's not used if side effects occur
	 * in augmentation or longjmp handling.
	 */
	duk_hthread_sync_and_null_currpc(thr);

	/*
	 *  Create and push an error object onto the top of stack.
	 *  If a "double error" occurs, use a fixed error instance
	 *  to avoid further trouble.
	 */

	/* XXX: if attempt to push beyond allocated valstack, this double fault
	 * handling fails miserably.  We should really write the double error
	 * directly to thr->heap->lj.value1 and avoid valstack use entirely.
	 */

	if (double_error) {
		if (thr->builtins[DUK_BIDX_DOUBLE_ERROR]) {
			DUK_D(DUK_DPRINT("double fault detected -> push built-in fixed 'double error' instance"));
			duk_push_hobject_bidx(ctx, DUK_BIDX_DOUBLE_ERROR);
		} else {
			DUK_D(DUK_DPRINT("double fault detected; there is no built-in fixed 'double error' instance "
			                 "-> push the error code as a number"));
			duk_push_int(ctx, (duk_int_t) code);
		}
	} else {
		/* Error object is augmented at its creation here. */
		duk_require_stack(ctx, 1);
		/* XXX: unnecessary '%s' formatting here, but cannot use
		 * 'msg' as a format string directly.
		 */
#ifdef DUK_USE_VERBOSE_ERRORS
		duk_push_error_object_raw(ctx,
		                          code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
		                          filename,
		                          line,
		                          "%s",
		                          (const char *) msg);
#else
		duk_push_error_object_raw(ctx,
		                          code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
		                          NULL,
		                          0,
		                          NULL);
#endif
	}

	/*
	 *  Augment error (throw time), unless alloc/double error
	 */

	if (double_error || code == DUK_ERR_ALLOC_ERROR) {
		DUK_D(DUK_DPRINT("alloc or double error: skip throw augmenting to avoid further trouble"));
	} else {
#if defined(DUK_USE_AUGMENT_ERROR_THROW)
		DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT (before throw augment)",
		                     (duk_tval *) duk_get_tval(ctx, -1)));
		duk_err_augment_error_throw(thr);
#endif
	}

	/*
	 *  Finally, longjmp
	 */

	duk_err_setup_heap_ljstate(thr, DUK_LJ_TYPE_THROW);

	thr->callstack_max = DUK_CALLSTACK_DEFAULT_MAX;  /* reset callstack limit */
	thr->heap->handling_error = 0;

	DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT, %!iT (after throw augment)",
	                     (duk_tval *) &thr->heap->lj.value1, (duk_tval *) &thr->heap->lj.value2));

	duk_err_longjmp(thr);
	DUK_UNREACHABLE();
}
Esempio n. 2
0
DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code, const char *msg, const char *filename, duk_int_t line) {
#else
DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code) {
#endif
	duk_context *ctx = (duk_context *) thr;
	duk_bool_t double_error = thr->heap->handling_error;

#ifdef DUK_USE_VERBOSE_ERRORS
	DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld, msg=%s, filename=%s, line=%ld",
	                   (long) code, (const char *) msg,
	                   (const char *) filename, (long) line));
#else
	DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld", (long) code));
#endif

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

	thr->heap->handling_error = 1;

	/*
	 *  Create and push an error object onto the top of stack.
	 *  If a "double error" occurs, use a fixed error instance
	 *  to avoid further trouble.
	 */

	/* XXX: if attempt to push beyond allocated valstack, this double fault
	 * handling fails miserably.  We should really write the double error
	 * directly to thr->heap->lj.value1 and avoid valstack use entirely.
	 */

	if (double_error) {
		if (thr->builtins[DUK_BIDX_DOUBLE_ERROR]) {
			DUK_D(DUK_DPRINT("double fault detected -> push built-in fixed 'double error' instance"));
			duk_push_hobject_bidx(ctx, DUK_BIDX_DOUBLE_ERROR);
		} else {
			DUK_D(DUK_DPRINT("double fault detected; there is no built-in fixed 'double error' instance "
			                 "-> push the error code as a number"));
			duk_push_int(ctx, (duk_int_t) code);
		}
	} else {
		/* Error object is augmented at its creation here. */
		duk_require_stack(ctx, 1);
		/* XXX: unnecessary '%s' formatting here, but cannot use
		 * 'msg' as a format string directly.
		 */
#ifdef DUK_USE_VERBOSE_ERRORS
		duk_push_error_object_raw(ctx,
		                          code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
		                          filename,
		                          line,
		                          "%s",
		                          (const char *) msg);
#else
		duk_push_error_object_raw(ctx,
		                          code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
		                          NULL,
		                          0,
		                          NULL);
#endif
	}

	/*
	 *  Augment error (throw time), unless alloc/double error
	 */

	if (double_error || code == DUK_ERR_ALLOC_ERROR) {
		DUK_D(DUK_DPRINT("alloc or double error: skip throw augmenting to avoid further trouble"));
	} else {
#if defined(DUK_USE_AUGMENT_ERROR_THROW)
		DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT (before throw augment)",
		                     (duk_tval *) duk_get_tval(ctx, -1)));
		duk_err_augment_error_throw(thr);
#endif
	}

	/*
	 *  Finally, longjmp
	 */

	thr->heap->handling_error = 0;

	duk_err_setup_heap_ljstate(thr, DUK_LJ_TYPE_THROW);

	DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT, %!iT (after throw augment)",
	                     (duk_tval *) &thr->heap->lj.value1, (duk_tval *) &thr->heap->lj.value2));

	duk_err_longjmp(thr);
	DUK_UNREACHABLE();
}
Esempio n. 3
0
void duk_err_create_and_throw(duk_hthread *thr, duk_uint32_t code, const char *msg, const char *filename, int line) {
#else
void duk_err_create_and_throw(duk_hthread *thr, duk_uint32_t code) {
#endif
	duk_context *ctx = (duk_context *) thr;
	int double_error = thr->heap->handling_error;

#ifdef DUK_USE_VERBOSE_ERRORS
	DUK_DDPRINT("duk_err_create_and_throw(): code=%d, msg=%s, filename=%s, line=%d",
	             code, msg ? msg : "null", filename ? filename : "null", line);
#else
	DUK_DDPRINT("duk_err_create_and_throw(): code=%d", code);
#endif

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

	thr->heap->handling_error = 1;

	/*
	 *  Create and push an error object onto the top of stack.
	 *  If a "double error" occurs, use a fixed error instance
	 *  to avoid further trouble.
	 */

	/* FIXME: if attempt to push beyond allocated valstack, this double fault
	 * handling fails miserably.  We should really write the double error
	 * directly to thr->heap->lj.value1 and avoid valstack use entirely.
	 */

	if (double_error) {
		if (thr->builtins[DUK_BIDX_DOUBLE_ERROR]) {
			DUK_DPRINT("double fault detected -> push built-in fixed 'double error' instance");
			duk_push_hobject(ctx, thr->builtins[DUK_BIDX_DOUBLE_ERROR]);
		} else {
			DUK_DPRINT("double fault detected; there is no built-in fixed 'double error' instance "
			           "-> push the error code as a number");
			duk_push_int(ctx, code);
		}
	} else {
		/* Error object is augmented at its creation here. */
		duk_require_stack(ctx, 1);
		/* FIXME: unnecessary '%s' formatting here */
#ifdef DUK_USE_VERBOSE_ERRORS
		duk_push_error_object_raw(ctx,
		                          code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
		                          filename,
		                          line,
		                          "%s",
		                          msg);
#else
		duk_push_error_object_raw(ctx,
		                          code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
		                          NULL,
		                          0,
		                          NULL);
#endif
	}

	/*
	 *  Call errhandler (unless error is an alloc error)
	 *
	 *  Note: must back up the current jmpbuf if it is the shared bytecode
	 *  executor one (handled internally by the helper).
	 */

	if (double_error || code == DUK_ERR_ALLOC_ERROR) {
		DUK_DPRINT("alloc or double error: skip calling errhandler to avoid further trouble");
	} else {
		duk__call_errhandler(thr);
	}

	/*
	 *  Finally, longjmp
	 */

	thr->heap->handling_error = 0;

	duk_err_setup_heap_ljstate(thr, DUK_LJ_TYPE_THROW);

	DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT, %!iT",
	             &thr->heap->lj.value1, &thr->heap->lj.value2);

	duk_err_longjmp(thr);
	DUK_UNREACHABLE();
}