JavaScript-Embedded

 view release on metacpan or  search on metacpan

lib/JavaScript/Embedded/C/lib/duktape.c  view on Meta::CPAN

	duk_require_valid_index(thr, 1);

	if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
		duk_set_top(thr, 2);
		duk_hex_decode(thr, 1);
		DUK_ASSERT_TOP(thr, 2);
	} else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
		duk_set_top(thr, 2);
		duk_base64_decode(thr, 1);
		DUK_ASSERT_TOP(thr, 2);
#if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JX)
	} else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
		duk_bi_json_parse_helper(thr, 1 /*idx_value*/, 2 /*idx_replacer*/, DUK_JSON_FLAG_EXT_CUSTOM /*flags*/);
#endif
#if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JC)
	} else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
		duk_bi_json_parse_helper(thr, 1 /*idx_value*/, 2 /*idx_replacer*/, DUK_JSON_FLAG_EXT_COMPATIBLE /*flags*/);
#endif
	} else {
		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
	}
	return 1;
}

/*
 *  Compact an object
 */

DUK_INTERNAL duk_ret_t duk_bi_duktape_object_compact(duk_hthread *thr) {
	DUK_ASSERT_TOP(thr, 1);
	duk_compact(thr, 0);
	return 1; /* return the argument object */
}

#endif /* DUK_USE_DUKTAPE_BUILTIN */
#line 1 "duk_bi_encoding.c"
/*
 *  WHATWG Encoding API built-ins
 *
 *  API specification: https://encoding.spec.whatwg.org/#api
 *  Web IDL: https://www.w3.org/TR/WebIDL/
 */

/* #include duk_internal.h -> already included */

/*
 *  Data structures for encoding/decoding
 */

typedef struct {
	duk_uint8_t *out; /* where to write next byte(s) */
	duk_codepoint_t lead; /* lead surrogate */
} duk__encode_context;

typedef struct {
	/* UTF-8 decoding state */
	duk_codepoint_t codepoint; /* built up incrementally */
	duk_uint8_t upper; /* max value of next byte (decode error otherwise) */
	duk_uint8_t lower; /* min value of next byte (ditto) */
	duk_uint8_t needed; /* how many more bytes we need */
	duk_uint8_t bom_handled; /* BOM seen or no longer expected */

	/* Decoder configuration */
	duk_uint8_t fatal;
	duk_uint8_t ignore_bom;
} duk__decode_context;

/* The signed duk_codepoint_t type is used to signal a decoded codepoint
 * (>= 0) or various other states using negative values.
 */
#define DUK__CP_CONTINUE (-1) /* continue to next byte, no completed codepoint */
#define DUK__CP_ERROR    (-2) /* decoding error */
#define DUK__CP_RETRY    (-3) /* decoding error; retry last byte */

/*
 *  Raw helpers for encoding/decoding
 */

/* Emit UTF-8 (= CESU-8) encoded U+FFFD (replacement char), i.e. ef bf bd. */
DUK_LOCAL duk_uint8_t *duk__utf8_emit_repl(duk_uint8_t *ptr) {
	*ptr++ = 0xef;
	*ptr++ = 0xbf;
	*ptr++ = 0xbd;
	return ptr;
}

DUK_LOCAL void duk__utf8_decode_init(duk__decode_context *dec_ctx) {
	/* (Re)init the decoding state of 'dec_ctx' but leave decoder
	 * configuration fields untouched.
	 */
	dec_ctx->codepoint = 0x0000L;
	dec_ctx->upper = 0xbf;
	dec_ctx->lower = 0x80;
	dec_ctx->needed = 0;
	dec_ctx->bom_handled = 0;
}

DUK_LOCAL duk_codepoint_t duk__utf8_decode_next(duk__decode_context *dec_ctx, duk_uint8_t x) {
	/*
	 *  UTF-8 algorithm based on the Encoding specification:
	 *  https://encoding.spec.whatwg.org/#utf-8-decoder
	 *
	 *  Two main states: decoding initial byte vs. decoding continuation
	 *  bytes.  Shortest length encoding is validated by restricting the
	 *  allowed range of first continuation byte using 'lower' and 'upper'.
	 */

	if (dec_ctx->needed == 0) {
		/* process initial byte */
		if (x <= 0x7f) {
			/* U+0000-U+007F, 1 byte (ASCII) */
			return (duk_codepoint_t) x;
		} else if (x >= 0xc2 && x <= 0xdf) {
			/* U+0080-U+07FF, 2 bytes */
			dec_ctx->needed = 1;
			dec_ctx->codepoint = x & 0x1f;
			DUK_ASSERT(dec_ctx->lower == 0x80);
			DUK_ASSERT(dec_ctx->upper == 0xbf);
			return DUK__CP_CONTINUE;
		} else if (x >= 0xe0 && x <= 0xef) {
			/* U+0800-U+FFFF, 3 bytes */

lib/JavaScript/Embedded/C/lib/duktape.c  view on Meta::CPAN

		 * string.  For standard ECMAScript strings, represented
		 * internally as CESU-8, this is fine.  However, behavior
		 * beyond CESU-8 is not very strict: codepoints using an
		 * extended form of UTF-8 are also accepted, and invalid
		 * codepoint sequences (which are allowed in Duktape strings)
		 * are not handled as well as they could (e.g. invalid
		 * continuation bytes may mask following codepoints).
		 * This is how ECMAScript code would also see such strings.
		 * Maybe replace duk_decode_string() with an explicit strict
		 * CESU-8 decoder here?
		 */
		enc_ctx.lead = 0x0000L;
		enc_ctx.out = output;
		duk_decode_string(thr, 0, duk__utf8_encode_char, (void *) &enc_ctx);
		if (enc_ctx.lead != 0x0000L) {
			/* unpaired high surrogate at end of string */
			enc_ctx.out = duk__utf8_emit_repl(enc_ctx.out);
			DUK_ASSERT(enc_ctx.out <= output + (3 * len));
		}

		/* The output buffer is usually very much oversized, so shrink it to
		 * actually needed size.  Pointer stability assumed up to this point.
		 */
		DUK_ASSERT_TOP(thr, 2);
		DUK_ASSERT(output == (duk_uint8_t *) duk_get_buffer_data(thr, -1, NULL));

		final_len = (duk_size_t) (enc_ctx.out - output);
		duk_resize_buffer(thr, -1, final_len);
		/* 'output' and 'enc_ctx.out' are potentially invalidated by the resize. */
	} else {
		final_len = 0;
	}

	/* Standard WHATWG output is a Uint8Array.  Here the Uint8Array will
	 * be backed by a dynamic buffer which differs from e.g. Uint8Arrays
	 * created as 'new Uint8Array(N)'.  ECMAScript code won't see the
	 * difference but C code will.  When bufferobjects are not supported,
	 * returns a plain dynamic buffer.
	 */
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
	duk_push_buffer_object(thr, -1, 0, final_len, DUK_BUFOBJ_UINT8ARRAY);
#endif
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_textdecoder_constructor(duk_hthread *thr) {
	duk__decode_context *dec_ctx;
	duk_bool_t fatal = 0;
	duk_bool_t ignore_bom = 0;

	DUK_ASSERT_TOP(thr, 2);
	duk_require_constructor_call(thr);
	if (!duk_is_undefined(thr, 0)) {
		/* XXX: For now ignore 'label' (encoding identifier). */
		duk_to_string(thr, 0);
	}
	if (!duk_is_null_or_undefined(thr, 1)) {
		if (duk_get_prop_literal(thr, 1, "fatal")) {
			fatal = duk_to_boolean(thr, -1);
		}
		if (duk_get_prop_literal(thr, 1, "ignoreBOM")) {
			ignore_bom = duk_to_boolean(thr, -1);
		}
	}

	duk_push_this(thr);

	/* The decode context is not assumed to be zeroed; all fields are
	 * initialized explicitly.
	 */
	dec_ctx = (duk__decode_context *) duk_push_fixed_buffer(thr, sizeof(duk__decode_context));
	dec_ctx->fatal = (duk_uint8_t) fatal;
	dec_ctx->ignore_bom = (duk_uint8_t) ignore_bom;
	duk__utf8_decode_init(dec_ctx); /* Initializes remaining fields. */

	duk_put_prop_literal(thr, -2, DUK_INTERNAL_SYMBOL("Context"));
	return 0;
}

/* Get TextDecoder context from 'this'; leaves garbage on stack. */
DUK_LOCAL duk__decode_context *duk__get_textdecoder_context(duk_hthread *thr) {
	duk__decode_context *dec_ctx;
	duk_push_this(thr);
	duk_get_prop_literal(thr, -1, DUK_INTERNAL_SYMBOL("Context"));
	dec_ctx = (duk__decode_context *) duk_require_buffer(thr, -1, NULL);
	DUK_ASSERT(dec_ctx != NULL);
	return dec_ctx;
}

DUK_INTERNAL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_hthread *thr) {
	duk__decode_context *dec_ctx;
	duk_int_t magic;

	dec_ctx = duk__get_textdecoder_context(thr);
	magic = duk_get_current_magic(thr);
	switch (magic) {
	case 0:
		/* Encoding is now fixed, so _Context lookup is only needed to
		 * validate the 'this' binding (TypeError if not TextDecoder-like).
		 */
		duk_push_literal(thr, "utf-8");
		break;
	case 1:
		duk_push_boolean(thr, dec_ctx->fatal);
		break;
	default:
		duk_push_boolean(thr, dec_ctx->ignore_bom);
		break;
	}

	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_hthread *thr) {
	duk__decode_context *dec_ctx;

	dec_ctx = duk__get_textdecoder_context(thr);
	return duk__decode_helper(thr, dec_ctx);
}
#endif /* DUK_USE_ENCODING_BUILTINS */

/*
 *  Internal helper for Node.js Buffer
 */

/* Internal helper used for Node.js Buffer .toString().  Value stack convention
 * is currently odd: it mimics TextDecoder .decode() so that argument must be at
 * index 0, and decode options (not present for Buffer) at index 1.  Return value
 * is a Duktape/C function return value.
 */
DUK_INTERNAL duk_ret_t duk_textdecoder_decode_utf8_nodejs(duk_hthread *thr) {
	duk__decode_context dec_ctx;

	dec_ctx.fatal = 0; /* use replacement chars */
	dec_ctx.ignore_bom = 1; /* ignore BOMs (matches Node.js Buffer .toString()) */
	duk__utf8_decode_init(&dec_ctx);

	return duk__decode_helper(thr, &dec_ctx);
}

/* automatic undefs */
#undef DUK__CP_CONTINUE
#undef DUK__CP_ERROR
#undef DUK__CP_RETRY
#line 1 "duk_bi_error.c"
/*
 *  Error built-ins
 */

/* #include duk_internal.h -> already included */

DUK_INTERNAL duk_ret_t duk_bi_error_constructor_shared(duk_hthread *thr) {
	/* Behavior for constructor and non-constructor call is
	 * the same except for augmenting the created error.  When
	 * called as a constructor, the caller (duk_new()) will handle
	 * augmentation; when called as normal function, we need to do
	 * it here.
	 */

	duk_small_int_t bidx_prototype = duk_get_current_magic(thr);

	/* same for both error and each subclass like TypeError */
	duk_uint_t flags_and_class =
	    DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_FASTREFS | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR);

	(void) duk_push_object_helper(thr, flags_and_class, bidx_prototype);

	/* If message is undefined, the own property 'message' is not set at
	 * all to save property space.  An empty message is inherited anyway.
	 */
	if (!duk_is_undefined(thr, 0)) {
		duk_to_string(thr, 0);
		duk_dup_0(thr); /* [ message error message ] */
		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
	}

	/* Augment the error if called as a normal function.  __FILE__ and __LINE__
	 * are not desirable in this case.
	 */

#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
	if (!duk_is_constructor_call(thr)) {
		duk_err_augment_error_create(thr, thr, NULL, 0, DUK_AUGMENT_FLAG_NOBLAME_FILELINE);
	}
#endif

	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_error_prototype_to_string(duk_hthread *thr) {
	/* XXX: optimize with more direct internal access */

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



( run in 0.433 second using v1.01-cache-2.11-cpan-f0fbb3f571b )