]> git.kaiwu.me - njs.git/commitdiff
Fixed handling of NJS_DECLINED returned by NJS_PROPERTY_HANDLER.
authorDmitry Volyntsev <xeioex@nginx.com>
Wed, 14 Aug 2019 17:22:32 +0000 (20:22 +0300)
committerDmitry Volyntsev <xeioex@nginx.com>
Wed, 14 Aug 2019 17:22:32 +0000 (20:22 +0300)
src/njs_array.c
src/njs_object_prop.c
src/njs_value.c
src/njs_value.h
src/njs_vmcode.c
src/test/njs_unit_test.c

index 1ea1a4ef9a68754fd7a456dc30168d9491493967..3da31f033293eb92aadb8ac43b3e37bced4855f4 100644 (file)
@@ -331,8 +331,8 @@ njs_array_length(njs_vm_t *vm, njs_value_t *value, njs_value_t *setval,
         } while (proto != NULL);
 
         if (njs_slow_path(proto == NULL)) {
-            njs_internal_error(vm, "no array in proto chain");
-            return NJS_ERROR;
+            njs_set_undefined(retval);
+            return NJS_DECLINED;
         }
 
         array = (njs_array_t *) proto;
@@ -342,6 +342,7 @@ njs_array_length(njs_vm_t *vm, njs_value_t *value, njs_value_t *setval,
     }
 
     if (proto->type != NJS_ARRAY) {
+        njs_set_undefined(retval);
         return NJS_DECLINED;
     }
 
index 509de6d5f7f17c2dfa5a210bdbee8124f833bd1a..0152440811fa3a63b56238d5e317ac515abca4e9 100644 (file)
@@ -324,10 +324,9 @@ done:
     if (njs_is_valid(&prop->value)) {
         if (prev->type == NJS_PROPERTY_HANDLER) {
             if (njs_is_data_descriptor(prev) && prev->writable) {
-                ret = prev->value.data.u.prop_handler(vm, object,
-                                                         &prop->value,
-                                                         &vm->retval);
-                if (njs_slow_path(ret != NJS_OK)) {
+                ret = prev->value.data.u.prop_handler(vm, object, &prop->value,
+                                                      &vm->retval);
+                if (njs_slow_path(ret == NJS_ERROR)) {
                     return ret;
                 }
             }
@@ -519,7 +518,7 @@ njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest,
             prop = &pq.scratch;
             ret = prop->value.data.u.prop_handler(vm, value, NULL,
                                                   &prop->value);
-            if (njs_slow_path(ret != NJS_OK)) {
+            if (njs_slow_path(ret == NJS_ERROR)) {
                 return ret;
             }
 
index f97d270a583932108bdd7187949399d74bc17072..9a034d197fe00ed082fad3e37c2aa0ba3b1ca6fc 100644 (file)
@@ -1018,11 +1018,12 @@ njs_value_property(njs_vm_t *vm, njs_value_t *value, njs_value_t *key,
             ret = prop->value.data.u.prop_handler(vm, value, NULL,
                                                   &prop->value);
 
-            if (njs_slow_path(ret != NJS_OK)) {
+            if (njs_slow_path(ret == NJS_ERROR)) {
                 return ret;
             }
 
             *retval = prop->value;
+
             break;
 
         default:
@@ -1096,7 +1097,7 @@ njs_value_property_set(njs_vm_t *vm, njs_value_t *value, njs_value_t *key,
         if (prop->type == NJS_PROPERTY_HANDLER) {
             ret = prop->value.data.u.prop_handler(vm, value, setval,
                                                   &vm->retval);
-            if (ret != NJS_DECLINED) {
+            if (njs_slow_path(ret != NJS_DECLINED)) {
                 return ret;
             }
         }
index 592269ef81dece14e30bc253ecba6c4ca147eef5..79bc90d6c4d1ee4ca2ce9603f771345ebaeff866 100644 (file)
@@ -85,7 +85,8 @@ typedef enum {
  * njs_prop_handler_t is expected to return:
  *   NJS_OK - handler executed successfully;
  *   NJS_ERROR - some error, vm->retval contains appropriate exception;
- *   NJS_DECLINED - handler was applied to inappropriate object.
+ *   NJS_DECLINED - handler was applied to inappropriate object, vm->retval
+ *   contains undefined value.
  */
 typedef njs_int_t (*njs_prop_handler_t) (njs_vm_t *vm, njs_value_t *value,
     njs_value_t *setval, njs_value_t *retval);
index 2f32f600e90dff6277021a6fbf7d39fb78aeb9b7..d4b8878bbf37e09131fc6f1fd88fd275f3299593 100644 (file)
@@ -1168,11 +1168,15 @@ njs_vmcode_property_init(njs_vm_t *vm, njs_value_t *value, njs_value_t *key,
                 if (prop->type == NJS_PROPERTY_HANDLER) {
                     ret = prop->value.data.u.prop_handler(vm, value, init,
                                                           &vm->retval);
-                    if (njs_slow_path(ret != NJS_OK)) {
+                    if (njs_slow_path(ret == NJS_ERROR)) {
                         return ret;
                     }
 
-                    break;
+                    if (ret == NJS_OK) {
+                        break;
+                    }
+
+                    /* NJS_DECLINED */
                 }
             }
         }
@@ -1273,7 +1277,7 @@ njs_vmcode_property_delete(njs_vm_t *vm, njs_value_t *value, njs_value_t *key)
             if (njs_is_external(value)) {
                 ret = prop->value.data.u.prop_handler(vm, value, NULL, NULL);
                 if (njs_slow_path(ret != NJS_OK)) {
-                    return ret;
+                    return NJS_ERROR;
                 }
 
                 goto done;
index 6fb8a59f65c0f0b8015c8b04d3e3e1b62fdf02a6..aadb8f338e0d68605642a7fc623e10d0a313f932 100644 (file)
@@ -8807,6 +8807,9 @@ static njs_unit_test_t  njs_test[] =
               "Object.getPrototypeOf(o) === Object.prototype"),
       njs_str("true") },
 
+    { njs_str("var o = {__proto__: Array.prototype, length:3}; o.fill('a')[2]"),
+      njs_str("a") },
+
     { njs_str("({}).__proto__.constructor === Object"),
       njs_str("true") },