From: Valentin Bartenev Date: Thu, 23 May 2019 12:05:51 +0000 (+0300) Subject: Fixed array length property handler. X-Git-Url: http://git.kaiwu.me/postgresql/log/contrib/postgres_fdw/static/gitweb.js?a=commitdiff_plain;h=51a28b4c8e1da025071dd1d2cf7cca2889f9c5f9;p=njs.git Fixed array length property handler. Previously it might change the length of prototype arrays. --- diff --git a/njs/njs_array.c b/njs/njs_array.c index efd05586..2f13437b 100644 --- a/njs/njs_array.c +++ b/njs/njs_array.c @@ -434,57 +434,65 @@ njs_array_length(njs_vm_t *vm, njs_value_t *value, njs_value_t *setval, 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); + array = (njs_array_t *) proto; - if (nxt_slow_path(proto == NULL)) { - njs_internal_error(vm, "no array in proto chain"); - return NJS_ERROR; + njs_value_number_set(retval, array->length); + return NJS_OK; } - array = (njs_array_t *) proto; - - if (setval != NULL) { - if (!njs_is_number(setval)) { - njs_range_error(vm, "Invalid array length"); - return NJS_ERROR; - } + if (proto->type != NJS_ARRAY) { + return NJS_DECLINED; + } - num = setval->data.u.number; - length = (uint32_t) num; + if (!njs_is_number(setval)) { + njs_range_error(vm, "Invalid array length"); + return NJS_ERROR; + } - if ((double) length != num) { - njs_range_error(vm, "Invalid array length"); - return NJS_ERROR; - } + num = setval->data.u.number; + length = (uint32_t) num; - size = (int64_t) length - array->length; + if ((double) length != num) { + njs_range_error(vm, "Invalid array length"); + return NJS_ERROR; + } - if (size > 0) { - ret = njs_array_expand(vm, array, 0, size); - if (nxt_slow_path(ret != NXT_OK)) { - return NJS_ERROR; - } + array = (njs_array_t *) proto; - val = &array->start[array->length]; + size = (int64_t) length - array->length; - do { - njs_set_invalid(val); - val++; - size--; - } while (size != 0); + if (size > 0) { + ret = njs_array_expand(vm, array, 0, size); + if (nxt_slow_path(ret != NXT_OK)) { + return NJS_ERROR; } - 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 --git a/njs/njs_vm.c b/njs/njs_vm.c index c13f5c74..f6f2e3e7 100644 --- a/njs/njs_vm.c +++ b/njs/njs_vm.c @@ -694,11 +694,17 @@ njs_vmcode_property_set(njs_vm_t *vm, njs_value_t *object, 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 --git a/njs/njs_vm.h b/njs/njs_vm.h index 1f14fa9c..41f2b5c3 100644 --- a/njs/njs_vm.h +++ b/njs/njs_vm.h @@ -147,6 +147,11 @@ typedef struct njs_generator_s njs_generator_t; * 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 --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index a3dc530c..ecb873db 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -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]"),