[es6] Initial support for let/const bindings in sloppy mode
Allow let in sloppy mode with --harmony-sloppy Allow ES'15 const in sloppy mode with --harmony-sloppy --no-legacy-const Functions in block are not done yet. They are only let bound in the block at this point. BUG=v8:3305, v8:2198 LOG=N R=littledan@chromium.org, rossberg@chromium.org, adamk@chromium.org Review URL: https://codereview.chromium.org/1219853004 Cr-Commit-Position: refs/heads/master@{#29536}
This commit is contained in:
parent
7fc183af06
commit
3b1aabc960
@ -1387,7 +1387,7 @@ Statement* Parser::ParseStatementListItem(bool* ok) {
|
||||
case Token::VAR:
|
||||
return ParseVariableStatement(kStatementListItem, NULL, ok);
|
||||
case Token::LET:
|
||||
if (is_strict(language_mode())) {
|
||||
if (allow_let()) {
|
||||
return ParseVariableStatement(kStatementListItem, NULL, ok);
|
||||
}
|
||||
break;
|
||||
@ -2049,7 +2049,7 @@ Variable* Parser::Declare(Declaration* declaration,
|
||||
// because the var declaration is hoisted to the function scope where 'x'
|
||||
// is already bound.
|
||||
DCHECK(IsDeclaredVariableMode(var->mode()));
|
||||
if (is_strict(language_mode())) {
|
||||
if (is_strict(language_mode()) || allow_harmony_sloppy()) {
|
||||
// In harmony we treat re-declarations as early errors. See
|
||||
// ES5 16 for a definition of early errors.
|
||||
if (declaration_kind == DeclarationDescriptor::NORMAL) {
|
||||
@ -2207,7 +2207,7 @@ Statement* Parser::ParseFunctionDeclaration(
|
||||
VariableMode mode =
|
||||
is_strong(language_mode())
|
||||
? CONST
|
||||
: is_strict(language_mode()) &&
|
||||
: (is_strict(language_mode()) || allow_harmony_sloppy()) &&
|
||||
!(scope_->is_script_scope() || scope_->is_eval_scope() ||
|
||||
scope_->is_function_scope())
|
||||
? LET
|
||||
@ -2287,7 +2287,7 @@ Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names,
|
||||
|
||||
|
||||
Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) {
|
||||
if (is_strict(language_mode())) {
|
||||
if (is_strict(language_mode()) || allow_harmony_sloppy()) {
|
||||
return ParseScopedBlock(labels, ok);
|
||||
}
|
||||
|
||||
@ -2439,14 +2439,14 @@ void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
|
||||
parsing_result->descriptor.init_op = Token::INIT_CONST_LEGACY;
|
||||
++use_counts_[v8::Isolate::kLegacyConst];
|
||||
} else {
|
||||
DCHECK(is_strict(language_mode()));
|
||||
DCHECK(is_strict(language_mode()) || allow_harmony_sloppy());
|
||||
DCHECK(var_context != kStatement);
|
||||
parsing_result->descriptor.mode = CONST;
|
||||
parsing_result->descriptor.init_op = Token::INIT_CONST;
|
||||
}
|
||||
parsing_result->descriptor.is_const = true;
|
||||
parsing_result->descriptor.needs_init = true;
|
||||
} else if (peek() == Token::LET && is_strict(language_mode())) {
|
||||
} else if (peek() == Token::LET && allow_let()) {
|
||||
Consume(Token::LET);
|
||||
DCHECK(var_context != kStatement);
|
||||
parsing_result->descriptor.mode = LET;
|
||||
@ -3498,7 +3498,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
||||
DeclarationParsingResult parsing_result;
|
||||
if (peek() != Token::SEMICOLON) {
|
||||
if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) ||
|
||||
(peek() == Token::LET && is_strict(language_mode()))) {
|
||||
(peek() == Token::LET && allow_let())) {
|
||||
ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK);
|
||||
is_const = parsing_result.descriptor.mode == CONST;
|
||||
|
||||
@ -3973,6 +3973,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
||||
Scope* original_declaration_scope = original_scope_->DeclarationScope();
|
||||
Scope* scope = function_type == FunctionLiteral::DECLARATION &&
|
||||
is_sloppy(language_mode()) &&
|
||||
!allow_harmony_sloppy() &&
|
||||
(original_scope_ == original_declaration_scope ||
|
||||
declaration_scope != original_declaration_scope)
|
||||
? NewScope(declaration_scope, FUNCTION_SCOPE, kind)
|
||||
@ -4030,11 +4031,12 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
||||
Variable* fvar = NULL;
|
||||
Token::Value fvar_init_op = Token::INIT_CONST_LEGACY;
|
||||
if (function_type == FunctionLiteral::NAMED_EXPRESSION) {
|
||||
if (is_strict(language_mode())) {
|
||||
bool use_strict_const = is_strict(language_mode()) ||
|
||||
(!allow_legacy_const() && allow_harmony_sloppy());
|
||||
if (use_strict_const) {
|
||||
fvar_init_op = Token::INIT_CONST;
|
||||
}
|
||||
VariableMode fvar_mode =
|
||||
is_strict(language_mode()) ? CONST : CONST_LEGACY;
|
||||
VariableMode fvar_mode = use_strict_const ? CONST : CONST_LEGACY;
|
||||
DCHECK(function_name != NULL);
|
||||
fvar = new (zone())
|
||||
Variable(scope_, function_name, fvar_mode, Variable::NORMAL,
|
||||
|
@ -197,7 +197,7 @@ PreParser::Statement PreParser::ParseStatementListItem(bool* ok) {
|
||||
}
|
||||
break;
|
||||
case Token::LET:
|
||||
if (is_strict(language_mode())) {
|
||||
if (allow_let()) {
|
||||
return ParseVariableStatement(kStatementListItem, ok);
|
||||
}
|
||||
break;
|
||||
@ -456,7 +456,7 @@ PreParser::Statement PreParser::ParseBlock(bool* ok) {
|
||||
Expect(Token::LBRACE, CHECK_OK);
|
||||
Statement final = Statement::Default();
|
||||
while (peek() != Token::RBRACE) {
|
||||
if (is_strict(language_mode())) {
|
||||
if (is_strict(language_mode()) || allow_harmony_sloppy()) {
|
||||
final = ParseStatementListItem(CHECK_OK);
|
||||
} else {
|
||||
final = ParseStatement(CHECK_OK);
|
||||
@ -524,12 +524,13 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
|
||||
// existing pages. Therefore we keep allowing const with the old
|
||||
// non-harmony semantics in sloppy mode.
|
||||
Consume(Token::CONST);
|
||||
if (is_strict(language_mode())) {
|
||||
if (is_strict(language_mode()) ||
|
||||
(allow_harmony_sloppy() && !allow_legacy_const())) {
|
||||
DCHECK(var_context != kStatement);
|
||||
is_strict_const = true;
|
||||
require_initializer = var_context != kForStatement;
|
||||
}
|
||||
} else if (peek() == Token::LET && is_strict(language_mode())) {
|
||||
} else if (peek() == Token::LET && allow_let()) {
|
||||
Consume(Token::LET);
|
||||
DCHECK(var_context != kStatement);
|
||||
} else {
|
||||
@ -869,7 +870,7 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) {
|
||||
if (peek() != Token::SEMICOLON) {
|
||||
ForEachStatement::VisitMode mode;
|
||||
if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) ||
|
||||
(peek() == Token::LET && is_strict(language_mode()))) {
|
||||
(peek() == Token::LET && allow_let())) {
|
||||
int decl_count;
|
||||
Scanner::Location first_initializer_loc = Scanner::Location::invalid();
|
||||
Scanner::Location bindings_loc = Scanner::Location::invalid();
|
||||
|
@ -494,7 +494,12 @@ class ParserBase : public Traits {
|
||||
bool is_generator() const { return function_state_->is_generator(); }
|
||||
|
||||
bool allow_const() {
|
||||
return is_strict(language_mode()) || allow_legacy_const();
|
||||
return is_strict(language_mode()) || allow_harmony_sloppy() ||
|
||||
allow_legacy_const();
|
||||
}
|
||||
|
||||
bool allow_let() {
|
||||
return is_strict(language_mode()) || allow_harmony_sloppy();
|
||||
}
|
||||
|
||||
// Report syntax errors.
|
||||
|
@ -6766,7 +6766,7 @@ TEST(NewTarget) {
|
||||
}
|
||||
|
||||
|
||||
TEST(LegacyConst) {
|
||||
TEST(ConstLegacy) {
|
||||
// clang-format off
|
||||
const char* context_data[][2] = {
|
||||
{"", ""},
|
||||
@ -6784,9 +6784,57 @@ TEST(LegacyConst) {
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
static const ParserFlag always_flags[] = {kNoLegacyConst};
|
||||
|
||||
static const ParserFlag always_flags[] = {kNoLegacyConst};
|
||||
RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
|
||||
arraysize(always_flags));
|
||||
RunParserSyncTest(context_data, data, kSuccess);
|
||||
}
|
||||
|
||||
|
||||
TEST(ConstSloppy) {
|
||||
// clang-format off
|
||||
const char* context_data[][2] = {
|
||||
{"", ""},
|
||||
{"{", "}"},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
const char* data[] = {
|
||||
"const x = 1",
|
||||
"for (const x = 1; x < 1; x++) {}",
|
||||
"for (const x in {}) {}",
|
||||
"for (const x of []) {}",
|
||||
NULL
|
||||
};
|
||||
// clang-format on
|
||||
static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
|
||||
kNoLegacyConst};
|
||||
RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
|
||||
arraysize(always_flags));
|
||||
}
|
||||
|
||||
|
||||
TEST(LetSloppy) {
|
||||
// clang-format off
|
||||
const char* context_data[][2] = {
|
||||
{"", ""},
|
||||
{"'use strict';", ""},
|
||||
{"{", "}"},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
const char* data[] = {
|
||||
"let x",
|
||||
"let x = 1",
|
||||
"for (let x = 1; x < 1; x++) {}",
|
||||
"for (let x in {}) {}",
|
||||
"for (let x of []) {}",
|
||||
NULL
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
|
||||
RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
|
||||
arraysize(always_flags));
|
||||
}
|
||||
|
@ -175,7 +175,7 @@ try {
|
||||
|
||||
|
||||
// Verify that the context is correctly set in the stack frame after exiting
|
||||
// from with.
|
||||
// from eval.
|
||||
function f() {}
|
||||
|
||||
(function(x) {
|
||||
|
159
test/mjsunit/harmony/block-const-assign-sloppy.js
Normal file
159
test/mjsunit/harmony/block-const-assign-sloppy.js
Normal file
@ -0,0 +1,159 @@
|
||||
// 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: --harmony-computed-property-names
|
||||
// Flags: --no-legacy-const --harmony-sloppy
|
||||
|
||||
// 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.
|
||||
|
||||
const decls = [
|
||||
// Const declaration.
|
||||
function(use) { return "const c = 1; " + use + ";" }, TypeError,
|
||||
function(use) { return "const x = 0, c = 1; " + use + ";" }, TypeError,
|
||||
function(use) { return "const c = 1, x = (" + use + ");" }, TypeError,
|
||||
function(use) { return use + "; const c = 1;" }, ReferenceError,
|
||||
function(use) { return use + "; const x = 0, c = 1;" }, ReferenceError,
|
||||
function(use) { return "const x = (" + use + "), c = 1;" }, ReferenceError,
|
||||
function(use) { return "const c = (" + use + ");" }, ReferenceError,
|
||||
|
||||
// Function expression.
|
||||
function(use) { return "(function c() { " + use + "; })();"; }, TypeError,
|
||||
// TODO(rossberg): Once we have default parameters, test using 'c' there.
|
||||
|
||||
// Class expression.
|
||||
function(use) {
|
||||
return "new class c { constructor() { " + use + " } };";
|
||||
}, TypeError,
|
||||
function(use) {
|
||||
return "(new class c { m() { " + use + " } }).m();";
|
||||
}, TypeError,
|
||||
function(use) {
|
||||
return "(new class c { get a() { " + use + " } }).a;";
|
||||
}, TypeError,
|
||||
function(use) {
|
||||
return "(new class c { set a(x) { " + use + " } }).a = 0;";
|
||||
}, TypeError,
|
||||
function(use) {
|
||||
return "(class c { static m() { " + use + " } }).s();";
|
||||
}, TypeError,
|
||||
function(use) {
|
||||
return "(class c extends (" + use + ") {});";
|
||||
}, ReferenceError,
|
||||
function(use) {
|
||||
return "(class c { [" + use + "]() {} });";
|
||||
}, ReferenceError,
|
||||
function(use) {
|
||||
return "(class c { get [" + use + "]() {} });";
|
||||
}, ReferenceError,
|
||||
function(use) {
|
||||
return "(class c { set [" + use + "](x) {} });";
|
||||
}, ReferenceError,
|
||||
function(use) {
|
||||
return "(class c { static [" + use + "]() {} });";
|
||||
}, ReferenceError,
|
||||
|
||||
// For loop.
|
||||
function(use) {
|
||||
return "for (const c = 0; " + use + ";) {}"
|
||||
}, TypeError,
|
||||
function(use) {
|
||||
return "for (const x = 0, c = 0; " + use + ";) {}"
|
||||
}, TypeError,
|
||||
function(use) {
|
||||
return "for (const c = 0; ; " + use + ") {}"
|
||||
}, TypeError,
|
||||
function(use) {
|
||||
return "for (const x = 0, c = 0; ; " + use + ") {}"
|
||||
}, TypeError,
|
||||
function(use) {
|
||||
return "for (const c = 0; ;) { " + use + "; }"
|
||||
}, TypeError,
|
||||
function(use) {
|
||||
return "for (const x = 0, c = 0; ;) { " + use + "; }"
|
||||
}, TypeError,
|
||||
function(use) {
|
||||
return "for (const c in {a: 1}) { " + use + "; }"
|
||||
}, TypeError,
|
||||
function(use) {
|
||||
return "for (const c of [1]) { " + use + "; }"
|
||||
}, TypeError,
|
||||
function(use) {
|
||||
return "for (const x = (" + use + "), c = 0; ;) {}"
|
||||
}, ReferenceError,
|
||||
function(use) {
|
||||
return "for (const c = (" + use + "); ;) {}"
|
||||
}, ReferenceError,
|
||||
]
|
||||
|
||||
let uses = [
|
||||
'c = 1',
|
||||
'c += 1',
|
||||
'++c',
|
||||
'c--',
|
||||
];
|
||||
|
||||
let declcontexts = [
|
||||
function(decl) { return decl; },
|
||||
function(decl) { return "eval(\'" + decl + "\')"; },
|
||||
function(decl) { return "{ " + decl + " }"; },
|
||||
function(decl) { return "(function() { " + decl + " })()"; },
|
||||
];
|
||||
|
||||
let usecontexts = [
|
||||
function(use) { return use; },
|
||||
function(use) { return "eval(\"" + use + "\")"; },
|
||||
function(use) { return "(function() { " + use + " })()"; },
|
||||
function(use) { return "(function() { eval(\"" + use + "\"); })()"; },
|
||||
function(use) { return "eval(\"(function() { " + use + "; })\")()"; },
|
||||
];
|
||||
|
||||
function Test(program, error) {
|
||||
program = "'use strict'; " + program;
|
||||
try {
|
||||
print(program, " // throw " + error.name);
|
||||
eval(program);
|
||||
} catch (e) {
|
||||
assertInstanceof(e, error);
|
||||
if (e === TypeError) {
|
||||
assertTrue(e.toString().indexOf("Assignment to constant variable") >= 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
assertUnreachable();
|
||||
}
|
||||
|
||||
for (var d = 0; d < decls.length; d += 2) {
|
||||
for (var u = 0; u < uses.length; ++u) {
|
||||
for (var o = 0; o < declcontexts.length; ++o) {
|
||||
for (var i = 0; i < usecontexts.length; ++i) {
|
||||
Test(declcontexts[o](decls[d](usecontexts[i](uses[u]))), decls[d + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
199
test/mjsunit/harmony/block-for-sloppy.js
Normal file
199
test/mjsunit/harmony/block-for-sloppy.js
Normal file
@ -0,0 +1,199 @@
|
||||
// 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-legacy-const --harmony-sloppy
|
||||
|
||||
function props(x) {
|
||||
var array = [];
|
||||
for (let p in x) array.push(p);
|
||||
return array.sort();
|
||||
}
|
||||
|
||||
assertEquals(0, props({}).length);
|
||||
assertEquals(1, props({x:1}).length);
|
||||
assertEquals(2, props({x:1, y:2}).length);
|
||||
|
||||
assertArrayEquals(["x"], props({x:1}));
|
||||
assertArrayEquals(["x", "y"], props({x:1, y:2}));
|
||||
assertArrayEquals(["x", "y", "zoom"], props({x:1, y:2, zoom:3}));
|
||||
|
||||
assertEquals(0, props([]).length);
|
||||
assertEquals(1, props([1]).length);
|
||||
assertEquals(2, props([1,2]).length);
|
||||
|
||||
assertArrayEquals(["0"], props([1]));
|
||||
assertArrayEquals(["0", "1"], props([1,2]));
|
||||
assertArrayEquals(["0", "1", "2"], props([1,2,3]));
|
||||
|
||||
var o = {};
|
||||
var a = [];
|
||||
let i = "outer_i";
|
||||
let s = "outer_s";
|
||||
for (let i = 0x0020; i < 0x01ff; i+=2) {
|
||||
let s = 'char:' + String.fromCharCode(i);
|
||||
a.push(s);
|
||||
o[s] = i;
|
||||
}
|
||||
assertArrayEquals(a, props(o));
|
||||
assertEquals(i, "outer_i");
|
||||
assertEquals(s, "outer_s");
|
||||
|
||||
var a = [];
|
||||
assertEquals(0, props(a).length);
|
||||
a[Math.pow(2,30)-1] = 0;
|
||||
assertEquals(1, props(a).length);
|
||||
a[Math.pow(2,31)-1] = 0;
|
||||
assertEquals(2, props(a).length);
|
||||
a[1] = 0;
|
||||
assertEquals(3, props(a).length);
|
||||
|
||||
var result = '';
|
||||
for (let p in {a : [0], b : 1}) { result += p; }
|
||||
assertEquals('ab', result);
|
||||
|
||||
var result = '';
|
||||
for (let p in {a : {v:1}, b : 1}) { result += p; }
|
||||
assertEquals('ab', result);
|
||||
|
||||
var result = '';
|
||||
for (let p in { get a() {}, b : 1}) { result += p; }
|
||||
assertEquals('ab', result);
|
||||
|
||||
var result = '';
|
||||
for (let p in { get a() {}, set a(x) {}, b : 1}) { result += p; }
|
||||
assertEquals('ab', result);
|
||||
|
||||
|
||||
// Check that there is exactly one variable without initializer
|
||||
// in a for-in statement with let variables.
|
||||
assertThrows("function foo() { 'use strict'; for (let in {}) { } }", SyntaxError);
|
||||
assertThrows("function foo() { 'use strict'; for (let x = 3 in {}) { } }", SyntaxError);
|
||||
assertThrows("function foo() { 'use strict'; for (let x, y in {}) { } }", SyntaxError);
|
||||
assertThrows("function foo() { 'use strict'; for (let x = 3, y in {}) { } }", SyntaxError);
|
||||
assertThrows("function foo() { 'use strict'; for (let x, y = 4 in {}) { } }", SyntaxError);
|
||||
assertThrows("function foo() { 'use strict'; for (let x = 3, y = 4 in {}) { } }", SyntaxError);
|
||||
|
||||
|
||||
// In a normal for statement the iteration variable is
|
||||
// freshly allocated for each iteration.
|
||||
function closures1() {
|
||||
let a = [];
|
||||
for (let i = 0; i < 5; ++i) {
|
||||
a.push(function () { return i; });
|
||||
}
|
||||
for (let j = 0; j < 5; ++j) {
|
||||
assertEquals(j, a[j]());
|
||||
}
|
||||
}
|
||||
closures1();
|
||||
|
||||
|
||||
function closures2() {
|
||||
let a = [], b = [];
|
||||
for (let i = 0, j = 10; i < 5; ++i, ++j) {
|
||||
a.push(function () { return i; });
|
||||
b.push(function () { return j; });
|
||||
}
|
||||
for (let k = 0; k < 5; ++k) {
|
||||
assertEquals(k, a[k]());
|
||||
assertEquals(k + 10, b[k]());
|
||||
}
|
||||
}
|
||||
closures2();
|
||||
|
||||
|
||||
function closure_in_for_init() {
|
||||
let a = [];
|
||||
for (let i = 0, f = function() { return i }; i < 5; ++i) {
|
||||
a.push(f);
|
||||
}
|
||||
for (let k = 0; k < 5; ++k) {
|
||||
assertEquals(0, a[k]());
|
||||
}
|
||||
}
|
||||
closure_in_for_init();
|
||||
|
||||
|
||||
function closure_in_for_cond() {
|
||||
let a = [];
|
||||
for (let i = 0; a.push(function () { return i; }), i < 5; ++i) { }
|
||||
for (let k = 0; k < 5; ++k) {
|
||||
assertEquals(k, a[k]());
|
||||
}
|
||||
}
|
||||
closure_in_for_cond();
|
||||
|
||||
|
||||
function closure_in_for_next() {
|
||||
let a = [];
|
||||
for (let i = 0; i < 5; a.push(function () { return i; }), ++i) { }
|
||||
for (let k = 0; k < 5; ++k) {
|
||||
assertEquals(k + 1, a[k]());
|
||||
}
|
||||
}
|
||||
closure_in_for_next();
|
||||
|
||||
|
||||
// In a for-in statement the iteration variable is fresh
|
||||
// for each iteration.
|
||||
function closures3(x) {
|
||||
let a = [];
|
||||
for (let p in x) {
|
||||
a.push(function () { return p; });
|
||||
}
|
||||
let k = 0;
|
||||
for (let q in x) {
|
||||
assertEquals(q, a[k]());
|
||||
++k;
|
||||
}
|
||||
}
|
||||
closures3({a : [0], b : 1, c : {v : 1}, get d() {}, set e(x) {}});
|
||||
|
||||
// Check normal for statement completion values.
|
||||
assertEquals(1, eval("for (let i = 0; i < 10; i++) { 1; }"));
|
||||
assertEquals(9, eval("for (let i = 0; i < 10; i++) { i; }"));
|
||||
assertEquals(undefined, eval("for (let i = 0; false;) { }"));
|
||||
assertEquals(undefined, eval("for (const i = 0; false;) { }"));
|
||||
assertEquals(undefined, eval("for (let i = 0; i < 10; i++) { }"));
|
||||
assertEquals(undefined, eval("for (let i = 0; false;) { i; }"));
|
||||
assertEquals(undefined, eval("for (const i = 0; false;) { i; }"));
|
||||
assertEquals(undefined, eval("for (let i = 0; true;) { break; }"));
|
||||
assertEquals(undefined, eval("for (const i = 0; true;) { break; }"));
|
||||
assertEquals(undefined, eval("for (let i = 0; i < 10; i++) { continue; }"));
|
||||
assertEquals(undefined, eval("for (let i = 0; true;) { break; i; }"));
|
||||
assertEquals(undefined, eval("for (const i = 0; true;) { break; i; }"));
|
||||
assertEquals(undefined, eval("for (let i = 0; i < 10; i++) { continue; i; }"));
|
||||
assertEquals(0, eval("for (let i = 0; true;) { i; break; }"));
|
||||
assertEquals(0, eval("for (const i = 0; true;) { i; break; }"));
|
||||
assertEquals(9, eval("for (let i = 0; i < 10; i++) { i; continue; }"));
|
||||
assertEquals(3, eval("for (let i = 0; true; i++) { i; if (i >= 3) break; }"));
|
||||
assertEquals(2, eval("for (let i = 0; true; i++) { if (i >= 3) break; i; }"));
|
||||
assertEquals(
|
||||
2, eval("for (let i = 0; i < 10; i++) { if (i >= 3) continue; i; }"));
|
||||
assertEquals(undefined, eval("foo: for (let i = 0; true;) { break foo; }"));
|
||||
assertEquals(undefined, eval("foo: for (const i = 0; true;) { break foo; }"));
|
||||
assertEquals(3, eval("foo: for (let i = 3; true;) { i; break foo; }"));
|
224
test/mjsunit/harmony/block-leave-sloppy.js
Normal file
224
test/mjsunit/harmony/block-leave-sloppy.js
Normal file
@ -0,0 +1,224 @@
|
||||
// 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-legacy-const --harmony-sloppy
|
||||
|
||||
// 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
|
||||
// lookup of 'x' might accidentally succeed.
|
||||
|
||||
{
|
||||
let x = 2;
|
||||
L: {
|
||||
let x = 3;
|
||||
assertEquals(3, x);
|
||||
break L;
|
||||
assertTrue(false);
|
||||
}
|
||||
assertEquals(2, x);
|
||||
}
|
||||
|
||||
do {
|
||||
let x = 4;
|
||||
assertEquals(4,x);
|
||||
{
|
||||
let x = 5;
|
||||
assertEquals(5, x);
|
||||
continue;
|
||||
assertTrue(false);
|
||||
}
|
||||
} while (false);
|
||||
|
||||
var caught = false;
|
||||
try {
|
||||
{
|
||||
let xx = 18;
|
||||
throw 25;
|
||||
assertTrue(false);
|
||||
}
|
||||
} catch (e) {
|
||||
caught = true;
|
||||
assertEquals(25, e);
|
||||
(function () {
|
||||
try {
|
||||
// NOTE: This checks that the block scope containing xx has been
|
||||
// removed from the context chain.
|
||||
eval('xx');
|
||||
assertTrue(false); // should not reach here
|
||||
} catch (e2) {
|
||||
assertTrue(e2 instanceof ReferenceError);
|
||||
}
|
||||
})();
|
||||
}
|
||||
assertTrue(caught);
|
||||
|
||||
|
||||
(function(x) {
|
||||
label: {
|
||||
let x = 'inner';
|
||||
break label;
|
||||
}
|
||||
assertEquals('outer', eval('x'));
|
||||
})('outer');
|
||||
|
||||
|
||||
(function(x) {
|
||||
label: {
|
||||
let x = 'middle';
|
||||
{
|
||||
let x = 'inner';
|
||||
break label;
|
||||
}
|
||||
}
|
||||
assertEquals('outer', eval('x'));
|
||||
})('outer');
|
||||
|
||||
|
||||
(function(x) {
|
||||
for (var i = 0; i < 10; ++i) {
|
||||
let x = 'inner' + i;
|
||||
continue;
|
||||
}
|
||||
assertEquals('outer', eval('x'));
|
||||
})('outer');
|
||||
|
||||
|
||||
(function(x) {
|
||||
label: for (var i = 0; i < 10; ++i) {
|
||||
let x = 'middle' + i;
|
||||
for (var j = 0; j < 10; ++j) {
|
||||
let x = 'inner' + j;
|
||||
continue label;
|
||||
}
|
||||
}
|
||||
assertEquals('outer', eval('x'));
|
||||
})('outer');
|
||||
|
||||
|
||||
(function(x) {
|
||||
try {
|
||||
let x = 'inner';
|
||||
throw 0;
|
||||
} catch (e) {
|
||||
assertEquals('outer', eval('x'));
|
||||
}
|
||||
})('outer');
|
||||
|
||||
|
||||
(function(x) {
|
||||
try {
|
||||
let x = 'middle';
|
||||
{
|
||||
let x = 'inner';
|
||||
throw 0;
|
||||
}
|
||||
} catch (e) {
|
||||
assertEquals('outer', eval('x'));
|
||||
}
|
||||
})('outer');
|
||||
|
||||
|
||||
try {
|
||||
(function(x) {
|
||||
try {
|
||||
let x = 'inner';
|
||||
throw 0;
|
||||
} finally {
|
||||
assertEquals('outer', eval('x'));
|
||||
}
|
||||
})('outer');
|
||||
} catch (e) {
|
||||
if (e instanceof MjsUnitAssertionError) throw e;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
(function(x) {
|
||||
try {
|
||||
let x = 'middle';
|
||||
{
|
||||
let x = 'inner';
|
||||
throw 0;
|
||||
}
|
||||
} finally {
|
||||
assertEquals('outer', eval('x'));
|
||||
}
|
||||
})('outer');
|
||||
} catch (e) {
|
||||
if (e instanceof MjsUnitAssertionError) throw e;
|
||||
}
|
||||
|
||||
|
||||
// Verify that the context is correctly set in the stack frame after exiting
|
||||
// from eval.
|
||||
function f() {}
|
||||
|
||||
(function(x) {
|
||||
label: {
|
||||
let x = 'inner';
|
||||
break label;
|
||||
}
|
||||
f(); // The context could be restored from the stack after the call.
|
||||
assertEquals('outer', eval('x'));
|
||||
})('outer');
|
||||
|
||||
|
||||
(function(x) {
|
||||
for (var i = 0; i < 10; ++i) {
|
||||
let x = 'inner';
|
||||
continue;
|
||||
}
|
||||
f();
|
||||
assertEquals('outer', eval('x'));
|
||||
})('outer');
|
||||
|
||||
|
||||
(function(x) {
|
||||
try {
|
||||
let x = 'inner';
|
||||
throw 0;
|
||||
} catch (e) {
|
||||
f();
|
||||
assertEquals('outer', eval('x'));
|
||||
}
|
||||
})('outer');
|
||||
|
||||
|
||||
try {
|
||||
(function(x) {
|
||||
try {
|
||||
let x = 'inner';
|
||||
throw 0;
|
||||
} finally {
|
||||
f();
|
||||
assertEquals('outer', eval('x'));
|
||||
}
|
||||
})('outer');
|
||||
} catch (e) {
|
||||
if (e instanceof MjsUnitAssertionError) throw e;
|
||||
}
|
483
test/mjsunit/harmony/block-let-crankshaft-sloppy.js
Normal file
483
test/mjsunit/harmony/block-let-crankshaft-sloppy.js
Normal file
@ -0,0 +1,483 @@
|
||||
// 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: --allow-natives-syntax
|
||||
// Flags: --no-legacy-const --harmony-sloppy
|
||||
|
||||
// Check that the following functions are optimizable.
|
||||
var functions = [ f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14,
|
||||
f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26,
|
||||
f27, f28, f29, f30, f31, f32, f33];
|
||||
|
||||
for (var i = 0; i < functions.length; ++i) {
|
||||
var func = functions[i];
|
||||
print("Testing:");
|
||||
print(func);
|
||||
for (var j = 0; j < 10; ++j) {
|
||||
func(12);
|
||||
}
|
||||
%OptimizeFunctionOnNextCall(func);
|
||||
func(12);
|
||||
assertOptimized(func);
|
||||
}
|
||||
|
||||
function f1() { }
|
||||
|
||||
function f2(x) { }
|
||||
|
||||
function f3() {
|
||||
let x;
|
||||
}
|
||||
|
||||
function f4() {
|
||||
function foo() {
|
||||
}
|
||||
}
|
||||
|
||||
function f5() {
|
||||
let x = 1;
|
||||
}
|
||||
|
||||
function f6() {
|
||||
const x = 1;
|
||||
}
|
||||
|
||||
function f7(x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
function f8() {
|
||||
let x;
|
||||
return x;
|
||||
}
|
||||
|
||||
function f9() {
|
||||
function x() {
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
function f10(x) {
|
||||
x = 1;
|
||||
}
|
||||
|
||||
function f11() {
|
||||
let x;
|
||||
x = 1;
|
||||
}
|
||||
|
||||
function f12() {
|
||||
function x() {};
|
||||
x = 1;
|
||||
}
|
||||
|
||||
function f13(x) {
|
||||
(function() { x; });
|
||||
}
|
||||
|
||||
function f14() {
|
||||
let x;
|
||||
(function() { x; });
|
||||
}
|
||||
|
||||
function f15() {
|
||||
function x() {
|
||||
}
|
||||
(function() { x; });
|
||||
}
|
||||
|
||||
function f16() {
|
||||
let x = 1;
|
||||
(function() { x; });
|
||||
}
|
||||
|
||||
function f17() {
|
||||
const x = 1;
|
||||
(function() { x; });
|
||||
}
|
||||
|
||||
function f18(x) {
|
||||
return x;
|
||||
(function() { x; });
|
||||
}
|
||||
|
||||
function f19() {
|
||||
let x;
|
||||
return x;
|
||||
(function() { x; });
|
||||
}
|
||||
|
||||
function f20() {
|
||||
function x() {
|
||||
}
|
||||
return x;
|
||||
(function() { x; });
|
||||
}
|
||||
|
||||
function f21(x) {
|
||||
x = 1;
|
||||
(function() { x; });
|
||||
}
|
||||
|
||||
function f22() {
|
||||
let x;
|
||||
x = 1;
|
||||
(function() { x; });
|
||||
}
|
||||
|
||||
function f23() {
|
||||
function x() { }
|
||||
x = 1;
|
||||
(function() { x; });
|
||||
}
|
||||
|
||||
function f24() {
|
||||
let x = 1;
|
||||
{
|
||||
let x = 2;
|
||||
{
|
||||
let x = 3;
|
||||
assertEquals(3, x);
|
||||
}
|
||||
assertEquals(2, x);
|
||||
}
|
||||
assertEquals(1, x);
|
||||
}
|
||||
|
||||
function f25() {
|
||||
{
|
||||
let x = 2;
|
||||
L: {
|
||||
let x = 3;
|
||||
assertEquals(3, x);
|
||||
break L;
|
||||
assertTrue(false);
|
||||
}
|
||||
assertEquals(2, x);
|
||||
}
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
function f26() {
|
||||
{
|
||||
let x = 1;
|
||||
L: {
|
||||
let x = 2;
|
||||
{
|
||||
let x = 3;
|
||||
assertEquals(3, x);
|
||||
break L;
|
||||
assertTrue(false);
|
||||
}
|
||||
assertTrue(false);
|
||||
}
|
||||
assertEquals(1, x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function f27() {
|
||||
do {
|
||||
let x = 4;
|
||||
assertEquals(4,x);
|
||||
{
|
||||
let x = 5;
|
||||
assertEquals(5, x);
|
||||
continue;
|
||||
assertTrue(false);
|
||||
}
|
||||
} while (false);
|
||||
}
|
||||
|
||||
function f28() {
|
||||
label: for (var i = 0; i < 10; ++i) {
|
||||
let x = 'middle' + i;
|
||||
for (var j = 0; j < 10; ++j) {
|
||||
let x = 'inner' + j;
|
||||
continue label;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function f29() {
|
||||
// Verify that the context is correctly set in the stack frame after exiting
|
||||
// from with.
|
||||
|
||||
let x = 'outer';
|
||||
label: {
|
||||
let x = 'inner';
|
||||
break label;
|
||||
}
|
||||
f(); // The context could be restored from the stack after the call.
|
||||
assertEquals('outer', x);
|
||||
|
||||
function f() {
|
||||
assertEquals('outer', x);
|
||||
};
|
||||
}
|
||||
|
||||
function f30() {
|
||||
let x = 'outer';
|
||||
for (var i = 0; i < 10; ++i) {
|
||||
let x = 'inner';
|
||||
continue;
|
||||
}
|
||||
f();
|
||||
assertEquals('outer', x);
|
||||
|
||||
function f() {
|
||||
assertEquals('outer', x);
|
||||
};
|
||||
}
|
||||
|
||||
function f31() {
|
||||
{
|
||||
let x = 'outer';
|
||||
label: for (var i = 0; assertEquals('outer', x), i < 10; ++i) {
|
||||
let x = 'middle' + i;
|
||||
{
|
||||
let x = 'inner' + j;
|
||||
continue label;
|
||||
}
|
||||
}
|
||||
assertEquals('outer', x);
|
||||
}
|
||||
}
|
||||
|
||||
var c = true;
|
||||
|
||||
function f32() {
|
||||
{
|
||||
let x = 'outer';
|
||||
L: {
|
||||
{
|
||||
let x = 'inner';
|
||||
if (c) {
|
||||
break L;
|
||||
}
|
||||
}
|
||||
foo();
|
||||
}
|
||||
}
|
||||
|
||||
function foo() {
|
||||
return 'bar';
|
||||
}
|
||||
}
|
||||
|
||||
function f33() {
|
||||
{
|
||||
let x = 'outer';
|
||||
L: {
|
||||
{
|
||||
let x = 'inner';
|
||||
if (c) {
|
||||
break L;
|
||||
}
|
||||
foo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function foo() {
|
||||
return 'bar';
|
||||
}
|
||||
}
|
||||
|
||||
function TestThrow() {
|
||||
function f() {
|
||||
let x = 'outer';
|
||||
{
|
||||
let x = 'inner';
|
||||
throw x;
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < 5; i++) {
|
||||
try {
|
||||
f();
|
||||
} catch (e) {
|
||||
assertEquals('inner', e);
|
||||
}
|
||||
}
|
||||
%OptimizeFunctionOnNextCall(f);
|
||||
try {
|
||||
f();
|
||||
} catch (e) {
|
||||
assertEquals('inner', e);
|
||||
}
|
||||
assertOptimized(f);
|
||||
}
|
||||
|
||||
TestThrow();
|
||||
|
||||
// Test that temporal dead zone semantics for function and block scoped
|
||||
// let bindings are handled by the optimizing compiler.
|
||||
|
||||
function TestFunctionLocal(s) {
|
||||
'use strict';
|
||||
var func = eval("(function baz(){" + s + "; })");
|
||||
print("Testing:");
|
||||
print(func);
|
||||
for (var i = 0; i < 5; ++i) {
|
||||
try {
|
||||
func();
|
||||
assertUnreachable();
|
||||
} catch (e) {
|
||||
assertInstanceof(e, ReferenceError);
|
||||
}
|
||||
}
|
||||
%OptimizeFunctionOnNextCall(func);
|
||||
try {
|
||||
func();
|
||||
assertUnreachable();
|
||||
} catch (e) {
|
||||
assertInstanceof(e, ReferenceError);
|
||||
}
|
||||
}
|
||||
|
||||
function TestFunctionContext(s) {
|
||||
'use strict';
|
||||
var func = eval("(function baz(){ " + s + "; (function() { x; }); })");
|
||||
print("Testing:");
|
||||
print(func);
|
||||
for (var i = 0; i < 5; ++i) {
|
||||
print(i);
|
||||
try {
|
||||
func();
|
||||
assertUnreachable();
|
||||
} catch (e) {
|
||||
assertInstanceof(e, ReferenceError);
|
||||
}
|
||||
}
|
||||
print("optimize");
|
||||
%OptimizeFunctionOnNextCall(func);
|
||||
try {
|
||||
print("call");
|
||||
func();
|
||||
assertUnreachable();
|
||||
} catch (e) {
|
||||
print("catch");
|
||||
assertInstanceof(e, ReferenceError);
|
||||
}
|
||||
}
|
||||
|
||||
function TestBlockLocal(s) {
|
||||
'use strict';
|
||||
var func = eval("(function baz(){ { " + s + "; } })");
|
||||
print("Testing:");
|
||||
print(func);
|
||||
for (var i = 0; i < 5; ++i) {
|
||||
try {
|
||||
func();
|
||||
assertUnreachable();
|
||||
} catch (e) {
|
||||
assertInstanceof(e, ReferenceError);
|
||||
}
|
||||
}
|
||||
%OptimizeFunctionOnNextCall(func);
|
||||
try {
|
||||
func();
|
||||
assertUnreachable();
|
||||
} catch (e) {
|
||||
assertInstanceof(e, ReferenceError);
|
||||
}
|
||||
}
|
||||
|
||||
function TestBlockContext(s) {
|
||||
'use strict';
|
||||
var func = eval("(function baz(){ { " + s + "; (function() { x; }); } })");
|
||||
print("Testing:");
|
||||
print(func);
|
||||
for (var i = 0; i < 5; ++i) {
|
||||
print(i);
|
||||
try {
|
||||
func();
|
||||
assertUnreachable();
|
||||
} catch (e) {
|
||||
assertInstanceof(e, ReferenceError);
|
||||
}
|
||||
}
|
||||
print("optimize");
|
||||
%OptimizeFunctionOnNextCall(func);
|
||||
try {
|
||||
print("call");
|
||||
func();
|
||||
assertUnreachable();
|
||||
} catch (e) {
|
||||
print("catch");
|
||||
assertInstanceof(e, ReferenceError);
|
||||
}
|
||||
}
|
||||
|
||||
function TestAll(s) {
|
||||
TestFunctionLocal(s);
|
||||
TestFunctionContext(s);
|
||||
TestBlockLocal(s);
|
||||
TestBlockContext(s);
|
||||
}
|
||||
|
||||
// Use before initialization in declaration statement.
|
||||
TestAll('let x = x + 1');
|
||||
TestAll('let x = x += 1');
|
||||
TestAll('let x = x++');
|
||||
TestAll('let x = ++x');
|
||||
TestAll('const x = x + 1');
|
||||
|
||||
// Use before initialization in prior statement.
|
||||
TestAll('x + 1; let x;');
|
||||
TestAll('x = 1; let x;');
|
||||
TestAll('x += 1; let x;');
|
||||
TestAll('++x; let x;');
|
||||
TestAll('x++; let x;');
|
||||
TestAll('let y = x; const x = 1;');
|
||||
|
||||
|
||||
function f(x) {
|
||||
let y = x + 42;
|
||||
return y;
|
||||
}
|
||||
|
||||
function g(x) {
|
||||
{
|
||||
let y = x + 42;
|
||||
return y;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i=0; i<10; i++) {
|
||||
f(i);
|
||||
g(i);
|
||||
}
|
||||
|
||||
%OptimizeFunctionOnNextCall(f);
|
||||
%OptimizeFunctionOnNextCall(g);
|
||||
|
||||
f(12);
|
||||
g(12);
|
||||
|
||||
assertTrue(%GetOptimizationStatus(f) != 2);
|
||||
assertTrue(%GetOptimizationStatus(g) != 2);
|
157
test/mjsunit/harmony/block-let-declaration-sloppy.js
Normal file
157
test/mjsunit/harmony/block-let-declaration-sloppy.js
Normal file
@ -0,0 +1,157 @@
|
||||
// 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.
|
||||
|
||||
// Test let declarations in various settings.
|
||||
|
||||
// Flags: --no-legacy-const --harmony-sloppy
|
||||
|
||||
// Global
|
||||
let x;
|
||||
let y = 2;
|
||||
const z = 4;
|
||||
|
||||
// Block local
|
||||
{
|
||||
let y;
|
||||
let x = 3;
|
||||
const z = 5;
|
||||
}
|
||||
|
||||
assertEquals(undefined, x);
|
||||
assertEquals(2,y);
|
||||
assertEquals(4,z);
|
||||
|
||||
if (true) {
|
||||
let y;
|
||||
assertEquals(undefined, y);
|
||||
}
|
||||
|
||||
// Invalid declarations are early errors in harmony mode and thus should trigger
|
||||
// an exception in eval code during parsing, before even compiling or executing
|
||||
// the code. Thus the generated function is not called here.
|
||||
function TestLocalThrows(str, expect) {
|
||||
assertThrows("(function(arg){ 'use strict'; " + str + "})", expect);
|
||||
}
|
||||
|
||||
function TestLocalDoesNotThrow(str) {
|
||||
assertDoesNotThrow("(function(arg){ 'use strict'; " + str + "})()");
|
||||
}
|
||||
|
||||
// Test let declarations in statement positions.
|
||||
TestLocalThrows("if (true) let x;", SyntaxError);
|
||||
TestLocalThrows("if (true) {} else let x;", SyntaxError);
|
||||
TestLocalThrows("do let x; while (false)", SyntaxError);
|
||||
TestLocalThrows("while (false) let x;", SyntaxError);
|
||||
TestLocalThrows("label: let x;", SyntaxError);
|
||||
TestLocalThrows("for (;false;) let x;", SyntaxError);
|
||||
TestLocalDoesNotThrow("switch (true) { case true: let x; }");
|
||||
TestLocalDoesNotThrow("switch (true) { default: let x; }");
|
||||
|
||||
// Test const declarations with initialisers in statement positions.
|
||||
TestLocalThrows("if (true) const x = 1;", SyntaxError);
|
||||
TestLocalThrows("if (true) {} else const x = 1;", SyntaxError);
|
||||
TestLocalThrows("do const x = 1; while (false)", SyntaxError);
|
||||
TestLocalThrows("while (false) const x = 1;", SyntaxError);
|
||||
TestLocalThrows("label: const x = 1;", SyntaxError);
|
||||
TestLocalThrows("for (;false;) const x = 1;", SyntaxError);
|
||||
TestLocalDoesNotThrow("switch (true) { case true: const x = 1; }");
|
||||
TestLocalDoesNotThrow("switch (true) { default: const x = 1; }");
|
||||
|
||||
// Test const declarations without initialisers.
|
||||
TestLocalThrows("const x;", SyntaxError);
|
||||
TestLocalThrows("const x = 1, y;", SyntaxError);
|
||||
TestLocalThrows("const x, y = 1;", SyntaxError);
|
||||
|
||||
// Test const declarations without initialisers in statement positions.
|
||||
TestLocalThrows("if (true) const x;", SyntaxError);
|
||||
TestLocalThrows("if (true) {} else const x;", SyntaxError);
|
||||
TestLocalThrows("do const x; while (false)", SyntaxError);
|
||||
TestLocalThrows("while (false) const x;", SyntaxError);
|
||||
TestLocalThrows("label: const x;", SyntaxError);
|
||||
TestLocalThrows("for (;false;) const x;", SyntaxError);
|
||||
TestLocalThrows("switch (true) { case true: const x; }", SyntaxError);
|
||||
TestLocalThrows("switch (true) { default: const x; }", SyntaxError);
|
||||
|
||||
// Test var declarations in statement positions.
|
||||
TestLocalDoesNotThrow("if (true) var x;");
|
||||
TestLocalDoesNotThrow("if (true) {} else var x;");
|
||||
TestLocalDoesNotThrow("do var x; while (false)");
|
||||
TestLocalDoesNotThrow("while (false) var x;");
|
||||
TestLocalDoesNotThrow("label: var x;");
|
||||
TestLocalDoesNotThrow("for (;false;) var x;");
|
||||
TestLocalDoesNotThrow("switch (true) { case true: var x; }");
|
||||
TestLocalDoesNotThrow("switch (true) { default: var x; }");
|
||||
|
||||
// Test that redeclarations of functions are only allowed in outermost scope.
|
||||
TestLocalThrows("{ let f; var f; }");
|
||||
TestLocalThrows("{ var f; let f; }");
|
||||
TestLocalThrows("{ function f() {} let f; }");
|
||||
TestLocalThrows("{ let f; function f() {} }");
|
||||
TestLocalThrows("{ function f() {} var f; }");
|
||||
TestLocalThrows("{ var f; function f() {} }");
|
||||
TestLocalThrows("{ function f() {} function f() {} }");
|
||||
TestLocalThrows("function f() {} let f;");
|
||||
TestLocalThrows("let f; function f() {}");
|
||||
TestLocalDoesNotThrow("function arg() {}");
|
||||
TestLocalDoesNotThrow("function f() {} var f;");
|
||||
TestLocalDoesNotThrow("var f; function f() {}");
|
||||
TestLocalDoesNotThrow("function f() {} function f() {}");
|
||||
|
||||
function g(f) {
|
||||
function f() { return 1 }
|
||||
return f()
|
||||
}
|
||||
assertEquals(1, g(function() { return 2 }))
|
||||
|
||||
|
||||
// Test function declarations in source element and
|
||||
// sloppy statement positions.
|
||||
function f() {
|
||||
// Sloppy source element positions.
|
||||
function g0() {
|
||||
"use strict";
|
||||
// Strict source element positions.
|
||||
function h() { }
|
||||
{
|
||||
function h1() { }
|
||||
}
|
||||
}
|
||||
{
|
||||
function g1() { }
|
||||
}
|
||||
}
|
||||
f();
|
||||
|
||||
// Test function declarations in statement position in strict mode.
|
||||
TestLocalThrows("function f() { if (true) function g() {} }", SyntaxError);
|
||||
TestLocalThrows("function f() { if (true) {} else function g() {} }", SyntaxError);
|
||||
TestLocalThrows("function f() { do function g() {} while (false) }", SyntaxError);
|
||||
TestLocalThrows("function f() { while (false) function g() {} }", SyntaxError);
|
||||
TestLocalThrows("function f() { label: function g() {} }", SyntaxError);
|
||||
TestLocalThrows("function f() { for (;false;) function g() {} }", SyntaxError);
|
||||
TestLocalDoesNotThrow("function f() { switch (true) { case true: function g() {} } }");
|
||||
TestLocalDoesNotThrow("function f() { switch (true) { default: function g() {} } }");
|
188
test/mjsunit/harmony/block-let-semantics-sloppy.js
Normal file
188
test/mjsunit/harmony/block-let-semantics-sloppy.js
Normal file
@ -0,0 +1,188 @@
|
||||
// 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: --harmony-sloppy --no-legacy-const
|
||||
|
||||
// Test temporal dead zone semantics of let bound variables in
|
||||
// function and block scopes.
|
||||
|
||||
function TestFunctionLocal(s) {
|
||||
try {
|
||||
eval("(function(){" + s + "; })")();
|
||||
} catch (e) {
|
||||
assertInstanceof(e, ReferenceError);
|
||||
return;
|
||||
}
|
||||
assertUnreachable();
|
||||
}
|
||||
|
||||
function TestBlockLocal(s,e) {
|
||||
try {
|
||||
eval("(function(){ {" + s + ";} })")();
|
||||
} catch (e) {
|
||||
assertInstanceof(e, ReferenceError);
|
||||
return;
|
||||
}
|
||||
assertUnreachable();
|
||||
}
|
||||
|
||||
|
||||
function TestAll(s) {
|
||||
TestBlockLocal(s);
|
||||
TestFunctionLocal(s);
|
||||
}
|
||||
|
||||
// Use before initialization in declaration statement.
|
||||
TestAll('let x = x + 1');
|
||||
TestAll('let x = x += 1');
|
||||
TestAll('let x = x++');
|
||||
TestAll('let x = ++x');
|
||||
TestAll('const x = x + 1');
|
||||
|
||||
// Use before initialization in prior statement.
|
||||
TestAll('x + 1; let x;');
|
||||
TestAll('x = 1; let x;');
|
||||
TestAll('x += 1; let x;');
|
||||
TestAll('++x; let x;');
|
||||
TestAll('x++; let x;');
|
||||
TestAll('let y = x; const x = 1;');
|
||||
|
||||
TestAll('f(); let x; function f() { return x + 1; }');
|
||||
TestAll('f(); let x; function f() { x = 1; }');
|
||||
TestAll('f(); let x; function f() { x += 1; }');
|
||||
TestAll('f(); let x; function f() { ++x; }');
|
||||
TestAll('f(); let x; function f() { x++; }');
|
||||
TestAll('f(); const x = 1; function f() { return x; }');
|
||||
|
||||
TestAll('f()(); let x; function f() { return function() { return x + 1; } }');
|
||||
TestAll('f()(); let x; function f() { return function() { x = 1; } }');
|
||||
TestAll('f()(); let x; function f() { return function() { x += 1; } }');
|
||||
TestAll('f()(); let x; function f() { return function() { ++x; } }');
|
||||
TestAll('f()(); let x; function f() { return function() { x++; } }');
|
||||
TestAll('f()(); const x = 1; function f() { return function() { return x; } }');
|
||||
|
||||
// Use before initialization with a dynamic lookup.
|
||||
TestAll('eval("x + 1;"); let x;');
|
||||
TestAll('eval("x = 1;"); let x;');
|
||||
TestAll('eval("x += 1;"); let x;');
|
||||
TestAll('eval("++x;"); let x;');
|
||||
TestAll('eval("x++;"); let x;');
|
||||
TestAll('eval("x"); const x = 1;');
|
||||
|
||||
// Use before initialization with check for eval-shadowed bindings.
|
||||
TestAll('function f() { eval("var y = 2;"); x + 1; }; f(); let x;');
|
||||
// TODO(arv): https://code.google.com/p/v8/issues/detail?id=4284
|
||||
// TestAll('function f() { eval("var y = 2;"); x = 1; }; f(); let x;');
|
||||
TestAll('function f() { eval("var y = 2;"); x += 1; }; f(); let x;');
|
||||
TestAll('function f() { eval("var y = 2;"); ++x; }; f(); let x;');
|
||||
TestAll('function f() { eval("var y = 2;"); x++; }; f(); let x;');
|
||||
|
||||
// Test that variables introduced by function declarations are created and
|
||||
// initialized upon entering a function / block scope.
|
||||
function f() {
|
||||
{
|
||||
assertEquals(2, g1());
|
||||
assertEquals(2, eval("g1()"));
|
||||
|
||||
// block scoped function declaration
|
||||
function g1() {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals(3, g2());
|
||||
assertEquals(3, eval("g2()"));
|
||||
// function scoped function declaration
|
||||
function g2() {
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
f();
|
||||
|
||||
// Test that a function declaration introduces a block scoped variable.
|
||||
TestAll('{ function k() { return 0; } }; k(); ');
|
||||
|
||||
// Test that a function declaration sees the scope it resides in.
|
||||
function f2() {
|
||||
let m, n, o, p;
|
||||
{
|
||||
m = g;
|
||||
function g() {
|
||||
return a;
|
||||
}
|
||||
let a = 1;
|
||||
}
|
||||
assertEquals(1, m());
|
||||
|
||||
try {
|
||||
throw 2;
|
||||
} catch(b) {
|
||||
n = h;
|
||||
function h() {
|
||||
return b + c;
|
||||
}
|
||||
let c = 3;
|
||||
}
|
||||
assertEquals(5, n());
|
||||
|
||||
{
|
||||
o = i;
|
||||
function i() {
|
||||
return d;
|
||||
}
|
||||
let d = 4;
|
||||
}
|
||||
assertEquals(4, o());
|
||||
|
||||
try {
|
||||
throw 5;
|
||||
} catch(e) {
|
||||
p = j;
|
||||
function j() {
|
||||
return e + f;
|
||||
}
|
||||
let f = 6;
|
||||
}
|
||||
assertEquals(11, p());
|
||||
}
|
||||
f2();
|
||||
|
||||
// Test that resolution of let bound variables works with scopes that call eval.
|
||||
function outer() {
|
||||
function middle() {
|
||||
function inner() {
|
||||
return x;
|
||||
}
|
||||
eval("1 + 1");
|
||||
return x + inner();
|
||||
}
|
||||
|
||||
let x = 1;
|
||||
return middle();
|
||||
}
|
||||
|
||||
assertEquals(2, outer());
|
269
test/mjsunit/harmony/block-scoping-sloppy.js
Normal file
269
test/mjsunit/harmony/block-scoping-sloppy.js
Normal file
@ -0,0 +1,269 @@
|
||||
// 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: --allow-natives-syntax --harmony-sloppy --no-legacy-const
|
||||
// Test functionality of block scopes.
|
||||
|
||||
// Hoisting of var declarations.
|
||||
function f1() {
|
||||
{
|
||||
var x = 1;
|
||||
var y;
|
||||
}
|
||||
assertEquals(1, x)
|
||||
assertEquals(undefined, y)
|
||||
}
|
||||
for (var j = 0; j < 5; ++j) f1();
|
||||
%OptimizeFunctionOnNextCall(f1);
|
||||
f1();
|
||||
assertTrue(%GetOptimizationStatus(f1) != 2);
|
||||
|
||||
// Dynamic lookup in and through block contexts.
|
||||
function f2(one) {
|
||||
var x = one + 1;
|
||||
let y = one + 2;
|
||||
const u = one + 4;
|
||||
{
|
||||
let z = one + 3;
|
||||
const v = one + 5;
|
||||
assertEquals(1, eval('one'));
|
||||
assertEquals(2, eval('x'));
|
||||
assertEquals(3, eval('y'));
|
||||
assertEquals(4, eval('z'));
|
||||
assertEquals(5, eval('u'));
|
||||
assertEquals(6, eval('v'));
|
||||
}
|
||||
}
|
||||
|
||||
f2(1);
|
||||
|
||||
// Lookup in and through block contexts.
|
||||
function f3(one) {
|
||||
var x = one + 1;
|
||||
let y = one + 2;
|
||||
const u = one + 4;
|
||||
{
|
||||
let z = one + 3;
|
||||
const v = one + 5;
|
||||
assertEquals(1, one);
|
||||
assertEquals(2, x);
|
||||
assertEquals(3, y);
|
||||
assertEquals(4, z);
|
||||
assertEquals(5, u);
|
||||
assertEquals(6, v);
|
||||
}
|
||||
}
|
||||
for (var j = 0; j < 5; ++j) f3(1);
|
||||
%OptimizeFunctionOnNextCall(f3);
|
||||
f3(1);
|
||||
assertTrue(%GetOptimizationStatus(f3) != 2);
|
||||
|
||||
|
||||
|
||||
// Dynamic lookup from closure.
|
||||
function f4(one) {
|
||||
var x = one + 1;
|
||||
let y = one + 2;
|
||||
const u = one + 4;
|
||||
{
|
||||
let z = one + 3;
|
||||
const v = one + 5;
|
||||
function f() {
|
||||
assertEquals(1, eval('one'));
|
||||
assertEquals(2, eval('x'));
|
||||
assertEquals(3, eval('y'));
|
||||
assertEquals(4, eval('z'));
|
||||
assertEquals(5, eval('u'));
|
||||
assertEquals(6, eval('v'));
|
||||
}
|
||||
f();
|
||||
}
|
||||
}
|
||||
f4(1);
|
||||
|
||||
|
||||
// Lookup from closure.
|
||||
function f5(one) {
|
||||
var x = one + 1;
|
||||
let y = one + 2;
|
||||
const u = one + 4;
|
||||
{
|
||||
let z = one + 3;
|
||||
const v = one + 5;
|
||||
function f() {
|
||||
assertEquals(1, one);
|
||||
assertEquals(2, x);
|
||||
assertEquals(3, y);
|
||||
assertEquals(4, z);
|
||||
assertEquals(5, u);
|
||||
assertEquals(6, v);
|
||||
}
|
||||
f();
|
||||
}
|
||||
}
|
||||
f5(1);
|
||||
|
||||
|
||||
// Return from block.
|
||||
function f6() {
|
||||
let x = 1;
|
||||
const u = 3;
|
||||
{
|
||||
let y = 2;
|
||||
const v = 4;
|
||||
return x + y;
|
||||
}
|
||||
}
|
||||
assertEquals(3, f6(6));
|
||||
|
||||
|
||||
// Variable shadowing and lookup.
|
||||
function f7(a) {
|
||||
let b = 1;
|
||||
var c = 1;
|
||||
var d = 1;
|
||||
const e = 1;
|
||||
{ // let variables shadowing argument, let, const and var variables
|
||||
let a = 2;
|
||||
let b = 2;
|
||||
let c = 2;
|
||||
let e = 2;
|
||||
assertEquals(2,a);
|
||||
assertEquals(2,b);
|
||||
assertEquals(2,c);
|
||||
assertEquals(2,e);
|
||||
}
|
||||
{ // const variables shadowing argument, let, const and var variables
|
||||
const a = 2;
|
||||
const b = 2;
|
||||
const c = 2;
|
||||
const e = 2;
|
||||
assertEquals(2,a);
|
||||
assertEquals(2,b);
|
||||
assertEquals(2,c);
|
||||
assertEquals(2,e);
|
||||
}
|
||||
try {
|
||||
throw 'stuff1';
|
||||
} catch (a) {
|
||||
assertEquals('stuff1',a);
|
||||
// catch variable shadowing argument
|
||||
a = 2;
|
||||
assertEquals(2,a);
|
||||
{
|
||||
// let variable shadowing catch variable
|
||||
let a = 3;
|
||||
assertEquals(3,a);
|
||||
try {
|
||||
throw 'stuff2';
|
||||
} catch (a) {
|
||||
assertEquals('stuff2',a);
|
||||
// catch variable shadowing let variable
|
||||
a = 4;
|
||||
assertEquals(4,a);
|
||||
}
|
||||
assertEquals(3,a);
|
||||
}
|
||||
assertEquals(2,a);
|
||||
}
|
||||
try {
|
||||
throw 'stuff3';
|
||||
} catch (c) {
|
||||
// catch variable shadowing var variable
|
||||
assertEquals('stuff3',c);
|
||||
{
|
||||
// const variable shadowing catch variable
|
||||
const c = 3;
|
||||
assertEquals(3,c);
|
||||
}
|
||||
assertEquals('stuff3',c);
|
||||
try {
|
||||
throw 'stuff4';
|
||||
} catch(c) {
|
||||
assertEquals('stuff4',c);
|
||||
// catch variable shadowing catch variable
|
||||
c = 3;
|
||||
assertEquals(3,c);
|
||||
}
|
||||
(function(c) {
|
||||
// argument shadowing catch variable
|
||||
c = 3;
|
||||
assertEquals(3,c);
|
||||
})();
|
||||
assertEquals('stuff3', c);
|
||||
(function() {
|
||||
// var variable shadowing catch variable
|
||||
var c = 3;
|
||||
})();
|
||||
assertEquals('stuff3', c);
|
||||
c = 2;
|
||||
}
|
||||
assertEquals(1,c);
|
||||
(function(a,b,c,e) {
|
||||
// arguments shadowing argument, let, const and var variable
|
||||
a = 2;
|
||||
b = 2;
|
||||
c = 2;
|
||||
e = 2;
|
||||
assertEquals(2,a);
|
||||
assertEquals(2,b);
|
||||
assertEquals(2,c);
|
||||
assertEquals(2,e);
|
||||
// var variable shadowing var variable
|
||||
var d = 2;
|
||||
})(1,1);
|
||||
assertEquals(1,a);
|
||||
assertEquals(1,b);
|
||||
assertEquals(1,c);
|
||||
assertEquals(1,d);
|
||||
assertEquals(1,e);
|
||||
}
|
||||
f7(1);
|
||||
|
||||
|
||||
// Ensure let and const variables are block local
|
||||
// and var variables function local.
|
||||
function f8() {
|
||||
var let_accessors = [];
|
||||
var var_accessors = [];
|
||||
var const_accessors = [];
|
||||
for (var i = 0; i < 10; i++) {
|
||||
let x = i;
|
||||
var y = i;
|
||||
const z = i;
|
||||
let_accessors[i] = function() { return x; }
|
||||
var_accessors[i] = function() { return y; }
|
||||
const_accessors[i] = function() { return z; }
|
||||
}
|
||||
for (var j = 0; j < 10; j++) {
|
||||
y = j + 10;
|
||||
assertEquals(j, let_accessors[j]());
|
||||
assertEquals(y, var_accessors[j]());
|
||||
assertEquals(j, const_accessors[j]());
|
||||
}
|
||||
}
|
||||
f8();
|
34
test/mjsunit/harmony/block-scoping-top-level-sloppy.js
Normal file
34
test/mjsunit/harmony/block-scoping-top-level-sloppy.js
Normal file
@ -0,0 +1,34 @@
|
||||
// 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: --min-preparse-length=0
|
||||
// Flags: --no-legacy-const --harmony-sloppy
|
||||
|
||||
let xxx = 1;
|
||||
let f = undefined;
|
||||
{
|
||||
let inner_x = xxx;
|
||||
f = function() { return inner_x; };
|
||||
}
|
||||
|
||||
assertSame(1, f());
|
||||
|
||||
xxx = 42;
|
||||
{
|
||||
f = function() { return inner_x1; };
|
||||
let inner_x1 = xxx;
|
||||
}
|
||||
|
||||
assertSame(42, f());
|
||||
|
||||
xxx = 31;
|
||||
{
|
||||
let inner_x1 = xxx;
|
||||
try {
|
||||
throw new Error();
|
||||
} catch (e) {
|
||||
f = function() { return inner_x1; };
|
||||
}
|
||||
}
|
||||
assertSame(31, f());
|
Loading…
Reference in New Issue
Block a user