v8/test/mjsunit/strong/implicit-conversions.js
conradw ae7ce701ae [strong] Disallow implicit conversions for binary arithmetic operations
Implements the strong mode proposal's restrictions on
implicit conversions for binary arithmetic operations, not
including the + special case. Adds some infrastructure
for future implementation of the restrictions for other
operators.

BUG=v8:3956
LOG=N

Review URL: https://codereview.chromium.org/1092353002

Cr-Commit-Position: refs/heads/master@{#28045}
2015-04-24 12:32:41 +00:00

165 lines
3.6 KiB
JavaScript

// 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: --strong-mode --allow-natives-syntax
'use strict';
// TODO(conradw): Implement other strong operators
let strong_arith = [
"-",
"*",
"/",
"%"
]
let nonnumber_values = [
"{}",
"'foo'",
"(function(){})",
"[]",
"'0'",
"'NaN'",
"(class Foo {})"
]
let number_values = [
"0",
"(-0)",
"1",
"0.79",
"(-0.79)",
"4294967295",
"4294967296",
"(-4294967295)",
"(-4294967296)",
"9999999999999",
"(-9999999999999)",
"1.5e10",
"(-1.5e10)",
"0xFFF",
"(-0xFFF)",
"NaN",
"Infinity",
"(-Infinity)"
]
function sub_strong(x, y) {
"use strong";
let v = x - y;
return v;
}
function mul_strong(x, y) {
"use strong";
let v = x * y;
return v;
}
function div_strong(x, y) {
"use strong";
let v = x / y;
return v;
}
function mod_strong(x, y) {
"use strong";
let v = x % y;
return v;
}
let strong_funcs = [sub_strong, mul_strong, div_strong, mod_strong];
function inline_sub_strong(x, y) {
"use strong";
let v = x - y;
return v;
}
function inline_outer(x, y) {
return inline_sub_strong(x, y);
}
function inline_sub(x, y) {
let v = x - y;
return v;
}
function inline_outer_strong(x, y) {
"use strong";
return inline_sub(x, y);
}
for (let op of strong_arith) {
for (let left of number_values) {
for (let right of number_values) {
let expr = "(" + left + op + right + ")";
assertEquals(eval(expr), eval("'use strong';" + expr));
assertDoesNotThrow("'use strong'; " + expr + ";");
assertDoesNotThrow("'use strong'; let v = " + expr + ";");
}
}
for (let left of number_values) {
for (let right of nonnumber_values) {
let expr = "(" + left + op + right + ")";
assertDoesNotThrow("'use strict'; " + expr + ";");
assertDoesNotThrow("'use strict'; let v = " + expr + ";");
assertThrows("'use strong'; " + expr + ";", TypeError);
assertThrows("'use strong'; let v = " + expr + ";", TypeError);
}
}
for (let left of nonnumber_values) {
for (let right of number_values.concat(nonnumber_values)) {
let expr = "(" + left + op + right + ")";
assertDoesNotThrow("'use strict'; " + expr + ";");
assertDoesNotThrow("'use strict'; let v = " + expr + ";");
assertThrows("'use strong'; " + expr + ";", TypeError);
assertThrows("'use strong'; let v = " + expr + ";", TypeError);
}
}
}
for (let func of strong_funcs) {
let a = func(4, 5);
let b = func(4, 5);
assertTrue(a === b);
%OptimizeFunctionOnNextCall(func);
let c = func(4, 5);
assertOptimized(func);
assertTrue(b === c);
%DeoptimizeFunction(func);
let d = func(4, 5);
assertTrue(c === d);
%DeoptimizeFunction(func);
%ClearFunctionTypeFeedback(func);
}
for (let func of strong_funcs) {
try {
let a = func(2, 3);
let b = func(2, 3);
assertTrue(a === b);
%OptimizeFunctionOnNextCall(func);
let c = func(2, "foo");
assertUnreachable();
} catch(e) {
assertTrue(e instanceof TypeError);
assertUnoptimized(func);
assertThrows(function(){func(2, "foo");}, TypeError);
assertDoesNotThrow(function(){func(2, 3);});
}
}
assertThrows(function(){inline_outer(1, {})}, TypeError);
for (var i = 0; i < 100; i++) {
inline_outer(1, 2);
}
assertThrows(function(){inline_outer(1, {})}, TypeError);
assertDoesNotThrow(function(){inline_outer_strong(1, {})});
for (var i = 0; i < 100; i++) {
inline_outer_strong(1, 2);
}
assertDoesNotThrow(function(){inline_outer_strong(1, {})});