Title: [203101] trunk
Revision
203101
Author
[email protected]
Date
2016-07-11 17:57:35 -0700 (Mon, 11 Jul 2016)

Log Message

[JSC] Array.from() and Array.of() try to build objects even if "this" is not a constructor
https://bugs.webkit.org/show_bug.cgi?id=159604

Reviewed by Yusuke Suzuki.

Source/_javascript_Core:

The spec says IsConstructor(), we were just checking if "this"
is any function.

* builtins/ArrayConstructor.js:
(of):
(from):

LayoutTests:

* js/array-from-expected.txt:
* js/array-of-expected.txt:
* js/script-tests/array-from.js:
* js/script-tests/array-of.js:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (203100 => 203101)


--- trunk/LayoutTests/ChangeLog	2016-07-12 00:16:19 UTC (rev 203100)
+++ trunk/LayoutTests/ChangeLog	2016-07-12 00:57:35 UTC (rev 203101)
@@ -1,3 +1,15 @@
+2016-07-11  Benjamin Poulain  <[email protected]>
+
+        [JSC] Array.from() and Array.of() try to build objects even if "this" is not a constructor
+        https://bugs.webkit.org/show_bug.cgi?id=159604
+
+        Reviewed by Yusuke Suzuki.
+
+        * js/array-from-expected.txt:
+        * js/array-of-expected.txt:
+        * js/script-tests/array-from.js:
+        * js/script-tests/array-of.js:
+
 2016-07-11  Simon Fraser  <[email protected]>
 
         Deleting in a text input inside an iframe causes the page to scroll incorrectly

Modified: trunk/LayoutTests/js/array-from-expected.txt (203100 => 203101)


--- trunk/LayoutTests/js/array-from-expected.txt	2016-07-12 00:16:19 UTC (rev 203100)
+++ trunk/LayoutTests/js/array-from-expected.txt	2016-07-12 00:57:35 UTC (rev 203101)
@@ -67,6 +67,31 @@
 Construction using Set object
 -------
 PASS Array.from(set) is ['zero', 'one', 'two']
+
+"this" is a constructor
+-------
+PASS Array.from.call(CustomConstructor, ['WebKit']).constructor is CustomConstructor
+PASS Object.getPrototypeOf(Array.from.call(CustomConstructor, ['WebKit'])) is CustomConstructor.prototype
+PASS Array.from.call(nonConstructor, ['WebKit']).length is 1
+PASS Array.from.call(nonConstructor, ['WebKit'])[0] is "WebKit"
+PASS Array.from.call(CustomConstructor, nonIterable).constructor is CustomConstructor
+PASS Object.getPrototypeOf(Array.from.call(CustomConstructor, nonIterable)) is CustomConstructor.prototype
+PASS Array.from.call(nonConstructor, nonIterable).length is 2
+PASS Array.from.call(nonConstructor, nonIterable)[0] is "one"
+PASS Array.from.call(nonConstructor, nonIterable)[1] is 2
+
+"this" is not a constructor
+-------
+PASS Array.from.call(nonConstructor, ['WebKit']).constructor is Array
+PASS Object.getPrototypeOf(Array.from.call(nonConstructor, ['WebKit'])) is Array.prototype
+PASS Array.from.call(nonConstructor, ['WebKit']).length is 1
+PASS Array.from.call(nonConstructor, ['WebKit'])[0] is "WebKit"
+PASS nonConstructorWasCalled is false
+PASS Array.from.call(nonConstructor, nonIterable).constructor is Array
+PASS Object.getPrototypeOf(Array.from.call(nonConstructor, nonIterable)) is Array.prototype
+PASS Array.from.call(nonConstructor, nonIterable).length is 2
+PASS Array.from.call(nonConstructor, nonIterable)[0] is "one"
+PASS Array.from.call(nonConstructor, nonIterable)[1] is 2
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/js/array-of-expected.txt (203100 => 203101)


--- trunk/LayoutTests/js/array-of-expected.txt	2016-07-12 00:16:19 UTC (rev 203100)
+++ trunk/LayoutTests/js/array-of-expected.txt	2016-07-12 00:57:35 UTC (rev 203101)
@@ -17,9 +17,16 @@
 PASS x[1].length is 5
 Check that a setter isn't called.
 PASS Array.of(1, 2, 3) did not throw exception.
+"this" is a constructor
 PASS Array.of.call(Foo, 'a', 'b', 'c') instanceof Foo is true
 PASS Array.of.call(Foo, 'a', 'b', 'c').givenLength is 3
 PASS var foo = Array.of.call(Foo, 'a', 'b', 'c'); [foo.length, foo[0], foo[1], foo[2]] is [3, 'a', 'b', 'c']
+"this" is not a constructor
+PASS Array.of.call(nonConstructor, Foo).constructor is Array
+PASS Object.getPrototypeOf(Array.of.call(nonConstructor, Foo)) is Array.prototype
+PASS Array.of.call(nonConstructor, Foo).length is 1
+PASS Array.of.call(nonConstructor, Foo)[0] is Foo
+PASS nonConstructorWasCalled is false
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/js/script-tests/array-from.js (203100 => 203101)


--- trunk/LayoutTests/js/script-tests/array-from.js	2016-07-12 00:16:19 UTC (rev 203100)
+++ trunk/LayoutTests/js/script-tests/array-from.js	2016-07-12 00:57:35 UTC (rev 203101)
@@ -100,3 +100,47 @@
 set.add("one");
 set.add("two");
 shouldBe("Array.from(set)", "['zero', 'one', 'two']");
+
+section("\"this\" is a constructor");
+var CustomConstructor = function (length) { this.givenLength = length; };
+shouldBe("Array.from.call(CustomConstructor, ['WebKit']).constructor", "CustomConstructor");
+shouldBe("Object.getPrototypeOf(Array.from.call(CustomConstructor, ['WebKit']))", "CustomConstructor.prototype");
+shouldBe("Array.from.call(nonConstructor, ['WebKit']).length", "1");
+shouldBeEqualToString("Array.from.call(nonConstructor, ['WebKit'])[0]", "WebKit");
+
+var nonIterable = {
+    get 0() {
+        return "one";
+    },
+    get 1() {
+        return 2;
+    },
+    get 2() {
+        throw "ERROR: this should never be called";
+    },
+    get length() {
+        return 2;
+    }
+};
+
+shouldBe("Array.from.call(CustomConstructor, nonIterable).constructor", "CustomConstructor");
+shouldBe("Object.getPrototypeOf(Array.from.call(CustomConstructor, nonIterable))", "CustomConstructor.prototype");
+shouldBe("Array.from.call(nonConstructor, nonIterable).length", "2");
+shouldBeEqualToString("Array.from.call(nonConstructor, nonIterable)[0]", "one");
+shouldBe("Array.from.call(nonConstructor, nonIterable)[1]", "2");
+
+
+section("\"this\" is not a constructor");
+var nonConstructorWasCalled = false;
+var nonConstructor = () => { nonConstructorWasCalled = true; };
+shouldBe("Array.from.call(nonConstructor, ['WebKit']).constructor", "Array");
+shouldBe("Object.getPrototypeOf(Array.from.call(nonConstructor, ['WebKit']))", "Array.prototype");
+shouldBe("Array.from.call(nonConstructor, ['WebKit']).length", "1");
+shouldBeEqualToString("Array.from.call(nonConstructor, ['WebKit'])[0]", "WebKit");
+shouldBeFalse("nonConstructorWasCalled");
+
+shouldBe("Array.from.call(nonConstructor, nonIterable).constructor", "Array");
+shouldBe("Object.getPrototypeOf(Array.from.call(nonConstructor, nonIterable))", "Array.prototype");
+shouldBe("Array.from.call(nonConstructor, nonIterable).length", "2");
+shouldBeEqualToString("Array.from.call(nonConstructor, nonIterable)[0]", "one");
+shouldBe("Array.from.call(nonConstructor, nonIterable)[1]", "2");

Modified: trunk/LayoutTests/js/script-tests/array-of.js (203100 => 203101)


--- trunk/LayoutTests/js/script-tests/array-of.js	2016-07-12 00:16:19 UTC (rev 203100)
+++ trunk/LayoutTests/js/script-tests/array-of.js	2016-07-12 00:57:35 UTC (rev 203101)
@@ -25,7 +25,17 @@
 
 shouldNotThrow("Array.of(1, 2, 3)");
 
+debug("\"this\" is a constructor");
 var Foo = function FooBar(length) { this.givenLength = length; };
-shouldBeTrue("Array.of.call(Foo, 'a', 'b', 'c') instanceof Foo")
+shouldBeTrue("Array.of.call(Foo, 'a', 'b', 'c') instanceof Foo");
 shouldBe("Array.of.call(Foo, 'a', 'b', 'c').givenLength", "3");
 shouldBe("var foo = Array.of.call(Foo, 'a', 'b', 'c'); [foo.length, foo[0], foo[1], foo[2]]", "[3, 'a', 'b', 'c']");
+
+debug("\"this\" is not a constructor");
+var nonConstructorWasCalled = false;
+var nonConstructor = () => { nonConstructorWasCalled = true; };
+shouldBe("Array.of.call(nonConstructor, Foo).constructor", "Array");
+shouldBe("Object.getPrototypeOf(Array.of.call(nonConstructor, Foo))", "Array.prototype");
+shouldBe("Array.of.call(nonConstructor, Foo).length", "1");
+shouldBe("Array.of.call(nonConstructor, Foo)[0]", "Foo");
+shouldBeFalse("nonConstructorWasCalled");

Modified: trunk/Source/_javascript_Core/ChangeLog (203100 => 203101)


--- trunk/Source/_javascript_Core/ChangeLog	2016-07-12 00:16:19 UTC (rev 203100)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-07-12 00:57:35 UTC (rev 203101)
@@ -1,3 +1,17 @@
+2016-07-11  Benjamin Poulain  <[email protected]>
+
+        [JSC] Array.from() and Array.of() try to build objects even if "this" is not a constructor
+        https://bugs.webkit.org/show_bug.cgi?id=159604
+
+        Reviewed by Yusuke Suzuki.
+
+        The spec says IsConstructor(), we were just checking if "this"
+        is any function.
+
+        * builtins/ArrayConstructor.js:
+        (of):
+        (from):
+
 2016-07-11  Keith Miller  <[email protected]>
 
         defineProperty on a index of a TypedArray should throw if configurable

Modified: trunk/Source/_javascript_Core/builtins/ArrayConstructor.js (203100 => 203101)


--- trunk/Source/_javascript_Core/builtins/ArrayConstructor.js	2016-07-12 00:16:19 UTC (rev 203100)
+++ trunk/Source/_javascript_Core/builtins/ArrayConstructor.js	2016-07-12 00:57:35 UTC (rev 203101)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015, 2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -28,8 +28,7 @@
     "use strict";
 
     var length = arguments.length;
-    // TODO: Need isConstructor(this) instead of typeof "function" check.
-    var array = typeof this === 'function' ? new this(length) : new @Array(length);
+    var array = @isConstructor(this) ? new this(length) : new @Array(length);
     for (var k = 0; k < length; ++k)
         @putByValDirect(array, k, arguments[k]);
     array.length = length;
@@ -62,8 +61,7 @@
         if (typeof iteratorMethod !== "function")
             throw new @TypeError("Array.from requires that the property of the first argument, items[Symbol.iterator], when exists, be a function");
 
-        // TODO: Need isConstructor(thisObj) instead of typeof "function" check.
-        var result = (typeof thisObj === "function") ? @Object(new thisObj()) : [];
+        var result = @isConstructor(thisObj) ? new thisObj() : [];
 
         var k = 0;
         var iterator = iteratorMethod.@call(items);
@@ -89,8 +87,7 @@
     var arrayLike = @Object(items);
     var arrayLikeLength = @toLength(arrayLike.length);
 
-    // TODO: Need isConstructor(thisObj) instead of typeof "function" check.
-    var result = (typeof thisObj === "function") ? @Object(new thisObj(arrayLikeLength)) : new @Array(arrayLikeLength);
+    var result = @isConstructor(thisObj) ? new thisObj(arrayLikeLength) : new @Array(arrayLikeLength);
 
     var k = 0;
     while (k < arrayLikeLength) {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to