Title: [207997] branches/safari-602-branch
Revision
207997
Author
[email protected]
Date
2016-10-27 12:41:43 -0700 (Thu, 27 Oct 2016)

Log Message

Merge r207518. rdar://problem/28216050, rdar://problem/28216232

    2016-10-18  Mark Lam  <[email protected]>

    Invoking Object.prototype.__proto__ accessors directly should throw a TypeError.
    https://bugs.webkit.org/show_bug.cgi?id=154377
    <rdar://problem/27330808>

    Reviewed by Filip Pizlo and Saam Barati.

JSTests:

    * stress/object-prototype-proto-accessors-should-throw-on-undefined-this.js: Added.

Source/_javascript_Core:

    In a scenario where we cache the __proto__ accessors in global variables, and
    later explicitly invoke those accessors as functions, the spec for Function Calls
    (see https://tc39.github.io/ecma262/#sec-function-calls) states that the function
    ref value is of type Reference, and base of ref is an Environment Record.  Then,
    it follows that the thisValue should be set to refEnv.WithBaseObject()
    (see section 4.b.ii of 12.3.4.1 at
    https://tc39.github.io/ecma262/#sec-function-calls-runtime-semantics-evaluation).

    refEnv in this case is the environment record that the cached accessors were
    found in i.e. the global object.  The WithBaseObject() of the global object is
    undefined (see details about WithBaseObject at
    https://tc39.github.io/ecma262/#sec-environment-records).

    Hence, the __proto__ accessors should see a thisValue of undefined, and throw
    TypeErrors.  See https://tc39.github.io/ecma262/#sec-get-object.prototype.__proto__,
    https://tc39.github.io/ecma262/#sec-set-object.prototype.__proto__,
    https://tc39.github.io/ecma262/#sec-toobject, and
    https://tc39.github.io/ecma262/#sec-requireobjectcoercible.

    In JSC's implementation, the callee needs to do a ToThis operation on the
    incoming "this" argument in order to get the specified thisValue.  The
    implementations of the __proto__ accessors were not doing this correctly.  This
    has now been fixed.

    * runtime/JSGlobalObjectFunctions.cpp:
    (JSC::globalFuncProtoGetter):
    (JSC::globalFuncProtoSetter):

LayoutTests:

    * http/tests/security/xss-DENIED-htmlelelment-with-iframe-proto-expected.txt:
    * http/tests/security/xss-DENIED-method-with-iframe-proto-expected.txt:
    * http/tests/security/xss-DENIED-non-shadowable-propterty-with-iframe-proto-expected.txt:
    * http/tests/security/xss-DENIED-regular-propterty-with-iframe-proto-expected.txt:
    * http/tests/security/xss-DENIED-regular-propterty-with-iframe-proto.html:
    * js/dom/activation-proto-expected.txt:
    * js/dom/script-tests/activation-proto.js:
    * js/object-literal-shorthand-construction-expected.txt:
    * js/script-tests/object-literal-shorthand-construction.js:
    * js/script-tests/sloppy-getter-setter-global-object.js:
    * js/sloppy-getter-setter-global-object-expected.txt:

Modified Paths

Added Paths

Diff

Modified: branches/safari-602-branch/JSTests/ChangeLog (207996 => 207997)


--- branches/safari-602-branch/JSTests/ChangeLog	2016-10-27 19:38:04 UTC (rev 207996)
+++ branches/safari-602-branch/JSTests/ChangeLog	2016-10-27 19:41:43 UTC (rev 207997)
@@ -1,3 +1,17 @@
+2016-10-27  Mark Lam  <[email protected]>
+
+        Merge r207518. rdar://problem/28216050, rdar://problem/28216232
+
+    2016-10-18  Mark Lam  <[email protected]>
+
+            Invoking Object.prototype.__proto__ accessors directly should throw a TypeError.
+            https://bugs.webkit.org/show_bug.cgi?id=154377
+            <rdar://problem/27330808>
+
+            Reviewed by Filip Pizlo and Saam Barati.
+
+            * stress/object-prototype-proto-accessors-should-throw-on-undefined-this.js: Added.
+
 2016-10-24  Matthew Hanson  <[email protected]>
 
         Merge r206281. rdar://problem/28870938

Added: branches/safari-602-branch/JSTests/stress/object-prototype-proto-accessors-should-throw-on-undefined-this.js (0 => 207997)


--- branches/safari-602-branch/JSTests/stress/object-prototype-proto-accessors-should-throw-on-undefined-this.js	                        (rev 0)
+++ branches/safari-602-branch/JSTests/stress/object-prototype-proto-accessors-should-throw-on-undefined-this.js	2016-10-27 19:41:43 UTC (rev 207997)
@@ -0,0 +1,38 @@
+//@ runFTLNoCJIT
+
+function shouldEqual(testId, actual, expected) {
+    if (actual != expected) {
+        throw testId + ": ERROR: expect " + expected + ", actual " + actual;
+    }
+}
+
+let numberOfIterations = 10000;
+
+function testInvokeGetter() {
+    var getter = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").get;
+    return (function() { return getter(); })();
+}
+noInline(testInvokeGetter);
+
+function testInvokeSetter() {
+    var setter = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").set;
+    return (function() { return setter({}); })();
+}
+noInline(testInvokeSetter);
+
+function runTest(testId, test, expectedResult, expectedException) {
+    for (var i = 0; i < numberOfIterations; i++) {
+        var exception;
+        var result;
+        try {
+            result = test({});
+        } catch (e) {
+            exception = "" + e;
+        }
+        shouldEqual(testId, result, expectedResult);
+        shouldEqual(testId, exception, expectedException);
+    }
+}
+
+runTest(10000, testInvokeGetter, undefined, "TypeError: Object.prototype.__proto__ called on null or undefined");
+runTest(10100, testInvokeSetter, undefined, "TypeError: Object.prototype.__proto__ called on null or undefined");

Modified: branches/safari-602-branch/LayoutTests/ChangeLog (207996 => 207997)


--- branches/safari-602-branch/LayoutTests/ChangeLog	2016-10-27 19:38:04 UTC (rev 207996)
+++ branches/safari-602-branch/LayoutTests/ChangeLog	2016-10-27 19:41:43 UTC (rev 207997)
@@ -1,3 +1,27 @@
+2016-10-27  Mark Lam  <[email protected]>
+
+        Merge r207518. rdar://problem/28216050, rdar://problem/28216232
+
+    2016-10-18  Mark Lam  <[email protected]>
+
+            Invoking Object.prototype.__proto__ accessors directly should throw a TypeError.
+            https://bugs.webkit.org/show_bug.cgi?id=154377
+            <rdar://problem/27330808>
+
+            Reviewed by Filip Pizlo and Saam Barati.
+
+            * http/tests/security/xss-DENIED-htmlelelment-with-iframe-proto-expected.txt:
+            * http/tests/security/xss-DENIED-method-with-iframe-proto-expected.txt:
+            * http/tests/security/xss-DENIED-non-shadowable-propterty-with-iframe-proto-expected.txt:
+            * http/tests/security/xss-DENIED-regular-propterty-with-iframe-proto-expected.txt:
+            * http/tests/security/xss-DENIED-regular-propterty-with-iframe-proto.html:
+            * js/dom/activation-proto-expected.txt:
+            * js/dom/script-tests/activation-proto.js:
+            * js/object-literal-shorthand-construction-expected.txt:
+            * js/script-tests/object-literal-shorthand-construction.js:
+            * js/script-tests/sloppy-getter-setter-global-object.js:
+            * js/sloppy-getter-setter-global-object-expected.txt:
+
 2016-10-27  Matthew Hanson  <[email protected]>
 
         Merge r206119. rdar://problem/28964589

Modified: branches/safari-602-branch/LayoutTests/fast/dom/Window/script-tests/window-custom-prototype.js (207996 => 207997)


--- branches/safari-602-branch/LayoutTests/fast/dom/Window/script-tests/window-custom-prototype.js	2016-10-27 19:38:04 UTC (rev 207996)
+++ branches/safari-602-branch/LayoutTests/fast/dom/Window/script-tests/window-custom-prototype.js	2016-10-27 19:41:43 UTC (rev 207997)
@@ -1,18 +1,18 @@
 description("Test what happens when you set the window's prototype to various values.");
 
-var originalWindowPrototype = __proto__;
+var originalWindowPrototype = this.__proto__;
 var chainPointingBackToWindow = { __proto__: window };
 var anotherObject = { };
 
-shouldThrow("__proto__ = window; __proto", "'TypeError: cyclic __proto__ value'");
-shouldThrow("__proto__ = chainPointingBackToWindow; __proto__", "'TypeError: cyclic __proto__ value'");
-shouldBe("__proto__ = 1; __proto__", "originalWindowPrototype");
-shouldBe("__proto__ = 'a string'; __proto__", "originalWindowPrototype");
-shouldBe("__proto__ = anotherObject; __proto__", "anotherObject");
-shouldThrow("anotherObject.__proto__ = window; __proto__", "'TypeError: cyclic __proto__ value'");
-shouldBe("__proto__ = 1; __proto__", "anotherObject");
-shouldBe("__proto__ = 'a string'; __proto__", "anotherObject");
-shouldBe("__proto__ = anotherObject; __proto__", "anotherObject");
-shouldBe("__proto__ = originalWindowPrototype; __proto__", "originalWindowPrototype");
+shouldThrow("this.__proto__ = window; this.__proto__", "'TypeError: cyclic __proto__ value'");
+shouldThrow("this.__proto__ = chainPointingBackToWindow; this.__proto__", "'TypeError: cyclic __proto__ value'");
+shouldBe("this.__proto__ = 1; this.__proto__", "originalWindowPrototype");
+shouldBe("this.__proto__ = 'a string'; this.__proto__", "originalWindowPrototype");
+shouldBe("this.__proto__ = anotherObject; this.__proto__", "anotherObject");
+shouldThrow("anotherObject.__proto__ = window; this.__proto__", "'TypeError: cyclic __proto__ value'");
+shouldBe("this.__proto__ = 1; this.__proto__", "anotherObject");
+shouldBe("this.__proto__ = 'a string'; this.__proto__", "anotherObject");
+shouldBe("this.__proto__ = anotherObject; this.__proto__", "anotherObject");
+shouldBe("this.__proto__ = originalWindowPrototype; this.__proto__", "originalWindowPrototype");
 shouldBe("anotherObject.__proto__ = window; anotherObject.__proto__", "window");
-shouldBe("__proto__ = null; __proto__", "null");
+shouldBe("this.__proto__ = null; this.__proto__", "undefined");

Modified: branches/safari-602-branch/LayoutTests/fast/dom/Window/window-custom-prototype-expected.txt (207996 => 207997)


--- branches/safari-602-branch/LayoutTests/fast/dom/Window/window-custom-prototype-expected.txt	2016-10-27 19:38:04 UTC (rev 207996)
+++ branches/safari-602-branch/LayoutTests/fast/dom/Window/window-custom-prototype-expected.txt	2016-10-27 19:41:43 UTC (rev 207997)
@@ -3,18 +3,18 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS __proto__ = window; __proto threw exception TypeError: cyclic __proto__ value.
-PASS __proto__ = chainPointingBackToWindow; __proto__ threw exception TypeError: cyclic __proto__ value.
-PASS __proto__ = 1; __proto__ is originalWindowPrototype
-PASS __proto__ = 'a string'; __proto__ is originalWindowPrototype
-PASS __proto__ = anotherObject; __proto__ is anotherObject
-PASS anotherObject.__proto__ = window; __proto__ threw exception TypeError: cyclic __proto__ value.
-PASS __proto__ = 1; __proto__ is anotherObject
-PASS __proto__ = 'a string'; __proto__ is anotherObject
-PASS __proto__ = anotherObject; __proto__ is anotherObject
-PASS __proto__ = originalWindowPrototype; __proto__ is originalWindowPrototype
+PASS this.__proto__ = window; this.__proto__ threw exception TypeError: cyclic __proto__ value.
+PASS this.__proto__ = chainPointingBackToWindow; this.__proto__ threw exception TypeError: cyclic __proto__ value.
+PASS this.__proto__ = 1; this.__proto__ is originalWindowPrototype
+PASS this.__proto__ = 'a string'; this.__proto__ is originalWindowPrototype
+PASS this.__proto__ = anotherObject; this.__proto__ is anotherObject
+PASS anotherObject.__proto__ = window; this.__proto__ threw exception TypeError: cyclic __proto__ value.
+PASS this.__proto__ = 1; this.__proto__ is anotherObject
+PASS this.__proto__ = 'a string'; this.__proto__ is anotherObject
+PASS this.__proto__ = anotherObject; this.__proto__ is anotherObject
+PASS this.__proto__ = originalWindowPrototype; this.__proto__ is originalWindowPrototype
 PASS anotherObject.__proto__ = window; anotherObject.__proto__ is window
-PASS __proto__ = null; __proto__ is null
+PASS this.__proto__ = null; this.__proto__ is undefined
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: branches/safari-602-branch/LayoutTests/http/tests/security/xss-DENIED-htmlelelment-with-iframe-proto.html (207996 => 207997)


--- branches/safari-602-branch/LayoutTests/http/tests/security/xss-DENIED-htmlelelment-with-iframe-proto.html	2016-10-27 19:38:04 UTC (rev 207996)
+++ branches/safari-602-branch/LayoutTests/http/tests/security/xss-DENIED-htmlelelment-with-iframe-proto.html	2016-10-27 19:41:43 UTC (rev 207997)
@@ -15,7 +15,7 @@
 targetWindow = frames[0];
 
 window._onload_ = function() {
-  __proto__ = targetWindow;
+  this.__proto__ = targetWindow;
   shouldBeUndefined('targetWindow.myinput');
 }
 </script>

Modified: branches/safari-602-branch/LayoutTests/http/tests/security/xss-DENIED-method-with-iframe-proto.html (207996 => 207997)


--- branches/safari-602-branch/LayoutTests/http/tests/security/xss-DENIED-method-with-iframe-proto.html	2016-10-27 19:38:04 UTC (rev 207996)
+++ branches/safari-602-branch/LayoutTests/http/tests/security/xss-DENIED-method-with-iframe-proto.html	2016-10-27 19:41:43 UTC (rev 207997)
@@ -30,7 +30,7 @@
 window._onload_ = function() {
   originalSetTimeout = setTimeout;
 
-  __proto__ = targetWindow;
+  this.__proto__ = targetWindow;
 
   var needsCheck = false;
   try {

Modified: branches/safari-602-branch/LayoutTests/http/tests/security/xss-DENIED-non-shadowable-propterty-with-iframe-proto.html (207996 => 207997)


--- branches/safari-602-branch/LayoutTests/http/tests/security/xss-DENIED-non-shadowable-propterty-with-iframe-proto.html	2016-10-27 19:38:04 UTC (rev 207996)
+++ branches/safari-602-branch/LayoutTests/http/tests/security/xss-DENIED-non-shadowable-propterty-with-iframe-proto.html	2016-10-27 19:41:43 UTC (rev 207997)
@@ -16,7 +16,7 @@
 window._onload_ = function() {
   originalLocation = location;
 
-  __proto__ = targetWindow;
+  this.__proto__ = targetWindow;
 
   shouldBeTrue('location === originalLocation');
   shouldBeTrue('this.location === originalLocation');

Modified: branches/safari-602-branch/LayoutTests/http/tests/security/xss-DENIED-regular-propterty-with-iframe-proto.html (207996 => 207997)


--- branches/safari-602-branch/LayoutTests/http/tests/security/xss-DENIED-regular-propterty-with-iframe-proto.html	2016-10-27 19:38:04 UTC (rev 207996)
+++ branches/safari-602-branch/LayoutTests/http/tests/security/xss-DENIED-regular-propterty-with-iframe-proto.html	2016-10-27 19:41:43 UTC (rev 207997)
@@ -16,7 +16,7 @@
 window._onload_ = function() {
   originalInnerHeight = innerHeight;
 
-  __proto__ = targetWindow;
+  this.__proto__ = targetWindow;
 
   shouldBeTrue('innerHeight === originalInnerHeight');
   shouldBeTrue('this.innerHeight === originalInnerHeight');

Modified: branches/safari-602-branch/LayoutTests/js/dom/activation-proto-expected.txt (207996 => 207997)


--- branches/safari-602-branch/LayoutTests/js/dom/activation-proto-expected.txt	2016-10-27 19:38:04 UTC (rev 207996)
+++ branches/safari-602-branch/LayoutTests/js/dom/activation-proto-expected.txt	2016-10-27 19:41:43 UTC (rev 207997)
@@ -3,7 +3,7 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS (function() { __proto__.testVariable = 'found'; return window.testVariable; })() is 'found'
+PASS (function() { this.__proto__.testVariable = 'found'; return window.testVariable; })() is 'found'
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: branches/safari-602-branch/LayoutTests/js/dom/script-tests/activation-proto.js (207996 => 207997)


--- branches/safari-602-branch/LayoutTests/js/dom/script-tests/activation-proto.js	2016-10-27 19:38:04 UTC (rev 207996)
+++ branches/safari-602-branch/LayoutTests/js/dom/script-tests/activation-proto.js	2016-10-27 19:41:43 UTC (rev 207997)
@@ -4,4 +4,4 @@
 
 );
 
-shouldBe("(function() { __proto__.testVariable = 'found'; return window.testVariable; })()", "'found'");
+shouldBe("(function() { this.__proto__.testVariable = 'found'; return window.testVariable; })()", "'found'");

Modified: branches/safari-602-branch/LayoutTests/js/object-literal-shorthand-construction-expected.txt (207996 => 207997)


--- branches/safari-602-branch/LayoutTests/js/object-literal-shorthand-construction-expected.txt	2016-10-27 19:38:04 UTC (rev 207996)
+++ branches/safari-602-branch/LayoutTests/js/object-literal-shorthand-construction-expected.txt	2016-10-27 19:41:43 UTC (rev 207997)
@@ -61,9 +61,9 @@
 PASS !!Object.getOwnPropertyDescriptor({set x(value){}}, 'x').set is true
 PASS !!Object.getOwnPropertyDescriptor({set 'x'(value){}}, 'x').set is true
 PASS !!Object.getOwnPropertyDescriptor({set 42(value){}}, '42').set is true
-PASS __proto__ = []; ({__proto__: __proto__}) instanceof Array is true
-PASS __proto__ = []; ({__proto__}) instanceof Array is false
-PASS __proto__ = []; ({__proto__}).__proto__ instanceof Array is true
+PASS this.__proto__ = []; ({__proto__: __proto__}) instanceof Array threw exception TypeError: Object.prototype.__proto__ called on null or undefined.
+PASS this.__proto__ = []; ({__proto__}) instanceof Array threw exception TypeError: Object.prototype.__proto__ called on null or undefined.
+PASS this.__proto__ = []; ({__proto__}).__proto__ instanceof Array threw exception TypeError: Object.prototype.__proto__ called on null or undefined.
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: branches/safari-602-branch/LayoutTests/js/script-tests/object-literal-shorthand-construction.js (207996 => 207997)


--- branches/safari-602-branch/LayoutTests/js/script-tests/object-literal-shorthand-construction.js	2016-10-27 19:38:04 UTC (rev 207996)
+++ branches/safari-602-branch/LayoutTests/js/script-tests/object-literal-shorthand-construction.js	2016-10-27 19:41:43 UTC (rev 207997)
@@ -110,6 +110,6 @@
 shouldBeTrue("!!Object.getOwnPropertyDescriptor({set 42(value){}}, '42').set");
 
 // __proto__ shorthand should be not modify the prototype.
-shouldBeTrue("__proto__ = []; ({__proto__: __proto__}) instanceof Array");
-shouldBeFalse("__proto__ = []; ({__proto__}) instanceof Array");
-shouldBeTrue("__proto__ = []; ({__proto__}).__proto__ instanceof Array");
+shouldThrow("this.__proto__ = []; ({__proto__: __proto__}) instanceof Array", '"TypeError: Object.prototype.__proto__ called on null or undefined"');
+shouldThrow("this.__proto__ = []; ({__proto__}) instanceof Array", '"TypeError: Object.prototype.__proto__ called on null or undefined"');
+shouldThrow("this.__proto__ = []; ({__proto__}).__proto__ instanceof Array", '"TypeError: Object.prototype.__proto__ called on null or undefined"');

Modified: branches/safari-602-branch/LayoutTests/js/script-tests/sloppy-getter-setter-global-object.js (207996 => 207997)


--- branches/safari-602-branch/LayoutTests/js/script-tests/sloppy-getter-setter-global-object.js	2016-10-27 19:38:04 UTC (rev 207996)
+++ branches/safari-602-branch/LayoutTests/js/script-tests/sloppy-getter-setter-global-object.js	2016-10-27 19:41:43 UTC (rev 207997)
@@ -25,12 +25,12 @@
 shouldNotThrow("Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').get()");
 shouldNotThrow("Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').set(['foo'])");
 
-shouldThrow("(0,Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').get)()", "\"TypeError: Can't convert undefined or null to object\"");
-shouldThrow("(0,Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').set)(['foo'])", "\"TypeError: Can't convert undefined or null to object\"");
+shouldThrow("(0,Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').get)()", "\"TypeError: Object.prototype.__proto__ called on null or undefined\"");
+shouldThrow("(0,Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').set)(['foo'])", "\"TypeError: Object.prototype.__proto__ called on null or undefined\"");
 
 
 var top_level_sloppy_getter = Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').get;
-shouldNotThrow("top_level_sloppy_getter();");
+shouldThrow("top_level_sloppy_getter();", "\"TypeError: Object.prototype.__proto__ called on null or undefined\"");
 
 var top_level_sloppy_setter = Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').set;
-shouldNotThrow("top_level_sloppy_setter(['foo']);");
+shouldThrow("top_level_sloppy_setter(['foo']);", "\"TypeError: Object.prototype.__proto__ called on null or undefined\"");

Modified: branches/safari-602-branch/LayoutTests/js/sloppy-getter-setter-global-object-expected.txt (207996 => 207997)


--- branches/safari-602-branch/LayoutTests/js/sloppy-getter-setter-global-object-expected.txt	2016-10-27 19:38:04 UTC (rev 207996)
+++ branches/safari-602-branch/LayoutTests/js/sloppy-getter-setter-global-object-expected.txt	2016-10-27 19:41:43 UTC (rev 207997)
@@ -8,10 +8,10 @@
 PASS Object.prototype.valueOf.call(null); threw exception TypeError: null is not an object (evaluating 'Object.prototype.valueOf.call(null)').
 PASS Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').get() did not throw exception.
 PASS Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').set(['foo']) did not throw exception.
-PASS (0,Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').get)() threw exception TypeError: Can't convert undefined or null to object.
-PASS (0,Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').set)(['foo']) threw exception TypeError: Can't convert undefined or null to object.
-PASS top_level_sloppy_getter(); did not throw exception.
-PASS top_level_sloppy_setter(['foo']); did not throw exception.
+PASS (0,Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').get)() threw exception TypeError: Object.prototype.__proto__ called on null or undefined.
+PASS (0,Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').set)(['foo']) threw exception TypeError: Object.prototype.__proto__ called on null or undefined.
+PASS top_level_sloppy_getter(); threw exception TypeError: Object.prototype.__proto__ called on null or undefined.
+PASS top_level_sloppy_setter(['foo']); threw exception TypeError: Object.prototype.__proto__ called on null or undefined.
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: branches/safari-602-branch/Source/_javascript_Core/ChangeLog (207996 => 207997)


--- branches/safari-602-branch/Source/_javascript_Core/ChangeLog	2016-10-27 19:38:04 UTC (rev 207996)
+++ branches/safari-602-branch/Source/_javascript_Core/ChangeLog	2016-10-27 19:41:43 UTC (rev 207997)
@@ -1,3 +1,43 @@
+2016-10-27  Mark Lam  <[email protected]>
+
+        Merge r207518. rdar://problem/28216050, rdar://problem/28216232
+
+    2016-10-18  Mark Lam  <[email protected]>
+
+            Invoking Object.prototype.__proto__ accessors directly should throw a TypeError.
+            https://bugs.webkit.org/show_bug.cgi?id=154377
+            <rdar://problem/27330808>
+
+            Reviewed by Filip Pizlo and Saam Barati.
+
+            In a scenario where we cache the __proto__ accessors in global variables, and
+            later explicitly invoke those accessors as functions, the spec for Function Calls
+            (see https://tc39.github.io/ecma262/#sec-function-calls) states that the function
+            ref value is of type Reference, and base of ref is an Environment Record.  Then,
+            it follows that the thisValue should be set to refEnv.WithBaseObject()
+            (see section 4.b.ii of 12.3.4.1 at
+            https://tc39.github.io/ecma262/#sec-function-calls-runtime-semantics-evaluation).
+
+            refEnv in this case is the environment record that the cached accessors were
+            found in i.e. the global object.  The WithBaseObject() of the global object is
+            undefined (see details about WithBaseObject at
+            https://tc39.github.io/ecma262/#sec-environment-records).
+
+            Hence, the __proto__ accessors should see a thisValue of undefined, and throw
+            TypeErrors.  See https://tc39.github.io/ecma262/#sec-get-object.prototype.__proto__,
+            https://tc39.github.io/ecma262/#sec-set-object.prototype.__proto__,
+            https://tc39.github.io/ecma262/#sec-toobject, and
+            https://tc39.github.io/ecma262/#sec-requireobjectcoercible.
+
+            In JSC's implementation, the callee needs to do a ToThis operation on the
+            incoming "this" argument in order to get the specified thisValue.  The
+            implementations of the __proto__ accessors were not doing this correctly.  This
+            has now been fixed.
+
+            * runtime/JSGlobalObjectFunctions.cpp:
+            (JSC::globalFuncProtoGetter):
+            (JSC::globalFuncProtoSetter):
+
 2016-10-24  Matthew Hanson  <[email protected]>
 
         Merge r207229. rdar://problem/28718809

Modified: branches/safari-602-branch/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp (207996 => 207997)


--- branches/safari-602-branch/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp	2016-10-27 19:38:04 UTC (rev 207996)
+++ branches/safari-602-branch/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp	2016-10-27 19:41:43 UTC (rev 207997)
@@ -53,6 +53,8 @@
 
 namespace JSC {
 
+static const char* const ObjectProtoCalledOnNullOrUndefinedError = "Object.prototype.__proto__ called on null or undefined";
+
 template<typename CallbackWhenNoException>
 static ALWAYS_INLINE typename std::result_of<CallbackWhenNoException(JSString::SafeView&)>::type toSafeView(ExecState* exec, JSValue value, CallbackWhenNoException callback)
 {
@@ -887,11 +889,11 @@
 
 EncodedJSValue JSC_HOST_CALL globalFuncProtoGetter(ExecState* exec)
 {
-    if (exec->thisValue().isUndefinedOrNull()) 
-        return throwVMTypeError(exec, ASCIILiteral("Can't convert undefined or null to object"));
+    JSValue thisValue = exec->thisValue().toThis(exec, StrictMode);
+    if (thisValue.isUndefinedOrNull())
+        return throwVMTypeError(exec, ASCIILiteral(ObjectProtoCalledOnNullOrUndefinedError));
 
-    JSObject* thisObject = jsDynamicCast<JSObject*>(exec->thisValue().toThis(exec, NotStrictMode));
-
+    JSObject* thisObject = jsDynamicCast<JSObject*>(thisValue);
     if (!thisObject) {
         JSObject* prototype = exec->thisValue().synthesizePrototype(exec);
         if (UNLIKELY(!prototype))
@@ -944,12 +946,13 @@
 
 EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState* exec)
 {
-    if (exec->thisValue().isUndefinedOrNull()) 
-        return throwVMTypeError(exec, ASCIILiteral("Can't convert undefined or null to object"));
+    JSValue thisValue = exec->thisValue().toThis(exec, StrictMode);
+    if (thisValue.isUndefinedOrNull())
+        return throwVMTypeError(exec, ASCIILiteral(ObjectProtoCalledOnNullOrUndefinedError));
 
     JSValue value = exec->argument(0);
 
-    JSObject* thisObject = jsDynamicCast<JSObject*>(exec->thisValue().toThis(exec, NotStrictMode));
+    JSObject* thisObject = jsDynamicCast<JSObject*>(thisValue);
 
     // Setting __proto__ of a primitive should have no effect.
     if (!thisObject)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to