[njs] Fixed array length property handler.
Valentin Bartenev
vbart at nginx.com
Thu May 23 12:54:48 UTC 2019
details: https://hg.nginx.org/njs/rev/fd0918b6dd56
branches:
changeset: 981:fd0918b6dd56
user: Valentin Bartenev <vbart at nginx.com>
date: Thu May 23 15:05:51 2019 +0300
description:
Fixed array length property handler.
Previously it might change the length of prototype arrays.
diffstat:
njs/njs_array.c | 86 ++++++++++++++++++++++++++---------------------
njs/njs_vm.c | 12 +++++-
njs/njs_vm.h | 5 ++
njs/test/njs_unit_test.c | 4 ++
4 files changed, 65 insertions(+), 42 deletions(-)
diffs (161 lines):
diff -r f7eedb8257eb -r fd0918b6dd56 njs/njs_array.c
--- a/njs/njs_array.c Thu May 23 15:05:51 2019 +0300
+++ b/njs/njs_array.c Thu May 23 15:05:51 2019 +0300
@@ -434,57 +434,65 @@ njs_array_length(njs_vm_t *vm, njs_value
proto = value->data.u.object;
- do {
- if (nxt_fast_path(proto->type == NJS_ARRAY)) {
- break;
+ if (setval == NULL) {
+ do {
+ if (nxt_fast_path(proto->type == NJS_ARRAY)) {
+ break;
+ }
+
+ proto = proto->__proto__;
+ } while (proto != NULL);
+
+ if (nxt_slow_path(proto == NULL)) {
+ njs_internal_error(vm, "no array in proto chain");
+ return NJS_ERROR;
}
- proto = proto->__proto__;
- } while (proto != NULL);
-
- if (nxt_slow_path(proto == NULL)) {
- njs_internal_error(vm, "no array in proto chain");
+ array = (njs_array_t *) proto;
+
+ njs_value_number_set(retval, array->length);
+ return NJS_OK;
+ }
+
+ if (proto->type != NJS_ARRAY) {
+ return NJS_DECLINED;
+ }
+
+ if (!njs_is_number(setval)) {
+ njs_range_error(vm, "Invalid array length");
+ return NJS_ERROR;
+ }
+
+ num = setval->data.u.number;
+ length = (uint32_t) num;
+
+ if ((double) length != num) {
+ njs_range_error(vm, "Invalid array length");
return NJS_ERROR;
}
array = (njs_array_t *) proto;
- if (setval != NULL) {
- if (!njs_is_number(setval)) {
- njs_range_error(vm, "Invalid array length");
- return NJS_ERROR;
- }
-
- num = setval->data.u.number;
- length = (uint32_t) num;
-
- if ((double) length != num) {
- njs_range_error(vm, "Invalid array length");
+ size = (int64_t) length - array->length;
+
+ if (size > 0) {
+ ret = njs_array_expand(vm, array, 0, size);
+ if (nxt_slow_path(ret != NXT_OK)) {
return NJS_ERROR;
}
- size = (int64_t) length - array->length;
-
- if (size > 0) {
- ret = njs_array_expand(vm, array, 0, size);
- if (nxt_slow_path(ret != NXT_OK)) {
- return NJS_ERROR;
- }
-
- val = &array->start[array->length];
-
- do {
- njs_set_invalid(val);
- val++;
- size--;
- } while (size != 0);
- }
-
- array->length = length;
+ val = &array->start[array->length];
+
+ do {
+ njs_set_invalid(val);
+ val++;
+ size--;
+ } while (size != 0);
}
- njs_value_number_set(retval, array->length);
-
+ array->length = length;
+
+ njs_value_number_set(retval, length);
return NJS_OK;
}
diff -r f7eedb8257eb -r fd0918b6dd56 njs/njs_vm.c
--- a/njs/njs_vm.c Thu May 23 15:05:51 2019 +0300
+++ b/njs/njs_vm.c Thu May 23 15:05:51 2019 +0300
@@ -694,11 +694,17 @@ njs_vmcode_property_set(njs_vm_t *vm, nj
if (prop->type == NJS_PROPERTY_HANDLER) {
ret = prop->value.data.u.prop_handler(vm, object, value,
&vm->retval);
- if (nxt_slow_path(ret != NXT_OK)) {
+
+ switch (ret) {
+ case NXT_OK:
+ return sizeof(njs_vmcode_prop_set_t);
+
+ case NXT_DECLINED:
+ break;
+
+ default:
return ret;
}
-
- return sizeof(njs_vmcode_prop_set_t);
}
if (pq.own) {
diff -r f7eedb8257eb -r fd0918b6dd56 njs/njs_vm.h
--- a/njs/njs_vm.h Thu May 23 15:05:51 2019 +0300
+++ b/njs/njs_vm.h Thu May 23 15:05:51 2019 +0300
@@ -147,6 +147,11 @@ typedef struct njs_generator_s nj
* njs_prop_handler_t operates as a property getter and/or setter.
* The handler receives NULL setval if it is invoked in GET context and
* non-null otherwise.
+ *
+ * njs_prop_handler_t is expected to return:
+ * NXT_OK - handler executed successfully;
+ * NXT_ERROR - some error, vm->retval contains appropriate exception;
+ * NXT_DECLINED - handler was applied to inappropriate object.
*/
typedef njs_ret_t (*njs_prop_handler_t) (njs_vm_t *vm, njs_value_t *value,
njs_value_t *setval, njs_value_t *retval);
diff -r f7eedb8257eb -r fd0918b6dd56 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Thu May 23 15:05:51 2019 +0300
+++ b/njs/test/njs_unit_test.c Thu May 23 15:05:51 2019 +0300
@@ -8405,6 +8405,10 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("Array.prototype.length = 3, Array.prototype"),
nxt_string(",,") },
+ { nxt_string("var o = Object.create(Array.prototype); o.length = 3;"
+ "[Array.prototype, Array.prototype.length, o.length]"),
+ nxt_string(",0,3") },
+
{ nxt_string("var o = Object.create(Array.prototype);"
"Object.defineProperty(o, 'length', {value: 3});"
"[Array.prototype, Array.prototype.length, o.length]"),
More information about the nginx-devel
mailing list