[njs] Fixed SetFunctionName() with Symbol keys.
Dmitry Volyntsev
xeioex at nginx.com
Thu Jul 9 14:00:27 UTC 2020
details: https://hg.nginx.org/njs/rev/5f2034557bc3
branches:
changeset: 1463:5f2034557bc3
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Thu Jul 09 13:57:10 2020 +0000
description:
Fixed SetFunctionName() with Symbol keys.
This improves 85c1b6ba326b.
diffstat:
src/njs_builtin.c | 27 +++++++++----
src/njs_function.c | 45 ++++++++++++++++++------
src/njs_function.h | 2 +-
src/njs_json.c | 4 +-
src/njs_object.h | 2 +-
src/njs_object_prop.c | 2 +-
src/njs_string.c | 2 +-
src/njs_symbol.c | 88 +++++++++++++++++++----------------------------
src/njs_symbol.h | 5 +-
src/test/njs_unit_test.c | 10 +++++
10 files changed, 106 insertions(+), 81 deletions(-)
diffs (377 lines):
diff -r 0c941c887ab7 -r 5f2034557bc3 src/njs_builtin.c
--- a/src/njs_builtin.c Wed Jul 08 13:07:06 2020 +0000
+++ b/src/njs_builtin.c Thu Jul 09 13:57:10 2020 +0000
@@ -396,6 +396,7 @@ njs_builtin_traverse(njs_vm_t *vm, njs_t
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_t
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 -r 0c941c887ab7 -r 5f2034557bc3 src/njs_function.c
--- a/src/njs_function.c Wed Jul 08 13:07:06 2020 +0000
+++ b/src/njs_function.c Thu Jul 09 13:57:10 2020 +0000
@@ -131,30 +131,53 @@ njs_function_active_closures(njs_vm_t *v
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);
+ }
- start = njs_string_alloc(vm, &prop->value, string.size + 6,
- string.length + 6);
- if (njs_slow_path(start == NULL)) {
+ if (prefix != NULL || symbol != 0) {
+ value = prop->value;
+ (void) njs_string_prop(&string, &value);
+
+ 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
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 -r 0c941c887ab7 -r 5f2034557bc3 src/njs_function.h
--- a/src/njs_function.h Wed Jul 08 13:07:06 2020 +0000
+++ b/src/njs_function.h Thu Jul 09 13:57:10 2020 +0000
@@ -93,7 +93,7 @@ njs_function_t *njs_function_alloc(njs_v
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 -r 0c941c887ab7 -r 5f2034557bc3 src/njs_json.c
--- a/src/njs_json.c Wed Jul 08 13:07:06 2020 +0000
+++ b/src/njs_json.c Thu Jul 09 13:57:10 2020 +0000
@@ -1856,7 +1856,7 @@ njs_dump_terminal(njs_json_stringify_t *
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 *
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 -r 0c941c887ab7 -r 5f2034557bc3 src/njs_object.h
--- a/src/njs_object.h Wed Jul 08 13:07:06 2020 +0000
+++ b/src/njs_object.h Thu Jul 09 13:57:10 2020 +0000
@@ -213,7 +213,7 @@ njs_key_string_get(njs_vm_t *vm, njs_val
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 -r 0c941c887ab7 -r 5f2034557bc3 src/njs_object_prop.c
--- a/src/njs_object_prop.c Wed Jul 08 13:07:06 2020 +0000
+++ b/src/njs_object_prop.c Thu Jul 09 13:57:10 2020 +0000
@@ -554,7 +554,7 @@ njs_prop_private_copy(njs_vm_t *vm, njs_
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 -r 0c941c887ab7 -r 5f2034557bc3 src/njs_string.c
--- a/src/njs_string.c Wed Jul 08 13:07:06 2020 +0000
+++ b/src/njs_string.c Thu Jul 09 13:57:10 2020 +0000
@@ -486,7 +486,7 @@ njs_string_constructor(njs_vm_t *vm, njs
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 -r 0c941c887ab7 -r 5f2034557bc3 src/njs_symbol.c
--- a/src/njs_symbol.c Wed Jul 08 13:07:06 2020 +0000
+++ b/src/njs_symbol.c Thu Jul 09 13:57:10 2020 +0000
@@ -54,56 +54,52 @@ static const njs_value_t *njs_symbol_na
};
-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 (name == NULL) {
- if (njs_fast_path(njs_symbol_key(value) < NJS_SYMBOL_KNOWN_MAX)) {
+ if (njs_symbol_key(value) < NJS_SYMBOL_KNOWN_MAX) {
+ name = njs_symbol_names[njs_symbol_key(value)];
- name = njs_symbol_names[njs_symbol_key(value)];
+ } else {
+ name = value->data.u.value;
- } else {
- *dst = string_symbol;
-
- 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;
+
+ description = njs_symbol_description(value);
- start = njs_cpymem(start, "[", 1);
- start = njs_cpymem(start, string.start, string.size);
- *start = ']';
+ if (njs_is_undefined(description)) {
+ description = &njs_string_empty;
+ }
- } else {
- string.length += njs_length("Symbol()");
+ (void) njs_string_prop(&string, description);
+
+ 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_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 = ')';
- }
+ 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
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 -r 0c941c887ab7 -r 5f2034557bc3 src/njs_symbol.h
--- a/src/njs_symbol.h Wed Jul 08 13:07:06 2020 +0000
+++ b/src/njs_symbol.h Thu Jul 09 13:57:10 2020 +0000
@@ -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 -r 0c941c887ab7 -r 5f2034557bc3 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c Wed Jul 08 13:07:06 2020 +0000
+++ b/src/test/njs_unit_test.c Thu Jul 09 13:57:10 2020 +0000
@@ -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)/, '$<g>')"),
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") },
More information about the nginx-devel
mailing list