Mercurial > njs
changeset 1210:ba6f17a75b3a
Moving top-level objects to global object.
| author | Dmitry Volyntsev <xeioex@nginx.com> |
|---|---|
| date | Thu, 31 Oct 2019 18:17:31 +0300 |
| parents | 796870eab669 |
| children | c75a8fc6d534 |
| files | src/njs_builtin.c src/njs_generator.c src/njs_lexer.h src/njs_lexer_keyword.c src/njs_object_hash.h src/njs_parser_terminal.c src/njs_value.h src/test/njs_unit_test.c test/njs_expect_test.exp |
| diffstat | 9 files changed, 178 insertions(+), 104 deletions(-) [+] |
line wrap: on
line diff
--- a/src/njs_builtin.c Thu Oct 31 18:17:30 2019 +0300 +++ b/src/njs_builtin.c Thu Oct 31 18:17:31 2019 +0300 @@ -1042,8 +1042,58 @@ } +static njs_int_t +njs_top_level_object(njs_vm_t *vm, njs_object_prop_t *self, + njs_value_t *global, njs_value_t *setval, njs_value_t *retval) +{ + njs_int_t ret; + njs_object_t *object; + njs_object_prop_t *prop; + njs_lvlhsh_query_t lhq; + + if (njs_slow_path(setval != NULL)) { + *retval = *setval; + + } else { + njs_set_object(retval, &vm->shared->objects[self->value.data.magic16]); + + object = njs_object_value_copy(vm, retval); + if (njs_slow_path(object == NULL)) { + return NJS_ERROR; + } + } + + prop = njs_object_prop_alloc(vm, &self->name, retval, 1); + if (njs_slow_path(prop == NULL)) { + return NJS_ERROR; + } + + /* GC */ + + prop->value = *retval; + prop->enumerable = 0; + + lhq.value = prop; + njs_string_get(&self->name, &lhq.key); + lhq.key_hash = self->value.data.magic32; + lhq.replace = 1; + lhq.pool = vm->mem_pool; + lhq.proto = &njs_object_hash_proto; + + ret = njs_lvlhsh_insert(njs_object_hash(global), &lhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "lvlhsh insert/replace failed"); + return NJS_ERROR; + } + + return NJS_OK; +} + + static const njs_object_prop_t njs_global_this_object_properties[] = { + /* Global constants. */ + { .type = NJS_PROPERTY, .name = njs_string("NaN"), @@ -1062,6 +1112,8 @@ .value = njs_value(NJS_UNDEFINED, 0, NAN), }, + /* Global functions. */ + { .type = NJS_PROPERTY, .name = njs_string("isFinite"), @@ -1174,6 +1226,44 @@ .configurable = 1, }, + /* Global objects. */ + + { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("njs"), + .value = njs_prop_handler2(njs_top_level_object, NJS_OBJECT_NJS, + NJS_NJS_HASH), + .writable = 1, + .configurable = 1, + }, + + { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("process"), + .value = njs_prop_handler2(njs_top_level_object, NJS_OBJECT_PROCESS, + NJS_PROCESS_HASH), + .writable = 1, + .configurable = 1, + }, + + { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("Math"), + .value = njs_prop_handler2(njs_top_level_object, NJS_OBJECT_MATH, + NJS_MATH_HASH), + .writable = 1, + .configurable = 1, + }, + + { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("JSON"), + .value = njs_prop_handler2(njs_top_level_object, NJS_OBJECT_JSON, + NJS_JSON_HASH), + .writable = 1, + .configurable = 1, + }, + };
--- a/src/njs_generator.c Thu Oct 31 18:17:30 2019 +0300 +++ b/src/njs_generator.c Thu Oct 31 18:17:31 2019 +0300 @@ -59,8 +59,6 @@ size_t size); static njs_int_t njs_generate_name(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node); -static njs_int_t njs_generate_builtin_object(njs_vm_t *vm, - njs_generator_t *generator, njs_parser_node_t *node); static njs_int_t njs_generate_variable(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node, njs_reference_type_t type); static njs_int_t njs_generate_var_statement(njs_vm_t *vm, @@ -460,12 +458,6 @@ return NJS_OK; - case NJS_TOKEN_NJS: - case NJS_TOKEN_PROCESS: - case NJS_TOKEN_MATH: - case NJS_TOKEN_JSON: - return njs_generate_builtin_object(vm, generator, node); - case NJS_TOKEN_FUNCTION: return njs_generate_function_declaration(vm, generator, node); @@ -587,32 +579,6 @@ static njs_int_t -njs_generate_builtin_object(njs_vm_t *vm, njs_generator_t *generator, - njs_parser_node_t *node) -{ - njs_index_t index; - njs_vmcode_object_copy_t *copy; - - index = njs_variable_index(vm, node); - if (njs_slow_path(index == NJS_INDEX_NONE)) { - return NJS_ERROR; - } - - node->index = njs_generate_dest_index(vm, generator, node); - if (njs_slow_path(node->index == NJS_INDEX_ERROR)) { - return NJS_ERROR; - } - - njs_generate_code(generator, njs_vmcode_object_copy_t, copy, - NJS_VMCODE_OBJECT_COPY, 2); - copy->retval = node->index; - copy->object = index; - - return NJS_OK; -} - - -static njs_int_t njs_generate_variable(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node, njs_reference_type_t type) {
--- a/src/njs_lexer.h Thu Oct 31 18:17:30 2019 +0300 +++ b/src/njs_lexer.h Thu Oct 31 18:17:31 2019 +0300 @@ -166,18 +166,11 @@ NJS_TOKEN_THROW, NJS_TOKEN_THIS, + NJS_TOKEN_GLOBAL_OBJECT, NJS_TOKEN_NON_LOCAL_THIS, NJS_TOKEN_ARGUMENTS, NJS_TOKEN_EVAL, -#define NJS_TOKEN_FIRST_OBJECT NJS_TOKEN_GLOBAL_OBJECT - - NJS_TOKEN_GLOBAL_OBJECT, - NJS_TOKEN_NJS, - NJS_TOKEN_PROCESS, - NJS_TOKEN_MATH, - NJS_TOKEN_JSON, - NJS_TOKEN_OBJECT_CONSTRUCTOR, NJS_TOKEN_ARRAY_CONSTRUCTOR, NJS_TOKEN_BOOLEAN_CONSTRUCTOR,
--- a/src/njs_lexer_keyword.c Thu Oct 31 18:17:30 2019 +0300 +++ b/src/njs_lexer_keyword.c Thu Oct 31 18:17:31 2019 +0300 @@ -47,14 +47,6 @@ { njs_str("finally"), NJS_TOKEN_FINALLY, 0 }, { njs_str("throw"), NJS_TOKEN_THROW, 0 }, - /* Builtin objects. */ - - { njs_str("this"), NJS_TOKEN_THIS, 0 }, - { njs_str("njs"), NJS_TOKEN_NJS, 0 }, - { njs_str("process"), NJS_TOKEN_PROCESS, 0 }, - { njs_str("Math"), NJS_TOKEN_MATH, 0 }, - { njs_str("JSON"), NJS_TOKEN_JSON, 0 }, - /* Builtin functions. */ { njs_str("Object"), NJS_TOKEN_OBJECT_CONSTRUCTOR, 0 }, @@ -82,6 +74,7 @@ /* Reserved words. */ + { njs_str("this"), NJS_TOKEN_THIS, 0 }, { njs_str("arguments"), NJS_TOKEN_ARGUMENTS, 0 }, { njs_str("eval"), NJS_TOKEN_EVAL, 0 },
--- a/src/njs_object_hash.h Thu Oct 31 18:17:30 2019 +0300 +++ b/src/njs_object_hash.h Thu Oct 31 18:17:31 2019 +0300 @@ -146,6 +146,14 @@ 'j'), 'o'), 'i'), 'n') +#define NJS_JSON_HASH \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add(NJS_DJB_HASH_INIT, \ + 'J'), 'S'), 'O'), 'N') + + #define NJS_LENGTH_HASH \ njs_djb_hash_add( \ njs_djb_hash_add( \ @@ -164,6 +172,21 @@ 'n'), 'a'), 'm'), 'e') +#define NJS_NJS_HASH \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add(NJS_DJB_HASH_INIT, \ + 'n'), 'j'), 's') + + +#define NJS_MATH_HASH \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add(NJS_DJB_HASH_INIT, \ + 'M'), 'a'), 't'), 'h') + + #define NJS_MESSAGE_HASH \ njs_djb_hash_add( \ njs_djb_hash_add( \ @@ -202,6 +225,17 @@ 'p'), 'a'), 't'), 'h') +#define NJS_PROCESS_HASH \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add(NJS_DJB_HASH_INIT, \ + 'p'), 'r'), 'o'), 'c'), 'e'), 's'), 's') + + #define NJS_PROTOTYPE_HASH \ njs_djb_hash_add( \ njs_djb_hash_add( \
--- a/src/njs_parser_terminal.c Thu Oct 31 18:17:30 2019 +0300 +++ b/src/njs_parser_terminal.c Thu Oct 31 18:17:31 2019 +0300 @@ -11,9 +11,6 @@ static njs_parser_node_t *njs_parser_reference(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token, njs_str_t *name, uint32_t hash, uint32_t token_line); -static njs_int_t njs_parser_builtin(njs_vm_t *vm, njs_parser_t *parser, - njs_parser_node_t *node, njs_value_type_t type, njs_str_t *name, - uint32_t hash); static njs_token_t njs_parser_object(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *obj); static njs_int_t njs_parser_object_property(njs_vm_t *vm, njs_parser_t *parser, @@ -259,17 +256,6 @@ break; - case NJS_TOKEN_NJS: - case NJS_TOKEN_PROCESS: - case NJS_TOKEN_MATH: - case NJS_TOKEN_JSON: - ret = njs_parser_builtin(vm, parser, node, NJS_OBJECT, name, hash); - if (njs_slow_path(ret != NJS_OK)) { - return NULL; - } - - break; - case NJS_TOKEN_OBJECT_CONSTRUCTOR: node->index = NJS_INDEX_OBJECT; break; @@ -399,42 +385,6 @@ } -static njs_int_t -njs_parser_builtin(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node, - njs_value_type_t type, njs_str_t *name, uint32_t hash) -{ - njs_int_t ret; - njs_uint_t index; - njs_variable_t *var; - njs_parser_scope_t *scope; - - scope = njs_parser_global_scope(vm); - - var = njs_variable_add(vm, scope, name, hash, NJS_VARIABLE_VAR); - if (njs_slow_path(var == NULL)) { - return NJS_ERROR; - } - - /* TODO: once */ - switch (type) { - case NJS_OBJECT: - index = node->token - NJS_TOKEN_FIRST_OBJECT; - njs_set_object(&var->value, &vm->shared->objects[index]); - break; - - default: - return NJS_ERROR; - } - - ret = njs_variable_reference(vm, scope, node, name, hash, NJS_REFERENCE); - if (njs_slow_path(ret != NJS_OK)) { - return NJS_ERROR; - } - - return NJS_OK; -} - - static njs_token_t njs_parser_object(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *obj) {
--- a/src/njs_value.h Thu Oct 31 18:17:30 2019 +0300 +++ b/src/njs_value.h Thu Oct 31 18:17:31 2019 +0300 @@ -128,8 +128,8 @@ */ uint8_t truth; - uint16_t _spare1; - uint32_t _spare2; + uint16_t magic16; + uint32_t magic32; union { double number; @@ -409,6 +409,17 @@ } +#define njs_prop_handler2(_handler, _magic16, _magic32) { \ + .data = { \ + .type = NJS_INVALID, \ + .truth = 1, \ + .magic16 = _magic16, \ + .magic32 = _magic32, \ + .u = { .prop_handler = _handler } \ + } \ +} + + #define njs_is_null(value) \ ((value)->type == NJS_NULL)
--- a/src/test/njs_unit_test.c Thu Oct 31 18:17:30 2019 +0300 +++ b/src/test/njs_unit_test.c Thu Oct 31 18:17:31 2019 +0300 @@ -13227,6 +13227,43 @@ { njs_str("parseFloat('-5.7e+abc')"), njs_str("-5.7") }, + /* Top-level objects. */ + + { njs_str("var global = this;" + "function isMutableObject(v) {" + " var d = Object.getOwnPropertyDescriptor(global, v);" + " return d.writable && !d.enumerable && d.configurable;" + "};" + "['njs', 'process', 'Math', 'JSON'].every((v)=>isMutableObject(v))"), + njs_str("true") }, + + { njs_str("njs === njs"), + njs_str("true") }, + + { njs_str("this.njs = 1; njs"), + njs_str("1") }, + + { njs_str("process === process"), + njs_str("true") }, + + { njs_str("this.process = 1; process"), + njs_str("1") }, + + { njs_str("Math === Math"), + njs_str("true") }, + + { njs_str("this.Math = 1; Math"), + njs_str("1") }, + + { njs_str("JSON === JSON"), + njs_str("true") }, + + { njs_str("this.JSON = 1; JSON"), + njs_str("1") }, + + { njs_str("delete this.JSON; JSON"), + njs_str("ReferenceError: \"JSON\" is not defined in 1") }, + /* JSON.parse() */ { njs_str("JSON.parse('null')"),
