mirror of
https://github.com/bellard/quickjs.git
synced 2024-11-22 05:38:11 +08:00
added 'in' operator for private fields
This commit is contained in:
parent
16057644f3
commit
3ab1c2b314
2
TODO
2
TODO
@ -63,5 +63,5 @@ Optimization ideas:
|
|||||||
Test262o: 0/11262 errors, 463 excluded
|
Test262o: 0/11262 errors, 463 excluded
|
||||||
Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
|
Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
|
||||||
|
|
||||||
Result: 16/76909 errors, 1497 excluded, 8136 skipped
|
Result: 18/76947 errors, 1497 excluded, 8117 skipped
|
||||||
Test262 commit: 6cbb6da9473c56d95358d8e679c5a6d2b4574efb
|
Test262 commit: 6cbb6da9473c56d95358d8e679c5a6d2b4574efb
|
||||||
|
@ -256,6 +256,7 @@ DEF( and, 1, 2, 1, none)
|
|||||||
DEF( xor, 1, 2, 1, none)
|
DEF( xor, 1, 2, 1, none)
|
||||||
DEF( or, 1, 2, 1, none)
|
DEF( or, 1, 2, 1, none)
|
||||||
DEF(is_undefined_or_null, 1, 1, 1, none)
|
DEF(is_undefined_or_null, 1, 1, 1, none)
|
||||||
|
DEF( private_in, 1, 2, 1, none)
|
||||||
#ifdef CONFIG_BIGNUM
|
#ifdef CONFIG_BIGNUM
|
||||||
DEF( mul_pow10, 1, 2, 1, none)
|
DEF( mul_pow10, 1, 2, 1, none)
|
||||||
DEF( math_mod, 1, 2, 1, none)
|
DEF( math_mod, 1, 2, 1, none)
|
||||||
@ -280,7 +281,7 @@ def(scope_put_var_init, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in pha
|
|||||||
def(scope_get_private_field, 7, 1, 1, atom_u16) /* obj -> value, emitted in phase 1, removed in phase 2 */
|
def(scope_get_private_field, 7, 1, 1, atom_u16) /* obj -> value, emitted in phase 1, removed in phase 2 */
|
||||||
def(scope_get_private_field2, 7, 1, 2, atom_u16) /* obj -> obj value, emitted in phase 1, removed in phase 2 */
|
def(scope_get_private_field2, 7, 1, 2, atom_u16) /* obj -> obj value, emitted in phase 1, removed in phase 2 */
|
||||||
def(scope_put_private_field, 7, 2, 0, atom_u16) /* obj value ->, emitted in phase 1, removed in phase 2 */
|
def(scope_put_private_field, 7, 2, 0, atom_u16) /* obj value ->, emitted in phase 1, removed in phase 2 */
|
||||||
|
def(scope_in_private_field, 7, 1, 1, atom_u16) /* obj -> res emitted in phase 1, removed in phase 2 */
|
||||||
def( set_class_name, 5, 1, 1, u32) /* emitted in phase 1, removed in phase 2 */
|
def( set_class_name, 5, 1, 1, u32) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
|
||||||
def( line_num, 5, 0, 0, u32) /* emitted in phase 1, removed in phase 3 */
|
def( line_num, 5, 0, 0, u32) /* emitted in phase 1, removed in phase 3 */
|
||||||
|
234
quickjs.c
234
quickjs.c
@ -7351,6 +7351,8 @@ static int JS_SetPrivateField(JSContext *ctx, JSValueConst obj,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* add a private brand field to 'home_obj' if not already present and
|
||||||
|
if obj is != null add a private brand to it */
|
||||||
static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj)
|
static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj)
|
||||||
{
|
{
|
||||||
JSObject *p, *p1;
|
JSObject *p, *p1;
|
||||||
@ -7366,10 +7368,10 @@ static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj)
|
|||||||
p = JS_VALUE_GET_OBJ(home_obj);
|
p = JS_VALUE_GET_OBJ(home_obj);
|
||||||
prs = find_own_property(&pr, p, JS_ATOM_Private_brand);
|
prs = find_own_property(&pr, p, JS_ATOM_Private_brand);
|
||||||
if (!prs) {
|
if (!prs) {
|
||||||
|
/* if the brand is not present, add it */
|
||||||
brand = JS_NewSymbolFromAtom(ctx, JS_ATOM_brand, JS_ATOM_TYPE_PRIVATE);
|
brand = JS_NewSymbolFromAtom(ctx, JS_ATOM_brand, JS_ATOM_TYPE_PRIVATE);
|
||||||
if (JS_IsException(brand))
|
if (JS_IsException(brand))
|
||||||
return -1;
|
return -1;
|
||||||
/* if the brand is not present, add it */
|
|
||||||
pr = add_property(ctx, p, JS_ATOM_Private_brand, JS_PROP_C_W_E);
|
pr = add_property(ctx, p, JS_ATOM_Private_brand, JS_PROP_C_W_E);
|
||||||
if (!pr) {
|
if (!pr) {
|
||||||
JS_FreeValue(ctx, brand);
|
JS_FreeValue(ctx, brand);
|
||||||
@ -7381,26 +7383,27 @@ static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj)
|
|||||||
}
|
}
|
||||||
brand_atom = js_symbol_to_atom(ctx, brand);
|
brand_atom = js_symbol_to_atom(ctx, brand);
|
||||||
|
|
||||||
if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) {
|
if (JS_IsObject(obj)) {
|
||||||
JS_ThrowTypeErrorNotAnObject(ctx);
|
p1 = JS_VALUE_GET_OBJ(obj);
|
||||||
|
prs = find_own_property(&pr, p1, brand_atom);
|
||||||
|
if (unlikely(prs)) {
|
||||||
|
JS_FreeAtom(ctx, brand_atom);
|
||||||
|
JS_ThrowTypeError(ctx, "private method is already present");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pr = add_property(ctx, p1, brand_atom, JS_PROP_C_W_E);
|
||||||
JS_FreeAtom(ctx, brand_atom);
|
JS_FreeAtom(ctx, brand_atom);
|
||||||
return -1;
|
if (!pr)
|
||||||
}
|
return -1;
|
||||||
p1 = JS_VALUE_GET_OBJ(obj);
|
pr->u.value = JS_UNDEFINED;
|
||||||
prs = find_own_property(&pr, p1, brand_atom);
|
} else {
|
||||||
if (unlikely(prs)) {
|
|
||||||
JS_FreeAtom(ctx, brand_atom);
|
JS_FreeAtom(ctx, brand_atom);
|
||||||
JS_ThrowTypeError(ctx, "private method is already present");
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
pr = add_property(ctx, p1, brand_atom, JS_PROP_C_W_E);
|
|
||||||
JS_FreeAtom(ctx, brand_atom);
|
|
||||||
if (!pr)
|
|
||||||
return -1;
|
|
||||||
pr->u.value = JS_UNDEFINED;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* return a boolean telling if the brand of the home object of 'func'
|
||||||
|
is present on 'obj' or -1 in case of exception */
|
||||||
static int JS_CheckBrand(JSContext *ctx, JSValueConst obj, JSValueConst func)
|
static int JS_CheckBrand(JSContext *ctx, JSValueConst obj, JSValueConst func)
|
||||||
{
|
{
|
||||||
JSObject *p, *p1, *home_obj;
|
JSObject *p, *p1, *home_obj;
|
||||||
@ -7409,11 +7412,8 @@ static int JS_CheckBrand(JSContext *ctx, JSValueConst obj, JSValueConst func)
|
|||||||
JSValueConst brand;
|
JSValueConst brand;
|
||||||
|
|
||||||
/* get the home object of 'func' */
|
/* get the home object of 'func' */
|
||||||
if (unlikely(JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT)) {
|
if (unlikely(JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT))
|
||||||
not_obj:
|
goto not_obj;
|
||||||
JS_ThrowTypeErrorNotAnObject(ctx);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
p1 = JS_VALUE_GET_OBJ(func);
|
p1 = JS_VALUE_GET_OBJ(func);
|
||||||
if (!js_class_has_bytecode(p1->class_id))
|
if (!js_class_has_bytecode(p1->class_id))
|
||||||
goto not_obj;
|
goto not_obj;
|
||||||
@ -7431,15 +7431,14 @@ static int JS_CheckBrand(JSContext *ctx, JSValueConst obj, JSValueConst func)
|
|||||||
goto not_obj;
|
goto not_obj;
|
||||||
|
|
||||||
/* get the brand array of 'obj' */
|
/* get the brand array of 'obj' */
|
||||||
if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT))
|
if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) {
|
||||||
goto not_obj;
|
not_obj:
|
||||||
p = JS_VALUE_GET_OBJ(obj);
|
JS_ThrowTypeErrorNotAnObject(ctx);
|
||||||
prs = find_own_property(&pr, p, js_symbol_to_atom(ctx, (JSValue)brand));
|
|
||||||
if (!prs) {
|
|
||||||
JS_ThrowTypeError(ctx, "invalid brand on object");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
p = JS_VALUE_GET_OBJ(obj);
|
||||||
|
prs = find_own_property(&pr, p, js_symbol_to_atom(ctx, (JSValue)brand));
|
||||||
|
return (prs != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t js_string_obj_get_length(JSContext *ctx,
|
static uint32_t js_string_obj_get_length(JSContext *ctx,
|
||||||
@ -14498,6 +14497,43 @@ static __exception int js_operator_in(JSContext *ctx, JSValue *sp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static __exception int js_operator_private_in(JSContext *ctx, JSValue *sp)
|
||||||
|
{
|
||||||
|
JSValue op1, op2;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
op1 = sp[-2]; /* object */
|
||||||
|
op2 = sp[-1]; /* field name or method function */
|
||||||
|
|
||||||
|
if (JS_VALUE_GET_TAG(op1) != JS_TAG_OBJECT) {
|
||||||
|
JS_ThrowTypeError(ctx, "invalid 'in' operand");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (JS_IsObject(op2)) {
|
||||||
|
/* method: use the brand */
|
||||||
|
ret = JS_CheckBrand(ctx, op1, op2);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
JSAtom atom;
|
||||||
|
JSObject *p;
|
||||||
|
JSShapeProperty *prs;
|
||||||
|
JSProperty *pr;
|
||||||
|
/* field */
|
||||||
|
atom = JS_ValueToAtom(ctx, op2);
|
||||||
|
if (unlikely(atom == JS_ATOM_NULL))
|
||||||
|
return -1;
|
||||||
|
p = JS_VALUE_GET_OBJ(op1);
|
||||||
|
prs = find_own_property(&pr, p, atom);
|
||||||
|
JS_FreeAtom(ctx, atom);
|
||||||
|
ret = (prs != NULL);
|
||||||
|
}
|
||||||
|
JS_FreeValue(ctx, op1);
|
||||||
|
JS_FreeValue(ctx, op2);
|
||||||
|
sp[-2] = JS_NewBool(ctx, ret);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static __exception int js_has_unscopable(JSContext *ctx, JSValueConst obj,
|
static __exception int js_has_unscopable(JSContext *ctx, JSValueConst obj,
|
||||||
JSAtom atom)
|
JSAtom atom)
|
||||||
{
|
{
|
||||||
@ -16500,8 +16536,15 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
|||||||
}
|
}
|
||||||
BREAK;
|
BREAK;
|
||||||
CASE(OP_check_brand):
|
CASE(OP_check_brand):
|
||||||
if (JS_CheckBrand(ctx, sp[-2], sp[-1]) < 0)
|
{
|
||||||
goto exception;
|
int ret = JS_CheckBrand(ctx, sp[-2], sp[-1]);
|
||||||
|
if (ret < 0)
|
||||||
|
goto exception;
|
||||||
|
if (!ret) {
|
||||||
|
JS_ThrowTypeError(ctx, "invalid brand on object");
|
||||||
|
goto exception;
|
||||||
|
}
|
||||||
|
}
|
||||||
BREAK;
|
BREAK;
|
||||||
CASE(OP_add_brand):
|
CASE(OP_add_brand):
|
||||||
if (JS_AddBrand(ctx, sp[-2], sp[-1]) < 0)
|
if (JS_AddBrand(ctx, sp[-2], sp[-1]) < 0)
|
||||||
@ -18156,6 +18199,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
|||||||
goto exception;
|
goto exception;
|
||||||
sp--;
|
sp--;
|
||||||
BREAK;
|
BREAK;
|
||||||
|
CASE(OP_private_in):
|
||||||
|
if (js_operator_private_in(ctx, sp))
|
||||||
|
goto exception;
|
||||||
|
sp--;
|
||||||
|
BREAK;
|
||||||
CASE(OP_instanceof):
|
CASE(OP_instanceof):
|
||||||
if (js_operator_instanceof(ctx, sp))
|
if (js_operator_instanceof(ctx, sp))
|
||||||
goto exception;
|
goto exception;
|
||||||
@ -22642,8 +22690,9 @@ static JSAtom get_private_setter_name(JSContext *ctx, JSAtom name)
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
JSFunctionDef *fields_init_fd;
|
JSFunctionDef *fields_init_fd;
|
||||||
int computed_fields_count;
|
int computed_fields_count;
|
||||||
BOOL has_brand;
|
BOOL need_brand;
|
||||||
int brand_push_pos;
|
int brand_push_pos;
|
||||||
|
BOOL is_static;
|
||||||
} ClassFieldsDef;
|
} ClassFieldsDef;
|
||||||
|
|
||||||
static __exception int emit_class_init_start(JSParseState *s,
|
static __exception int emit_class_init_start(JSParseState *s,
|
||||||
@ -22657,48 +22706,34 @@ static __exception int emit_class_init_start(JSParseState *s,
|
|||||||
|
|
||||||
s->cur_func = cf->fields_init_fd;
|
s->cur_func = cf->fields_init_fd;
|
||||||
|
|
||||||
/* XXX: would be better to add the code only if needed, maybe in a
|
if (!cf->is_static) {
|
||||||
later pass */
|
/* add the brand to the newly created instance */
|
||||||
emit_op(s, OP_push_false); /* will be patched later */
|
/* XXX: would be better to add the code only if needed, maybe in a
|
||||||
cf->brand_push_pos = cf->fields_init_fd->last_opcode_pos;
|
later pass */
|
||||||
label_add_brand = emit_goto(s, OP_if_false, -1);
|
emit_op(s, OP_push_false); /* will be patched later */
|
||||||
|
cf->brand_push_pos = cf->fields_init_fd->last_opcode_pos;
|
||||||
emit_op(s, OP_scope_get_var);
|
label_add_brand = emit_goto(s, OP_if_false, -1);
|
||||||
emit_atom(s, JS_ATOM_this);
|
|
||||||
emit_u16(s, 0);
|
|
||||||
|
|
||||||
emit_op(s, OP_scope_get_var);
|
|
||||||
emit_atom(s, JS_ATOM_home_object);
|
|
||||||
emit_u16(s, 0);
|
|
||||||
|
|
||||||
emit_op(s, OP_add_brand);
|
|
||||||
|
|
||||||
emit_label(s, label_add_brand);
|
|
||||||
|
|
||||||
s->cur_func = s->cur_func->parent;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __exception int add_brand(JSParseState *s, ClassFieldsDef *cf)
|
|
||||||
{
|
|
||||||
if (!cf->has_brand) {
|
|
||||||
/* define the brand field in 'this' of the initializer */
|
|
||||||
if (!cf->fields_init_fd) {
|
|
||||||
if (emit_class_init_start(s, cf))
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
/* patch the start of the function to enable the OP_add_brand code */
|
|
||||||
cf->fields_init_fd->byte_code.buf[cf->brand_push_pos] = OP_push_true;
|
|
||||||
|
|
||||||
cf->has_brand = TRUE;
|
emit_op(s, OP_scope_get_var);
|
||||||
|
emit_atom(s, JS_ATOM_this);
|
||||||
|
emit_u16(s, 0);
|
||||||
|
|
||||||
|
emit_op(s, OP_scope_get_var);
|
||||||
|
emit_atom(s, JS_ATOM_home_object);
|
||||||
|
emit_u16(s, 0);
|
||||||
|
|
||||||
|
emit_op(s, OP_add_brand);
|
||||||
|
|
||||||
|
emit_label(s, label_add_brand);
|
||||||
}
|
}
|
||||||
|
s->cur_func = s->cur_func->parent;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_class_init_end(JSParseState *s, ClassFieldsDef *cf)
|
static void emit_class_init_end(JSParseState *s, ClassFieldsDef *cf)
|
||||||
{
|
{
|
||||||
int cpool_idx;
|
int cpool_idx;
|
||||||
|
|
||||||
s->cur_func = cf->fields_init_fd;
|
s->cur_func = cf->fields_init_fd;
|
||||||
emit_op(s, OP_return_undef);
|
emit_op(s, OP_return_undef);
|
||||||
s->cur_func = s->cur_func->parent;
|
s->cur_func = s->cur_func->parent;
|
||||||
@ -22725,7 +22760,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
|
|||||||
const uint8_t *class_start_ptr = s->token.ptr;
|
const uint8_t *class_start_ptr = s->token.ptr;
|
||||||
const uint8_t *start_ptr;
|
const uint8_t *start_ptr;
|
||||||
ClassFieldsDef class_fields[2];
|
ClassFieldsDef class_fields[2];
|
||||||
|
|
||||||
/* classes are parsed and executed in strict mode */
|
/* classes are parsed and executed in strict mode */
|
||||||
saved_js_mode = fd->js_mode;
|
saved_js_mode = fd->js_mode;
|
||||||
fd->js_mode |= JS_MODE_STRICT;
|
fd->js_mode |= JS_MODE_STRICT;
|
||||||
@ -22798,7 +22833,8 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
|
|||||||
ClassFieldsDef *cf = &class_fields[i];
|
ClassFieldsDef *cf = &class_fields[i];
|
||||||
cf->fields_init_fd = NULL;
|
cf->fields_init_fd = NULL;
|
||||||
cf->computed_fields_count = 0;
|
cf->computed_fields_count = 0;
|
||||||
cf->has_brand = FALSE;
|
cf->need_brand = FALSE;
|
||||||
|
cf->is_static = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctor_fd = NULL;
|
ctor_fd = NULL;
|
||||||
@ -22905,8 +22941,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
|
|||||||
JS_VAR_PRIVATE_GETTER + is_set, is_static) < 0)
|
JS_VAR_PRIVATE_GETTER + is_set, is_static) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (add_brand(s, &class_fields[is_static]) < 0)
|
class_fields[is_static].need_brand = TRUE;
|
||||||
goto fail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (js_parse_function_decl2(s, JS_PARSE_FUNC_GETTER + is_set,
|
if (js_parse_function_decl2(s, JS_PARSE_FUNC_GETTER + is_set,
|
||||||
@ -23053,8 +23088,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
|
|||||||
func_type = JS_PARSE_FUNC_CLASS_CONSTRUCTOR;
|
func_type = JS_PARSE_FUNC_CLASS_CONSTRUCTOR;
|
||||||
}
|
}
|
||||||
if (is_private) {
|
if (is_private) {
|
||||||
if (add_brand(s, &class_fields[is_static]) < 0)
|
class_fields[is_static].need_brand = TRUE;
|
||||||
goto fail;
|
|
||||||
}
|
}
|
||||||
if (js_parse_function_decl2(s, func_type, func_kind, JS_ATOM_NULL, start_ptr, s->token.line_num, JS_PARSE_EXPORT_NONE, &method_fd))
|
if (js_parse_function_decl2(s, func_type, func_kind, JS_ATOM_NULL, start_ptr, s->token.line_num, JS_PARSE_EXPORT_NONE, &method_fd))
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -23120,12 +23154,29 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
|
|||||||
if (next_token(s))
|
if (next_token(s))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* store the function to initialize the fields to that it can be
|
|
||||||
referenced by the constructor */
|
|
||||||
{
|
{
|
||||||
ClassFieldsDef *cf = &class_fields[0];
|
ClassFieldsDef *cf = &class_fields[0];
|
||||||
int var_idx;
|
int var_idx;
|
||||||
|
|
||||||
|
if (cf->need_brand) {
|
||||||
|
/* add a private brand to the prototype */
|
||||||
|
emit_op(s, OP_dup);
|
||||||
|
emit_op(s, OP_null);
|
||||||
|
emit_op(s, OP_swap);
|
||||||
|
emit_op(s, OP_add_brand);
|
||||||
|
|
||||||
|
/* define the brand field in 'this' of the initializer */
|
||||||
|
if (!cf->fields_init_fd) {
|
||||||
|
if (emit_class_init_start(s, cf))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
/* patch the start of the function to enable the
|
||||||
|
OP_add_brand_instance code */
|
||||||
|
cf->fields_init_fd->byte_code.buf[cf->brand_push_pos] = OP_push_true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* store the function to initialize the fields to that it can be
|
||||||
|
referenced by the constructor */
|
||||||
var_idx = define_var(s, fd, JS_ATOM_class_fields_init,
|
var_idx = define_var(s, fd, JS_ATOM_class_fields_init,
|
||||||
JS_VAR_DEF_CONST);
|
JS_VAR_DEF_CONST);
|
||||||
if (var_idx < 0)
|
if (var_idx < 0)
|
||||||
@ -23143,6 +23194,13 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
|
|||||||
/* drop the prototype */
|
/* drop the prototype */
|
||||||
emit_op(s, OP_drop);
|
emit_op(s, OP_drop);
|
||||||
|
|
||||||
|
if (class_fields[1].need_brand) {
|
||||||
|
/* add a private brand to the class */
|
||||||
|
emit_op(s, OP_dup);
|
||||||
|
emit_op(s, OP_dup);
|
||||||
|
emit_op(s, OP_add_brand);
|
||||||
|
}
|
||||||
|
|
||||||
/* initialize the static fields */
|
/* initialize the static fields */
|
||||||
if (class_fields[1].fields_init_fd != NULL) {
|
if (class_fields[1].fields_init_fd != NULL) {
|
||||||
ClassFieldsDef *cf = &class_fields[1];
|
ClassFieldsDef *cf = &class_fields[1];
|
||||||
@ -25013,9 +25071,32 @@ static __exception int js_parse_expr_binary(JSParseState *s, int level,
|
|||||||
if (level == 0) {
|
if (level == 0) {
|
||||||
return js_parse_unary(s, (parse_flags & PF_ARROW_FUNC) |
|
return js_parse_unary(s, (parse_flags & PF_ARROW_FUNC) |
|
||||||
PF_POW_ALLOWED);
|
PF_POW_ALLOWED);
|
||||||
|
} else if (s->token.val == TOK_PRIVATE_NAME &&
|
||||||
|
(parse_flags & PF_IN_ACCEPTED) && level == 4 &&
|
||||||
|
peek_token(s, FALSE) == TOK_IN) {
|
||||||
|
JSAtom atom;
|
||||||
|
|
||||||
|
atom = JS_DupAtom(s->ctx, s->token.u.ident.atom);
|
||||||
|
if (next_token(s))
|
||||||
|
goto fail_private_in;
|
||||||
|
if (s->token.val != TOK_IN)
|
||||||
|
goto fail_private_in;
|
||||||
|
if (next_token(s))
|
||||||
|
goto fail_private_in;
|
||||||
|
if (js_parse_expr_binary(s, level - 1, parse_flags & ~PF_ARROW_FUNC)) {
|
||||||
|
fail_private_in:
|
||||||
|
JS_FreeAtom(s->ctx, atom);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
emit_op(s, OP_scope_in_private_field);
|
||||||
|
emit_atom(s, atom);
|
||||||
|
emit_u16(s, s->cur_func->scope_level);
|
||||||
|
JS_FreeAtom(s->ctx, atom);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
if (js_parse_expr_binary(s, level - 1, parse_flags))
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
if (js_parse_expr_binary(s, level - 1, parse_flags))
|
|
||||||
return -1;
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
op = s->token.val;
|
op = s->token.val;
|
||||||
switch(level) {
|
switch(level) {
|
||||||
@ -30507,6 +30588,10 @@ static int resolve_scope_private_field(JSContext *ctx, JSFunctionDef *s,
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case OP_scope_in_private_field:
|
||||||
|
get_loc_or_ref(bc, is_ref, idx);
|
||||||
|
dbuf_putc(bc, OP_private_in);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
@ -31213,6 +31298,7 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
|
|||||||
case OP_scope_get_private_field:
|
case OP_scope_get_private_field:
|
||||||
case OP_scope_get_private_field2:
|
case OP_scope_get_private_field2:
|
||||||
case OP_scope_put_private_field:
|
case OP_scope_put_private_field:
|
||||||
|
case OP_scope_in_private_field:
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
var_name = get_u32(bc_buf + pos + 1);
|
var_name = get_u32(bc_buf + pos + 1);
|
||||||
|
@ -76,7 +76,7 @@ caller
|
|||||||
change-array-by-copy
|
change-array-by-copy
|
||||||
class
|
class
|
||||||
class-fields-private
|
class-fields-private
|
||||||
class-fields-private-in=skip
|
class-fields-private-in
|
||||||
class-fields-public
|
class-fields-public
|
||||||
class-methods-private
|
class-methods-private
|
||||||
class-static-block
|
class-static-block
|
||||||
|
@ -11,6 +11,8 @@ test262/test/language/expressions/assignment/target-member-computed-reference-un
|
|||||||
test262/test/language/expressions/assignment/target-member-computed-reference-undefined.js:32: strict mode: Test262Error: Expected a DummyError but got a TypeError
|
test262/test/language/expressions/assignment/target-member-computed-reference-undefined.js:32: strict mode: Test262Error: Expected a DummyError but got a TypeError
|
||||||
test262/test/language/expressions/dynamic-import/usage-from-eval.js:26: TypeError: $DONE() not called
|
test262/test/language/expressions/dynamic-import/usage-from-eval.js:26: TypeError: $DONE() not called
|
||||||
test262/test/language/expressions/dynamic-import/usage-from-eval.js:26: strict mode: TypeError: $DONE() not called
|
test262/test/language/expressions/dynamic-import/usage-from-eval.js:26: strict mode: TypeError: $DONE() not called
|
||||||
|
test262/test/language/expressions/in/private-field-invalid-assignment-target.js:23: unexpected error type: Test262: This statement should not be evaluated.
|
||||||
|
test262/test/language/expressions/in/private-field-invalid-assignment-target.js:23: strict mode: unexpected error type: Test262: This statement should not be evaluated.
|
||||||
test262/test/language/expressions/optional-chaining/optional-call-preserves-this.js:21: TypeError: cannot read property 'c' of undefined
|
test262/test/language/expressions/optional-chaining/optional-call-preserves-this.js:21: TypeError: cannot read property 'c' of undefined
|
||||||
test262/test/language/expressions/optional-chaining/optional-call-preserves-this.js:15: strict mode: TypeError: cannot read property '_b' of undefined
|
test262/test/language/expressions/optional-chaining/optional-call-preserves-this.js:15: strict mode: TypeError: cannot read property '_b' of undefined
|
||||||
test262/test/language/global-code/script-decl-lex-var-declared-via-eval-sloppy.js:13: Test262Error: variable Expected a SyntaxError to be thrown but no exception was thrown at all
|
test262/test/language/global-code/script-decl-lex-var-declared-via-eval-sloppy.js:13: Test262Error: variable Expected a SyntaxError to be thrown but no exception was thrown at all
|
||||||
|
Loading…
Reference in New Issue
Block a user