massive cleanup
This commit is contained in:
673
source/quickjs.c
673
source/quickjs.c
@@ -1735,7 +1735,6 @@ enum OPCodeEnum {
|
||||
static JSValue js_call_c_function (JSContext *ctx, JSValue func_obj, JSValue this_obj, int argc, JSValue *argv);
|
||||
static JSValue js_call_bound_function (JSContext *ctx, JSValue func_obj, JSValue this_obj, int argc, JSValue *argv);
|
||||
static JSValue JS_CallInternal (JSContext *ctx, JSValue func_obj, JSValue this_obj, int argc, JSValue *argv, int flags);
|
||||
static JSValue JS_EvalObject (JSContext *ctx, JSValue this_obj, JSValue val, int flags, int scope_idx);
|
||||
int JS_DeleteProperty (JSContext *ctx, JSValue obj, JSValue prop);
|
||||
JSValue __attribute__ ((format (printf, 2, 3)))
|
||||
JS_ThrowInternalError (JSContext *ctx, const char *fmt, ...);
|
||||
@@ -1820,7 +1819,6 @@ static JSValue js_print (JSContext *ctx, JSValue this_val, int argc, JSValue *ar
|
||||
JSValue JS_ThrowOutOfMemory (JSContext *ctx);
|
||||
static JSValue JS_EvalInternal (JSContext *ctx, JSValue this_obj, const char *input, size_t input_len, const char *filename, int flags, int scope_idx);
|
||||
|
||||
static int js_string_compare (JSContext *ctx, const JSText *p1, const JSText *p2);
|
||||
static JSValue JS_ToNumber (JSContext *ctx, JSValue val);
|
||||
static int JS_SetPropertyValue (JSContext *ctx, JSValue this_obj, JSValue prop, JSValue val);
|
||||
static int JS_GetOwnPropertyInternal (JSContext *ctx,
|
||||
@@ -1832,7 +1830,6 @@ static __exception int js_get_length32 (JSContext *ctx, uint32_t *pres, JSValue
|
||||
static __exception int js_get_length64 (JSContext *ctx, int64_t *pres, JSValue obj);
|
||||
static void free_arg_list (JSContext *ctx, JSValue *tab, uint32_t len);
|
||||
static JSValue *build_arg_list (JSContext *ctx, uint32_t *plen, JSValue *parray_arg);
|
||||
static BOOL js_get_fast_array (JSContext *ctx, JSValue obj, JSValue **arrpp, uint32_t *countp);
|
||||
static JSValue js_regexp_toString (JSContext *ctx, JSValue this_val, int argc, JSValue *argv);
|
||||
|
||||
static JSValue js_error_toString (JSContext *ctx, JSValue this_val, int argc, JSValue *argv);
|
||||
@@ -2091,7 +2088,7 @@ static inline BOOL js_check_stack_overflow (JSRuntime *rt,
|
||||
size_t alloca_size) {
|
||||
uintptr_t sp;
|
||||
sp = js_get_stack_pointer () - alloca_size;
|
||||
return unlikely (sp < rt->stack_limit);
|
||||
return unlikely (sp < (uintptr_t)rt->stack_limit);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3357,22 +3354,6 @@ void JS_FreeCString (JSContext *ctx, const char *ptr) {
|
||||
(void)ptr;
|
||||
}
|
||||
|
||||
/* return < 0, 0 or > 0 */
|
||||
static int js_string_compare (JSContext *ctx, const JSText *p1, const JSText *p2) {
|
||||
int len, i;
|
||||
int len1 = (int)JSText_len (p1);
|
||||
int len2 = (int)JSText_len (p2);
|
||||
(void)ctx;
|
||||
len = min_int (len1, len2);
|
||||
for (i = 0; i < len; i++) {
|
||||
uint32_t c1 = string_get (p1, i);
|
||||
uint32_t c2 = string_get (p2, i);
|
||||
if (c1 != c2) return c1 < c2 ? -1 : 1;
|
||||
}
|
||||
if (len1 == len2) return 0;
|
||||
return len1 < len2 ? -1 : 1;
|
||||
}
|
||||
|
||||
static JSValue JS_ConcatString1 (JSContext *ctx, const JSText *p1, const JSText *p2) {
|
||||
JSText *p;
|
||||
uint32_t len;
|
||||
@@ -3380,8 +3361,7 @@ static JSValue JS_ConcatString1 (JSContext *ctx, const JSText *p1, const JSText
|
||||
int len2 = (int)JSText_len (p2);
|
||||
|
||||
len = len1 + len2;
|
||||
if (len > JS_STRING_LEN_MAX)
|
||||
return JS_ThrowInternalError (ctx, "string too long");
|
||||
/* len is uint32_t, JS_STRING_LEN_MAX is 56 bits, so this always fits */
|
||||
p = js_alloc_string (ctx, len);
|
||||
if (!p) return JS_EXCEPTION;
|
||||
/* Pack first string */
|
||||
@@ -3418,18 +3398,6 @@ static BOOL JS_ConcatStringInPlace (JSContext *ctx, JSText *p1, JSValue op2) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static JSValue JS_ConcatString2 (JSContext *ctx, JSValue op1, JSValue op2) {
|
||||
JSValue ret;
|
||||
JSText *p1, *p2;
|
||||
p1 = JS_VALUE_GET_STRING (op1);
|
||||
if (JS_ConcatStringInPlace (ctx, p1, op2)) {
|
||||
return op1;
|
||||
}
|
||||
p2 = JS_VALUE_GET_STRING (op2);
|
||||
ret = JS_ConcatString1 (ctx, p1, p2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Helper for string value comparison (handles immediate and heap strings) */
|
||||
static int js_string_compare_value (JSContext *ctx, JSValue op1, JSValue op2, BOOL eq_only) {
|
||||
(void)ctx;
|
||||
@@ -3527,13 +3495,6 @@ static JSValue JS_ConcatString (JSContext *ctx, JSValue op1, JSValue op2) {
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static JSRecord *get_proto_obj (JSValue proto_val) {
|
||||
if (!JS_IsRecord (proto_val))
|
||||
return NULL;
|
||||
else
|
||||
return JS_VALUE_GET_OBJ (proto_val);
|
||||
}
|
||||
|
||||
/* WARNING: proto must be an object or JS_NULL */
|
||||
JSValue JS_NewObjectProtoClass (JSContext *ctx, JSValue proto_val, JSClassID class_id) {
|
||||
JSGCRef proto_ref;
|
||||
@@ -3610,12 +3571,6 @@ static JSFunctionBytecode *JS_GetFunctionBytecode (JSValue val) {
|
||||
return f->u.func.function_bytecode;
|
||||
}
|
||||
|
||||
static JSValue js_get_function_name (JSContext *ctx, JSValue fn) {
|
||||
JSValue name_str = JS_NULL;
|
||||
// TODO: implement
|
||||
return name_str;
|
||||
}
|
||||
|
||||
// TODO: needs reworked
|
||||
static int js_method_set_properties (JSContext *ctx, JSValue func_obj, JSValue name, int flags, JSValue home_obj) {
|
||||
(void)ctx;
|
||||
@@ -3758,28 +3713,6 @@ static JSValue js_new_function (JSContext *ctx, JSFunctionKind kind) {
|
||||
return JS_MKPTR (func);
|
||||
}
|
||||
|
||||
/* Allocate GC-managed frame for closure support */
|
||||
static JSFrame *js_new_frame (JSContext *ctx, JSFunction *func,
|
||||
JSFrame *caller, uint32_t ret_pc) {
|
||||
JSFunctionBytecode *b = func->u.func.function_bytecode;
|
||||
uint16_t slot_count = b->arg_count + b->var_count + b->stack_size;
|
||||
|
||||
size_t size = sizeof (JSFrame) + slot_count * sizeof (JSValue);
|
||||
JSFrame *f = js_mallocz (ctx, size);
|
||||
if (!f) return NULL;
|
||||
|
||||
f->header = objhdr_make (slot_count, OBJ_FRAME, false, false, false, false);
|
||||
f->function = JS_MKPTR(func);
|
||||
f->caller = caller ? JS_MKPTR(caller) : JS_NULL;
|
||||
f->return_pc = ret_pc;
|
||||
|
||||
/* Initialize all slots to JS_NULL */
|
||||
for (int i = 0; i < slot_count; i++)
|
||||
f->slots[i] = JS_NULL;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
/* Get pointer to an upvalue in outer scope frame chain.
|
||||
depth=0 is current frame, depth=1 is immediate outer, etc.
|
||||
Returns NULL if depth exceeds the frame chain.
|
||||
@@ -3797,76 +3730,6 @@ static inline JSValue *get_upvalue_ptr (JSValue frame_val, int depth, int slot)
|
||||
return &frame->slots[slot];
|
||||
}
|
||||
|
||||
/* Compute memory used by various object types */
|
||||
/* XXX: poor man's approach to handling multiply referenced objects */
|
||||
typedef struct JSMemoryUsage_helper {
|
||||
double memory_used_count;
|
||||
double str_count;
|
||||
double str_size;
|
||||
int64_t js_func_count;
|
||||
double js_func_size;
|
||||
int64_t js_func_code_size;
|
||||
int64_t js_func_pc2line_count;
|
||||
int64_t js_func_pc2line_size;
|
||||
} JSMemoryUsage_helper;
|
||||
|
||||
static void compute_value_size (JSValue val, JSMemoryUsage_helper *hp);
|
||||
|
||||
static void compute_JSText_size (JSText *str, JSMemoryUsage_helper *hp) {
|
||||
/* UTF-32 packs 2 chars per 64-bit word */
|
||||
word_t len = JSText_len (str);
|
||||
size_t data_words = (len + 1) / 2;
|
||||
hp->str_count += 1;
|
||||
hp->str_size += sizeof (*str) + data_words * sizeof (uint64_t);
|
||||
}
|
||||
|
||||
static void compute_bytecode_size (JSFunctionBytecode *b,
|
||||
JSMemoryUsage_helper *hp) {
|
||||
int memory_used_count, js_func_size, i;
|
||||
|
||||
memory_used_count = 0;
|
||||
js_func_size = offsetof (JSFunctionBytecode, debug);
|
||||
if (b->vardefs) {
|
||||
js_func_size += (b->arg_count + b->var_count) * sizeof (*b->vardefs);
|
||||
}
|
||||
if (b->cpool) {
|
||||
js_func_size += b->cpool_count * sizeof (*b->cpool);
|
||||
for (i = 0; i < b->cpool_count; i++) {
|
||||
JSValue val = b->cpool[i];
|
||||
compute_value_size (val, hp);
|
||||
}
|
||||
}
|
||||
if (b->closure_var) {
|
||||
js_func_size += b->closure_var_count * sizeof (*b->closure_var);
|
||||
}
|
||||
if (!b->read_only_bytecode && b->byte_code_buf) {
|
||||
hp->js_func_code_size += b->byte_code_len;
|
||||
}
|
||||
if (b->has_debug) {
|
||||
js_func_size += sizeof (*b) - offsetof (JSFunctionBytecode, debug);
|
||||
if (b->debug.source) {
|
||||
memory_used_count++;
|
||||
js_func_size += b->debug.source_len + 1;
|
||||
}
|
||||
if (b->debug.pc2line_len) {
|
||||
memory_used_count++;
|
||||
hp->js_func_pc2line_count += 1;
|
||||
hp->js_func_pc2line_size += b->debug.pc2line_len;
|
||||
}
|
||||
}
|
||||
hp->js_func_size += js_func_size;
|
||||
hp->js_func_count += 1;
|
||||
hp->memory_used_count += memory_used_count;
|
||||
}
|
||||
|
||||
static void compute_value_size (JSValue val, JSMemoryUsage_helper *hp) {
|
||||
switch (JS_VALUE_GET_TAG (val)) {
|
||||
case JS_TAG_STRING:
|
||||
compute_JSText_size (JS_VALUE_GET_STRING (val), hp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void JS_ComputeMemoryUsage (JSRuntime *rt, JSMemoryUsage *s) {
|
||||
}
|
||||
|
||||
@@ -4007,28 +3870,6 @@ fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return a string property without executing arbitrary JS code (used
|
||||
when dumping the stack trace or in debug print). */
|
||||
static const char *get_prop_string (JSContext *ctx, JSValue obj, JSValue prop) {
|
||||
if (!JS_IsRecord (obj)) return NULL;
|
||||
JSRecord *rec = (JSRecord *)JS_VALUE_GET_OBJ (obj);
|
||||
|
||||
int slot = rec_find_slot (rec, prop);
|
||||
if (slot <= 0) {
|
||||
/* we look at one level in the prototype to handle the 'name'
|
||||
field of the Error objects */
|
||||
JSRecord *proto = rec->proto;
|
||||
if (!proto) return NULL;
|
||||
slot = rec_find_slot (proto, prop);
|
||||
if (slot <= 0) return NULL;
|
||||
rec = proto;
|
||||
}
|
||||
|
||||
JSValue val = rec->slots[slot].val;
|
||||
if (!JS_IsText (val)) return NULL;
|
||||
return JS_ToCString (ctx, val);
|
||||
}
|
||||
|
||||
/* in order to avoid executing arbitrary code during the stack trace
|
||||
generation, we only look at simple 'name' properties containing a
|
||||
string. */
|
||||
@@ -4257,12 +4098,6 @@ static JSValue JS_ThrowTypeErrorNotAnObject (JSContext *ctx) {
|
||||
return JS_ThrowTypeError (ctx, "not an object");
|
||||
}
|
||||
|
||||
static JSValue JS_ThrowReferenceErrorNotDefined (JSContext *ctx,
|
||||
JSValue name) {
|
||||
char buf[KEY_GET_STR_BUF_SIZE];
|
||||
return JS_ThrowReferenceError (ctx, "'%s' is not defined", JS_KeyGetStr (ctx, buf, sizeof (buf), name));
|
||||
}
|
||||
|
||||
static JSValue JS_ThrowReferenceErrorUninitialized (JSContext *ctx,
|
||||
JSValue name) {
|
||||
char buf[KEY_GET_STR_BUF_SIZE];
|
||||
@@ -4582,29 +4417,6 @@ static JSValue JS_Invoke (JSContext *ctx, JSValue this_val, JSValue method, int
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Simplified delete_property using JSRecord.
|
||||
Deletion fails only if object is stone. */
|
||||
static int delete_property (JSContext *ctx, JSRecord *rec, JSValue key) {
|
||||
/* Cannot delete from a stone object */
|
||||
if (obj_is_stone (rec)) return FALSE;
|
||||
|
||||
int slot = rec_find_slot (rec, key);
|
||||
if (slot < 0) {
|
||||
/* not found - success (nothing to delete) */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Free key and value */
|
||||
|
||||
/* Mark as tombstone */
|
||||
rec->slots[slot].key = JS_EXCEPTION; /* tombstone marker */
|
||||
rec->slots[slot].val = JS_NULL;
|
||||
rec->len--;
|
||||
/* tombs tracking removed - not needed with copying GC */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* GC-SAFE: May trigger GC if record needs to resize */
|
||||
int JS_SetProperty (JSContext *ctx, JSValue this_obj, JSValue prop, JSValue val) {
|
||||
if (!JS_IsRecord (this_obj)) {
|
||||
@@ -5674,20 +5486,6 @@ static void js_print_raw_string (JSPrintValueState *s, JSValue val) {
|
||||
js_print_raw_string2 (s, val, FALSE);
|
||||
}
|
||||
|
||||
static BOOL is_ascii_ident (const JSText *p) {
|
||||
int i, c;
|
||||
int len = (int)JSText_len (p);
|
||||
|
||||
if (len == 0) return FALSE;
|
||||
for (i = 0; i < len; i++) {
|
||||
c = string_get (p, i);
|
||||
if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
|
||||
|| (c == '_' || c == '$') || (c >= '0' && c <= '9' && i > 0)))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void js_print_comma (JSPrintValueState *s, int *pcomma_state) {
|
||||
switch (*pcomma_state) {
|
||||
case 0:
|
||||
@@ -5707,75 +5505,6 @@ static void js_print_more_items (JSPrintValueState *s, int *pcomma_state, uint32
|
||||
js_printf (s, "... %u more item%s", n, n > 1 ? "s" : "");
|
||||
}
|
||||
|
||||
static void js_print_object (JSPrintValueState *s, JSRecord *p) {
|
||||
JSRuntime *rt = s->rt;
|
||||
int comma_state;
|
||||
BOOL is_array;
|
||||
uint32_t i;
|
||||
|
||||
comma_state = 0;
|
||||
is_array = FALSE;
|
||||
if (REC_GET_CLASS_ID(p) == JS_CLASS_REGEXP && s->ctx && !s->options.raw_dump) {
|
||||
JSValue str
|
||||
= js_regexp_toString (s->ctx, JS_MKPTR (p), 0, NULL);
|
||||
if (JS_IsException (str)) goto default_obj;
|
||||
js_print_raw_string (s, str);
|
||||
comma_state = 2;
|
||||
} else if (REC_GET_CLASS_ID(p) == JS_CLASS_ERROR && s->ctx && !s->options.raw_dump) {
|
||||
JSValue str
|
||||
= js_error_toString (s->ctx, JS_MKPTR (p), 0, NULL);
|
||||
if (JS_IsException (str)) goto default_obj;
|
||||
js_print_raw_string (s, str);
|
||||
/* dump the stack if present */
|
||||
str = JS_GetProperty (s->ctx, JS_MKPTR (p), JS_KEY_stack);
|
||||
if (JS_IsText (str)) {
|
||||
js_putc (s, '\n');
|
||||
js_print_raw_string2 (s, str, TRUE);
|
||||
}
|
||||
comma_state = 2;
|
||||
} else {
|
||||
default_obj:
|
||||
if (REC_GET_CLASS_ID(p) != JS_CLASS_OBJECT) {
|
||||
const char *name = rt->class_array[REC_GET_CLASS_ID(p)].class_name;
|
||||
if (name) js_printf (s, "%s ", name);
|
||||
}
|
||||
js_printf (s, "{ ");
|
||||
}
|
||||
|
||||
/* Print properties from JSRecord */
|
||||
JSRecord *rec = (JSRecord *)p;
|
||||
uint32_t mask = (uint32_t)objhdr_cap56 (rec->mist_hdr);
|
||||
uint32_t j = 0;
|
||||
|
||||
for (i = 1; i <= mask; i++) {
|
||||
JSValue k = rec->slots[i].key;
|
||||
if (!rec_key_is_empty (k) && !rec_key_is_tomb (k)) {
|
||||
if (j < s->options.max_item_count) {
|
||||
js_print_comma (s, &comma_state);
|
||||
js_print_value (s, k);
|
||||
js_printf (s, ": ");
|
||||
js_print_value (s, rec->slots[i].val);
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
if (j > s->options.max_item_count)
|
||||
js_print_more_items (s, &comma_state, j - s->options.max_item_count);
|
||||
|
||||
if (!is_array) {
|
||||
if (comma_state != 2) { js_printf (s, " }"); }
|
||||
} else {
|
||||
js_printf (s, " ]");
|
||||
}
|
||||
}
|
||||
|
||||
static int js_print_stack_index (JSPrintValueState *s, JSRecord *p) {
|
||||
int i;
|
||||
for (i = 0; i < s->level; i++)
|
||||
if (s->print_stack[i] == p) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void js_print_value (JSPrintValueState *s, JSValue val) {
|
||||
uint32_t tag = JS_VALUE_GET_NORM_TAG (val);
|
||||
const char *str;
|
||||
@@ -6280,18 +6009,6 @@ static JSValue js_throw_type_error (JSContext *ctx, JSValue this_val, int argc,
|
||||
#define GLOBAL_VAR_OFFSET 0x40000000
|
||||
#define ARGUMENT_VAR_OFFSET 0x20000000
|
||||
|
||||
/* Access an Array's internal JSValue array if available */
|
||||
static BOOL js_get_fast_array (JSContext *ctx, JSValue obj, JSValue **arrpp, uint32_t *countp) {
|
||||
/* Fast path for intrinsic arrays */
|
||||
if (JS_IsArray (obj)) {
|
||||
JSArray *arr = JS_VALUE_GET_ARRAY (obj);
|
||||
*countp = arr->len;
|
||||
*arrpp = arr->values;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static __exception int JS_CopyDataProperties (JSContext *ctx, JSValue target, JSValue source, JSValue excluded, BOOL setprop) {
|
||||
JSValue keys, key, val;
|
||||
uint32_t i, key_count;
|
||||
@@ -6336,11 +6053,6 @@ exception:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* only valid inside C functions */
|
||||
static JSValue JS_GetActiveFunction (JSContext *ctx) {
|
||||
return ctx->rt->current_stack_frame->cur_func;
|
||||
}
|
||||
|
||||
static JSValue js_closure2 (JSContext *ctx, JSValue func_obj, JSFunctionBytecode *b, JSStackFrame *sf) {
|
||||
JSFunction *f;
|
||||
f = JS_VALUE_GET_FUNCTION (func_obj);
|
||||
@@ -6482,6 +6194,28 @@ static JSValue js_call_c_function (JSContext *ctx, JSValue func_obj, JSValue thi
|
||||
case JS_CFUNC_3:
|
||||
ret_val = func.f3 (ctx, this_obj, arg_buf[0], arg_buf[1], arg_buf[2]);
|
||||
break;
|
||||
case JS_CFUNC_4:
|
||||
ret_val = func.f4 (ctx, this_obj, arg_buf[0], arg_buf[1], arg_buf[2], arg_buf[3]);
|
||||
break;
|
||||
/* Pure functions (no this_val) */
|
||||
case JS_CFUNC_PURE:
|
||||
ret_val = func.pure (ctx, argc, arg_buf);
|
||||
break;
|
||||
case JS_CFUNC_PURE_0:
|
||||
ret_val = func.pure0 (ctx);
|
||||
break;
|
||||
case JS_CFUNC_PURE_1:
|
||||
ret_val = func.pure1 (ctx, arg_buf[0]);
|
||||
break;
|
||||
case JS_CFUNC_PURE_2:
|
||||
ret_val = func.pure2 (ctx, arg_buf[0], arg_buf[1]);
|
||||
break;
|
||||
case JS_CFUNC_PURE_3:
|
||||
ret_val = func.pure3 (ctx, arg_buf[0], arg_buf[1], arg_buf[2]);
|
||||
break;
|
||||
case JS_CFUNC_PURE_4:
|
||||
ret_val = func.pure4 (ctx, arg_buf[0], arg_buf[1], arg_buf[2], arg_buf[3]);
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
@@ -6531,7 +6265,7 @@ static JSValue JS_CallInternal (JSContext *caller_ctx, JSValue func_obj, JSValue
|
||||
JSStackFrame sf_s, *sf = &sf_s;
|
||||
const uint8_t *pc;
|
||||
int opcode, arg_allocated_size, i;
|
||||
JSValue *local_buf, *stack_buf, *var_buf, *arg_buf, *sp, ret_val, *pval;
|
||||
JSValue *stack_buf, *var_buf, *arg_buf, *sp, ret_val;
|
||||
size_t alloca_size;
|
||||
|
||||
#if !DIRECT_DISPATCH
|
||||
@@ -8280,9 +8014,6 @@ exception:
|
||||
}
|
||||
ret_val = JS_EXCEPTION;
|
||||
done:
|
||||
/* free the local variables and stack */
|
||||
for (pval = local_buf; pval < sp; pval++) {
|
||||
}
|
||||
rt->current_stack_frame = sf->prev_frame;
|
||||
|
||||
if (unlikely (caller_ctx->trace_hook)
|
||||
@@ -11432,24 +11163,6 @@ static __exception int js_parse_array_literal (JSParseState *s) {
|
||||
return js_parse_expect (s, ']');
|
||||
}
|
||||
|
||||
/* XXX: remove */
|
||||
static BOOL has_with_scope (JSFunctionDef *s, int scope_level) {
|
||||
/* check if scope chain contains a with statement */
|
||||
while (s) {
|
||||
int scope_idx = s->scopes[scope_level].first;
|
||||
while (scope_idx >= 0) {
|
||||
JSVarDef *vd = &s->vars[scope_idx];
|
||||
|
||||
if (js_key_equal_str (vd->var_name, "_with_")) return TRUE;
|
||||
scope_idx = vd->scope_next;
|
||||
}
|
||||
/* check parent scopes */
|
||||
scope_level = s->parent_scope_level;
|
||||
s = s->parent;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static __exception int get_lvalue (JSParseState *s, int *popcode, int *pscope, JSValue *pname, int *plabel, int *pdepth, BOOL keep, int tok) {
|
||||
JSFunctionDef *fd;
|
||||
int opcode, scope, label, depth;
|
||||
@@ -12949,47 +12662,6 @@ static BOOL is_label (JSParseState *s) {
|
||||
&& peek_token (s, FALSE) == ':');
|
||||
}
|
||||
|
||||
/* test if the current token is a let keyword. Use simplistic look-ahead
|
||||
* scanner */
|
||||
static int is_let (JSParseState *s, int decl_mask) {
|
||||
int res = FALSE;
|
||||
const uint8_t *last_token_ptr;
|
||||
|
||||
if (token_is_pseudo_keyword (s, JS_KEY_let)) {
|
||||
JSParsePos pos;
|
||||
js_parse_get_pos (s, &pos);
|
||||
for (;;) {
|
||||
last_token_ptr = s->token.ptr;
|
||||
if (next_token (s)) {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (s->token.val == '[') {
|
||||
/* let [ is a syntax restriction:
|
||||
it never introduces an ExpressionStatement */
|
||||
res = TRUE;
|
||||
break;
|
||||
}
|
||||
if (s->token.val == '{'
|
||||
|| (s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)
|
||||
|| s->token.val == TOK_YIELD || s->token.val == TOK_AWAIT) {
|
||||
/* Check for possible ASI if not scanning for Declaration */
|
||||
/* XXX: should also check that `{` introduces a BindingPattern,
|
||||
but Firefox does not and rejects eval("let=1;let\n{if(1)2;}") */
|
||||
if (!has_lf_in_range (last_token_ptr, s->token.ptr)
|
||||
|| (decl_mask & DECL_MASK_OTHER)) {
|
||||
res = TRUE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (js_parse_seek_token (s, &pos)) { res = -1; }
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* for-in and for-of loops are not supported */
|
||||
static __exception int js_parse_for_in_of (JSParseState *s, int label_name) {
|
||||
return js_parse_error (s, "'for in' and 'for of' loops are not supported");
|
||||
@@ -15097,18 +14769,6 @@ static __exception int resolve_variables (JSContext *ctx, JSFunctionDef *s) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
fail:
|
||||
/* continue the copy to keep the atom refcounts consistent */
|
||||
/* XXX: find a better solution ? */
|
||||
for (; pos < bc_len; pos = pos_next) {
|
||||
op = bc_buf[pos];
|
||||
len = opcode_info[op].size;
|
||||
pos_next = pos + len;
|
||||
dbuf_put (&bc_out, bc_buf + pos, len);
|
||||
}
|
||||
dbuf_free (&s->byte_code);
|
||||
s->byte_code = bc_out;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* the pc2line table gives a source position for each PC value */
|
||||
@@ -17061,7 +16721,6 @@ static JSValue __JS_EvalInternal (JSContext *ctx, JSValue this_obj, const char *
|
||||
|
||||
err = js_parse_program (s);
|
||||
if (err) {
|
||||
fail:
|
||||
free_token (s, &s->token);
|
||||
ctx->current_parse_fd = NULL; /* Clear GC root before freeing */
|
||||
js_free_function_def (ctx, fd);
|
||||
@@ -17102,19 +16761,6 @@ static JSValue JS_EvalInternal (JSContext *ctx, JSValue this_obj, const char *in
|
||||
return ret;
|
||||
}
|
||||
|
||||
static JSValue JS_EvalObject (JSContext *ctx, JSValue this_obj, JSValue val, int flags, int scope_idx) {
|
||||
JSValue ret;
|
||||
const char *str;
|
||||
size_t len;
|
||||
|
||||
if (!JS_IsText (val)) return val;
|
||||
str = JS_ToCStringLen (ctx, &len, val);
|
||||
if (!str) return JS_EXCEPTION;
|
||||
ret = JS_EvalInternal (ctx, this_obj, str, len, "<input>", flags, scope_idx);
|
||||
JS_FreeCString (ctx, str);
|
||||
return ret;
|
||||
}
|
||||
|
||||
JSValue JS_EvalThis (JSContext *ctx, JSValue this_obj, const char *input, size_t input_len, const char *filename, int eval_flags) {
|
||||
int eval_type = eval_flags & JS_EVAL_TYPE_MASK;
|
||||
JSValue ret;
|
||||
@@ -17446,9 +17092,6 @@ static int JS_WriteFunctionBytecode (BCWriterState *s, const uint8_t *bc_buf1, i
|
||||
|
||||
js_free (s->ctx, bc_buf);
|
||||
return 0;
|
||||
fail:
|
||||
js_free (s->ctx, bc_buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void JS_WriteString (BCWriterState *s, JSText *p) {
|
||||
@@ -17464,87 +17107,6 @@ static void JS_WriteString (BCWriterState *s, JSText *p) {
|
||||
|
||||
static int JS_WriteObjectRec (BCWriterState *s, JSValue obj);
|
||||
|
||||
static int JS_WriteFunctionTag (BCWriterState *s, JSValue obj) {
|
||||
JSFunctionBytecode *b = JS_VALUE_GET_PTR (obj);
|
||||
uint32_t flags;
|
||||
int idx, i;
|
||||
|
||||
bc_put_u8 (s, BC_TAG_FUNCTION_BYTECODE);
|
||||
flags = idx = 0;
|
||||
bc_set_flags (&flags, &idx, b->has_prototype, 1);
|
||||
bc_set_flags (&flags, &idx, b->has_simple_parameter_list, 1);
|
||||
bc_set_flags (&flags, &idx, b->func_kind, 2);
|
||||
bc_set_flags (&flags, &idx, b->has_debug, 1);
|
||||
bc_set_flags (&flags, &idx, b->is_direct_or_indirect_eval, 1);
|
||||
assert (idx <= 16);
|
||||
bc_put_u16 (s, flags);
|
||||
bc_put_u8 (s, b->js_mode);
|
||||
bc_put_key (s, b->func_name);
|
||||
|
||||
bc_put_leb128 (s, b->arg_count);
|
||||
bc_put_leb128 (s, b->var_count);
|
||||
bc_put_leb128 (s, b->defined_arg_count);
|
||||
bc_put_leb128 (s, b->stack_size);
|
||||
bc_put_leb128 (s, b->closure_var_count);
|
||||
bc_put_leb128 (s, b->cpool_count);
|
||||
bc_put_leb128 (s, b->byte_code_len);
|
||||
if (b->vardefs) {
|
||||
/* XXX: this field is redundant */
|
||||
bc_put_leb128 (s, b->arg_count + b->var_count);
|
||||
for (i = 0; i < b->arg_count + b->var_count; i++) {
|
||||
JSVarDef *vd = &b->vardefs[i];
|
||||
bc_put_key (s, vd->var_name);
|
||||
bc_put_leb128 (s, vd->scope_level);
|
||||
bc_put_leb128 (s, vd->scope_next + 1);
|
||||
flags = idx = 0;
|
||||
bc_set_flags (&flags, &idx, vd->var_kind, 4);
|
||||
bc_set_flags (&flags, &idx, vd->is_const, 1);
|
||||
bc_set_flags (&flags, &idx, vd->is_lexical, 1);
|
||||
bc_set_flags (&flags, &idx, vd->is_captured, 1);
|
||||
assert (idx <= 8);
|
||||
bc_put_u8 (s, flags);
|
||||
}
|
||||
} else {
|
||||
bc_put_leb128 (s, 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < b->closure_var_count; i++) {
|
||||
JSClosureVar *cv = &b->closure_var[i];
|
||||
bc_put_key (s, cv->var_name);
|
||||
bc_put_leb128 (s, cv->var_idx);
|
||||
flags = idx = 0;
|
||||
bc_set_flags (&flags, &idx, cv->is_local, 1);
|
||||
bc_set_flags (&flags, &idx, cv->is_arg, 1);
|
||||
bc_set_flags (&flags, &idx, cv->is_const, 1);
|
||||
bc_set_flags (&flags, &idx, cv->is_lexical, 1);
|
||||
bc_set_flags (&flags, &idx, cv->var_kind, 4);
|
||||
assert (idx <= 8);
|
||||
bc_put_u8 (s, flags);
|
||||
}
|
||||
|
||||
if (JS_WriteFunctionBytecode (s, b->byte_code_buf, b->byte_code_len))
|
||||
goto fail;
|
||||
|
||||
if (b->has_debug) {
|
||||
bc_put_key (s, b->debug.filename);
|
||||
bc_put_leb128 (s, b->debug.pc2line_len);
|
||||
dbuf_put (&s->dbuf, b->debug.pc2line_buf, b->debug.pc2line_len);
|
||||
if (b->debug.source) {
|
||||
bc_put_leb128 (s, b->debug.source_len);
|
||||
dbuf_put (&s->dbuf, (uint8_t *)b->debug.source, b->debug.source_len);
|
||||
} else {
|
||||
bc_put_leb128 (s, 0);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < b->cpool_count; i++) {
|
||||
if (JS_WriteObjectRec (s, b->cpool[i])) goto fail;
|
||||
}
|
||||
return 0;
|
||||
fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int JS_WriteObjectTag (BCWriterState *s, JSValue obj) {
|
||||
JSRecord *rec = (JSRecord *)JS_VALUE_GET_OBJ (obj);
|
||||
uint32_t mask = (uint32_t)objhdr_cap56 (rec->mist_hdr);
|
||||
@@ -17660,7 +17222,6 @@ static int JS_WriteObjectRec (BCWriterState *s, JSValue obj) {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
invalid_tag:
|
||||
JS_ThrowInternalError (s->ctx, "unsupported tag (%d)", tag);
|
||||
goto fail;
|
||||
}
|
||||
@@ -17904,10 +17465,7 @@ static JSText *JS_ReadString (BCReaderState *s) {
|
||||
uint32_t i;
|
||||
|
||||
if (bc_get_leb128 (s, &len)) return NULL;
|
||||
if (len > JS_STRING_LEN_MAX) {
|
||||
JS_ThrowInternalError (s->ctx, "string too long");
|
||||
return NULL;
|
||||
}
|
||||
/* len is uint32_t, JS_STRING_LEN_MAX is 56 bits, so this always fits */
|
||||
p = js_alloc_string (s->ctx, len);
|
||||
if (!p) {
|
||||
s->error_state = -1;
|
||||
@@ -18528,33 +18086,6 @@ static JSValue *build_arg_list (JSContext *ctx, uint32_t *plen, JSValue *parray_
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* magic value: 0 = normal apply, 2 = Reflect.apply */
|
||||
static JSValue js_function_apply (JSContext *ctx, JSValue this_val, int argc, JSValue *argv, int magic) {
|
||||
JSValue this_arg, array_arg;
|
||||
uint32_t len;
|
||||
JSValue *tab, ret;
|
||||
JSFunction *f;
|
||||
|
||||
if (check_function (ctx, this_val)) return JS_EXCEPTION;
|
||||
f = JS_VALUE_GET_FUNCTION (this_val);
|
||||
this_arg = argv[0];
|
||||
array_arg = argv[1];
|
||||
if (JS_VALUE_GET_TAG (array_arg) == JS_TAG_NULL && magic != 2) {
|
||||
return JS_Call (ctx, this_val, this_arg, 0, NULL);
|
||||
}
|
||||
/* Fast path: check arity before building arg list */
|
||||
if (JS_IsArray (array_arg)) {
|
||||
JSArray *arr = JS_VALUE_GET_ARRAY (array_arg);
|
||||
if (unlikely (arr->len > f->length))
|
||||
return JS_ThrowTypeError (ctx, "too many arguments");
|
||||
}
|
||||
tab = build_arg_list (ctx, &len, &argv[1]);
|
||||
if (!tab) return JS_EXCEPTION;
|
||||
ret = JS_Call (ctx, this_val, this_arg, len, (JSValue *)tab);
|
||||
free_arg_list (ctx, tab, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Error class */
|
||||
static JSValue js_error_constructor (JSContext *ctx, JSValue this_val, int argc, JSValue *argv, int magic) {
|
||||
JSValue obj, msg;
|
||||
@@ -18655,15 +18186,6 @@ static JSValue js_array_includes (JSContext *ctx, JSValue this_val, int argc, JS
|
||||
return JS_NewBool (ctx, TRUE);
|
||||
}
|
||||
|
||||
static int string_cmp (JSText *p1, JSText *p2, int x1, int x2, int len) {
|
||||
int i, c1, c2;
|
||||
for (i = 0; i < len; i++) {
|
||||
if ((c1 = string_get (p1, x1 + i)) != (c2 = string_get (p2, x2 + i)))
|
||||
return c1 - c2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return < 0 if exception or TRUE/FALSE */
|
||||
static int js_is_regexp (JSContext *ctx, JSValue obj);
|
||||
|
||||
@@ -19131,146 +18653,6 @@ fail:
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
/* delete portions of a string that match a given regex */
|
||||
static JSValue JS_RegExpDelete (JSContext *ctx, JSValue this_val, JSValue arg) {
|
||||
JSRegExp *re = js_get_regexp (ctx, this_val, TRUE);
|
||||
JSText *str;
|
||||
JSValue str_val, val;
|
||||
uint8_t *re_bytecode;
|
||||
int ret;
|
||||
uint8_t **capture, *str_buf;
|
||||
uint16_t *utf16_buf = NULL;
|
||||
int utf16_len = 0;
|
||||
int capture_count, shift, re_flags;
|
||||
int next_src_pos, start, end;
|
||||
int64_t last_index;
|
||||
JSText *b;
|
||||
|
||||
if (!re) return JS_EXCEPTION;
|
||||
|
||||
b = pretext_init (ctx, 0);
|
||||
if (!b) return JS_EXCEPTION;
|
||||
|
||||
capture = NULL;
|
||||
str_val = JS_ToString (ctx, arg);
|
||||
if (JS_IsException (str_val)) goto fail;
|
||||
str = JS_VALUE_GET_STRING (str_val);
|
||||
re_bytecode = (uint8_t *)re->bytecode->packed;
|
||||
re_flags = lre_get_flags (re_bytecode);
|
||||
if ((re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY)) == 0) {
|
||||
last_index = 0;
|
||||
} else {
|
||||
val = JS_GetPropertyStr (ctx, this_val, "lastIndex");
|
||||
if (JS_IsException (val) || JS_ToLength (ctx, &last_index, val))
|
||||
goto fail;
|
||||
}
|
||||
capture_count = lre_get_capture_count (re_bytecode);
|
||||
if (capture_count > 0) {
|
||||
capture = js_malloc (ctx, sizeof (capture[0]) * capture_count * 2);
|
||||
if (!capture) goto fail;
|
||||
}
|
||||
/* Convert UTF-32 string to UTF-16 for regex engine */
|
||||
utf16_buf = js_string_to_utf16 (ctx, str, &utf16_len);
|
||||
if (!utf16_buf) goto fail;
|
||||
shift = 1; /* UTF-16 mode */
|
||||
str_buf = (uint8_t *)utf16_buf;
|
||||
next_src_pos = 0;
|
||||
for (;;) {
|
||||
if (last_index > utf16_len) break;
|
||||
|
||||
ret = lre_exec (capture, re_bytecode, str_buf, last_index, utf16_len, shift, ctx);
|
||||
if (ret != 1) {
|
||||
if (ret >= 0) {
|
||||
if (ret == 2 || (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY))) {
|
||||
if (JS_SetPropertyStr (ctx, this_val, "lastIndex", JS_NewInt32 (ctx, 0))
|
||||
< 0)
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
if (ret == LRE_RET_TIMEOUT) {
|
||||
JS_ThrowInterrupted (ctx);
|
||||
} else {
|
||||
JS_ThrowInternalError (ctx, "out of memory in regexp execution");
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
}
|
||||
start = (capture[0] - str_buf) >> shift;
|
||||
end = (capture[1] - str_buf) >> shift;
|
||||
last_index = end;
|
||||
if (next_src_pos < start) {
|
||||
b = pretext_concat (ctx, b, str, next_src_pos, start);
|
||||
if (!b) goto fail;
|
||||
}
|
||||
next_src_pos = end;
|
||||
if (!(re_flags & LRE_FLAG_GLOBAL)) {
|
||||
if (JS_SetPropertyStr (ctx, this_val, "lastIndex", JS_NewInt32 (ctx, end))
|
||||
< 0)
|
||||
goto fail;
|
||||
break;
|
||||
}
|
||||
if (end == start) {
|
||||
/* Advance by one code unit or one code point if unicode mode */
|
||||
if (!(re_flags & LRE_FLAG_UNICODE) || (unsigned)end >= utf16_len) {
|
||||
end++;
|
||||
} else {
|
||||
/* Check for surrogate pair in UTF-16 buffer */
|
||||
uint16_t c = utf16_buf[end];
|
||||
end++;
|
||||
if (is_hi_surrogate (c) && end < utf16_len
|
||||
&& is_lo_surrogate (utf16_buf[end])) {
|
||||
end++;
|
||||
}
|
||||
}
|
||||
}
|
||||
last_index = end;
|
||||
}
|
||||
b = pretext_concat (ctx, b, str, next_src_pos, (uint32_t)JSText_len (str));
|
||||
if (!b) goto fail;
|
||||
js_free (ctx, capture);
|
||||
js_free (ctx, utf16_buf);
|
||||
return pretext_end (ctx, b);
|
||||
fail:
|
||||
js_free (ctx, capture);
|
||||
js_free (ctx, utf16_buf);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
static JSValue JS_RegExpExec (JSContext *ctx, JSValue r, JSValue s) {
|
||||
JSValue method, ret;
|
||||
|
||||
method = JS_GetProperty (ctx, r, JS_KEY_exec);
|
||||
if (JS_IsException (method)) return method;
|
||||
if (JS_IsFunction (method)) {
|
||||
ret = JS_Call (ctx, method, r, 1, &s);
|
||||
if (JS_IsException (ret)) return ret;
|
||||
if (!JS_IsObject (ret) && !JS_IsNull (ret)) {
|
||||
return JS_ThrowTypeError (
|
||||
ctx, "RegExp exec method must return an object or null");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return js_regexp_exec (ctx, r, 1, &s);
|
||||
}
|
||||
|
||||
static int js_is_standard_regexp (JSContext *ctx, JSValue rx) {
|
||||
JSValue val;
|
||||
int res;
|
||||
|
||||
val = JS_GetPropertyStr (ctx, rx, "constructor");
|
||||
if (JS_IsException (val)) return -1;
|
||||
// rx.constructor === RegExp
|
||||
res = js_strict_eq (ctx, val, ctx->regexp_ctor);
|
||||
if (res) {
|
||||
val = JS_GetProperty (ctx, rx, JS_KEY_exec);
|
||||
if (JS_IsException (val)) return -1;
|
||||
// rx.exec === RE_exec
|
||||
res = JS_IsCFunction (val, js_regexp_exec, 0);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_regexp_proto_funcs[] = {
|
||||
JS_CFUNC_DEF ("exec", 1, js_regexp_exec),
|
||||
JS_CFUNC_DEF ("compile", 2, js_regexp_compile),
|
||||
@@ -19753,7 +19135,6 @@ static int js_json_to_str (JSContext *ctx, JSONStringifyContext *jsc, JSValue ho
|
||||
JS_PopGCRef (ctx, &val_ref);
|
||||
return 0;
|
||||
}
|
||||
concat_primitive:
|
||||
switch (JS_VALUE_GET_NORM_TAG (val_ref.val)) {
|
||||
case JS_TAG_STRING_IMM:
|
||||
val_ref.val = JS_ToQuotedString (ctx, val_ref.val);
|
||||
@@ -25052,7 +24433,7 @@ void js_debug_info (JSContext *js, JSValue fn, js_debug *dbg) {
|
||||
dbg->closure_n = b->closure_var_count;
|
||||
dbg->param_n = b->arg_count;
|
||||
dbg->vararg = 1;
|
||||
dbg->source = b->debug.source;
|
||||
dbg->source = (const uint8_t *)b->debug.source;
|
||||
dbg->srclen = b->debug.source_len;
|
||||
dbg->line = 0; /* see below */
|
||||
return;
|
||||
|
||||
@@ -176,8 +176,6 @@ void JS_DeleteGCRef(JSContext *ctx, JSGCRef *ref);
|
||||
Value Extraction
|
||||
============================================================ */
|
||||
|
||||
#define JS_VALUE_GET_INT(v) ((int)(v) >> 1)
|
||||
|
||||
/* Get primary tag (low 2-3 bits) */
|
||||
static inline int
|
||||
JS_VALUE_GET_TAG (JSValue v) {
|
||||
@@ -811,7 +809,14 @@ typedef enum JSCFunctionEnum {
|
||||
JS_CFUNC_1, /* JSValue f(ctx, this_val, arg0) */
|
||||
JS_CFUNC_2, /* JSValue f(ctx, this_val, arg0, arg1) */
|
||||
JS_CFUNC_3, /* JSValue f(ctx, this_val, arg0, arg1, arg2) */
|
||||
JS_CFUNC_4
|
||||
JS_CFUNC_4,
|
||||
/* Pure functions (no this_val) - for global utility functions */
|
||||
JS_CFUNC_PURE, /* JSValue f(ctx, argc, argv) - generic pure */
|
||||
JS_CFUNC_PURE_0, /* JSValue f(ctx) */
|
||||
JS_CFUNC_PURE_1, /* JSValue f(ctx, arg0) */
|
||||
JS_CFUNC_PURE_2, /* JSValue f(ctx, arg0, arg1) */
|
||||
JS_CFUNC_PURE_3, /* JSValue f(ctx, arg0, arg1, arg2) */
|
||||
JS_CFUNC_PURE_4 /* JSValue f(ctx, arg0, arg1, arg2, arg3) */
|
||||
} JSCFunctionEnum;
|
||||
|
||||
/* Fixed-arity C function types for fast paths */
|
||||
@@ -827,6 +832,16 @@ typedef JSValue JSCFunction4 (JSContext *ctx, JSValue this_val,
|
||||
JSValue arg0, JSValue arg1,
|
||||
JSValue arg2, JSValue arg3);
|
||||
|
||||
/* Pure function types (no this_val) */
|
||||
typedef JSValue JSCFunctionPure (JSContext *ctx, int argc, JSValue *argv);
|
||||
typedef JSValue JSCFunctionPure0 (JSContext *ctx);
|
||||
typedef JSValue JSCFunctionPure1 (JSContext *ctx, JSValue arg0);
|
||||
typedef JSValue JSCFunctionPure2 (JSContext *ctx, JSValue arg0, JSValue arg1);
|
||||
typedef JSValue JSCFunctionPure3 (JSContext *ctx, JSValue arg0, JSValue arg1,
|
||||
JSValue arg2);
|
||||
typedef JSValue JSCFunctionPure4 (JSContext *ctx, JSValue arg0, JSValue arg1,
|
||||
JSValue arg2, JSValue arg3);
|
||||
|
||||
typedef union JSCFunctionType {
|
||||
JSCFunction *generic;
|
||||
JSValue (*generic_magic) (JSContext *ctx, JSValue this_val, int argc,
|
||||
@@ -839,6 +854,13 @@ typedef union JSCFunctionType {
|
||||
JSCFunction2 *f2;
|
||||
JSCFunction3 *f3;
|
||||
JSCFunction4 *f4;
|
||||
/* Pure function pointers */
|
||||
JSCFunctionPure *pure;
|
||||
JSCFunctionPure0 *pure0;
|
||||
JSCFunctionPure1 *pure1;
|
||||
JSCFunctionPure2 *pure2;
|
||||
JSCFunctionPure3 *pure3;
|
||||
JSCFunctionPure4 *pure4;
|
||||
} JSCFunctionType;
|
||||
|
||||
JSValue JS_NewCFunction2 (JSContext *ctx, JSCFunction *func, const char *name,
|
||||
@@ -955,6 +977,43 @@ typedef struct JSCFunctionListEntry {
|
||||
.u \
|
||||
= {.func = { 3, JS_CFUNC_3, { .f3 = func1 } } } \
|
||||
}
|
||||
/* Pure function (no this_val) macros */
|
||||
#define JS_CFUNC_PURE_DEF(name, length, func1) \
|
||||
{ \
|
||||
name, 0, JS_DEF_CFUNC, 0, \
|
||||
.u \
|
||||
= {.func = { length, JS_CFUNC_PURE, { .pure = func1 } } } \
|
||||
}
|
||||
#define JS_CFUNC_PURE0_DEF(name, func1) \
|
||||
{ \
|
||||
name, 0, JS_DEF_CFUNC, 0, \
|
||||
.u \
|
||||
= {.func = { 0, JS_CFUNC_PURE_0, { .pure0 = func1 } } } \
|
||||
}
|
||||
#define JS_CFUNC_PURE1_DEF(name, func1) \
|
||||
{ \
|
||||
name, 0, JS_DEF_CFUNC, 0, \
|
||||
.u \
|
||||
= {.func = { 1, JS_CFUNC_PURE_1, { .pure1 = func1 } } } \
|
||||
}
|
||||
#define JS_CFUNC_PURE2_DEF(name, func1) \
|
||||
{ \
|
||||
name, 0, JS_DEF_CFUNC, 0, \
|
||||
.u \
|
||||
= {.func = { 2, JS_CFUNC_PURE_2, { .pure2 = func1 } } } \
|
||||
}
|
||||
#define JS_CFUNC_PURE3_DEF(name, func1) \
|
||||
{ \
|
||||
name, 0, JS_DEF_CFUNC, 0, \
|
||||
.u \
|
||||
= {.func = { 3, JS_CFUNC_PURE_3, { .pure3 = func1 } } } \
|
||||
}
|
||||
#define JS_CFUNC_PURE4_DEF(name, func1) \
|
||||
{ \
|
||||
name, 0, JS_DEF_CFUNC, 0, \
|
||||
.u \
|
||||
= {.func = { 4, JS_CFUNC_PURE_4, { .pure4 = func1 } } } \
|
||||
}
|
||||
#define JS_ITERATOR_NEXT_DEF(name, length, func1, magic) \
|
||||
{ \
|
||||
name, 0, JS_DEF_CFUNC, magic, .u = { \
|
||||
|
||||
Reference in New Issue
Block a user