Merge V8 5.2.361.47 DO NOT MERGE
https://chromium.googlesource.com/v8/v8/+/5.2.361.47
FPIIM-449
Change-Id: Ibec421b85a9b88cb3a432ada642e469fe7e78346
(cherry picked from commit bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8)
diff --git a/test/mjsunit/arguments.js b/test/mjsunit/arguments.js
index 26eb389..97ec7cc 100644
--- a/test/mjsunit/arguments.js
+++ b/test/mjsunit/arguments.js
@@ -204,3 +204,70 @@
}
assertTrue(%HasSloppyArgumentsElements(a));
})();
+
+(function testDeleteArguments() {
+ function f() { return arguments };
+ var args = f(1, 2);
+ assertEquals(1, args[0]);
+ assertEquals(2, args[1]);
+ assertEquals(2, args.length);
+
+ delete args[0];
+ assertEquals(undefined, args[0]);
+ assertEquals(2, args[1]);
+ assertEquals(2, args.length);
+
+ delete args[1];
+ assertEquals(undefined, args[0]);
+ assertEquals(undefined, args[1]);
+ assertEquals(2, args.length);
+})();
+
+(function testDeleteFastSloppyArguments() {
+ function f(a) { return arguments };
+ var args = f(1, 2);
+ assertEquals(1, args[0]);
+ assertEquals(2, args[1]);
+ assertEquals(2, args.length);
+
+ delete args[0];
+ assertEquals(undefined, args[0]);
+ assertEquals(2, args[1]);
+ assertEquals(2, args.length);
+
+ delete args[1];
+ assertEquals(undefined, args[0]);
+ assertEquals(undefined, args[1]);
+ assertEquals(2, args.length);
+})();
+
+(function testDeleteSlowSloppyArguments() {
+ var key = 10000;
+ function f(a) {
+ arguments[key] = key;
+ return arguments
+ };
+ var args = f(1, 2);
+ assertEquals(1, args[0]);
+ assertEquals(2, args[1]);
+ assertEquals(key, args[key]);
+ assertEquals(2, args.length);
+
+ delete args[0];
+ assertEquals(undefined, args[0]);
+ assertEquals(2, args[1]);
+ assertEquals(key, args[key]);
+ assertEquals(2, args.length);
+
+ delete args[1];
+ assertEquals(undefined, args[0]);
+ assertEquals(undefined, args[1]);
+ assertEquals(key, args[key]);
+ assertEquals(2, args.length);
+
+ delete args[key];
+ assertEquals(undefined, args[0]);
+ assertEquals(undefined, args[1]);
+ assertEquals(undefined, args[key]);
+ assertEquals(2, args.length);
+})();
diff --git a/test/mjsunit/array-push.js b/test/mjsunit/array-push.js
index c87fd12..ece3319 100644
--- a/test/mjsunit/array-push.js
+++ b/test/mjsunit/array-push.js
@@ -146,3 +146,16 @@
f(a, {});
assertEquals(10, a.f());
})();
+
+
+(function testDoubleArrayPush() {
+ var a = [];
+ var max = 1000;
+ for (var i = 0; i < max; i++) {
+ a.push(i + 0.1);
+ }
+ assertEquals(max, a.length);
+ for (var i = 0; i < max; i++) {
+ assertEquals(i+0.1, a[i]);
+ }
+})();
diff --git a/test/mjsunit/array-push7.js b/test/mjsunit/array-push7.js
deleted file mode 100644
index 68c3a2a..0000000
--- a/test/mjsunit/array-push7.js
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-object-observe
-// Flags: --allow-natives-syntax
-
-var v = 0;
-
-function push_wrapper(array, value) {
- array.push(value);
-}
-function pop_wrapper(array) {
- return array.pop();
-}
-
-// Test that Object.observe() notification events are properly sent from
-// Array.push() and Array.pop() both from optimized and un-optimized code.
-var array = [];
-
-function somethingChanged(changes) {
- v++;
-}
-
-Object.observe(array, somethingChanged);
-push_wrapper(array, 1);
-%RunMicrotasks();
-assertEquals(1, array.length);
-assertEquals(1, v);
-push_wrapper(array, 1);
-%RunMicrotasks();
-assertEquals(2, array.length);
-assertEquals(2, v);
-%OptimizeFunctionOnNextCall(push_wrapper);
-push_wrapper(array, 1);
-%RunMicrotasks();
-assertEquals(3, array.length);
-assertEquals(3, v);
-push_wrapper(array, 1);
-%RunMicrotasks();
-assertEquals(4, array.length);
-assertEquals(4, v);
-
-pop_wrapper(array);
-%RunMicrotasks();
-assertEquals(3, array.length);
-assertEquals(5, v);
-pop_wrapper(array);
-%RunMicrotasks();
-assertEquals(2, array.length);
-assertEquals(6, v);
-%OptimizeFunctionOnNextCall(pop_wrapper);
-pop_wrapper(array);
-%RunMicrotasks();
-assertEquals(1, array.length);
-assertEquals(7, v);
-pop_wrapper(array);
-%RunMicrotasks();
-assertEquals(0, array.length);
-assertEquals(8, v);
diff --git a/test/mjsunit/array-slice.js b/test/mjsunit/array-slice.js
index ae0e3bc..b017dd5 100644
--- a/test/mjsunit/array-slice.js
+++ b/test/mjsunit/array-slice.js
@@ -228,6 +228,7 @@
func([]);
func(['a'], 'a');
func(['a', 1], 'a', 1);
+ func(['a', 1, 2, 3, 4, 5], 'a', 1, 2, 3, 4, 5);
func(['a', 1, undefined], 'a', 1, undefined);
func(['a', 1, undefined, void(0)], 'a', 1, undefined, void(0));
})();
diff --git a/test/mjsunit/array-splice.js b/test/mjsunit/array-splice.js
index 744e954..75ff2d1 100644
--- a/test/mjsunit/array-splice.js
+++ b/test/mjsunit/array-splice.js
@@ -300,6 +300,55 @@
}
})();
+// Check the behaviour when approaching maximal values for length.
+(function() {
+ for (var i = 0; i < 7; i++) {
+ try {
+ new Array(Math.pow(2, 32) - 3).splice(-1, 0, 1, 2, 3, 4, 5);
+ throw 'Should have thrown RangeError';
+ } catch (e) {
+ assertTrue(e instanceof RangeError);
+ }
+
+ // Check smi boundary
+ var bigNum = (1 << 30) - 3;
+ var array = new Array(bigNum);
+ array.splice(-1, 0, 1, 2, 3, 4, 5, 6, 7);
+ assertEquals(bigNum + 7, array.length);
+ }
+})();
+
+(function() {
+ for (var i = 0; i < 7; i++) {
+ var a = [7, 8, 9];
+ a.splice(0, 0, 1, 2, 3, 4, 5, 6);
+ assertEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], a);
+ assertFalse(a.hasOwnProperty(10), "a.hasOwnProperty(10)");
+ assertEquals(undefined, a[10]);
+ }
+})();
+
+(function testSpliceDeleteDouble() {
+ var a = [1.1, 1.2, 1.3, 1.4];
+ a.splice(2, 1)
+ assertEquals([1.1, 1.2, 1.4], a);
+})();
+
+// Past this point the ArrayProtector is invalidated since we modify the
+// Array.prototype.
+
+// Check the case of JS builtin .splice()
+(function() {
+ for (var i = 0; i < 7; i++) {
+ var array = [1, 2, 3, 4];
+ Array.prototype[3] = 'foo'; // To force JS builtin.
+
+ var spliced = array.splice();
+
+ assertEquals([], spliced);
+ assertEquals([1, 2, 3, 4], array);
+ }
+})();
// Now check the case with array of holes and some elements on prototype.
(function() {
@@ -350,7 +399,6 @@
}
})();
-
// Now check the case with array of holes and some elements on prototype.
(function() {
var len = 9;
@@ -397,46 +445,3 @@
"array.hasOwnProperty(Math.pow(2, 32) - 2)");
}
})();
-
-
-// Check the case of JS builtin .splice()
-(function() {
- for (var i = 0; i < 7; i++) {
- var array = [1, 2, 3, 4];
- Array.prototype[3] = 'foo'; // To force JS builtin.
-
- var spliced = array.splice();
-
- assertEquals([], spliced);
- assertEquals([1, 2, 3, 4], array);
- }
-})();
-
-
-// Check the behaviour when approaching maximal values for length.
-(function() {
- for (var i = 0; i < 7; i++) {
- try {
- new Array(Math.pow(2, 32) - 3).splice(-1, 0, 1, 2, 3, 4, 5);
- throw 'Should have thrown RangeError';
- } catch (e) {
- assertTrue(e instanceof RangeError);
- }
-
- // Check smi boundary
- var bigNum = (1 << 30) - 3;
- var array = new Array(bigNum);
- array.splice(-1, 0, 1, 2, 3, 4, 5, 6, 7);
- assertEquals(bigNum + 7, array.length);
- }
-})();
-
-(function() {
- for (var i = 0; i < 7; i++) {
- var a = [7, 8, 9];
- a.splice(0, 0, 1, 2, 3, 4, 5, 6);
- assertEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], a);
- assertFalse(a.hasOwnProperty(10), "a.hasOwnProperty(10)");
- assertEquals(undefined, a[10]);
- }
-})();
diff --git a/test/mjsunit/compiler/escape-analysis-1.js b/test/mjsunit/compiler/escape-analysis-1.js
index b8c6644..f05040b 100644
--- a/test/mjsunit/compiler/escape-analysis-1.js
+++ b/test/mjsunit/compiler/escape-analysis-1.js
@@ -26,7 +26,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax --turbo-escape
-//
function f(a) {
"use strict";
diff --git a/test/mjsunit/compiler/escape-analysis-10.js b/test/mjsunit/compiler/escape-analysis-10.js
index c53cf4d..4f06d57 100644
--- a/test/mjsunit/compiler/escape-analysis-10.js
+++ b/test/mjsunit/compiler/escape-analysis-10.js
@@ -26,6 +26,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax --turbo-escape
+
(function() {
"use strict";
function f() {
diff --git a/test/mjsunit/compiler/escape-analysis-2.js b/test/mjsunit/compiler/escape-analysis-2.js
index d116e9a..49f440e 100644
--- a/test/mjsunit/compiler/escape-analysis-2.js
+++ b/test/mjsunit/compiler/escape-analysis-2.js
@@ -26,7 +26,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax --turbo-escape
-//
function f(a) {
"use strict";
diff --git a/test/mjsunit/compiler/escape-analysis-3.js b/test/mjsunit/compiler/escape-analysis-3.js
index d1ebc9b..b92d1c3 100644
--- a/test/mjsunit/compiler/escape-analysis-3.js
+++ b/test/mjsunit/compiler/escape-analysis-3.js
@@ -26,7 +26,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax --turbo-escape
-//
function f(a) {
"use strict";
diff --git a/test/mjsunit/compiler/escape-analysis-4.js b/test/mjsunit/compiler/escape-analysis-4.js
index d9fdccc..ef9f95f 100644
--- a/test/mjsunit/compiler/escape-analysis-4.js
+++ b/test/mjsunit/compiler/escape-analysis-4.js
@@ -26,7 +26,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax --turbo-escape
-//
function f(a) {
"use strict";
diff --git a/test/mjsunit/compiler/escape-analysis-5.js b/test/mjsunit/compiler/escape-analysis-5.js
index cfaf81d..54b5e82 100644
--- a/test/mjsunit/compiler/escape-analysis-5.js
+++ b/test/mjsunit/compiler/escape-analysis-5.js
@@ -26,7 +26,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax --turbo-escape
-//
function f(h) {
"use strict";
diff --git a/test/mjsunit/compiler/escape-analysis-6.js b/test/mjsunit/compiler/escape-analysis-6.js
index 6143cfb..c36e7d9 100644
--- a/test/mjsunit/compiler/escape-analysis-6.js
+++ b/test/mjsunit/compiler/escape-analysis-6.js
@@ -26,7 +26,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax --turbo-escape
-//
function f(a) {
"use strict";
diff --git a/test/mjsunit/compiler/escape-analysis-7.js b/test/mjsunit/compiler/escape-analysis-7.js
index 16bc71c..cfa30cb 100644
--- a/test/mjsunit/compiler/escape-analysis-7.js
+++ b/test/mjsunit/compiler/escape-analysis-7.js
@@ -26,7 +26,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax --turbo-escape
-//
function f() {
this.x=0;
diff --git a/test/mjsunit/compiler/escape-analysis-8.js b/test/mjsunit/compiler/escape-analysis-8.js
index bc5b1d9..d9c6d25 100644
--- a/test/mjsunit/compiler/escape-analysis-8.js
+++ b/test/mjsunit/compiler/escape-analysis-8.js
@@ -26,7 +26,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax --turbo-escape
-//
function f(a) {
this.x=a;
diff --git a/test/mjsunit/compiler/escape-analysis-9.js b/test/mjsunit/compiler/escape-analysis-9.js
index a19786b..0b8f75c 100644
--- a/test/mjsunit/compiler/escape-analysis-9.js
+++ b/test/mjsunit/compiler/escape-analysis-9.js
@@ -26,7 +26,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax --turbo-escape
-//
function f() {
return arguments;
diff --git a/test/mjsunit/compiler/optimized-float32array-length.js b/test/mjsunit/compiler/optimized-float32array-length.js
new file mode 100644
index 0000000..eed8922
--- /dev/null
+++ b/test/mjsunit/compiler/optimized-float32array-length.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+var a = new Float32Array(1);
+function len(a) { return a.length; }
+assertEquals(1, len(a));
+assertEquals(1, len(a));
+%OptimizeFunctionOnNextCall(len);
+assertEquals(1, len(a));
+assertOptimized(len);
diff --git a/test/mjsunit/compiler/optimized-float64array-length.js b/test/mjsunit/compiler/optimized-float64array-length.js
new file mode 100644
index 0000000..f6a3d77
--- /dev/null
+++ b/test/mjsunit/compiler/optimized-float64array-length.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+var a = new Float64Array(1);
+function len(a) { return a.length; }
+assertEquals(1, len(a));
+assertEquals(1, len(a));
+%OptimizeFunctionOnNextCall(len);
+assertEquals(1, len(a));
+assertOptimized(len);
diff --git a/test/mjsunit/compiler/optimized-instanceof-1.js b/test/mjsunit/compiler/optimized-instanceof-1.js
new file mode 100644
index 0000000..538b0ef
--- /dev/null
+++ b/test/mjsunit/compiler/optimized-instanceof-1.js
@@ -0,0 +1,17 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --harmony-instanceof
+
+function F() {}
+var f = new F
+
+var proto = Object.getPrototypeOf(F);
+Object.setPrototypeOf(F, null);
+F[Symbol.hasInstance] = function(v) { return true };
+Object.setPrototypeOf(F, proto);
+
+function foo(x) { return x instanceof F };
+%OptimizeFunctionOnNextCall(foo);
+assertTrue(foo(1));
diff --git a/test/mjsunit/compiler/optimized-instanceof-2.js b/test/mjsunit/compiler/optimized-instanceof-2.js
new file mode 100644
index 0000000..80bbdcd
--- /dev/null
+++ b/test/mjsunit/compiler/optimized-instanceof-2.js
@@ -0,0 +1,19 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --harmony-instanceof
+
+function F() {}
+var f = new F
+
+function foo(x) { return x instanceof F };
+%OptimizeFunctionOnNextCall(foo);
+assertFalse(foo(1));
+
+var proto = Object.getPrototypeOf(F);
+Object.setPrototypeOf(F, null);
+F[Symbol.hasInstance] = function(v) { return true };
+Object.setPrototypeOf(F, proto);
+
+assertTrue(foo(1));
diff --git a/test/mjsunit/compiler/optimized-int32array-length.js b/test/mjsunit/compiler/optimized-int32array-length.js
new file mode 100644
index 0000000..250d523
--- /dev/null
+++ b/test/mjsunit/compiler/optimized-int32array-length.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+var a = new Int32Array(1);
+function len(a) { return a.length; }
+assertEquals(1, len(a));
+assertEquals(1, len(a));
+%OptimizeFunctionOnNextCall(len);
+assertEquals(1, len(a));
+assertOptimized(len);
diff --git a/test/mjsunit/compiler/optimized-uint32array-length.js b/test/mjsunit/compiler/optimized-uint32array-length.js
new file mode 100644
index 0000000..d389370
--- /dev/null
+++ b/test/mjsunit/compiler/optimized-uint32array-length.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+var a = new Uint32Array(1);
+function len(a) { return a.length; }
+assertEquals(1, len(a));
+assertEquals(1, len(a));
+%OptimizeFunctionOnNextCall(len);
+assertEquals(1, len(a));
+assertOptimized(len);
diff --git a/test/mjsunit/compiler/osr-alignment.js b/test/mjsunit/compiler/osr-alignment.js
index 085d6c4..f815e71 100644
--- a/test/mjsunit/compiler/osr-alignment.js
+++ b/test/mjsunit/compiler/osr-alignment.js
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
function f1() {
var sum = 0;
diff --git a/test/mjsunit/compiler/osr-backedges1.js b/test/mjsunit/compiler/osr-backedges1.js
index d415f4a..18a7e04 100644
--- a/test/mjsunit/compiler/osr-backedges1.js
+++ b/test/mjsunit/compiler/osr-backedges1.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
function foo(a) {
var i = a | 0;
diff --git a/test/mjsunit/compiler/osr-block-scope-func.js b/test/mjsunit/compiler/osr-block-scope-func.js
index df4076c..7c41f54 100644
--- a/test/mjsunit/compiler/osr-block-scope-func.js
+++ b/test/mjsunit/compiler/osr-block-scope-func.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
"use strict";
diff --git a/test/mjsunit/compiler/osr-block-scope-id.js b/test/mjsunit/compiler/osr-block-scope-id.js
index 923c72f..bcc7cdd 100644
--- a/test/mjsunit/compiler/osr-block-scope-id.js
+++ b/test/mjsunit/compiler/osr-block-scope-id.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
"use strict";
diff --git a/test/mjsunit/compiler/osr-block-scope.js b/test/mjsunit/compiler/osr-block-scope.js
index 0d78cdc..c60f8af 100644
--- a/test/mjsunit/compiler/osr-block-scope.js
+++ b/test/mjsunit/compiler/osr-block-scope.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
"use strict";
diff --git a/test/mjsunit/compiler/osr-follow.js b/test/mjsunit/compiler/osr-follow.js
index b6a2e8e..46581a8 100644
--- a/test/mjsunit/compiler/osr-follow.js
+++ b/test/mjsunit/compiler/osr-follow.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --use-osr --turbo-osr
+// Flags: --use-osr
function foo(a) {
var sum = 0;
diff --git a/test/mjsunit/compiler/osr-for-let.js b/test/mjsunit/compiler/osr-for-let.js
index 4b2fa3e..b8cef78 100644
--- a/test/mjsunit/compiler/osr-for-let.js
+++ b/test/mjsunit/compiler/osr-for-let.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
"use strict";
diff --git a/test/mjsunit/compiler/osr-forin-nested.js b/test/mjsunit/compiler/osr-forin-nested.js
index ad55b30..dd81089 100644
--- a/test/mjsunit/compiler/osr-forin-nested.js
+++ b/test/mjsunit/compiler/osr-forin-nested.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --turbo-osr --allow-natives-syntax
+// Flags: --allow-natives-syntax
function test(e, f, v) {
assertEquals(e, f(v));
diff --git a/test/mjsunit/compiler/osr-forin.js b/test/mjsunit/compiler/osr-forin.js
index 8d16782..b45d200 100644
--- a/test/mjsunit/compiler/osr-forin.js
+++ b/test/mjsunit/compiler/osr-forin.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --use-osr --turbo-osr
+// Flags: --use-osr
function f(a) {
var sum = 0;
diff --git a/test/mjsunit/compiler/osr-forof.js b/test/mjsunit/compiler/osr-forof.js
index 36bff09..ce7b24d 100644
--- a/test/mjsunit/compiler/osr-forof.js
+++ b/test/mjsunit/compiler/osr-forof.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --use-osr --turbo-osr
+// Flags: --use-osr
function f(a) {
var sum = 0;
diff --git a/test/mjsunit/compiler/osr-function-id.js b/test/mjsunit/compiler/osr-function-id.js
index c506ae8..8761e85 100644
--- a/test/mjsunit/compiler/osr-function-id.js
+++ b/test/mjsunit/compiler/osr-function-id.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --use-osr --turbo-osr
+// Flags: --use-osr
function id(f) { return f; }
diff --git a/test/mjsunit/compiler/osr-function-id2.js b/test/mjsunit/compiler/osr-function-id2.js
index 561c62e..e25ec31 100644
--- a/test/mjsunit/compiler/osr-function-id2.js
+++ b/test/mjsunit/compiler/osr-function-id2.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --use-osr --turbo-osr
+// Flags: --use-osr
function id(f) { return f; }
diff --git a/test/mjsunit/compiler/osr-function.js b/test/mjsunit/compiler/osr-function.js
index 06d137b..cee7e9d 100644
--- a/test/mjsunit/compiler/osr-function.js
+++ b/test/mjsunit/compiler/osr-function.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --use-osr --turbo-osr
+// Flags: --use-osr
function foo() {
var sum = 0;
diff --git a/test/mjsunit/compiler/osr-infinite.js b/test/mjsunit/compiler/osr-infinite.js
index aa74c87..9d0bb47 100644
--- a/test/mjsunit/compiler/osr-infinite.js
+++ b/test/mjsunit/compiler/osr-infinite.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --use-osr --allow-natives-syntax --turbo-osr
+// Flags: --use-osr --allow-natives-syntax
var global_counter = 0;
diff --git a/test/mjsunit/compiler/osr-labeled.js b/test/mjsunit/compiler/osr-labeled.js
index 1a97092..1384e9a 100644
--- a/test/mjsunit/compiler/osr-labeled.js
+++ b/test/mjsunit/compiler/osr-labeled.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
function foo() {
var sum = 0;
diff --git a/test/mjsunit/compiler/osr-literals-adapted.js b/test/mjsunit/compiler/osr-literals-adapted.js
index 950d8b0..4d1798c 100644
--- a/test/mjsunit/compiler/osr-literals-adapted.js
+++ b/test/mjsunit/compiler/osr-literals-adapted.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
function mod() {
function f0() {
diff --git a/test/mjsunit/compiler/osr-literals.js b/test/mjsunit/compiler/osr-literals.js
index d9f68a0..f2051dc 100644
--- a/test/mjsunit/compiler/osr-literals.js
+++ b/test/mjsunit/compiler/osr-literals.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
function mod() {
function f0() {
diff --git a/test/mjsunit/compiler/osr-manual1.js b/test/mjsunit/compiler/osr-manual1.js
index 29a4948..c3db796 100644
--- a/test/mjsunit/compiler/osr-manual1.js
+++ b/test/mjsunit/compiler/osr-manual1.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
var counter = 111;
diff --git a/test/mjsunit/compiler/osr-manual2.js b/test/mjsunit/compiler/osr-manual2.js
index 8aa5d69..de7ec24 100644
--- a/test/mjsunit/compiler/osr-manual2.js
+++ b/test/mjsunit/compiler/osr-manual2.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
var counter = 188;
diff --git a/test/mjsunit/compiler/osr-multiple.js b/test/mjsunit/compiler/osr-multiple.js
index c318645..72fff85 100644
--- a/test/mjsunit/compiler/osr-multiple.js
+++ b/test/mjsunit/compiler/osr-multiple.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --use-osr --turbo-osr
+// Flags: --use-osr
function f1(a,b,c) {
var x = 0;
diff --git a/test/mjsunit/compiler/osr-multiple2.js b/test/mjsunit/compiler/osr-multiple2.js
index 9a81bfb..edb627a 100644
--- a/test/mjsunit/compiler/osr-multiple2.js
+++ b/test/mjsunit/compiler/osr-multiple2.js
@@ -3,7 +3,6 @@
// found in the LICENSE file.
// Flags: --use-osr
-// TODO(titzer): enable --turbo-osr when nested OSR works.
function f1(a,b,c) {
var x = 0;
diff --git a/test/mjsunit/compiler/osr-multiple3.js b/test/mjsunit/compiler/osr-multiple3.js
index 0fb1ac7..fa703ea 100644
--- a/test/mjsunit/compiler/osr-multiple3.js
+++ b/test/mjsunit/compiler/osr-multiple3.js
@@ -3,7 +3,6 @@
// found in the LICENSE file.
// Flags: --use-osr
-// TODO(titzer): enable --turbo-osr when nested OSR works.
function f1(a,b,c) {
var x = 0;
diff --git a/test/mjsunit/compiler/osr-nested2.js b/test/mjsunit/compiler/osr-nested2.js
index 41bd9b2..efe31f1 100644
--- a/test/mjsunit/compiler/osr-nested2.js
+++ b/test/mjsunit/compiler/osr-nested2.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
function f() {
var sum = 0;
diff --git a/test/mjsunit/compiler/osr-nested2b.js b/test/mjsunit/compiler/osr-nested2b.js
index e64c10c..1808811 100644
--- a/test/mjsunit/compiler/osr-nested2b.js
+++ b/test/mjsunit/compiler/osr-nested2b.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
function f() {
var sum = 0;
diff --git a/test/mjsunit/compiler/osr-nested3.js b/test/mjsunit/compiler/osr-nested3.js
index f5d09ba..d7c144b 100644
--- a/test/mjsunit/compiler/osr-nested3.js
+++ b/test/mjsunit/compiler/osr-nested3.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
function f() {
var sum = 0;
diff --git a/test/mjsunit/compiler/osr-nested3b.js b/test/mjsunit/compiler/osr-nested3b.js
index 32ac2a7..a10d328 100644
--- a/test/mjsunit/compiler/osr-nested3b.js
+++ b/test/mjsunit/compiler/osr-nested3b.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
function f() {
var sum = 0;
diff --git a/test/mjsunit/compiler/osr-regex-id.js b/test/mjsunit/compiler/osr-regex-id.js
index 7831b14..e0b4dad 100644
--- a/test/mjsunit/compiler/osr-regex-id.js
+++ b/test/mjsunit/compiler/osr-regex-id.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
function id(f) { return f; }
diff --git a/test/mjsunit/compiler/osr-sar.js b/test/mjsunit/compiler/osr-sar.js
index cc04adc..02684f0 100644
--- a/test/mjsunit/compiler/osr-sar.js
+++ b/test/mjsunit/compiler/osr-sar.js
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
function test() {
// Loop to force OSR.
diff --git a/test/mjsunit/compiler/osr-warm.js b/test/mjsunit/compiler/osr-warm.js
index 7c30c07..73e1fd5 100644
--- a/test/mjsunit/compiler/osr-warm.js
+++ b/test/mjsunit/compiler/osr-warm.js
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --use-osr --turbo-osr
+// Flags: --use-osr
function f1(x) {
while (x > 0) {
diff --git a/test/mjsunit/compiler/osr-while-let.js b/test/mjsunit/compiler/osr-while-let.js
index c19cf6c..11ebc4b 100644
--- a/test/mjsunit/compiler/osr-while-let.js
+++ b/test/mjsunit/compiler/osr-while-let.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
"use strict";
diff --git a/test/mjsunit/compiler/regress-607493.js b/test/mjsunit/compiler/regress-607493.js
new file mode 100644
index 0000000..540b47e
--- /dev/null
+++ b/test/mjsunit/compiler/regress-607493.js
@@ -0,0 +1,37 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+(function ForInTryCatchContrinueOsr() {
+ var a = [1];
+
+ function g() {
+ for (var x in a) {
+ try {
+ for (var i = 0; i < 10; i++) { %OptimizeOsr(); }
+ return;
+ } catch(e) {
+ continue;
+ }
+ }
+ }
+
+ g();
+})();
+
+(function ForInContinueNestedOsr() {
+ var a = [1];
+
+ function g() {
+ for (var x in a) {
+ if (x) {
+ for (var i = 0; i < 10; i++) { %OptimizeOsr(); }
+ }
+ continue;
+ }
+ }
+
+ g();
+})();
diff --git a/test/mjsunit/compiler/regress-621147.js b/test/mjsunit/compiler/regress-621147.js
new file mode 100644
index 0000000..0a5a221
--- /dev/null
+++ b/test/mjsunit/compiler/regress-621147.js
@@ -0,0 +1,29 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --turbo-filter=test2
+
+function test(n) {
+ return Array(n);
+}
+
+function test2() {
+ return test(2);
+}
+
+function test3(a) {
+ a[0] = 1;
+}
+
+test(0);
+
+var smi_array = [1,2];
+smi_array[2] = 3;
+test3(smi_array);
+
+%OptimizeFunctionOnNextCall(test2);
+
+var broken_array = test2();
+test3(broken_array);
+1+broken_array[0];
diff --git a/test/mjsunit/compiler/try-osr.js b/test/mjsunit/compiler/try-osr.js
index e4eb8dd..c0ef27a 100644
--- a/test/mjsunit/compiler/try-osr.js
+++ b/test/mjsunit/compiler/try-osr.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --turbo-osr
+// Flags: --allow-natives-syntax
function OSRInsideTry(x) {
try {
diff --git a/test/mjsunit/debug-allscopes-on-debugger.js b/test/mjsunit/debug-allscopes-on-debugger.js
index b7a8dff..17668cf 100644
--- a/test/mjsunit/debug-allscopes-on-debugger.js
+++ b/test/mjsunit/debug-allscopes-on-debugger.js
@@ -49,10 +49,11 @@
var i = 0; // Break 1.
i++; // Break 2.
i++; // Break 3.
- return i; // Break 4.
-}()); // Break 5.
+ debugger; // Break 4.
+ return i; // Break 5.
+}()); // Break 6.
-assertNull(exception); // Break 6.
+assertNull(exception); // Break 7.
assertEquals(expected_breaks, break_count);
Debug.setListener(null);
diff --git a/test/mjsunit/debug-backtrace-text.js b/test/mjsunit/debug-backtrace-text.js
index 61648fa..cfc89e6 100644
--- a/test/mjsunit/debug-backtrace-text.js
+++ b/test/mjsunit/debug-backtrace-text.js
@@ -35,7 +35,8 @@
Point.prototype.distanceTo = function(p) {
debugger;
- return Math.sqrt(Math.pow(Math.abs(this.x - p.x), 2) + Math.pow(Math.abs(this.y - p.y), 2))
+ return Math.sqrt(Math.pow(Math.abs(this.x - p.x), 2) +
+ Math.pow(Math.abs(this.y - p.y), 2))
}
p1 = new Point(1,1);
@@ -58,7 +59,7 @@
// Get the Debug object exposed from the debug context global object.
Debug = debug.Debug
-testConstructor = false; // Flag to control which part of the test is run.
+what = 'constructor'; // Flag to control which part of the test is run.
listenerCalled = false;
exception = false;
@@ -72,30 +73,47 @@
function listener(event, exec_state, event_data, data) {
try {
- if (event == Debug.DebugEvent.Break)
- {
- if (!testConstructor) {
- // The expected backtrace is
- // 0: Call distance on Point where distance is a property on the prototype
- // 1: Call distance on Point where distance is a direct property
- // 2: Call on function an array element 2
- // 3: [anonymous]
- assertEquals("#<Point>.distanceTo(p=#<Point>)", exec_state.frame(0).invocationText());
- assertEquals("#<Point>.distanceTo(p=#<Point>)", exec_state.frame(1).invocationText());
- assertEquals("#<Array>[2](aka distance)(p=#<Point>, q=#<Point>)", exec_state.frame(2).invocationText());
- assertEquals("[anonymous]()", exec_state.frame(3).invocationText());
- listenerCalled = true;
- } else {
- // The expected backtrace is
- // 0: Call Point constructor
- // 1: Call on global function createPoint
- // 2: [anonymous]
- assertEquals("new Point(x=0, y=0)", exec_state.frame(0).invocationText());
- assertEquals("createPoint(x=0, y=0)", exec_state.frame(1).invocationText());
- assertEquals("[anonymous]()", exec_state.frame(2).invocationText());
- listenerCalled = true;
+ if (event == Debug.DebugEvent.Break) {
+ if (what == 'constructor') {
+ // The expected backtrace is
+ // 0: Call distance on Point where distance is a prototype property
+ // 1: Call distance on Point where distance is a direct property
+ // 2: Call on function an array element 2
+ // 3: [anonymous]
+ assertEquals("#<Point>.distanceTo(p=#<Point>)",
+ exec_state.frame(0).invocationText());
+ assertEquals("#<Point>.distanceTo(p=#<Point>)",
+ exec_state.frame(1).invocationText());
+ assertEquals("#<Array>[2](aka distance)(p=#<Point>, q=#<Point>)",
+ exec_state.frame(2).invocationText());
+ assertEquals("[anonymous]()", exec_state.frame(3).invocationText());
+ listenerCalled = true;
+ } else if (what == 'breakpoint') {
+ // The expected backtrace is
+ // 0: Call Point constructor
+ // 1: Call on global function createPoint
+ // 2: [anonymous]
+ assertEquals("new Point(x=0, y=0)",
+ exec_state.frame(0).invocationText());
+ assertEquals("createPoint(x=0, y=0)",
+ exec_state.frame(1).invocationText());
+ assertEquals("[anonymous]()", exec_state.frame(2).invocationText());
+ listenerCalled = true;
+ } else if (what == 'symbol') {
+ // The expected backtrace is
+ // 0: Call Point constructor
+ // 1: Call on symbol method
+ // 2: [anonymous]
+ assertEquals("new Point(x=0, y=0)",
+ exec_state.frame(0).invocationText());
+ assertEquals("#<Object>[Symbol(Das Symbol)](x=0, y=0)",
+ exec_state.frame(1).invocationText());
+ assertEquals("[anonymous]()", exec_state.frame(2).invocationText());
+ listenerCalled = true;
+ } else {
+ assertUnreachable();
+ }
}
- }
} catch (e) {
exception = e
};
@@ -112,11 +130,21 @@
assertFalse(exception, "exception in listener")
// Set a break point and call to invoke the debug event listener.
+what = 'breakpoint';
listenerCalled = false;
-testConstructor = true;
Debug.setBreakPoint(Point, 0, 0);
createPoint(0, 0);
// Make sure that the debug event listener vas invoked (again).
assertTrue(listenerCalled);
assertFalse(exception, "exception in listener")
+
+what = 'symbol';
+listenerCalled = false;
+var S = Symbol('Das Symbol');
+var o = { [S](x, y) { return new Point(x, y); } };
+Debug.setBreakPoint(Point, 0, 0);
+o[S](0, 0);
+
+assertTrue(listenerCalled);
+assertFalse(exception, "exception in listener")
diff --git a/test/mjsunit/debug-eval-scope.js b/test/mjsunit/debug-eval-scope.js
new file mode 100644
index 0000000..2b97bf6
--- /dev/null
+++ b/test/mjsunit/debug-eval-scope.js
@@ -0,0 +1,144 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug --no-always-opt
+
+// Test that the (strict) eval scope is visible to the debugger.
+
+var Debug = debug.Debug;
+var exception = null;
+var delegate = null;
+
+function listener(event, exec_state, event_data, data) {
+ if (event != Debug.DebugEvent.Break) return;
+ try {
+ delegate(exec_state);
+ } catch (e) {
+ exception = e;
+ }
+}
+
+Debug.setListener(listener);
+
+// Current function is the top-level eval.
+// We can access stack- and context-allocated values in the eval-scope.
+delegate = function(exec_state) {
+ assertEquals([ debug.ScopeType.Eval,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global ],
+ exec_state.frame(0).allScopes().map(s => s.scopeType()));
+ var scope = exec_state.frame(0).scope(0);
+ assertEquals(1, scope.scopeObject().property("a").value().value());
+ assertEquals(1, exec_state.frame(0).evaluate("a").value());
+ scope.setVariableValue("a", 2);
+ assertEquals(2, exec_state.frame(0).evaluate("a++").value());
+}
+
+eval("'use strict'; \n" +
+ "var a = 1; \n" +
+ "debugger; \n" +
+ "assertEquals(3, a);\n");
+
+eval("'use strict'; \n" +
+ "var a = 1; \n" +
+ "(x=>a); \n" + // Force context-allocation.
+ "debugger; \n" +
+ "assertEquals(3, a);\n");
+
+// Current function is an inner function.
+// We cannot access stack-allocated values in the eval-scope.
+delegate = function(exec_state) {
+ assertEquals([ debug.ScopeType.Local,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global ],
+ exec_state.frame(0).allScopes().map(s => s.scopeType()));
+ assertEquals([ debug.ScopeType.Eval,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global ],
+ exec_state.frame(1).allScopes().map(s => s.scopeType()));
+ var scope = exec_state.frame(0).scope(0);
+ assertThrows(() => exec_state.frame(0).evaluate("a"), ReferenceError);
+ assertTrue(scope.scopeObject().property("a").isUndefined());
+}
+
+eval("'use strict'; \n" +
+ "var a = 1; \n" +
+ "(() => {debugger})()\n");
+
+// Current function is an escaped inner function.
+delegate = function(exec_state) {
+ assertEquals([ debug.ScopeType.Local,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global ],
+ exec_state.frame(0).allScopes().map(s => s.scopeType()));
+ assertEquals([ debug.ScopeType.Script,
+ debug.ScopeType.Global ],
+ exec_state.frame(1).allScopes().map(s => s.scopeType()));
+ var scope = exec_state.frame(0).scope(0);
+ assertThrows(() => exec_state.frame(0).evaluate("a"), ReferenceError);
+ assertTrue(scope.scopeObject().property("a").isUndefined());
+}
+
+var f = eval("'use strict'; \n" +
+ "var a = 1; \n" +
+ "() => {debugger}\n");
+f();
+
+// Current function is an inner function.
+// We can access context-allocated values in the eval-scope.
+delegate = function(exec_state) {
+ assertEquals([ debug.ScopeType.Local,
+ debug.ScopeType.Closure,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global ],
+ exec_state.frame(0).allScopes().map(s => s.scopeType()));
+ assertEquals([ debug.ScopeType.Eval,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global ],
+ exec_state.frame(1).allScopes().map(s => s.scopeType()));
+ var scope = exec_state.frame(1).scope(0);
+ assertEquals(1, scope.scopeObject().property("a").value().value());
+ assertEquals(1, exec_state.frame(1).evaluate("a").value());
+ assertEquals(1, exec_state.frame(0).evaluate("a").value());
+ scope.setVariableValue("a", 2);
+ assertEquals(2, exec_state.frame(0).evaluate("a++").value());
+ assertEquals(3, exec_state.frame(1).evaluate("a++").value());
+}
+
+eval("'use strict'; \n" +
+ "var a = 1; \n" +
+ "(() => { a; \n" + // Force context-allocation.
+ " debugger; \n" +
+ " assertEquals(4, a);\n" +
+ " })(); \n"
+ );
+
+// Current function is an escaped inner function.
+// We can access context-allocated values in the eval-scope.
+delegate = function(exec_state) {
+ assertEquals([ debug.ScopeType.Local,
+ debug.ScopeType.Closure,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global ],
+ exec_state.frame(0).allScopes().map(s => s.scopeType()));
+ assertEquals([ debug.ScopeType.Script,
+ debug.ScopeType.Global ],
+ exec_state.frame(1).allScopes().map(s => s.scopeType()));
+ var scope = exec_state.frame(0).scope(1);
+ assertEquals(1, scope.scopeObject().property("a").value().value());
+ assertEquals(1, exec_state.frame(0).evaluate("a").value());
+ scope.setVariableValue("a", 2);
+ assertEquals(2, exec_state.frame(0).evaluate("a++").value());
+}
+
+var g = eval("'use strict'; \n" +
+ "var a = 1; \n" +
+ "() => { a; \n" +
+ " debugger; \n" +
+ " assertEquals(3, a);\n" +
+ " } \n");
+g();
+
+Debug.setListener(null);
+assertNull(exception);
diff --git a/test/mjsunit/debug-evaluate-nested.js b/test/mjsunit/debug-evaluate-nested.js
index da11b90..965b5a7 100644
--- a/test/mjsunit/debug-evaluate-nested.js
+++ b/test/mjsunit/debug-evaluate-nested.js
@@ -34,7 +34,7 @@
exec_state.frame(0).evaluate("debugger;");
} else {
checkScopes(exec_state.frame(0).allScopes(),
- [ ScopeType.With, ScopeType.Closure,
+ [ ScopeType.Eval, ScopeType.With, ScopeType.Closure,
ScopeType.Script, ScopeType.Global ]);
}
} catch (e) {
diff --git a/test/mjsunit/debug-function-scopes.js b/test/mjsunit/debug-function-scopes.js
index f63d7b2..5509038 100644
--- a/test/mjsunit/debug-function-scopes.js
+++ b/test/mjsunit/debug-function-scopes.js
@@ -42,14 +42,7 @@
}
}
-// A copy of the scope types from debug/mirrors.js.
-var ScopeType = { Global: 0,
- Local: 1,
- With: 2,
- Closure: 3,
- Catch: 4,
- Block: 5,
- Script: 6};
+var ScopeType = debug.ScopeType;
var f1 = (function F1(x) {
function F2(y) {
diff --git a/test/mjsunit/debug-liveedit-exceptions.js b/test/mjsunit/debug-liveedit-exceptions.js
new file mode 100644
index 0000000..28ec01d
--- /dev/null
+++ b/test/mjsunit/debug-liveedit-exceptions.js
@@ -0,0 +1,67 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug
+
+Debug = debug.Debug
+
+function BestEditor() {
+ throw 'Emacs';
+}
+
+var exception = null;
+var results = [];
+var log = []
+
+function listener(event, exec_state, event_data, data) {
+ if (event != Debug.DebugEvent.Exception) return;
+ try {
+ var source_line = event_data.sourceLineText();
+ print(source_line);
+ log.push(source_line);
+ switch (results.length) {
+ case 0:
+ Replace(BestEditor, "Emacs", "Eclipse");
+ break;
+ case 1:
+ Replace(BestEditor, "Eclipse", "Vim");
+ break;
+ case 2:
+ break;
+ default:
+ assertUnreachable();
+ }
+ } catch (e) {
+ exception = e;
+ }
+};
+
+function Replace(fun, original, patch) {
+ var script = Debug.findScript(fun);
+ if (fun.toString().indexOf(original) < 0) return;
+ var patch_pos = script.source.indexOf(original);
+ var change_log = [];
+ Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, original.length, patch, change_log);
+}
+
+Debug.setListener(listener);
+Debug.setBreakOnException();
+
+for (var i = 0; i < 3; i++) {
+ try {
+ BestEditor();
+ } catch (e) {
+ results.push(e);
+ }
+}
+Debug.setListener(null);
+
+assertNull(exception);
+assertEquals(["Emacs", "Eclipse", "Vim"], results);
+print(JSON.stringify(log, 1));
+assertEquals([
+ " throw 'Emacs';",
+ " throw 'Eclipse';",
+ " throw 'Vim';",
+], log);
diff --git a/test/mjsunit/debug-liveedit-stepin.js b/test/mjsunit/debug-liveedit-stepin.js
index 601a66f..c6070ce 100644
--- a/test/mjsunit/debug-liveedit-stepin.js
+++ b/test/mjsunit/debug-liveedit-stepin.js
@@ -7,8 +7,7 @@
Debug = debug.Debug
function BestEditor() {
- var best_editor = "Emacs";
- return best_editor;
+ return 'Emacs';
}
var exception = null;
@@ -62,20 +61,15 @@
assertEquals([
"debugger;",
"results.push(BestEditor());",
- " var best_editor = \"Emacs\";",
- " return best_editor;","}",
+ " return 'Emacs';","}",
"results.push(BestEditor());",
"results.push(BestEditor());",
- " var best_editor = \"Emacs\";",
- " return best_editor;",
- " var best_editor = \"Eclipse\";",
- " return best_editor;","}",
+ " return 'Emacs';",
+ " return 'Eclipse';","}",
"results.push(BestEditor());",
"results.push(BestEditor());",
- " var best_editor = \"Eclipse\";",
- " return best_editor;",
- " var best_editor = \"Vim\";",
- " return best_editor;",
+ " return 'Eclipse';",
+ " return 'Vim';",
"}","results.push(BestEditor());",
"Debug.setListener(null);"
], log);
diff --git a/test/mjsunit/debug-scopes.js b/test/mjsunit/debug-scopes.js
index 3659d4e..935de9c 100644
--- a/test/mjsunit/debug-scopes.js
+++ b/test/mjsunit/debug-scopes.js
@@ -183,10 +183,8 @@
if (!scope.scopeObject().property('this').isUndefined()) {
scope_size--;
}
- // Skip property with empty name.
- if (!scope.scopeObject().property('').isUndefined()) {
- scope_size--;
- }
+ // Temporary variables introduced by the parser have not been materialized.
+ assertTrue(scope.scopeObject().property('').isUndefined());
if (count != scope_size) {
print('Names found in scope:');
@@ -1179,11 +1177,10 @@
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
- debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
- CheckScopeChainPositions([{start: 52, end: 111}, {start: 42, end: 111}, {start: 22, end: 145}, {}, {}], exec_state);
+ CheckScopeChainPositions([{start: 52, end: 111}, {start: 22, end: 145}, {}, {}], exec_state);
}
eval(code3);
EndTest();
diff --git a/test/mjsunit/debug-stack-check-position.js b/test/mjsunit/debug-stack-check-position.js
new file mode 100644
index 0000000..a5570ce
--- /dev/null
+++ b/test/mjsunit/debug-stack-check-position.js
@@ -0,0 +1,30 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug --allow-natives-syntax
+
+var Debug = debug.Debug;
+var exception = null;
+var loop = true;
+
+function listener(event, exec_state, event_data, data) {
+ if (event != Debug.DebugEvent.Break) return;
+ try {
+ assertTrue(exec_state.frame(0).sourceLineText().indexOf("BREAK") > 0);
+ } catch (e) {
+ exception = e;
+ }
+}
+
+function f() { // BREAK
+ return 1;
+}
+
+Debug.setListener(listener);
+
+%ScheduleBreak(); // Break on function entry.
+f();
+
+Debug.setListener(null);
+assertNull(exception);
diff --git a/test/mjsunit/delete.js b/test/mjsunit/delete.js
index 8d4636a..20fa6bf 100644
--- a/test/mjsunit/delete.js
+++ b/test/mjsunit/delete.js
@@ -178,3 +178,17 @@
}
load_deleted_property_using_IC();
+
+
+(function deleteLargeDoubleArrayAtEnd() {
+ var o = {};
+ var max = 100000;
+ for (var i = 0; i <= max; i++) {
+ o[i] = 1.1;
+ }
+ delete o[max];
+ for (var i = 0; i < max; i++) {
+ assertEquals(1.1, o[i]);
+ }
+ assertEquals(undefined, o[max]);
+})();
diff --git a/test/mjsunit/es6/array-concat.js b/test/mjsunit/es6/array-concat.js
index fe320d6..00edfd6 100644
--- a/test/mjsunit/es6/array-concat.js
+++ b/test/mjsunit/es6/array-concat.js
@@ -1,7 +1,6 @@
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-
(function testArrayConcatArity() {
"use strict";
assertEquals(1, Array.prototype.concat.length);
@@ -20,6 +19,15 @@
assertEquals(false, desc.enumerable);
})();
+(function testNonConcatSpreadableArray() {
+ "use strict"
+ var array = [1, 2, 3];
+ assertEquals(array, [].concat(array));
+ assertEquals(array, array.concat([]));
+ array[Symbol.isConcatSpreadable] = false;
+ assertEquals([[1,2,3]], [].concat(array));
+ assertEquals([[1,2,3]], array.concat([]));
+})();
(function testConcatArrayLike() {
"use strict";
diff --git a/test/mjsunit/es6/array-species-neg-zero.js b/test/mjsunit/es6/array-species-neg-zero.js
new file mode 100644
index 0000000..d60b8ba
--- /dev/null
+++ b/test/mjsunit/es6/array-species-neg-zero.js
@@ -0,0 +1,23 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * 9.4.2.3 ArraySpeciesCreate(originalArray, length)
+ *
+ * 1. Assert: length is an integer Number ≥ 0.
+ * 2. If length is −0, let length be +0.
+ * [...]
+ */
+
+var x = [];
+var deleteCount;
+
+x.constructor = function() {};
+x.constructor[Symbol.species] = function(param) {
+ deleteCount = param;
+};
+
+x.splice(0, -0);
+
+assertEquals(0, deleteCount);
diff --git a/test/mjsunit/harmony/block-conflicts-sloppy.js b/test/mjsunit/es6/block-conflicts-sloppy.js
similarity index 98%
rename from test/mjsunit/harmony/block-conflicts-sloppy.js
rename to test/mjsunit/es6/block-conflicts-sloppy.js
index 8908ce4..866abee 100644
--- a/test/mjsunit/harmony/block-conflicts-sloppy.js
+++ b/test/mjsunit/es6/block-conflicts-sloppy.js
@@ -4,8 +4,6 @@
// Test for conflicting variable bindings.
-// Flags: --harmony-sloppy --harmony-sloppy-let --harmony-sloppy-function
-
function CheckException(e) {
var string = e.toString();
assertTrue(string.indexOf("has already been declared") >= 0 ||
diff --git a/test/mjsunit/harmony/block-const-assign-sloppy.js b/test/mjsunit/es6/block-const-assign-sloppy.js
similarity index 98%
rename from test/mjsunit/harmony/block-const-assign-sloppy.js
rename to test/mjsunit/es6/block-const-assign-sloppy.js
index 5dde82c..99024ef 100644
--- a/test/mjsunit/harmony/block-const-assign-sloppy.js
+++ b/test/mjsunit/es6/block-const-assign-sloppy.js
@@ -25,8 +25,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --harmony-sloppy --harmony-sloppy-let
-
// Test that we throw early syntax errors in harmony mode
// when using an immutable binding in an assigment or with
// prefix/postfix decrement/increment operators.
diff --git a/test/mjsunit/es6/block-early-errors.js b/test/mjsunit/es6/block-early-errors.js
deleted file mode 100644
index 4af6521..0000000
--- a/test/mjsunit/es6/block-early-errors.js
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Flags: --no-harmony-sloppy-let
-
-function CheckException(e) {
- var string = e.toString();
- assertInstanceof(e, SyntaxError);
-}
-
-function Check(str) {
- try {
- eval("(function () { " + str + " })");
- assertUnreachable();
- } catch (e) {
- CheckException(e);
- }
- try {
- eval("(function () { { " + str + " } })");
- assertUnreachable();
- } catch (e) {
- CheckException(e);
- }
-}
-
-// Check for early syntax errors when using let
-// declarations outside of strict mode.
-Check("let x;");
-Check("let x = 1;");
-Check("let x, y;");
diff --git a/test/mjsunit/harmony/block-eval-var-over-let.js b/test/mjsunit/es6/block-eval-var-over-let.js
similarity index 96%
rename from test/mjsunit/harmony/block-eval-var-over-let.js
rename to test/mjsunit/es6/block-eval-var-over-let.js
index 98091b4..febc83f 100644
--- a/test/mjsunit/harmony/block-eval-var-over-let.js
+++ b/test/mjsunit/es6/block-eval-var-over-let.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy --harmony-sloppy-let --harmony-sloppy-function
-
// Var-let conflict in a function throws, even if the var is in an eval
// Throws at the top level of a function
diff --git a/test/mjsunit/harmony/block-for-sloppy.js b/test/mjsunit/es6/block-for-sloppy.js
similarity index 98%
rename from test/mjsunit/harmony/block-for-sloppy.js
rename to test/mjsunit/es6/block-for-sloppy.js
index 261c46a..4f0f63f 100644
--- a/test/mjsunit/harmony/block-for-sloppy.js
+++ b/test/mjsunit/es6/block-for-sloppy.js
@@ -25,8 +25,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --harmony-sloppy --harmony-sloppy-let
-
function props(x) {
var array = [];
for (let p in x) array.push(p);
diff --git a/test/mjsunit/harmony/block-leave-sloppy.js b/test/mjsunit/es6/block-leave-sloppy.js
similarity index 98%
rename from test/mjsunit/harmony/block-leave-sloppy.js
rename to test/mjsunit/es6/block-leave-sloppy.js
index 0023fa0..1313026 100644
--- a/test/mjsunit/harmony/block-leave-sloppy.js
+++ b/test/mjsunit/es6/block-leave-sloppy.js
@@ -25,8 +25,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --harmony-sloppy --harmony-sloppy-let
-
// We want to test the context chain shape. In each of the tests cases
// below, the outer with is to force a runtime lookup of the identifier 'x'
// to actually verify that the inner context has been discarded. A static
diff --git a/test/mjsunit/es6/block-let-contextual-sloppy.js b/test/mjsunit/es6/block-let-contextual-sloppy.js
index ac7bca1..8282d77 100644
--- a/test/mjsunit/es6/block-let-contextual-sloppy.js
+++ b/test/mjsunit/es6/block-let-contextual-sloppy.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy --harmony-sloppy-let
-
// let is usable as a variable with var, but not let or ES6 const
(function (){
diff --git a/test/mjsunit/harmony/block-let-crankshaft-sloppy.js b/test/mjsunit/es6/block-let-crankshaft-sloppy.js
similarity index 99%
rename from test/mjsunit/harmony/block-let-crankshaft-sloppy.js
rename to test/mjsunit/es6/block-let-crankshaft-sloppy.js
index 4f29c05..b5e81f7 100644
--- a/test/mjsunit/harmony/block-let-crankshaft-sloppy.js
+++ b/test/mjsunit/es6/block-let-crankshaft-sloppy.js
@@ -26,7 +26,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax
-// Flags: --harmony-sloppy --harmony-sloppy-let
// Check that the following functions are optimizable.
var functions = [ f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14,
diff --git a/test/mjsunit/harmony/block-let-declaration-sloppy.js b/test/mjsunit/es6/block-let-declaration-sloppy.js
similarity index 98%
rename from test/mjsunit/harmony/block-let-declaration-sloppy.js
rename to test/mjsunit/es6/block-let-declaration-sloppy.js
index af95553..ea0e39b 100644
--- a/test/mjsunit/harmony/block-let-declaration-sloppy.js
+++ b/test/mjsunit/es6/block-let-declaration-sloppy.js
@@ -27,8 +27,6 @@
// Test let declarations in various settings.
-// Flags: --harmony-sloppy --harmony-sloppy-let
-
// Global
let x;
let y = 2;
diff --git a/test/mjsunit/harmony/block-let-semantics-sloppy.js b/test/mjsunit/es6/block-let-semantics-sloppy.js
similarity index 98%
rename from test/mjsunit/harmony/block-let-semantics-sloppy.js
rename to test/mjsunit/es6/block-let-semantics-sloppy.js
index a55ff8f..4102ec8 100644
--- a/test/mjsunit/harmony/block-let-semantics-sloppy.js
+++ b/test/mjsunit/es6/block-let-semantics-sloppy.js
@@ -25,8 +25,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --harmony-sloppy --harmony-sloppy-let --harmony-sloppy-function
-
// Test temporal dead zone semantics of let bound variables in
// function and block scopes.
diff --git a/test/mjsunit/es6/block-non-strict-errors.js b/test/mjsunit/es6/block-non-strict-errors.js
deleted file mode 100644
index db7f558..0000000
--- a/test/mjsunit/es6/block-non-strict-errors.js
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --no-harmony-sloppy-let --no-harmony-sloppy-function
-// Flags: --no-harmony-sloppy
-
-function CheckError(source) {
- var exception = null;
- try {
- eval(source);
- } catch (e) {
- exception = e;
- }
- assertNotNull(exception);
- assertEquals(
- "Block-scoped declarations (let, const, function, class) not yet supported outside strict mode",
- exception.message);
-}
-
-
-function CheckOk(source) {
- eval(source);
-}
-
-CheckError("let x = 1;");
-CheckError("{ let x = 1; }");
-CheckError("function f() { let x = 1; }");
-CheckError("for (let x = 1; x < 1; x++) {}");
-CheckError("for (let x of []) {}");
-CheckError("for (let x in []) {}");
-CheckError("class C {}");
-CheckError("class C extends Array {}");
-CheckError("(class {});");
-CheckError("(class extends Array {});");
-CheckError("(class C {});");
-CheckError("(class C exends Array {});");
-
-CheckOk("let = 1;");
-CheckOk("{ let = 1; }");
-CheckOk("function f() { let = 1; }");
-CheckOk("for (let = 1; let < 1; let++) {}");
diff --git a/test/mjsunit/es6/block-scope-class.js b/test/mjsunit/es6/block-scope-class.js
index 351feaa..7bbd49d 100644
--- a/test/mjsunit/es6/block-scope-class.js
+++ b/test/mjsunit/es6/block-scope-class.js
@@ -4,8 +4,6 @@
// Test for conflicting variable bindings.
-// Flags: --harmony-sloppy --harmony-sloppy-function
-
function AssertEqualsStrictAndSloppy(value, code) {
assertEquals(value, eval("(function() {" + code + "})()"));
assertEquals(value, eval("(function() { 'use strict'; " + code + "})()"));
diff --git a/test/mjsunit/harmony/block-scoping-sloppy.js b/test/mjsunit/es6/block-scoping-sloppy.js
similarity index 98%
rename from test/mjsunit/harmony/block-scoping-sloppy.js
rename to test/mjsunit/es6/block-scoping-sloppy.js
index 1785901..f5c5a63 100644
--- a/test/mjsunit/harmony/block-scoping-sloppy.js
+++ b/test/mjsunit/es6/block-scoping-sloppy.js
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --allow-natives-syntax --harmony-sloppy --harmony-sloppy-let --harmony-sloppy-function
+// Flags: --allow-natives-syntax
// Test functionality of block scopes.
// Hoisting of var declarations.
diff --git a/test/mjsunit/harmony/block-scoping-top-level-sloppy.js b/test/mjsunit/es6/block-scoping-top-level-sloppy.js
similarity index 91%
rename from test/mjsunit/harmony/block-scoping-top-level-sloppy.js
rename to test/mjsunit/es6/block-scoping-top-level-sloppy.js
index 6f6a8fe..2a3b903 100644
--- a/test/mjsunit/harmony/block-scoping-top-level-sloppy.js
+++ b/test/mjsunit/es6/block-scoping-top-level-sloppy.js
@@ -3,7 +3,6 @@
// found in the LICENSE file.
// Flags: --min-preparse-length=0
-// Flags: --harmony-sloppy --harmony-sloppy-let
let xxx = 1;
let f = undefined;
diff --git a/test/mjsunit/harmony/block-sloppy-function.js b/test/mjsunit/es6/block-sloppy-function.js
similarity index 98%
rename from test/mjsunit/harmony/block-sloppy-function.js
rename to test/mjsunit/es6/block-sloppy-function.js
index 2bea147..41063b4 100644
--- a/test/mjsunit/harmony/block-sloppy-function.js
+++ b/test/mjsunit/es6/block-sloppy-function.js
@@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy --harmony-sloppy-let
-// Flags: --harmony-sloppy-function
-
// Test Annex B 3.3 semantics for functions declared in blocks in sloppy mode.
// http://www.ecma-international.org/ecma-262/6.0/#sec-block-level-function-declarations-web-legacy-compatibility-semantics
diff --git a/test/mjsunit/es6/class-computed-property-names-super.js b/test/mjsunit/es6/class-computed-property-names-super.js
index cb9f251..b5a2ac9 100644
--- a/test/mjsunit/es6/class-computed-property-names-super.js
+++ b/test/mjsunit/es6/class-computed-property-names-super.js
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy
// Flags: --allow-natives-syntax
diff --git a/test/mjsunit/es6/class-property-name-eval-arguments.js b/test/mjsunit/es6/class-property-name-eval-arguments.js
index 72ff60f..bbd05cc 100644
--- a/test/mjsunit/es6/class-property-name-eval-arguments.js
+++ b/test/mjsunit/es6/class-property-name-eval-arguments.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy
-
(function Method() {
class C {
diff --git a/test/mjsunit/es6/classes-derived-return-type.js b/test/mjsunit/es6/classes-derived-return-type.js
index 8283bcb..3f81a34 100644
--- a/test/mjsunit/es6/classes-derived-return-type.js
+++ b/test/mjsunit/es6/classes-derived-return-type.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy
-
class Base {}
diff --git a/test/mjsunit/es6/classes.js b/test/mjsunit/es6/classes.js
index 4dabda8..fb77dbb 100644
--- a/test/mjsunit/es6/classes.js
+++ b/test/mjsunit/es6/classes.js
@@ -2,8 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy --harmony-function-name --allow-natives-syntax
-// Flags: --harmony-do-expressions
+// Flags: --allow-natives-syntax --harmony-do-expressions
(function TestBasics() {
var C = class C {}
diff --git a/test/mjsunit/es6/completion.js b/test/mjsunit/es6/completion.js
index 7559514..988e970 100644
--- a/test/mjsunit/es6/completion.js
+++ b/test/mjsunit/es6/completion.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy-let
-
function assertUndef(x) {
assertEquals(undefined, x);
diff --git a/test/mjsunit/es6/debug-blockscopes.js b/test/mjsunit/es6/debug-blockscopes.js
index 193ad70..bf04a0a 100644
--- a/test/mjsunit/es6/debug-blockscopes.js
+++ b/test/mjsunit/es6/debug-blockscopes.js
@@ -52,6 +52,7 @@
listener_delegate(exec_state);
}
} catch (e) {
+ print(e, e.stack);
exception = e;
}
}
@@ -147,10 +148,8 @@
if (!scope.scopeObject().property('arguments').isUndefined()) {
scope_size--;
}
- // Skip property with empty name.
- if (!scope.scopeObject().property('').isUndefined()) {
- scope_size--;
- }
+ // Temporary variables introduced by the parser have not been materialized.
+ assertTrue(scope.scopeObject().property('').isUndefined());
if (count != scope_size) {
print('Names found in scope:');
@@ -380,16 +379,12 @@
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
- debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({x:'y'}, 0, exec_state);
// The function scope contains a temporary iteration variable, but it is
// hidden to the debugger.
- // TODO(adamk): This variable is only used to provide a TDZ for the enumerable
- // expression and should not be visible to the debugger.
- CheckScopeContent({x:undefined}, 1, exec_state);
};
for_loop_1();
EndTest();
@@ -409,7 +404,6 @@
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
debug.ScopeType.Block,
- debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
@@ -417,9 +411,6 @@
CheckScopeContent({x:'y'}, 1, exec_state);
// The function scope contains a temporary iteration variable, hidden to the
// debugger.
- // TODO(adamk): This variable is only used to provide a TDZ for the enumerable
- // expression and should not be visible to the debugger.
- CheckScopeContent({x:undefined}, 2, exec_state);
};
for_loop_2();
EndTest();
@@ -436,13 +427,11 @@
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
- debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({x:3}, 0, exec_state);
- CheckScopeContent({x:3}, 1, exec_state);
- CheckScopeContent({}, 2, exec_state);
+ CheckScopeContent({}, 1, exec_state);
};
for_loop_3();
EndTest();
@@ -461,14 +450,12 @@
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
debug.ScopeType.Block,
- debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({x:5}, 0, exec_state);
CheckScopeContent({x:3}, 1, exec_state);
- CheckScopeContent({x:3}, 2, exec_state);
- CheckScopeContent({}, 3, exec_state);
+ CheckScopeContent({}, 2, exec_state);
};
for_loop_4();
EndTest();
@@ -485,13 +472,11 @@
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
- debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({x:3,y:5}, 0, exec_state);
- CheckScopeContent({x:3,y:5}, 1, exec_state);
- CheckScopeContent({}, 2, exec_state);
+ CheckScopeContent({}, 1, exec_state);
};
for_loop_5();
EndTest();
diff --git a/test/mjsunit/es6/debug-evaluate-receiver-before-super.js b/test/mjsunit/es6/debug-evaluate-receiver-before-super.js
new file mode 100644
index 0000000..dc8ce2c
--- /dev/null
+++ b/test/mjsunit/es6/debug-evaluate-receiver-before-super.js
@@ -0,0 +1,39 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug
+
+// Test that debug-evaluate doesn't crash when this is used before super() call
+// in constructor.
+
+Debug = debug.Debug
+
+var result;
+
+function listener(event, exec_state, event_data, data)
+{
+ try {
+ if (event == Debug.DebugEvent.Break) {
+ result = exec_state.frame(0).evaluate("this.a").value();
+ }
+ } catch (e) {
+ result = e.message;
+ }
+}
+
+Debug.setListener(listener);
+
+class A { constructor () { this.a = 239; } }
+class B extends A {
+ constructor () {
+ debugger;
+ assertEquals("Cannot read property 'a' of undefined", result);
+ super();
+ debugger;
+ assertEquals(239, result);
+ }
+}
+new B();
+
+Debug.setListener(null);
diff --git a/test/mjsunit/es6/debug-promises/stepin-constructor.js b/test/mjsunit/es6/debug-promises/stepin-constructor.js
index 906969e..6914ae0 100644
--- a/test/mjsunit/es6/debug-promises/stepin-constructor.js
+++ b/test/mjsunit/es6/debug-promises/stepin-constructor.js
@@ -21,9 +21,9 @@
Debug.setListener(listener);
function resolver(resolve, reject) {
- 1;
- 2;
- 3;
+ print(1);
+ print(2);
+ print(3);
resolve();
}
@@ -35,9 +35,9 @@
var expected_breaks = [
"debugger;",
"var p = new Promise(resolver);",
- "1;",
- "2;",
- "3;",
+ "print(1);",
+ "print(2);",
+ "print(3);",
"resolve();",
"}",
"Debug.setListener(null);"
diff --git a/test/mjsunit/es6/debug-scope-default-param-with-eval.js b/test/mjsunit/es6/debug-scope-default-param-with-eval.js
new file mode 100644
index 0000000..d4dc93f
--- /dev/null
+++ b/test/mjsunit/es6/debug-scope-default-param-with-eval.js
@@ -0,0 +1,61 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug
+
+// Test that the parameter initialization block scope set up for
+// sloppy eval is visible to the debugger.
+
+var Debug = debug.Debug;
+var exception = null;
+var break_count = 0;
+
+function call_for_break() {
+ return 5;
+}
+
+function test(x = eval("var y = 7; debugger; y") + call_for_break()) {
+ return x;
+}
+
+function listener(event, exec_state, event_data, data) {
+ if (event != Debug.DebugEvent.Break) return;
+ try {
+ var frame = exec_state.frame(0);
+ var block_scope;
+ if (break_count++ == 0) {
+ // Inside eval.
+ assertEquals([ debug.ScopeType.Eval,
+ debug.ScopeType.Block,
+ debug.ScopeType.Closure,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global ],
+ frame.allScopes().map(s => s.scopeType()));
+ exec_state.prepareStep(Debug.StepAction.StepOut);
+ block_scope = frame.scope(1);
+ } else {
+ // Outside of eval.
+ assertEquals([ debug.ScopeType.Block,
+ debug.ScopeType.Local,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global ],
+ frame.allScopes().map(s => s.scopeType()));
+ block_scope = frame.scope(0);
+ }
+ assertTrue(block_scope.scopeObject().propertyNames().includes('y'));
+ assertEquals(7, block_scope.scopeObject().property('y').value().value());
+ } catch (e) {
+ print(e);
+ exception = e;
+ }
+}
+
+Debug.setListener(listener);
+
+assertEquals(12, test());
+
+Debug.setListener(null);
+
+assertNull(exception);
+assertEquals(2, break_count);
diff --git a/test/mjsunit/es6/debug-stepin-microtasks.js b/test/mjsunit/es6/debug-stepin-microtasks.js
index 6a7c553..e541f0f 100644
--- a/test/mjsunit/es6/debug-stepin-microtasks.js
+++ b/test/mjsunit/es6/debug-stepin-microtasks.js
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-object-observe
// Flags: --allow-natives-syntax --expose-debug-as debug
Debug = debug.Debug
@@ -46,6 +45,7 @@
.then(Boolean) // Should skip stepping into native.
.then(promise2)
.catch(promise3)
+ .then(promise4)
.catch(function(e) {
%AbortJS("FAIL: uncaught exception " + e);
});
@@ -60,36 +60,16 @@
}
function promise3() {
- installObservers(); // Break 4. StepOver.
- return break_count; // Break 5.
-} // Break 6.
-
-function installObservers() {
- var dummy = {};
- Object.observe(dummy, observer1);
- Object.observe(dummy, Object); // Should skip stepping into native.
- Object.observe(dummy, Boolean); // Should skip stepping into native.
- Object.observe(dummy, observer2);
- dummy.foo = 1;
-}
-
-function observer1() {
- return exception || 3; // Break 7.
-} // Break 8.
-
-function observer2() {
- Promise.resolve().then(promise4); // Break 9. StepOver.
- return break_count + 1; // Break 10.
-} // Break 11.
+ return break_count; // Break 4.
+} // Break 5.
function promise4() {
- finalize(); // Break 12. StepOver.
- return 0; // Break 13.
-} // Break 14. StepOver.
+ finalize(); // Break 6. StepOver.
+ return 0; // Break 7.
+} // Break 8. StepOver.
function finalize() {
- var dummy = {};
- Object.observe(dummy, function() {
+ Promise.resolve().then(function() {
if (expected_breaks !== break_count) {
%AbortJS("FAIL: expected <" + expected_breaks + "> breaks instead of <" +
break_count + ">");
@@ -98,5 +78,4 @@
%AbortJS("FAIL: exception: " + exception);
}
});
- dummy.foo = 1;
}
diff --git a/test/mjsunit/es6/debug-stepin-proxies.js b/test/mjsunit/es6/debug-stepin-proxies.js
index 4e71c79..72c01f0 100644
--- a/test/mjsunit/es6/debug-stepin-proxies.js
+++ b/test/mjsunit/es6/debug-stepin-proxies.js
@@ -54,7 +54,7 @@
assertEquals([
"a0",
- "b17", "h4b20", "i2b20", // [[Has]]
+ "b17", "h4b17", "i2b17", // [[Has]]
"c15", "j4c15", "k2c15", // [[Get]]
"d0", "l4d11", "m2d11", // [[Set]]
"g0"
diff --git a/test/mjsunit/es6/debug-stepnext-for.js b/test/mjsunit/es6/debug-stepnext-for.js
index 9d5641a..d425a46 100644
--- a/test/mjsunit/es6/debug-stepnext-for.js
+++ b/test/mjsunit/es6/debug-stepnext-for.js
@@ -11,6 +11,8 @@
var s = 0;
var a = [1, 2, 3];
+var b = [1, 2, 3, 4];
+var null_value = null;
var i = 0;
function f() {
@@ -18,11 +20,11 @@
debugger; // Break a
var j; // Break b
- for (var i in null) { // Break c
+ for (var i in null_value) { // Break c
s += a[i];
}
- for (j in null) { // Break d
+ for (j in null_value) { // Break d
s += a[j];
}
@@ -46,7 +48,7 @@
s += j; // Break I
}
- for (let i of a) { // Break j
+ for (let i of a) { // Break j
s += i; // Break J
}
@@ -61,6 +63,11 @@
for (let i = 0; i < 3; i++) { // Break m
s += a[i]; // Break M
}
+
+ for (let i of a) {} // Break n
+
+ [1, ...a] // Break o
+
} // Break y
function listener(event, exec_state, event_data, data) {
@@ -103,17 +110,21 @@
// For-in-let: get enumerable, next, body, next, ...
"g16","g11","G4","g11","G4","g11","G4","g11",
// For-of-var: [Symbol.iterator](), next(), body, next(), body, ...
- "h16","h14","h15","H4","h15","H4","h15","H4","h15",
+ "h16","h13","H4","h13","H4","h13","H4","h13",
// For-of: [Symbol.iterator](), next(), body, next(), body, ...
- "i12","i10","i11","I4","i11","I4","i11","I4","i11",
+ "i12","i9","I4","i9","I4","i9","I4","i9",
// For-of-let: [Symbol.iterator](), next(), body, next(), ...
- "j16","j14","j15","J4","j15","J4","j15","J4","j15",
+ "j18","j14","J4","j14","J4","j14","J4","j14",
// For-var: init, condition, body, next, condition, body, ...
"k15","k20","K4","k26","k20","K4","k26","k20","K4","k26","k20",
// For: init, condition, body, next, condition, body, ...
"l7","l16","L4","l22","l16","L4","l22","l16","L4","l22","l16",
// For-let: init, condition, body, next, condition, body, ...
"m15","m20","M4","m26","m20","M4","m26","m20","M4","m26","m20",
+ // For-of, empty: [Symbol.iterator](), next() once
+ "n16", "n13",
+ // Spread: expression statement, spread
+ "o2", "o9",
// Exit.
"y0","z0",
]
diff --git a/test/mjsunit/es6/generators-objects.js b/test/mjsunit/es6/generators-objects.js
index a0c3b80..2d23841 100644
--- a/test/mjsunit/es6/generators-objects.js
+++ b/test/mjsunit/es6/generators-objects.js
@@ -87,3 +87,29 @@
TestNonGenerator(g.prototype);
}
TestGeneratorObjectMethods();
+
+
+function TestPrototype() {
+ function* g() { }
+
+ let g_prototype = g.prototype;
+ assertEquals([], Reflect.ownKeys(g_prototype));
+
+ let generator_prototype = Object.getPrototypeOf(g_prototype);
+ assertSame(generator_prototype, Object.getPrototypeOf(g).prototype);
+
+ // Unchanged .prototype
+ assertSame(g_prototype, Object.getPrototypeOf(g()));
+
+ // Custom object as .prototype
+ {
+ let proto = {};
+ g.prototype = proto;
+ assertSame(proto, Object.getPrototypeOf(g()));
+ }
+
+ // Custom non-object as .prototype
+ g.prototype = null;
+ assertSame(generator_prototype, Object.getPrototypeOf(g()));
+}
+TestPrototype();
diff --git a/test/mjsunit/es6/microtask-delivery.js b/test/mjsunit/es6/microtask-delivery.js
index 01b971d..6b239be 100644
--- a/test/mjsunit/es6/microtask-delivery.js
+++ b/test/mjsunit/es6/microtask-delivery.js
@@ -25,7 +25,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --harmony-object-observe
// Flags: --allow-natives-syntax
var ordering = [];
@@ -71,22 +70,6 @@
};
}
-function newObserver(id, fn, obj) {
- var observer = {
- value: 1,
- recordCounts: []
- };
-
- Object.observe(observer, function(records) {
- ordering.push('o' + id);
- observer.recordCounts.push(records.length);
- if (fn) fn();
- });
-
- return observer;
-}
-
-
(function PromiseThens() {
reset();
@@ -98,72 +81,3 @@
assertOrdering(['p1', 'p2', 'p1:1', 'p2:1']);
})();
-
-
-(function ObserversBatch() {
- reset();
-
- var p1 = newPromise(1);
- var p2 = newPromise(2);
- var p3 = newPromise(3);
-
- var ob1 = newObserver(1);
- var ob2 = newObserver(2, function() {
- ob3.value++;
- p3.resolve();
- ob1.value++;
- });
- var ob3 = newObserver(3);
-
- p1.resolve();
- ob1.value++;
- p2.resolve();
- ob2.value++;
-
- assertOrdering(['p1', 'o1', 'o2', 'p2', 'o1', 'o3', 'p3']);
- assertArrayValues([1, 1], ob1.recordCounts);
- assertArrayValues([1], ob2.recordCounts);
- assertArrayValues([1], ob3.recordCounts);
-})();
-
-
-(function ObserversGetAllRecords() {
- reset();
-
- var p1 = newPromise(1);
- var p2 = newPromise(2);
- var ob1 = newObserver(1, function() {
- ob2.value++;
- });
- var ob2 = newObserver(2);
-
- p1.resolve();
- ob1.value++;
- p2.resolve();
- ob2.value++;
-
- assertOrdering(['p1', 'o1', 'o2', 'p2']);
- assertArrayValues([1], ob1.recordCounts);
- assertArrayValues([2], ob2.recordCounts);
-})();
-
-
-(function NewObserverDeliveryGetsNewMicrotask() {
- reset();
-
- var p1 = newPromise(1);
- var p2 = newPromise(2);
- var ob1 = newObserver(1);
- var ob2 = newObserver(2, function() {
- ob1.value++;
- });
-
- p1.resolve();
- ob1.value++;
- p2.resolve();
- ob2.value++;
-
- assertOrdering(['p1', 'o1', 'o2', 'p2', 'o1']);
- assertArrayValues([1, 1], ob1.recordCounts);
- assertArrayValues([1], ob2.recordCounts);
-})();
diff --git a/test/mjsunit/es6/mirror-collections.js b/test/mjsunit/es6/mirror-collections.js
index 81a98b8..4232ef9 100644
--- a/test/mjsunit/es6/mirror-collections.js
+++ b/test/mjsunit/es6/mirror-collections.js
@@ -88,16 +88,21 @@
assertSame(o2, values[0]);
assertEquals(undefined, values[1]);
+function initWeakMap(weakMap) {
+ weakMap.set(o1, 11);
+ weakMap.set(new Object(), 22);
+ weakMap.set(o3, 33);
+ weakMap.set(new Object(), 44);
+ var weakMapMirror = debug.MakeMirror(weakMap);
+ testMapMirror(weakMapMirror);
+ weakMap.set(new Object(), 55);
+ assertTrue(weakMapMirror.entries().length <= 5);
+ return weakMapMirror;
+}
+
// Test the mirror object for WeakMaps
var weakMap = new WeakMap();
-weakMap.set(o1, 11);
-weakMap.set(new Object(), 22);
-weakMap.set(o3, 33);
-weakMap.set(new Object(), 44);
-var weakMapMirror = debug.MakeMirror(weakMap);
-testMapMirror(weakMapMirror);
-weakMap.set(new Object(), 55);
-assertTrue(weakMapMirror.entries().length <= 5);
+var weakMapMirror = initWeakMap(weakMap);
gc();
function testWeakMapEntries(weakMapMirror) {
@@ -121,18 +126,23 @@
testWeakMapEntries(weakMapMirror);
+function initWeakSet(weakSet) {
+ weakSet.add(o1);
+ weakSet.add(new Object());
+ weakSet.add(o2);
+ weakSet.add(new Object());
+ weakSet.add(new Object());
+ weakSet.add(o3);
+ weakSet.delete(o2);
+ var weakSetMirror = debug.MakeMirror(weakSet);
+ testSetMirror(weakSetMirror);
+ assertTrue(weakSetMirror.values().length <= 5);
+ return weakSetMirror;
+}
+
// Test the mirror object for WeakSets
var weakSet = new WeakSet();
-weakSet.add(o1);
-weakSet.add(new Object());
-weakSet.add(o2);
-weakSet.add(new Object());
-weakSet.add(new Object());
-weakSet.add(o3);
-weakSet.delete(o2);
-var weakSetMirror = debug.MakeMirror(weakSet);
-testSetMirror(weakSetMirror);
-assertTrue(weakSetMirror.values().length <= 5);
+var weakSetMirror = initWeakSet(weakSet);
gc();
function testWeakSetValues(weakSetMirror) {
diff --git a/test/mjsunit/es6/proxies-for.js b/test/mjsunit/es6/proxies-for.js
index 5b81845..a171227 100644
--- a/test/mjsunit/es6/proxies-for.js
+++ b/test/mjsunit/es6/proxies-for.js
@@ -209,10 +209,15 @@
assertThrowsEquals(() => {keys(proxy)}, "error");
})();
-
-(function () {
- var symbol = Symbol();
- var p = new Proxy({}, {ownKeys() { return ["1", symbol, "2"] }});
- assertEquals(["1","2"], Object.getOwnPropertyNames(p));
- assertEquals([symbol], Object.getOwnPropertySymbols(p));
+(function testNestedProxy() {
+ var handler = {
+ ownKeys() {
+ return ['c'];
+ },
+ getOwnPropertyDescriptor() { return {configurable: true, enumerable: true } }
+ }
+ var proxy = new Proxy({}, handler);
+ var proxy2 = new Proxy(proxy, {});
+ assertEquals(['c'], keys(proxy));
+ assertEquals(['c'], keys(proxy2));
})();
diff --git a/test/mjsunit/es6/proxies-keys.js b/test/mjsunit/es6/proxies-keys.js
index 7344032..65dea6a 100644
--- a/test/mjsunit/es6/proxies-keys.js
+++ b/test/mjsunit/es6/proxies-keys.js
@@ -37,3 +37,14 @@
handler.ownKeys = undefined;
assertEquals(["target"], Object.keys(proxy));
assertEquals(["target"], Object.keys(target));
+
+var proxy2 = new Proxy(proxy, {});
+assertEquals(["target"], Object.keys(proxy2));
+
+
+(function testForSymbols() {
+ var symbol = Symbol();
+ var p = new Proxy({}, {ownKeys() { return ["1", symbol, "2"] }});
+ assertEquals(["1","2"], Object.getOwnPropertyNames(p));
+ assertEquals([symbol], Object.getOwnPropertySymbols(p));
+})();
diff --git a/test/mjsunit/es6/reflect-define-property.js b/test/mjsunit/es6/reflect-define-property.js
index b19c5aa..d62a934 100644
--- a/test/mjsunit/es6/reflect-define-property.js
+++ b/test/mjsunit/es6/reflect-define-property.js
@@ -441,8 +441,7 @@
}
-// Test runtime calls to DefineDataPropertyUnchecked and
-// DefineAccessorPropertyUnchecked - make sure we don't
+// Test runtime calls to DefineAccessorPropertyUnchecked - make sure we don't
// crash.
try {
%DefineAccessorPropertyUnchecked(0, 0, 0, 0, 0);
@@ -451,29 +450,11 @@
}
try {
- %DefineDataPropertyUnchecked(0, 0, 0, 0);
-} catch (e) {
- assertTrue(/illegal access/.test(e));
-}
-
-try {
- %DefineDataPropertyUnchecked(null, null, null, null);
-} catch (e) {
- assertTrue(/illegal access/.test(e));
-}
-
-try {
%DefineAccessorPropertyUnchecked(null, null, null, null, null);
} catch (e) {
assertTrue(/illegal access/.test(e));
}
-try {
- %DefineDataPropertyUnchecked({}, null, null, null);
-} catch (e) {
- assertTrue(/illegal access/.test(e));
-}
-
// Defining properties null should fail even when we have
// other allowed values
try {
@@ -482,12 +463,6 @@
assertTrue(/illegal access/.test(e));
}
-try {
- %DefineDataPropertyUnchecked(null, 'foo', 0, 0);
-} catch (e) {
- assertTrue(/illegal access/.test(e));
-}
-
// Test that all possible differences in step 6 in DefineOwnProperty are
// exercised, i.e., any difference in the given property descriptor and the
// existing properties should not return true, but throw an error if the
diff --git a/test/mjsunit/es6/regress/regress-3750.js b/test/mjsunit/es6/regress/regress-3750.js
deleted file mode 100644
index 10509bf..0000000
--- a/test/mjsunit/es6/regress/regress-3750.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Flags: --harmony-object-observe
-
-'use strict';
-class Example { }
-Object.observe(Example.prototype, function(){});
diff --git a/test/mjsunit/harmony/regress/regress-4482.js b/test/mjsunit/es6/regress/regress-4482.js
similarity index 91%
rename from test/mjsunit/harmony/regress/regress-4482.js
rename to test/mjsunit/es6/regress/regress-4482.js
index 2472b46..d813d21 100644
--- a/test/mjsunit/harmony/regress/regress-4482.js
+++ b/test/mjsunit/es6/regress/regress-4482.js
@@ -1,8 +1,6 @@
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-//
-// Flags: --harmony-sloppy
assertEquals("function", (function f() { f = 42; return typeof f })());
assertEquals("function",
diff --git a/test/mjsunit/es6/regress/regress-468661.js b/test/mjsunit/es6/regress/regress-468661.js
index 4a42350..4a58a71 100644
--- a/test/mjsunit/es6/regress/regress-468661.js
+++ b/test/mjsunit/es6/regress/regress-468661.js
@@ -9,7 +9,8 @@
var break_count = 0;
var expected_values =
- [ReferenceError, undefined, 0, 0, 0, 0, 1, ReferenceError, ReferenceError];
+ [ReferenceError, undefined, 0, 0, 0, 0, 1,
+ ReferenceError, ReferenceError];
function listener(event, exec_state, event_data, data) {
try {
@@ -39,7 +40,6 @@
assertTrue(v instanceof ReferenceError);
} else {
assertSame(expected_values[break_count], v);
-
}
++break_count;
diff --git a/test/mjsunit/es6/spread-call-new-class.js b/test/mjsunit/es6/spread-call-new-class.js
index 1fdf25b..de88cff 100644
--- a/test/mjsunit/es6/spread-call-new-class.js
+++ b/test/mjsunit/es6/spread-call-new-class.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy
-
(function testConstructClassStrict() {
"use strict";
diff --git a/test/mjsunit/es6/spread-call-super-property.js b/test/mjsunit/es6/spread-call-super-property.js
index b298a69..a85ea41 100644
--- a/test/mjsunit/es6/spread-call-super-property.js
+++ b/test/mjsunit/es6/spread-call-super-property.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy
-
(function testCallSuperPropertyStrict() {
"use strict";
class BaseClass {
diff --git a/test/mjsunit/es6/super.js b/test/mjsunit/es6/super.js
index a2ba1e8..4c80ce7 100644
--- a/test/mjsunit/es6/super.js
+++ b/test/mjsunit/es6/super.js
@@ -3,7 +3,6 @@
// found in the LICENSE file.
// Flags: --allow-natives-syntax
-// Flags: --harmony-sloppy
(function TestSuperNamedLoads() {
function Base() { }
diff --git a/test/mjsunit/es6/tail-call.js b/test/mjsunit/es6/tail-call.js
index d0d00f4..6ecf04f 100644
--- a/test/mjsunit/es6/tail-call.js
+++ b/test/mjsunit/es6/tail-call.js
@@ -3,6 +3,8 @@
// found in the LICENSE file.
// Flags: --allow-natives-syntax --harmony-tailcalls
+// Flags: --harmony-do-expressions
+
"use strict";
Error.prepareStackTrace = (error,stack) => {
@@ -259,9 +261,8 @@
}
%NeverOptimizeFunction(g);
- var context = 10;
function f(v) {
- return g(context);
+ return g();
}
%SetForceInlineFlag(f);
@@ -319,10 +320,57 @@
return f([f, g3, test], 13), f([f, test], 153);
}
+ function g4(a) {
+ return f([f, g4, test], false) ||
+ (f([f, g4, test], true) && f([f, test], true));
+ }
+
+ function g5(a) {
+ return f([f, g5, test], true) &&
+ (f([f, g5, test], false) || f([f, test], true));
+ }
+
+ function g6(a) {
+ return f([f, g6, test], 13), f([f, g6, test], 42),
+ f([f, test], 153);
+ }
+
+ function g7(a) {
+ return f([f, g7, test], false) ||
+ (f([f, g7, test], false) ? f([f, test], true)
+ : f([f, test], true));
+ }
+
+ function g8(a) {
+ return f([f, g8, test], false) || f([f, g8, test], true) &&
+ f([f, test], true);
+ }
+
+ function g9(a) {
+ return f([f, g9, test], true) && f([f, g9, test], false) ||
+ f([f, test], true);
+ }
+
+ function g10(a) {
+ return f([f, g10, test], true) && f([f, g10, test], false) ||
+ f([f, g10, test], true) ?
+ f([f, g10, test], true) && f([f, g10, test], false) ||
+ f([f, test], true) :
+ f([f, g10, test], true) && f([f, g10, test], false) ||
+ f([f, test], true);
+ }
+
function test() {
assertEquals(true, g1());
assertEquals(true, g2());
assertEquals(153, g3());
+ assertEquals(true, g4());
+ assertEquals(true, g5());
+ assertEquals(153, g6());
+ assertEquals(true, g7());
+ assertEquals(true, g8());
+ assertEquals(true, g9());
+ assertEquals(true, g10());
}
test();
test();
@@ -534,9 +582,34 @@
return (() => f_153([f_153, test]))();
}
+ function g3(a) {
+ var closure = () => f([f, closure, test], true)
+ ? f_153([f_153, test])
+ : f_153([f_153, test]);
+ return closure();
+ }
+
function test() {
assertEquals(153, g1());
assertEquals(153, g2());
+ assertEquals(153, g3());
+ }
+ test();
+ test();
+ %OptimizeFunctionOnNextCall(test);
+ test();
+})();
+
+
+// Test tail calls from do expressions.
+(function () {
+ function g1(a) {
+ var a = do { return f_153([f_153, test]); 42; };
+ return a;
+ }
+
+ function test() {
+ assertEquals(153, g1());
}
test();
test();
diff --git a/test/mjsunit/es7/object-observe-debug-event.js b/test/mjsunit/es7/object-observe-debug-event.js
deleted file mode 100644
index 06123b8..0000000
--- a/test/mjsunit/es7/object-observe-debug-event.js
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-object-observe
-// Flags: --expose-debug-as debug
-
-Debug = debug.Debug;
-
-var base_id = -1;
-var exception = null;
-var expected = [
- "enqueue #1",
- "willHandle #1",
- "didHandle #1",
-];
-
-function assertLog(msg) {
- print(msg);
- assertTrue(expected.length > 0);
- assertEquals(expected.shift(), msg);
- if (!expected.length) {
- Debug.setListener(null);
- }
-}
-
-function listener(event, exec_state, event_data, data) {
- if (event != Debug.DebugEvent.AsyncTaskEvent) return;
- try {
- if (base_id < 0)
- base_id = event_data.id();
- var id = event_data.id() - base_id + 1;
- assertEquals("Object.observe", event_data.name());
- assertLog(event_data.type() + " #" + id);
- } catch (e) {
- print(e + e.stack)
- exception = e;
- }
-}
-
-Debug.setListener(listener);
-
-var obj = {};
-Object.observe(obj, function(changes) {
- print(change.type + " " + change.name + " " + change.oldValue);
-});
-
-obj.foo = 1;
-obj.zoo = 2;
-obj.foo = 3;
-
-assertNull(exception);
diff --git a/test/mjsunit/es7/object-observe-runtime.js b/test/mjsunit/es7/object-observe-runtime.js
deleted file mode 100644
index 1a07141..0000000
--- a/test/mjsunit/es7/object-observe-runtime.js
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-object-observe
-// Flags: --allow-natives-syntax
-
-// These tests are meant to ensure that that the Object.observe runtime
-// functions are hardened.
-
-var obj = {};
-%SetIsObserved(obj);
-assertThrows(function() {
- %SetIsObserved(obj);
-});
-
-assertThrows(function() {
- %SetIsObserved(this);
-});
diff --git a/test/mjsunit/es7/object-observe.js b/test/mjsunit/es7/object-observe.js
deleted file mode 100644
index a558c51..0000000
--- a/test/mjsunit/es7/object-observe.js
+++ /dev/null
@@ -1,1865 +0,0 @@
-// Copyright 2012 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Flags: --harmony-object-observe
-// Flags: --allow-natives-syntax
-
-var allObservers = [];
-function reset() {
- allObservers.forEach(function(observer) { observer.reset(); });
-}
-
-function stringifyNoThrow(arg) {
- try {
- return JSON.stringify(arg);
- } catch (e) {
- return '{<circular reference>}';
- }
-}
-
-function createObserver() {
- "use strict"; // So that |this| in callback can be undefined.
-
- var observer = {
- records: undefined,
- callbackCount: 0,
- reset: function() {
- this.records = undefined;
- this.callbackCount = 0;
- },
- assertNotCalled: function() {
- assertEquals(undefined, this.records);
- assertEquals(0, this.callbackCount);
- },
- assertCalled: function() {
- assertEquals(1, this.callbackCount);
- },
- assertRecordCount: function(count) {
- this.assertCalled();
- assertEquals(count, this.records.length);
- },
- assertCallbackRecords: function(recs) {
- this.assertRecordCount(recs.length);
- for (var i = 0; i < recs.length; i++) {
- if ('name' in recs[i]) recs[i].name = String(recs[i].name);
- print(i, stringifyNoThrow(this.records[i]), stringifyNoThrow(recs[i]));
- assertSame(this.records[i].object, recs[i].object);
- assertEquals('string', typeof recs[i].type);
- assertPropertiesEqual(this.records[i], recs[i]);
- }
- }
- };
-
- observer.callback = function(r) {
- assertEquals(undefined, this);
- assertEquals('object', typeof r);
- assertTrue(r instanceof Array)
- observer.records = r;
- observer.callbackCount++;
- };
-
- observer.reset();
- allObservers.push(observer);
- return observer;
-}
-
-var observer = createObserver();
-var observer2 = createObserver();
-
-assertEquals("function", typeof observer.callback);
-assertEquals("function", typeof observer2.callback);
-
-var obj = {};
-
-function frozenFunction() {}
-Object.freeze(frozenFunction);
-var nonFunction = {};
-var changeRecordWithAccessor = { type: 'foo' };
-var recordCreated = false;
-Object.defineProperty(changeRecordWithAccessor, 'name', {
- get: function() {
- recordCreated = true;
- return "bar";
- },
- enumerable: true
-})
-
-
-// Object.observe
-assertThrows(function() { Object.observe("non-object", observer.callback); },
- TypeError);
-assertThrows(function() { Object.observe(this, observer.callback); },
- TypeError);
-assertThrows(function() { Object.observe(obj, nonFunction); }, TypeError);
-assertThrows(function() { Object.observe(obj, frozenFunction); }, TypeError);
-assertEquals(obj, Object.observe(obj, observer.callback, [1]));
-assertEquals(obj, Object.observe(obj, observer.callback, [true]));
-assertEquals(obj, Object.observe(obj, observer.callback, ['foo', null]));
-assertEquals(obj, Object.observe(obj, observer.callback, [undefined]));
-assertEquals(obj, Object.observe(obj, observer.callback,
- ['foo', 'bar', 'baz']));
-assertEquals(obj, Object.observe(obj, observer.callback, []));
-assertEquals(obj, Object.observe(obj, observer.callback, undefined));
-assertEquals(obj, Object.observe(obj, observer.callback));
-
-// Object.unobserve
-assertThrows(function() { Object.unobserve(4, observer.callback); }, TypeError);
-assertThrows(function() { Object.unobserve(this, observer.callback); },
- TypeError);
-assertThrows(function() { Object.unobserve(obj, nonFunction); }, TypeError);
-assertEquals(obj, Object.unobserve(obj, observer.callback));
-
-
-// Object.getNotifier
-var notifier = Object.getNotifier(obj);
-assertSame(notifier, Object.getNotifier(obj));
-assertEquals(null, Object.getNotifier(Object.freeze({})));
-assertThrows(function() { Object.getNotifier(this) }, TypeError);
-assertFalse(notifier.hasOwnProperty('notify'));
-assertEquals([], Object.keys(notifier));
-var notifyDesc = Object.getOwnPropertyDescriptor(notifier.__proto__, 'notify');
-assertTrue(notifyDesc.configurable);
-assertTrue(notifyDesc.writable);
-assertFalse(notifyDesc.enumerable);
-assertThrows(function() { notifier.notify({}); }, TypeError);
-assertThrows(function() { notifier.notify({ type: 4 }); }, TypeError);
-
-assertThrows(function() { notifier.performChange(1, function(){}); }, TypeError);
-assertThrows(function() { notifier.performChange(undefined, function(){}); }, TypeError);
-assertThrows(function() { notifier.performChange('foo', undefined); }, TypeError);
-assertThrows(function() { notifier.performChange('foo', 'bar'); }, TypeError);
-var global = this;
-notifier.performChange('foo', function() {
- assertEquals(global, this);
-});
-
-var notify = notifier.notify;
-assertThrows(function() { notify.call(undefined, { type: 'a' }); }, TypeError);
-assertThrows(function() { notify.call(null, { type: 'a' }); }, TypeError);
-assertThrows(function() { notify.call(5, { type: 'a' }); }, TypeError);
-assertThrows(function() { notify.call('hello', { type: 'a' }); }, TypeError);
-assertThrows(function() { notify.call(false, { type: 'a' }); }, TypeError);
-assertThrows(function() { notify.call({}, { type: 'a' }); }, TypeError);
-assertFalse(recordCreated);
-notifier.notify(changeRecordWithAccessor);
-assertFalse(recordCreated); // not observed yet
-
-
-// Object.deliverChangeRecords
-assertThrows(function() { Object.deliverChangeRecords(nonFunction); }, TypeError);
-
-Object.observe(obj, observer.callback);
-
-
-// notify uses to [[CreateOwnProperty]] to create changeRecord;
-reset();
-var protoExpandoAccessed = false;
-Object.defineProperty(Object.prototype, 'protoExpando',
- {
- configurable: true,
- set: function() { protoExpandoAccessed = true; }
- }
-);
-notifier.notify({ type: 'foo', protoExpando: 'val'});
-assertFalse(protoExpandoAccessed);
-delete Object.prototype.protoExpando;
-Object.deliverChangeRecords(observer.callback);
-
-
-// Multiple records are delivered.
-reset();
-notifier.notify({
- type: 'update',
- name: 'foo',
- expando: 1
-});
-
-notifier.notify({
- object: notifier, // object property is ignored
- type: 'delete',
- name: 'bar',
- expando2: 'str'
-});
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, name: 'foo', type: 'update', expando: 1 },
- { object: obj, name: 'bar', type: 'delete', expando2: 'str' }
-]);
-
-// Non-string accept values are coerced to strings
-reset();
-Object.observe(obj, observer.callback, [true, 1, null, undefined]);
-notifier = Object.getNotifier(obj);
-notifier.notify({ type: 'true' });
-notifier.notify({ type: 'false' });
-notifier.notify({ type: '1' });
-notifier.notify({ type: '-1' });
-notifier.notify({ type: 'null' });
-notifier.notify({ type: 'nill' });
-notifier.notify({ type: 'undefined' });
-notifier.notify({ type: 'defined' });
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, type: 'true' },
- { object: obj, type: '1' },
- { object: obj, type: 'null' },
- { object: obj, type: 'undefined' }
-]);
-
-// No delivery takes place if no records are pending
-reset();
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-
-// Multiple observation has no effect.
-reset();
-Object.observe(obj, observer.callback);
-Object.observe(obj, observer.callback);
-Object.getNotifier(obj).notify({
- type: 'update',
-});
-Object.deliverChangeRecords(observer.callback);
-observer.assertCalled();
-
-
-// Observation can be stopped.
-reset();
-Object.unobserve(obj, observer.callback);
-Object.getNotifier(obj).notify({
- type: 'update',
-});
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-
-// Multiple unobservation has no effect
-reset();
-Object.unobserve(obj, observer.callback);
-Object.unobserve(obj, observer.callback);
-Object.getNotifier(obj).notify({
- type: 'update',
-});
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-
-// Re-observation works and only includes changeRecords after of call.
-reset();
-Object.getNotifier(obj).notify({
- type: 'update',
-});
-Object.observe(obj, observer.callback);
-Object.getNotifier(obj).notify({
- type: 'update',
-});
-records = undefined;
-Object.deliverChangeRecords(observer.callback);
-observer.assertRecordCount(1);
-
-// Get notifier prior to observing
-reset();
-var obj = {};
-Object.getNotifier(obj);
-Object.observe(obj, observer.callback);
-obj.id = 1;
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, type: 'add', name: 'id' },
-]);
-
-// The empty-string property is observable
-reset();
-var obj = {};
-Object.observe(obj, observer.callback);
-obj[''] = '';
-obj[''] = ' ';
-delete obj[''];
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, type: 'add', name: '' },
- { object: obj, type: 'update', name: '', oldValue: '' },
- { object: obj, type: 'delete', name: '', oldValue: ' ' },
-]);
-
-// Object.preventExtensions
-reset();
-var obj = { foo: 'bar'};
-Object.observe(obj, observer.callback);
-obj.baz = 'bat';
-Object.preventExtensions(obj);
-
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, type: 'add', name: 'baz' },
- { object: obj, type: 'preventExtensions' },
-]);
-
-reset();
-var obj = { foo: 'bar'};
-Object.preventExtensions(obj);
-Object.observe(obj, observer.callback);
-Object.preventExtensions(obj);
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-// Object.freeze
-reset();
-var obj = { a: 'a' };
-Object.defineProperty(obj, 'b', {
- writable: false,
- configurable: true,
- value: 'b'
-});
-Object.defineProperty(obj, 'c', {
- writable: true,
- configurable: false,
- value: 'c'
-});
-Object.defineProperty(obj, 'd', {
- writable: false,
- configurable: false,
- value: 'd'
-});
-Object.observe(obj, observer.callback);
-Object.freeze(obj);
-
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, type: 'preventExtensions' },
- { object: obj, type: 'reconfigure', name: 'a' },
- { object: obj, type: 'reconfigure', name: 'b' },
- { object: obj, type: 'reconfigure', name: 'c' },
-]);
-
-reset();
-var obj = { foo: 'bar'};
-Object.freeze(obj);
-Object.observe(obj, observer.callback);
-Object.freeze(obj);
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-// Object.seal
-reset();
-var obj = { a: 'a' };
-Object.defineProperty(obj, 'b', {
- writable: false,
- configurable: true,
- value: 'b'
-});
-Object.defineProperty(obj, 'c', {
- writable: true,
- configurable: false,
- value: 'c'
-});
-Object.defineProperty(obj, 'd', {
- writable: false,
- configurable: false,
- value: 'd'
-});
-Object.observe(obj, observer.callback);
-Object.seal(obj);
-
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, type: 'preventExtensions' },
- { object: obj, type: 'reconfigure', name: 'a' },
- { object: obj, type: 'reconfigure', name: 'b' },
-]);
-
-reset();
-var obj = { foo: 'bar'};
-Object.seal(obj);
-Object.observe(obj, observer.callback);
-Object.seal(obj);
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-// Observing a continuous stream of changes, while itermittantly unobserving.
-reset();
-var obj = {};
-Object.observe(obj, observer.callback);
-Object.getNotifier(obj).notify({
- type: 'update',
- val: 1
-});
-
-Object.unobserve(obj, observer.callback);
-Object.getNotifier(obj).notify({
- type: 'update',
- val: 2
-});
-
-Object.observe(obj, observer.callback);
-Object.getNotifier(obj).notify({
- type: 'update',
- val: 3
-});
-
-Object.unobserve(obj, observer.callback);
-Object.getNotifier(obj).notify({
- type: 'update',
- val: 4
-});
-
-Object.observe(obj, observer.callback);
-Object.getNotifier(obj).notify({
- type: 'update',
- val: 5
-});
-
-Object.unobserve(obj, observer.callback);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, type: 'update', val: 1 },
- { object: obj, type: 'update', val: 3 },
- { object: obj, type: 'update', val: 5 }
-]);
-
-// Accept
-reset();
-Object.observe(obj, observer.callback, ['somethingElse']);
-Object.getNotifier(obj).notify({
- type: 'add'
-});
-Object.getNotifier(obj).notify({
- type: 'update'
-});
-Object.getNotifier(obj).notify({
- type: 'delete'
-});
-Object.getNotifier(obj).notify({
- type: 'reconfigure'
-});
-Object.getNotifier(obj).notify({
- type: 'setPrototype'
-});
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-reset();
-Object.observe(obj, observer.callback, ['add', 'delete', 'setPrototype']);
-Object.getNotifier(obj).notify({
- type: 'add'
-});
-Object.getNotifier(obj).notify({
- type: 'update'
-});
-Object.getNotifier(obj).notify({
- type: 'delete'
-});
-Object.getNotifier(obj).notify({
- type: 'delete'
-});
-Object.getNotifier(obj).notify({
- type: 'reconfigure'
-});
-Object.getNotifier(obj).notify({
- type: 'setPrototype'
-});
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, type: 'add' },
- { object: obj, type: 'delete' },
- { object: obj, type: 'delete' },
- { object: obj, type: 'setPrototype' }
-]);
-
-reset();
-Object.observe(obj, observer.callback, ['update', 'foo']);
-Object.getNotifier(obj).notify({
- type: 'add'
-});
-Object.getNotifier(obj).notify({
- type: 'update'
-});
-Object.getNotifier(obj).notify({
- type: 'delete'
-});
-Object.getNotifier(obj).notify({
- type: 'foo'
-});
-Object.getNotifier(obj).notify({
- type: 'bar'
-});
-Object.getNotifier(obj).notify({
- type: 'foo'
-});
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, type: 'update' },
- { object: obj, type: 'foo' },
- { object: obj, type: 'foo' }
-]);
-
-reset();
-function Thingy(a, b, c) {
- this.a = a;
- this.b = b;
-}
-
-Thingy.MULTIPLY = 'multiply';
-Thingy.INCREMENT = 'increment';
-Thingy.INCREMENT_AND_MULTIPLY = 'incrementAndMultiply';
-
-Thingy.prototype = {
- increment: function(amount) {
- var notifier = Object.getNotifier(this);
-
- var self = this;
- notifier.performChange(Thingy.INCREMENT, function() {
- self.a += amount;
- self.b += amount;
-
- return {
- incremented: amount
- }; // implicit notify
- });
- },
-
- multiply: function(amount) {
- var notifier = Object.getNotifier(this);
-
- var self = this;
- notifier.performChange(Thingy.MULTIPLY, function() {
- self.a *= amount;
- self.b *= amount;
-
- return {
- multiplied: amount
- }; // implicit notify
- });
- },
-
- incrementAndMultiply: function(incAmount, multAmount) {
- var notifier = Object.getNotifier(this);
-
- var self = this;
- notifier.performChange(Thingy.INCREMENT_AND_MULTIPLY, function() {
- self.increment(incAmount);
- self.multiply(multAmount);
-
- return {
- incremented: incAmount,
- multiplied: multAmount
- }; // implicit notify
- });
- }
-}
-
-Thingy.observe = function(thingy, callback) {
- Object.observe(thingy, callback, [Thingy.INCREMENT,
- Thingy.MULTIPLY,
- Thingy.INCREMENT_AND_MULTIPLY,
- 'update']);
-}
-
-Thingy.unobserve = function(thingy, callback) {
- Object.unobserve(thingy);
-}
-
-var thingy = new Thingy(2, 4);
-
-Object.observe(thingy, observer.callback);
-Thingy.observe(thingy, observer2.callback);
-thingy.increment(3); // { a: 5, b: 7 }
-thingy.b++; // { a: 5, b: 8 }
-thingy.multiply(2); // { a: 10, b: 16 }
-thingy.a++; // { a: 11, b: 16 }
-thingy.incrementAndMultiply(2, 2); // { a: 26, b: 36 }
-
-Object.deliverChangeRecords(observer.callback);
-Object.deliverChangeRecords(observer2.callback);
-observer.assertCallbackRecords([
- { object: thingy, type: 'update', name: 'a', oldValue: 2 },
- { object: thingy, type: 'update', name: 'b', oldValue: 4 },
- { object: thingy, type: 'update', name: 'b', oldValue: 7 },
- { object: thingy, type: 'update', name: 'a', oldValue: 5 },
- { object: thingy, type: 'update', name: 'b', oldValue: 8 },
- { object: thingy, type: 'update', name: 'a', oldValue: 10 },
- { object: thingy, type: 'update', name: 'a', oldValue: 11 },
- { object: thingy, type: 'update', name: 'b', oldValue: 16 },
- { object: thingy, type: 'update', name: 'a', oldValue: 13 },
- { object: thingy, type: 'update', name: 'b', oldValue: 18 },
-]);
-observer2.assertCallbackRecords([
- { object: thingy, type: Thingy.INCREMENT, incremented: 3 },
- { object: thingy, type: 'update', name: 'b', oldValue: 7 },
- { object: thingy, type: Thingy.MULTIPLY, multiplied: 2 },
- { object: thingy, type: 'update', name: 'a', oldValue: 10 },
- {
- object: thingy,
- type: Thingy.INCREMENT_AND_MULTIPLY,
- incremented: 2,
- multiplied: 2
- }
-]);
-
-// ArrayPush cached stub
-reset();
-
-function pushMultiple(arr) {
- arr.push('a');
- arr.push('b');
- arr.push('c');
-}
-
-for (var i = 0; i < 5; i++) {
- var arr = [];
- pushMultiple(arr);
-}
-
-for (var i = 0; i < 5; i++) {
- reset();
- var arr = [];
- Object.observe(arr, observer.callback);
- pushMultiple(arr);
- Object.unobserve(arr, observer.callback);
- Object.deliverChangeRecords(observer.callback);
- observer.assertCallbackRecords([
- { object: arr, type: 'add', name: '0' },
- { object: arr, type: 'update', name: 'length', oldValue: 0 },
- { object: arr, type: 'add', name: '1' },
- { object: arr, type: 'update', name: 'length', oldValue: 1 },
- { object: arr, type: 'add', name: '2' },
- { object: arr, type: 'update', name: 'length', oldValue: 2 },
- ]);
-}
-
-
-// ArrayPop cached stub
-reset();
-
-function popMultiple(arr) {
- arr.pop();
- arr.pop();
- arr.pop();
-}
-
-for (var i = 0; i < 5; i++) {
- var arr = ['a', 'b', 'c'];
- popMultiple(arr);
-}
-
-for (var i = 0; i < 5; i++) {
- reset();
- var arr = ['a', 'b', 'c'];
- Object.observe(arr, observer.callback);
- popMultiple(arr);
- Object.unobserve(arr, observer.callback);
- Object.deliverChangeRecords(observer.callback);
- observer.assertCallbackRecords([
- { object: arr, type: 'delete', name: '2', oldValue: 'c' },
- { object: arr, type: 'update', name: 'length', oldValue: 3 },
- { object: arr, type: 'delete', name: '1', oldValue: 'b' },
- { object: arr, type: 'update', name: 'length', oldValue: 2 },
- { object: arr, type: 'delete', name: '0', oldValue: 'a' },
- { object: arr, type: 'update', name: 'length', oldValue: 1 },
- ]);
-}
-
-
-reset();
-function RecursiveThingy() {}
-
-RecursiveThingy.MULTIPLY_FIRST_N = 'multiplyFirstN';
-
-RecursiveThingy.prototype = {
- __proto__: Array.prototype,
-
- multiplyFirstN: function(amount, n) {
- if (!n)
- return;
- var notifier = Object.getNotifier(this);
- var self = this;
- notifier.performChange(RecursiveThingy.MULTIPLY_FIRST_N, function() {
- self[n-1] = self[n-1]*amount;
- self.multiplyFirstN(amount, n-1);
- });
-
- notifier.notify({
- type: RecursiveThingy.MULTIPLY_FIRST_N,
- multiplied: amount,
- n: n
- });
- },
-}
-
-RecursiveThingy.observe = function(thingy, callback) {
- Object.observe(thingy, callback, [RecursiveThingy.MULTIPLY_FIRST_N]);
-}
-
-RecursiveThingy.unobserve = function(thingy, callback) {
- Object.unobserve(thingy);
-}
-
-var thingy = new RecursiveThingy;
-thingy.push(1, 2, 3, 4);
-
-Object.observe(thingy, observer.callback);
-RecursiveThingy.observe(thingy, observer2.callback);
-thingy.multiplyFirstN(2, 3); // [2, 4, 6, 4]
-
-Object.deliverChangeRecords(observer.callback);
-Object.deliverChangeRecords(observer2.callback);
-observer.assertCallbackRecords([
- { object: thingy, type: 'update', name: '2', oldValue: 3 },
- { object: thingy, type: 'update', name: '1', oldValue: 2 },
- { object: thingy, type: 'update', name: '0', oldValue: 1 }
-]);
-observer2.assertCallbackRecords([
- { object: thingy, type: RecursiveThingy.MULTIPLY_FIRST_N, multiplied: 2, n: 3 }
-]);
-
-reset();
-function DeckSuit() {
- this.push('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'A', 'Q', 'K');
-}
-
-DeckSuit.SHUFFLE = 'shuffle';
-
-DeckSuit.prototype = {
- __proto__: Array.prototype,
-
- shuffle: function() {
- var notifier = Object.getNotifier(this);
- var self = this;
- notifier.performChange(DeckSuit.SHUFFLE, function() {
- self.reverse();
- self.sort(function() { return Math.random()* 2 - 1; });
- var cut = self.splice(0, 6);
- Array.prototype.push.apply(self, cut);
- self.reverse();
- self.sort(function() { return Math.random()* 2 - 1; });
- var cut = self.splice(0, 6);
- Array.prototype.push.apply(self, cut);
- self.reverse();
- self.sort(function() { return Math.random()* 2 - 1; });
- });
-
- notifier.notify({
- type: DeckSuit.SHUFFLE
- });
- },
-}
-
-DeckSuit.observe = function(thingy, callback) {
- Object.observe(thingy, callback, [DeckSuit.SHUFFLE]);
-}
-
-DeckSuit.unobserve = function(thingy, callback) {
- Object.unobserve(thingy);
-}
-
-var deck = new DeckSuit;
-
-DeckSuit.observe(deck, observer2.callback);
-deck.shuffle();
-
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
- { object: deck, type: DeckSuit.SHUFFLE }
-]);
-
-// Observing multiple objects; records appear in order.
-reset();
-var obj2 = {};
-var obj3 = {}
-Object.observe(obj, observer.callback);
-Object.observe(obj3, observer.callback);
-Object.observe(obj2, observer.callback);
-Object.getNotifier(obj).notify({
- type: 'add',
-});
-Object.getNotifier(obj2).notify({
- type: 'update',
-});
-Object.getNotifier(obj3).notify({
- type: 'delete',
-});
-Object.observe(obj3, observer.callback);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, type: 'add' },
- { object: obj2, type: 'update' },
- { object: obj3, type: 'delete' }
-]);
-
-
-// Recursive observation.
-var obj = {a: 1};
-var callbackCount = 0;
-function recursiveObserver(r) {
- assertEquals(1, r.length);
- ++callbackCount;
- if (r[0].oldValue < 100) ++obj[r[0].name];
-}
-Object.observe(obj, recursiveObserver);
-++obj.a;
-Object.deliverChangeRecords(recursiveObserver);
-assertEquals(100, callbackCount);
-
-var obj1 = {a: 1};
-var obj2 = {a: 1};
-var recordCount = 0;
-function recursiveObserver2(r) {
- recordCount += r.length;
- if (r[0].oldValue < 100) {
- ++obj1.a;
- ++obj2.a;
- }
-}
-Object.observe(obj1, recursiveObserver2);
-Object.observe(obj2, recursiveObserver2);
-++obj1.a;
-Object.deliverChangeRecords(recursiveObserver2);
-assertEquals(199, recordCount);
-
-
-// Observing named properties.
-reset();
-var obj = {a: 1}
-Object.observe(obj, observer.callback);
-obj.a = 2;
-obj["a"] = 3;
-delete obj.a;
-obj.a = 4;
-obj.a = 4; // ignored
-obj.a = 5;
-Object.defineProperty(obj, "a", {value: 6});
-Object.defineProperty(obj, "a", {writable: false});
-obj.a = 7; // ignored
-Object.defineProperty(obj, "a", {value: 8});
-Object.defineProperty(obj, "a", {value: 7, writable: true});
-Object.defineProperty(obj, "a", {get: function() {}});
-Object.defineProperty(obj, "a", {get: frozenFunction});
-Object.defineProperty(obj, "a", {get: frozenFunction}); // ignored
-Object.defineProperty(obj, "a", {get: frozenFunction, set: frozenFunction});
-Object.defineProperty(obj, "a", {set: frozenFunction}); // ignored
-Object.defineProperty(obj, "a", {get: undefined, set: frozenFunction});
-delete obj.a;
-delete obj.a;
-Object.defineProperty(obj, "a", {get: function() {}, configurable: true});
-Object.defineProperty(obj, "a", {value: 9, writable: true});
-obj.a = 10;
-++obj.a;
-obj.a++;
-obj.a *= 3;
-delete obj.a;
-Object.defineProperty(obj, "a", {value: 11, configurable: true});
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, name: "a", type: "update", oldValue: 1 },
- { object: obj, name: "a", type: "update", oldValue: 2 },
- { object: obj, name: "a", type: "delete", oldValue: 3 },
- { object: obj, name: "a", type: "add" },
- { object: obj, name: "a", type: "update", oldValue: 4 },
- { object: obj, name: "a", type: "update", oldValue: 5 },
- { object: obj, name: "a", type: "reconfigure" },
- { object: obj, name: "a", type: "update", oldValue: 6 },
- { object: obj, name: "a", type: "reconfigure", oldValue: 8 },
- { object: obj, name: "a", type: "reconfigure", oldValue: 7 },
- { object: obj, name: "a", type: "reconfigure" },
- { object: obj, name: "a", type: "reconfigure" },
- { object: obj, name: "a", type: "reconfigure" },
- { object: obj, name: "a", type: "delete" },
- { object: obj, name: "a", type: "add" },
- { object: obj, name: "a", type: "reconfigure" },
- { object: obj, name: "a", type: "update", oldValue: 9 },
- { object: obj, name: "a", type: "update", oldValue: 10 },
- { object: obj, name: "a", type: "update", oldValue: 11 },
- { object: obj, name: "a", type: "update", oldValue: 12 },
- { object: obj, name: "a", type: "delete", oldValue: 36 },
- { object: obj, name: "a", type: "add" },
-]);
-
-
-// Observing indexed properties.
-reset();
-var obj = {'1': 1}
-Object.observe(obj, observer.callback);
-obj[1] = 2;
-obj[1] = 3;
-delete obj[1];
-obj[1] = 4;
-obj[1] = 4; // ignored
-obj[1] = 5;
-Object.defineProperty(obj, "1", {value: 6});
-Object.defineProperty(obj, "1", {writable: false});
-obj[1] = 7; // ignored
-Object.defineProperty(obj, "1", {value: 8});
-Object.defineProperty(obj, "1", {value: 7, writable: true});
-Object.defineProperty(obj, "1", {get: function() {}});
-Object.defineProperty(obj, "1", {get: frozenFunction});
-Object.defineProperty(obj, "1", {get: frozenFunction}); // ignored
-Object.defineProperty(obj, "1", {get: frozenFunction, set: frozenFunction});
-Object.defineProperty(obj, "1", {set: frozenFunction}); // ignored
-Object.defineProperty(obj, "1", {get: undefined, set: frozenFunction});
-delete obj[1];
-delete obj[1];
-Object.defineProperty(obj, "1", {get: function() {}, configurable: true});
-Object.defineProperty(obj, "1", {value: 9, writable: true});
-obj[1] = 10;
-++obj[1];
-obj[1]++;
-obj[1] *= 3;
-delete obj[1];
-Object.defineProperty(obj, "1", {value: 11, configurable: true});
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, name: "1", type: "update", oldValue: 1 },
- { object: obj, name: "1", type: "update", oldValue: 2 },
- { object: obj, name: "1", type: "delete", oldValue: 3 },
- { object: obj, name: "1", type: "add" },
- { object: obj, name: "1", type: "update", oldValue: 4 },
- { object: obj, name: "1", type: "update", oldValue: 5 },
- { object: obj, name: "1", type: "reconfigure" },
- { object: obj, name: "1", type: "update", oldValue: 6 },
- { object: obj, name: "1", type: "reconfigure", oldValue: 8 },
- { object: obj, name: "1", type: "reconfigure", oldValue: 7 },
- { object: obj, name: "1", type: "reconfigure" },
- { object: obj, name: "1", type: "reconfigure" },
- { object: obj, name: "1", type: "reconfigure" },
- { object: obj, name: "1", type: "delete" },
- { object: obj, name: "1", type: "add" },
- { object: obj, name: "1", type: "reconfigure" },
- { object: obj, name: "1", type: "update", oldValue: 9 },
- { object: obj, name: "1", type: "update", oldValue: 10 },
- { object: obj, name: "1", type: "update", oldValue: 11 },
- { object: obj, name: "1", type: "update", oldValue: 12 },
- { object: obj, name: "1", type: "delete", oldValue: 36 },
- { object: obj, name: "1", type: "add" },
-]);
-
-
-// Observing symbol properties (not).
-print("*****")
-reset();
-var obj = {}
-var symbol = Symbol("secret");
-Object.observe(obj, observer.callback);
-obj[symbol] = 3;
-delete obj[symbol];
-Object.defineProperty(obj, symbol, {get: function() {}, configurable: true});
-Object.defineProperty(obj, symbol, {value: 6});
-Object.defineProperty(obj, symbol, {writable: false});
-delete obj[symbol];
-Object.defineProperty(obj, symbol, {value: 7});
-++obj[symbol];
-obj[symbol]++;
-obj[symbol] *= 3;
-delete obj[symbol];
-obj.__defineSetter__(symbol, function() {});
-obj.__defineGetter__(symbol, function() {});
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-
-// Test all kinds of objects generically.
-function TestObserveConfigurable(obj, prop) {
- reset();
- Object.observe(obj, observer.callback);
- Object.unobserve(obj, observer.callback);
- obj[prop] = 1;
- Object.observe(obj, observer.callback);
- obj[prop] = 2;
- obj[prop] = 3;
- delete obj[prop];
- obj[prop] = 4;
- obj[prop] = 4; // ignored
- obj[prop] = 5;
- Object.defineProperty(obj, prop, {value: 6});
- Object.defineProperty(obj, prop, {writable: false});
- obj[prop] = 7; // ignored
- Object.defineProperty(obj, prop, {value: 8});
- Object.defineProperty(obj, prop, {value: 7, writable: true});
- Object.defineProperty(obj, prop, {get: function() {}});
- Object.defineProperty(obj, prop, {get: frozenFunction});
- Object.defineProperty(obj, prop, {get: frozenFunction}); // ignored
- Object.defineProperty(obj, prop, {get: frozenFunction, set: frozenFunction});
- Object.defineProperty(obj, prop, {set: frozenFunction}); // ignored
- Object.defineProperty(obj, prop, {get: undefined, set: frozenFunction});
- obj.__defineSetter__(prop, frozenFunction); // ignored
- obj.__defineSetter__(prop, function() {});
- obj.__defineGetter__(prop, function() {});
- delete obj[prop];
- delete obj[prop]; // ignored
- obj.__defineGetter__(prop, function() {});
- delete obj[prop];
- Object.defineProperty(obj, prop, {get: function() {}, configurable: true});
- Object.defineProperty(obj, prop, {value: 9, writable: true});
- obj[prop] = 10;
- ++obj[prop];
- obj[prop]++;
- obj[prop] *= 3;
- delete obj[prop];
- Object.defineProperty(obj, prop, {value: 11, configurable: true});
- Object.deliverChangeRecords(observer.callback);
- observer.assertCallbackRecords([
- { object: obj, name: prop, type: "update", oldValue: 1 },
- { object: obj, name: prop, type: "update", oldValue: 2 },
- { object: obj, name: prop, type: "delete", oldValue: 3 },
- { object: obj, name: prop, type: "add" },
- { object: obj, name: prop, type: "update", oldValue: 4 },
- { object: obj, name: prop, type: "update", oldValue: 5 },
- { object: obj, name: prop, type: "reconfigure" },
- { object: obj, name: prop, type: "update", oldValue: 6 },
- { object: obj, name: prop, type: "reconfigure", oldValue: 8 },
- { object: obj, name: prop, type: "reconfigure", oldValue: 7 },
- { object: obj, name: prop, type: "reconfigure" },
- { object: obj, name: prop, type: "reconfigure" },
- { object: obj, name: prop, type: "reconfigure" },
- { object: obj, name: prop, type: "reconfigure" },
- { object: obj, name: prop, type: "reconfigure" },
- { object: obj, name: prop, type: "delete" },
- { object: obj, name: prop, type: "add" },
- { object: obj, name: prop, type: "delete" },
- { object: obj, name: prop, type: "add" },
- { object: obj, name: prop, type: "reconfigure" },
- { object: obj, name: prop, type: "update", oldValue: 9 },
- { object: obj, name: prop, type: "update", oldValue: 10 },
- { object: obj, name: prop, type: "update", oldValue: 11 },
- { object: obj, name: prop, type: "update", oldValue: 12 },
- { object: obj, name: prop, type: "delete", oldValue: 36 },
- { object: obj, name: prop, type: "add" },
- ]);
- Object.unobserve(obj, observer.callback);
- delete obj[prop];
-}
-
-function TestObserveNonConfigurable(obj, prop, desc) {
- reset();
- Object.observe(obj, observer.callback);
- Object.unobserve(obj, observer.callback);
- obj[prop] = 1;
- Object.observe(obj, observer.callback);
- obj[prop] = 4;
- obj[prop] = 4; // ignored
- obj[prop] = 5;
- Object.defineProperty(obj, prop, {value: 6});
- Object.defineProperty(obj, prop, {value: 6}); // ignored
- Object.defineProperty(obj, prop, {value: 7});
- Object.defineProperty(obj, prop, {enumerable: desc.enumerable}); // ignored
- Object.defineProperty(obj, prop, {writable: false});
- obj[prop] = 7; // ignored
- Object.deliverChangeRecords(observer.callback);
- observer.assertCallbackRecords([
- { object: obj, name: prop, type: "update", oldValue: 1 },
- { object: obj, name: prop, type: "update", oldValue: 4 },
- { object: obj, name: prop, type: "update", oldValue: 5 },
- { object: obj, name: prop, type: "update", oldValue: 6 },
- { object: obj, name: prop, type: "reconfigure" },
- ]);
- Object.unobserve(obj, observer.callback);
-}
-
-// TODO(rafaelw) Enable when ES6 Proxies are implemented
-/*
-function createProxy(create, x) {
- var handler = {
- getPropertyDescriptor: function(k) {
- for (var o = this.target; o; o = Object.getPrototypeOf(o)) {
- var desc = Object.getOwnPropertyDescriptor(o, k);
- if (desc) return desc;
- }
- return undefined;
- },
- getOwnPropertyDescriptor: function(k) {
- return Object.getOwnPropertyDescriptor(this.target, k);
- },
- defineProperty: function(k, desc) {
- var x = Object.defineProperty(this.target, k, desc);
- Object.deliverChangeRecords(this.callback);
- return x;
- },
- delete: function(k) {
- var x = delete this.target[k];
- Object.deliverChangeRecords(this.callback);
- return x;
- },
- getPropertyNames: function() {
- return Object.getOwnPropertyNames(this.target);
- },
- target: {isProxy: true},
- callback: function(changeRecords) {
- print("callback", stringifyNoThrow(handler.proxy), stringifyNoThrow(got));
- for (var i in changeRecords) {
- var got = changeRecords[i];
- var change = {object: handler.proxy, name: got.name, type: got.type};
- if ("oldValue" in got) change.oldValue = got.oldValue;
- Object.getNotifier(handler.proxy).notify(change);
- }
- },
- };
- Object.observe(handler.target, handler.callback);
- return handler.proxy = create(handler, x);
-}
-*/
-
-var objects = [
- {},
- [],
- function(){},
- (function(){ return arguments })(),
- (function(){ "use strict"; return arguments })(),
- Object(1), Object(true), Object("bla"),
- new Date(),
- Object, Function, Date, RegExp,
- new Set, new Map, new WeakMap,
- new ArrayBuffer(10), new Int32Array(5)
-// TODO(rafaelw) Enable when ES6 Proxies are implemented.
-// createProxy(Proxy.create, null),
-// createProxy(Proxy.createFunction, function(){}),
-];
-var properties = ["a", "1", 1, "length", "setPrototype", "name", "caller"];
-
-// Cases that yield non-standard results.
-function blacklisted(obj, prop) {
- return (obj instanceof Int32Array && prop == 1) ||
- (obj instanceof Int32Array && prop === "length") ||
- (obj instanceof ArrayBuffer && prop == 1) ||
- (obj instanceof Function && prop === "name") || // Has its own test.
- (obj instanceof Function && prop === "length"); // Has its own test.
-}
-
-for (var i in objects) for (var j in properties) {
- var obj = objects[i];
- var prop = properties[j];
- if (blacklisted(obj, prop)) continue;
- var desc = Object.getOwnPropertyDescriptor(obj, prop);
- print("***", typeof obj, stringifyNoThrow(obj), prop);
- if (!desc || desc.configurable)
- TestObserveConfigurable(obj, prop);
- else if (desc.writable)
- TestObserveNonConfigurable(obj, prop, desc);
-}
-
-
-// Observing array length (including truncation)
-reset();
-var arr = ['a', 'b', 'c', 'd'];
-var arr2 = ['alpha', 'beta'];
-var arr3 = ['hello'];
-arr3[2] = 'goodbye';
-arr3.length = 6;
-Object.defineProperty(arr, '0', {configurable: false});
-Object.defineProperty(arr, '2', {get: function(){}});
-Object.defineProperty(arr2, '0', {get: function(){}, configurable: false});
-Object.observe(arr, observer.callback);
-Array.observe(arr, observer2.callback);
-Object.observe(arr2, observer.callback);
-Array.observe(arr2, observer2.callback);
-Object.observe(arr3, observer.callback);
-Array.observe(arr3, observer2.callback);
-arr.length = 2;
-arr.length = 0;
-arr.length = 10;
-Object.defineProperty(arr, 'length', {writable: false});
-arr2.length = 0;
-arr2.length = 1; // no change expected
-Object.defineProperty(arr2, 'length', {value: 1, writable: false});
-arr3.length = 0;
-++arr3.length;
-arr3.length++;
-arr3.length /= 2;
-Object.defineProperty(arr3, 'length', {value: 5});
-arr3[4] = 5;
-Object.defineProperty(arr3, 'length', {value: 1, writable: false});
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: arr, name: '3', type: 'delete', oldValue: 'd' },
- { object: arr, name: '2', type: 'delete' },
- { object: arr, name: 'length', type: 'update', oldValue: 4 },
- { object: arr, name: '1', type: 'delete', oldValue: 'b' },
- { object: arr, name: 'length', type: 'update', oldValue: 2 },
- { object: arr, name: 'length', type: 'update', oldValue: 1 },
- { object: arr, name: 'length', type: 'reconfigure' },
- { object: arr2, name: '1', type: 'delete', oldValue: 'beta' },
- { object: arr2, name: 'length', type: 'update', oldValue: 2 },
- { object: arr2, name: 'length', type: 'reconfigure' },
- { object: arr3, name: '2', type: 'delete', oldValue: 'goodbye' },
- { object: arr3, name: '0', type: 'delete', oldValue: 'hello' },
- { object: arr3, name: 'length', type: 'update', oldValue: 6 },
- { object: arr3, name: 'length', type: 'update', oldValue: 0 },
- { object: arr3, name: 'length', type: 'update', oldValue: 1 },
- { object: arr3, name: 'length', type: 'update', oldValue: 2 },
- { object: arr3, name: 'length', type: 'update', oldValue: 1 },
- { object: arr3, name: '4', type: 'add' },
- { object: arr3, name: '4', type: 'delete', oldValue: 5 },
- // TODO(rafaelw): It breaks spec compliance to get two records here.
- // When the TODO in v8natives.js::DefineArrayProperty is addressed
- // which prevents DefineProperty from over-writing the magic length
- // property, these will collapse into a single record.
- { object: arr3, name: 'length', type: 'update', oldValue: 5 },
- { object: arr3, name: 'length', type: 'reconfigure' }
-]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
- { object: arr, type: 'splice', index: 2, removed: [, 'd'], addedCount: 0 },
- { object: arr, type: 'splice', index: 1, removed: ['b'], addedCount: 0 },
- { object: arr, type: 'splice', index: 1, removed: [], addedCount: 9 },
- { object: arr2, type: 'splice', index: 1, removed: ['beta'], addedCount: 0 },
- { object: arr3, type: 'splice', index: 0, removed: ['hello',, 'goodbye',,,,], addedCount: 0 },
- { object: arr3, type: 'splice', index: 0, removed: [], addedCount: 1 },
- { object: arr3, type: 'splice', index: 1, removed: [], addedCount: 1 },
- { object: arr3, type: 'splice', index: 1, removed: [,], addedCount: 0 },
- { object: arr3, type: 'splice', index: 1, removed: [], addedCount: 4 },
- { object: arr3, name: '4', type: 'add' },
- { object: arr3, type: 'splice', index: 1, removed: [,,,5], addedCount: 0 }
-]);
-
-
-// Updating length on large (slow) array
-reset();
-var slow_arr = %NormalizeElements([]);
-slow_arr[500000000] = 'hello';
-slow_arr.length = 1000000000;
-Object.observe(slow_arr, observer.callback);
-var spliceRecords;
-function slowSpliceCallback(records) {
- spliceRecords = records;
-}
-Array.observe(slow_arr, slowSpliceCallback);
-slow_arr.length = 100;
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: slow_arr, name: '500000000', type: 'delete', oldValue: 'hello' },
- { object: slow_arr, name: 'length', type: 'update', oldValue: 1000000000 },
-]);
-Object.deliverChangeRecords(slowSpliceCallback);
-assertEquals(spliceRecords.length, 1);
-// Have to custom assert this splice record because the removed array is huge.
-var splice = spliceRecords[0];
-assertSame(splice.object, slow_arr);
-assertEquals(splice.type, 'splice');
-assertEquals(splice.index, 100);
-assertEquals(splice.addedCount, 0);
-var array_keys = %GetArrayKeys(splice.removed, splice.removed.length);
-assertEquals(array_keys.length, 1);
-assertEquals(array_keys[0], 499999900);
-assertEquals(splice.removed[499999900], 'hello');
-assertEquals(splice.removed.length, 999999900);
-
-
-// Assignments in loops (checking different IC states).
-reset();
-var obj = {};
-Object.observe(obj, observer.callback);
-for (var i = 0; i < 5; i++) {
- obj["a" + i] = i;
-}
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, name: "a0", type: "add" },
- { object: obj, name: "a1", type: "add" },
- { object: obj, name: "a2", type: "add" },
- { object: obj, name: "a3", type: "add" },
- { object: obj, name: "a4", type: "add" },
-]);
-
-reset();
-var obj = {};
-Object.observe(obj, observer.callback);
-for (var i = 0; i < 5; i++) {
- obj[i] = i;
-}
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, name: "0", type: "add" },
- { object: obj, name: "1", type: "add" },
- { object: obj, name: "2", type: "add" },
- { object: obj, name: "3", type: "add" },
- { object: obj, name: "4", type: "add" },
-]);
-
-
-// Adding elements past the end of an array should notify on length for
-// Object.observe and emit "splices" for Array.observe.
-reset();
-var arr = [1, 2, 3];
-Object.observe(arr, observer.callback);
-Array.observe(arr, observer2.callback);
-arr[3] = 10;
-arr[100] = 20;
-Object.defineProperty(arr, '200', {value: 7});
-Object.defineProperty(arr, '400', {get: function(){}});
-arr[50] = 30; // no length change expected
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: arr, name: '3', type: 'add' },
- { object: arr, name: 'length', type: 'update', oldValue: 3 },
- { object: arr, name: '100', type: 'add' },
- { object: arr, name: 'length', type: 'update', oldValue: 4 },
- { object: arr, name: '200', type: 'add' },
- { object: arr, name: 'length', type: 'update', oldValue: 101 },
- { object: arr, name: '400', type: 'add' },
- { object: arr, name: 'length', type: 'update', oldValue: 201 },
- { object: arr, name: '50', type: 'add' },
-]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
- { object: arr, type: 'splice', index: 3, removed: [], addedCount: 1 },
- { object: arr, type: 'splice', index: 4, removed: [], addedCount: 97 },
- { object: arr, type: 'splice', index: 101, removed: [], addedCount: 100 },
- { object: arr, type: 'splice', index: 201, removed: [], addedCount: 200 },
- { object: arr, type: 'add', name: '50' },
-]);
-
-
-// Tests for array methods, first on arrays and then on plain objects
-//
-// === ARRAYS ===
-//
-// Push
-reset();
-var array = [1, 2];
-Object.observe(array, observer.callback);
-Array.observe(array, observer2.callback);
-array.push(3, 4);
-array.push(5);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '2', type: 'add' },
- { object: array, name: 'length', type: 'update', oldValue: 2 },
- { object: array, name: '3', type: 'add' },
- { object: array, name: 'length', type: 'update', oldValue: 3 },
- { object: array, name: '4', type: 'add' },
- { object: array, name: 'length', type: 'update', oldValue: 4 },
-]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
- { object: array, type: 'splice', index: 2, removed: [], addedCount: 2 },
- { object: array, type: 'splice', index: 4, removed: [], addedCount: 1 }
-]);
-
-// Pop
-reset();
-var array = [1, 2];
-Object.observe(array, observer.callback);
-array.pop();
-array.pop();
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '1', type: 'delete', oldValue: 2 },
- { object: array, name: 'length', type: 'update', oldValue: 2 },
- { object: array, name: '0', type: 'delete', oldValue: 1 },
- { object: array, name: 'length', type: 'update', oldValue: 1 },
-]);
-
-// Shift
-reset();
-var array = [1, 2];
-Object.observe(array, observer.callback);
-array.shift();
-array.shift();
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '0', type: 'update', oldValue: 1 },
- { object: array, name: '1', type: 'delete', oldValue: 2 },
- { object: array, name: 'length', type: 'update', oldValue: 2 },
- { object: array, name: '0', type: 'delete', oldValue: 2 },
- { object: array, name: 'length', type: 'update', oldValue: 1 },
-]);
-
-// Unshift
-reset();
-var array = [1, 2];
-Object.observe(array, observer.callback);
-array.unshift(3, 4);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '3', type: 'add' },
- { object: array, name: 'length', type: 'update', oldValue: 2 },
- { object: array, name: '2', type: 'add' },
- { object: array, name: '0', type: 'update', oldValue: 1 },
- { object: array, name: '1', type: 'update', oldValue: 2 },
-]);
-
-// Splice
-reset();
-var array = [1, 2, 3];
-Object.observe(array, observer.callback);
-array.splice(1, 1, 4, 5);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '3', type: 'add' },
- { object: array, name: 'length', type: 'update', oldValue: 3 },
- { object: array, name: '1', type: 'update', oldValue: 2 },
- { object: array, name: '2', type: 'update', oldValue: 3 },
-]);
-
-// Sort
-reset();
-var array = [3, 2, 1];
-Object.observe(array, observer.callback);
-array.sort();
-assertEquals(1, array[0]);
-assertEquals(2, array[1]);
-assertEquals(3, array[2]);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '1', type: 'update', oldValue: 2 },
- { object: array, name: '0', type: 'update', oldValue: 3 },
- { object: array, name: '2', type: 'update', oldValue: 1 },
- { object: array, name: '1', type: 'update', oldValue: 3 },
- { object: array, name: '0', type: 'update', oldValue: 2 },
-]);
-
-// Splice emitted after Array mutation methods
-function MockArray(initial, observer) {
- for (var i = 0; i < initial.length; i++)
- this[i] = initial[i];
-
- this.length_ = initial.length;
- this.observer = observer;
-}
-MockArray.prototype = {
- set length(length) {
- Object.getNotifier(this).notify({ type: 'lengthChange' });
- this.length_ = length;
- Object.observe(this, this.observer.callback, ['splice']);
- },
- get length() {
- return this.length_;
- }
-}
-
-reset();
-var array = new MockArray([], observer);
-Object.observe(array, observer.callback, ['lengthChange']);
-Array.prototype.push.call(array, 1);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, type: 'lengthChange' },
- { object: array, type: 'splice', index: 0, removed: [], addedCount: 1 },
-]);
-
-reset();
-var array = new MockArray([1], observer);
-Object.observe(array, observer.callback, ['lengthChange']);
-Array.prototype.pop.call(array);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, type: 'lengthChange' },
- { object: array, type: 'splice', index: 0, removed: [1], addedCount: 0 },
-]);
-
-reset();
-var array = new MockArray([1], observer);
-Object.observe(array, observer.callback, ['lengthChange']);
-Array.prototype.shift.call(array);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, type: 'lengthChange' },
- { object: array, type: 'splice', index: 0, removed: [1], addedCount: 0 },
-]);
-
-reset();
-var array = new MockArray([], observer);
-Object.observe(array, observer.callback, ['lengthChange']);
-Array.prototype.unshift.call(array, 1);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, type: 'lengthChange' },
- { object: array, type: 'splice', index: 0, removed: [], addedCount: 1 },
-]);
-
-reset();
-var array = new MockArray([0, 1, 2], observer);
-Object.observe(array, observer.callback, ['lengthChange']);
-Array.prototype.splice.call(array, 1, 1);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, type: 'lengthChange' },
- { object: array, type: 'splice', index: 1, removed: [1], addedCount: 0 },
-]);
-
-//
-// === PLAIN OBJECTS ===
-//
-// Push
-reset()
-var array = {0: 1, 1: 2, length: 2}
-Object.observe(array, observer.callback);
-Array.prototype.push.call(array, 3, 4);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '2', type: 'add' },
- { object: array, name: '3', type: 'add' },
- { object: array, name: 'length', type: 'update', oldValue: 2 },
-]);
-
-// Pop
-reset();
-var array = [1, 2];
-Object.observe(array, observer.callback);
-Array.observe(array, observer2.callback);
-array.pop();
-array.pop();
-array.pop();
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '1', type: 'delete', oldValue: 2 },
- { object: array, name: 'length', type: 'update', oldValue: 2 },
- { object: array, name: '0', type: 'delete', oldValue: 1 },
- { object: array, name: 'length', type: 'update', oldValue: 1 },
-]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
- { object: array, type: 'splice', index: 1, removed: [2], addedCount: 0 },
- { object: array, type: 'splice', index: 0, removed: [1], addedCount: 0 }
-]);
-
-// Shift
-reset();
-var array = [1, 2];
-Object.observe(array, observer.callback);
-Array.observe(array, observer2.callback);
-array.shift();
-array.shift();
-array.shift();
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '0', type: 'update', oldValue: 1 },
- { object: array, name: '1', type: 'delete', oldValue: 2 },
- { object: array, name: 'length', type: 'update', oldValue: 2 },
- { object: array, name: '0', type: 'delete', oldValue: 2 },
- { object: array, name: 'length', type: 'update', oldValue: 1 },
-]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
- { object: array, type: 'splice', index: 0, removed: [1], addedCount: 0 },
- { object: array, type: 'splice', index: 0, removed: [2], addedCount: 0 }
-]);
-
-// Unshift
-reset();
-var array = [1, 2];
-Object.observe(array, observer.callback);
-Array.observe(array, observer2.callback);
-array.unshift(3, 4);
-array.unshift(5);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '3', type: 'add' },
- { object: array, name: 'length', type: 'update', oldValue: 2 },
- { object: array, name: '2', type: 'add' },
- { object: array, name: '0', type: 'update', oldValue: 1 },
- { object: array, name: '1', type: 'update', oldValue: 2 },
- { object: array, name: '4', type: 'add' },
- { object: array, name: 'length', type: 'update', oldValue: 4 },
- { object: array, name: '3', type: 'update', oldValue: 2 },
- { object: array, name: '2', type: 'update', oldValue: 1 },
- { object: array, name: '1', type: 'update', oldValue: 4 },
- { object: array, name: '0', type: 'update', oldValue: 3 },
-]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
- { object: array, type: 'splice', index: 0, removed: [], addedCount: 2 },
- { object: array, type: 'splice', index: 0, removed: [], addedCount: 1 }
-]);
-
-// Splice
-reset();
-var array = [1, 2, 3];
-Object.observe(array, observer.callback);
-Array.observe(array, observer2.callback);
-array.splice(1, 0, 4, 5); // 1 4 5 2 3
-array.splice(0, 2); // 5 2 3
-array.splice(1, 2, 6, 7); // 5 6 7
-array.splice(2, 0);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '4', type: 'add' },
- { object: array, name: 'length', type: 'update', oldValue: 3 },
- { object: array, name: '3', type: 'add' },
- { object: array, name: '1', type: 'update', oldValue: 2 },
- { object: array, name: '2', type: 'update', oldValue: 3 },
-
- { object: array, name: '0', type: 'update', oldValue: 1 },
- { object: array, name: '1', type: 'update', oldValue: 4 },
- { object: array, name: '2', type: 'update', oldValue: 5 },
- { object: array, name: '4', type: 'delete', oldValue: 3 },
- { object: array, name: '3', type: 'delete', oldValue: 2 },
- { object: array, name: 'length', type: 'update', oldValue: 5 },
-
- { object: array, name: '1', type: 'update', oldValue: 2 },
- { object: array, name: '2', type: 'update', oldValue: 3 },
-]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
- { object: array, type: 'splice', index: 1, removed: [], addedCount: 2 },
- { object: array, type: 'splice', index: 0, removed: [1, 4], addedCount: 0 },
- { object: array, type: 'splice', index: 1, removed: [2, 3], addedCount: 2 },
-]);
-
-// Exercise StoreIC_ArrayLength
-reset();
-var dummy = {};
-Object.observe(dummy, observer.callback);
-Object.unobserve(dummy, observer.callback);
-var array = [0];
-Object.observe(array, observer.callback);
-array.splice(0, 1);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: array, name: '0', type: 'delete', oldValue: 0 },
- { object: array, name: 'length', type: 'update', oldValue: 1},
-]);
-
-
-// __proto__
-reset();
-var obj = {};
-Object.observe(obj, observer.callback);
-var p = {foo: 'yes'};
-var q = {bar: 'no'};
-obj.__proto__ = p;
-obj.__proto__ = p; // ignored
-obj.__proto__ = null;
-obj.__proto__ = q; // the __proto__ accessor is gone
-// TODO(adamk): Add tests for objects with hidden prototypes
-// once we support observing the global object.
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
- { object: obj, name: '__proto__', type: 'setPrototype',
- oldValue: Object.prototype },
- { object: obj, name: '__proto__', type: 'setPrototype', oldValue: p },
- { object: obj, name: '__proto__', type: 'add' },
-]);
-
-
-// Function.prototype
-reset();
-var fun = function(){};
-Object.observe(fun, observer.callback);
-var myproto = {foo: 'bar'};
-fun.prototype = myproto;
-fun.prototype = 7;
-fun.prototype = 7; // ignored
-Object.defineProperty(fun, 'prototype', {value: 8});
-Object.deliverChangeRecords(observer.callback);
-observer.assertRecordCount(3);
-// Manually examine the first record in order to test
-// lazy creation of oldValue
-assertSame(fun, observer.records[0].object);
-assertEquals('prototype', observer.records[0].name);
-assertEquals('update', observer.records[0].type);
-// The only existing reference to the oldValue object is in this
-// record, so to test that lazy creation happened correctly
-// we compare its constructor to our function (one of the invariants
-// ensured when creating an object via AllocateFunctionPrototype).
-assertSame(fun, observer.records[0].oldValue.constructor);
-observer.records.splice(0, 1);
-observer.assertCallbackRecords([
- { object: fun, name: 'prototype', type: 'update', oldValue: myproto },
- { object: fun, name: 'prototype', type: 'update', oldValue: 7 },
-]);
-
-// Function.prototype should not be observable except on the object itself
-reset();
-var fun = function(){};
-var obj = { __proto__: fun };
-Object.observe(obj, observer.callback);
-obj.prototype = 7;
-Object.deliverChangeRecords(observer.callback);
-observer.assertRecordCount(1);
-observer.assertCallbackRecords([
- { object: obj, name: 'prototype', type: 'add' },
-]);
-
-// Check that changes in observation status are detected in all IC states and
-// in optimized code, especially in cases usually using fast elements.
-var mutation = [
- "a[i] = v",
- "a[i] ? ++a[i] : a[i] = v",
- "a[i] ? a[i]++ : a[i] = v",
- "a[i] ? a[i] += 1 : a[i] = v",
- "a[i] ? a[i] -= -1 : a[i] = v",
-];
-
-var props = [1, "1", "a"];
-
-function TestFastElements(prop, mutation, prepopulate, polymorphic, optimize) {
- var setElement = eval(
- "(function setElement(a, i, v) { " + mutation + "; " +
- "/* " + [].join.call(arguments, " ") + " */" +
- "})"
- );
- print("TestFastElements:", setElement);
-
- var arr = prepopulate ? [1, 2, 3, 4, 5] : [0];
- if (prepopulate) arr[prop] = 2; // for non-element case
- setElement(arr, prop, 3);
- setElement(arr, prop, 4);
- if (polymorphic) setElement(["M", "i", "l", "n", "e", "r"], 0, "m");
- if (optimize) %OptimizeFunctionOnNextCall(setElement);
- setElement(arr, prop, 5);
-
- reset();
- Object.observe(arr, observer.callback);
- setElement(arr, prop, 989898);
- Object.deliverChangeRecords(observer.callback);
- observer.assertCallbackRecords([
- { object: arr, name: "" + prop, type: 'update', oldValue: 5 }
- ]);
-}
-
-for (var b1 = 0; b1 < 2; ++b1)
- for (var b2 = 0; b2 < 2; ++b2)
- for (var b3 = 0; b3 < 2; ++b3)
- for (var i in props)
- for (var j in mutation)
- TestFastElements(props[i], mutation[j], b1 != 0, b2 != 0, b3 != 0);
-
-
-var mutation = [
- "a.length = v",
- "a.length += newSize - oldSize",
- "a.length -= oldSize - newSize",
-];
-
-var mutationByIncr = [
- "++a.length",
- "a.length++",
-];
-
-function TestFastElementsLength(
- mutation, polymorphic, optimize, oldSize, newSize) {
- var setLength = eval(
- "(function setLength(a, v) { " + mutation + "; " +
- "/* " + [].join.call(arguments, " ") + " */"
- + "})"
- );
- print("TestFastElementsLength:", setLength);
-
- function array(n) {
- var arr = new Array(n);
- for (var i = 0; i < n; ++i) arr[i] = i;
- return arr;
- }
-
- setLength(array(oldSize), newSize);
- setLength(array(oldSize), newSize);
- if (polymorphic) setLength(array(oldSize).map(isNaN), newSize);
- if (optimize) %OptimizeFunctionOnNextCall(setLength);
- setLength(array(oldSize), newSize);
-
- reset();
- var arr = array(oldSize);
- Object.observe(arr, observer.callback);
- setLength(arr, newSize);
- Object.deliverChangeRecords(observer.callback);
- if (oldSize === newSize) {
- observer.assertNotCalled();
- } else {
- var count = oldSize > newSize ? oldSize - newSize : 0;
- observer.assertRecordCount(count + 1);
- var lengthRecord = observer.records[count];
- assertSame(arr, lengthRecord.object);
- assertEquals('length', lengthRecord.name);
- assertEquals('update', lengthRecord.type);
- assertSame(oldSize, lengthRecord.oldValue);
- }
-}
-
-for (var b1 = 0; b1 < 2; ++b1)
- for (var b2 = 0; b2 < 2; ++b2)
- for (var n1 = 0; n1 < 3; ++n1)
- for (var n2 = 0; n2 < 3; ++n2)
- for (var i in mutation)
- TestFastElementsLength(mutation[i], b1 != 0, b2 != 0, 20*n1, 20*n2);
-
-for (var b1 = 0; b1 < 2; ++b1)
- for (var b2 = 0; b2 < 2; ++b2)
- for (var n = 0; n < 3; ++n)
- for (var i in mutationByIncr)
- TestFastElementsLength(mutationByIncr[i], b1 != 0, b2 != 0, 7*n, 7*n+1);
-
-
-(function TestFunctionName() {
- reset();
-
- function fun() {}
- Object.observe(fun, observer.callback);
- fun.name = 'x'; // No change. Not writable.
- Object.defineProperty(fun, 'name', {value: 'a'});
- Object.defineProperty(fun, 'name', {writable: true});
- fun.name = 'b';
- delete fun.name;
- fun.name = 'x'; // No change. Function.prototype.name is non writable
- Object.defineProperty(Function.prototype, 'name', {writable: true});
- fun.name = 'c';
- fun.name = 'c'; // Same, no update.
- Object.deliverChangeRecords(observer.callback);
- observer.assertCallbackRecords([
- { object: fun, type: 'update', name: 'name', oldValue: 'fun' },
- { object: fun, type: 'reconfigure', name: 'name'},
- { object: fun, type: 'update', name: 'name', oldValue: 'a' },
- { object: fun, type: 'delete', name: 'name', oldValue: 'b' },
- { object: fun, type: 'add', name: 'name' },
- ]);
-})();
-
-
-(function TestFunctionLength() {
- reset();
-
- function fun(x) {}
- Object.observe(fun, observer.callback);
- fun.length = 'x'; // No change. Not writable.
- Object.defineProperty(fun, 'length', {value: 'a'});
- Object.defineProperty(fun, 'length', {writable: true});
- fun.length = 'b';
- delete fun.length;
- fun.length = 'x'; // No change. Function.prototype.length is non writable
- Object.defineProperty(Function.prototype, 'length', {writable: true});
- fun.length = 'c';
- fun.length = 'c'; // Same, no update.
- Object.deliverChangeRecords(observer.callback);
- observer.assertCallbackRecords([
- { object: fun, type: 'update', name: 'length', oldValue: 1 },
- { object: fun, type: 'reconfigure', name: 'length'},
- { object: fun, type: 'update', name: 'length', oldValue: 'a' },
- { object: fun, type: 'delete', name: 'length', oldValue: 'b' },
- { object: fun, type: 'add', name: 'length' },
- ]);
-})();
-
-
-(function TestObserveInvalidAcceptMessage() {
- var ex;
- try {
- Object.observe({}, function(){}, "not an object");
- } catch (e) {
- ex = e;
- }
- assertInstanceof(ex, TypeError);
- assertEquals("Third argument to Object.observe must be an array of strings.",
- ex.message);
-})()
diff --git a/test/mjsunit/es7/regress/regress-443982.js b/test/mjsunit/es7/regress/regress-443982.js
deleted file mode 100644
index e04f14c..0000000
--- a/test/mjsunit/es7/regress/regress-443982.js
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Flags: --harmony-object-observe
-
-var records;
-function observer(r) {
- records = r;
-}
-
-Object.defineProperty(Array.prototype, '0', {
- get: function() { return 0; },
- set: function() { throw "boom!"; }
-});
-arr = [1, 2];
-Array.observe(arr, observer);
-arr.length = 0;
-assertEquals(0, arr.length);
-
-Object.deliverChangeRecords(observer);
-assertEquals(1, records.length);
-assertEquals('splice', records[0].type);
-assertArrayEquals([1, 2], records[0].removed);
diff --git a/test/mjsunit/es8/syntactic-tail-call-parsing-sloppy.js b/test/mjsunit/es8/syntactic-tail-call-parsing-sloppy.js
new file mode 100644
index 0000000..d026086
--- /dev/null
+++ b/test/mjsunit/es8/syntactic-tail-call-parsing-sloppy.js
@@ -0,0 +1,410 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --harmony-explicit-tailcalls
+// Flags: --harmony-do-expressions
+
+var SyntaxErrorTests = [
+ { msg: "Unexpected expression inside tail call",
+ tests: [
+ { src: `()=>{ return continue foo ; }`,
+ err: ` ^^^`,
+ },
+ { src: `()=>{ return continue 42 ; }`,
+ err: ` ^^`,
+ },
+ { src: `()=>{ return continue new foo () ; }`,
+ err: ` ^^^^^^^^^^`,
+ },
+ { src: `()=>{ loop: return continue loop ; }`,
+ err: ` ^^^^`,
+ },
+ { src: `class A { foo() { return continue super.x ; } }`,
+ err: ` ^^^^^^^`,
+ },
+ { src: `()=>{ return continue this ; }`,
+ err: ` ^^^^`,
+ },
+ { src: `()=>{ return continue class A {} ; }`,
+ err: ` ^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue class A extends B {} ; }`,
+ err: ` ^^^^^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue function A() { } ; }`,
+ err: ` ^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue { a: b, c: d} ; }`,
+ err: ` ^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue function* Gen() { yield 1; } ; }`,
+ err: ` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^`,
+ },
+ { src: `function A() { return continue new.target ; }`,
+ err: ` ^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue () ; }`,
+ err: ` ^^`,
+ },
+ { src: `()=>{ return continue ( 42 ) ; }`,
+ err: ` ^^^^^^`,
+ },
+ { src: "()=>{ return continue `123 ${foo} 34lk` ; }",
+ err: ` ^^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue do { x ? foo() : bar() ; } }`,
+ err: ` ^^^^^^^^^^^^^^^^^^^^^^^^^^`,
+ },
+ ],
+ },
+ { msg: "Tail call expression is not allowed here",
+ tests: [
+ { src: `class A {}; class B extends A { constructor() { return continue foo () ; } }`,
+ err: ` ^^^^^^^^^^^^^^^`,
+ },
+ { src: `class A extends continue f () {}; }`,
+ err: ` ^^^^^^^^^^^^^`,
+ },
+ ],
+ },
+ { msg: "Tail call expressions are not allowed in non-strict mode",
+ tests: [
+ { src: `()=>{ return continue continue continue b() ; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue ( continue b() ) ; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue f() - a ; }`,
+ err: ` ^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return b + continue f() ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return 1, 2, 3, continue f() , 4 ; }`,
+ err: ` ^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ var x = continue f ( ) ; }`,
+ err: ` ^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue f () ? 1 : 2 ; }`,
+ err: ` ^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return (1, 2, 3, continue f()), 4; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return [1, 2, continue f() ] ; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return [1, 2, ... continue f() ] ; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return [1, 2, continue f(), 3 ] ; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: "()=>{ return `123 ${a} ${ continue foo ( ) } 34lk` ; }",
+ err: ` ^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return g( 1, 2, continue f() ); }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue f() || a; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a || b || c || continue f() || d; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a && b && c && continue f() && d; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a && b || c && continue f() ? d : e; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a ? b : c && continue f() && d || e; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue foo() instanceof bar ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return bar instanceof continue foo() ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue foo() in bar ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return bar in continue foo() ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ function* G() { yield continue foo(); } }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ (1, 2, 3, continue f() ) => {} }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ (... continue f()) => {} }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ (a, b, c, ... continue f() ) => {} }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a <= continue f(); }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return b > continue f(); }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a << continue f(); }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return b >> continue f(); }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return c >>> continue f(); }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue f() = a ; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a = continue f() ; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a += continue f(); }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a ** continue f() ; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return delete continue foo() ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ typeof continue foo() ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return ~ continue foo() ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return void continue foo() ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return !continue foo() ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return -continue foo() ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return +continue foo() ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return ++ continue f( ) ; }`,
+ err: ` ^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue f() ++; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue f() --; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return (continue foo()) () ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ for (var i = continue foo(); i < 10; i++) bar(); }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ for (var i = 0; i < continue foo(); i++) bar(); }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ for (var i = 0; i < 10; continue foo()) bar(); }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ if (continue foo()) bar(); }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ while (continue foo()) bar(); }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ do { smth; } while (continue foo()) ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ throw continue foo() ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ switch (continue foo()) { case 1: break; } ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ with (continue foo()) { smth; } }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ let x = continue foo() }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ const c = continue foo() }`,
+ err: ` ^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ try { return continue f ( ) ; } catch(e) {} }`,
+ err: ` ^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ try { try { smth; } catch(e) { return continue f( ) ; } }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ try { try { smth; } catch(e) { return continue f( ) ; } } finally { bla; } }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ try { smth; } catch(e) { return continue f ( ) ; } finally { blah; } }`,
+ err: ` ^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ try { smth; } catch(e) { try { smth; } catch (e) { return continue f ( ) ; } } finally { blah; } }`,
+ err: ` ^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ for (var v in {a:0}) { return continue foo () ; } }`,
+ err: ` ^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ for (var v of [1, 2, 3]) { return continue foo () ; } }`,
+ err: ` ^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue a.b.c.foo () ; }`,
+ err: ` ^^^^^^^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue a().b.c().d.foo () ; }`,
+ err: ` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue foo (1)(2)(3, 4) ; }`,
+ err: ` ^^^^^^^^^^^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return ( continue b() ) ; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: "()=>{ return continue bar`ab cd ef` ; }",
+ err: ` ^^^^^^^^^^^^^^^^^^^^^^`,
+ },
+ { src: "()=>{ return continue bar`ab ${cd} ef` ; }",
+ err: ` ^^^^^^^^^^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a || continue f() ; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a && continue f() ; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a , continue f() ; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ function* G() { return continue foo(); } }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ function B() { return continue new.target() ; } }`,
+ err: ` ^^^^^^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue do { x ? foo() : bar() ; }() }`,
+ err: ` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue (do { x ? foo() : bar() ; })() }`,
+ err: ` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return do { 1, continue foo() } }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return do { x ? continue foo() : y } }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a || (b && continue c()); }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a && (b || continue c()); }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a || (b ? c : continue d()); }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return 1, 2, 3, a || (b ? c : continue d()); }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=> continue (foo ()) ;`,
+ err: ` ^^^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=> a || continue foo () ;`,
+ err: ` ^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=> a && continue foo () ;`,
+ err: ` ^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=> a ? continue foo () : b;`,
+ err: ` ^^^^^^^^^^^^^^^^`,
+ },
+ ],
+ },
+ { msg: "Undefined label 'foo'",
+ tests: [
+ { src: `()=>{ continue foo () ; }`,
+ err: ` ^^^`,
+ },
+ ],
+ },
+];
+
+
+// Should parse successfully.
+var NoErrorTests = [
+ `()=>{ class A { foo() { return continue super.f() ; } } }`,
+ `()=>{ class A { foo() { return continue f() ; } } }`,
+ `()=>{ class A { foo() { return a || continue f() ; } } }`,
+ `()=>{ class A { foo() { return b && continue f() ; } } }`,
+];
+
+
+(function() {
+ for (var test_set of SyntaxErrorTests) {
+ var expected_message = "SyntaxError: " + test_set.msg;
+ for (var test of test_set.tests) {
+ var passed = true;
+ var e = null;
+ try {
+ Realm.eval(0, test.src);
+ } catch (ee) {
+ e = ee;
+ }
+ print("=======================================");
+ print("Expected | " + expected_message);
+ print("Source | " + test.src);
+ print(" | " + test.err);
+
+ if (e === null) {
+ print("FAILED");
+ throw new Error("SyntaxError was not thrown");
+ }
+
+ var details = %GetExceptionDetails(e);
+ if (details.start_pos == undefined ||
+ details.end_pos == undefined) {
+ throw new Error("Bad message object returned");
+ }
+ var underline = " ".repeat(details.start_pos) +
+ "^".repeat(details.end_pos - details.start_pos);
+ var passed = expected_message === e.toString() &&
+ test.err === underline;
+
+ if (passed) {
+ print("PASSED");
+ print();
+ } else {
+ print("---------------------------------------");
+ print("Actual | " + e);
+ print("Source | " + test.src);
+ print(" | " + underline);
+ print("FAILED");
+ throw new Error("Test failed");
+ }
+ }
+ }
+})();
+
+
+(function() {
+ for (var src of NoErrorTests) {
+ print("=======================================");
+ print("Source | " + src);
+ Realm.eval(0, src);
+ print("PASSED");
+ print();
+ }
+})();
diff --git a/test/mjsunit/es8/syntactic-tail-call-parsing.js b/test/mjsunit/es8/syntactic-tail-call-parsing.js
new file mode 100644
index 0000000..9ceff9c
--- /dev/null
+++ b/test/mjsunit/es8/syntactic-tail-call-parsing.js
@@ -0,0 +1,388 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --harmony-explicit-tailcalls
+// Flags: --harmony-do-expressions
+"use strict";
+
+var SyntaxErrorTests = [
+ { msg: "Unexpected expression inside tail call",
+ tests: [
+ { src: `()=>{ return continue foo ; }`,
+ err: ` ^^^`,
+ },
+ { src: `()=>{ return continue 42 ; }`,
+ err: ` ^^`,
+ },
+ { src: `()=>{ return continue new foo () ; }`,
+ err: ` ^^^^^^^^^^`,
+ },
+ { src: `()=>{ loop: return continue loop ; }`,
+ err: ` ^^^^`,
+ },
+ { src: `class A { foo() { return continue super.x ; } }`,
+ err: ` ^^^^^^^`,
+ },
+ { src: `()=>{ return continue this ; }`,
+ err: ` ^^^^`,
+ },
+ { src: `()=>{ return continue class A {} ; }`,
+ err: ` ^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue class A extends B {} ; }`,
+ err: ` ^^^^^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue function A() { } ; }`,
+ err: ` ^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue { a: b, c: d} ; }`,
+ err: ` ^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue function* Gen() { yield 1; } ; }`,
+ err: ` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^`,
+ },
+ { src: `function A() { return continue new.target ; }`,
+ err: ` ^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue () ; }`,
+ err: ` ^^`,
+ },
+ { src: `()=>{ return continue ( 42 ) ; }`,
+ err: ` ^^^^^^`,
+ },
+ { src: "()=>{ return continue `123 ${foo} 34lk` ; }",
+ err: ` ^^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue do { x ? foo() : bar() ; } }`,
+ err: ` ^^^^^^^^^^^^^^^^^^^^^^^^^^`,
+ },
+ ],
+ },
+ { msg: "Tail call expression is not allowed here",
+ tests: [
+ { src: `()=>{ return continue continue continue b() ; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue ( continue b() ) ; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue f() - a ; }`,
+ err: ` ^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return b + continue f() ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return 1, 2, 3, continue f() , 4 ; }`,
+ err: ` ^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ var x = continue f ( ) ; }`,
+ err: ` ^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue f () ? 1 : 2 ; }`,
+ err: ` ^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return (1, 2, 3, continue f()), 4; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return [1, 2, continue f() ] ; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return [1, 2, ... continue f() ] ; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return [1, 2, continue f(), 3 ] ; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: "()=>{ return `123 ${a} ${ continue foo ( ) } 34lk` ; }",
+ err: ` ^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return g( 1, 2, continue f() ); }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue f() || a; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a || b || c || continue f() || d; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a && b && c && continue f() && d; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a && b || c && continue f() ? d : e; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a ? b : c && continue f() && d || e; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue foo() instanceof bar ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return bar instanceof continue foo() ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue foo() in bar ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return bar in continue foo() ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ function* G() { yield continue foo(); } }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ (1, 2, 3, continue f() ) => {} }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ (... continue f()) => {} }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ (a, b, c, ... continue f() ) => {} }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a <= continue f(); }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return b > continue f(); }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a << continue f(); }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return b >> continue f(); }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return c >>> continue f(); }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue f() = a ; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a = continue f() ; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a += continue f(); }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a ** continue f() ; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return delete continue foo() ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ typeof continue foo() ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return ~ continue foo() ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return void continue foo() ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return !continue foo() ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return -continue foo() ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return +continue foo() ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return ++ continue f( ) ; }`,
+ err: ` ^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue f() ++; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return continue f() --; }`,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return (continue foo()) () ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ for (var i = continue foo(); i < 10; i++) bar(); }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ for (var i = 0; i < continue foo(); i++) bar(); }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ for (var i = 0; i < 10; continue foo()) bar(); }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ if (continue foo()) bar(); }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ while (continue foo()) bar(); }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ do { smth; } while (continue foo()) ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ throw continue foo() ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ switch (continue foo()) { case 1: break; } ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ let x = continue foo() }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ const c = continue foo() }`,
+ err: ` ^^^^^^^^^^^^^^^`,
+ },
+ { src: `class A {}; class B extends A { constructor() { return continue foo () ; } }`,
+ err: ` ^^^^^^^^^^^^^^^`,
+ },
+ { src: `class A extends continue f () {}; }`,
+ err: ` ^^^^^^^^^^^^^`,
+ },
+ ],
+ },
+ { msg: "Tail call expression in try block",
+ tests: [
+ { src: `()=>{ try { return continue f ( ) ; } catch(e) {} }`,
+ err: ` ^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ try { try { smth; } catch(e) { return continue f( ) ; } }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ try { try { smth; } catch(e) { return continue f( ) ; } } finally { bla; } }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ ],
+ },
+ { msg: "Tail call expression in catch block when finally block is also present",
+ tests: [
+ { src: `()=>{ try { smth; } catch(e) { return continue f ( ) ; } finally { blah; } }`,
+ err: ` ^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ try { smth; } catch(e) { try { smth; } catch (e) { return continue f ( ) ; } } finally { blah; } }`,
+ err: ` ^^^^^^^^^^^^^^^^`,
+ },
+ ],
+ },
+ { msg: "Tail call expression in for-in/of body",
+ tests: [
+ { src: `()=>{ for (var v in {a:0}) { return continue foo () ; } }`,
+ err: ` ^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ for (var v of [1, 2, 3]) { return continue foo () ; } }`,
+ err: ` ^^^^^^^^^^^^^^^^`,
+ },
+ ],
+ },
+ { msg: "Tail call of a direct eval is not allowed",
+ tests: [
+ { src: `()=>{ return continue eval(" foo () " ) ; }`,
+ err: ` ^^^^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a || continue eval("", 1, 2) ; }`,
+ err: ` ^^^^^^^^^^^^^^`,
+ },
+ { src: `()=>{ return a, continue eval ( ) ; }`,
+ err: ` ^^^^^^^^^`,
+ },
+ { src: `()=> a, continue eval ( ) ; `,
+ err: ` ^^^^^^^^^`,
+ },
+ { src: `()=> a || continue eval (' ' ) ; `,
+ err: ` ^^^^^^^^^^^^`,
+ },
+ ],
+ },
+ { msg: "Undefined label 'foo'",
+ tests: [
+ { src: `()=>{ continue foo () ; }`,
+ err: ` ^^^`,
+ },
+ ],
+ },
+];
+
+
+// Should parse successfully.
+var NoErrorTests = [
+ `()=>{ return continue a.b.c.foo () ; }`,
+ `()=>{ return continue a().b.c().d.foo () ; }`,
+ `()=>{ return continue foo (1)(2)(3, 4) ; }`,
+ `()=>{ return continue (0, eval)(); }`,
+ `()=>{ return ( continue b() ) ; }`,
+ "()=>{ return continue bar`ab cd ef` ; }",
+ "()=>{ return continue bar`ab ${cd} ef` ; }",
+ `()=>{ return a || continue f() ; }`,
+ `()=>{ return a && continue f() ; }`,
+ `()=>{ return a , continue f() ; }`,
+ `()=>{ function* G() { return continue foo(); } }`,
+ `()=>{ class A { foo() { return continue super.f() ; } } }`,
+ `()=>{ function B() { return continue new.target() ; } }`,
+ `()=>{ return continue do { x ? foo() : bar() ; }() }`,
+ `()=>{ return continue (do { x ? foo() : bar() ; })() }`,
+ `()=>{ return do { 1, continue foo() } }`,
+ `()=>{ return do { x ? continue foo() : y } }`,
+ `()=>{ return a || (b && continue c()); }`,
+ `()=>{ return a && (b || continue c()); }`,
+ `()=>{ return a || (b ? c : continue d()); }`,
+ `()=>{ return 1, 2, 3, a || (b ? c : continue d()); }`,
+ `()=> continue (foo ()) ;`,
+ `()=> a || continue foo () ;`,
+ `()=> a && continue foo () ;`,
+ `()=> a ? continue foo () : b;`,
+];
+
+
+(function() {
+ for (var test_set of SyntaxErrorTests) {
+ var expected_message = "SyntaxError: " + test_set.msg;
+ for (var test of test_set.tests) {
+ var passed = true;
+ var e = null;
+ try {
+ eval(test.src);
+ } catch (ee) {
+ e = ee;
+ }
+ print("=======================================");
+ print("Expected | " + expected_message);
+ print("Source | " + test.src);
+ print(" | " + test.err);
+
+ if (e === null) {
+ print("FAILED");
+ throw new Error("SyntaxError was not thrown");
+ }
+
+ var details = %GetExceptionDetails(e);
+ if (details.start_pos == undefined ||
+ details.end_pos == undefined) {
+ throw new Error("Bad message object returned");
+ }
+ var underline = " ".repeat(details.start_pos) +
+ "^".repeat(details.end_pos - details.start_pos);
+ var passed = expected_message === e.toString() &&
+ test.err === underline;
+
+ if (passed) {
+ print("PASSED");
+ print();
+ } else {
+ print("---------------------------------------");
+ print("Actual | " + e);
+ print("Source | " + test.src);
+ print(" | " + underline);
+ print("FAILED");
+ throw new Error("Test failed");
+ }
+ }
+ }
+})();
+
+
+(function() {
+ for (var src of NoErrorTests) {
+ print("=======================================");
+ print("Source | " + src);
+ src = `"use strict"; ` + src;
+ Realm.eval(0, src);
+ print("PASSED");
+ print();
+ }
+})();
diff --git a/test/mjsunit/es8/syntactic-tail-call-simple.js b/test/mjsunit/es8/syntactic-tail-call-simple.js
new file mode 100644
index 0000000..ec7ade6
--- /dev/null
+++ b/test/mjsunit/es8/syntactic-tail-call-simple.js
@@ -0,0 +1,143 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --harmony-explicit-tailcalls --stack-size=100
+
+//
+// Tail calls work only in strict mode.
+//
+(function() {
+ function f(n) {
+ if (n <= 0) {
+ return "foo";
+ }
+ return f(n - 1);
+ }
+ assertThrows(()=>{ f(1e5) });
+ %OptimizeFunctionOnNextCall(f);
+ assertThrows(()=>{ f(1e5) });
+})();
+
+
+//
+// Tail call normal functions.
+//
+(function() {
+ "use strict";
+ function f(n) {
+ if (n <= 0) {
+ return "foo";
+ }
+ return continue f(n - 1);
+ }
+ assertEquals("foo", f(1e5));
+ %OptimizeFunctionOnNextCall(f);
+ assertEquals("foo", f(1e5));
+})();
+
+
+(function() {
+ "use strict";
+ function f(n) {
+ if (n <= 0) {
+ return "foo";
+ }
+ return continue f(n - 1, 42); // Call with arguments adaptor.
+ }
+ assertEquals("foo", f(1e5));
+ %OptimizeFunctionOnNextCall(f);
+ assertEquals("foo", f(1e5));
+})();
+
+
+(function() {
+ "use strict";
+ function f(n){
+ if (n <= 0) {
+ return "foo";
+ }
+ return continue g(n - 1);
+ }
+ function g(n){
+ if (n <= 0) {
+ return "bar";
+ }
+ return continue f(n - 1);
+ }
+ assertEquals("foo", f(1e5));
+ assertEquals("bar", f(1e5 + 1));
+ %OptimizeFunctionOnNextCall(f);
+ assertEquals("foo", f(1e5));
+ assertEquals("bar", f(1e5 + 1));
+})();
+
+
+(function() {
+ "use strict";
+ function f(n){
+ if (n <= 0) {
+ return "foo";
+ }
+ return continue g(n - 1, 42); // Call with arguments adaptor.
+ }
+ function g(n){
+ if (n <= 0) {
+ return "bar";
+ }
+ return continue f(n - 1, 42); // Call with arguments adaptor.
+ }
+ assertEquals("foo", f(1e5));
+ assertEquals("bar", f(1e5 + 1));
+ %OptimizeFunctionOnNextCall(f);
+ assertEquals("foo", f(1e5));
+ assertEquals("bar", f(1e5 + 1));
+})();
+
+
+//
+// Tail call bound functions.
+//
+(function() {
+ "use strict";
+ function f0(n) {
+ if (n <= 0) {
+ return "foo";
+ }
+ return continue f_bound(n - 1);
+ }
+ var f_bound = f0.bind({});
+ function f(n) {
+ return continue f_bound(n);
+ }
+ assertEquals("foo", f(1e5));
+ %OptimizeFunctionOnNextCall(f);
+ assertEquals("foo", f(1e5));
+})();
+
+
+(function() {
+ "use strict";
+ function f0(n){
+ if (n <= 0) {
+ return "foo";
+ }
+ return continue g_bound(n - 1);
+ }
+ function g0(n){
+ if (n <= 0) {
+ return "bar";
+ }
+ return continue f_bound(n - 1);
+ }
+ var f_bound = f0.bind({});
+ var g_bound = g0.bind({});
+ function f(n) {
+ return continue f_bound(n);
+ }
+ assertEquals("foo", f(1e5));
+ assertEquals("bar", f(1e5 + 1));
+ %OptimizeFunctionOnNextCall(f);
+ assertEquals("foo", f(1e5));
+ assertEquals("bar", f(1e5 + 1));
+})();
diff --git a/test/mjsunit/es8/syntactic-tail-call.js b/test/mjsunit/es8/syntactic-tail-call.js
new file mode 100644
index 0000000..44936a4
--- /dev/null
+++ b/test/mjsunit/es8/syntactic-tail-call.js
@@ -0,0 +1,604 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --harmony-explicit-tailcalls
+// Flags: --harmony-do-expressions
+
+"use strict";
+
+Error.prepareStackTrace = (error,stack) => {
+ error.strace = stack;
+ return error.message + "\n at " + stack.join("\n at ");
+}
+
+
+function CheckStackTrace(expected) {
+ var e = new Error();
+ e.stack; // prepare stack trace
+ var stack = e.strace;
+ assertEquals("CheckStackTrace", stack[0].getFunctionName());
+ for (var i = 0; i < expected.length; i++) {
+ assertEquals(expected[i].name, stack[i + 1].getFunctionName());
+ }
+}
+%NeverOptimizeFunction(CheckStackTrace);
+
+
+function f(expected_call_stack, a, b) {
+ CheckStackTrace(expected_call_stack);
+ return a;
+}
+
+function f_153(expected_call_stack, a) {
+ CheckStackTrace(expected_call_stack);
+ return 153;
+}
+
+
+// Tail call when caller does not have an arguments adaptor frame.
+(function() {
+ // Caller and callee have same number of arguments.
+ function f1(a) {
+ CheckStackTrace([f1, test]);
+ return 10 + a;
+ }
+ function g1(a) { return continue f1(2); }
+
+ // Caller has more arguments than callee.
+ function f2(a) {
+ CheckStackTrace([f2, test]);
+ return 10 + a;
+ }
+ function g2(a, b, c) { return continue f2(2); }
+
+ // Caller has less arguments than callee.
+ function f3(a, b, c) {
+ CheckStackTrace([f3, test]);
+ return 10 + a + b + c;
+ }
+ function g3(a) { return continue f3(2, 3, 4); }
+
+ // Callee has arguments adaptor frame.
+ function f4(a, b, c) {
+ CheckStackTrace([f4, test]);
+ return 10 + a;
+ }
+ function g4(a) { return continue f4(2); }
+
+ function test() {
+ assertEquals(12, g1(1));
+ assertEquals(12, g2(1, 2, 3));
+ assertEquals(19, g3(1));
+ assertEquals(12, g4(1));
+ }
+ test();
+ test();
+ %OptimizeFunctionOnNextCall(test);
+ test();
+})();
+
+
+// Tail call when caller has an arguments adaptor frame.
+(function() {
+ // Caller and callee have same number of arguments.
+ function f1(a) {
+ CheckStackTrace([f1, test]);
+ return 10 + a;
+ }
+ function g1(a) { return continue f1(2); }
+
+ // Caller has more arguments than callee.
+ function f2(a) {
+ CheckStackTrace([f2, test]);
+ return 10 + a;
+ }
+ function g2(a, b, c) { return continue f2(2); }
+
+ // Caller has less arguments than callee.
+ function f3(a, b, c) {
+ CheckStackTrace([f3, test]);
+ return 10 + a + b + c;
+ }
+ function g3(a) { return continue f3(2, 3, 4); }
+
+ // Callee has arguments adaptor frame.
+ function f4(a, b, c) {
+ CheckStackTrace([f4, test]);
+ return 10 + a;
+ }
+ function g4(a) { return continue f4(2); }
+
+ function test() {
+ assertEquals(12, g1());
+ assertEquals(12, g2());
+ assertEquals(19, g3());
+ assertEquals(12, g4());
+ }
+ test();
+ test();
+ %OptimizeFunctionOnNextCall(test);
+ test();
+})();
+
+
+// Tail call bound function when caller does not have an arguments
+// adaptor frame.
+(function() {
+ // Caller and callee have same number of arguments.
+ function f1(a) {
+ assertEquals(153, this.a);
+ CheckStackTrace([f1, test]);
+ return 10 + a;
+ }
+ var b1 = f1.bind({a: 153});
+ function g1(a) { return continue b1(2); }
+
+ // Caller has more arguments than callee.
+ function f2(a) {
+ assertEquals(153, this.a);
+ CheckStackTrace([f2, test]);
+ return 10 + a;
+ }
+ var b2 = f2.bind({a: 153});
+ function g2(a, b, c) { return continue b2(2); }
+
+ // Caller has less arguments than callee.
+ function f3(a, b, c) {
+ assertEquals(153, this.a);
+ CheckStackTrace([f3, test]);
+ return 10 + a + b + c;
+ }
+ var b3 = f3.bind({a: 153});
+ function g3(a) { return continue b3(2, 3, 4); }
+
+ // Callee has arguments adaptor frame.
+ function f4(a, b, c) {
+ assertEquals(153, this.a);
+ CheckStackTrace([f4, test]);
+ return 10 + a;
+ }
+ var b4 = f4.bind({a: 153});
+ function g4(a) { return continue b4(2); }
+
+ function test() {
+ assertEquals(12, g1(1));
+ assertEquals(12, g2(1, 2, 3));
+ assertEquals(19, g3(1));
+ assertEquals(12, g4(1));
+ }
+ test();
+ test();
+ %OptimizeFunctionOnNextCall(test);
+ test();
+})();
+
+
+// Tail call bound function when caller has an arguments adaptor frame.
+(function() {
+ // Caller and callee have same number of arguments.
+ function f1(a) {
+ assertEquals(153, this.a);
+ CheckStackTrace([f1, test]);
+ return 10 + a;
+ }
+ var b1 = f1.bind({a: 153});
+ function g1(a) { return continue b1(2); }
+
+ // Caller has more arguments than callee.
+ function f2(a) {
+ assertEquals(153, this.a);
+ CheckStackTrace([f2, test]);
+ return 10 + a;
+ }
+ var b2 = f2.bind({a: 153});
+ function g2(a, b, c) { return continue b2(2); }
+
+ // Caller has less arguments than callee.
+ function f3(a, b, c) {
+ assertEquals(153, this.a);
+ CheckStackTrace([f3, test]);
+ return 10 + a + b + c;
+ }
+ var b3 = f3.bind({a: 153});
+ function g3(a) { return continue b3(2, 3, 4); }
+
+ // Callee has arguments adaptor frame.
+ function f4(a, b, c) {
+ assertEquals(153, this.a);
+ CheckStackTrace([f4, test]);
+ return 10 + a;
+ }
+ var b4 = f4.bind({a: 153});
+ function g4(a) { return continue b4(2); }
+
+ function test() {
+ assertEquals(12, g1());
+ assertEquals(12, g2());
+ assertEquals(19, g3());
+ assertEquals(12, g4());
+ }
+ test();
+ test();
+ %OptimizeFunctionOnNextCall(test);
+ test();
+})();
+
+
+// Tail calling from getter.
+(function() {
+ function g(v) {
+ CheckStackTrace([g, test]);
+ %DeoptimizeFunction(test);
+ return 153;
+ }
+ %NeverOptimizeFunction(g);
+
+ function f(v) {
+ return continue g();
+ }
+ %SetForceInlineFlag(f);
+
+ function test() {
+ var o = {};
+ o.__defineGetter__('p', f);
+ assertEquals(153, o.p);
+ }
+
+ test();
+ test();
+ %OptimizeFunctionOnNextCall(test);
+ test();
+})();
+
+
+// Tail calling from setter.
+(function() {
+ function g() {
+ CheckStackTrace([g, test]);
+ %DeoptimizeFunction(test);
+ return 153;
+ }
+ %NeverOptimizeFunction(g);
+
+ function f(v) {
+ return continue g();
+ }
+ %SetForceInlineFlag(f);
+
+ function test() {
+ var o = {};
+ o.__defineSetter__('q', f);
+ assertEquals(1, o.q = 1);
+ }
+
+ test();
+ test();
+ %OptimizeFunctionOnNextCall(test);
+ test();
+})();
+
+
+// Tail calling from constructor.
+(function() {
+ function g(context) {
+ CheckStackTrace([g, test]);
+ %DeoptimizeFunction(test);
+ return {x: 153};
+ }
+ %NeverOptimizeFunction(g);
+
+ function A() {
+ this.x = 42;
+ return continue g();
+ }
+
+ function test() {
+ var o = new A();
+ %DebugPrint(o);
+ assertEquals(153, o.x);
+ }
+
+ test();
+ test();
+ %OptimizeFunctionOnNextCall(test);
+ test();
+})();
+
+
+// Tail calling via various expressions.
+(function() {
+ function g1(a) {
+ return f([f, g1, test], false) || continue f([f, test], true);
+ }
+
+ function g2(a) {
+ return f([f, g2, test], true) && continue f([f, test], true);
+ }
+
+ function g3(a) {
+ return f([f, g3, test], 13), continue f([f, test], 153);
+ }
+
+ function g4(a) {
+ return f([f, g4, test], false) ||
+ (f([f, g4, test], true) && continue f([f, test], true));
+ }
+
+ function g5(a) {
+ return f([f, g5, test], true) &&
+ (f([f, g5, test], false) || continue f([f, test], true));
+ }
+
+ function g6(a) {
+ return f([f, g6, test], 13), f([f, g6, test], 42),
+ continue f([f, test], 153);
+ }
+
+ function g7(a) {
+ return f([f, g7, test], false) ||
+ (f([f, g7, test], false) ? continue f([f, test], true)
+ : continue f([f, test], true));
+ }
+
+ function g8(a) {
+ return f([f, g8, test], false) || f([f, g8, test], true) &&
+ continue f([f, test], true);
+ }
+
+ function g9(a) {
+ return f([f, g9, test], true) && f([f, g9, test], false) ||
+ continue f([f, test], true);
+ }
+
+ function g10(a) {
+ return f([f, g10, test], true) && f([f, g10, test], false) ||
+ f([f, g10, test], true) ?
+ f([f, g10, test], true) && f([f, g10, test], false) ||
+ continue f([f, test], true) :
+ f([f, g10, test], true) && f([f, g10, test], false) ||
+ continue f([f, test], true);
+ }
+
+ function test() {
+ assertEquals(true, g1());
+ assertEquals(true, g2());
+ assertEquals(153, g3());
+ assertEquals(true, g4());
+ assertEquals(true, g5());
+ assertEquals(153, g6());
+ assertEquals(true, g7());
+ assertEquals(true, g8());
+ assertEquals(true, g9());
+ assertEquals(true, g10());
+ }
+ test();
+ test();
+ %OptimizeFunctionOnNextCall(test);
+ test();
+})();
+
+
+// Tail calling from various statements.
+(function() {
+ function g3() {
+ for (var i = 0; i < 10; i++) {
+ return continue f_153([f_153, test]);
+ }
+ }
+
+ function g4() {
+ while (true) {
+ return continue f_153([f_153, test]);
+ }
+ }
+
+ function g5() {
+ do {
+ return continue f_153([f_153, test]);
+ } while (true);
+ }
+
+ function test() {
+ assertEquals(153, g3());
+ assertEquals(153, g4());
+ assertEquals(153, g5());
+ }
+ test();
+ test();
+ %OptimizeFunctionOnNextCall(test);
+ test();
+})();
+
+
+// Test tail calls from try-catch constructs.
+(function() {
+ function tc1(a) {
+ try {
+ f_153([f_153, tc1, test]);
+ return f_153([f_153, tc1, test]);
+ } catch(e) {
+ f_153([f_153, tc1, test]);
+ }
+ }
+
+ function tc2(a) {
+ try {
+ f_153([f_153, tc2, test]);
+ throw new Error("boom");
+ } catch(e) {
+ f_153([f_153, tc2, test]);
+ return continue f_153([f_153, test]);
+ }
+ }
+
+ function tc3(a) {
+ try {
+ f_153([f_153, tc3, test]);
+ throw new Error("boom");
+ } catch(e) {
+ f_153([f_153, tc3, test]);
+ }
+ f_153([f_153, tc3, test]);
+ return continue f_153([f_153, test]);
+ }
+
+ function test() {
+ assertEquals(153, tc1());
+ assertEquals(153, tc2());
+ assertEquals(153, tc3());
+ }
+ test();
+ test();
+ %OptimizeFunctionOnNextCall(test);
+ test();
+})();
+
+
+// Test tail calls from try-finally constructs.
+(function() {
+ function tf1(a) {
+ try {
+ f_153([f_153, tf1, test]);
+ return f_153([f_153, tf1, test]);
+ } finally {
+ f_153([f_153, tf1, test]);
+ }
+ }
+
+ function tf2(a) {
+ try {
+ f_153([f_153, tf2, test]);
+ throw new Error("boom");
+ } finally {
+ f_153([f_153, tf2, test]);
+ return continue f_153([f_153, test]);
+ }
+ }
+
+ function tf3(a) {
+ try {
+ f_153([f_153, tf3, test]);
+ } finally {
+ f_153([f_153, tf3, test]);
+ }
+ return continue f_153([f_153, test]);
+ }
+
+ function test() {
+ assertEquals(153, tf1());
+ assertEquals(153, tf2());
+ assertEquals(153, tf3());
+ }
+ test();
+ test();
+ %OptimizeFunctionOnNextCall(test);
+ test();
+})();
+
+
+// Test tail calls from try-catch-finally constructs.
+(function() {
+ function tcf1(a) {
+ try {
+ f_153([f_153, tcf1, test]);
+ return f_153([f_153, tcf1, test]);
+ } catch(e) {
+ } finally {
+ f_153([f_153, tcf1, test]);
+ }
+ }
+
+ function tcf2(a) {
+ try {
+ f_153([f_153, tcf2, test]);
+ throw new Error("boom");
+ } catch(e) {
+ f_153([f_153, tcf2, test]);
+ return f_153([f_153, tcf2, test]);
+ } finally {
+ f_153([f_153, tcf2, test]);
+ }
+ }
+
+ function tcf3(a) {
+ try {
+ f_153([f_153, tcf3, test]);
+ throw new Error("boom");
+ } catch(e) {
+ f_153([f_153, tcf3, test]);
+ } finally {
+ f_153([f_153, tcf3, test]);
+ return continue f_153([f_153, test]);
+ }
+ }
+
+ function tcf4(a) {
+ try {
+ f_153([f_153, tcf4, test]);
+ throw new Error("boom");
+ } catch(e) {
+ f_153([f_153, tcf4, test]);
+ } finally {
+ f_153([f_153, tcf4, test]);
+ }
+ return continue f_153([f_153, test]);
+ }
+
+ function test() {
+ assertEquals(153, tcf1());
+ assertEquals(153, tcf2());
+ assertEquals(153, tcf3());
+ assertEquals(153, tcf4());
+ }
+ test();
+ test();
+ %OptimizeFunctionOnNextCall(test);
+ test();
+})();
+
+
+// Test tail calls from arrow functions.
+(function () {
+ function g1(a) {
+ return continue (() => { return continue f_153([f_153, test]); })();
+ }
+
+ function g2(a) {
+ return continue (() => continue f_153([f_153, test]))();
+ }
+
+ function g3(a) {
+ var closure = () => f([f, closure, test], true)
+ ? continue f_153([f_153, test])
+ : continue f_153([f_153, test]);
+ return continue closure();
+ }
+
+ function test() {
+ assertEquals(153, g1());
+ assertEquals(153, g2());
+ assertEquals(153, g3());
+ }
+ test();
+ test();
+ %OptimizeFunctionOnNextCall(test);
+ test();
+})();
+
+
+// Test tail calls from do expressions.
+(function () {
+ function g1(a) {
+ var a = do { return continue f_153([f_153, test]); 42; };
+ return a;
+ }
+
+ function test() {
+ assertEquals(153, g1());
+ }
+ test();
+ test();
+ %OptimizeFunctionOnNextCall(test);
+ test();
+})();
diff --git a/test/mjsunit/eval-origin.js b/test/mjsunit/eval-origin.js
new file mode 100644
index 0000000..bb86ef3
--- /dev/null
+++ b/test/mjsunit/eval-origin.js
@@ -0,0 +1,39 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --nostress-opt
+
+Error.prepareStackTrace = function(exception, frames) {
+ return frames[0].getEvalOrigin();
+}
+
+var source = "new Error()";
+var eval_origin;
+var geval = eval;
+var log = [];
+
+(function() {
+ log.push([geval(source).stack, "17:13"]);
+ log.push([geval(source).stack, "18:13"]);
+ // log.push([geval(source).stack, "19:13"]); TODO(4921).
+})();
+
+(function() {
+ log.push([eval(source).stack, "23:13"]);
+ log.push([eval(source).stack, "24:13"]);
+ // log.push([eval(source).stack, "25:13"]); TODO(4921).
+})();
+
+log.push([eval(source).stack, "28:11"]);
+log.push([eval(source).stack, "29:11"]);
+// log.push([eval(source).stack, "30:11"]); TODO(4921).
+
+Error.prepareStackTrace = undefined;
+
+for (var item of log) {
+ var stacktraceline = item[0];
+ var expectation = item[1];
+ var re = new RegExp(`:${expectation}\\)$`);
+ assertTrue(re.test(stacktraceline));
+}
diff --git a/test/mjsunit/for-in.js b/test/mjsunit/for-in.js
index bece37a..547c748 100644
--- a/test/mjsunit/for-in.js
+++ b/test/mjsunit/for-in.js
@@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// Flags: --noharmony-for-in
+
function props(x) {
var array = [];
for (var p in x) array.push(p);
diff --git a/test/mjsunit/harmony/array-concat-array-proto-getter.js b/test/mjsunit/harmony/array-concat-array-proto-getter.js
new file mode 100644
index 0000000..9368e7f
--- /dev/null
+++ b/test/mjsunit/harmony/array-concat-array-proto-getter.js
@@ -0,0 +1,53 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Check that @@isConcatSpreadable is checked when set on Object.prototype
+
+"use strict"
+
+var array = [1, 2, 3];
+var object = {length: 1, '0': 'a'};
+
+function testConcatDefaults() {
+ assertEquals(array, [].concat(array));
+ assertEquals(array, array.concat([]));
+ assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+ assertEquals([object], [].concat(object));
+ assertEquals([1, 2, 3, object], array.concat(object));
+ assertEquals([object], Array.prototype.concat.call(object,[]));
+ assertEquals([object, 1, 2, 3], Array.prototype.concat.call(object, array));
+ assertEquals([object, object], Array.prototype.concat.call(object, object));
+}
+
+testConcatDefaults();
+
+var concatSpreadable = false;
+Object.defineProperty(Array.prototype, Symbol.isConcatSpreadable, {
+ get() { return concatSpreadable },
+ configurable: true
+});
+
+assertEquals([[], array], [].concat(array));
+assertEquals([array, []], array.concat([]));
+assertEquals([array, array], array.concat(array));
+assertEquals([[], object], [].concat(object));
+assertEquals([array, object], array.concat(object));
+assertEquals([object, []], Array.prototype.concat.call(object,[]));
+assertEquals([object, array], Array.prototype.concat.call(object, array));
+assertEquals([object, object], Array.prototype.concat.call(object, object));
+
+concatSpreadable = true;
+
+assertEquals(array, [].concat(array));
+assertEquals(array, array.concat([]));
+assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+assertEquals([object], [].concat(object));
+assertEquals([1, 2, 3, object], array.concat(object));
+assertEquals([object], Array.prototype.concat.call(object,[]));
+assertEquals([object, 1, 2, 3], Array.prototype.concat.call(object, array));
+assertEquals([object, object], Array.prototype.concat.call(object, object));
+
+
+delete Array.prototype[Symbol.isConcatSpreadable];
+testConcatDefaults();
diff --git a/test/mjsunit/harmony/array-concat-array-proto.js b/test/mjsunit/harmony/array-concat-array-proto.js
new file mode 100644
index 0000000..520178f
--- /dev/null
+++ b/test/mjsunit/harmony/array-concat-array-proto.js
@@ -0,0 +1,48 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Check that @@isConcatSpreadable is checked when set on Object.prototype
+
+"use strict"
+
+var array = [1, 2, 3];
+var object = {length: 1, '0': 'a'};
+
+function testConcatDefaults() {
+ assertEquals(array, [].concat(array));
+ assertEquals(array, array.concat([]));
+ assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+ assertEquals([object], [].concat(object));
+ assertEquals([1, 2, 3, object], array.concat(object));
+ assertEquals([object], Array.prototype.concat.call(object,[]));
+ assertEquals([object, 1, 2, 3], Array.prototype.concat.call(object, array));
+ assertEquals([object, object], Array.prototype.concat.call(object, object));
+}
+
+testConcatDefaults();
+
+Array.prototype[Symbol.isConcatSpreadable] = false;
+
+assertEquals([[], array], [].concat(array));
+assertEquals([array, []], array.concat([]));
+assertEquals([array, array], array.concat(array));
+assertEquals([[], object], [].concat(object));
+assertEquals([array, object], array.concat(object));
+assertEquals([object, []], Array.prototype.concat.call(object,[]));
+assertEquals([object, array], Array.prototype.concat.call(object, array));
+assertEquals([object, object], Array.prototype.concat.call(object, object));
+
+Array.prototype[Symbol.isConcatSpreadable] = true;
+
+assertEquals(array, [].concat(array));
+assertEquals(array, array.concat([]));
+assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+assertEquals([object], [].concat(object));
+assertEquals([1, 2, 3, object], array.concat(object));
+assertEquals([object], Array.prototype.concat.call(object,[]));
+assertEquals([object, 1, 2, 3], Array.prototype.concat.call(object, array));
+assertEquals([object, object], Array.prototype.concat.call(object, object));
+
+delete Array.prototype[Symbol.isConcatSpreadable];
+testConcatDefaults();
diff --git a/test/mjsunit/harmony/array-concat-object-proto-dict-getter.js b/test/mjsunit/harmony/array-concat-object-proto-dict-getter.js
new file mode 100644
index 0000000..6e61588
--- /dev/null
+++ b/test/mjsunit/harmony/array-concat-object-proto-dict-getter.js
@@ -0,0 +1,57 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Check that @@isConcatSpreadable is checked when set on Object.prototype
+// with a dictionary backing store.
+
+// Force Object.prototype into dictionary backing store by adding many
+// properties.
+for (var i = 0; i < 10*1000; i++) {
+ Object.prototype['generatedProperty'+i] = true;
+}
+
+var array = [1, 2, 3];
+var object = {length: 1, '0': 'a'};
+
+function testConcatDefaults() {
+ assertEquals(array, [].concat(array));
+ assertEquals(array, array.concat([]));
+ assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+ assertEquals([object], [].concat(object));
+ assertEquals([1, 2, 3, object], array.concat(object));
+ assertEquals([object], Array.prototype.concat.call(object,[]));
+ assertEquals([object, 1, 2, 3], Array.prototype.concat.call(object, array));
+ assertEquals([object, object], Array.prototype.concat.call(object, object));
+}
+
+testConcatDefaults();
+
+var concatSpreadable = false;
+Object.defineProperty(Object.prototype, Symbol.isConcatSpreadable, {
+ get() { return concatSpreadable },
+ configurable: true
+});
+
+assertEquals([[], array], [].concat(array));
+assertEquals([array, []], array.concat([]));
+assertEquals([array, array], array.concat(array));
+assertEquals([[], object], [].concat(object));
+assertEquals([array, object], array.concat(object));
+assertEquals([object, []], Array.prototype.concat.call(object,[]));
+assertEquals([object, array], Array.prototype.concat.call(object, array));
+assertEquals([object, object], Array.prototype.concat.call(object, object));
+
+concatSpreadable = true;
+
+assertEquals(array, [].concat(array));
+assertEquals(array, array.concat([]));
+assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+assertEquals(['a'], [].concat(object));
+assertEquals([1, 2, 3, 'a'], array.concat(object));
+assertEquals(['a'], Array.prototype.concat.call(object,[]));
+assertEquals(['a', 1, 2, 3], Array.prototype.concat.call(object, array));
+assertEquals(['a', 'a'], Array.prototype.concat.call(object, object));
+
+delete Object.prototype[Symbol.isConcatSpreadable];
+testConcatDefaults();
diff --git a/test/mjsunit/harmony/array-concat-object-proto-dict.js b/test/mjsunit/harmony/array-concat-object-proto-dict.js
new file mode 100644
index 0000000..c817006
--- /dev/null
+++ b/test/mjsunit/harmony/array-concat-object-proto-dict.js
@@ -0,0 +1,53 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Check that @@isConcatSpreadable is checked when set on Object.prototype
+// with a dictionary backing store.
+
+// Force Object.prototype into dictionary backing store by adding many
+// properties.
+for (var i = 0; i < 10*1000; i++) {
+ Object.prototype['generatedProperty'+i] = true;
+}
+
+var array = [1, 2, 3];
+var object = {length: 1, '0': 'a'};
+
+function testConcatDefaults() {
+ assertEquals(array, [].concat(array));
+ assertEquals(array, array.concat([]));
+ assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+ assertEquals([object], [].concat(object));
+ assertEquals([1, 2, 3, object], array.concat(object));
+ assertEquals([object], Array.prototype.concat.call(object,[]));
+ assertEquals([object, 1, 2, 3], Array.prototype.concat.call(object, array));
+ assertEquals([object, object], Array.prototype.concat.call(object, object));
+}
+
+testConcatDefaults();
+
+Object.prototype[Symbol.isConcatSpreadable] = false;
+
+assertEquals([[], array], [].concat(array));
+assertEquals([array, []], array.concat([]));
+assertEquals([array, array], array.concat(array));
+assertEquals([[], object], [].concat(object));
+assertEquals([array, object], array.concat(object));
+assertEquals([object, []], Array.prototype.concat.call(object,[]));
+assertEquals([object, array], Array.prototype.concat.call(object, array));
+assertEquals([object, object], Array.prototype.concat.call(object, object));
+
+Object.prototype[Symbol.isConcatSpreadable] = true;
+
+assertEquals(array, [].concat(array));
+assertEquals(array, array.concat([]));
+assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+assertEquals(['a'], [].concat(object));
+assertEquals([1, 2, 3, 'a'], array.concat(object));
+assertEquals(['a'], Array.prototype.concat.call(object,[]));
+assertEquals(['a', 1, 2, 3], Array.prototype.concat.call(object, array));
+assertEquals(['a', 'a'], Array.prototype.concat.call(object, object));
+
+delete Object.prototype[Symbol.isConcatSpreadable];
+testConcatDefaults();
diff --git a/test/mjsunit/harmony/array-concat-object-proto-generic-dict.js b/test/mjsunit/harmony/array-concat-object-proto-generic-dict.js
new file mode 100644
index 0000000..7b61422
--- /dev/null
+++ b/test/mjsunit/harmony/array-concat-object-proto-generic-dict.js
@@ -0,0 +1,65 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Check that @@isConcatSpreadable is checked when set on Object.prototype
+// with a dictionary backing store.
+
+// Force Object.prototype into dictionary backing store by adding many
+// properties.
+for (var i = 0; i < 10*1000; i++) {
+ Object.prototype['generatedProperty'+i] = true;
+}
+
+var array = [1, 2, 3];
+var object = {length: 1, '0': 'a'};
+
+function SetProperty(receiver, key, value) {
+ receiver[key] = value;
+}
+
+// Force the Keyed Store IC in SetProperty to be generic.
+var receiver = {};
+for (var i = 0; i < 100; i++) {
+ SetProperty(receiver, 'prop'+i, 'value');
+}
+
+function testConcatDefaults() {
+ assertEquals(array, [].concat(array));
+ assertEquals(array, array.concat([]));
+ assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+ assertEquals([object], [].concat(object));
+ assertEquals([1, 2, 3, object], array.concat(object));
+ assertEquals([object], Array.prototype.concat.call(object,[]));
+ assertEquals([object, 1, 2, 3], Array.prototype.concat.call(object, array));
+ assertEquals([object, object], Array.prototype.concat.call(object, object));
+}
+
+testConcatDefaults();
+
+// Use a generic IC to set @@isConcatSpreadable
+SetProperty(Object.prototype, Symbol.isConcatSpreadable, false);
+
+assertEquals([[], array], [].concat(array));
+assertEquals([array, []], array.concat([]));
+assertEquals([array, array], array.concat(array));
+assertEquals([[], object], [].concat(object));
+assertEquals([array, object], array.concat(object));
+assertEquals([object, []], Array.prototype.concat.call(object,[]));
+assertEquals([object, array], Array.prototype.concat.call(object, array));
+assertEquals([object, object], Array.prototype.concat.call(object, object));
+
+// Use a generic IC to set @@isConcatSpreadable
+SetProperty(Object.prototype, Symbol.isConcatSpreadable, true);
+
+assertEquals(array, [].concat(array));
+assertEquals(array, array.concat([]));
+assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+assertEquals(['a'], [].concat(object));
+assertEquals([1, 2, 3, 'a'], array.concat(object));
+assertEquals(['a'], Array.prototype.concat.call(object,[]));
+assertEquals(['a', 1, 2, 3], Array.prototype.concat.call(object, array));
+assertEquals(['a', 'a'], Array.prototype.concat.call(object, object));
+
+delete Object.prototype[Symbol.isConcatSpreadable];
+testConcatDefaults();
diff --git a/test/mjsunit/harmony/array-concat-object-proto.js b/test/mjsunit/harmony/array-concat-object-proto.js
new file mode 100644
index 0000000..307326c
--- /dev/null
+++ b/test/mjsunit/harmony/array-concat-object-proto.js
@@ -0,0 +1,48 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Check that @@isConcatSpreadable is checked when set on Object.prototype
+
+"use strict"
+
+var array = [1, 2, 3];
+var object = {length: 1, '0': 'a'};
+
+function testConcatDefaults() {
+ assertEquals(array, [].concat(array));
+ assertEquals(array, array.concat([]));
+ assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+ assertEquals([object], [].concat(object));
+ assertEquals([1, 2, 3, object], array.concat(object));
+ assertEquals([object], Array.prototype.concat.call(object,[]));
+ assertEquals([object, 1, 2, 3], Array.prototype.concat.call(object, array));
+ assertEquals([object, object], Array.prototype.concat.call(object, object));
+}
+
+testConcatDefaults();
+
+Object.prototype[Symbol.isConcatSpreadable] = false;
+
+assertEquals([[], array], [].concat(array));
+assertEquals([array, []], array.concat([]));
+assertEquals([array, array], array.concat(array));
+assertEquals([[], object], [].concat(object));
+assertEquals([array, object], array.concat(object));
+assertEquals([object, []], Array.prototype.concat.call(object,[]));
+assertEquals([object, array], Array.prototype.concat.call(object, array));
+assertEquals([object, object], Array.prototype.concat.call(object, object));
+
+Object.prototype[Symbol.isConcatSpreadable] = true;
+
+assertEquals(array, [].concat(array));
+assertEquals(array, array.concat([]));
+assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+assertEquals(['a'], [].concat(object));
+assertEquals([1, 2, 3, 'a'], array.concat(object));
+assertEquals(['a'], Array.prototype.concat.call(object,[]));
+assertEquals(['a', 1, 2, 3], Array.prototype.concat.call(object, array));
+assertEquals(['a', 'a'], Array.prototype.concat.call(object, object));
+
+delete Object.prototype[Symbol.isConcatSpreadable];
+testConcatDefaults();
diff --git a/test/mjsunit/harmony/async-arrow-lexical-arguments.js b/test/mjsunit/harmony/async-arrow-lexical-arguments.js
new file mode 100644
index 0000000..44d38a4
--- /dev/null
+++ b/test/mjsunit/harmony/async-arrow-lexical-arguments.js
@@ -0,0 +1,42 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-async-await --allow-natives-syntax
+
+function assertEqualsAsync(expected, run, msg) {
+ var actual;
+ var hadValue = false;
+ var hadError = false;
+ var promise = run();
+
+ if (typeof promise !== "object" || typeof promise.then !== "function") {
+ throw new MjsUnitAssertionError(
+ "Expected " + run.toString() +
+ " to return a Promise, but it returned " + PrettyPrint(promise));
+ }
+
+ promise.then(function(value) { hadValue = true; actual = value; },
+ function(error) { hadError = true; actual = error; });
+
+ assertFalse(hadValue || hadError);
+
+ %RunMicrotasks();
+
+ if (hadError) throw actual;
+
+ assertTrue(
+ hadValue, "Expected '" + run.toString() + "' to produce a value");
+
+ assertEquals(expected, actual, msg);
+};
+
+assertEqualsAsync("[1,2,3]", () => (function() {
+ return (async () => JSON.stringify([...arguments]))();
+})(1, 2, 3));
+
+assertEqualsAsync("[4,5,6]",
+ () => (function() {
+ return (async () => {
+ return JSON.stringify([...await arguments]) })();
+ })(4, 5, 6));
diff --git a/test/mjsunit/harmony/async-arrow-lexical-new.target.js b/test/mjsunit/harmony/async-arrow-lexical-new.target.js
new file mode 100644
index 0000000..72b29e6
--- /dev/null
+++ b/test/mjsunit/harmony/async-arrow-lexical-new.target.js
@@ -0,0 +1,43 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-async-await --allow-natives-syntax
+
+function assertEqualsAsync(expected, run, msg) {
+ var actual;
+ var hadValue = false;
+ var hadError = false;
+ var promise = run();
+
+ if (typeof promise !== "object" || typeof promise.then !== "function") {
+ throw new MjsUnitAssertionError(
+ "Expected " + run.toString() +
+ " to return a Promise, but it returned " + PrettyPrint(promise));
+ }
+
+ promise.then(function(value) { hadValue = true; actual = value; },
+ function(error) { hadError = true; actual = error; });
+
+ assertFalse(hadValue || hadError);
+
+ %RunMicrotasks();
+
+ if (hadError) throw actual;
+
+ assertTrue(
+ hadValue, "Expected '" + run.toString() + "' to produce a value");
+
+ assertEquals(expected, actual, msg);
+};
+
+class BaseClass {
+ constructor() {
+ return async () => new.target;
+ }
+}
+
+class ChildClass extends BaseClass {}
+
+assertEqualsAsync(BaseClass, () => new BaseClass()());
+assertEqualsAsync(ChildClass, () => new ChildClass()());
diff --git a/test/mjsunit/harmony/async-arrow-lexical-super.js b/test/mjsunit/harmony/async-arrow-lexical-super.js
new file mode 100644
index 0000000..78f5d55
--- /dev/null
+++ b/test/mjsunit/harmony/async-arrow-lexical-super.js
@@ -0,0 +1,58 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-async-await --allow-natives-syntax
+
+function assertEqualsAsync(expected, run, msg) {
+ var actual;
+ var hadValue = false;
+ var hadError = false;
+ var promise = run();
+
+ if (typeof promise !== "object" || typeof promise.then !== "function") {
+ throw new MjsUnitAssertionError(
+ "Expected " + run.toString() +
+ " to return a Promise, but it returned " + PrettyPrint(promise));
+ }
+
+ promise.then(function(value) { hadValue = true; actual = value; },
+ function(error) { hadError = true; actual = error; });
+
+ assertFalse(hadValue || hadError);
+
+ %RunMicrotasks();
+
+ if (hadError) throw actual;
+
+ assertTrue(
+ hadValue, "Expected '" + run.toString() + "' to produce a value");
+
+ assertEquals(expected, actual, msg);
+};
+
+class BaseClass {
+ constructor(x) {
+ this.name_ = x;
+ }
+ get name() { return this.name_; }
+};
+
+class DeferredSuperCall extends BaseClass {
+ constructor(x) {
+ return async() => super(x);
+ }
+};
+
+assertEqualsAsync(
+ "LexicalSuperCall",
+ () => new DeferredSuperCall("LexicalSuperCall")().then(x => x.name));
+
+
+class DeferredSuperProperty extends BaseClass {
+ deferredName() { return async() => super.name; }
+};
+
+assertEqualsAsync(
+ "LexicalSuperProperty",
+ () => new DeferredSuperProperty("LexicalSuperProperty").deferredName()());
diff --git a/test/mjsunit/harmony/async-arrow-lexical-this.js b/test/mjsunit/harmony/async-arrow-lexical-this.js
new file mode 100644
index 0000000..182db47
--- /dev/null
+++ b/test/mjsunit/harmony/async-arrow-lexical-this.js
@@ -0,0 +1,48 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-async-await --allow-natives-syntax
+
+function assertEqualsAsync(expected, run, msg) {
+ var actual;
+ var hadValue = false;
+ var hadError = false;
+ var promise = run();
+
+ if (typeof promise !== "object" || typeof promise.then !== "function") {
+ throw new MjsUnitAssertionError(
+ "Expected " + run.toString() +
+ " to return a Promise, but it returned " + PrettyPrint(promise));
+ }
+
+ promise.then(function(value) { hadValue = true; actual = value; },
+ function(error) { hadError = true; actual = error; });
+
+ assertFalse(hadValue || hadError);
+
+ %RunMicrotasks();
+
+ if (hadError) throw actual;
+
+ assertTrue(
+ hadValue, "Expected '" + run.toString() + "' to produce a value");
+
+ assertEquals(expected, actual, msg);
+};
+
+var O = {
+ [Symbol.toStringTag]: "LexicalThis",
+ run(n) {
+ return async passFail => `${n}. ${passFail}: ${this}`;
+ },
+};
+
+assertEqualsAsync("1. PASS: [object LexicalThis]", () => O.run(1)("PASS"));
+
+var O2 = {
+ [Symbol.toStringTag]: "LexicalThis",
+ run: O.run(2)
+};
+
+assertEqualsAsync("2. PASS: [object LexicalThis]", () => O2.run("PASS"));
diff --git a/test/mjsunit/harmony/async-await-basic.js b/test/mjsunit/harmony/async-await-basic.js
new file mode 100644
index 0000000..d0888ea
--- /dev/null
+++ b/test/mjsunit/harmony/async-await-basic.js
@@ -0,0 +1,347 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-async-await --allow-natives-syntax
+
+// Do not install `AsyncFunction` constructor on global object
+
+function assertThrowsAsync(run, errorType, message) {
+ var actual;
+ var hadValue = false;
+ var hadError = false;
+ var promise = run();
+
+ if (typeof promise !== "object" || typeof promise.then !== "function") {
+ throw new MjsUnitAssertionError(
+ "Expected " + run.toString() +
+ " to return a Promise, but it returned " + PrettyPrint(promise));
+ }
+
+ promise.then(function(value) { hadValue = true; actual = value; },
+ function(error) { hadError = true; actual = error; });
+
+ assertFalse(hadValue || hadError);
+
+ %RunMicrotasks();
+
+ if (!hadError) {
+ throw new MjsUnitAssertionError(
+ "Expected " + run + "() to throw " + errorType.name +
+ ", but did not throw.");
+ }
+ if (!(actual instanceof errorType))
+ throw new MjsUnitAssertionError(
+ "Expected " + run + "() to throw " + errorType.name +
+ ", but threw '" + actual + "'");
+ if (message !== void 0 && actual.message !== message)
+ throw new MjsUnitAssertionError(
+ "Expected " + run + "() to throw '" + message + "', but threw '" +
+ actual.message + "'");
+};
+
+function assertEqualsAsync(expected, run, msg) {
+ var actual;
+ var hadValue = false;
+ var hadError = false;
+ var promise = run();
+
+ if (typeof promise !== "object" || typeof promise.then !== "function") {
+ throw new MjsUnitAssertionError(
+ "Expected " + run.toString() +
+ " to return a Promise, but it returned " + PrettyPrint(promise));
+ }
+
+ promise.then(function(value) { hadValue = true; actual = value; },
+ function(error) { hadError = true; actual = error; });
+
+ assertFalse(hadValue || hadError);
+
+ %RunMicrotasks();
+
+ if (hadError) throw actual;
+
+ assertTrue(
+ hadValue, "Expected '" + run.toString() + "' to produce a value");
+
+ assertEquals(expected, actual, msg);
+};
+
+assertEquals(undefined, this.AsyncFunction);
+let AsyncFunction = (async function() {}).constructor;
+
+// Let functionPrototype be the intrinsic object %AsyncFunctionPrototype%.
+async function asyncFunctionForProto() {}
+assertEquals(AsyncFunction.prototype,
+ Object.getPrototypeOf(asyncFunctionForProto));
+assertEquals(AsyncFunction.prototype,
+ Object.getPrototypeOf(async function() {}));
+assertEquals(AsyncFunction.prototype, Object.getPrototypeOf(async () => {}));
+assertEquals(AsyncFunction.prototype,
+ Object.getPrototypeOf({ async method() {} }.method));
+assertEquals(AsyncFunction.prototype, Object.getPrototypeOf(AsyncFunction()));
+assertEquals(AsyncFunction.prototype,
+ Object.getPrototypeOf(new AsyncFunction()));
+
+// AsyncFunctionCreate does not produce an object with a Prototype
+assertEquals(undefined, asyncFunctionForProto.prototype);
+assertEquals(false, asyncFunctionForProto.hasOwnProperty("prototype"));
+assertEquals(undefined, (async function() {}).prototype);
+assertEquals(false, (async function() {}).hasOwnProperty("prototype"));
+assertEquals(undefined, (async() => {}).prototype);
+assertEquals(false, (async() => {}).hasOwnProperty("prototype"));
+assertEquals(undefined, ({ async method() {} }).method.prototype);
+assertEquals(false, ({ async method() {} }).method.hasOwnProperty("prototype"));
+assertEquals(undefined, AsyncFunction().prototype);
+assertEquals(false, AsyncFunction().hasOwnProperty("prototype"));
+assertEquals(undefined, (new AsyncFunction()).prototype);
+assertEquals(false, (new AsyncFunction()).hasOwnProperty("prototype"));
+
+assertEquals(1, async function(a) { await 1; }.length);
+assertEquals(2, async function(a, b) { await 1; }.length);
+assertEquals(1, async function(a, b = 2) { await 1; }.length);
+assertEquals(2, async function(a, b, ...c) { await 1; }.length);
+
+assertEquals(1, (async(a) => await 1).length);
+assertEquals(2, (async(a, b) => await 1).length);
+assertEquals(1, (async(a, b = 2) => await 1).length);
+assertEquals(2, (async(a, b, ...c) => await 1).length);
+
+assertEquals(1, ({ async f(a) { await 1; } }).f.length);
+assertEquals(2, ({ async f(a, b) { await 1; } }).f.length);
+assertEquals(1, ({ async f(a, b = 2) { await 1; } }).f.length);
+assertEquals(2, ({ async f(a, b, ...c) { await 1; } }).f.length);
+
+assertEquals(1, AsyncFunction("a", "await 1").length);
+assertEquals(2, AsyncFunction("a", "b", "await 1").length);
+assertEquals(1, AsyncFunction("a", "b = 2", "await 1").length);
+assertEquals(2, AsyncFunction("a", "b", "...c", "await 1").length);
+
+assertEquals(1, (new AsyncFunction("a", "await 1")).length);
+assertEquals(2, (new AsyncFunction("a", "b", "await 1")).length);
+assertEquals(1, (new AsyncFunction("a", "b = 2", "await 1")).length);
+assertEquals(2, (new AsyncFunction("a", "b", "...c", "await 1")).length);
+
+// AsyncFunction.prototype[ @@toStringTag ]
+var descriptor =
+ Object.getOwnPropertyDescriptor(AsyncFunction.prototype,
+ Symbol.toStringTag);
+assertEquals("AsyncFunction", descriptor.value);
+assertEquals(false, descriptor.enumerable);
+assertEquals(false, descriptor.writable);
+assertEquals(true, descriptor.configurable);
+
+assertEquals(1, AsyncFunction.length);
+
+// Let F be ! FunctionAllocate(functionPrototype, Strict, "non-constructor")
+async function asyncNonConstructorDecl() {}
+assertThrows(
+ () => new asyncNonConstructorDecl(), TypeError);
+assertThrows(
+ () => new (async function() {}), TypeError);
+assertThrows(
+ () => new ({ async nonConstructor() {} }).nonConstructor(), TypeError);
+assertThrows(
+ () => new (() => "not a constructor!"), TypeError);
+assertThrows(
+ () => new (AsyncFunction()), TypeError);
+assertThrows(
+ () => new (new AsyncFunction()), TypeError);
+
+// Normal completion
+async function asyncDecl() { return "test"; }
+assertEqualsAsync("test", asyncDecl);
+assertEqualsAsync("test2", async function() { return "test2"; });
+assertEqualsAsync("test3", async () => "test3");
+assertEqualsAsync("test4", () => ({ async f() { return "test4"; } }).f());
+assertEqualsAsync("test5", () => AsyncFunction("no", "return 'test' + no;")(5));
+assertEqualsAsync("test6",
+ () => (new AsyncFunction("no", "return 'test' + no;"))(6));
+
+class MyError extends Error {};
+
+// Throw completion
+async function asyncDeclThrower(e) { throw new MyError(e); }
+assertThrowsAsync(() => asyncDeclThrower("boom!"), MyError, "boom!");
+assertThrowsAsync(
+ () => (async function(e) { throw new MyError(e); })("boom!!!"),
+ MyError, "boom!!!");
+assertThrowsAsync(
+ () => (async e => { throw new MyError(e) })("boom!!"), MyError, "boom!!");
+assertThrowsAsync(
+ () => ({ async thrower(e) { throw new MyError(e); } }).thrower("boom!1!"),
+ MyError, "boom!1!");
+assertThrowsAsync(
+ () => AsyncFunction("msg", "throw new MyError(msg)")("boom!2!!"),
+ MyError, "boom!2!!");
+assertThrowsAsync(
+ () => (new AsyncFunction("msg", "throw new MyError(msg)"))("boom!2!!!"),
+ MyError, "boom!2!!!");
+
+function resolveLater(value) { return Promise.resolve(value); }
+function rejectLater(error) { return Promise.reject(error); }
+
+// Resume after Normal completion
+var log = [];
+async function resumeAfterNormal(value) {
+ log.push("start:" + value);
+ value = await resolveLater(value + 1);
+ log.push("resume:" + value);
+ value = await resolveLater(value + 1);
+ log.push("resume:" + value);
+ return value + 1;
+}
+
+assertEqualsAsync(4, () => resumeAfterNormal(1));
+assertEquals("start:1 resume:2 resume:3", log.join(" "));
+
+var O = {
+ async resumeAfterNormal(value) {
+ log.push("start:" + value);
+ value = await resolveLater(value + 1);
+ log.push("resume:" + value);
+ value = await resolveLater(value + 1);
+ log.push("resume:" + value);
+ return value + 1;
+ }
+};
+log = [];
+assertEqualsAsync(5, () => O.resumeAfterNormal(2));
+assertEquals("start:2 resume:3 resume:4", log.join(" "));
+
+var resumeAfterNormalArrow = async (value) => {
+ log.push("start:" + value);
+ value = await resolveLater(value + 1);
+ log.push("resume:" + value);
+ value = await resolveLater(value + 1);
+ log.push("resume:" + value);
+ return value + 1;
+};
+log = [];
+assertEqualsAsync(6, () => resumeAfterNormalArrow(3));
+assertEquals("start:3 resume:4 resume:5", log.join(" "));
+
+var resumeAfterNormalEval = AsyncFunction("value", `
+ log.push("start:" + value);
+ value = await resolveLater(value + 1);
+ log.push("resume:" + value);
+ value = await resolveLater(value + 1);
+ log.push("resume:" + value);
+ return value + 1;`);
+log = [];
+assertEqualsAsync(7, () => resumeAfterNormalEval(4));
+assertEquals("start:4 resume:5 resume:6", log.join(" "));
+
+var resumeAfterNormalNewEval = new AsyncFunction("value", `
+ log.push("start:" + value);
+ value = await resolveLater(value + 1);
+ log.push("resume:" + value);
+ value = await resolveLater(value + 1);
+ log.push("resume:" + value);
+ return value + 1;`);
+log = [];
+assertEqualsAsync(8, () => resumeAfterNormalNewEval(5));
+assertEquals("start:5 resume:6 resume:7", log.join(" "));
+
+// Resume after Throw completion
+async function resumeAfterThrow(value) {
+ log.push("start:" + value);
+ try {
+ value = await rejectLater("throw1");
+ } catch (e) {
+ log.push("resume:" + e);
+ }
+ try {
+ value = await rejectLater("throw2");
+ } catch (e) {
+ log.push("resume:" + e);
+ }
+ return value + 1;
+}
+
+log = [];
+assertEqualsAsync(2, () => resumeAfterThrow(1));
+assertEquals("start:1 resume:throw1 resume:throw2", log.join(" "));
+
+var O = {
+ async resumeAfterThrow(value) {
+ log.push("start:" + value);
+ try {
+ value = await rejectLater("throw1");
+ } catch (e) {
+ log.push("resume:" + e);
+ }
+ try {
+ value = await rejectLater("throw2");
+ } catch (e) {
+ log.push("resume:" + e);
+ }
+ return value + 1;
+ }
+}
+log = [];
+assertEqualsAsync(3, () => O.resumeAfterThrow(2));
+assertEquals("start:2 resume:throw1 resume:throw2", log.join(" "));
+
+var resumeAfterThrowArrow = async (value) => {
+ log.push("start:" + value);
+ try {
+ value = await rejectLater("throw1");
+ } catch (e) {
+ log.push("resume:" + e);
+ }
+ try {
+ value = await rejectLater("throw2");
+ } catch (e) {
+ log.push("resume:" + e);
+ }
+ return value + 1;
+};
+
+log = [];
+
+assertEqualsAsync(4, () => resumeAfterThrowArrow(3));
+assertEquals("start:3 resume:throw1 resume:throw2", log.join(" "));
+
+var resumeAfterThrowEval = AsyncFunction("value", `
+ log.push("start:" + value);
+ try {
+ value = await rejectLater("throw1");
+ } catch (e) {
+ log.push("resume:" + e);
+ }
+ try {
+ value = await rejectLater("throw2");
+ } catch (e) {
+ log.push("resume:" + e);
+ }
+ return value + 1;`);
+log = [];
+assertEqualsAsync(5, () => resumeAfterThrowEval(4));
+assertEquals("start:4 resume:throw1 resume:throw2", log.join(" "));
+
+var resumeAfterThrowNewEval = new AsyncFunction("value", `
+ log.push("start:" + value);
+ try {
+ value = await rejectLater("throw1");
+ } catch (e) {
+ log.push("resume:" + e);
+ }
+ try {
+ value = await rejectLater("throw2");
+ } catch (e) {
+ log.push("resume:" + e);
+ }
+ return value + 1;`);
+log = [];
+assertEqualsAsync(6, () => resumeAfterThrowNewEval(5));
+assertEquals("start:5 resume:throw1 resume:throw2", log.join(" "));
+
+async function foo() {}
+assertEquals("async function foo() {}", foo.toString());
+assertEquals("async function () {}", async function() {}.toString());
+assertEquals("async x => x", (async x => x).toString());
+assertEquals("async x => { return x }", (async x => { return x }).toString());
+class AsyncMethod { async foo() { } }
+assertEquals("async foo() { }", Function.prototype.toString.call(AsyncMethod.prototype.foo));
+assertEquals("async foo() { }", Function.prototype.toString.call({async foo() { }}.foo));
diff --git a/test/mjsunit/harmony/atomics.js b/test/mjsunit/harmony/atomics.js
index bf27eb4..e608df3 100644
--- a/test/mjsunit/harmony/atomics.js
+++ b/test/mjsunit/harmony/atomics.js
@@ -16,26 +16,19 @@
return value;
}
-function toRangeClamped(value) {
- if (value < this.min) return this.min;
- if (value > this.max) return this.max;
- return value;
-}
-
function makeConstructorObject(constr, min, max, toRange) {
var o = {constr: constr, min: min, max: max};
- o.toRange = toRange.bind(o);
+ o.toRange = toRangeWrapped.bind(o);
return o;
}
var IntegerTypedArrayConstructors = [
- makeConstructorObject(Int8Array, -128, 127, toRangeWrapped),
- makeConstructorObject(Int16Array, -32768, 32767, toRangeWrapped),
- makeConstructorObject(Int32Array, -0x80000000, 0x7fffffff, toRangeWrapped),
- makeConstructorObject(Uint8Array, 0, 255, toRangeWrapped),
- makeConstructorObject(Uint8ClampedArray, 0, 255, toRangeClamped),
- makeConstructorObject(Uint16Array, 0, 65535, toRangeWrapped),
- makeConstructorObject(Uint32Array, 0, 0xffffffff, toRangeWrapped),
+ makeConstructorObject(Int8Array, -128, 127),
+ makeConstructorObject(Int16Array, -32768, 32767),
+ makeConstructorObject(Int32Array, -0x80000000, 0x7fffffff),
+ makeConstructorObject(Uint8Array, 0, 255),
+ makeConstructorObject(Uint16Array, 0, 65535),
+ makeConstructorObject(Uint32Array, 0, 0xffffffff),
];
(function TestBadArray() {
@@ -44,9 +37,13 @@
var sab = new SharedArrayBuffer(128);
var sf32a = new Float32Array(sab);
var sf64a = new Float64Array(sab);
+ var u8ca = new Uint8ClampedArray(sab);
// Atomic ops required integer shared typed arrays
- [undefined, 1, 'hi', 3.4, ab, u32a, sab, sf32a, sf64a].forEach(function(o) {
+ var badArrayTypes = [
+ undefined, 1, 'hi', 3.4, ab, u32a, sab, sf32a, sf64a, u8ca
+ ];
+ badArrayTypes.forEach(function(o) {
assertThrows(function() { Atomics.compareExchange(o, 0, 0, 0); },
TypeError);
assertThrows(function() { Atomics.load(o, 0); }, TypeError);
@@ -129,15 +126,16 @@
var testOp = function(op, ia, index, expectedIndex, name) {
for (var i = 0; i < ia.length; ++i)
- ia[i] = 22;
+ ia[i] = i * 2;
ia[expectedIndex] = 0;
- assertEquals(0, op(ia, index, 0, 0), name);
+ var result = op(ia, index, 0, 0);
+ assertEquals(0, result, name);
assertEquals(0, ia[expectedIndex], name);
for (var i = 0; i < ia.length; ++i) {
if (i == expectedIndex) continue;
- assertEquals(22, ia[i], name);
+ assertEquals(i * 2, ia[i], name);
}
};
@@ -222,6 +220,24 @@
}
})
});
+
+ // Test Smi range
+ (function () {
+ var sab = new SharedArrayBuffer(4);
+ var i32 = new Int32Array(sab);
+ var u32 = new Uint32Array(sab);
+
+ function testLoad(signedValue, unsignedValue) {
+ u32[0] = unsignedValue;
+ assertEquals(unsignedValue, Atomics.load(u32, 0));
+ assertEquals(signedValue, Atomics.load(i32, 0));
+ }
+
+ testLoad(0x3fffffff, 0x3fffffff); // 2**30-1 (always smi)
+ testLoad(0x40000000, 0x40000000); // 2**30 (smi if signed and 32-bits)
+ testLoad(0x80000000, -0x80000000); // 2**31 (smi if signed and 32-bits)
+ testLoad(0xffffffff, -1); // 2**31 (smi if signed)
+ });
})();
(function TestStore() {
@@ -405,7 +421,7 @@
assertEquals(50, Atomics.compareExchange(sta, 0, v, v), name);
// Store
- assertEquals(+v, Atomics.store(sta, 0, v), name);
+ assertEquals(v|0, Atomics.store(sta, 0, v), name);
assertEquals(v|0, sta[0], name);
// Add
diff --git a/test/mjsunit/harmony/do-expressions.js b/test/mjsunit/harmony/do-expressions.js
index b3be4ec..38b68b6 100644
--- a/test/mjsunit/harmony/do-expressions.js
+++ b/test/mjsunit/harmony/do-expressions.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-do-expressions --harmony-sloppy-let --allow-natives-syntax
+// Flags: --harmony-do-expressions --allow-natives-syntax
function returnValue(v) { return v; }
function MyError() {}
diff --git a/test/mjsunit/harmony/for-in.js b/test/mjsunit/harmony/for-in.js
new file mode 100644
index 0000000..58e343b
--- /dev/null
+++ b/test/mjsunit/harmony/for-in.js
@@ -0,0 +1,9 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-for-in
+
+assertThrows("for (var x = 0 in {});", SyntaxError);
+assertThrows("for (const x = 0 in {});", SyntaxError);
+assertThrows("for (let x = 0 in {});", SyntaxError);
diff --git a/test/mjsunit/harmony/function-sent.js b/test/mjsunit/harmony/function-sent.js
index b3cd644..cd0ca95 100644
--- a/test/mjsunit/harmony/function-sent.js
+++ b/test/mjsunit/harmony/function-sent.js
@@ -49,7 +49,7 @@
try {
yield function.sent;
} finally {
- return 666;
+ return 23;
}
}
@@ -77,7 +77,7 @@
let x = g();
assertEquals({value: 1, done: false}, x.next(1));
assertEquals({value: undefined, done: false}, x.next(2));
- assertEquals({value: 42, done: true}, x.return(42));
+ assertEquals({value: 23, done: true}, x.return(42));
}
}
diff --git a/test/mjsunit/harmony/generators.js b/test/mjsunit/harmony/generators.js
index df6cec8..895a248 100644
--- a/test/mjsunit/harmony/generators.js
+++ b/test/mjsunit/harmony/generators.js
@@ -2,6 +2,34 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Flags: --ignition-generators --harmony-do-expressions
+// Flags: --allow-natives-syntax
+
+
+function MaybeOptimizeOrDeoptimize(f) {
+ let x = Math.random(); // --random-seed makes this deterministic
+ if (x <= 0.33) {
+ %OptimizeFunctionOnNextCall(f);
+ } else if (x <= 0.66) {
+ %DeoptimizeFunction(f);
+ }
+}
+
+function Next(generator, ...args) {
+ MaybeOptimizeOrDeoptimize(%GeneratorGetFunction(generator));
+ return generator.next(...args);
+}
+
+function Return(generator, ...args) {
+ MaybeOptimizeOrDeoptimize(%GeneratorGetFunction(generator));
+ return generator.return(...args);
+}
+
+function Throw(generator, ...args) {
+ MaybeOptimizeOrDeoptimize(%GeneratorGetFunction(generator));
+ return generator.throw(...args);
+}
+
{ // yield in try-catch
@@ -9,19 +37,19 @@
try {yield 1} catch (error) {assertEquals("caught", error)}
};
- assertThrowsEquals(() => g().throw("not caught"), "not caught");
+ assertThrowsEquals(() => Throw(g(), "not caught"), "not caught");
{
let x = g();
- assertEquals({value: 1, done: false}, x.next());
- assertEquals({value: undefined, done: true}, x.throw("caught"));
+ assertEquals({value: 1, done: false}, Next(x));
+ assertEquals({value: undefined, done: true}, Throw(x, "caught"));
}
{
let x = g();
- assertEquals({value: 1, done: false}, x.next());
- assertEquals({value: undefined, done: true}, x.next());
- assertThrowsEquals(() => x.throw("not caught"), "not caught");
+ assertEquals({value: 1, done: false}, Next(x));
+ assertEquals({value: undefined, done: true}, Next(x));
+ assertThrowsEquals(() => Throw(x, "not caught"), "not caught");
}
}
@@ -31,19 +59,19 @@
{
let x = g();
- assertEquals({value: 43, done: false}, x.next());
- assertEquals({value: 42, done: true}, x.next());
+ assertEquals({value: 43, done: false}, Next(x));
+ assertEquals({value: 42, done: true}, Next(x));
}
}
{ // return that doesn't close
let x;
- let g = function*() { try {return 42} finally {x.throw(666)} };
+ let g = function*() { try {return 42} finally {Throw(x, 666)} };
{
x = g();
- assertThrows(() => x.next(), TypeError); // still executing
+ assertThrows(() => Next(x), TypeError); // still executing
}
}
@@ -54,42 +82,42 @@
{ // "return" closes at suspendedStart
let x = g();
- assertEquals({value: 666, done: true}, x.return(666));
- assertEquals({value: undefined, done: true}, x.next(42));
- assertThrowsEquals(() => x.throw(43), 43);
- assertEquals({value: 42, done: true}, x.return(42));
+ assertEquals({value: 666, done: true}, Return(x, 666));
+ assertEquals({value: undefined, done: true}, Next(x, 42));
+ assertThrowsEquals(() => Throw(x, 43), 43);
+ assertEquals({value: 42, done: true}, Return(x, 42));
}
{ // "throw" closes at suspendedStart
let x = g();
- assertThrowsEquals(() => x.throw(666), 666);
- assertEquals({value: undefined, done: true}, x.next(42));
- assertEquals({value: 43, done: true}, x.return(43));
- assertThrowsEquals(() => x.throw(44), 44);
+ assertThrowsEquals(() => Throw(x, 666), 666);
+ assertEquals({value: undefined, done: true}, Next(x, 42));
+ assertEquals({value: 43, done: true}, Return(x, 43));
+ assertThrowsEquals(() => Throw(x, 44), 44);
}
{ // "next" closes at suspendedYield
let x = g();
- assertEquals({value: 42, done: false}, x.next());
- assertEquals({value: 13, done: true}, x.next(666));
- assertEquals({value: undefined, done: true}, x.next(666));
- assertThrowsEquals(() => x.throw(666), 666);
+ assertEquals({value: 42, done: false}, Next(x));
+ assertEquals({value: 13, done: true}, Next(x, 666));
+ assertEquals({value: undefined, done: true}, Next(x, 666));
+ assertThrowsEquals(() => Throw(x, 666), 666);
}
{ // "return" closes at suspendedYield
let x = g();
- assertEquals({value: 42, done: false}, x.next());
- assertEquals({value: 13, done: true}, x.return(666));
- assertEquals({value: undefined, done: true}, x.next(666));
- assertEquals({value: 666, done: true}, x.return(666));
+ assertEquals({value: 42, done: false}, Next(x));
+ assertEquals({value: 13, done: true}, Return(x, 666));
+ assertEquals({value: undefined, done: true}, Next(x, 666));
+ assertEquals({value: 666, done: true}, Return(x, 666));
}
{ // "throw" closes at suspendedYield
let x = g();
- assertEquals({value: 42, done: false}, x.next());
- assertEquals({value: 13, done: true}, x.throw(666));
- assertThrowsEquals(() => x.throw(666), 666);
- assertEquals({value: undefined, done: true}, x.next(666));
+ assertEquals({value: 42, done: false}, Next(x));
+ assertEquals({value: 13, done: true}, Throw(x, 666));
+ assertThrowsEquals(() => Throw(x, 666), 666);
+ assertEquals({value: undefined, done: true}, Next(x, 666));
}
}
@@ -100,45 +128,45 @@
{ // "return" closes at suspendedStart
let x = g();
- assertEquals({value: 666, done: true}, x.return(666));
- assertEquals({value: undefined, done: true}, x.next(42));
- assertThrowsEquals(() => x.throw(43), 43);
- assertEquals({value: 42, done: true}, x.return(42));
+ assertEquals({value: 666, done: true}, Return(x, 666));
+ assertEquals({value: undefined, done: true}, Next(x, 42));
+ assertThrowsEquals(() => Throw(x, 43), 43);
+ assertEquals({value: 42, done: true}, Return(x, 42));
}
{ // "throw" closes at suspendedStart
let x = g();
- assertThrowsEquals(() => x.throw(666), 666);
- assertEquals({value: undefined, done: true}, x.next(42));
- assertEquals({value: 43, done: true}, x.return(43));
- assertThrowsEquals(() => x.throw(44), 44);
+ assertThrowsEquals(() => Throw(x, 666), 666);
+ assertEquals({value: undefined, done: true}, Next(x, 42));
+ assertEquals({value: 43, done: true}, Return(x, 43));
+ assertThrowsEquals(() => Throw(x, 44), 44);
}
{ // "next" closes at suspendedYield
let x = g();
- assertEquals({value: 42, done: false}, x.next());
- assertEquals({value: undefined, done: true}, x.next(666));
- assertEquals({value: undefined, done: true}, x.next(666));
- assertThrowsEquals(() => x.throw(666), 666);
- assertEquals({value: 42, done: true}, x.return(42));
+ assertEquals({value: 42, done: false}, Next(x));
+ assertEquals({value: undefined, done: true}, Next(x, 666));
+ assertEquals({value: undefined, done: true}, Next(x, 666));
+ assertThrowsEquals(() => Throw(x, 666), 666);
+ assertEquals({value: 42, done: true}, Return(x, 42));
}
{ // "return" closes at suspendedYield
let x = g();
- assertEquals({value: 42, done: false}, x.next());
- assertEquals({value: 666, done: true}, x.return(666));
- assertEquals({value: undefined, done: true}, x.next(666));
- assertThrowsEquals(() => x.throw(44), 44);
- assertEquals({value: 42, done: true}, x.return(42));
+ assertEquals({value: 42, done: false}, Next(x));
+ assertEquals({value: 666, done: true}, Return(x, 666));
+ assertEquals({value: undefined, done: true}, Next(x, 666));
+ assertThrowsEquals(() => Throw(x, 44), 44);
+ assertEquals({value: 42, done: true}, Return(x, 42));
}
{ // "throw" closes at suspendedYield
let x = g();
- assertEquals({value: 42, done: false}, x.next());
- assertThrowsEquals(() => x.throw(666), 666);
- assertEquals({value: undefined, done: true}, x.next(666));
- assertThrowsEquals(() => x.throw(666), 666);
- assertEquals({value: 42, done: true}, x.return(42));
+ assertEquals({value: 42, done: false}, Next(x));
+ assertThrowsEquals(() => Throw(x, 666), 666);
+ assertEquals({value: undefined, done: true}, Next(x, 666));
+ assertThrowsEquals(() => Throw(x, 666), 666);
+ assertEquals({value: 42, done: true}, Return(x, 42));
}
}
@@ -149,17 +177,17 @@
{
let x = g();
- assertEquals({value: 42, done: false}, x.next());
- assertEquals({value: 43, done: false}, x.return(666));
- assertEquals({value: 13, done: true}, x.next());
- assertEquals({value: 666, done: true}, x.return(666));
+ assertEquals({value: 42, done: false}, Next(x));
+ assertEquals({value: 43, done: false}, Return(x, 666));
+ assertEquals({value: 13, done: true}, Next(x));
+ assertEquals({value: 666, done: true}, Return(x, 666));
}
{
let x = g();
- assertEquals({value: 666, done: true}, x.return(666));
- assertEquals({value: undefined, done: true}, x.next());
- assertEquals({value: 666, done: true}, x.return(666));
+ assertEquals({value: 666, done: true}, Return(x, 666));
+ assertEquals({value: undefined, done: true}, Next(x));
+ assertEquals({value: 666, done: true}, Return(x, 666));
}
}
@@ -170,17 +198,17 @@
{
let x = g();
- assertEquals({value: 42, done: false}, x.next());
- assertEquals({value: 43, done: false}, x.return(666));
- assertEquals({value: 666, done: true}, x.next());
- assertEquals({value: 5, done: true}, x.return(5));
+ assertEquals({value: 42, done: false}, Next(x));
+ assertEquals({value: 43, done: false}, Return(x, 666));
+ assertEquals({value: 666, done: true}, Next(x));
+ assertEquals({value: 5, done: true}, Return(x, 5));
}
{
let x = g();
- assertEquals({value: 666, done: true}, x.return(666));
- assertEquals({value: undefined, done: true}, x.next());
- assertEquals({value: 666, done: true}, x.return(666));
+ assertEquals({value: 666, done: true}, Return(x, 666));
+ assertEquals({value: undefined, done: true}, Next(x));
+ assertEquals({value: 666, done: true}, Return(x, 666));
}
}
@@ -192,29 +220,29 @@
{
let x = g();
- assertEquals({value: 1, done: false}, x.next());
- assertEquals({value: 42, done: false}, x.next());
- assertEquals({value: 43, done: false}, x.next(666));
- assertEquals({value: 13, done: false}, x.next());
- assertEquals({value: undefined, done: true}, x.next());
+ assertEquals({value: 1, done: false}, Next(x));
+ assertEquals({value: 42, done: false}, Next(x));
+ assertEquals({value: 43, done: false}, Next(x, 666));
+ assertEquals({value: 13, done: false}, Next(x));
+ assertEquals({value: undefined, done: true}, Next(x));
}
{
let x = g();
- assertEquals({value: 1, done: false}, x.next());
- assertEquals({value: 42, done: false}, x.next());
- assertEquals({value: 43, done: false}, x.return(666));
- assertEquals({value: 13, done: false}, x.next());
- assertEquals({value: undefined, done: true}, x.next());
+ assertEquals({value: 1, done: false}, Next(x));
+ assertEquals({value: 42, done: false}, Next(x));
+ assertEquals({value: 43, done: false}, Return(x, 666));
+ assertEquals({value: 13, done: false}, Next(x));
+ assertEquals({value: undefined, done: true}, Next(x));
}
{
let x = g();
- assertEquals({value: 1, done: false}, x.next());
- assertEquals({value: 42, done: false}, x.next());
- assertEquals({value: 43, done: false}, x.throw(666));
- assertEquals({value: 13, done: false}, x.next());
- assertEquals({value: undefined, done: true}, x.next());
+ assertEquals({value: 1, done: false}, Next(x));
+ assertEquals({value: 42, done: false}, Next(x));
+ assertEquals({value: 43, done: false}, Throw(x, 666));
+ assertEquals({value: 13, done: false}, Next(x));
+ assertEquals({value: undefined, done: true}, Next(x));
}
}
@@ -226,28 +254,28 @@
{
let x = g();
- assertEquals({value: 1, done: false}, x.next());
- assertEquals({value: 42, done: false}, x.next());
- assertEquals({value: 43, done: false}, x.next(666));
- assertEquals({value: undefined, done: false}, x.next());
- assertEquals({value: undefined, done: true}, x.next());
+ assertEquals({value: 1, done: false}, Next(x));
+ assertEquals({value: 42, done: false}, Next(x));
+ assertEquals({value: 43, done: false}, Next(x, 666));
+ assertEquals({value: undefined, done: false}, Next(x));
+ assertEquals({value: undefined, done: true}, Next(x));
}
{
let x = g();
- assertEquals({value: 1, done: false}, x.next());
- assertEquals({value: 42, done: false}, x.next());
- assertEquals({value: 43, done: false}, x.return(44));
- assertEquals({value: 44, done: false}, x.next());
- assertEquals({value: undefined, done: true}, x.next());
+ assertEquals({value: 1, done: false}, Next(x));
+ assertEquals({value: 42, done: false}, Next(x));
+ assertEquals({value: 43, done: false}, Return(x, 44));
+ assertEquals({value: 44, done: false}, Next(x));
+ assertEquals({value: undefined, done: true}, Next(x));
}
{
let x = g();
- assertEquals({value: 1, done: false}, x.next());
- assertEquals({value: 42, done: false}, x.next());
- assertEquals({value: 43, done: false}, x.throw(666));
- assertThrowsEquals(() => x.next(), 666);
+ assertEquals({value: 1, done: false}, Next(x));
+ assertEquals({value: 42, done: false}, Next(x));
+ assertEquals({value: 43, done: false}, Throw(x, 666));
+ assertThrowsEquals(() => Next(x), 666);
}
}
@@ -265,8 +293,370 @@
{
let x = g();
- assertEquals({value: 1, done: false}, x.next());
- assertEquals({value: 2, done: false}, x.next());
- assertEquals({value: 42, done: true}, x.return(42));
+ assertEquals({value: 1, done: false}, Next(x));
+ assertEquals({value: 2, done: false}, Next(x));
+ assertEquals({value: 42, done: true}, Return(x, 42));
}
}
+
+
+// More or less random tests from here on.
+
+
+{
+ function* foo() { }
+ let g = foo();
+ assertEquals({value: undefined, done: true}, Next(g));
+ assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+ function* foo() { return new.target }
+ let g = foo();
+ assertEquals({value: undefined, done: true}, Next(g));
+ assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+ function* foo() { throw 666; return 42}
+ let g = foo();
+ assertThrowsEquals(() => Next(g), 666);
+ assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+ function* foo(a) { return a; }
+ let g = foo(42);
+ assertEquals({value: 42, done: true}, Next(g));
+ assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+ function* foo(a) { a.iwashere = true; return a; }
+ let x = {};
+ let g = foo(x);
+ assertEquals({value: {iwashere: true}, done: true}, Next(g));
+ assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+ let a = 42;
+ function* foo() { return a; }
+ let g = foo();
+ assertEquals({value: 42, done: true}, Next(g));
+ assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+ let a = 40;
+ function* foo(b) { return a + b; }
+ let g = foo(2);
+ assertEquals({value: 42, done: true}, Next(g));
+ assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+ let a = 40;
+ function* foo(b) { a--; b++; return a + b; }
+ let g = foo(2);
+ assertEquals({value: 42, done: true}, Next(g));
+ assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+ let g;
+ function* foo() { Next(g) }
+ g = foo();
+ assertThrows(() => Next(g), TypeError);
+ assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+ function* foo() { yield 2; yield 3; yield 4 }
+ g = foo();
+ assertEquals({value: 2, done: false}, Next(g));
+ assertEquals({value: 3, done: false}, Next(g));
+ assertEquals({value: 4, done: false}, Next(g));
+ assertEquals({value: undefined, done: true}, Next(g));
+ assertEquals({value: undefined, done: true}, Next(g));
+}
+
+
+{
+ function* foo() { yield 2; if (true) { yield 3 }; yield 4 }
+ g = foo();
+ assertEquals({value: 2, done: false}, Next(g));
+ assertEquals({value: 3, done: false}, Next(g));
+ assertEquals({value: 4, done: false}, Next(g));
+ assertEquals({value: undefined, done: true}, Next(g));
+ assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+ function* foo() { yield 2; if (true) { yield 3; yield 4 } }
+ g = foo();
+ assertEquals({value: 2, done: false}, Next(g));
+ assertEquals({value: 3, done: false}, Next(g));
+ assertEquals({value: 4, done: false}, Next(g));
+ assertEquals({value: undefined, done: true}, Next(g));
+ assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+ function* foo() { yield 2; if (false) { yield 3 }; yield 4 }
+ g = foo();
+ assertEquals({value: 2, done: false}, Next(g));
+ assertEquals({value: 4, done: false}, Next(g));
+ assertEquals({value: undefined, done: true}, Next(g));
+ assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+ function* foo() { yield 2; while (true) { yield 3 }; yield 4 }
+ g = foo();
+ assertEquals({value: 2, done: false}, Next(g));
+ assertEquals({value: 3, done: false}, Next(g));
+ assertEquals({value: 3, done: false}, Next(g));
+ assertEquals({value: 3, done: false}, Next(g));
+ assertEquals({value: 3, done: false}, Next(g));
+}
+
+{
+ function* foo() { yield 2; (yield 3) + 42; yield 4 }
+ g = foo();
+ assertEquals({value: 2, done: false}, Next(g));
+ assertEquals({value: 3, done: false}, Next(g));
+ assertEquals({value: 4, done: false}, Next(g));
+}
+
+{
+ function* foo() { yield 2; (do {yield 3}) + 42; yield 4 }
+ g = foo();
+ assertEquals({value: 2, done: false}, Next(g));
+ assertEquals({value: 3, done: false}, Next(g));
+ assertEquals({value: 4, done: false}, Next(g));
+}
+
+{
+ function* foo() { yield 2; return (yield 3) + 42; yield 4 }
+ g = foo();
+ assertEquals({value: 2, done: false}, Next(g));
+ assertEquals({value: 3, done: false}, Next(g));
+ assertEquals({value: 42, done: true}, Next(g, 0));
+ assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+ let x = 42;
+ function* foo() {
+ yield x;
+ for (let x in {a: 1, b: 2}) {
+ let i = 2;
+ yield x;
+ yield i;
+ do {
+ yield i;
+ } while (i-- > 0);
+ }
+ yield x;
+ return 5;
+ }
+ g = foo();
+ assertEquals({value: 42, done: false}, Next(g));
+ assertEquals({value: 'a', done: false}, Next(g));
+ assertEquals({value: 2, done: false}, Next(g));
+ assertEquals({value: 2, done: false}, Next(g));
+ assertEquals({value: 1, done: false}, Next(g));
+ assertEquals({value: 0, done: false}, Next(g));
+ assertEquals({value: 'b', done: false}, Next(g));
+ assertEquals({value: 2, done: false}, Next(g));
+ assertEquals({value: 2, done: false}, Next(g));
+ assertEquals({value: 1, done: false}, Next(g));
+ assertEquals({value: 0, done: false}, Next(g));
+ assertEquals({value: 42, done: false}, Next(g));
+ assertEquals({value: 5, done: true}, Next(g));
+}
+
+{
+ let a = 3;
+ function* foo() {
+ let b = 4;
+ yield 1;
+ { let c = 5; yield 2; yield a; yield b; yield c; }
+ }
+ g = foo();
+ assertEquals({value: 1, done: false}, Next(g));
+ assertEquals({value: 2, done: false}, Next(g));
+ assertEquals({value: 3, done: false}, Next(g));
+ assertEquals({value: 4, done: false}, Next(g));
+ assertEquals({value: 5, done: false}, Next(g));
+ assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+ function* foo() {
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ yield 42;
+ }
+ g = foo();
+ for (let i = 0; i < 100; ++i) {
+ assertEquals({value: 42, done: false}, i%25 === 0 ? Next(g) : g.next());
+ }
+ assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+ function* foo() {
+ for (let i = 0; i < 3; ++i) {
+ let j = 0
+ yield i;
+ do {
+ yield (i + 10);
+ } while (++j < 2);
+ }
+ }
+ g = foo();
+ assertEquals({value: 0, done: false}, Next(g));
+ assertEquals({value: 10, done: false}, Next(g));
+ assertEquals({value: 10, done: false}, Next(g));
+ assertEquals({value: 1, done: false}, Next(g));
+ assertEquals({value: 11, done: false}, Next(g));
+ assertEquals({value: 11, done: false}, Next(g));
+ assertEquals({value: 2, done: false}, Next(g));
+ assertEquals({value: 12, done: false}, Next(g));
+ assertEquals({value: 12, done: false}, Next(g));
+ assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+ let foo = function*() {
+ while (true) {
+ if (true || false) yield 42;
+ continue;
+ }
+ }
+ g = foo();
+ assertEquals({value: 42, done: false}, Next(g));
+ assertEquals({value: 42, done: false}, Next(g));
+ assertEquals({value: 42, done: false}, Next(g));
+}
+
+{
+ let foo = function*() {
+ yield* (function*() { yield 42; }());
+ assertUnreachable();
+ }
+ g = foo();
+ assertEquals({value: 42, done: false}, Next(g));
+ assertEquals({value: 23, done: true}, Return(g, 23));
+}
+
+{
+ let iterable = {
+ [Symbol.iterator]() {
+ return { next() { return {} } };
+ }
+ };
+ let foo = function*() { yield* iterable };
+ g = foo();
+ g.next();
+ assertThrows(() => Throw(g), TypeError);
+}
diff --git a/test/mjsunit/harmony/harmony-string-pad-end.js b/test/mjsunit/harmony/harmony-string-pad-end.js
index 3292e94..03e5aea 100644
--- a/test/mjsunit/harmony/harmony-string-pad-end.js
+++ b/test/mjsunit/harmony/harmony-string-pad-end.js
@@ -67,8 +67,19 @@
(function TestFillerToString() {
assertEquals(". ", ".".padEnd(10));
assertEquals(". ", ".".padEnd(10, undefined));
- assertEquals(". ", ".".padEnd(10, { toString() { return ""; } }));
assertEquals(".nullnulln", ".".padEnd(10, null));
+ assertEquals(".XXXXXXXXX", ".".padEnd(10, { toString() { return "X"; } }));
+ assertEquals(
+ ".111111111",
+ ".".padEnd(10, { toString: undefined, valueOf() { return 1; } }));
+})();
+
+
+(function TestFillerEmptyString() {
+ assertEquals(".", ".".padEnd(10, ""));
+ assertEquals(".", ".".padEnd(10, { toString() { return ""; } }));
+ assertEquals(
+ ".", ".".padEnd(10, { toString: undefined, valueOf() { return ""; } }));
})();
diff --git a/test/mjsunit/harmony/harmony-string-pad-start.js b/test/mjsunit/harmony/harmony-string-pad-start.js
index 2b2d004..33bf8f3 100644
--- a/test/mjsunit/harmony/harmony-string-pad-start.js
+++ b/test/mjsunit/harmony/harmony-string-pad-start.js
@@ -67,8 +67,19 @@
(function TestFillerToString() {
assertEquals(" .", ".".padStart(10));
assertEquals(" .", ".".padStart(10, undefined));
- assertEquals(" .", ".".padStart(10, { toString() { return ""; } }));
assertEquals("nullnulln.", ".".padStart(10, null));
+ assertEquals("XXXXXXXXX.", ".".padStart(10, { toString() { return "X"; } }));
+ assertEquals(
+ "111111111.",
+ ".".padStart(10, { toString: undefined, valueOf() { return 1; } }));
+})();
+
+
+(function TestFillerEmptyString() {
+ assertEquals(".", ".".padStart(10, ""));
+ assertEquals(".", ".".padStart(10, { toString() { return ""; } }));
+ assertEquals(
+ ".", ".".padStart(10, { toString: undefined, valueOf() { return ""; } }));
})();
diff --git a/test/mjsunit/harmony/instanceof-es6.js b/test/mjsunit/harmony/instanceof-es6.js
index 60e7ee2..4971c9c 100644
--- a/test/mjsunit/harmony/instanceof-es6.js
+++ b/test/mjsunit/harmony/instanceof-es6.js
@@ -48,3 +48,22 @@
// OrdinaryHasInstance passed a non-object argument returns false.
assertEquals(Function.prototype[Symbol.hasInstance].call(Array, 0), false);
+
+// Cannot assign to @@hasInstance with %FunctionPrototype%.
+(function() {
+ "use strict";
+ function F() {}
+ assertThrows(function() { F[Symbol.hasInstance] = (v) => v }, TypeError);
+})();
+
+// Check correct invocation of @@hasInstance handler on function instance.
+(function() {
+ function F() {}
+ var counter = 0;
+ var proto = Object.getPrototypeOf(F);
+ Object.setPrototypeOf(F, null);
+ F[Symbol.hasInstance] = function(v) { ++counter; return true };
+ Object.setPrototypeOf(F, proto);
+ assertTrue(1 instanceof F);
+ assertEquals(1, counter);
+})();
diff --git a/test/mjsunit/harmony/iterator-close.js b/test/mjsunit/harmony/iterator-close.js
index 09e0153..03cdeac 100644
--- a/test/mjsunit/harmony/iterator-close.js
+++ b/test/mjsunit/harmony/iterator-close.js
@@ -1007,6 +1007,26 @@
assertThrowsEquals(() => {
(([x]) => x)(g());
}, 666);
+
+ assertThrowsEquals(() => {
+ var [...x] = g();
+ }, 666);
+
+ assertThrowsEquals(() => {
+ let [...x] = g();
+ }, 666);
+
+ assertThrowsEquals(() => {
+ const [...x] = g();
+ }, 666);
+
+ assertThrowsEquals(() => {
+ [...x] = g();
+ }, 666);
+
+ assertThrowsEquals(() => {
+ (([...x]) => x)(g());
+ }, 666);
}
@@ -1051,6 +1071,26 @@
assertThrowsEquals(() => {
(([x]) => x)(g());
}, 666);
+
+ assertThrowsEquals(() => {
+ var [...x] = g();
+ }, 666);
+
+ assertThrowsEquals(() => {
+ let [...x] = g();
+ }, 666);
+
+ assertThrowsEquals(() => {
+ const [...x] = g();
+ }, 666);
+
+ assertThrowsEquals(() => {
+ [...x] = g();
+ }, 666);
+
+ assertThrowsEquals(() => {
+ (([...x]) => x)(g());
+ }, 666);
}
@@ -1095,6 +1135,26 @@
assertThrowsEquals(() => {
(([x]) => x)(g());
}, 666);
+
+ assertThrowsEquals(() => {
+ var [...x] = g();
+ }, 666);
+
+ assertThrowsEquals(() => {
+ let [...x] = g();
+ }, 666);
+
+ assertThrowsEquals(() => {
+ const [...x] = g();
+ }, 666);
+
+ assertThrowsEquals(() => {
+ [...x] = g();
+ }, 666);
+
+ assertThrowsEquals(() => {
+ (([...x]) => x)(g());
+ }, 666);
}
@@ -1238,3 +1298,75 @@
}, 5);
assertEquals([1], log);
}
+
+
+// yield*, argument's return method is "undefined".
+function TestYieldStarWithoutReturn(get_iterable) {
+ assertTrue(get_iterable().return == undefined);
+
+ function* g() { yield* get_iterable() }
+
+ {
+ let gen = g();
+ assertEquals({value: 1, done: false}, gen.next());
+ assertEquals({value: undefined, done: true}, gen.return());
+ }
+
+ assertEquals(42, (() => {
+ for (let x of g()) break;
+ return 42;
+ })());
+
+ assertEquals(42, (() => {
+ for (let x of g()) return 42;
+ })());
+
+ assertThrowsEquals(() => {
+ for (let x of g()) throw 42;
+ }, 42);
+}
+{
+ let get_iterable1 = () => [1, 2];
+ let get_iterable2 = function*() { yield 1; yield 2 };
+ get_iterable2.prototype.return = null;
+ TestYieldStarWithoutReturn(get_iterable1);
+ TestYieldStarWithoutReturn(get_iterable2);
+}
+
+
+// yield*, argument's return method is defined.
+{
+ let get_iterable = function*() { yield 1; yield 2 };
+ const obj = {};
+ get_iterable.prototype.return = (...args) => obj;
+
+ function* g() { yield* get_iterable() }
+
+ {
+ let gen = g();
+ assertEquals({value: 1, done: false}, gen.next());
+ assertSame(obj, gen.return());
+ assertSame(obj, gen.return());
+ assertSame(obj, gen.return());
+ assertEquals({value: 2, done: false}, gen.next());
+ assertSame(obj, gen.return());
+ assertSame(obj, gen.return());
+ assertSame(obj, gen.return());
+ assertEquals({value: undefined, done: true}, gen.next());
+ assertEquals({value: undefined, done: true}, gen.return());
+ assertEquals({value: undefined, done: true}, gen.return());
+ }
+
+ assertEquals(42, (() => {
+ for (let x of g()) break;
+ return 42;
+ })());
+
+ assertEquals(42, (() => {
+ for (let x of g()) return 42;
+ })());
+
+ assertThrowsEquals(() => {
+ for (let x of g()) throw 42;
+ }, 42);
+}
diff --git a/test/mjsunit/harmony/regexp-property-binary.js b/test/mjsunit/harmony/regexp-property-binary.js
new file mode 100644
index 0000000..d0894b7
--- /dev/null
+++ b/test/mjsunit/harmony/regexp-property-binary.js
@@ -0,0 +1,25 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-regexp-property --harmony-unicode-regexps
+
+function t(re, s) { assertTrue(re.test(s)); }
+function f(re, s) { assertFalse(re.test(s)); }
+
+t(/\p{Bidi_Control}+/u, "\u200E");
+f(/\p{Bidi_C}+/u, "On a dark desert highway, cool wind in my hair");
+t(/\p{AHex}+/u, "DEADBEEF");
+t(/\p{Alphabetic}+/u, "abcdefg");
+t(/\P{Alphabetic}+/u, "1234");
+t(/\p{White_Space}+/u, "\u00A0");
+t(/\p{Uppercase}+/u, "V");
+f(/\p{Lower}+/u, "U");
+t(/\p{Ideo}+/u, "字");
+f(/\p{Ideo}+/u, "x");
+
+assertThrows("/\\p{Hiragana}/u");
+assertThrows("/\\p{Bidi_Class}/u");
+assertThrows("/\\p{Bidi_C=False}/u");
+assertThrows("/\\P{Bidi_Control=Y}/u");
+assertThrows("/\\p{AHex=Yes}/u");
diff --git a/test/mjsunit/harmony/regexp-property-blocks.js b/test/mjsunit/harmony/regexp-property-blocks.js
index d186e98..f41c06e 100644
--- a/test/mjsunit/harmony/regexp-property-blocks.js
+++ b/test/mjsunit/harmony/regexp-property-blocks.js
@@ -7,28 +7,28 @@
function t(re, s) { assertTrue(re.test(s)); }
function f(re, s) { assertFalse(re.test(s)); }
-t(/\p{InASCII}+/u, ".");
-t(/\p{InASCII}+/u, "supercalifragilisticexpialidocious");
-t(/\p{InBasic_Latin}+/u, ".");
-t(/\p{InBasic_Latin}+/u, "supercalifragilisticexpialidocious");
+t(/\p{Block=ASCII}+/u, ".");
+t(/\p{Block=ASCII}+/u, "supercalifragilisticexpialidocious");
+t(/\p{Block=Basic_Latin}+/u, ".");
+t(/\p{Block=Basic_Latin}+/u, "supercalifragilisticexpialidocious");
-t(/\p{InCJK}+/u, "话说天下大势,分久必合,合久必分");
-t(/\p{InCJK_Unified_Ideographs}+/u, "吾庄后有一桃园,花开正盛");
-f(/\p{InCJK}+/u, "おはようございます");
-f(/\p{InCJK_Unified_Ideographs}+/u,
+t(/\p{blk=CJK}+/u, "话说天下大势,分久必合,合久必分");
+t(/\p{blk=CJK_Unified_Ideographs}+/u, "吾庄后有一桃园,花开正盛");
+f(/\p{blk=CJK}+/u, "おはようございます");
+f(/\p{blk=CJK_Unified_Ideographs}+/u,
"Something is rotten in the state of Denmark");
-t(/\p{InLatin_1}+/u, "Wie froh bin ich, daß ich weg bin!");
-f(/\p{InLatin_1_Supplement}+/u, "奔腾千里荡尘埃,渡水登山紫雾开");
-f(/\p{InLatin_1_Sup}+/u, "いただきます");
+t(/\p{blk=Latin_1}+/u, "Wie froh bin ich, daß ich weg bin!");
+f(/\p{blk=Latin_1_Supplement}+/u, "奔腾千里荡尘埃,渡水登山紫雾开");
+f(/\p{blk=Latin_1_Sup}+/u, "いただきます");
-t(/\p{InHiragana}/u, "いただきます");
-t(/\p{Hiragana}/u, "\u{1b001}"); // This refers to the script "Hiragana".
-f(/\p{InHiragana}/u, "\u{1b001}"); // This refers to the block "Hiragana".
+t(/\p{blk=Hiragana}/u, "いただきます");
+t(/\p{sc=Hiragana}/u, "\u{1b001}"); // This refers to the script "Hiragana".
+f(/\p{blk=Hiragana}/u, "\u{1b001}"); // This refers to the block "Hiragana".
-t(/\p{InGreek_And_Coptic}/u,
+t(/\p{blk=Greek_And_Coptic}/u,
"ἄνδρα μοι ἔννεπε, μοῦσα, πολύτροπον, ὃς μάλα πολλὰ");
-t(/\p{InGreek}/u, "μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος");
+t(/\p{blk=Greek}/u, "μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος");
assertThrows("/\\p{In}/u");
assertThrows("/\\pI/u");
diff --git a/test/mjsunit/harmony/regexp-property-char-class.js b/test/mjsunit/harmony/regexp-property-char-class.js
index 76774cb..6162012 100644
--- a/test/mjsunit/harmony/regexp-property-char-class.js
+++ b/test/mjsunit/harmony/regexp-property-char-class.js
@@ -9,9 +9,6 @@
assertThrows("/[\\p{}]/u");
assertThrows("/[\\p{]/u");
assertThrows("/[\\p}]/u");
-assertThrows("/[\\p{Math}]/u");
-assertThrows("/[\\p{Bidi_M}]/u");
-assertThrows("/[\\p{Hex}]/u");
assertTrue(/^[\p{Lu}\p{Ll}]+$/u.test("ABCabc"));
assertTrue(/^[\p{Lu}-\p{Ll}]+$/u.test("ABC-abc"));
@@ -19,6 +16,9 @@
assertTrue(/^[\P{Lu}\p{Ll}]+$/u.test("abc"));
assertTrue(/^[\P{Lu}]+$/u.test("abc123"));
assertFalse(/^[\P{Lu}]+$/u.test("XYZ"));
+assertTrue(/[\p{Math}]/u.test("+"));
+assertTrue(/[\P{Bidi_M}]/u.test(" "));
+assertTrue(/[\p{Hex}]/u.test("A"));
assertTrue(/^[^\P{Lu}]+$/u.test("XYZ"));
assertFalse(/^[^\p{Lu}\p{Ll}]+$/u.test("abc"));
diff --git a/test/mjsunit/harmony/regexp-property-enumerated.js b/test/mjsunit/harmony/regexp-property-enumerated.js
new file mode 100644
index 0000000..e4a81a4
--- /dev/null
+++ b/test/mjsunit/harmony/regexp-property-enumerated.js
@@ -0,0 +1,28 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-regexp-property --harmony-unicode-regexps
+
+function t(re, s) { assertTrue(re.test(s)); }
+function f(re, s) { assertFalse(re.test(s)); }
+
+t(/\p{Bidi_Class=L}+/u, "Is this the real life?");
+t(/\p{bc=Left_To_Right}+/u, "Is this just fantasy?");
+t(/\p{bc=AL}+/u, "السلام عليكم");
+t(/\p{bc=Arabic_Letter}+/u, "متشرف بمعرفتك");
+
+t(/\p{Line_Break=Glue}/u, "\u00A0");
+t(/\p{lb=AL}/u, "~");
+
+assertThrows("/\\p{Block=}/u");
+assertThrows("/\\p{=}/u");
+assertThrows("/\\p{=L}/u");
+assertThrows("/\\p{=Hiragana}/u");
+assertThrows("/\\p{Block=CJK=}/u");
+
+assertThrows("/\\p{Age=V8_0}/u");
+assertThrows("/\\p{General_Category=Letter}/u");
+assertThrows("/\\p{gc=L}/u");
+assertThrows("/\\p{General_Category_Mask=Letter}/u");
+assertThrows("/\\p{gcm=L}/u");
diff --git a/test/mjsunit/harmony/regexp-property-exact-match.js b/test/mjsunit/harmony/regexp-property-exact-match.js
index 4dfcc5f..fe233f2 100644
--- a/test/mjsunit/harmony/regexp-property-exact-match.js
+++ b/test/mjsunit/harmony/regexp-property-exact-match.js
@@ -6,12 +6,12 @@
assertThrows("/\\p{In CJK}/u");
assertThrows("/\\p{InCJKUnifiedIdeographs}/u");
-assertDoesNotThrow("/\\p{InCJK}/u");
-assertDoesNotThrow("/\\p{InCJK_Unified_Ideographs}/u");
+assertThrows("/\\p{InCJK}/u");
+assertThrows("/\\p{InCJK_Unified_Ideographs}/u");
-assertDoesNotThrow("/\\p{InCyrillic_Sup}/u");
-assertDoesNotThrow("/\\p{InCyrillic_Supplement}/u");
-assertDoesNotThrow("/\\p{InCyrillic_Supplementary}/u");
+assertThrows("/\\p{InCyrillic_Sup}/u");
+assertThrows("/\\p{InCyrillic_Supplement}/u");
+assertThrows("/\\p{InCyrillic_Supplementary}/u");
assertThrows("/\\p{InCyrillicSupplementary}/u");
assertThrows("/\\p{InCyrillic_supplementary}/u");
@@ -25,9 +25,18 @@
assertDoesNotThrow("/\\p{Combining_Mark}/u");
assertThrows("/\\p{Combining Mark}/u");
-assertDoesNotThrow("/\\p{Copt}/u");
-assertDoesNotThrow("/\\p{Coptic}/u");
-assertDoesNotThrow("/\\p{Qaac}/u");
-assertDoesNotThrow("/\\p{Egyp}/u");
-assertDoesNotThrow("/\\p{Egyptian_Hieroglyphs}/u");
+assertDoesNotThrow("/\\p{Script=Copt}/u");
+assertThrows("/\\p{Coptic}/u");
+assertThrows("/\\p{Qaac}/u");
+assertThrows("/\\p{Egyp}/u");
+assertDoesNotThrow("/\\p{Script=Egyptian_Hieroglyphs}/u");
assertThrows("/\\p{EgyptianHieroglyphs}/u");
+
+assertThrows("/\\p{BidiClass=LeftToRight}/u");
+assertThrows("/\\p{BidiC=LeftToRight}/u");
+assertThrows("/\\p{bidi_c=Left_To_Right}/u");
+
+assertDoesNotThrow("/\\p{Block=CJK}/u");
+assertThrows("/\\p{Block = CJK}/u");
+assertThrows("/\\p{Block=cjk}/u");
+assertThrows("/\\p{BLK=CJK}/u");
diff --git a/test/mjsunit/harmony/regexp-property-scripts.js b/test/mjsunit/harmony/regexp-property-scripts.js
index 19b50ee..ec2b11d 100644
--- a/test/mjsunit/harmony/regexp-property-scripts.js
+++ b/test/mjsunit/harmony/regexp-property-scripts.js
@@ -7,33 +7,33 @@
function t(re, s) { assertTrue(re.test(s)); }
function f(re, s) { assertFalse(re.test(s)); }
-t(/\p{Common}+/u, ".");
-f(/\p{Common}+/u, "supercalifragilisticexpialidocious");
+t(/\p{Script=Common}+/u, ".");
+f(/\p{Script=Common}+/u, "supercalifragilisticexpialidocious");
-t(/\p{Han}+/u, "话说天下大势,分久必合,合久必分");
-t(/\p{Hani}+/u, "吾庄后有一桃园,花开正盛");
-f(/\p{Han}+/u, "おはようございます");
-f(/\p{Hani}+/u, "Something is rotten in the state of Denmark");
+t(/\p{Script=Han}+/u, "话说天下大势,分久必合,合久必分");
+t(/\p{Script=Hani}+/u, "吾庄后有一桃园,花开正盛");
+f(/\p{Script=Han}+/u, "おはようございます");
+f(/\p{Script=Hani}+/u, "Something is rotten in the state of Denmark");
-t(/\p{Latin}+/u, "Wie froh bin ich, daß ich weg bin!");
-t(/\p{Latn}+/u,
+t(/\p{Script=Latin}+/u, "Wie froh bin ich, daß ich weg bin!");
+t(/\p{Script=Latn}+/u,
"It was a bright day in April, and the clocks were striking thirteen");
-f(/\p{Latin}+/u, "奔腾千里荡尘埃,渡水登山紫雾开");
-f(/\p{Latn}+/u, "いただきます");
+f(/\p{Script=Latin}+/u, "奔腾千里荡尘埃,渡水登山紫雾开");
+f(/\p{Script=Latn}+/u, "いただきます");
-t(/\p{Hiragana}/u, "いただきます");
-t(/\p{Hira}/u, "ありがとうございました");
-f(/\p{Hiragana}/u,
+t(/\p{sc=Hiragana}/u, "いただきます");
+t(/\p{sc=Hira}/u, "ありがとうございました");
+f(/\p{sc=Hiragana}/u,
"Als Gregor Samsa eines Morgens aus unruhigen Träumen erwachte");
-f(/\p{Hira}/u, "Call me Ishmael");
+f(/\p{sc=Hira}/u, "Call me Ishmael");
-t(/\p{Phoenician}/u, "\u{10900}\u{1091a}");
-t(/\p{Phnx}/u, "\u{1091f}\u{10916}");
-f(/\p{Phoenician}/u, "Arthur est un perroquet");
-f(/\p{Phnx}/u, "设心狠毒非良士,操卓原来一路人");
+t(/\p{sc=Phoenician}/u, "\u{10900}\u{1091a}");
+t(/\p{sc=Phnx}/u, "\u{1091f}\u{10916}");
+f(/\p{sc=Phoenician}/u, "Arthur est un perroquet");
+f(/\p{sc=Phnx}/u, "设心狠毒非良士,操卓原来一路人");
-t(/\p{Grek}/u, "ἄνδρα μοι ἔννεπε, μοῦσα, πολύτροπον, ὃς μάλα πολλὰ");
-t(/\p{Greek}/u, "μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος");
-f(/\p{Greek}/u, "高贤未服英雄志,屈节偏生杰士疑");
-f(/\p{Greek}/u,
+t(/\p{sc=Grek}/u, "ἄνδρα μοι ἔννεπε, μοῦσα, πολύτροπον, ὃς μάλα πολλὰ");
+t(/\p{sc=Greek}/u, "μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος");
+f(/\p{sc=Greek}/u, "高贤未服英雄志,屈节偏生杰士疑");
+f(/\p{sc=Greek}/u,
"Mr. Jones, of the Manor Farm, had locked the hen-houses for the night");
diff --git a/test/mjsunit/harmony/regress/regress-4904.js b/test/mjsunit/harmony/regress/regress-4904.js
new file mode 100644
index 0000000..a57d246
--- /dev/null
+++ b/test/mjsunit/harmony/regress/regress-4904.js
@@ -0,0 +1,24 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-do-expressions
+
+(function testCatchScopeInDoExpression() {
+ var f = (s = 17, y = do { try { throw 25; } catch(e) { s += e; }; }) => s;
+ var result = f();
+ assertEquals(result, 42);
+})();
+
+(function testCatchScopeInDoExpression() {
+ var f = (s = 17, y = do { let t; try { throw 25; } catch(e) { s += e; }; }) => s;
+ var result = f();
+ assertEquals(result, 42);
+})();
+
+(function testCatchScopeInDoExpression() {
+ let t1;
+ var f = (s = 17, y = do { let t2; try { throw 25; } catch(e) { s += e; }; }) => s;
+ var result = f();
+ assertEquals(result, 42);
+})();
diff --git a/test/mjsunit/harmony/regress/regress-observe-empty-double-array.js b/test/mjsunit/harmony/regress/regress-observe-empty-double-array.js
deleted file mode 100644
index 1460889..0000000
--- a/test/mjsunit/harmony/regress/regress-observe-empty-double-array.js
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2012 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Flags: --harmony-object-observe
-// Flags: --allow-natives-syntax
-//
-// Test passes if it does not crash.
-
-arr = [1.1];
-Object.observe(arr, function(){});
-arr.length = 0;
-// TODO(observe): we currently disallow fast elements for observed object.
-// assertTrue(%HasFastDoubleElements(arr));
-// Should not crash
-arr.push(1.1);
diff --git a/test/mjsunit/holy-double-no-arg-array.js b/test/mjsunit/holy-double-no-arg-array.js
new file mode 100644
index 0000000..73e2ddc
--- /dev/null
+++ b/test/mjsunit/holy-double-no-arg-array.js
@@ -0,0 +1,14 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function() {
+ function f() {
+ return new Array();
+ }
+ var a = f();
+ a[0] = 0.5;
+ var b = f();
+ b[2] = 0.5;
+ assertEquals(undefined, b[0]);
+})();
diff --git a/test/mjsunit/ignition/elided-instruction-no-ignition.js b/test/mjsunit/ignition/elided-instruction-no-ignition.js
index d31150b..50ad528 100644
--- a/test/mjsunit/ignition/elided-instruction-no-ignition.js
+++ b/test/mjsunit/ignition/elided-instruction-no-ignition.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --expose-debug-as debug
+// Flags: --no-ignition --expose-debug-as debug
Debug = debug.Debug
diff --git a/test/mjsunit/ignition/elided-instruction.js b/test/mjsunit/ignition/elided-instruction.js
index 807974b..a047f41 100644
--- a/test/mjsunit/ignition/elided-instruction.js
+++ b/test/mjsunit/ignition/elided-instruction.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --expose-debug-as debug
+// Flags: --ignition --expose-debug-as debug
Debug = debug.Debug
diff --git a/test/mjsunit/ignition/ignition-statistics-extension.js b/test/mjsunit/ignition/ignition-statistics-extension.js
new file mode 100644
index 0000000..43d05c9
--- /dev/null
+++ b/test/mjsunit/ignition/ignition-statistics-extension.js
@@ -0,0 +1,62 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --ignition --trace-ignition-dispatches
+
+assertEquals(typeof getIgnitionDispatchCounters, "function");
+
+var old_dispatch_counters = getIgnitionDispatchCounters();
+
+// Check that old_dispatch_counters is a non-empty object of objects, such that
+// the value of each property in the inner objects is a number.
+
+assertEquals(typeof old_dispatch_counters, "object");
+assertTrue(Object.getOwnPropertyNames(old_dispatch_counters).length > 0);
+for (var source_bytecode in old_dispatch_counters) {
+ var counters_row = old_dispatch_counters[source_bytecode];
+ assertEquals(typeof counters_row, "object");
+ for (var counter in counters_row) {
+ assertEquals(typeof counters_row[counter], "number");
+ }
+}
+
+// Do something
+function f(x) { return x*x; }
+f(42);
+
+var new_dispatch_counters = getIgnitionDispatchCounters();
+
+var old_source_bytecodes = Object.getOwnPropertyNames(old_dispatch_counters);
+var new_source_bytecodes = Object.getOwnPropertyNames(new_dispatch_counters);
+var common_source_bytecodes = new_source_bytecodes.filter(function (name) {
+ return old_source_bytecodes.indexOf(name) > -1;
+});
+
+// Check that the keys on the outer objects are the same
+assertEquals(common_source_bytecodes, old_source_bytecodes);
+assertEquals(common_source_bytecodes, new_source_bytecodes);
+
+common_source_bytecodes.forEach(function (source_bytecode) {
+ var new_counters_row = new_dispatch_counters[source_bytecode];
+ var old_counters_row = old_dispatch_counters[source_bytecode];
+
+ var old_destination_bytecodes = Object.getOwnPropertyNames(old_counters_row);
+ var new_destination_bytecodes = Object.getOwnPropertyNames(new_counters_row);
+
+ // Check that all the keys in old_ are in new_ too
+ old_destination_bytecodes.forEach(function (name) {
+ assertTrue(new_destination_bytecodes.indexOf(name) > -1);
+ });
+
+ // Check that for each source-destination pair, the counter has either
+ // appeared (was undefined before calling f()), is unchanged, or incremented.
+ new_destination_bytecodes.forEach(function (destination_bytecode) {
+ var new_counter = new_counters_row[destination_bytecode];
+ var old_counter = old_counters_row[destination_bytecode];
+ assertTrue(typeof new_counter === "number");
+ if (typeof old_counter === "number") {
+ assertTrue(new_counter >= old_counter);
+ }
+ });
+});
diff --git a/test/mjsunit/ignition/regress-599001-verifyheap.js b/test/mjsunit/ignition/regress-599001-verifyheap.js
index 5aa2efd..ce5b46d 100644
--- a/test/mjsunit/ignition/regress-599001-verifyheap.js
+++ b/test/mjsunit/ignition/regress-599001-verifyheap.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --verify-heap --expose-gc
+// Flags: --ignition --verify-heap --expose-gc
// Tests that verify heap works for BytecodeArrays in the large object space.
diff --git a/test/mjsunit/messages.js b/test/mjsunit/messages.js
index 8796d05..d40994d 100644
--- a/test/mjsunit/messages.js
+++ b/test/mjsunit/messages.js
@@ -147,7 +147,12 @@
}, "Method Set.prototype.add called on incompatible receiver [object Array]",
TypeError);
-// kInstanceofFunctionExpected
+// kNonCallableInInstanceOfCheck
+test(function() {
+ 1 instanceof {};
+}, "Right-hand side of 'instanceof' is not callable", TypeError);
+
+// kNonObjectInInstanceOfCheck
test(function() {
1 instanceof 1;
}, "Right-hand side of 'instanceof' is not an object", TypeError);
diff --git a/test/mjsunit/migrations.js b/test/mjsunit/migrations.js
index a18d884..2bd70fb 100644
--- a/test/mjsunit/migrations.js
+++ b/test/mjsunit/migrations.js
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-ayle license that can be
// found in the LICENSE file.
-// Flags: --harmony-object-observe
// Flags: --allow-natives-syntax --track-fields --expose-gc
var global = Function('return this')();
@@ -275,10 +274,6 @@
},
},
{
- name: "observe",
- migr: function(o, i) { Object.observe(o, function(){}); },
- },
- {
name: "seal",
migr: function(o, i) { Object.seal(o); },
},
diff --git a/test/mjsunit/mirror-object.js b/test/mjsunit/mirror-object.js
index 834d7a5..cae652a 100644
--- a/test/mjsunit/mirror-object.js
+++ b/test/mjsunit/mirror-object.js
@@ -265,3 +265,27 @@
assertTrue("[[BoundArgs]]" in property_map);
assertEquals("object", property_map["[[BoundArgs]]"].value().type());
assertEquals(1, property_map["[[BoundArgs]]"].value().value().length);
+
+// Test JSProxy internal properties.
+var target = {};
+var handler = {
+ get: function (target, name, receiver) {
+ return target[name];
+ },
+ set: function(target, name, value, receiver) {
+ target[name] = value;
+ return value;
+ }
+}
+ip = debug.ObjectMirror.GetInternalProperties(new Proxy(target, handler));
+assertEquals(3, ip.length);
+var property_map = {};
+for (var i = 0; i < ip.length; i++) {
+ property_map[ip[i].name()] = ip[i];
+}
+assertTrue("[[Target]]" in property_map);
+assertEquals(target, property_map["[[Target]]"].value().value());
+assertTrue("[[Handler]]" in property_map);
+assertEquals(handler, property_map["[[Handler]]"].value().value());
+assertTrue("[[IsRevoked]]" in property_map);
+assertEquals(false, property_map["[[IsRevoked]]"].value().value());
diff --git a/test/mjsunit/mjsunit.gyp b/test/mjsunit/mjsunit.gyp
index 35ce2ff..e0a7469 100644
--- a/test/mjsunit/mjsunit.gyp
+++ b/test/mjsunit/mjsunit.gyp
@@ -13,8 +13,8 @@
'../../src/d8.gyp:d8_run',
],
'includes': [
- '../../build/features.gypi',
- '../../build/isolate.gypi',
+ '../../gypfiles/features.gypi',
+ '../../gypfiles/isolate.gypi',
],
'sources': [
'mjsunit.isolate',
diff --git a/test/mjsunit/mjsunit.js b/test/mjsunit/mjsunit.js
index 9b07953..6a7c2da 100644
--- a/test/mjsunit/mjsunit.js
+++ b/test/mjsunit/mjsunit.js
@@ -114,6 +114,9 @@
var assertOptimized;
var assertUnoptimized;
+// Assert that a string contains another expected substring.
+var assertContains;
+
(function () { // Scope for utility functions.
@@ -416,6 +419,12 @@
throw new MjsUnitAssertionError(message);
};
+ assertContains = function(sub, value, name_opt) {
+ if (value == null ? (sub != null) : value.indexOf(sub) == -1) {
+ fail("contains '" + String(sub) + "'", value, name_opt);
+ }
+ };
+
var OptimizationStatusImpl = undefined;
var OptimizationStatus = function(fun, sync_opt) {
diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status
index 6d786f9..228832b 100644
--- a/test/mjsunit/mjsunit.status
+++ b/test/mjsunit/mjsunit.status
@@ -76,6 +76,7 @@
'unicode-test': [PASS, NO_VARIANTS],
'whitespaces': [PASS, NO_VARIANTS],
'compiler/osr-assert': [PASS, NO_VARIANTS],
+ 'ignition/regress-599001-verifyheap': [PASS, NO_VARIANTS],
'es6/string-fromcodepoint': [PASS, NO_VARIANTS],
'regress/regress-2185-2': [PASS, NO_VARIANTS],
'regress/regress-2612': [PASS, NO_VARIANTS],
@@ -149,10 +150,6 @@
# issue 4078:
'allocation-site-info': [PASS, NO_VARIANTS],
- # TODO(turbofan): The escape analysis needs some investigation.
- 'compiler/escape-analysis-deopt-5': [PASS, NO_VARIANTS],
- 'compiler/escape-analysis-9': [PASS, NO_VARIANTS],
-
##############################################################################
# Too slow in debug mode with --stress-opt mode.
'compiler/regress-stacktrace-methods': [PASS, ['mode == debug', SKIP]],
@@ -260,7 +257,6 @@
# Slow tests.
'copy-on-write-assert': [PASS, SLOW],
'debug-scopes': [PASS, SLOW],
- 'es7/object-observe': [PASS, ['mode == debug', SLOW]],
'numops-fuzz-part*': [PASS, ['mode == debug', SLOW]],
'readonly': [PASS, SLOW],
'regress/regress-1200351': [PASS, ['mode == debug', SLOW]],
@@ -274,21 +270,72 @@
'wasm/asm-wasm-literals': [PASS, ['arch in [arm, arm64, mips, mipsel, mips64, mips64el] or ignition == True', SKIP]],
'wasm/asm-wasm-copy': [PASS, ['arch in [arm, arm64, mips, mipsel, mips64, mips64el]', SKIP]],
'wasm/asm-wasm-deopt': [PASS, ['arch in [arm, arm64, mips, mipsel, mips64, mips64el]', SKIP]],
+ 'wasm/asm-wasm-switch': [PASS, ['arch in [arm, arm64, mips, mipsel, mips64, mips64el]', SKIP]],
# TODO(branelson): Figure out why ignition + asm->wasm fails embenchen.
'wasm/embenchen/*': [PASS, ['arch == arm64', SKIP], ['ignition == True', SKIP]],
- # TODO(bradnelson) Fix and re-enable.
- 'wasm/embenchen/box2d': [SKIP], # hang
- 'wasm/embenchen/lua_binarytrees': [SKIP], # fails decode
- #'wasm/embenchen/zlib': [SKIP], # fails gc-stress
-
# case-insensitive unicode regexp relies on case mapping provided by ICU.
'harmony/unicode-regexp-ignore-case': [PASS, ['no_i18n == True', FAIL]],
'harmony/unicode-regexp-ignore-case-noi18n': [FAIL, ['no_i18n == True', PASS]],
'regress/regress-5036': [PASS, ['no_i18n == True', FAIL]],
# desugaring regexp property class relies on ICU.
'harmony/regexp-property-*': [PASS, ['no_i18n == True', FAIL]],
+
+ ############################################################################
+ # Ignition
+
+ # TODO(mythria, 4780): Related to type feedback for calls in interpreter.
+ 'array-literal-feedback': [PASS, NO_IGNITION],
+ 'regress/regress-4121': [PASS, NO_IGNITION],
+
+ # TODO(mythria, 4764): lack of osr support.
+ 'regress/regress-2618': [PASS, NO_IGNITION],
+
+ # TODO(mythria, 4764): lack of osr support. The tests waits in a loop
+ # till it is optimized. So test timeouts.
+ 'array-literal-transitions': [PASS, NO_IGNITION],
+
+ # TODO(rmcilroy, 4680): Script throws RangeError as expected, but does so during
+ # eager compile of the whole script instead of during lazy compile of the function
+ # f(), so we can't catch the exception in the try/catch. Skip because on some
+ # platforms the stack limit is different and the exception doesn't fire.
+ 'regress/regress-crbug-589472': [PASS, NO_IGNITION],
+
+ # TODO(4680): Test doesn't know about three tier compiler pipeline.
+ 'assert-opt-and-deopt': [PASS, NO_IGNITION],
+
+ # BUG(rmcilroy,4989): Function is optimized without type feedback and so immediately deopts again, causing check failure in the test.
+ 'compiler/deopt-inlined-from-call': [PASS, NO_IGNITION],
+ 'compiler/increment-typefeedback': [PASS, NO_IGNITION],
+ 'compiler/manual-concurrent-recompile': [PASS, NO_IGNITION],
+ 'constant-folding-2': [PASS, NO_IGNITION],
+ 'debug-is-active': [PASS, NO_IGNITION],
+ 'deopt-with-fp-regs': [PASS, NO_IGNITION],
+ 'deserialize-optimize-inner': [PASS, NO_IGNITION],
+ 'div-mul-minus-one': [PASS, NO_IGNITION],
+ 'double-intrinsics': [PASS, NO_IGNITION],
+ 'elements-transition-hoisting': [PASS, NO_IGNITION],
+ 'es6/block-let-crankshaft': [PASS, NO_IGNITION],
+ 'es6/block-let-crankshaft-sloppy': [PASS, NO_IGNITION],
+ 'getters-on-elements': [PASS, NO_IGNITION],
+ 'harmony/do-expressions': [PASS, NO_IGNITION],
+ 'math-floor-of-div-minus-zero': [PASS, NO_IGNITION],
+ 'regress/regress-2132': [PASS, NO_IGNITION],
+ 'regress/regress-2339': [PASS, NO_IGNITION],
+ 'regress/regress-3176': [PASS, NO_IGNITION],
+ 'regress/regress-3709': [PASS, NO_IGNITION],
+ 'regress/regress-385565': [PASS, NO_IGNITION],
+ 'regress/regress-crbug-594183': [PASS, NO_IGNITION],
+ 'regress/regress-embedded-cons-string': [PASS, NO_IGNITION],
+ 'regress/regress-map-invalidation-2': [PASS, NO_IGNITION],
+ 'regress/regress-param-local-type': [PASS, NO_IGNITION],
+ 'regress/regress-prepare-break-while-recompile': [PASS, NO_IGNITION],
+ 'shift-for-integer-div': [PASS, NO_IGNITION],
+ 'sin-cos': [PASS, NO_IGNITION],
+ 'smi-mul-const': [PASS, NO_IGNITION],
+ 'smi-mul': [PASS, NO_IGNITION],
+ 'unary-minus-deopt': [PASS, NO_IGNITION],
}], # ALWAYS
['novfp3 == True', {
@@ -459,6 +506,13 @@
'unicodelctest': [PASS, SLOW],
'unicode-test': [PASS, SLOW],
'whitespaces': [PASS, TIMEOUT, SLOW],
+
+ # TODO(rmcilroy,4680): Arm64 specific timeouts.
+ 'asm/construct-double': [PASS, NO_IGNITION],
+ 'compiler/osr-one': [PASS, NO_IGNITION],
+ 'compiler/osr-two': [PASS, NO_IGNITION],
+ 'wasm/asm-wasm-i32': [PASS, NO_IGNITION],
+ 'wasm/asm-wasm-u32': [PASS, NO_IGNITION],
}], # 'arch == arm64'
['arch == arm64 and mode == debug and simulator_run == True', {
@@ -475,6 +529,11 @@
'unicodelctest-no-optimization': [PASS, TIMEOUT],
# Issue 3219:
'getters-on-elements': [PASS, ['gc_stress == True', FAIL]],
+
+ # Ignition.
+ 'es6/templates': [PASS, ['no_snap and mode == debug', NO_IGNITION]],
+ 'harmony/generators': [PASS, ['no_snap and mode == debug', NO_IGNITION]],
+ 'regress/regress-crbug-364374': [PASS, ['no_snap and mode == debug', NO_IGNITION]],
}], # 'arch == arm64 and mode == debug and simulator_run == True'
##############################################################################
@@ -497,6 +556,17 @@
'deep-recursion': [SKIP],
'regress/regress-builtinbust-7': [SKIP],
'string-localecompare': [SKIP],
+
+ # TODO(mythria,4680): All of these tests have large loops and hence slow
+ # and timeout.
+ 'compiler/osr-big': [PASS, NO_IGNITION],
+ 'compiler/osr-nested': [PASS, NO_IGNITION],
+ 'regress/regress-298269': [PASS, NO_IGNITION],
+ 'regress/regress-crbug-319860': [PASS, NO_IGNITION],
+ 'regress/regress-deep-proto': [PASS, NO_IGNITION],
+ 'try': [PASS, NO_IGNITION],
+ # Too slow for interpreter and msan.
+ 'es6/tail-call-megatest*': [PASS, NO_IGNITION],
}], # 'msan == True'
##############################################################################
@@ -542,6 +612,11 @@
'regress/regress-91008': [PASS, SLOW],
'regress/regress-json-stringify-gc': [PASS, SLOW],
'string-indexof-2': [PASS, TIMEOUT],
+
+ # TODO(rmcilroy,4680): Arm specific timeouts.
+ 'compiler/osr-one': [PASS, NO_IGNITION],
+ 'compiler/osr-two': [PASS, NO_IGNITION],
+ 'regress/regress-1257': [PASS, NO_IGNITION],
}], # 'arch == arm or arch == android_arm'
##############################################################################
@@ -759,35 +834,14 @@
}], # 'arch == ppc and simulator_run == True'
##############################################################################
-['ignition == True', {
- # TODO(yangguo,4690): assertion failures in debugger tests.
- 'debug-allscopes-on-debugger': [FAIL],
- 'es6/debug-stepnext-for': [FAIL],
- 'es6/debug-promises/stepin-constructor': [FAIL],
- 'es6/debug-stepin-proxies': [FAIL],
- 'regress/regress-crbug-119800': [FAIL],
- 'regress/regress-opt-after-debug-deopt': [FAIL],
+['arch == ppc64', {
- # TODO(yangguo,4690): flaky failures on the bots.
- 'debug-stepin-builtin-callback-opt': [SKIP],
+ # stack overflow
+ 'big-array-literal': [SKIP],
+}], # 'arch == ppc64'
- # TODO(rmcilroy,4765): assertion failures in LiveEdit tests.
- 'debug-liveedit-restart-frame': [FAIL],
- 'debug-liveedit-literals': [FAIL],
- 'debug-liveedit-3': [FAIL],
- 'debug-liveedit-1': [FAIL],
- 'debug-liveedit-2': [FAIL],
- 'debug-liveedit-patch-positions-replace': [FAIL],
- 'debug-liveedit-patch-positions': [FAIL],
- 'debug-liveedit-stepin': [FAIL],
- 'debug-liveedit-newsource': [FAIL],
- 'debug-liveedit-stack-padding': [FAIL],
- 'debug-liveedit-breakpoints': [FAIL],
- 'es6/debug-liveedit-new-target-1': [FAIL],
- 'es6/debug-liveedit-new-target-2': [FAIL],
- 'es6/debug-liveedit-new-target-3': [FAIL],
- 'es6/generators-debug-liveedit': [FAIL],
-
+##############################################################################
+['ignition or ignition_turbofan', {
# TODO(mythria, 4780): Related to type feedback for calls in interpreter.
'array-literal-feedback': [FAIL],
'regress/regress-4121': [FAIL],
@@ -798,56 +852,37 @@
# till it is optimized. So test timeouts.
'array-literal-transitions': [SKIP],
- # TODO(mythria, 4680): Relate to GC and ignition holding references to
- # objects.
- 'es6/mirror-collections': [FAIL],
-
- # TODO(mythria, 4680): Fails with context_register_count_ > 0 (0 vs. 0) when
- # trying to get a context register in BytecodeGenerator.
- 'harmony/regress/regress-4658': [FAIL, ['mode == release and dcheck_always_on == False', PASS],],
-
# TODO(rmcilroy, 4680): Script throws RangeError as expected, but does so during
# eager compile of the whole script instead of during lazy compile of the function
# f(), so we can't catch the exception in the try/catch. Skip because on some
# platforms the stack limit is different and the exception doesn't fire.
'regress/regress-crbug-589472': [SKIP],
- # Debugger test cases that pass with ignition, but not full-codegen.
- # These differences between full-codegen and ignition are deliberate.
- 'ignition/elided-instruction-no-ignition': [FAIL],
-
'wasm/asm-wasm-f32': [PASS, ['arch in [arm64]', SKIP]],
'wasm/asm-wasm-f64': [PASS, ['arch in [arm64]', SKIP]],
-}], # ignition == True
-['ignition == True and system == windows', {
- # TODO(rmcilroy,4680): Crash on windows nosnap shared.
- 'regress/regress-crbug-352058': [PASS, ['no_snap == True', SKIP]],
+ # TODO(rmcilroy,titzer): Times out after
+ # https://codereview.chromium.org/1951013002 .
+ 'regress/regress-599717': [PASS, ['tsan', SKIP]],
+}], # ignition or ignition_turbofan
- # TODO(513471): Attempting to optimize generator hits unreachable path.
- 'regress/regress-crbug-513471': [PASS, ['no_snap == True', SKIP]],
-
- # TODO(rmcilroy,4680): Fails on win32 debug.
- 'div-mod': [PASS, ['arch == ia32', SKIP]],
-}], # ignition == True and system == windows
-
-['ignition == True and arch == arm64', {
+['(ignition or ignition_turbofan) and arch == arm64', {
# TODO(rmcilroy,4680): Arm64 specific timeouts.
'asm/construct-double': [SKIP],
'compiler/osr-one': [SKIP],
'compiler/osr-two': [SKIP],
'wasm/asm-wasm-i32': [SKIP],
'wasm/asm-wasm-u32': [SKIP],
-}], # ignition == True and arch == arm64
+}], # (ignition or ignition_turbofan) and arch == arm64
-['ignition == True and arch == arm', {
+['(ignition or ignition_turbofan) and arch == arm', {
# TODO(rmcilroy,4680): Arm specific timeouts.
'compiler/osr-one': [SKIP],
'compiler/osr-two': [SKIP],
'regress/regress-1257': [SKIP],
-}], # ignition == True and arch == arm
+}], # (ignition or ignition_turbofan) and arch == arm
-['ignition == True and msan', {
+['(ignition or ignition_turbofan) and msan', {
# TODO(mythria,4680): All of these tests have large loops and hence slow
# and timeout.
'compiler/osr-big': [SKIP],
@@ -858,55 +893,7 @@
'try': [SKIP],
# Too slow for interpreter and msan.
'es6/tail-call-megatest*': [SKIP],
-}], # ignition == True and msan
-
-['ignition == True and gc_stress == True', {
- # TODO(oth,4680): failures from the bots.
- 'es6/debug-step-destructuring-bind': [SKIP],
- 'es6/debug-stepin-collections-foreach': [SKIP],
- 'ignition/elided-instruction': [SKIP],
- 'regress/regress-269': [SKIP],
-}], # ignition == True and gc_stress == True
-
-['ignition == False', {
- # Debugger test cases that pass with full-codegen, but not ignition.
- # These differences between full-codegen and ignition are deliberate.
- 'ignition/elided-instruction': [FAIL],
-}], # ignition == False
-
-['ignition == True and system == windows and no_snap', {
- # TODO(rmcilroy): Fail with nosnap and shared libraries.
- 'es6/array-from': [FAIL],
- 'es6/classes-subclass-builtins': [FAIL],
- 'es6/computed-property-names-classes': [FAIL],
- 'es6/computed-property-names-object-literals-methods': [FAIL],
- 'es6/debug-stepin-generators': [FAIL],
- 'es6/destructuring': [FAIL],
- 'es6/destructuring-assignment': [FAIL],
- 'es6/generators-iteration': [FAIL],
- 'es6/generators-mirror': [FAIL],
- 'es6/generators-parsing': [FAIL],
- 'es6/generators-poisoned-properties': [FAIL],
- 'es6/generators-relocation': [FAIL],
- 'es6/generators-states': [FAIL],
- 'es6/iteration-semantics': [FAIL],
- 'es6/object-literals-method': [FAIL],
- 'es6/object-literals-super': [FAIL],
- 'es6/promises': [FAIL],
- 'es6/regress/regress-2681': [FAIL],
- 'es6/regress/regress-2691': [FAIL],
- 'es6/regress/regress-3280': [FAIL],
- 'es6/spread-array': [FAIL],
- 'es6/spread-call': [FAIL],
- 'es6/typedarray': [FAIL],
- 'es6/typedarray-from': [FAIL],
- 'harmony/function-sent': [FAIL],
- 'harmony/generators': [FAIL],
- 'harmony/iterator-close': [FAIL],
- 'harmony/regress/regress-4482': [FAIL],
- 'messages': [FAIL],
- 'regress-3225': [FAIL],
-}], # ignition == True and system == windows and no_snap
+}], # (ignition or ignition_turbofan) and msan
##############################################################################
['gcov_coverage', {
diff --git a/test/mjsunit/object-define-property.js b/test/mjsunit/object-define-property.js
index 4c495c6..380a71a 100644
--- a/test/mjsunit/object-define-property.js
+++ b/test/mjsunit/object-define-property.js
@@ -467,8 +467,7 @@
}
-// Test runtime calls to DefineDataPropertyUnchecked and
-// DefineAccessorPropertyUnchecked - make sure we don't
+// Test runtime calls to DefineAccessorPropertyUnchecked - make sure we don't
// crash.
try {
%DefineAccessorPropertyUnchecked(0, 0, 0, 0, 0);
@@ -477,29 +476,11 @@
}
try {
- %DefineDataPropertyUnchecked(0, 0, 0, 0);
-} catch (e) {
- assertTrue(/illegal access/.test(e));
-}
-
-try {
- %DefineDataPropertyUnchecked(null, null, null, null);
-} catch (e) {
- assertTrue(/illegal access/.test(e));
-}
-
-try {
%DefineAccessorPropertyUnchecked(null, null, null, null, null);
} catch (e) {
assertTrue(/illegal access/.test(e));
}
-try {
- %DefineDataPropertyUnchecked({}, null, null, null);
-} catch (e) {
- assertTrue(/illegal access/.test(e));
-}
-
// Defining properties null should fail even when we have
// other allowed values
try {
@@ -508,12 +489,6 @@
assertTrue(/illegal access/.test(e));
}
-try {
- %DefineDataPropertyUnchecked(null, 'foo', 0, 0);
-} catch (e) {
- assertTrue(/illegal access/.test(e));
-}
-
// Test that all possible differences in step 6 in DefineOwnProperty are
// exercised, i.e., any difference in the given property descriptor and the
// existing properties should not return true, but throw an error if the
diff --git a/test/mjsunit/osr-elements-kind.js b/test/mjsunit/osr-elements-kind.js
index bd15ef3..aee7017 100644
--- a/test/mjsunit/osr-elements-kind.js
+++ b/test/mjsunit/osr-elements-kind.js
@@ -30,7 +30,7 @@
// Limit the number of stress runs to reduce polymorphism it defeats some of the
// assumptions made about how elements transitions work because transition stubs
// end up going generic.
-// Flags: --stress-runs=2
+// Flags: --stress-runs=1
var elements_kind = {
fast_smi_only : 'fast smi only elements',
diff --git a/test/mjsunit/regexp-compile.js b/test/mjsunit/regexp-compile.js
index 92c3f7b..f001780 100644
--- a/test/mjsunit/regexp-compile.js
+++ b/test/mjsunit/regexp-compile.js
@@ -42,3 +42,7 @@
assertEquals(["y", "y"], re.exec("axyb"));
assertEquals(2, re.compile.length);
+
+// If RegExp parsing fails, the RegExp is not modified
+var r = /./; try { r.compile('? invalid'); } catch(err){}
+assertEquals("/./", r.toString());
diff --git a/test/mjsunit/regexp-lastIndex.js b/test/mjsunit/regexp-lastIndex.js
deleted file mode 100644
index 1445b9b..0000000
--- a/test/mjsunit/regexp-lastIndex.js
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// lastIndex is set according to funny rules. It is typically set only
-// for global or sticky RegExps, but on a failure to find a match, it is
-// set unconditionally. If a set fails, then it acts as if in strict mode
-// and throws.
-
-var re = /x/;
-Object.defineProperty(re, 'lastIndex', {writable: false});
-assertThrows(() => re.exec(""), TypeError);
-assertEquals(["x"], re.exec("x"));
-
-var re = /x/y;
-Object.defineProperty(re, 'lastIndex', {writable: false});
-assertThrows(() => re.exec(""), TypeError);
-assertThrows(() => re.exec("x"), TypeError);
diff --git a/test/mjsunit/regress-604044.js b/test/mjsunit/regress-604044.js
new file mode 100644
index 0000000..58ccfbe
--- /dev/null
+++ b/test/mjsunit/regress-604044.js
@@ -0,0 +1,7 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --min-preparse-length 1
+
+(function(_ = function() {}){})
diff --git a/test/mjsunit/regress/regress-3315.js b/test/mjsunit/regress/regress-3315.js
deleted file mode 100644
index bfd7df2..0000000
--- a/test/mjsunit/regress/regress-3315.js
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Flags: --harmony-object-observe
-
-var indexZeroCallCount = 0;
-var indexOneCallCount = 0;
-var lengthCallCount = 0;
-var acceptList = {
- get 0() {
- indexZeroCallCount++;
- return 'foo';
- },
- get 1() {
- indexOneCallCount++;
- return 'bar';
- },
- get length() {
- lengthCallCount++;
- return 1;
- }
-};
-
-Object.observe({}, function(){}, acceptList);
-assertEquals(1, lengthCallCount);
-assertEquals(1, indexZeroCallCount);
-assertEquals(0, indexOneCallCount);
diff --git a/test/mjsunit/regress/regress-353004.js b/test/mjsunit/regress/regress-353004.js
index 658fd6d..7e1fb7e 100644
--- a/test/mjsunit/regress/regress-353004.js
+++ b/test/mjsunit/regress/regress-353004.js
@@ -41,19 +41,21 @@
var buffer5 = new ArrayBuffer(100 * 1024);
-var buffer6 = buffer5.slice({valueOf : function() {
- %ArrayBufferNeuter(buffer5);
- return 0;
-}}, 100 * 1024 * 1024);
-assertEquals(0, buffer6.byteLength);
+assertThrows(function() {
+ buffer5.slice({valueOf : function() {
+ %ArrayBufferNeuter(buffer5);
+ return 0;
+ }}, 100 * 1024 * 1024);
+}, TypeError);
var buffer7 = new ArrayBuffer(100 * 1024 * 1024);
-var buffer8 = buffer7.slice(0, {valueOf : function() {
- %ArrayBufferNeuter(buffer7);
- return 100 * 1024 * 1024;
-}});
-assertEquals(0, buffer8.byteLength);
+assertThrows(function() {
+ buffer7.slice(0, {valueOf : function() {
+ %ArrayBufferNeuter(buffer7);
+ return 100 * 1024 * 1024;
+ }});
+}, TypeError);
var buffer9 = new ArrayBuffer(1024);
var array9 = new Uint8Array(buffer9);
diff --git a/test/mjsunit/regress/regress-356589.js b/test/mjsunit/regress/regress-356589.js
deleted file mode 100644
index a47f51b..0000000
--- a/test/mjsunit/regress/regress-356589.js
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Flags: --harmony-object-observe
-
-// This test passes if it does not crash in debug mode
-
-arr = ['a', 'b', 'c', 'd'];
-Object.defineProperty(arr.__proto__, '0', { get: function(){} });
-Object.defineProperty(arr, '2', {get: function(){} });
-Object.observe(arr, function() {});
-arr.length = 2;
diff --git a/test/mjsunit/regress/regress-3926.js b/test/mjsunit/regress/regress-3926.js
index 4720c1b..4d9b298 100644
--- a/test/mjsunit/regress/regress-3926.js
+++ b/test/mjsunit/regress/regress-3926.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy --harmony-sloppy-let
-
// See: http://code.google.com/p/v8/issues/detail?id=3926
// Switch statements should disable hole check elimination
diff --git a/test/mjsunit/regress/regress-417709a.js b/test/mjsunit/regress/regress-417709a.js
deleted file mode 100644
index 5500be2..0000000
--- a/test/mjsunit/regress/regress-417709a.js
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-object-observe
-// Flags: --stack-size=100
-
-var a = [];
-
-Object.observe(a, function() {});
-
-function f(a, x) {
- a.length = x;
- f(a, x + 1);
-}
-
-assertThrows(function() { f(a, 1); }, RangeError);
diff --git a/test/mjsunit/regress/regress-417709b.js b/test/mjsunit/regress/regress-417709b.js
deleted file mode 100644
index 4d9572e..0000000
--- a/test/mjsunit/regress/regress-417709b.js
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-object-observe --stack-size=100
-
-var a = [];
-
-Array.observe(a, function() {});
-
-function f(a, x) {
- a.length = x;
- f(a, x + 1);
-}
-
-assertThrows(function() { f(a, 1); }, RangeError);
diff --git a/test/mjsunit/regress/regress-4693.js b/test/mjsunit/regress/regress-4693.js
index 13b4e2b..2c31cd9 100644
--- a/test/mjsunit/regress/regress-4693.js
+++ b/test/mjsunit/regress/regress-4693.js
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// Flags: --harmony-sloppy-function
// In sloppy mode we allow function redeclarations within blocks for webcompat.
(function() {
diff --git a/test/mjsunit/regress/regress-4908.js b/test/mjsunit/regress/regress-4908.js
new file mode 100644
index 0000000..ec618b3
--- /dev/null
+++ b/test/mjsunit/regress/regress-4908.js
@@ -0,0 +1,7 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Flags: --always-opt --no-lazy
+
+(function() { ((s = 17, y = s) => s)() })();
diff --git a/test/mjsunit/regress/regress-4945.js b/test/mjsunit/regress/regress-4945.js
new file mode 100644
index 0000000..8e595e6
--- /dev/null
+++ b/test/mjsunit/regress/regress-4945.js
@@ -0,0 +1,10 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function* g(o) {
+ yield 'x' in o;
+}
+
+assertTrue(g({x: 1}).next().value);
+assertFalse(g({}).next().value);
diff --git a/test/mjsunit/regress/regress-4964.js b/test/mjsunit/regress/regress-4964.js
new file mode 100644
index 0000000..d834708
--- /dev/null
+++ b/test/mjsunit/regress/regress-4964.js
@@ -0,0 +1,22 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+// Neutered source
+var ab = new ArrayBuffer(10);
+ab.constructor = { get [Symbol.species]() { %ArrayBufferNeuter(ab); return ArrayBuffer; } };
+assertThrows(() => ab.slice(0), TypeError);
+
+// Neutered target
+class NeuteredArrayBuffer extends ArrayBuffer {
+ constructor(...args) {
+ super(...args);
+ %ArrayBufferNeuter(this);
+ }
+}
+
+var ab2 = new ArrayBuffer(10);
+ab2.constructor = NeuteredArrayBuffer;
+assertThrows(() => ab2.slice(0), TypeError);
diff --git a/test/mjsunit/regress/regress-4967.js b/test/mjsunit/regress/regress-4967.js
new file mode 100644
index 0000000..9b36405
--- /dev/null
+++ b/test/mjsunit/regress/regress-4967.js
@@ -0,0 +1,9 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+assertThrows(() => {
+ new class extends Object {
+ constructor() { (() => delete super[super()])(); }
+ }
+}, ReferenceError);
diff --git a/test/mjsunit/regress/regress-4971.js b/test/mjsunit/regress/regress-4971.js
new file mode 100644
index 0000000..041f6c2
--- /dev/null
+++ b/test/mjsunit/regress/regress-4971.js
@@ -0,0 +1,41 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+(function TestDeoptInNamedSuperGetter() {
+ class C { m() { return 23 } }
+ class D extends C { f() { return super.boom() } }
+
+ var should_deoptimize_caller = false;
+ Object.defineProperty(C.prototype, "boom", { get: function() {
+ if (should_deoptimize_caller) %DeoptimizeFunction(D.prototype.f);
+ return this.m
+ }})
+
+ assertEquals(23, new D().f());
+ assertEquals(23, new D().f());
+ %OptimizeFunctionOnNextCall(D.prototype.f);
+ assertEquals(23, new D().f());
+ should_deoptimize_caller = true;
+ assertEquals(23, new D().f());
+})();
+
+(function TestDeoptInKeyedSuperGetter() {
+ class C { m() { return 23 } }
+ class D extends C { f(name) { return super[name]() } }
+
+ var should_deoptimize_caller = false;
+ Object.defineProperty(C.prototype, "boom", { get: function() {
+ if (should_deoptimize_caller) %DeoptimizeFunction(D.prototype.f);
+ return this.m
+ }})
+
+ assertEquals(23, new D().f("boom"));
+ assertEquals(23, new D().f("boom"));
+ %OptimizeFunctionOnNextCall(D.prototype.f);
+ assertEquals(23, new D().f("boom"));
+ should_deoptimize_caller = true;
+ assertEquals(23, new D().f("boom"));
+})();
diff --git a/test/mjsunit/regress/regress-5033.js b/test/mjsunit/regress/regress-5033.js
new file mode 100644
index 0000000..728094f
--- /dev/null
+++ b/test/mjsunit/regress/regress-5033.js
@@ -0,0 +1,21 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+var test = function() {
+ var t = Date.now(); // Just any non-constant double value.
+ var o = {
+ ['p']: 1,
+ t
+ };
+};
+
+function caller() {
+ test();
+}
+caller();
+caller();
+%OptimizeFunctionOnNextCall(caller);
+caller();
diff --git a/test/mjsunit/regress/regress-5178.js b/test/mjsunit/regress/regress-5178.js
new file mode 100644
index 0000000..bc0dd11
--- /dev/null
+++ b/test/mjsunit/regress/regress-5178.js
@@ -0,0 +1,7 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+assertThrows(() => {
+ try { throw {} } catch({a=b, b}) { a+b }
+}, ReferenceError);
diff --git a/test/mjsunit/regress/regress-5199.js b/test/mjsunit/regress/regress-5199.js
new file mode 100644
index 0000000..818e71a
--- /dev/null
+++ b/test/mjsunit/regress/regress-5199.js
@@ -0,0 +1,5 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+assertTrue(/(a[\u1000A])+/i.test('aa'));
diff --git a/test/mjsunit/regress/regress-520029.js b/test/mjsunit/regress/regress-520029.js
index 299dd75..9a1d200 100644
--- a/test/mjsunit/regress/regress-520029.js
+++ b/test/mjsunit/regress/regress-520029.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy-let --harmony-sloppy
-
// Test that hoisting a function out of a lexical scope does not
// lead to a parsing error
diff --git a/test/mjsunit/regress/regress-536751.js b/test/mjsunit/regress/regress-536751.js
index 0707e00..a63fae3 100644
--- a/test/mjsunit/regress/regress-536751.js
+++ b/test/mjsunit/regress/regress-536751.js
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy --harmony-sloppy-function --harmony-sloppy-let
// Flags: --no-harmony-restrictive-declarations
// At some point, this code led to DCHECK errors in debug mode
diff --git a/test/mjsunit/regress/regress-542099.js b/test/mjsunit/regress/regress-542099.js
index eef4953..6345fd4 100644
--- a/test/mjsunit/regress/regress-542099.js
+++ b/test/mjsunit/regress/regress-542099.js
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy --harmony-sloppy-function
// Flags: --no-harmony-restrictive-declarations
// Previously, this caused a CHECK fail in debug mode
diff --git a/test/mjsunit/regress/regress-542100.js b/test/mjsunit/regress/regress-542100.js
index 70fb5dc..c16e628 100644
--- a/test/mjsunit/regress/regress-542100.js
+++ b/test/mjsunit/regress/regress-542100.js
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy --harmony-sloppy-function
// Flags: --no-harmony-restrictive-declarations
(function() {
diff --git a/test/mjsunit/regress/regress-585041.js b/test/mjsunit/regress/regress-585041.js
new file mode 100644
index 0000000..c072ed2
--- /dev/null
+++ b/test/mjsunit/regress/regress-585041.js
@@ -0,0 +1,21 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function f(arr, i) {
+ arr[i] = 50;
+}
+
+function boom(dummy) {
+ var arr = new Array(10);
+ f(arr, 10);
+ if (dummy) {
+ f(arr, -2147483648);
+ }
+}
+
+boom(false);
+%OptimizeFunctionOnNextCall(boom);
+boom(false);
diff --git a/test/mjsunit/regress/regress-592352.js b/test/mjsunit/regress/regress-592352.js
new file mode 100644
index 0000000..f3477c0
--- /dev/null
+++ b/test/mjsunit/regress/regress-592352.js
@@ -0,0 +1,20 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-wasm --allow-natives-syntax
+
+function __f_76() {
+ "use asm";
+ function __f_72() {
+ %OptimizeFunctionOnNextCall();
+ }
+ return {__f_72:__f_72};
+}
+
+try {
+ Wasm.instantiateModuleFromAsm( __f_76.toString());
+ assertTrue(false);
+} catch (e) {
+ print("Caught: " + e);
+}
diff --git a/test/mjsunit/regress/regress-599068-func-bindings.js b/test/mjsunit/regress/regress-599068-func-bindings.js
new file mode 100644
index 0000000..887c000
--- /dev/null
+++ b/test/mjsunit/regress/regress-599068-func-bindings.js
@@ -0,0 +1,45 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+// Tests function bindings are correctly handled in ignition.
+(function f() {
+ function assignSloppy() {
+ f = 0;
+ }
+ assertDoesNotThrow(assignSloppy);
+
+ function assignStrict() {
+ 'use strict';
+ f = 0;
+ }
+ assertThrows(assignStrict, TypeError);
+
+ function assignStrictLookup() {
+ eval("'use strict'; f = 1;");
+ }
+ assertThrows(assignStrictLookup, TypeError);
+})();
+
+// Tests for compound assignments which are handled differently
+// in crankshaft.
+(function f() {
+ function assignSloppy() {
+ f += "x";
+ }
+ assertDoesNotThrow(assignSloppy);
+ assertDoesNotThrow(assignSloppy);
+ %OptimizeFunctionOnNextCall(assignSloppy);
+ assertDoesNotThrow(assignSloppy);
+
+ function assignStrict() {
+ 'use strict';
+ f += "x";
+ }
+ assertThrows(assignStrict, TypeError);
+ assertThrows(assignStrict, TypeError);
+ %OptimizeFunctionOnNextCall(assignStrict);
+ assertThrows(assignStrict, TypeError);
+})();
diff --git a/test/mjsunit/regress/regress-599717.js b/test/mjsunit/regress/regress-599717.js
new file mode 100644
index 0000000..2cfd7fc
--- /dev/null
+++ b/test/mjsunit/regress/regress-599717.js
@@ -0,0 +1,25 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-wasm
+
+function __f_61(stdlib, buffer) {
+ "use asm";
+ var __v_14 = new stdlib.Float64Array(buffer);
+ function __f_74() {
+ var __v_35 = 6.0;
+ __v_14[2] = __v_35 + 1.0;
+ }
+ return {__f_74: __f_74};
+}
+var ok = false;
+try {
+ var __v_12 = new ArrayBuffer(2147483648);
+ ok = true;
+} catch (e) {
+ // Can happen on 32 bit systems.
+}
+if (ok) {
+ var module = Wasm.instantiateModuleFromAsm( __f_61.toString(), null, __v_12);
+}
diff --git a/test/mjsunit/regress/regress-599719.js b/test/mjsunit/regress/regress-599719.js
new file mode 100644
index 0000000..579fa1f
--- /dev/null
+++ b/test/mjsunit/regress/regress-599719.js
@@ -0,0 +1,24 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --expose-wasm
+
+function __f_7() {
+ %DeoptimizeFunction(__f_5);
+}
+function __f_8(global, env) {
+ "use asm";
+ var __f_7 = env.__f_7;
+ function __f_9(i4, i5) {
+ i4 = i4 | 0;
+ i5 = i5 | 0;
+ __f_7();
+ }
+ return {'__f_9': __f_9}
+}
+function __f_5() {
+ var __v_5 = Wasm.instantiateModuleFromAsm( __f_8.toString(), {'__f_7': __f_7});
+ __v_5.__f_9(0, 0, 0);
+}
+__f_5();
diff --git a/test/mjsunit/regress/regress-605470.js b/test/mjsunit/regress/regress-605470.js
new file mode 100644
index 0000000..722e8ae
--- /dev/null
+++ b/test/mjsunit/regress/regress-605470.js
@@ -0,0 +1,17 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --ignition
+
+function function_with_m_args(m) {
+ var source = '(function f() { return; })(';
+ for (var arg = 0; arg < m ; arg++) {
+ if (arg != 0) source += ',';
+ source += arg;
+ }
+ source += ')';
+ return eval(source);
+}
+
+function_with_m_args(0x7FFF);
diff --git a/test/mjsunit/regress/regress-605488.js b/test/mjsunit/regress/regress-605488.js
new file mode 100644
index 0000000..03e6a38
--- /dev/null
+++ b/test/mjsunit/regress/regress-605488.js
@@ -0,0 +1,12 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-wasm
+
+try {
+ Wasm.instantiateModuleFromAsm("");
+ assertTrue(false);
+} catch (e) {
+ print("Caught: " + e);
+}
diff --git a/test/mjsunit/regress/regress-606021.js b/test/mjsunit/regress/regress-606021.js
new file mode 100644
index 0000000..54b283e
--- /dev/null
+++ b/test/mjsunit/regress/regress-606021.js
@@ -0,0 +1,32 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function foo() {
+ return function(c) {
+ var double_var = [3.0, 3.5][0];
+ var literal = c ? [1, double_var] : [double_var, 3.5];
+ return literal[0];
+ };
+}
+
+var f1 = foo();
+var f2 = foo();
+
+// Both closures point to full code.
+f1(false);
+f2(false);
+
+// Optimize f1, but don't initialize the [1, double_var] literal.
+%OptimizeFunctionOnNextCall(f1);
+f1(false);
+
+// Initialize the [1, double_var] literal, and transition the boilerplate to
+// double.
+f2(true);
+
+// Trick crankshaft into writing double_var at the wrong position.
+var l = f1(true);
+assertEquals(1, l);
diff --git a/test/mjsunit/regress/regress-608630.js b/test/mjsunit/regress/regress-608630.js
new file mode 100644
index 0000000..a0f3c43
--- /dev/null
+++ b/test/mjsunit/regress/regress-608630.js
@@ -0,0 +1,69 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-wasm
+
+var __v_5 = {};
+var __v_35 = {};
+var __v_44 = {};
+var __v_43 = {};
+
+try {
+__v_1 = 1;
+__v_2 = {
+ get: function() { return function() {} },
+ has() { return true },
+ getOwnPropertyDescriptor: function() {
+ if (__v_1-- == 0) throw "please die";
+ return {value: function() {}, configurable: true};
+ }
+};
+__v_3 = new Proxy({}, __v_2);
+__v_30 = Object.create(__v_35);
+with (__v_5) { f() }
+} catch(e) { print("Caught: " + e); }
+
+function __f_1(asmfunc, expect) {
+ var __v_1 = asmfunc.toString();
+ var __v_2 = __v_1.replace(new RegExp("use asm"), "");
+ var __v_39 = {Math: Math};
+ var __v_4 = eval("(" + __v_2 + ")")(__v_3);
+ print("Testing " + asmfunc.name + " (js)...");
+ __v_44.valueOf = __v_43;
+ expect(__v_4);
+ print("Testing " + asmfunc.name + " (asm.js)...");
+ var __v_5 = asmfunc(__v_3);
+ expect(__v_5);
+ print("Testing " + asmfunc.name + " (wasm)...");
+ var __v_6 = Wasm.instantiateModuleFromAsm(__v_1, __v_3);
+ expect(__v_6);
+}
+function __f_2() {
+ "use asm";
+ function __f_3() { return 0; }
+ function __f_4() { return 1; }
+ function __f_5() { return 4; }
+ function __f_6() { return 64; }
+ function __f_7() { return 137; }
+ function __f_8() { return 128; }
+ function __f_9() { return -1; }
+ function __f_10() { return 1000; }
+ function __f_11() { return 2000000; }
+ function __f_12() { return 2147483647; }
+ return {__f_3: __f_3, __f_4: __f_4, __f_5: __f_5, __f_6: __f_6, __f_7: __f_7, __f_8: __f_8,
+ __f_9: __f_9, __f_10: __f_10, __f_11, __f_12: __f_12};
+}
+try {
+__f_1(__f_2, function(module) {
+ assertEquals(0, module.__f_3());
+ assertEquals(1, module.__f_4());
+ assertEquals(4, module.__f_5());
+ assertEquals(64, module.__f_6());
+ assertEquals(128, module.__f_8());
+ assertEquals(-1, module.__f_9());
+ assertEquals(1000, module.__f_10());
+ assertEquals(2000000, module.__f_11());
+ assertEquals(2147483647, module.__f_12());
+});
+} catch(e) { print("Caught: " + e); }
diff --git a/test/mjsunit/regress/regress-610633.js b/test/mjsunit/regress/regress-610633.js
new file mode 100644
index 0000000..8ee0e7e
--- /dev/null
+++ b/test/mjsunit/regress/regress-610633.js
@@ -0,0 +1,40 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function getLength(a) {
+ return a.length;
+}
+
+function getByteLength(a) {
+ return a.byteLength;
+}
+
+function getByteOffset(a) {
+ return a.byteOffset;
+}
+
+var a = new Uint8Array([1, 2, 3]);
+getLength(a);
+getLength(a);
+
+Object.defineProperty(a.__proto__, 'length', {value: 42});
+
+assertEquals(42, getLength(a));
+assertEquals(42, a.length);
+
+getByteLength(a);
+getByteLength(a);
+
+Object.defineProperty(a.__proto__, 'byteLength', {value: 42});
+
+assertEquals(42, getByteLength(a));
+assertEquals(42, a.byteLength);
+
+getByteOffset(a);
+getByteOffset(a);
+
+Object.defineProperty(a.__proto__, 'byteOffset', {value: 42});
+
+assertEquals(42, getByteOffset(a));
+assertEquals(42, a.byteOffset);
diff --git a/test/mjsunit/regress/regress-616386.js b/test/mjsunit/regress/regress-616386.js
new file mode 100644
index 0000000..d462ab7
--- /dev/null
+++ b/test/mjsunit/regress/regress-616386.js
@@ -0,0 +1,10 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --no-lazy
+
+assertEquals(0, ((y = (function(a2) { bbbb = a2 }), bbbb = eval('1')) => {y(0); return bbbb})())
+assertEquals(0, (({y = (function(a2) { bbbb = a2 }), bbbb = eval('1')} = {}) => {y(0); return bbbb})())
+assertEquals(0, (function (y = (function(a2) { bbbb = a2 }), bbbb = eval('1')) {y(0); return bbbb})())
+assertEquals(0, (function ({y = (function(a2) { bbbb = a2 }), bbbb = eval('1')} = {}) {y(0); return bbbb})())
diff --git a/test/mjsunit/regress/regress-619382.js b/test/mjsunit/regress/regress-619382.js
new file mode 100644
index 0000000..971318a
--- /dev/null
+++ b/test/mjsunit/regress/regress-619382.js
@@ -0,0 +1,35 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// // Use of this source code is governed by a BSD-style license that can be
+// // found in the LICENSE file.
+//
+// // Flags: --expose-gc --always-opt
+
+(function __f_9() {
+})();
+function __f_16(ctor_desc) {
+ var __v_22 = 5;
+ var __v_25 = [];
+ gc(); gc(); gc();
+ for (var __v_18 = 0; __v_18 < __v_22; __v_18++) {
+ __v_25[__v_18] = ctor_desc.ctor.apply();
+ }
+}
+var __v_28 = [
+ {
+ ctor: function(__v_27) { return {a: __v_27}; },
+ args: function() { return [1.5 + __v_18]; } },
+ {
+ ctor: function(__v_27) { var __v_21 = []; __v_21[1] = __v_27; __v_21[200000] = __v_27; return __v_21; },
+ args: function() { return [1.5 + __v_18]; } },
+ {
+ ctor: function() {
+ } }
+];
+var __v_26 = [
+ {
+ }];
+ __v_26.forEach(function(__v_16) {
+ __v_28.forEach(function(ctor) {
+ __f_16(ctor);
+ });
+ });
diff --git a/test/mjsunit/regress/regress-620553.js b/test/mjsunit/regress/regress-620553.js
new file mode 100644
index 0000000..461b9bb
--- /dev/null
+++ b/test/mjsunit/regress/regress-620553.js
@@ -0,0 +1,17 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-gc
+
+var o0 = [];
+var o1 = [];
+var cnt = 0;
+o1.__defineGetter__(0, function() {
+ if (cnt++ > 2) return;
+ o0.shift();
+ gc();
+ o0.push(0);
+ o0.concat(o1);
+});
+o1[0];
diff --git a/test/mjsunit/regress/regress-621869.js b/test/mjsunit/regress/regress-621869.js
new file mode 100644
index 0000000..db34064
--- /dev/null
+++ b/test/mjsunit/regress/regress-621869.js
@@ -0,0 +1,18 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-gc
+
+var o0 = [];
+var o1 = [];
+var cnt = 0;
+var only_scavenge = true;
+o1.__defineGetter__(0, function() {
+ if (cnt++ > 2) return;
+ o0.shift();
+ gc(only_scavenge);
+ o0.push((64));
+ o0.concat(o1);
+});
+o1[0];
diff --git a/test/mjsunit/regress/regress-674753.js b/test/mjsunit/regress/regress-674753.js
index b3704ea..d8a504a 100644
--- a/test/mjsunit/regress/regress-674753.js
+++ b/test/mjsunit/regress/regress-674753.js
@@ -25,62 +25,138 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// Flags: --allow-natives-syntax
+
+var undetectable = %GetUndetectable();
+
// Number
assertTrue(typeof 0 == 'number');
assertTrue(typeof 0 === 'number');
+assertFalse(typeof 0 != 'number');
+assertFalse(typeof 0 !== 'number');
assertTrue(typeof 1.2 == 'number');
assertTrue(typeof 1.2 === 'number');
+assertFalse(typeof 1.2 != 'number');
+assertFalse(typeof 1.2 !== 'number');
+assertTrue(typeof 'x' != 'number');
+assertTrue(typeof 'x' !== 'number');
assertFalse(typeof 'x' == 'number');
assertFalse(typeof 'x' === 'number');
+assertTrue(typeof Object() != 'number');
+assertTrue(typeof Object() !== 'number');
+assertFalse(typeof Object() == 'number');
+assertFalse(typeof Object() === 'number');
// String
assertTrue(typeof 'x' == 'string');
assertTrue(typeof 'x' === 'string');
+assertFalse(typeof 'x' != 'string');
+assertFalse(typeof 'x' !== 'string');
assertTrue(typeof ('x' + 'x') == 'string');
assertTrue(typeof ('x' + 'x') === 'string');
+assertFalse(typeof ('x' + 'x') != 'string');
+assertFalse(typeof ('x' + 'x') !== 'string');
+assertTrue(typeof 1 != 'string');
+assertTrue(typeof 1 !== 'string');
assertFalse(typeof 1 == 'string');
assertFalse(typeof 1 === 'string');
+assertTrue(typeof Object() != 'string');
+assertTrue(typeof Object() !== 'string');
assertFalse(typeof Object() == 'string');
assertFalse(typeof Object() === 'string');
// Boolean
assertTrue(typeof true == 'boolean');
assertTrue(typeof true === 'boolean');
+assertFalse(typeof true != 'boolean');
+assertFalse(typeof true !== 'boolean');
assertTrue(typeof false == 'boolean');
assertTrue(typeof false === 'boolean');
+assertFalse(typeof false != 'boolean');
+assertFalse(typeof false !== 'boolean');
+assertTrue(typeof 1 != 'boolean');
+assertTrue(typeof 1 !== 'boolean');
assertFalse(typeof 1 == 'boolean');
assertFalse(typeof 1 === 'boolean');
+assertTrue(typeof 'x' != 'boolean');
+assertTrue(typeof 'x' !== 'boolean');
+assertFalse(typeof 'x' == 'boolean');
+assertFalse(typeof 'x' === 'boolean');
+assertTrue(typeof Object() != 'boolean');
+assertTrue(typeof Object() !== 'boolean');
assertFalse(typeof Object() == 'boolean');
assertFalse(typeof Object() === 'boolean');
// Undefined
assertTrue(typeof void 0 == 'undefined');
assertTrue(typeof void 0 === 'undefined');
+assertFalse(typeof void 0 != 'undefined');
+assertFalse(typeof void 0 !== 'undefined');
+assertTrue(typeof 1 != 'undefined');
+assertTrue(typeof 1 !== 'undefined');
assertFalse(typeof 1 == 'undefined');
assertFalse(typeof 1 === 'undefined');
+assertTrue(typeof null != 'undefined');
+assertTrue(typeof null !== 'undefined');
+assertFalse(typeof null == 'undefined');
+assertFalse(typeof null === 'undefined');
+assertTrue(typeof Object() != 'undefined');
+assertTrue(typeof Object() !== 'undefined');
assertFalse(typeof Object() == 'undefined');
assertFalse(typeof Object() === 'undefined');
+assertTrue(typeof undetectable == 'undefined');
+assertTrue(typeof undetectable === 'undefined');
+assertFalse(typeof undetectable != 'undefined');
+assertFalse(typeof undetectable !== 'undefined');
// Function
assertTrue(typeof Object == 'function');
assertTrue(typeof Object === 'function');
+assertFalse(typeof Object != 'function');
+assertFalse(typeof Object !== 'function');
+assertTrue(typeof 1 != 'function');
+assertTrue(typeof 1 !== 'function');
assertFalse(typeof 1 == 'function');
assertFalse(typeof 1 === 'function');
+assertTrue(typeof Object() != 'function');
+assertTrue(typeof Object() !== 'function');
assertFalse(typeof Object() == 'function');
assertFalse(typeof Object() === 'function');
+assertTrue(typeof undetectable != 'function');
+assertTrue(typeof undetectable !== 'function');
+assertFalse(typeof undetectable == 'function');
+assertFalse(typeof undetectable === 'function');
// Object
assertTrue(typeof Object() == 'object');
assertTrue(typeof Object() === 'object');
+assertFalse(typeof Object() != 'object');
+assertFalse(typeof Object() !== 'object');
assertTrue(typeof new String('x') == 'object');
assertTrue(typeof new String('x') === 'object');
+assertFalse(typeof new String('x') != 'object');
+assertFalse(typeof new String('x') !== 'object');
assertTrue(typeof ['x'] == 'object');
assertTrue(typeof ['x'] === 'object');
+assertFalse(typeof ['x'] != 'object');
+assertFalse(typeof ['x'] !== 'object');
assertTrue(typeof null == 'object');
assertTrue(typeof null === 'object');
+assertFalse(typeof null != 'object');
+assertFalse(typeof null !== 'object');
+assertTrue(typeof 1 != 'object');
+assertTrue(typeof 1 !== 'object');
assertFalse(typeof 1 == 'object');
assertFalse(typeof 1 === 'object');
+assertTrue(typeof 'x' != 'object');
+assertTrue(typeof 'x' !== 'object');
assertFalse(typeof 'x' == 'object'); // bug #674753
assertFalse(typeof 'x' === 'object');
+assertTrue(typeof Object != 'object');
+assertTrue(typeof Object !== 'object');
assertFalse(typeof Object == 'object');
assertFalse(typeof Object === 'object');
+assertTrue(typeof undetectable != 'object');
+assertTrue(typeof undetectable !== 'object');
+assertFalse(typeof undetectable == 'object');
+assertFalse(typeof undetectable === 'object');
diff --git a/test/mjsunit/regress/regress-crbug-119800.js b/test/mjsunit/regress/regress-crbug-119800.js
index 3946fbb..85f28a7 100644
--- a/test/mjsunit/regress/regress-crbug-119800.js
+++ b/test/mjsunit/regress/regress-crbug-119800.js
@@ -5,9 +5,9 @@
// Flags: --expose-debug-as debug
function f() {
- 1;
- 2;
- 3;
+ print(1);
+ print(2);
+ print(3);
}
var Debug = debug.Debug;
@@ -34,4 +34,5 @@
Debug.debuggerFlags().breakPointsActive.setValue(true);
assertNull(exception);
-assertEquals(breaks, ["1;", "2;", "3;", "}", "Debug.setListener(null);"]);
+assertEquals(breaks, ["print(1);", "print(2);", "print(3);", "}",
+ "Debug.setListener(null);"]);
diff --git a/test/mjsunit/regress/regress-crbug-451770.js b/test/mjsunit/regress/regress-crbug-451770.js
index 770c807..b4f088d 100644
--- a/test/mjsunit/regress/regress-crbug-451770.js
+++ b/test/mjsunit/regress/regress-crbug-451770.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy
-
assertThrows(function f() {
var t = { toString: function() { throw new Error(); } };
var o = { [t]: 23 };
diff --git a/test/mjsunit/regress/regress-crbug-480807.js b/test/mjsunit/regress/regress-crbug-480807.js
index c273f20..a1448d6 100644
--- a/test/mjsunit/regress/regress-crbug-480807.js
+++ b/test/mjsunit/regress/regress-crbug-480807.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --allow-natives-syntax --use-osr --turbo-osr --noalways-opt
+// Flags: --allow-natives-syntax --use-osr --noalways-opt
function foo() {
var c = 0;
diff --git a/test/mjsunit/regress/regress-crbug-582048.js b/test/mjsunit/regress/regress-crbug-582048.js
new file mode 100644
index 0000000..6d98f48
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-582048.js
@@ -0,0 +1,31 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug
+
+var Debug = debug.Debug;
+
+function listener(event, exec_state, event_data, data) {
+ if (event != Debug.DebugEvent.Break) return;
+ try {
+ var frame_count = exec_state.frameCount();
+ for (var i = 0; i < frame_count; i++) {
+ var frame = exec_state.frame(i);
+ var scope_count = frame.scopeCount();
+ for (var j = 0; j < scope_count; j++) {
+ var scope = frame.scope(j);
+ assertTrue(scope.scopeObject().property('').isUndefined());
+ }
+ }
+ } catch (e) {
+ print(e, e.stack);
+ exception = e;
+ }
+}
+
+Debug.setListener(listener);
+
+(function(a = 1) { debugger; })();
+
+Debug.setListener(null);
diff --git a/test/mjsunit/regress/regress-crbug-600257.js b/test/mjsunit/regress/regress-crbug-600257.js
new file mode 100644
index 0000000..87bd2e3
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-600257.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --stack-size=100
+
+(function rec() {
+ try {
+ rec();
+ } catch (e) {
+ /{/;
+ }
+})();
diff --git a/test/mjsunit/regress/regress-crbug-602184.js b/test/mjsunit/regress/regress-crbug-602184.js
new file mode 100644
index 0000000..c7d793b
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-602184.js
@@ -0,0 +1,17 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function f(test, a) {
+ var v;
+ if (test) {
+ v = v|0;
+ }
+ a[v] = 1;
+}
+var v = new String();
+f(false, v);
+f(false, v);
+
+v = new Int32Array(10);
+f(true, v);
diff --git a/test/mjsunit/regress/regress-crbug-602595.js b/test/mjsunit/regress/regress-crbug-602595.js
new file mode 100644
index 0000000..7f6d478
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-602595.js
@@ -0,0 +1,12 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --turbo-escape
+
+function f(a) { return [a] }
+
+assertEquals([23], f(23));
+assertEquals([42], f(42));
+%OptimizeFunctionOnNextCall(f);
+assertEquals([65], f(65));
diff --git a/test/mjsunit/regress/regress-crbug-603463.js b/test/mjsunit/regress/regress-crbug-603463.js
new file mode 100644
index 0000000..20bfae6
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-603463.js
@@ -0,0 +1,16 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function load(a, i) {
+ return a[i];
+}
+
+function f() {
+ return load(new Proxy({}, {}), undefined);
+}
+
+f();
+f();
+load([11, 22, 33], 0);
+f();
diff --git a/test/mjsunit/regress/regress-crbug-604299.js b/test/mjsunit/regress/regress-crbug-604299.js
new file mode 100644
index 0000000..9908f2d
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-604299.js
@@ -0,0 +1,9 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Array.prototype.__defineSetter__(0,function(value){});
+
+if (this.Intl) {
+ var o = new Intl.DateTimeFormat('en-US', {'timeZone': 'Asia/Katmandu'})
+}
diff --git a/test/mjsunit/regress/regress-crbug-605060.js b/test/mjsunit/regress/regress-crbug-605060.js
new file mode 100644
index 0000000..d2dc79a
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-605060.js
@@ -0,0 +1,10 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+Array.prototype.__defineGetter__('map', function(){});
+Array.prototype.__defineGetter__('map', function(){});
+Array.prototype.__defineGetter__('map', function(){});
+assertTrue(%HasFastProperties(Array.prototype));
diff --git a/test/mjsunit/regress/regress-crbug-605581.js b/test/mjsunit/regress/regress-crbug-605581.js
new file mode 100644
index 0000000..0f1daab
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-605581.js
@@ -0,0 +1,28 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug
+
+var Debug = debug.Debug;
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+ if (event != Debug.DebugEvent.Break) return;
+ try {
+ assertThrows(() => exec_state.frame(0).evaluate("bar.baz"), ReferenceError);
+ } catch (e) {
+ exception = e;
+ }
+}
+
+Debug.setListener(listener);
+
+(function() {
+ debugger; // bar is still in TDZ at this point.
+ let bar = 1;
+ (x => bar); // force bar to be context-allocated.
+})();
+
+Debug.setListener(null);
+assertNull(exception);
diff --git a/test/mjsunit/regress/regress-crbug-605862.js b/test/mjsunit/regress/regress-crbug-605862.js
new file mode 100644
index 0000000..3124c06
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-605862.js
@@ -0,0 +1,8 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-unicode-regexps
+
+/[]*1/u.exec("\u1234");
+/[^\u0000-\u{10ffff}]*1/u.exec("\u1234");
diff --git a/test/mjsunit/regress/regress-crbug-608279.js b/test/mjsunit/regress/regress-crbug-608279.js
new file mode 100644
index 0000000..22c69f2
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-608279.js
@@ -0,0 +1,18 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Flags: --always-opt --no-lazy
+
+function __f_38() {
+ try {
+ throw 0;
+ } catch (e) {
+ eval();
+ var __v_38 = { a: 'hest' };
+ __v_38.m = function () { return __v_38.a; };
+ }
+ return __v_38;
+}
+var __v_40 = __f_38();
+__v_40.m();
diff --git a/test/mjsunit/regress/regress-crbug-609029.js b/test/mjsunit/regress/regress-crbug-609029.js
new file mode 100644
index 0000000..bd77de2
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-609029.js
@@ -0,0 +1,7 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --always-opt --function-context-specialization --gc-interval=14
+// Flags: --turbo-filter=match --verify-heap
+"xxx".match();
diff --git a/test/mjsunit/regress/regress-crbug-609046.js b/test/mjsunit/regress/regress-crbug-609046.js
new file mode 100644
index 0000000..10b63af
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-609046.js
@@ -0,0 +1,36 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug
+
+// Test that hidden scopes are correctly walked in the scope chain.
+
+var Debug = debug.Debug;
+var exception = null;
+var delegate = null;
+var done = false;
+
+function listener(event, exec_state, event_data, data) {
+ if (event != Debug.DebugEvent.Break) return;
+ try {
+ assertEquals([ debug.ScopeType.Block,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global ],
+ exec_state.frame(0).allScopes().map(s => s.scopeType()));
+ done = true;
+ } catch (e) {
+ exception = e;
+ }
+}
+
+Debug.setListener(listener);
+
+for(let a = 0; a < 3; a++) {
+ debugger;
+ eval(); // Force context-allocation of everything.
+}
+
+Debug.setListener(null);
+assertNull(exception);
+assertTrue(done);
diff --git a/test/mjsunit/regress/regress-crbug-610207.js b/test/mjsunit/regress/regress-crbug-610207.js
new file mode 100644
index 0000000..4396a56
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-610207.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Error.prepareStackTrace = function(exception, frames) {
+ return frames[0].getEvalOrigin();
+}
+
+try {
+ Realm.eval(0, "throw new Error('boom');");
+} catch(e) {
+ print(e.stack);
+}
diff --git a/test/mjsunit/regress/regress-crbug-610228.js b/test/mjsunit/regress/regress-crbug-610228.js
deleted file mode 100644
index ca077d5..0000000
--- a/test/mjsunit/regress/regress-crbug-610228.js
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --allow-natives-syntax
-
-function foo() { return JSON.stringify({a: 0.1}); }
-assertEquals('{"a":0.1}', foo());
-assertEquals('{"a":0.1}', foo());
-%OptimizeFunctionOnNextCall(foo);
-assertEquals('{"a":0.1}', foo());
diff --git a/test/mjsunit/regress/regress-crbug-612142.js b/test/mjsunit/regress/regress-crbug-612142.js
new file mode 100644
index 0000000..de2dc8d
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-612142.js
@@ -0,0 +1,10 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var thrower = {[Symbol.toPrimitive]: function(e) { throw e }};
+try {
+ for (var i = 0; i < 10; i++) { }
+ for (var i = 0.5; i < 100000; ++i) { }
+ for (var i = 16 | 0 || 0 || this || 1; i;) { String.fromCharCode(thrower); }
+} catch (e) { }
diff --git a/test/mjsunit/regress/regress-crbug-617524.js b/test/mjsunit/regress/regress-crbug-617524.js
new file mode 100644
index 0000000..b32eeef
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-617524.js
@@ -0,0 +1,18 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-gc --always-opt
+
+function f(a,b,c) {
+ a.a = b;
+ a[1] = c;
+ return a;
+}
+
+f(new Array(5),.5,0);
+var o1 = f(new Array(5),0,.5);
+gc();
+var o2 = f(new Array(5),0,0);
+var o3 = f(new Array(5),0);
+assertEquals(0, o3.a);
diff --git a/test/mjsunit/regress/regress-crbug-620119.js b/test/mjsunit/regress/regress-crbug-620119.js
new file mode 100644
index 0000000..cbe5a78
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-620119.js
@@ -0,0 +1,8 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --no-lazy
+
+assertEquals(0, ((x, {[(x = function() { y = 0 }, "foo")]: y = eval(1)}) => { x(); return y })(42, {}));
+assertEquals(0, (function (x, {[(x = function() { y = 0 }, "foo")]: y = eval(1)}) { x(); return y })(42, {}));
diff --git a/test/mjsunit/regress/regress-object-assign-deprecated-2.js b/test/mjsunit/regress/regress-object-assign-deprecated-2.js
new file mode 100644
index 0000000..89693de
--- /dev/null
+++ b/test/mjsunit/regress/regress-object-assign-deprecated-2.js
@@ -0,0 +1,8 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var x = {a:1, b:2};
+Object.defineProperty(x, "c", {set(v) {}})
+var y = {get c() { return {a:1, b:2.5} }};
+Object.assign(x, y, x);
diff --git a/test/mjsunit/regress/regress-object-assign-deprecated.js b/test/mjsunit/regress/regress-object-assign-deprecated.js
new file mode 100644
index 0000000..d2e60f9
--- /dev/null
+++ b/test/mjsunit/regress/regress-object-assign-deprecated.js
@@ -0,0 +1,7 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var x = {a:1, b:2};
+var y = {a:1, b:2.5};
+Object.assign(x, x);
diff --git a/test/mjsunit/regress/regress-observe-map-cache.js b/test/mjsunit/regress/regress-observe-map-cache.js
deleted file mode 100644
index c71759c..0000000
--- a/test/mjsunit/regress/regress-observe-map-cache.js
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-object-observe
-// Flags: --allow-natives-syntax --enable-slow-asserts
-
-function f() {
- var x = new Array(0);
- x[-1] = -1;
- Object.observe(x, function() { });
-}
-
-f();
-f();
diff --git a/test/mjsunit/regress/regress-opt-typeof-null.js b/test/mjsunit/regress/regress-opt-typeof-null.js
new file mode 100644
index 0000000..e4721a1
--- /dev/null
+++ b/test/mjsunit/regress/regress-opt-typeof-null.js
@@ -0,0 +1,12 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function f() {
+ return typeof null === "object";
+};
+
+%OptimizeFunctionOnNextCall(f);
+assertTrue(f());
diff --git a/test/mjsunit/regress/regress-recurse-patch-binary-op.js b/test/mjsunit/regress/regress-recurse-patch-binary-op.js
new file mode 100644
index 0000000..842cc79
--- /dev/null
+++ b/test/mjsunit/regress/regress-recurse-patch-binary-op.js
@@ -0,0 +1,10 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var i = 0
+function valueOf() {
+ while (true) return i++ < 4 ? 1 + this : 2
+}
+
+1 + ({valueOf})
diff --git a/test/mjsunit/regress/regress-v8-5009.js b/test/mjsunit/regress/regress-v8-5009.js
new file mode 100644
index 0000000..f499548
--- /dev/null
+++ b/test/mjsunit/regress/regress-v8-5009.js
@@ -0,0 +1,61 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function fn1() {
+}
+
+function fn2() {
+}
+
+function fn3() {
+}
+
+function create(id) {
+ // Just some `FunctionTemplate` to hang on
+ var o = new version();
+
+ o.id = id;
+ o[0] = null;
+
+ return o;
+}
+
+function setM1(o) {
+ o.m1 = fn1;
+}
+
+function setM2(o) {
+ o.m2 = fn2;
+}
+
+function setAltM2(o) {
+ // Failing StoreIC happens here
+ o.m2 = fn3;
+}
+
+function setAltM1(o) {
+ o.m1 = null;
+}
+
+function test(o) {
+ o.m2();
+ o.m1();
+}
+
+var p0 = create(0);
+var p1 = create(1);
+var p2 = create(2);
+
+setM1(p0);
+setM1(p1);
+setM1(p2);
+
+setM2(p0);
+setAltM2(p0);
+setAltM1(p0);
+
+setAltM2(p1);
+
+setAltM2(p2);
+test(p2);
diff --git a/test/mjsunit/stack-traces-overflow.js b/test/mjsunit/stack-traces-overflow.js
index e20c609..af81971 100644
--- a/test/mjsunit/stack-traces-overflow.js
+++ b/test/mjsunit/stack-traces-overflow.js
@@ -27,10 +27,22 @@
// Flags: --stack-size=100
+function overflow() {
+ var a, b, c, d, e; // Allocates some locals on the function's stack frame.
+ overflow();
+}
function rec1(a) { rec1(a+1); }
function rec2(a) { rec3(a+1); }
function rec3(a) { rec2(a+1); }
+// Test stack trace has correct function location at top of the stack.
+try {
+ overflow();
+} catch (e) {
+ var first_frame = e.stack.split("\n")[1]
+ assertTrue(first_frame.indexOf("stack-traces-overflow.js:30:18") > 0);
+}
+
// Test stack trace getter and setter.
try {
rec1(0);
diff --git a/test/mjsunit/string-wrapper.js b/test/mjsunit/string-wrapper.js
new file mode 100644
index 0000000..d4b6500
--- /dev/null
+++ b/test/mjsunit/string-wrapper.js
@@ -0,0 +1,62 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var limit = 10000;
+
+function testStringWrapper(string) {
+ assertEquals('a', string[0]);
+ assertEquals('b', string[1]);
+ assertEquals('c', string[2]);
+}
+
+(function testFastStringWrapperGrow() {
+ var string = new String("abc");
+ for (var i = 0; i < limit; i += 2) {
+ string[i] = {};
+ }
+ testStringWrapper(string);
+
+ for (var i = limit; i > 0; i -= 2) {
+ delete string[i];
+ }
+ testStringWrapper(string);
+})();
+
+(function testSlowStringWrapperGrow() {
+ var string = new String("abc");
+ // Force Slow String Wrapper Elements Kind
+ string[limit] = limit;
+ for (var i = 0; i < limit; i += 2) {
+ string[i] = {};
+ }
+ testStringWrapper(string);
+ assertEquals(limit, string[limit]);
+
+ for (var i = limit; i > 0; i -= 2) {
+ delete string[i];
+ }
+ testStringWrapper(string);
+ assertEquals(undefined, string[limit]);
+})();
+
+
+(function testReconfigureStringWrapperElements() {
+ var s = new String('abc');
+ // Can't reconfigure string contents.
+ assertThrows(() => Object.defineProperty(s, '1', {value: "value"}), TypeError);
+
+ // Configure a property outside the string range
+ var value = 'v1';
+ Object.defineProperty(s, '3', {
+ get: () => {return value},
+ configurable:true
+ });
+ assertEquals('v1', s[3]);
+ value = 'v2';
+ assertEquals('v2', s[3]);
+
+ Object.defineProperty(s, '3', {value: 'v3', configurable: false});
+ assertEquals('v3', s[3]);
+ assertThrows(() => Object.defineProperty(s, '3', {value:2}), TypeError);
+})();
diff --git a/test/mjsunit/tools/tickprocessor-test-func-info.log b/test/mjsunit/tools/tickprocessor-test-func-info.log
index 94aa56d..fcbf3b1 100644
--- a/test/mjsunit/tools/tickprocessor-test-func-info.log
+++ b/test/mjsunit/tools/tickprocessor-test-func-info.log
@@ -1,6 +1,6 @@
-shared-library,"shell",0x08048000,0x081ee000
-shared-library,"/lib32/libm-2.7.so",0xf7db6000,0xf7dd9000
-shared-library,"ffffe000-fffff000",0xffffe000,0xfffff000
+shared-library,"shell",0x08048000,0x081ee000,0
+shared-library,"/lib32/libm-2.7.so",0xf7db6000,0xf7dd9000,0
+shared-library,"ffffe000-fffff000",0xffffe000,0xfffff000,0
profiler,"begin",1
code-creation,Stub,0,0x424260,348,"CompareStub_GE"
code-creation,LazyCompile,0,0x2a8100,18535,"DrawQube 3d-cube.js:188",0xf43abcac,
diff --git a/test/mjsunit/tools/tickprocessor-test.log b/test/mjsunit/tools/tickprocessor-test.log
index cf8b90d..fbc868e 100644
--- a/test/mjsunit/tools/tickprocessor-test.log
+++ b/test/mjsunit/tools/tickprocessor-test.log
@@ -1,6 +1,6 @@
-shared-library,"shell",0x08048000,0x081ee000
-shared-library,"/lib32/libm-2.7.so",0xf7db6000,0xf7dd9000
-shared-library,"ffffe000-fffff000",0xffffe000,0xfffff000
+shared-library,"shell",0x08048000,0x081ee000,0
+shared-library,"/lib32/libm-2.7.so",0xf7db6000,0xf7dd9000,0
+shared-library,"ffffe000-fffff000",0xffffe000,0xfffff000,0
profiler,"begin",1
code-creation,Stub,0,0xf540a100,474,"CEntryStub"
code-creation,Script,0,0xf541cd80,736,"exp.js"
diff --git a/test/mjsunit/tools/tickprocessor.js b/test/mjsunit/tools/tickprocessor.js
index 73af098..804a85d 100644
--- a/test/mjsunit/tools/tickprocessor.js
+++ b/test/mjsunit/tools/tickprocessor.js
@@ -81,7 +81,7 @@
var shell_prov = new UnixCppEntriesProvider();
var shell_syms = [];
- shell_prov.parseVmSymbols('shell', 0x08048000, 0x081ee000,
+ shell_prov.parseVmSymbols('shell', 0x08048000, 0x081ee000, 0,
function (name, start, end) {
shell_syms.push(Array.prototype.slice.apply(arguments, [0]));
});
@@ -107,7 +107,7 @@
};
var libc_prov = new UnixCppEntriesProvider();
var libc_syms = [];
- libc_prov.parseVmSymbols('libc', 0xf7c5c000, 0xf7da5000,
+ libc_prov.parseVmSymbols('libc', 0xf7c5c000, 0xf7da5000, 0,
function (name, start, end) {
libc_syms.push(Array.prototype.slice.apply(arguments, [0]));
});
@@ -145,17 +145,17 @@
var shell_prov = new MacCppEntriesProvider();
var shell_syms = [];
- shell_prov.parseVmSymbols('shell', 0x00001b00, 0x00163156,
+ shell_prov.parseVmSymbols('shell', 0x00001c00, 0x00163256, 0x100,
function (name, start, end) {
shell_syms.push(Array.prototype.slice.apply(arguments, [0]));
});
assertEquals(
- [['start', 0x00001b00, 0x00001b40],
- ['dyld_stub_binding_helper', 0x00001b40, 0x0011b710],
- ['v8::internal::RegExpMacroAssembler::CheckPosition', 0x0011b710, 0x00134250],
- ['v8::internal::Runtime_StringReplaceRegExpWithString', 0x00134250, 0x00137220],
- ['v8::internal::Runtime::GetElementOrCharAt', 0x00137220, 0x00137400],
- ['v8::internal::Runtime_DebugGetPropertyDetails', 0x00137400, 0x00163156]],
+ [['start', 0x00001c00, 0x00001c40],
+ ['dyld_stub_binding_helper', 0x00001c40, 0x0011b810],
+ ['v8::internal::RegExpMacroAssembler::CheckPosition', 0x0011b810, 0x00134350],
+ ['v8::internal::Runtime_StringReplaceRegExpWithString', 0x00134350, 0x00137320],
+ ['v8::internal::Runtime::GetElementOrCharAt', 0x00137320, 0x00137500],
+ ['v8::internal::Runtime_DebugGetPropertyDetails', 0x00137500, 0x00163256]],
shell_syms);
// stdc++ library
@@ -168,7 +168,7 @@
};
var stdc_prov = new MacCppEntriesProvider();
var stdc_syms = [];
- stdc_prov.parseVmSymbols('stdc++', 0x95728fb4, 0x95770005,
+ stdc_prov.parseVmSymbols('stdc++', 0x95728fb4, 0x95770005, 0,
function (name, start, end) {
stdc_syms.push(Array.prototype.slice.apply(arguments, [0]));
});
@@ -211,7 +211,7 @@
};
var shell_prov = new WindowsCppEntriesProvider();
var shell_syms = [];
- shell_prov.parseVmSymbols('shell.exe', 0x00400000, 0x0057c000,
+ shell_prov.parseVmSymbols('shell.exe', 0x00400000, 0x0057c000, 0,
function (name, start, end) {
shell_syms.push(Array.prototype.slice.apply(arguments, [0]));
});
@@ -252,7 +252,7 @@
read = exeSymbols;
var exe_exe_syms = [];
(new WindowsCppEntriesProvider()).parseVmSymbols(
- 'chrome.exe', 0x00400000, 0x00472000,
+ 'chrome.exe', 0x00400000, 0x00472000, 0,
function (name, start, end) {
exe_exe_syms.push(Array.prototype.slice.apply(arguments, [0]));
});
@@ -264,7 +264,7 @@
read = dllSymbols;
var exe_dll_syms = [];
(new WindowsCppEntriesProvider()).parseVmSymbols(
- 'chrome.exe', 0x00400000, 0x00472000,
+ 'chrome.exe', 0x00400000, 0x00472000, 0,
function (name, start, end) {
exe_dll_syms.push(Array.prototype.slice.apply(arguments, [0]));
});
@@ -275,7 +275,7 @@
read = dllSymbols;
var dll_dll_syms = [];
(new WindowsCppEntriesProvider()).parseVmSymbols(
- 'chrome.dll', 0x01c30000, 0x02b80000,
+ 'chrome.dll', 0x01c30000, 0x02b80000, 0,
function (name, start, end) {
dll_dll_syms.push(Array.prototype.slice.apply(arguments, [0]));
});
@@ -287,7 +287,7 @@
read = exeSymbols;
var dll_exe_syms = [];
(new WindowsCppEntriesProvider()).parseVmSymbols(
- 'chrome.dll', 0x01c30000, 0x02b80000,
+ 'chrome.dll', 0x01c30000, 0x02b80000, 0,
function (name, start, end) {
dll_exe_syms.push(Array.prototype.slice.apply(arguments, [0]));
});
@@ -304,7 +304,7 @@
CppEntriesProviderMock.prototype.parseVmSymbols = function(
- name, startAddr, endAddr, symbolAdder) {
+ name, startAddr, endAddr, slideAddr, symbolAdder) {
var symbols = {
'shell':
[['v8::internal::JSObject::LookupOwnRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)', 0x080f8800, 0x080f8d90],
diff --git a/test/mjsunit/wasm/adapter-frame.js b/test/mjsunit/wasm/adapter-frame.js
index 0e5d4b8..39164c7 100644
--- a/test/mjsunit/wasm/adapter-frame.js
+++ b/test/mjsunit/wasm/adapter-frame.js
@@ -27,8 +27,10 @@
var builder = new WasmModuleBuilder();
var sig = new Array();
- sig.push(type);
+ sig.push(args);
for (var i = 0; i < args; i++) sig.push(type);
+ sig.push(1);
+ sig.push(type);
builder.addFunction("select", sig)
.addBody([kExprGetLocal, which])
.exportFunc();
diff --git a/test/mjsunit/wasm/asm-wasm-switch.js b/test/mjsunit/wasm/asm-wasm-switch.js
new file mode 100644
index 0000000..bbdb1a2
--- /dev/null
+++ b/test/mjsunit/wasm/asm-wasm-switch.js
@@ -0,0 +1,468 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-wasm
+
+(function TestSwitch0() {
+ function asmModule() {
+ "use asm"
+
+ function caller() {
+ var ret = 0;
+ var x = 7;
+ switch (x) {
+ case 1: {
+ return 0;
+ }
+ case 7: {
+ ret = 5;
+ break;
+ }
+ default: return 0;
+ }
+ return ret|0;
+ }
+
+ return {caller:caller};
+ }
+ var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+ assertEquals(5, wasm.caller());
+})();
+
+(function TestSwitch() {
+ function asmModule() {
+ "use asm"
+
+ function caller() {
+ var ret = 0;
+ var x = 7;
+ switch (x) {
+ case 1: return 0;
+ case 7: {
+ ret = 12;
+ break;
+ }
+ default: return 0;
+ }
+ switch (x) {
+ case 1: return 0;
+ case 8: return 0;
+ default: ret = (ret + 11)|0;
+ }
+ return ret|0;
+ }
+
+ return {caller:caller};
+ }
+ var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+ assertEquals(23, wasm.caller());
+})();
+
+(function TestSwitchFallthrough() {
+ function asmModule() {
+ "use asm"
+
+ function caller() {
+ var x = 17;
+ var ret = 0;
+ switch (x) {
+ case 17:
+ case 14: ret = 39;
+ case 1: ret = (ret + 3)|0;
+ case 4: break;
+ default: ret = (ret + 1)|0;
+ }
+ return ret|0;
+ }
+
+ return {caller:caller};
+ }
+ var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+ assertEquals(42, wasm.caller());
+})();
+
+(function TestNestedSwitch() {
+ function asmModule() {
+ "use asm"
+
+ function caller() {
+ var x = 3;
+ var y = -13;
+ switch (x) {
+ case 1: return 0;
+ case 3: {
+ switch (y) {
+ case 2: return 0;
+ case -13: return 43;
+ default: return 0;
+ }
+ }
+ default: return 0;
+ }
+ return 0;
+ }
+
+ return {caller:caller};
+ }
+ var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+ assertEquals(43, wasm.caller());
+})();
+
+(function TestSwitchWithDefaultOnly() {
+ function asmModule() {
+ "use asm";
+ function main(x) {
+ x = x|0;
+ switch(x|0) {
+ default: return -10;
+ }
+ return 0;
+ }
+ return {
+ main: main,
+ };
+ }
+ var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+ assertEquals(-10, wasm.main(2));
+ assertEquals(-10, wasm.main(54));
+})();
+
+(function TestEmptySwitch() {
+ function asmModule() {
+ "use asm";
+ function main(x) {
+ x = x|0;
+ switch(x|0) {
+ }
+ return 73;
+ }
+ return {
+ main: main,
+ };
+ }
+ var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+ assertEquals(73, wasm.main(7));
+})();
+
+(function TestSwitchWithBrTable() {
+ function asmModule() {
+ "use asm";
+ function main(x) {
+ x = x|0;
+ switch(x|0) {
+ case 14: return 23;
+ case 12: return 25;
+ case 15: return 29;
+ case 19: return 34;
+ case 18: return 17;
+ case 16: return 16;
+ default: return -1;
+ }
+ return 0;
+ }
+ return {
+ main: main,
+ };
+ }
+ var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+ assertEquals(25, wasm.main(12));
+ assertEquals(23, wasm.main(14));
+ assertEquals(29, wasm.main(15));
+ assertEquals(16, wasm.main(16));
+ assertEquals(17, wasm.main(18));
+ assertEquals(34, wasm.main(19));
+ assertEquals(-1, wasm.main(-1));
+})();
+
+(function TestSwitchWithBalancedTree() {
+ function asmModule() {
+ "use asm";
+ function main(x) {
+ x = x|0;
+ switch(x|0) {
+ case 5: return 52;
+ case 1: return 11;
+ case 6: return 63;
+ case 9: return 19;
+ case -4: return -4;
+ }
+ return 0;
+ }
+ return {
+ main: main,
+ };
+ }
+ var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+ assertEquals(-4, wasm.main(-4));
+ assertEquals(11, wasm.main(1));
+ assertEquals(52, wasm.main(5));
+ assertEquals(63, wasm.main(6));
+ assertEquals(19, wasm.main(9));
+ assertEquals(0, wasm.main(11));
+})();
+
+(function TestSwitchHybrid() {
+ function asmModule() {
+ "use asm";
+ function main(x) {
+ x = x|0;
+ switch(x|0) {
+ case 1: return -4;
+ case 2: return 23;
+ case 3: return 32;
+ case 4: return 14;
+ case 7: return 17;
+ case 10: return 10;
+ case 11: return 121;
+ case 12: return 112;
+ case 13: return 31;
+ case 16: return 16;
+ default: return -1;
+ }
+ return 0;
+ }
+ return {
+ main: main,
+ };
+ }
+ var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+ assertEquals(-4, wasm.main(1));
+ assertEquals(23, wasm.main(2));
+ assertEquals(32, wasm.main(3));
+ assertEquals(14, wasm.main(4));
+ assertEquals(17, wasm.main(7));
+ assertEquals(10, wasm.main(10));
+ assertEquals(121, wasm.main(11));
+ assertEquals(112, wasm.main(12));
+ assertEquals(31, wasm.main(13));
+ assertEquals(16, wasm.main(16));
+ assertEquals(-1, wasm.main(20));
+})();
+
+(function TestSwitchFallthroughWithBrTable() {
+ function asmModule() {
+ "use asm";
+ function main(x) {
+ x = x|0;
+ var ret = 0;
+ switch(x|0) {
+ case 1: {
+ ret = 21;
+ break;
+ }
+ case 2: {
+ ret = 12;
+ break;
+ }
+ case 3: {
+ ret = 43;
+ }
+ case 4: {
+ ret = 54;
+ break;
+ }
+ default: {
+ ret = 10;
+ break;
+ }
+ }
+ return ret|0;
+ }
+ return {
+ main: main,
+ };
+ }
+ var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+ assertEquals(12, wasm.main(2));
+ assertEquals(10, wasm.main(10));
+ assertEquals(54, wasm.main(3));
+})();
+
+(function TestSwitchFallthroughHybrid() {
+ function asmModule() {
+ "use asm";
+ function main(x) {
+ x = x|0;
+ var ret = 0;
+ switch(x|0) {
+ case 1: {
+ ret = 1;
+ break;
+ }
+ case 2: {
+ ret = 2;
+ break;
+ }
+ case 3: {
+ ret = 3;
+ break;
+ }
+ case 4: {
+ ret = 4;
+ }
+ case 7: {
+ ret = 7;
+ break;
+ }
+ case 10: {
+ ret = 10;
+ }
+ case 16: {
+ ret = 16;
+ break;
+ }
+ case 17: {
+ ret = 17;
+ break;
+ }
+ case 18: {
+ ret = 18;
+ break;
+ }
+ case 19: {
+ ret = 19;
+ }
+ default: {
+ ret = -1;
+ break;
+ }
+ }
+ return ret|0;
+ }
+ return {
+ main: main,
+ };
+ }
+ var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+ assertEquals(7, wasm.main(4));
+ assertEquals(16, wasm.main(10));
+ assertEquals(-1, wasm.main(19));
+ assertEquals(-1, wasm.main(23));
+})();
+
+(function TestSwitchHybridWithNoDefault() {
+ function asmModule() {
+ "use asm";
+ function main(x) {
+ x = x|0;
+ var ret = 19;
+ switch(x|0) {
+ case 1: {
+ ret = 1;
+ break;
+ }
+ case 2: {
+ ret = 2;
+ break;
+ }
+ case 3: {
+ ret = 3;
+ break;
+ }
+ case 4: {
+ ret = 4;
+ break;
+ }
+ case 7: {
+ ret = 7;
+ break;
+ }
+ }
+ return ret|0;
+ }
+ return {
+ main: main,
+ };
+ }
+ var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+ assertEquals(2, wasm.main(2));
+ assertEquals(7, wasm.main(7));
+ assertEquals(19, wasm.main(-1));
+})();
+
+(function TestLargeSwitch() {
+ function LargeSwitchGenerator(begin, end, gap, handle_case) {
+ var str = "function asmModule() {\
+ \"use asm\";\
+ function main(x) {\
+ x = x|0;\
+ switch(x|0) {";
+ for (var i = begin; i <= end; i = i + gap) {
+ str = str.concat("case ", i.toString(), ": ", handle_case(i));
+ }
+ str = str.concat("default: return -1;\
+ }\
+ return -2;\
+ }\
+ return {main: main}; }");
+
+ var wasm = Wasm.instantiateModuleFromAsm(str);
+ return wasm;
+ }
+
+ var handle_case = function(k) {
+ return "return ".concat(k, ";");
+ }
+ var wasm = LargeSwitchGenerator(0, 513, 1, handle_case);
+ for (var i = 0; i <= 513; i++) {
+ assertEquals(i, wasm.main(i));
+ }
+ assertEquals(-1, wasm.main(-1));
+
+ wasm = LargeSwitchGenerator(0, 1024, 3, handle_case);
+ for (var i = 0; i <= 1024; i = i + 3) {
+ assertEquals(i, wasm.main(i));
+ }
+ assertEquals(-1, wasm.main(-1));
+
+ wasm = LargeSwitchGenerator(-2147483648, -2147483000, 1, handle_case);
+ for (var i = -2147483648; i <= -2147483000; i++) {
+ assertEquals(i, wasm.main(i));
+ }
+ assertEquals(-1, wasm.main(-1));
+ assertEquals(-1, wasm.main(214748647));
+
+ wasm = LargeSwitchGenerator(-2147483648, -2147483000, 3, handle_case);
+ for (var i = -2147483648; i <= -2147483000; i = i + 3) {
+ assertEquals(i, wasm.main(i));
+ }
+ assertEquals(-1, wasm.main(-1));
+ assertEquals(-1, wasm.main(214748647));
+
+ wasm = LargeSwitchGenerator(2147483000, 2147483647, 1, handle_case);
+ for (var i = 2147483000; i <= 2147483647; i++) {
+ assertEquals(i, wasm.main(i));
+ }
+ assertEquals(-1, wasm.main(-1));
+ assertEquals(-1, wasm.main(-214748647));
+
+ wasm = LargeSwitchGenerator(2147483000, 2147483647, 4, handle_case);
+ for (var i = 2147483000; i <= 2147483647; i = i + 4) {
+ assertEquals(i, wasm.main(i));
+ }
+ assertEquals(-1, wasm.main(-1));
+ assertEquals(-1, wasm.main(-214748647));
+
+ handle_case = function(k) {
+ if (k != 7) return "return ".concat(k, ";");
+ else return "break;";
+ }
+ wasm = LargeSwitchGenerator(0, 1499, 7, handle_case);
+ for (var i = 0; i <= 1499; i = i + 7) {
+ if (i == 7) assertEquals(-2, wasm.main(i));
+ else assertEquals(i, wasm.main(i));
+ }
+ assertEquals(-1, wasm.main(-1));
+
+ handle_case = function(k) {
+ if (k != 56) return "break;";
+ else return "return 23;";
+ }
+ wasm = LargeSwitchGenerator(0, 638, 2, handle_case);
+ for (var i = 0; i <= 638; i = i + 2) {
+ if (i == 56) assertEquals(23, wasm.main(i));
+ else assertEquals(-2, wasm.main(i));
+ }
+ assertEquals(-1, wasm.main(-1));
+})();
diff --git a/test/mjsunit/wasm/asm-wasm.js b/test/mjsunit/wasm/asm-wasm.js
index 2efb006..54d7d7a 100644
--- a/test/mjsunit/wasm/asm-wasm.js
+++ b/test/mjsunit/wasm/asm-wasm.js
@@ -23,6 +23,20 @@
assertWasm(11, EmptyTest);
+function VoidReturnTest() {
+ "use asm";
+ function caller() {
+ empty();
+ return 19;
+ }
+ function empty() {
+ var x = 0;
+ if (x) return;
+ }
+ return {caller: caller};
+}
+
+assertWasm(19, VoidReturnTest);
function IntTest() {
"use asm";
@@ -193,6 +207,55 @@
assertWasm(7, TestReturnInWhileWithoutBraces);
+function TestBreakInIf() {
+ "use asm";
+
+ function caller() {
+ label: {
+ if(1) break label;
+ return 11;
+ }
+ return 12;
+ }
+
+ return {caller: caller};
+}
+
+assertWasm(12, TestBreakInIf);
+
+function TestBreakInIfInDoWhileFalse() {
+ "use asm";
+
+ function caller() {
+ do {
+ if(1) break;
+ return 11;
+ } while(0);
+ return 12;
+ }
+
+ return {caller: caller};
+}
+
+assertWasm(12, TestBreakInIfInDoWhileFalse);
+
+function TestBreakInElse() {
+ "use asm";
+
+ function caller() {
+ do {
+ if(0) ;
+ else break;
+ return 14;
+ } while(0);
+ return 15;
+ }
+
+ return {caller: caller};
+}
+
+assertWasm(15, TestBreakInElse);
+
function TestBreakInWhile() {
"use asm";
@@ -209,6 +272,22 @@
assertWasm(8, TestBreakInWhile);
+function TestBreakInIfInWhile() {
+ "use asm";
+
+ function caller() {
+ while(1) {
+ if (1) break;
+ else break;
+ }
+ return 8;
+ }
+
+ return {caller: caller};
+}
+
+assertWasm(8, TestBreakInIfInWhile);
+
function TestBreakInNestedWhile() {
"use asm";
@@ -769,82 +848,6 @@
assertWasm(41, TestConditional);
-function TestSwitch() {
- "use asm"
-
- function caller() {
- var ret = 0;
- var x = 7;
- switch (x) {
- case 1: return 0;
- case 7: {
- ret = 12;
- break;
- }
- default: return 0;
- }
- switch (x) {
- case 1: return 0;
- case 8: return 0;
- default: ret = (ret + 11)|0;
- }
- return ret|0;
- }
-
- return {caller:caller};
-}
-
-assertWasm(23, TestSwitch);
-
-
-function TestSwitchFallthrough() {
- "use asm"
-
- function caller() {
- var x = 17;
- var ret = 0;
- switch (x) {
- case 17:
- case 14: ret = 39;
- case 1: ret = (ret + 3)|0;
- case 4: break;
- default: ret = (ret + 1)|0;
- }
- return ret|0;
- }
-
- return {caller:caller};
-}
-
-assertWasm(42, TestSwitchFallthrough);
-
-
-function TestNestedSwitch() {
- "use asm"
-
- function caller() {
- var x = 3;
- var y = -13;
- switch (x) {
- case 1: return 0;
- case 3: {
- switch (y) {
- case 2: return 0;
- case -13: return 43;
- default: return 0;
- }
- }
- default: return 0;
- }
- return 0;
- }
-
- return {caller:caller};
-}
-
-assertWasm(43, TestNestedSwitch);
-
-
(function () {
function TestInitFunctionWithNoGlobals() {
"use asm";
diff --git a/test/mjsunit/wasm/calls.js b/test/mjsunit/wasm/calls.js
index 11cc92a..94e97e6 100644
--- a/test/mjsunit/wasm/calls.js
+++ b/test/mjsunit/wasm/calls.js
@@ -37,20 +37,42 @@
assertFalse(exp === null);
assertFalse(exp === 0);
assertEquals("function", typeof exp);
-
return exp;
}
+(function I64SubTest() {
+
+ var builder = new WasmModuleBuilder();
+
+ builder.addMemory(1, 1, true);
+ builder.addFunction("sub", kSig_l_ll)
+ .addBody([ // --
+ kExprGetLocal, 0, // --
+ kExprGetLocal, 1, // --
+ kExprI64Sub]) // --
+ .exportFunc()
+
+ var module = builder.instantiate();
+ assertModule(module, kPageSize);
+
+ // Check the properties of the sub function.
+ var sub = assertFunction(module, "sub");
+ assertEquals(-55, sub(33, 88));
+ assertEquals(-55555, sub(33333, 88888));
+ assertEquals(-5555555, sub(3333333, 8888888));
+})();
+
(function SubTest() {
var builder = new WasmModuleBuilder();
builder.addMemory(1, 1, true);
- builder.addFunction("sub", [kAstI32, kAstI32, kAstI32])
+ builder.addFunction("sub", kSig_i_ii)
.addBody([
- kExprI32Sub, // --
kExprGetLocal, 0, // --
- kExprGetLocal, 1]) // --
+ kExprGetLocal, 1, // --
+ kExprI32Sub, // --
+ ])
.exportFunc()
var module = builder.instantiate();
@@ -70,7 +92,7 @@
var kPages = 2;
builder.addMemory(kPages, kPages, true);
- builder.addFunction("nop", [kAstStmt])
+ builder.addFunction("nop", kSig_v_v)
.addBody([kExprNop])
.exportFunc();
@@ -87,11 +109,12 @@
var kPages = 3;
builder.addMemory(kPages, kPages, true);
- builder.addFunction("flt", [kAstI32, kAstF64, kAstF64])
+ builder.addFunction("flt", kSig_i_dd)
.addBody([
- kExprF64Lt, // --
kExprGetLocal, 0, // --
- kExprGetLocal, 1]) // --
+ kExprGetLocal, 1, // --
+ kExprF64Lt // --
+ ]) // --
.exportFunc();
var module = builder.instantiate();
diff --git a/test/mjsunit/wasm/divrem-trap.js b/test/mjsunit/wasm/divrem-trap.js
index 976e473..6f3ff5d 100644
--- a/test/mjsunit/wasm/divrem-trap.js
+++ b/test/mjsunit/wasm/divrem-trap.js
@@ -33,8 +33,12 @@
function makeBinop(opcode) {
var builder = new WasmModuleBuilder();
- builder.addFunction("main", [kAstI32, kAstI32, kAstI32])
- .addBody([opcode, kExprGetLocal, 0, kExprGetLocal, 1])
+ builder.addFunction("main", kSig_i_ii)
+ .addBody([
+ kExprGetLocal, 0, // --
+ kExprGetLocal, 1, // --
+ opcode, // --
+ ])
.exportFunc();
return builder.instantiate().exports.main;
diff --git a/test/mjsunit/wasm/export-table.js b/test/mjsunit/wasm/export-table.js
index e85da9b..a41d85d 100644
--- a/test/mjsunit/wasm/export-table.js
+++ b/test/mjsunit/wasm/export-table.js
@@ -11,11 +11,12 @@
var kReturnValue = 88;
var builder = new WasmModuleBuilder();
- builder.addFunction("main", [kAstI32])
+ builder.addFunction("main", kSig_i)
.addBody([
- kExprReturn,
kExprI8Const,
- kReturnValue])
+ kReturnValue,
+ kExprReturn, kArity1
+ ])
.exportFunc();
var module = builder.instantiate();
@@ -31,11 +32,12 @@
var builder = new WasmModuleBuilder();
- builder.addFunction("main", [kAstI32])
+ builder.addFunction("main", kSig_i)
.addBody([
- kExprReturn,
kExprI8Const,
- kReturnValue])
+ kReturnValue,
+ kExprReturn, kArity1
+ ])
.exportAs("blah")
.exportAs("foo");
@@ -48,3 +50,25 @@
assertEquals(kReturnValue, module.exports.foo());
assertEquals(kReturnValue, module.exports.blah());
})();
+
+
+(function testNumericName() {
+ var kReturnValue = 93;
+
+ var builder = new WasmModuleBuilder();
+
+ builder.addFunction("main", kSig_i)
+ .addBody([
+ kExprI8Const,
+ kReturnValue,
+ kExprReturn, kArity1
+ ])
+ .exportAs("0");
+
+ var module = builder.instantiate();
+
+ assertEquals("object", typeof module.exports);
+ assertEquals("function", typeof module.exports["0"]);
+
+ assertEquals(kReturnValue, module.exports["0"]());
+})();
diff --git a/test/mjsunit/wasm/ffi-error.js b/test/mjsunit/wasm/ffi-error.js
index 649ee27..b6474c6 100644
--- a/test/mjsunit/wasm/ffi-error.js
+++ b/test/mjsunit/wasm/ffi-error.js
@@ -10,13 +10,14 @@
function testCallFFI(ffi) {
var builder = new WasmModuleBuilder();
- var sig_index = [kAstI32, kAstF64, kAstF64];
+ var sig_index = kSig_i_dd;
builder.addImport("fun", sig_index);
builder.addFunction("main", sig_index)
.addBody([
- kExprCallImport, 0, // --
- kExprGetLocal, 0, // --
- kExprGetLocal, 1]) // --
+ kExprGetLocal, 0, // --
+ kExprGetLocal, 1, // --
+ kExprCallFunction, kArity2, 0, // --
+ ]) // --
.exportFunc();
var module = builder.instantiate(ffi);
diff --git a/test/mjsunit/wasm/ffi.js b/test/mjsunit/wasm/ffi.js
index 61fcf02..87dfe3b 100644
--- a/test/mjsunit/wasm/ffi.js
+++ b/test/mjsunit/wasm/ffi.js
@@ -10,13 +10,14 @@
function testCallFFI(func, check) {
var builder = new WasmModuleBuilder();
- var sig_index = builder.addSignature([kAstI32, kAstF64, kAstF64]);
+ var sig_index = builder.addSignature(kSig_i_dd);
builder.addImport("func", sig_index);
builder.addFunction("main", sig_index)
.addBody([
- kExprCallImport, 0, // --
- kExprGetLocal, 0, // --
- kExprGetLocal, 1]) // --
+ kExprGetLocal, 0, // --
+ kExprGetLocal, 1, // --
+ kExprCallImport, kArity2, 0 // --
+ ]) // --
.exportFunc();
var main = builder.instantiate({func: func}).exports.main;
@@ -184,14 +185,14 @@
var builder = new WasmModuleBuilder();
- builder.addImport("func", [kAstStmt, type, type]);
- builder.addFunction("main", [kAstI32, type, type])
+ builder.addImport("func", makeSig_v_xx(type));
+ builder.addFunction("main", makeSig_r_xx(kAstI32, type))
.addBody([
- kExprBlock, 2, // --
- kExprCallImport, 0, // --
- kExprGetLocal, 0, // --
- kExprGetLocal, 1, // --
- kExprI8Const, 99]) // --
+ kExprGetLocal, 0, // --
+ kExprGetLocal, 1, // --
+ kExprCallImport, kArity2, 0, // --
+ kExprI8Const, 99 // --
+ ]) // --
.exportFunc()
var main = builder.instantiate(ffi).exports.main;
@@ -240,15 +241,15 @@
function testCallPrint() {
var builder = new WasmModuleBuilder();
- builder.addImport("print", [kAstStmt, kAstI32]);
- builder.addImport("print", [kAstStmt, kAstF64]);
- builder.addFunction("main", [kAstStmt, kAstF64])
+ builder.addImport("print", makeSig_v_x(kAstI32));
+ builder.addImport("print", makeSig_v_x(kAstF64));
+ builder.addFunction("main", makeSig_v_x(kAstF64))
.addBody([
- kExprBlock, 2, // --
- kExprCallImport, 0, // --
- kExprI8Const, 97, // --
- kExprCallImport, 1, // --
- kExprGetLocal, 0]) // --
+ kExprI8Const, 97, // --
+ kExprCallImport, kArity1, 0, // --
+ kExprGetLocal, 0, // --
+ kExprCallImport, kArity1, 1 // --
+ ]) // --
.exportFunc()
var main = builder.instantiate({print: print}).exports.main;
diff --git a/test/mjsunit/wasm/function-prototype.js b/test/mjsunit/wasm/function-prototype.js
index db04b95..25339ad 100644
--- a/test/mjsunit/wasm/function-prototype.js
+++ b/test/mjsunit/wasm/function-prototype.js
@@ -10,7 +10,7 @@
(function TestFunctionPrototype() {
var builder = new WasmModuleBuilder();
- builder.addFunction("nine", [kAstI32])
+ builder.addFunction("nine", kSig_i)
.addBody([kExprI8Const, 9])
.exportFunc();
diff --git a/test/mjsunit/wasm/gc-frame.js b/test/mjsunit/wasm/gc-frame.js
index 8387d26..5fa9b05 100644
--- a/test/mjsunit/wasm/gc-frame.js
+++ b/test/mjsunit/wasm/gc-frame.js
@@ -10,14 +10,13 @@
function makeFFI(func, t) {
var builder = new WasmModuleBuilder();
- var sig_index = builder.addSignature([t,t,t,t,t,t,t,t,t,t,t]);
+ var sig_index = builder.addSignature([10,t,t,t,t,t,t,t,t,t,t,1,t]);
builder.addImport("func", sig_index);
// Try to create a frame with lots of spilled values and parameters
// on the stack to try to catch GC bugs in the reference maps for
// the different parts of the stack.
builder.addFunction("main", sig_index)
.addBody([
- kExprCallImport, 0, // --
kExprGetLocal, 0, // --
kExprGetLocal, 1, // --
kExprGetLocal, 2, // --
@@ -28,7 +27,7 @@
kExprGetLocal, 7, // --
kExprGetLocal, 8, // --
kExprGetLocal, 9, // --
- kExprCallImport, 0, // --
+ kExprCallImport, 10, 0, // --
kExprGetLocal, 0, // --
kExprGetLocal, 1, // --
kExprGetLocal, 2, // --
@@ -38,7 +37,8 @@
kExprGetLocal, 6, // --
kExprGetLocal, 7, // --
kExprGetLocal, 8, // --
- kExprGetLocal, 9 // --
+ kExprGetLocal, 9, // --
+ kExprCallImport, 10, 0 // --
]) // --
.exportFunc();
diff --git a/test/mjsunit/wasm/import-table.js b/test/mjsunit/wasm/import-table.js
index 7579901..c3f8cb9 100644
--- a/test/mjsunit/wasm/import-table.js
+++ b/test/mjsunit/wasm/import-table.js
@@ -10,13 +10,13 @@
function testCallImport(func, check) {
var builder = new WasmModuleBuilder();
- var sig_index = builder.addSignature([kAstI32, kAstF64, kAstF64]);
+ var sig_index = builder.addSignature(kSig_i_dd);
builder.addImport("func", sig_index);
builder.addFunction("main", sig_index)
.addBody([
- kExprCallImport, 0, // --
kExprGetLocal, 0, // --
- kExprGetLocal, 1]) // --
+ kExprGetLocal, 1, // --
+ kExprCallImport, 2, 0]) // --
.exportAs("main");
var main = builder.instantiate({func: func}).exports.main;
@@ -186,14 +186,14 @@
var builder = new WasmModuleBuilder();
- builder.addImport("func", [kAstStmt, type, type]);
- builder.addFunction("main", [kAstI32, type, type])
+ builder.addImport("func", makeSig_v_xx(type));
+ builder.addFunction("main", makeSig_r_xx(kAstI32, type))
.addBody([
- kExprBlock, 2, // --
- kExprCallImport, 0, // --
kExprGetLocal, 0, // --
kExprGetLocal, 1, // --
- kExprI8Const, 99])
+ kExprCallImport, 2, 0, // --
+ kExprI8Const, 99, // --
+ ])
.exportFunc("main");
var main = builder.instantiate(ffi).exports.main;
@@ -241,15 +241,15 @@
function testCallPrint() {
var builder = new WasmModuleBuilder();
- builder.addImport("print", [kAstStmt, kAstI32]);
- builder.addImport("print", [kAstStmt, kAstF64]);
- builder.addFunction("main", [kAstStmt, kAstF64])
+ builder.addImport("print", makeSig_v_x(kAstI32));
+ builder.addImport("print", makeSig_r_x(kAstF64, kAstF64));
+ builder.addFunction("main", makeSig_r_x(kAstF64, kAstF64))
.addBody([
- kExprBlock, 2, // --
- kExprCallImport, 0, // --
- kExprI8Const, 97, // --
- kExprCallImport, 1, // --
- kExprGetLocal, 0]) // --
+ kExprI8Const, 97, // --
+ kExprCallImport, kArity1, 0, // --
+ kExprGetLocal, 0, // --
+ kExprCallImport, kArity1, 1 // --
+ ])
.exportFunc();
var main = builder.instantiate({print: print}).exports.main;
@@ -266,13 +266,14 @@
function testCallImport2(foo, bar, expected) {
var builder = new WasmModuleBuilder();
- builder.addImport("foo", [kAstI32]);
- builder.addImport("bar", [kAstI32]);
- builder.addFunction("main", [kAstI32])
+ builder.addImport("foo", kSig_i);
+ builder.addImport("bar", kSig_i);
+ builder.addFunction("main", kSig_i)
.addBody([
+ kExprCallImport, kArity0, 0, // --
+ kExprCallImport, kArity0, 1, // --
kExprI32Add, // --
- kExprCallImport, 0, // --
- kExprCallImport, 1]) // --
+ ]) // --
.exportFunc();
var main = builder.instantiate({foo: foo, bar: bar}).exports.main;
diff --git a/test/mjsunit/wasm/indirect-calls.js b/test/mjsunit/wasm/indirect-calls.js
index 3258687..80bee41 100644
--- a/test/mjsunit/wasm/indirect-calls.js
+++ b/test/mjsunit/wasm/indirect-calls.js
@@ -10,22 +10,25 @@
var module = (function () {
var builder = new WasmModuleBuilder();
- var sig_index = builder.addSignature([kAstI32, kAstI32, kAstI32]);
+ var sig_index = builder.addSignature(kSig_i_ii);
builder.addImport("add", sig_index);
builder.addFunction("add", sig_index)
.addBody([
- kExprCallImport, 0, kExprGetLocal, 0, kExprGetLocal, 1
+ kExprGetLocal, 0, kExprGetLocal, 1, kExprCallImport, kArity2, 0
]);
builder.addFunction("sub", sig_index)
.addBody([
- kExprI32Sub, kExprGetLocal, 0, kExprGetLocal, 1
+ kExprGetLocal, 0, // --
+ kExprGetLocal, 1, // --
+ kExprI32Sub, // --
]);
- builder.addFunction("main", [kAstI32, kAstI32, kAstI32, kAstI32])
+ builder.addFunction("main", kSig_i_iii)
.addBody([
- kExprCallIndirect, sig_index,
kExprGetLocal, 0,
kExprGetLocal, 1,
- kExprGetLocal, 2])
+ kExprGetLocal, 2,
+ kExprCallIndirect, kArity2, sig_index
+ ])
.exportFunc()
builder.appendToFunctionTable([0, 1, 2]);
diff --git a/test/mjsunit/wasm/instantiate-module-basic.js b/test/mjsunit/wasm/instantiate-module-basic.js
index bc13122..800dcc1 100644
--- a/test/mjsunit/wasm/instantiate-module-basic.js
+++ b/test/mjsunit/wasm/instantiate-module-basic.js
@@ -13,7 +13,7 @@
var builder = new WasmModuleBuilder();
builder.addMemory(1, 1, true);
- builder.addFunction("main", [kAstI32])
+ builder.addFunction("main", kSig_i)
.addBody([kExprI8Const, kReturnValue])
.exportFunc();
diff --git a/test/mjsunit/wasm/instantiate-run-basic.js b/test/mjsunit/wasm/instantiate-run-basic.js
index 2e649a0..fe6fc14 100644
--- a/test/mjsunit/wasm/instantiate-run-basic.js
+++ b/test/mjsunit/wasm/instantiate-run-basic.js
@@ -11,7 +11,7 @@
var kReturnValue = 107;
var builder = new WasmModuleBuilder();
- builder.addFunction("main", [kAstI32])
+ builder.addFunction("main", kSig_i_i)
.addBody([kExprI8Const, kReturnValue])
.exportFunc();
diff --git a/test/mjsunit/wasm/module-memory.js b/test/mjsunit/wasm/module-memory.js
index ef85eb2..a5e5f42 100644
--- a/test/mjsunit/wasm/module-memory.js
+++ b/test/mjsunit/wasm/module-memory.js
@@ -13,19 +13,27 @@
var builder = new WasmModuleBuilder();
builder.addMemory(1, 1, true);
- builder.addFunction("main", [kAstI32, kAstI32])
+ builder.addFunction("main", kSig_i_i)
.addBody([
- kExprBlock,2,
- kExprLoop,1,
- kExprIf,
+ // main body: while(i) { if(mem[i]) return -1; i -= 4; } return 0;
+ kExprLoop,
+ kExprGetLocal,0,
+ kExprIf,
kExprGetLocal,0,
- kExprBr, 0,
- kExprIfElse,
- kExprI32LoadMem,0,0,kExprGetLocal,0,
- kExprBr,2, kExprI8Const, 255,
- kExprSetLocal,0,
- kExprI32Sub,kExprGetLocal,0,kExprI8Const,4,
- kExprI8Const,0])
+ kExprI32LoadMem,0,0,
+ kExprIf,
+ kExprI8Const,255,
+ kExprReturn, kArity1,
+ kExprEnd,
+ kExprGetLocal,0,
+ kExprI8Const,4,
+ kExprI32Sub,
+ kExprSetLocal,0,
+ kExprBr, kArity1, 1,
+ kExprEnd,
+ kExprEnd,
+ kExprI8Const,0
+ ])
.exportFunc();
return builder.instantiate(null, memory);
@@ -120,14 +128,16 @@
var builder = new WasmModuleBuilder();
builder.addMemory(1, 1, true);
- builder.addFunction("geti", [kAstI32, kAstI32, kAstI32])
+ builder.addFunction("geti", kSig_i_ii)
.addBody([
- kExprI32StoreMem, 0, 0, kExprGetLocal, 0, kExprI32LoadMem, 0, 0, kExprGetLocal, 1
+ kExprGetLocal, 0,
+ kExprGetLocal, 1,
+ kExprI32LoadMem, 0, 0,
+ kExprI32StoreMem, 0, 0
])
.exportFunc();
var module = builder.instantiate();
-
var offset;
function read() { return module.exports.geti(0, offset); }
diff --git a/test/mjsunit/wasm/parallel_compilation.js b/test/mjsunit/wasm/parallel_compilation.js
new file mode 100644
index 0000000..23c5658
--- /dev/null
+++ b/test/mjsunit/wasm/parallel_compilation.js
@@ -0,0 +1,100 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-wasm --wasm-num-compilation-tasks=10
+
+load("test/mjsunit/wasm/wasm-constants.js");
+load("test/mjsunit/wasm/wasm-module-builder.js");
+
+function assertModule(module, memsize) {
+ // Check the module exists.
+ assertFalse(module === undefined);
+ assertFalse(module === null);
+ assertFalse(module === 0);
+ assertEquals("object", typeof module);
+
+ // Check the memory is an ArrayBuffer.
+ var mem = module.exports.memory;
+ assertFalse(mem === undefined);
+ assertFalse(mem === null);
+ assertFalse(mem === 0);
+ assertEquals("object", typeof mem);
+ assertTrue(mem instanceof ArrayBuffer);
+ for (var i = 0; i < 4; i++) {
+ module.exports.memory = 0; // should be ignored
+ assertEquals(mem, module.exports.memory);
+ }
+
+ assertEquals(memsize, module.exports.memory.byteLength);
+}
+
+function assertFunction(module, func) {
+ assertEquals("object", typeof module.exports);
+
+ var exp = module.exports[func];
+ assertFalse(exp === undefined);
+ assertFalse(exp === null);
+ assertFalse(exp === 0);
+ assertEquals("function", typeof exp);
+ return exp;
+}
+
+(function CompileFunctionsTest() {
+
+ var builder = new WasmModuleBuilder();
+
+ builder.addMemory(1, 1, true);
+ for (i = 0; i < 1000; i++) {
+ builder.addFunction("sub" + i, kSig_i_i)
+ .addBody([ // --
+ kExprGetLocal, 0, // --
+ kExprI32Const, i % 61, // --
+ kExprI32Sub]) // --
+ .exportFunc()
+ }
+
+ var module = builder.instantiate();
+ assertModule(module, kPageSize);
+
+ // Check the properties of the functions.
+ for (i = 0; i < 1000; i++) {
+ var sub = assertFunction(module, "sub" + i);
+ assertEquals(33 - (i % 61), sub(33));
+ }
+})();
+
+(function CallFunctionsTest() {
+
+ var builder = new WasmModuleBuilder();
+
+ var f = []
+
+ f[0] = builder.addFunction("add0", kSig_i_ii)
+ .addBody([
+ kExprGetLocal, 0, // --
+ kExprGetLocal, 1, // --
+ kExprI32Add, // --
+ ])
+ .exportFunc()
+
+ builder.addMemory(1, 1, true);
+ for (i = 1; i < 256; i++) {
+ f[i] = builder.addFunction("add" + i, kSig_i_ii)
+ .addBody([ // --
+ kExprGetLocal, 0, // --
+ kExprGetLocal, 1, // --
+ kExprCallFunction, kArity2, f[i >>> 1].index]) // --
+ .exportFunc()
+ }
+ var module = builder.instantiate();
+ assertModule(module, kPageSize);
+
+ // Check the properties of the functions.
+ for (i = 0; i < 256; i++) {
+ var add = assertFunction(module, "add" + i);
+ assertEquals(88, add(33, 55));
+ assertEquals(88888, add(33333, 55555));
+ assertEquals(8888888, add(3333333, 5555555));
+ }
+})();
diff --git a/test/mjsunit/wasm/params.js b/test/mjsunit/wasm/params.js
index 7c2b3d1..180ab1c 100644
--- a/test/mjsunit/wasm/params.js
+++ b/test/mjsunit/wasm/params.js
@@ -17,7 +17,7 @@
var builder = new WasmModuleBuilder();
- builder.addFunction("select", [type, type, type])
+ builder.addFunction("select", makeSig_r_xx(type, type))
.addBody([kExprGetLocal, which])
.exportFunc()
@@ -79,7 +79,7 @@
print("type = " + t + ", which = " + which);
var builder = new WasmModuleBuilder();
- builder.addFunction("select", [t,t,t,t,t,t,t,t,t,t,t])
+ builder.addFunction("select", [10,t,t,t,t,t,t,t,t,t,t,1,t])
.addBody([kExprGetLocal, which])
.exportFunc();
diff --git a/test/mjsunit/wasm/stack.js b/test/mjsunit/wasm/stack.js
index ed05517..a45db94 100644
--- a/test/mjsunit/wasm/stack.js
+++ b/test/mjsunit/wasm/stack.js
@@ -2,39 +2,129 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// clang-format off
// Flags: --expose-wasm
load("test/mjsunit/wasm/wasm-constants.js");
load("test/mjsunit/wasm/wasm-module-builder.js");
-var expected = "Error\n" +
- // The line numbers below will change as this test gains / loses lines..
- " at STACK (stack.js:24:11)\n" + // --
- " at <WASM> (<anonymous>)\n" + // TODO(jfb): wasm stack here.
- " at testStack (stack.js:38:18)\n" + // --
- " at stack.js:40:3"; // --
-
// The stack trace contains file path, only keep "stack.js".
function stripPath(s) {
return s.replace(/[^ (]*stack\.js/g, "stack.js");
}
+function verifyStack(frames, expected) {
+ assertEquals(expected.length, frames.length, "number of frames mismatch");
+ expected.forEach(function(exp, i) {
+ if (exp[1] != "?") {
+ assertEquals(exp[1], frames[i].getFunctionName(),
+ "["+i+"].getFunctionName()");
+ }
+ assertEquals(exp[2], frames[i].getLineNumber(), "["+i+"].getLineNumber()");
+ if (exp[0])
+ assertEquals(exp[3], frames[i].getPosition(),
+ "["+i+"].getPosition()");
+ assertContains(exp[4], frames[i].getFileName(), "["+i+"].getFileName()");
+ var toString;
+ if (exp[0]) {
+ var funName = exp[1] == "?" ? "" : exp[1];
+ toString = funName + " (<WASM>:" + exp[2] + ":" + exp[3] + ")";
+ } else {
+ toString = exp[4] + ":" + exp[2] + ":";
+ }
+ assertContains(toString, frames[i].toString(), "["+i+"].toString()");
+ });
+}
+
+
var stack;
function STACK() {
var e = new Error();
stack = e.stack;
}
-(function testStack() {
- var builder = new WasmModuleBuilder();
+var builder = new WasmModuleBuilder();
- builder.addImport("func", [kAstStmt]);
+builder.addImport("func", kSig_v_v);
- builder.addFunction(undefined, [kAstStmt])
- .addBody([kExprCallImport, 0])
- .exportAs("main");
+builder.addFunction("main", kSig_v_v)
+ .addBody([kExprCallImport, kArity0, 0])
+ .exportAs("main");
- var module = builder.instantiate({func: STACK});
+builder.addFunction("exec_unreachable", kSig_v_v)
+ .addBody([kExprUnreachable])
+ .exportAs("exec_unreachable");
+
+// Make this function unnamed, just to test also this case.
+var mem_oob_func = builder.addFunction(undefined, kSig_v_v)
+ // Access the memory at offset -1, to provoke a trap.
+ .addBody([kExprI32Const, 0x7f, kExprI32LoadMem8S, 0, 0])
+ .exportAs("mem_out_of_bounds");
+
+// Call the mem_out_of_bounds function, in order to have two WASM stack frames.
+builder.addFunction("call_mem_out_of_bounds", kSig_v_v)
+ .addBody([kExprCallFunction, kArity0, mem_oob_func.index])
+ .exportAs("call_mem_out_of_bounds");
+
+var module = builder.instantiate({func: STACK});
+
+(function testSimpleStack() {
+ var expected_string = "Error\n" +
+ // The line numbers below will change as this test gains / loses lines..
+ " at STACK (stack.js:42:11)\n" + // --
+ " at main (<WASM>:0:1)\n" + // --
+ " at testSimpleStack (stack.js:79:18)\n" + // --
+ " at stack.js:81:3"; // --
+
module.exports.main();
- assertEquals(expected, stripPath(stack));
+ assertEquals(expected_string, stripPath(stack));
+})();
+
+// For the remaining tests, collect the Callsite objects instead of just a
+// string:
+Error.prepareStackTrace = function(error, frames) {
+ return frames;
+};
+
+(function testStackFrames() {
+ module.exports.main();
+
+ verifyStack(stack, [
+ // isWasm function line pos file
+ [ false, "STACK", 42, 0, "stack.js"],
+ [ true, "main", 0, 1, null],
+ [ false, "testStackFrames", 90, 0, "stack.js"],
+ [ false, null, 99, 0, "stack.js"]
+ ]);
+})();
+
+(function testWasmUnreachable() {
+ try {
+ module.exports.exec_unreachable();
+ fail("expected wasm exception");
+ } catch (e) {
+ assertContains("unreachable", e.message);
+ verifyStack(e.stack, [
+ // isWasm function line pos file
+ [ true, "exec_unreachable", 1, 1, null],
+ [ false, "testWasmUnreachable", 103, 0, "stack.js"],
+ [ false, null, 114, 0, "stack.js"]
+ ]);
+ }
+})();
+
+(function testWasmMemOutOfBounds() {
+ try {
+ module.exports.call_mem_out_of_bounds();
+ fail("expected wasm exception");
+ } catch (e) {
+ assertContains("out of bounds", e.message);
+ verifyStack(e.stack, [
+ // isWasm function line pos file
+ [ true, "?", 2, 3, null],
+ [ true, "call_mem_out_of_bounds", 3, 1, null],
+ [ false, "testWasmMemOutOfBounds", 118, 0, "stack.js"],
+ [ false, null, 130, 0, "stack.js"]
+ ]);
+ }
})();
diff --git a/test/mjsunit/wasm/stackwalk.js b/test/mjsunit/wasm/stackwalk.js
index 8b8fb7e..5e5a1ef 100644
--- a/test/mjsunit/wasm/stackwalk.js
+++ b/test/mjsunit/wasm/stackwalk.js
@@ -10,13 +10,14 @@
function makeFFI(func) {
var builder = new WasmModuleBuilder();
- var sig_index = builder.addSignature([kAstI32, kAstF64, kAstF64]);
+ var sig_index = builder.addSignature(kSig_i_dd);
builder.addImport("func", sig_index);
builder.addFunction("main", sig_index)
.addBody([
- kExprCallImport, 0, // --
- kExprGetLocal, 0, // --
- kExprGetLocal, 1]) // --
+ kExprGetLocal, 0, // --
+ kExprGetLocal, 1, // --
+ kExprCallImport, kArity2, 0, // --
+ ])
.exportFunc()
return builder.instantiate({func: func}).exports.main;
diff --git a/test/mjsunit/wasm/start-function.js b/test/mjsunit/wasm/start-function.js
index bd4ccf2..3c5707a 100644
--- a/test/mjsunit/wasm/start-function.js
+++ b/test/mjsunit/wasm/start-function.js
@@ -37,19 +37,19 @@
return module;
}
-assertVerifies([kAstStmt], [kExprNop]);
-assertVerifies([kAstI32], [kExprI8Const, 0]);
+assertVerifies(kSig_v_v, [kExprNop]);
+assertVerifies(kSig_i, [kExprI8Const, 0]);
// Arguments aren't allow to start functions.
-assertFails([kAstI32, kAstI32], [kExprGetLocal, 0]);
-assertFails([kAstI32, kAstI32, kAstF32], [kExprGetLocal, 0]);
-assertFails([kAstI32, kAstI32, kAstF32, kAstF64], [kExprGetLocal, 0]);
+assertFails(kSig_i_i, [kExprGetLocal, 0]);
+assertFails(kSig_i_ii, [kExprGetLocal, 0]);
+assertFails(kSig_i_dd, [kExprGetLocal, 0]);
(function testInvalidIndex() {
print("testInvalidIndex");
var builder = new WasmModuleBuilder();
- var func = builder.addFunction("", [kAstStmt])
+ var func = builder.addFunction("", kSig_v_v)
.addBody([kExprNop]);
builder.addStart(func.index + 1);
@@ -62,7 +62,7 @@
print("testTwoStartFuncs");
var builder = new WasmModuleBuilder();
- var func = builder.addFunction("", [kAstStmt])
+ var func = builder.addFunction("", kSig_v_v)
.addBody([kExprNop]);
builder.addExplicitSection([kDeclStartFunction, 0]);
@@ -78,8 +78,8 @@
builder.addMemory(12, 12, true);
- var func = builder.addFunction("", [kAstStmt])
- .addBody([kExprI32StoreMem, 0, 0, kExprI8Const, 0, kExprI8Const, 77]);
+ var func = builder.addFunction("", kSig_v_v)
+ .addBody([kExprI8Const, 0, kExprI8Const, 77, kExprI32StoreMem, 0, 0]);
builder.addStart(func.index);
@@ -98,11 +98,11 @@
}};
var builder = new WasmModuleBuilder();
- var sig_index = builder.addSignature([kAstStmt]);
+ var sig_index = builder.addSignature(kSig_v_v);
builder.addImport("foo", sig_index);
var func = builder.addFunction("", sig_index)
- .addBody([kExprCallImport, 0]);
+ .addBody([kExprCallImport, kArity0, 0]);
builder.addStart(func.index);
diff --git a/test/mjsunit/wasm/test-wasm-module-builder.js b/test/mjsunit/wasm/test-wasm-module-builder.js
index 50797d0..969b550 100644
--- a/test/mjsunit/wasm/test-wasm-module-builder.js
+++ b/test/mjsunit/wasm/test-wasm-module-builder.js
@@ -12,7 +12,7 @@
(function BasicTest() {
var module = new WasmModuleBuilder();
module.addMemory(1, 2, false);
- module.addFunction("foo", [kAstI32])
+ module.addFunction("foo", kSig_i)
.addBody([kExprI8Const, 11])
.exportAs("blarg");
@@ -23,9 +23,9 @@
(function ImportTest() {
var module = new WasmModuleBuilder();
- var index = module.addImport("print", [kAstStmt, kAstI32]);
- module.addFunction("foo", [kAstStmt])
- .addBody([kExprCallImport, index, kExprI8Const, 13])
+ var index = module.addImport("print", makeSig_v_x(kAstI32));
+ module.addFunction("foo", kSig_v_v)
+ .addBody([kExprI8Const, 13, kExprCallImport, kArity1, index])
.exportAs("main");
var buffer = module.toBuffer(debug);
@@ -36,9 +36,9 @@
(function LocalsTest() {
var module = new WasmModuleBuilder();
- module.addFunction(undefined, [kAstI32, kAstI32])
+ module.addFunction(undefined, kSig_i_i)
.addLocals({i32_count: 1})
- .addBody([kExprSetLocal, 1, kExprGetLocal, 0])
+ .addBody([kExprGetLocal, 0, kExprSetLocal, 1])
.exportAs("main");
var buffer = module.toBuffer(debug);
@@ -58,9 +58,9 @@
for (p of types) {
var module = new WasmModuleBuilder();
- module.addFunction(undefined, [p.type, p.type])
+ module.addFunction(undefined, makeSig_r_x(p.type, p.type))
.addLocals(p.locals)
- .addBody([kExprSetLocal, 1, kExprGetLocal, 0])
+ .addBody([kExprGetLocal, 0, kExprSetLocal, 1])
.exportAs("main");
var buffer = module.toBuffer(debug);
@@ -72,10 +72,10 @@
(function CallTest() {
var module = new WasmModuleBuilder();
- module.addFunction("add", [kAstI32, kAstI32, kAstI32])
- .addBody([kExprI32Add, kExprGetLocal, 0, kExprGetLocal, 1]);
- module.addFunction("main", [kAstI32, kAstI32, kAstI32])
- .addBody([kExprCallFunction, 0, kExprGetLocal, 0, kExprGetLocal, 1])
+ module.addFunction("add", kSig_i_ii)
+ .addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprI32Add]);
+ module.addFunction("main", kSig_i_ii)
+ .addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprCallFunction, kArity2, 0])
.exportAs("main");
var instance = module.instantiate();
@@ -85,11 +85,11 @@
(function IndirectCallTest() {
var module = new WasmModuleBuilder();
- module.addFunction("add", [kAstI32, kAstI32, kAstI32])
- .addBody([kExprI32Add, kExprGetLocal, 0, kExprGetLocal, 1]);
- module.addFunction("main", [kAstI32, kAstI32, kAstI32, kAstI32])
- .addBody([kExprCallIndirect, 0, kExprGetLocal,
- 0, kExprGetLocal, 1, kExprGetLocal, 2])
+ module.addFunction("add", kSig_i_ii)
+ .addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprI32Add]);
+ module.addFunction("main", kSig_i_iii)
+ .addBody([kExprGetLocal,
+ 0, kExprGetLocal, 1, kExprGetLocal, 2, kExprCallIndirect, kArity2, 0])
.exportAs("main");
module.appendToFunctionTable([0]);
@@ -102,8 +102,8 @@
(function DataSegmentTest() {
var module = new WasmModuleBuilder();
module.addMemory(1, 1, false);
- module.addFunction("load", [kAstI32, kAstI32])
- .addBody([kExprI32LoadMem, 0, 0, kExprGetLocal, 0])
+ module.addFunction("load", kSig_i_i)
+ .addBody([kExprGetLocal, 0, kExprI32LoadMem, 0, 0])
.exportAs("load");
module.addDataSegment(0, [9, 9, 9, 9], true);
@@ -116,7 +116,7 @@
(function BasicTestWithUint8Array() {
var module = new WasmModuleBuilder();
module.addMemory(1, 2, false);
- module.addFunction("foo", [kAstI32])
+ module.addFunction("foo", kSig_i)
.addBody([kExprI8Const, 17])
.exportAs("blarg");
@@ -141,9 +141,9 @@
(function ImportTestTwoLevel() {
var module = new WasmModuleBuilder();
- var index = module.addImportWithModule("mod", "print", [kAstStmt, kAstI32]);
- module.addFunction("foo", [kAstStmt])
- .addBody([kExprCallImport, index, kExprI8Const, 19])
+ var index = module.addImportWithModule("mod", "print", makeSig_v_x(kAstI32));
+ module.addFunction("foo", kSig_v_v)
+ .addBody([kExprI8Const, 19, kExprCallImport, kArity1, index])
.exportAs("main");
var buffer = module.toBuffer(debug);
diff --git a/test/mjsunit/wasm/trap-location.js b/test/mjsunit/wasm/trap-location.js
new file mode 100644
index 0000000..5e3661d
--- /dev/null
+++ b/test/mjsunit/wasm/trap-location.js
@@ -0,0 +1,78 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-wasm
+
+load("test/mjsunit/wasm/wasm-constants.js");
+load("test/mjsunit/wasm/wasm-module-builder.js");
+
+// Collect the Callsite objects instead of just a string:
+Error.prepareStackTrace = function(error, frames) {
+ return frames;
+};
+
+var builder = new WasmModuleBuilder();
+
+var sig_index = builder.addSignature(kSig_i_v)
+
+// Build a function to resemble this code:
+// if (idx < 2) {
+// return load(-2 / idx);
+// } else if (idx == 2) {
+// unreachable;
+// } else {
+// return call_indirect(idx);
+// }
+// There are four different traps which are triggered by different input values:
+// (0) division by zero; (1) mem oob; (2) unreachable; (3) invalid call target
+// Each of them also has a different location where it traps.
+builder.addFunction("main", kSig_i_i)
+ .addBody([
+ // offset 1
+ kExprBlock,
+ kExprGetLocal, 0,
+ kExprI32Const, 2,
+ kExprI32LtU,
+ kExprIf,
+ // offset 8
+ kExprI32Const, 0x7e /* -2 */,
+ kExprGetLocal, 0,
+ kExprI32DivU,
+ // offset 13
+ kExprI32LoadMem, 0, 0,
+ kExprBr, 1, 1,
+ kExprEnd,
+ // offset 20
+ kExprGetLocal, 0,
+ kExprI32Const, 2,
+ kExprI32Eq,
+ kExprIf,
+ kExprUnreachable,
+ kExprEnd,
+ // offset 28
+ kExprGetLocal, 0,
+ kExprCallIndirect, kArity0, sig_index,
+ kExprEnd,
+ ])
+ .exportAs("main");
+
+var module = builder.instantiate();
+
+function testWasmTrap(value, reason, position) {
+ try {
+ module.exports.main(value);
+ fail("expected wasm exception");
+ } catch (e) {
+ assertEquals(kTrapMsgs[reason], e.message, "trap reason");
+ assertEquals(3, e.stack.length, "number of frames");
+ assertEquals(0, e.stack[0].getLineNumber(), "wasmFunctionIndex");
+ assertEquals(position, e.stack[0].getPosition(), "position");
+ }
+}
+
+// The actual tests:
+testWasmTrap(0, kTrapDivByZero, 12);
+testWasmTrap(1, kTrapMemOutOfBounds, 13);
+testWasmTrap(2, kTrapUnreachable, 26);
+testWasmTrap(3, kTrapFuncInvalid, 30);
diff --git a/test/mjsunit/wasm/unicode-validation.js b/test/mjsunit/wasm/unicode-validation.js
new file mode 100644
index 0000000..b2e4603
--- /dev/null
+++ b/test/mjsunit/wasm/unicode-validation.js
@@ -0,0 +1,121 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-wasm
+
+load("test/mjsunit/wasm/wasm-constants.js");
+load("test/mjsunit/wasm/wasm-module-builder.js");
+
+function toByteArray(s) {
+ var arr = [];
+ for (var i = 0; i < s.length; ++i) {
+ arr.push(s.charCodeAt(i) & 0xff);
+ }
+ return arr;
+}
+
+function toString(arr) {
+ if (typeof arr === "string") return arr;
+ var s = "";
+ for (var b of arr) s += String.fromCharCode(b);
+ return s;
+}
+
+function toUTF8(arr) {
+ if (typeof arr === "string" || arr === undefined) return arr;
+ return decodeURIComponent(escape(toString(arr)));
+}
+
+function isValidUtf8(arr) {
+ if (typeof arr === "string" || arr === undefined) return true;
+ try {
+ var s = toUTF8(arr);
+ for (var i = 0; i < s.length; ++i)
+ if ((s.charCodeAt(i) & 0xfffe) == 0xfffe)
+ return false;
+ return true;
+ } catch (e) {
+ if (e instanceof URIError) return false;
+ throw e;
+ }
+}
+
+function checkImportsAndExports(imported_module_name, imported_function_name,
+ internal_function_name, exported_function_name, shouldThrow) {
+ var builder = new WasmModuleBuilder();
+
+ builder.addImportWithModule(imported_module_name, imported_function_name,
+ kSig_v_v);
+
+ builder.addFunction(internal_function_name, kSig_v_v)
+ .addBody([kExprCallImport, kArity0, 0])
+ .exportAs(exported_function_name);
+
+ // sanity check: does javascript agree with out shouldThrow annotation?
+ assertEquals(shouldThrow,
+ !isValidUtf8(imported_module_name) ||
+ !isValidUtf8(imported_function_name) ||
+ !isValidUtf8(exported_function_name),
+ "JavaScript does not agree with our shouldThrow expectation");
+
+ if (!shouldThrow) {
+ imported_module_name = toUTF8(imported_module_name);
+ imported_function_name = toUTF8(imported_function_name);
+ }
+
+ var ffi = new Object();
+ if (imported_function_name === undefined) {
+ ffi[imported_module_name] = function() { };
+ } else {
+ ffi[imported_module_name] = new Object();
+ ffi[imported_module_name][imported_function_name] = function() { };
+ }
+
+ var hasThrown = true;
+ try {
+ builder.instantiate(ffi);
+ hasThrown = false;
+ } catch (err) {
+ if (!shouldThrow) print(err);
+ assertTrue(shouldThrow, "Should not throw error on valid names");
+ assertContains("UTF-8", err.toString());
+ }
+ assertEquals(shouldThrow, hasThrown,
+ "Should throw validation error on invalid names");
+}
+
+function checkImportedModuleName(name, shouldThrow) {
+ checkImportsAndExports(name, "imp", "func", undefined, shouldThrow);
+}
+
+function checkImportedFunctionName(name, shouldThrow) {
+ checkImportsAndExports("module", name, "func", "func", shouldThrow);
+}
+
+function checkExportedFunctionName(name, shouldThrow) {
+ checkImportsAndExports("module", "func", "func", name, shouldThrow);
+}
+
+function checkInternalFunctionName(name) {
+ checkImportsAndExports("module", "func", name, "func", false);
+}
+
+function checkAll(name, shouldThrow) {
+ checkImportedModuleName(name, shouldThrow);
+ checkImportedFunctionName(name, shouldThrow);
+ checkExportedFunctionName(name, shouldThrow);
+ checkInternalFunctionName(name);
+}
+
+checkAll("ascii", false);
+checkAll("some math: (½)² = ¼", false);
+checkAll("中国历史系列条目\n北", false);
+checkAll(toByteArray("\xef\xb7\x8f"), false);
+checkAll(toByteArray("a\xc2\x81\xe1\x80\xbf\xf1\x80\xa0\xbf"), false);
+checkAll(toByteArray("\xff"), true);
+checkAll(toByteArray("\xed\xa0\x8f"), true); // surrogate code points
+checkAll(toByteArray("\xe0\x82\x80"), true); // overlong sequence
+checkAll(toByteArray("\xf4\x90\x80\x80"), true); // beyond limit: U+110000
+checkAll(toByteArray("\xef\xbf\xbe"), true); // non-character; U+FFFE
+checkAll(toByteArray("with\x00null"), false);
diff --git a/test/mjsunit/wasm/unreachable.js b/test/mjsunit/wasm/unreachable.js
index 3e2dffb..d77b53e 100644
--- a/test/mjsunit/wasm/unreachable.js
+++ b/test/mjsunit/wasm/unreachable.js
@@ -9,7 +9,7 @@
var main = (function () {
var builder = new WasmModuleBuilder();
- builder.addFunction("main", [kAstStmt])
+ builder.addFunction("main", kSig_v_v)
.addBody([kExprUnreachable])
.exportAs("main");
@@ -23,4 +23,4 @@
print("correctly caught: " + e);
exception = e;
}
-assertEquals("unreachable", exception);
+assertEquals("unreachable", exception.message);
diff --git a/test/mjsunit/wasm/verify-function-simple.js b/test/mjsunit/wasm/verify-function-simple.js
index aa5c676..31c23a6 100644
--- a/test/mjsunit/wasm/verify-function-simple.js
+++ b/test/mjsunit/wasm/verify-function-simple.js
@@ -8,9 +8,9 @@
try {
var data = bytes(
- 0, kAstStmt, // signature
- kDeclNoLocals, // --
- kExprNop // body
+ kWasmFunctionTypeForm, 0, kAstStmt, // signature
+ kDeclNoLocals, // --
+ kExprNop // body
);
Wasm.verifyFunction(data);
@@ -23,9 +23,9 @@
var threw = false;
try {
var data = bytes(
- 0, kAstI32, // signature
- kDeclNoLocals, // --
- kExprBlock, 2, kExprNop, kExprNop // body
+ kWasmFunctionTypeForm, 0, 1, kAstI32, // signature
+ kDeclNoLocals, // --
+ kExprBlock, kExprNop, kExprNop, kExprEnd // body
);
Wasm.verifyFunction(data);
diff --git a/test/mjsunit/wasm/wasm-constants.js b/test/mjsunit/wasm/wasm-constants.js
index cc620bb..389383e 100644
--- a/test/mjsunit/wasm/wasm-constants.js
+++ b/test/mjsunit/wasm/wasm-constants.js
@@ -21,7 +21,7 @@
var kWasmH2 = 0x73;
var kWasmH3 = 0x6d;
-var kWasmV0 = 10;
+var kWasmV0 = 11;
var kWasmV1 = 0;
var kWasmV2 = 0;
var kWasmV3 = 0;
@@ -65,10 +65,16 @@
var kDeclFunctionBodies = 0x0b;
var kDeclNames = 0x0c;
+var kArity0 = 0;
+var kArity1 = 1;
+var kArity2 = 2;
+var kArity3 = 3;
+var kWasmFunctionTypeForm = 0x40;
+
var section_names = [
- "memory", "signatures", "functions", "globals", "data_segments",
- "function_table", "end", "start_function", "import_table", "export_table",
- "function_signatures", "function_bodies", "names"];
+ "memory", "type", "old_function", "global", "data",
+ "table", "end", "start", "import", "export",
+ "function", "code", "name"];
// Function declaration flags
var kDeclFunctionName = 0x01;
@@ -83,31 +89,60 @@
var kAstF32 = 3;
var kAstF64 = 4;
+// Useful signatures
+var kSig_i = [0, 1, kAstI32];
+var kSig_d = [0, 1, kAstF64];
+var kSig_i_i = [1, kAstI32, 1, kAstI32];
+var kSig_i_ii = [2, kAstI32, kAstI32, 1, kAstI32];
+var kSig_i_iii = [3, kAstI32, kAstI32, kAstI32, 1, kAstI32];
+var kSig_d_dd = [2, kAstF64, kAstF64, 1, kAstF64];
+var kSig_l_ll = [2, kAstI64, kAstI64, 1, kAstI64];
+var kSig_i_dd = [2, kAstF64, kAstF64, 1, kAstI32];
+var kSig_v_v = [0, 0];
+var kSig_i_v = [0, 1, kAstI32];
+
+function makeSig_v_xx(x) {
+ return [2, x, x, 0];
+}
+
+function makeSig_v_x(x) {
+ return [1, x, 0];
+}
+
+function makeSig_r_xx(r, x) {
+ return [2, x, x, 1, r];
+}
+
+function makeSig_r_x(r, x) {
+ return [1, x, 1, r];
+}
+
// Opcodes
var kExprNop = 0x00;
var kExprBlock = 0x01;
var kExprLoop = 0x02;
var kExprIf = 0x03;
-var kExprIfElse = 0x04;
+var kExprElse = 0x04;
var kExprSelect = 0x05;
var kExprBr = 0x06;
var kExprBrIf = 0x07;
-var kExprTableSwitch = 0x08;
-var kExprReturn = 0x14;
-var kExprUnreachable = 0x15;
+var kExprBrTable = 0x08;
+var kExprReturn = 0x09;
+var kExprUnreachable = 0x0a;
+var kExprEnd = 0x0f;
-var kExprI8Const = 0x09;
-var kExprI32Const = 0x0a;
-var kExprI64Const = 0x0b;
-var kExprF64Const = 0x0c;
-var kExprF32Const = 0x0d;
-var kExprGetLocal = 0x0e;
-var kExprSetLocal = 0x0f;
-var kExprLoadGlobal = 0x10;
-var kExprStoreGlobal = 0x11;
-var kExprCallFunction = 0x12;
-var kExprCallIndirect = 0x13;
-var kExprCallImport = 0x1F;
+var kExprI32Const = 0x10;
+var kExprI64Const = 0x11;
+var kExprF64Const = 0x12;
+var kExprF32Const = 0x13;
+var kExprGetLocal = 0x14;
+var kExprSetLocal = 0x15;
+var kExprCallFunction = 0x16;
+var kExprCallIndirect = 0x17;
+var kExprCallImport = 0x18;
+var kExprI8Const = 0xcb;
+var kExprLoadGlobal = 0xcc;
+var kExprStoreGlobal = 0xcd;
var kExprI32LoadMem8S = 0x20;
var kExprI32LoadMem8U = 0x21;
@@ -290,8 +325,8 @@
}
threwException = false;
} catch (e) {
- assertEquals("string", typeof e);
- assertEquals(kTrapMsgs[trap], e);
+ assertEquals("object", typeof e);
+ assertEquals(kTrapMsgs[trap], e.message);
// Success.
return;
}
diff --git a/test/mjsunit/wasm/wasm-module-builder.js b/test/mjsunit/wasm/wasm-module-builder.js
index e1d9963..bfc4460 100644
--- a/test/mjsunit/wasm/wasm-module-builder.js
+++ b/test/mjsunit/wasm/wasm-module-builder.js
@@ -53,7 +53,7 @@
return this;
}
-// Add a signature; format is [rettype, param0, param1, ...]
+// Add a signature; format is [param_count, param0, param1, ..., retcount, ret0]
WasmModuleBuilder.prototype.addSignature = function(sig) {
// TODO: canonicalize signatures?
this.signatures.push(sig);
@@ -75,9 +75,7 @@
}
WasmModuleBuilder.prototype.addImport = function(name, sig) {
- var sig_index = (typeof sig) == "number" ? sig : this.addSignature(sig);
- this.imports.push({module: name, name: undefined, sig_index: sig_index});
- return this.imports.length - 1;
+ this.addImportWithModule(name, undefined, sig);
}
WasmModuleBuilder.prototype.addDataSegment = function(addr, data, init) {
@@ -107,9 +105,19 @@
}
function emit_string(bytes, string) {
- emit_varint(bytes, string.length);
- for (var i = 0; i < string.length; i++) {
- emit_u8(bytes, string.charCodeAt(i));
+ // When testing illegal names, we pass a byte array directly.
+ if (string instanceof Array) {
+ emit_varint(bytes, string.length);
+ emit_bytes(bytes, string);
+ return;
+ }
+
+ // This is the hacky way to convert a JavaScript scring to a UTF8 encoded
+ // string only containing single-byte characters.
+ var string_utf8 = unescape(encodeURIComponent(string));
+ emit_varint(bytes, string_utf8.length);
+ for (var i = 0; i < string_utf8.length; i++) {
+ emit_u8(bytes, string_utf8.charCodeAt(i));
}
}
@@ -132,12 +140,14 @@
}
function emit_section(bytes, section_code, content_generator) {
- // Start the section in a temporary buffer: its full length isn't know yet.
+ // Emit section name.
+ emit_string(bytes, section_names[section_code]);
+ // Emit the section to a temporary buffer: its full length isn't know yet.
var tmp_bytes = [];
- emit_string(tmp_bytes, section_names[section_code]);
content_generator(tmp_bytes);
- // Now that we know the section length, emit it and copy the section.
+ // Emit section length.
emit_varint(bytes, tmp_bytes.length);
+ // Copy the temporary buffer.
Array.prototype.push.apply(bytes, tmp_bytes);
}
@@ -149,24 +159,13 @@
var wasm = this;
- // Add memory section
- if (wasm.memory != undefined) {
- if (debug) print("emitting memory @ " + bytes.length);
- emit_section(bytes, kDeclMemory, function(bytes) {
- emit_varint(bytes, wasm.memory.min);
- emit_varint(bytes, wasm.memory.max);
- emit_u8(bytes, wasm.memory.exp ? 1 : 0);
- });
- }
-
// Add signatures section
if (wasm.signatures.length > 0) {
if (debug) print("emitting signatures @ " + bytes.length);
emit_section(bytes, kDeclSignatures, function(bytes) {
emit_varint(bytes, wasm.signatures.length);
for (sig of wasm.signatures) {
- var params = sig.length - 1;
- emit_varint(bytes, params);
+ emit_u8(bytes, kWasmFunctionTypeForm);
for (var j = 0; j < sig.length; j++) {
emit_u8(bytes, sig[j]);
}
@@ -187,7 +186,7 @@
});
}
- // Add functions section
+ // Add functions declarations
var names = false;
var exports = 0;
if (wasm.functions.length > 0) {
@@ -206,6 +205,54 @@
}
});
+ }
+
+ // Add function table.
+ if (wasm.function_table.length > 0) {
+ if (debug) print("emitting function table @ " + bytes.length);
+ emit_section(bytes, kDeclFunctionTable, function(bytes) {
+ emit_varint(bytes, wasm.function_table.length);
+ for (index of wasm.function_table) {
+ emit_varint(bytes, index);
+ }
+ });
+ }
+
+ // Add memory section
+ if (wasm.memory != undefined) {
+ if (debug) print("emitting memory @ " + bytes.length);
+ emit_section(bytes, kDeclMemory, function(bytes) {
+ emit_varint(bytes, wasm.memory.min);
+ emit_varint(bytes, wasm.memory.max);
+ emit_u8(bytes, wasm.memory.exp ? 1 : 0);
+ });
+ }
+
+
+ // Add export table.
+ if (exports > 0) {
+ if (debug) print("emitting exports @ " + bytes.length);
+ emit_section(bytes, kDeclExportTable, function(bytes) {
+ emit_varint(bytes, exports);
+ for (func of wasm.functions) {
+ for (exp of func.exports) {
+ emit_varint(bytes, func.index);
+ emit_string(bytes, exp);
+ }
+ }
+ });
+ }
+
+ // Add start function section.
+ if (wasm.start_index != undefined) {
+ if (debug) print("emitting start function @ " + bytes.length);
+ emit_section(bytes, kDeclStartFunction, function(bytes) {
+ emit_varint(bytes, wasm.start_index);
+ });
+ }
+
+ // Add function bodies.
+ if (wasm.functions.length > 0) {
// emit function bodies
if (debug) print("emitting function bodies @ " + bytes.length);
emit_section(bytes, kDeclFunctionBodies, function(bytes) {
@@ -244,50 +291,7 @@
});
}
- // emit function names
- if (has_names) {
- if (debug) print("emitting names @ " + bytes.length);
- emit_section(bytes, kDeclNames, function(bytes) {
- emit_varint(bytes, wasm.functions.length);
- for (func of wasm.functions) {
- var name = func.name == undefined ? "" : func.name;
- emit_string(bytes, name);
- emit_u8(bytes, 0); // local names count == 0
- }
- });
- }
-
- // Add start function section.
- if (wasm.start_index != undefined) {
- if (debug) print("emitting start function @ " + bytes.length);
- emit_section(bytes, kDeclStartFunction, function(bytes) {
- emit_varint(bytes, wasm.start_index);
- });
- }
-
- if (wasm.function_table.length > 0) {
- if (debug) print("emitting function table @ " + bytes.length);
- emit_section(bytes, kDeclFunctionTable, function(bytes) {
- emit_varint(bytes, wasm.function_table.length);
- for (index of wasm.function_table) {
- emit_varint(bytes, index);
- }
- });
- }
-
- if (exports > 0) {
- if (debug) print("emitting exports @ " + bytes.length);
- emit_section(bytes, kDeclExportTable, function(bytes) {
- emit_varint(bytes, exports);
- for (func of wasm.functions) {
- for (exp of func.exports) {
- emit_varint(bytes, func.index);
- emit_string(bytes, exp);
- }
- }
- });
- }
-
+ // Add data segments.
if (wasm.data_segments.length > 0) {
if (debug) print("emitting data segments @ " + bytes.length);
emit_section(bytes, kDeclDataSegments, function(bytes) {
@@ -300,12 +304,25 @@
});
}
- // Emit any explicitly added sections
+ // Add any explicitly added sections
for (exp of wasm.explicit) {
if (debug) print("emitting explicit @ " + bytes.length);
emit_bytes(bytes, exp);
}
+ // Add function names.
+ if (has_names) {
+ if (debug) print("emitting names @ " + bytes.length);
+ emit_section(bytes, kDeclNames, function(bytes) {
+ emit_varint(bytes, wasm.functions.length);
+ for (func of wasm.functions) {
+ var name = func.name == undefined ? "" : func.name;
+ emit_string(bytes, name);
+ emit_u8(bytes, 0); // local names count == 0
+ }
+ });
+ }
+
// End the module.
if (debug) print("emitting end @ " + bytes.length);
emit_section(bytes, kDeclEnd, function(bytes) {});
diff --git a/test/mjsunit/wasm/wasm-object-api.js b/test/mjsunit/wasm/wasm-object-api.js
index 2f25c66..96088b8 100644
--- a/test/mjsunit/wasm/wasm-object-api.js
+++ b/test/mjsunit/wasm/wasm-object-api.js
@@ -10,3 +10,4 @@
assertEquals("function", typeof Wasm.verifyFunction);
assertEquals("function", typeof Wasm.instantiateModule);
assertEquals("function", typeof Wasm.instantiateModuleFromAsm);
+assertFalse(undefined == Wasm.experimentalVersion);