From: Dmitry Volyntsev Date: Thu, 9 Jul 2020 13:57:10 +0000 (+0000) Subject: Fixed SetFunctionName() with Symbol keys. X-Git-Tag: 0.4.3~25 X-Git-Url: http://git.kaiwu.me/postgresql/log/contrib/postgres_fdw/%7B@url%7D?a=commitdiff_plain;h=74511ee890f7fca36e0ed828370816abe9b0e92e;p=njs.git Fixed SetFunctionName() with Symbol keys. This improves 85c1b6ba326b. --- diff --git a/src/njs_builtin.c b/src/njs_builtin.c index 3bf758ad..bd41b76b 100644 --- a/src/njs_builtin.c +++ b/src/njs_builtin.c @@ -396,6 +396,7 @@ njs_builtin_traverse(njs_vm_t *vm, njs_traverse_t *traverse, void *data) u_char *p, *start, *end; njs_int_t ret, n; njs_str_t name; + njs_bool_t symbol; njs_value_t key; njs_function_t *func; njs_object_prop_t *prop; @@ -431,29 +432,37 @@ njs_builtin_traverse(njs_vm_t *vm, njs_traverse_t *traverse, void *data) end = buf + sizeof(buf); do { + symbol = 0; key = path[n]->prop->name; if (njs_slow_path(njs_is_symbol(&key))) { - ret = njs_symbol_to_string(vm, &key, &key, 1); - if (njs_slow_path(ret != NJS_OK)) { - name = njs_str_value("#BROKEN_KEY"); - } - - } else { - if (p != buf) { - *p++ = '.'; + symbol = 1; + key = *njs_symbol_description(&key); + if (njs_is_undefined(&key)) { + key = njs_string_empty; } } njs_string_get(&key, &name); - if (njs_slow_path((p + name.length + 1) > end)) { + if (njs_slow_path((p + name.length + 3) > end)) { njs_type_error(vm, "njs_builtin_traverse() key is too long"); return NJS_ERROR; } + if (symbol) { + *p++ = '['; + + } else if (p != buf) { + *p++ = '.'; + } + p = njs_cpymem(p, name.start, name.length); + if (symbol) { + *p++ = ']'; + } + } while (n-- > 0); if (ctx->type == NJS_BUILTIN_TRAVERSE_MATCH) { diff --git a/src/njs_function.c b/src/njs_function.c index 0898d5e4..5bd8fe92 100644 --- a/src/njs_function.c +++ b/src/njs_function.c @@ -131,30 +131,53 @@ njs_function_active_closures(njs_vm_t *vm, njs_function_t *function) njs_int_t njs_function_name_set(njs_vm_t *vm, njs_function_t *function, - njs_value_t *name, njs_bool_t bound) + njs_value_t *name, const char *prefix) { - u_char *start; + u_char *p; + size_t len, symbol; njs_int_t ret; + njs_value_t value; njs_string_prop_t string; njs_object_prop_t *prop; njs_lvlhsh_query_t lhq; prop = njs_object_prop_alloc(vm, &njs_string_name, name, 0); - if (njs_slow_path(name == NULL)) { + if (njs_slow_path(prop == NULL)) { return NJS_ERROR; } - if (bound) { - (void) njs_string_prop(&string, name); + symbol = 0; + + if (njs_is_symbol(&prop->value)) { + symbol = 2; + prop->value = *njs_symbol_description(&prop->value); + } + + if (prefix != NULL || symbol != 0) { + value = prop->value; + (void) njs_string_prop(&string, &value); - start = njs_string_alloc(vm, &prop->value, string.size + 6, - string.length + 6); - if (njs_slow_path(start == NULL)) { + len = (prefix != NULL) ? njs_strlen(prefix) + 1: 0; + p = njs_string_alloc(vm, &prop->value, string.size + len + symbol, + string.length + len + symbol); + if (njs_slow_path(p == NULL)) { return NJS_ERROR; } - start = njs_cpymem(start, "bound ", 6); - memcpy(start, string.start, string.size); + if (len != 0) { + p = njs_cpymem(p, prefix, len - 1); + *p++ = ' '; + } + + if (symbol != 0) { + *p++ = '['; + } + + p = njs_cpymem(p, string.start, string.size); + + if (symbol != 0) { + *p++ = ']'; + } } prop->configurable = 1; @@ -1204,7 +1227,7 @@ njs_function_prototype_bind(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, name = njs_string_empty; } - ret = njs_function_name_set(vm, function, &name, 1); + ret = njs_function_name_set(vm, function, &name, "bound"); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } diff --git a/src/njs_function.h b/src/njs_function.h index ce397a15..20cda079 100644 --- a/src/njs_function.h +++ b/src/njs_function.h @@ -93,7 +93,7 @@ njs_function_t *njs_function_alloc(njs_vm_t *vm, njs_function_lambda_t *lambda, njs_closure_t *closures[], njs_bool_t shared); njs_function_t *njs_function_value_copy(njs_vm_t *vm, njs_value_t *value); njs_int_t njs_function_name_set(njs_vm_t *vm, njs_function_t *function, - njs_value_t *name, njs_bool_t bound); + njs_value_t *name, const char *prefix); njs_int_t njs_function_arguments_object_init(njs_vm_t *vm, njs_native_frame_t *frame); njs_int_t njs_function_rest_parameters_init(njs_vm_t *vm, diff --git a/src/njs_json.c b/src/njs_json.c index 68d32525..8405add1 100644 --- a/src/njs_json.c +++ b/src/njs_json.c @@ -1856,7 +1856,7 @@ njs_dump_terminal(njs_json_stringify_t *stringify, njs_chb_t *chain, case NJS_OBJECT_SYMBOL: value = njs_object_value(value); - ret = njs_symbol_to_string(stringify->vm, &str_val, value, 0); + ret = njs_symbol_descriptive_string(stringify->vm, &str_val, value); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -1867,7 +1867,7 @@ njs_dump_terminal(njs_json_stringify_t *stringify, njs_chb_t *chain, break; case NJS_SYMBOL: - ret = njs_symbol_to_string(stringify->vm, &str_val, value, 0); + ret = njs_symbol_descriptive_string(stringify->vm, &str_val, value); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } diff --git a/src/njs_object.h b/src/njs_object.h index 76ed32d0..ddea784e 100644 --- a/src/njs_object.h +++ b/src/njs_object.h @@ -213,7 +213,7 @@ njs_key_string_get(njs_vm_t *vm, njs_value_t *key, njs_str_t *str) njs_int_t ret; if (njs_slow_path(njs_is_symbol(key))) { - ret = njs_symbol_to_string(vm, key, key, 0); + ret = njs_symbol_descriptive_string(vm, key, key); if (njs_slow_path(ret != NJS_OK)) { return ret; } diff --git a/src/njs_object_prop.c b/src/njs_object_prop.c index 6c6340a4..dc1aa215 100644 --- a/src/njs_object_prop.c +++ b/src/njs_object_prop.c @@ -554,7 +554,7 @@ njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq) return NJS_ERROR; } - return njs_function_name_set(vm, function, &prop->name, 0); + return njs_function_name_set(vm, function, &prop->name, NULL); default: break; diff --git a/src/njs_string.c b/src/njs_string.c index e9e35412..74c387e8 100644 --- a/src/njs_string.c +++ b/src/njs_string.c @@ -486,7 +486,7 @@ njs_string_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, if (njs_slow_path(!njs_is_string(value))) { if (!vm->top_frame->ctor && njs_is_symbol(value)) { - return njs_symbol_to_string(vm, &vm->retval, value, 0); + return njs_symbol_descriptive_string(vm, &vm->retval, value); } ret = njs_value_to_string(vm, value, value); diff --git a/src/njs_symbol.c b/src/njs_symbol.c index 9b704cc2..db262e79 100644 --- a/src/njs_symbol.c +++ b/src/njs_symbol.c @@ -54,57 +54,53 @@ static const njs_value_t *njs_symbol_names[NJS_SYMBOL_KNOWN_MAX] = { }; -njs_int_t -njs_symbol_to_string(njs_vm_t *vm, njs_value_t *dst, const njs_value_t *value, - njs_bool_t as_name) +const njs_value_t * +njs_symbol_description(const njs_value_t *value) { - u_char *start; const njs_value_t *name; - njs_string_prop_t string; - - static const njs_value_t string_symbol = njs_string("Symbol()"); - name = value->data.u.value; + if (njs_symbol_key(value) < NJS_SYMBOL_KNOWN_MAX) { + name = njs_symbol_names[njs_symbol_key(value)]; - if (name == NULL) { - if (njs_fast_path(njs_symbol_key(value) < NJS_SYMBOL_KNOWN_MAX)) { - - name = njs_symbol_names[njs_symbol_key(value)]; - - } else { - *dst = string_symbol; + } else { + name = value->data.u.value; - return NJS_OK; + if (name == NULL) { + return &njs_value_undefined; } } - (void) njs_string_prop(&string, name); + return name; +} - if (as_name) { - string.length += njs_length("[]"); - start = njs_string_alloc(vm, dst, string.size + 2, string.length); - if (njs_slow_path(start == NULL)) { - return NJS_ERROR; - } +njs_int_t +njs_symbol_descriptive_string(njs_vm_t *vm, njs_value_t *dst, + const njs_value_t *value) +{ + u_char *start; + const njs_value_t *description; + njs_string_prop_t string; - start = njs_cpymem(start, "[", 1); - start = njs_cpymem(start, string.start, string.size); - *start = ']'; + description = njs_symbol_description(value); - } else { - string.length += njs_length("Symbol()"); + if (njs_is_undefined(description)) { + description = &njs_string_empty; + } - start = njs_string_alloc(vm, dst, string.size + 8, string.length); - if (njs_slow_path(start == NULL)) { - return NJS_ERROR; - } + (void) njs_string_prop(&string, description); - start = njs_cpymem(start, "Symbol(", 7); - start = njs_cpymem(start, string.start, string.size); - *start = ')'; + string.length += njs_length("Symbol()"); + + start = njs_string_alloc(vm, dst, string.size + 8, string.length); + if (njs_slow_path(start == NULL)) { + return NJS_ERROR; } + start = njs_cpymem(start, "Symbol(", 7); + start = njs_cpymem(start, string.start, string.size); + *start = ')'; + return NJS_OK; } @@ -344,7 +340,7 @@ njs_symbol_prototype_to_string(njs_vm_t *vm, njs_value_t *args, return ret; } - return njs_symbol_to_string(vm, &vm->retval, &vm->retval, 0); + return njs_symbol_descriptive_string(vm, &vm->retval, &vm->retval); } @@ -352,28 +348,14 @@ static njs_int_t njs_symbol_prototype_description(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - njs_int_t ret; - const njs_value_t *value, *name; + njs_int_t ret; ret = njs_symbol_prototype_value_of(vm, args, nargs, unused); if (njs_slow_path(ret != NJS_OK)) { return ret; } - value = &vm->retval; - - name = value->data.u.value; - - if (name == NULL) { - if (njs_fast_path(njs_symbol_key(value) < NJS_SYMBOL_KNOWN_MAX)) { - name = njs_symbol_names[njs_symbol_key(value)]; - - } else { - name = &njs_value_undefined; - } - } - - vm->retval = *name; + vm->retval = *njs_symbol_description(&vm->retval); return NJS_OK; } diff --git a/src/njs_symbol.h b/src/njs_symbol.h index 3b338b94..d722d2ff 100644 --- a/src/njs_symbol.h +++ b/src/njs_symbol.h @@ -7,8 +7,9 @@ #ifndef _NJS_SYMBOL_H_INCLUDED_ #define _NJS_SYMBOL_H_INCLUDED_ -njs_int_t njs_symbol_to_string(njs_vm_t *vm, njs_value_t *dst, - const njs_value_t *value, njs_bool_t as_name); +const njs_value_t *njs_symbol_description(const njs_value_t *value); +njs_int_t njs_symbol_descriptive_string(njs_vm_t *vm, njs_value_t *dst, + const njs_value_t *value); extern const njs_object_type_init_t njs_symbol_type_init; diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index d0b7e567..65d0000c 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -6698,6 +6698,13 @@ static njs_unit_test_t njs_test[] = "[f.name, f.bind().name]"), njs_str("F,bound F") }, + { njs_str("var s = Symbol('F'); var f = Object.defineProperty(function() {}, 'name', {get:()=>s});" + "[f.name.description, f.bind().name]"), + njs_str("F,bound ") }, + + { njs_str("/a/[Symbol.replace].bind().name"), + njs_str("bound [Symbol.replace]") }, + { njs_str("var f = Object.defineProperty(function() {}, 'name', {get:()=>{throw Error('Oops')}});" "f.bind().name"), njs_str("Error: Oops") }, @@ -7736,6 +7743,9 @@ static njs_unit_test_t njs_test[] = "'ABC'.replace(/(B)/, '$')"), njs_str("OOps") }, + { njs_str("var name = /a/g[Symbol.replace].name; [name, typeof name]"), + njs_str("[Symbol.replace],string") }, + { njs_str("RegExp.prototype[Symbol.replace].call()"), njs_str("TypeError: \"this\" is not object") },