This closes #210 issue on Github.
njs_object_define_properties(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused)
{
- njs_int_t ret;
- njs_value_t *value, *desc;
- njs_lvlhsh_t *hash;
- njs_lvlhsh_each_t lhe;
- njs_object_prop_t *prop;
+ uint32_t i, length;
+ njs_int_t ret;
+ njs_array_t *keys;
+ njs_value_t desc, *value, *descs;
+ njs_object_prop_t *prop;
+ njs_property_query_t pq;
if (!njs_is_object(njs_arg(args, nargs, 1))) {
njs_type_error(vm, "Object.defineProperties is called on non-object");
return NJS_ERROR;
}
- value = njs_argument(args, 1);
-
- desc = njs_arg(args, nargs, 2);
+ descs = njs_arg(args, nargs, 2);
+ ret = njs_value_to_object(vm, descs);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
- if (!njs_is_object(desc)) {
- njs_type_error(vm, "descriptor is not an object");
+ keys = njs_value_own_enumerate(vm, descs, NJS_ENUM_KEYS,
+ NJS_ENUM_STRING | NJS_ENUM_SYMBOL, 0);
+ if (njs_slow_path(keys == NULL)) {
return NJS_ERROR;
}
- njs_lvlhsh_each_init(&lhe, &njs_object_hash_proto);
+ length = keys->length;
+ value = njs_argument(args, 1);
+ njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0);
- hash = njs_object_hash(desc);
+ for (i = 0; i < length; i++) {
+ ret = njs_property_query(vm, &pq, descs, &keys->start[i]);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return ret;
+ }
- for ( ;; ) {
- prop = njs_lvlhsh_each(hash, &lhe);
+ prop = pq.lhq.value;
- if (prop == NULL) {
- break;
+ if (ret == NJS_DECLINED || !prop->enumerable) {
+ continue;
}
- if (prop->enumerable && njs_is_object(&prop->value)) {
- ret = njs_object_prop_define(vm, value, &prop->name, &prop->value,
- NJS_OBJECT_PROP_DESCRIPTOR);
+ ret = njs_value_property(vm, descs, &keys->start[i], &desc);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return ret;
+ }
- if (njs_slow_path(ret != NJS_OK)) {
- return NJS_ERROR;
- }
+ ret = njs_object_prop_define(vm, value, &keys->start[i], &desc,
+ NJS_OBJECT_PROP_DESCRIPTOR);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return NJS_ERROR;
}
}
if (njs_is_valid(&prop->value)
&& prev->type != NJS_PROPERTY_HANDLER
- && !njs_values_strict_equal(&prop->value, &prev->value))
+ && !njs_values_same(&prop->value, &prev->value))
{
goto exception;
}
static const njs_value_t get_string = njs_string("get");
+ if (!njs_is_object(desc)) {
+ njs_type_error(vm, "property descriptor must be an object");
+ return NJS_ERROR;
+ }
+
data = 0;
accessor = 0;
"Object.keys(o)"),
njs_str("b") },
+ { njs_str("var o = Object.defineProperties({}, { get x() { return { value: 1 }; } });"
+ "Object.getOwnPropertyDescriptor(o, 'x').value"),
+ njs_str("1") },
+
+ { njs_str("Object.defineProperties({}, { get x() { return 1; } })"),
+ njs_str("TypeError: property descriptor must be an object") },
+
+ { njs_str("var obj = {}; var desc = {value:NaN}; Object.defineProperty(obj, 'foo', desc); "
+ "Object.defineProperties(obj, { foo: desc } ).foo"),
+ njs_str("NaN") },
+
+ { njs_str("var obj = {}; var desc = {value:-0}; Object.defineProperty(obj, 'foo', desc); "
+ "Object.defineProperties(obj, { foo: desc } ).foo"),
+ njs_str("-0") },
+
+ { njs_str("var obj = {}; var desc = {value:-0}; Object.defineProperty(obj, 'foo', {value:0}); "
+ "Object.defineProperties(obj, { foo: desc } ).foo"),
+ njs_str("TypeError: Cannot redefine property: \"foo\"") },
+
+ { njs_str("var obj = {}; var desc = {value:0}; Object.defineProperty(obj, 'foo', {value:-0}); "
+ "Object.defineProperties(obj, { foo: desc } ).foo"),
+ njs_str("TypeError: Cannot redefine property: \"foo\"") },
+
+ { njs_str("var descs = {a:{value:1}}; Object.defineProperty(descs, 'b', {value:{value:2}});"
+ "var o = Object.defineProperties({}, descs);"
+ "njs.dump([o.a, o.b])"),
+ njs_str("[1,undefined]") },
+
+ { njs_str("var descs = {a:{value:1}}; Object.defineProperty(descs, 'b', {value:{value:2}, enumerable:true});"
+ "var o = Object.defineProperties({}, descs);"
+ "njs.dump([o.a, o.b])"),
+ njs_str("[1,2]") },
+
{ njs_str("var o = {a:1}; delete o.a;"
"Object.defineProperty(o, 'a', { value: 1 }); o.a"),
njs_str("1") },
{ njs_str("Object.defineProperties(1, {})"),
njs_str("TypeError: Object.defineProperties is called on non-object") },
- { njs_str("Object.defineProperties({}, 1)"),
- njs_str("TypeError: descriptor is not an object") },
+ { njs_str("njs.dump(Object.defineProperties({}, 1))"),
+ njs_str("{}") },
{ njs_str("Object.defineProperties(Object.freeze({b:1}), {b:{value:1}}).b"),
njs_str("1") },