Commit 47d3bb1c authored by rossberg's avatar rossberg Committed by Commit bot

[es6] Fix function context check for super and new.target

R=adamk@chromium.org
BUG=v8:3330
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#29803}
parent 8de3518e
......@@ -3504,13 +3504,7 @@ ParserBase<Traits>::ParseSuperExpression(bool is_new,
int pos = position();
Expect(Token::SUPER, CHECK_OK);
Scope* scope = scope_->DeclarationScope();
while (scope->is_eval_scope() || scope->is_arrow_scope()) {
scope = scope->outer_scope();
DCHECK_NOT_NULL(scope);
scope = scope->DeclarationScope();
}
Scope* scope = scope_->ReceiverScope();
FunctionKind kind = scope->function_kind();
if (IsConciseMethod(kind) || IsAccessorFunction(kind) ||
i::IsConstructor(kind)) {
......@@ -3548,14 +3542,7 @@ ParserBase<Traits>::ParseNewTargetExpression(bool* ok) {
Consume(Token::PERIOD);
ExpectContextualKeyword(CStrVector("target"), CHECK_OK);
Scope* scope = scope_->DeclarationScope();
while (scope->is_eval_scope() || scope->is_arrow_scope()) {
scope = scope->outer_scope();
DCHECK_NOT_NULL(scope);
scope = scope->DeclarationScope();
}
if (!scope->is_function_scope()) {
if (!scope_->ReceiverScope()->is_function_scope()) {
ReportMessageAt(scanner()->location(),
MessageTemplate::kUnexpectedNewTarget);
*ok = false;
......
......@@ -763,24 +763,26 @@ int Scope::ContextChainLength(Scope* scope) {
}
Scope* Scope::ScriptScope() {
Scope* Scope::DeclarationScope() {
Scope* scope = this;
while (!scope->is_script_scope()) {
while (!scope->is_declaration_scope()) {
scope = scope->outer_scope();
}
return scope;
}
Scope* Scope::DeclarationScope() {
Scope* Scope::ReceiverScope() {
Scope* scope = this;
while (!scope->is_declaration_scope()) {
while (!scope->is_script_scope() &&
(!scope->is_function_scope() || scope->is_arrow_scope())) {
scope = scope->outer_scope();
}
return scope;
}
Handle<ScopeInfo> Scope::GetScopeInfo(Isolate* isolate) {
if (scope_info_.is_null()) {
scope_info_ = ScopeInfo::Create(isolate, zone(), this);
......
......@@ -483,15 +483,14 @@ class Scope: public ZoneObject {
// The number of contexts between this and scope; zero if this == scope.
int ContextChainLength(Scope* scope);
// Find the script scope.
// Used in modules implemenetation to find hosting scope.
// TODO(rossberg): is this needed?
Scope* ScriptScope();
// Find the first function, global, or eval scope. This is the scope
// where var declarations will be hoisted to in the implementation.
// Find the first function, script, eval or (declaration) block scope. This is
// the scope where var declarations will be hoisted to in the implementation.
Scope* DeclarationScope();
// Find the first (non-arrow) function or script scope. This is where
// 'this' is bound, and what determines the function kind.
Scope* ReceiverScope();
Handle<ScopeInfo> GetScopeInfo(Isolate* isolate);
// Get the chain of nested scopes within this scope for the source statement
......
......@@ -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-new-target --harmony-reflect
// Flags: --harmony-new-target --harmony-reflect --harmony-destructuring
// Flags: --harmony-rest-parameters --harmony-arrow-functions
......@@ -368,3 +368,17 @@
a2 = 3;
f(1, 2, 3);
})();
(function TestOtherScopes() {
function f1() { return eval("'use strict'; new.target") }
assertSame(f1, new f1);
function f2() { with ({}) return new.target }
assertSame(f2, new f2);
function f3({a}) { return new.target }
assertSame(f3, new f3({}));
function f4(...a) { return new.target }
assertSame(f4, new f4);
function f5() { 'use strict'; { let x; return new.target } }
assertSame(f5, new f5);
})();
......@@ -3,7 +3,8 @@
// found in the LICENSE file.
// Flags: --harmony-arrow-functions --allow-natives-syntax
// Flags: --harmony-spreadcalls
// Flags: --harmony-spreadcalls --harmony-destructuring
// Flags: --harmony-rest-parameters --harmony-sloppy
(function TestSuperNamedLoads() {
function Base() { }
......@@ -2122,6 +2123,34 @@ TestKeyedSetterCreatingOwnPropertiesNonConfigurable(42, 43, 44);
})();
(function TestSuperInOtherScopes() {
var p = {x: 99};
var o0 = {__proto__: p, f() { return eval("'use strict'; super.x") }};
assertEquals(p.x, o0.f());
var o1 = {__proto__: p, f() { with ({}) return super.x }};
assertEquals(p.x, o1.f());
var o2 = {__proto__: p, f({a}) { return super.x }};
assertEquals(p.x, o2.f({}));
var o3 = {__proto__: p, f(...a) { return super.x }};
assertEquals(p.x, o3.f());
var o4 = {__proto__: p, f() { 'use strict'; { let x; return super.x } }};
assertEquals(p.x, o4.f());
})();
(function TestSuperCallInOtherScopes() {
class C {constructor() { this.x = 99 }}
class D0 extends C {constructor() { eval("'use strict'; super()") }}
assertEquals(99, (new D0).x);
class D2 extends C {constructor({a}) { super() }}
assertEquals(99, (new D2({})).x);
class D3 extends C {constructor(...a) { super() }}
assertEquals(99, (new D3()).x);
class D4 extends C {constructor() { { let x; super() } }}
assertEquals(99, (new D4).x);
})();
(function TestSuperCallInEval() {
'use strict';
class Base {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment