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)) {
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;
}
-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);
// 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
// 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
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);
+})();
// 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() { }
})();
+(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 {