Title: [280364] trunk
Revision
280364
Author
shvaikal...@gmail.com
Date
2021-07-27 17:21:05 -0700 (Tue, 27 Jul 2021)

Log Message

ProxyObject callees should be skipped during Function.prototype.caller resolution
https://bugs.webkit.org/show_bug.cgi?id=228341

Reviewed by Yusuke Suzuki.

Source/_javascript_Core:

Just like a bound function, a Proxy with nullish "apply" handler merely forwards
[[Call]] to its target [1], without pushing onto the execution context stack.
This fact is also noted in Function.prototype.{caller,arguments} reflection proposal [2].

This patch aligns JSC with V8 and SpiderMonkey if Proxy's "apply" handler is userland
or nullish. However, since JSC implements proper tail calls, `Function.prototype.caller`
result is divergent from other engines if the handler is `Reflect.apply`, which performs
a tail call that gets optimized away [2] (unless called by another Proxy).

[1]: https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-call-thisargument-argumentslist (step 8)
[2]: https://github.com/claudepache/es-legacy-function-reflection/blob/master/spec.md#get-functionprototypecaller (see notes)

* runtime/FunctionPrototype.cpp:
(JSC::RetrieveCallerFunctionFunctor::operator() const):

LayoutTests:

* js/caller-property-expected.txt:
* js/script-tests/caller-property.js:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (280363 => 280364)


--- trunk/LayoutTests/ChangeLog	2021-07-28 00:12:30 UTC (rev 280363)
+++ trunk/LayoutTests/ChangeLog	2021-07-28 00:21:05 UTC (rev 280364)
@@ -1,3 +1,13 @@
+2021-07-27  Alexey Shvayka  <shvaikal...@gmail.com>
+
+        ProxyObject callees should be skipped during Function.prototype.caller resolution
+        https://bugs.webkit.org/show_bug.cgi?id=228341
+
+        Reviewed by Yusuke Suzuki.
+
+        * js/caller-property-expected.txt:
+        * js/script-tests/caller-property.js:
+
 2021-07-27  Eric Hutchison  <ehutchi...@apple.com>
 
         [BigSur wk2 Debug arm64] fast/text/emoji-overlap.html is a flaky image-only failure.

Modified: trunk/LayoutTests/js/caller-property-expected.txt (280363 => 280364)


--- trunk/LayoutTests/js/caller-property-expected.txt	2021-07-28 00:12:30 UTC (rev 280363)
+++ trunk/LayoutTests/js/caller-property-expected.txt	2021-07-28 00:21:05 UTC (rev 280364)
@@ -18,6 +18,13 @@
 PASS strictCaller(boundStrictCallee) threw exception TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context..
 PASS strictTailCaller(boundNonStrictCallee) is null
 PASS strictTailCaller(boundStrictCallee) threw exception TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context..
+PASS nonStrictCaller(new Proxy(nonStrictCallee, {})) is nonStrictCaller
+PASS nonStrictCaller(new Proxy(nonStrictCallee, {}).bind()) is nonStrictCaller
+PASS nonStrictCaller(new Proxy(new Proxy(nonStrictCallee, {}), {})) is nonStrictCaller
+PASS nonStrictCaller(new Proxy(boundNonStrictCallee, {})) is nonStrictCaller
+PASS nonStrictCaller(new Proxy(nonStrictCallee, Reflect)) is nonStrictCaller
+PASS nonStrictCaller(new Proxy(new Proxy(nonStrictCallee, Reflect), {})) is nonStrictCaller
+PASS nonStrictCaller(new Proxy(new Proxy(nonStrictCallee, {}), Reflect)) is null
 PASS nonStrictGetter(nonStrictAccessor) threw exception TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context..
 PASS nonStrictGetter(strictAccessor) threw exception TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context..
 PASS strictGetter(nonStrictAccessor) threw exception TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context..

Modified: trunk/LayoutTests/js/script-tests/caller-property.js (280363 => 280364)


--- trunk/LayoutTests/js/script-tests/caller-property.js	2021-07-28 00:12:30 UTC (rev 280363)
+++ trunk/LayoutTests/js/script-tests/caller-property.js	2021-07-28 00:21:05 UTC (rev 280364)
@@ -43,6 +43,15 @@
 shouldBe("strictTailCaller(boundNonStrictCallee)", "null");
 shouldThrow("strictTailCaller(boundStrictCallee)");
 
+shouldBe("nonStrictCaller(new Proxy(nonStrictCallee, {}))", "nonStrictCaller");
+shouldBe("nonStrictCaller(new Proxy(nonStrictCallee, {}).bind())", "nonStrictCaller");
+shouldBe("nonStrictCaller(new Proxy(new Proxy(nonStrictCallee, {}), {}))", "nonStrictCaller");
+shouldBe("nonStrictCaller(new Proxy(boundNonStrictCallee, {}))", "nonStrictCaller");
+
+shouldBe("nonStrictCaller(new Proxy(nonStrictCallee, Reflect))", "nonStrictCaller"); // tail call
+shouldBe("nonStrictCaller(new Proxy(new Proxy(nonStrictCallee, Reflect), {}))", "nonStrictCaller"); // tail call
+shouldBe("nonStrictCaller(new Proxy(new Proxy(nonStrictCallee, {}), Reflect))", "null"); // no tail call in Proxy's [[Call]]
+
 // Check that .caller throws as expected, over an accessor call. (per https://tc39.github.io/ecma262/#sec-forbidden-extensions)
 function getFooGetter(x) { return Object.getOwnPropertyDescriptor(x, 'foo').get; }
 function getFooSetter(x) { return Object.getOwnPropertyDescriptor(x, 'foo').set; }

Modified: trunk/Source/_javascript_Core/ChangeLog (280363 => 280364)


--- trunk/Source/_javascript_Core/ChangeLog	2021-07-28 00:12:30 UTC (rev 280363)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-07-28 00:21:05 UTC (rev 280364)
@@ -1,3 +1,25 @@
+2021-07-27  Alexey Shvayka  <shvaikal...@gmail.com>
+
+        ProxyObject callees should be skipped during Function.prototype.caller resolution
+        https://bugs.webkit.org/show_bug.cgi?id=228341
+
+        Reviewed by Yusuke Suzuki.
+
+        Just like a bound function, a Proxy with nullish "apply" handler merely forwards
+        [[Call]] to its target [1], without pushing onto the execution context stack.
+        This fact is also noted in Function.prototype.{caller,arguments} reflection proposal [2].
+
+        This patch aligns JSC with V8 and SpiderMonkey if Proxy's "apply" handler is userland
+        or nullish. However, since JSC implements proper tail calls, `Function.prototype.caller`
+        result is divergent from other engines if the handler is `Reflect.apply`, which performs
+        a tail call that gets optimized away [2] (unless called by another Proxy).
+
+        [1]: https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-call-thisargument-argumentslist (step 8)
+        [2]: https://github.com/claudepache/es-legacy-function-reflection/blob/master/spec.md#get-functionprototypecaller (see notes)
+
+        * runtime/FunctionPrototype.cpp:
+        (JSC::RetrieveCallerFunctionFunctor::operator() const):
+
 2021-07-26  Yusuke Suzuki  <ysuz...@apple.com>
 
         Add Temporal to features.json

Modified: trunk/Source/_javascript_Core/runtime/FunctionPrototype.cpp (280363 => 280364)


--- trunk/Source/_javascript_Core/runtime/FunctionPrototype.cpp	2021-07-28 00:12:30 UTC (rev 280363)
+++ trunk/Source/_javascript_Core/runtime/FunctionPrototype.cpp	2021-07-28 00:21:05 UTC (rev 280364)
@@ -181,7 +181,7 @@
 
         JSCell* callee = visitor->callee().asCell();
 
-        if (callee && callee->inherits<JSBoundFunction>(callee->vm()))
+        if (callee && (callee->inherits<JSBoundFunction>(callee->vm()) || callee->type() == ProxyObjectType))
             return StackVisitor::Continue;
 
         if (!m_hasFoundFrame && callee != m_targetCallee)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to