Explorar o código

Proxies ignore traps whose value is null

Fixes gh-646
Nicolò Ribaudo %!s(int64=10) %!d(string=hai) anos
pai
achega
27ee5ec2a3

+ 10 - 10
lib/Runtime/Library/JavascriptProxy.cpp

@@ -1741,17 +1741,17 @@ namespace Js
         //5. Let trap be the result of GetMethod(handler, "getOwnPropertyDescriptor").
         //6. ReturnIfAbrupt(trap).
 
-        //7.3.9 GetMethod(O, P)
-        //    The abstract operation GetMethod is used to get the value of a specific property of an object when the value of the property is expected to be a function.The operation is called with arguments O and P where O is the object, P is the property key.This abstract operation performs the following steps :
-        //1. Assert : Type(O) is Object.
-        //2. Assert : IsPropertyKey(P) is true.
-        //3. Let func be the result of calling the[[Get]] internal method of O passing P and O as the arguments.
-        //4. ReturnIfAbrupt(func).
-        //5. If func is undefined, then return undefined.
-        //6. If IsCallable(func) is false, then throw a TypeError exception.
-        //7. Return func.
+        //7.3.9 GetMethod(V, P)
+        //  The abstract operation GetMethod is used to get the value of a specific property of an ECMAScript language value when the value of the
+        //  property is expected to be a function. The operation is called with arguments V and P where V is the ECMAScript language value, P is the
+        //  property key. This abstract operation performs the following steps:
+        //  1. Assert: IsPropertyKey(P) is true.
+        //  2. Let func be ? GetV(V, P).
+        //  3. If func is either undefined or null, return undefined.
+        //  4. If IsCallable(func) is false, throw a TypeError exception.
+        //  5. Return func.
         BOOL result = JavascriptOperators::GetPropertyReference(handler, methodId, &varMethod, requestContext);
-        if (!result || JavascriptOperators::GetTypeId(varMethod) == TypeIds_Undefined)
+        if (!result || JavascriptOperators::IsUndefinedOrNull(varMethod))
         {
             return nullptr;
         }

+ 14 - 0
test/es6/ProxyInProxy.baseline

@@ -83,3 +83,17 @@ Symbol(prop2)
 Symbol(prop5)
 Symbol(prop4)
 Symbol(prop5)
+***Traps whose value is null are ignored
+"getPrototypeOf" called
+"setPrototypeOf" called
+"isExtensible" called
+"preventExtensions" called
+"getOwnPropertyDescriptor" called
+"defineProperty" called
+"has" called
+"get" called
+"set" called
+"deleteProperty" called
+"ownKeys" called
+"apply" called
+"construct" called

+ 33 - 2
test/es6/ProxyInProxy.js

@@ -36,7 +36,7 @@ function test1() {
     print(Object.keys(proxy2));
     print('***Testing Object.getOwnPropertySymbols()');
     print(Object.getOwnPropertySymbols(proxy2).length);
-   
+
     print('***Testing Object.freeze()');
     try{
         Object.freeze(proxy2);
@@ -139,9 +139,40 @@ function test3() {
     {
         print(symbols[i].toString())
     }
-   
+
+}
+
+function test4() {
+    print("***Traps whose value is null are ignored");
+
+    function getProxy(trap, result, obj) {
+        const proxy = new Proxy(obj, {
+            [trap]: () => {
+                print(`"${trap}" called`);
+                return result;
+            }
+        });
+        return new Proxy(proxy, {
+            [trap]: null
+        });
+    }
+
+    Object.getPrototypeOf(getProxy("getPrototypeOf", {}, {}));
+    Object.setPrototypeOf(getProxy("setPrototypeOf", true, {}), {});
+    Object.isExtensible(getProxy("isExtensible", true, {}));
+    Object.preventExtensions(getProxy("preventExtensions", false, {}));
+    Object.getOwnPropertyDescriptor(getProxy("getOwnPropertyDescriptor", undefined, {}));
+    Object.defineProperty(getProxy("defineProperty", true, {}), "prop", { value: 0 });
+    "prop" in getProxy("has", true, {});
+    getProxy("get", 0, {}).prop;
+    getProxy("set", true, {}).prop = 0;
+    delete getProxy("deleteProperty", true, {}).prop;
+    Object.keys(getProxy("ownKeys", [], {}));
+    getProxy("apply", 0, function () {})();
+    new (getProxy("construct", {}, function () {}));
 }
 
 test1();
 test2();
 test3();
+test4();