Commit eb4ebf98 authored by Sathya Gunasekaran's avatar Sathya Gunasekaran Committed by Commit Bot

[class] Initialize class fields after binding this

Class fields needs to be initialized after `this` is bound, as per the
new spec change:
https://github.com/tc39/proposal-class-fields/pull/92

This CL moves the initialization of `this` from parser desugaring to
the bytecode generator.

Bug: v8:7647
Change-Id: I20f749403e5a4d2f06a39726cf39012ceb541987
Reviewed-on: https://chromium-review.googlesource.com/1014383Reviewed-by: 's avatarMythri Alle <mythria@chromium.org>
Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52646}
parent a0a4c71e
...@@ -3639,6 +3639,16 @@ void BytecodeGenerator::VisitCallSuper(Call* expr) { ...@@ -3639,6 +3639,16 @@ void BytecodeGenerator::VisitCallSuper(Call* expr) {
} }
} }
// Explicit calls to the super constructor using super() perform an
// implicit binding assignment to the 'this' variable.
//
// Default constructors don't need have to do the assignment because
// 'this' isn't accessed in default constructors.
if (!IsDefaultConstructor(info()->literal()->kind())) {
BuildVariableAssignment(super->this_var()->var(), Token::INIT,
HoleCheckMode::kRequired);
}
// The derived constructor has the correct bit set always, so we // The derived constructor has the correct bit set always, so we
// don't emit code to load and call the initializer if not // don't emit code to load and call the initializer if not
// required. // required.
......
...@@ -3424,24 +3424,12 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) { ...@@ -3424,24 +3424,12 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) {
Call::PossiblyEval is_possibly_eval = Call::PossiblyEval is_possibly_eval =
CheckPossibleEvalCall(result, scope()); CheckPossibleEvalCall(result, scope());
bool is_super_call = result->IsSuperCallReference();
if (spread_pos.IsValid()) { if (spread_pos.IsValid()) {
result = impl()->SpreadCall(result, args, pos, is_possibly_eval); result = impl()->SpreadCall(result, args, pos, is_possibly_eval);
} else { } else {
result = factory()->NewCall(result, args, pos, is_possibly_eval); result = factory()->NewCall(result, args, pos, is_possibly_eval);
} }
// Explicit calls to the super constructor using super() perform an
// implicit binding assignment to the 'this' variable.
if (is_super_call) {
classifier()->RecordAssignmentPatternError(
Scanner::Location(pos, scanner()->location().end_pos),
MessageTemplate::kInvalidDestructuringTarget);
ExpressionT this_expr = impl()->ThisExpression(pos);
result =
factory()->NewAssignment(Token::INIT, this_expr, result, pos);
}
if (fni_ != nullptr) fni_->RemoveLastFunction(); if (fni_ != nullptr) fni_->RemoveLastFunction();
break; break;
} }
......
...@@ -104,7 +104,7 @@ snippet: " ...@@ -104,7 +104,7 @@ snippet: "
test = new B().constructor; test = new B().constructor;
})(); })();
" "
frame size: 5 frame size: 6
parameter count: 1 parameter count: 1
bytecode array length: 40 bytecode array length: 40
bytecodes: [ bytecodes: [
...@@ -116,14 +116,14 @@ bytecodes: [ ...@@ -116,14 +116,14 @@ bytecodes: [
B(Star), R(4), B(Star), R(4),
B(Ldar), R(0), B(Ldar), R(0),
/* 118 E> */ B(Construct), R(3), R(4), U8(1), U8(0), /* 118 E> */ B(Construct), R(3), R(4), U8(1), U8(0),
B(Star), R(2), B(Star), R(5),
B(Ldar), R(this), B(Ldar), R(this),
/* 118 E> */ B(ThrowSuperAlreadyCalledIfNotHole), B(ThrowSuperAlreadyCalledIfNotHole),
B(Mov), R(2), R(this), B(Mov), R(5), R(this),
/* 128 S> */ B(Ldar), R(this), /* 128 S> */ B(Ldar), R(this),
B(ThrowSuperNotCalledIfHole), B(ThrowSuperNotCalledIfHole),
B(LdaSmi), I8(2), B(LdaSmi), I8(2),
/* 136 E> */ B(StaNamedProperty), R(2), U8(0), U8(2), /* 136 E> */ B(StaNamedProperty), R(this), U8(0), U8(2),
B(Ldar), R(this), B(Ldar), R(this),
B(ThrowSuperNotCalledIfHole), B(ThrowSuperNotCalledIfHole),
/* 141 S> */ B(Return), /* 141 S> */ B(Return),
...@@ -147,7 +147,7 @@ snippet: " ...@@ -147,7 +147,7 @@ snippet: "
test = new B().constructor; test = new B().constructor;
})(); })();
" "
frame size: 4 frame size: 5
parameter count: 1 parameter count: 1
bytecode array length: 36 bytecode array length: 36
bytecodes: [ bytecodes: [
...@@ -157,14 +157,14 @@ bytecodes: [ ...@@ -157,14 +157,14 @@ bytecodes: [
B(GetSuperConstructor), R(3), B(GetSuperConstructor), R(3),
B(Ldar), R(0), B(Ldar), R(0),
/* 117 E> */ B(Construct), R(3), R(0), U8(0), U8(0), /* 117 E> */ B(Construct), R(3), R(0), U8(0), U8(0),
B(Star), R(2), B(Star), R(4),
B(Ldar), R(this), B(Ldar), R(this),
/* 117 E> */ B(ThrowSuperAlreadyCalledIfNotHole), B(ThrowSuperAlreadyCalledIfNotHole),
B(Mov), R(2), R(this), B(Mov), R(4), R(this),
/* 126 S> */ B(Ldar), R(this), /* 126 S> */ B(Ldar), R(this),
B(ThrowSuperNotCalledIfHole), B(ThrowSuperNotCalledIfHole),
B(LdaSmi), I8(2), B(LdaSmi), I8(2),
/* 134 E> */ B(StaNamedProperty), R(2), U8(0), U8(2), /* 134 E> */ B(StaNamedProperty), R(this), U8(0), U8(2),
B(Ldar), R(this), B(Ldar), R(this),
B(ThrowSuperNotCalledIfHole), B(ThrowSuperNotCalledIfHole),
/* 139 S> */ B(Return), /* 139 S> */ B(Return),
......
...@@ -49,7 +49,7 @@ snippet: " ...@@ -49,7 +49,7 @@ snippet: "
test = new B(1, 2, 3).constructor; test = new B(1, 2, 3).constructor;
})(); })();
" "
frame size: 8 frame size: 9
parameter count: 1 parameter count: 1
bytecode array length: 40 bytecode array length: 40
bytecodes: [ bytecodes: [
...@@ -65,10 +65,10 @@ bytecodes: [ ...@@ -65,10 +65,10 @@ bytecodes: [
B(Ldar), R(0), B(Ldar), R(0),
B(Mov), R(2), R(7), B(Mov), R(2), R(7),
/* 140 E> */ B(ConstructWithSpread), R(5), R(6), U8(2), U8(0), /* 140 E> */ B(ConstructWithSpread), R(5), R(6), U8(2), U8(0),
B(Star), R(4), B(Star), R(8),
B(Ldar), R(this), B(Ldar), R(this),
/* 140 E> */ B(ThrowSuperAlreadyCalledIfNotHole), B(ThrowSuperAlreadyCalledIfNotHole),
B(Mov), R(4), R(this), B(Mov), R(8), R(this),
B(Ldar), R(this), B(Ldar), R(this),
B(ThrowSuperNotCalledIfHole), B(ThrowSuperNotCalledIfHole),
/* 159 S> */ B(Return), /* 159 S> */ B(Return),
...@@ -142,10 +142,10 @@ bytecodes: [ ...@@ -142,10 +142,10 @@ bytecodes: [
B(Mov), R(6), R(9), B(Mov), R(6), R(9),
B(Mov), R(0), R(10), B(Mov), R(0), R(10),
/* 140 E> */ B(CallJSRuntime), U8(%reflect_construct), R(8), U8(3), /* 140 E> */ B(CallJSRuntime), U8(%reflect_construct), R(8), U8(3),
B(Star), R(4), B(Star), R(11),
B(Ldar), R(this), B(Ldar), R(this),
/* 140 E> */ B(ThrowSuperAlreadyCalledIfNotHole), B(ThrowSuperAlreadyCalledIfNotHole),
B(Mov), R(4), R(this), B(Mov), R(11), R(this),
B(Ldar), R(this), B(Ldar), R(this),
B(ThrowSuperNotCalledIfHole), B(ThrowSuperNotCalledIfHole),
/* 162 S> */ B(Return), /* 162 S> */ B(Return),
......
...@@ -507,7 +507,7 @@ x()(); ...@@ -507,7 +507,7 @@ x()();
} }
assertThrows(() => new C1, ReferenceError); assertThrows(() => new C1, ReferenceError);
assertEquals([1,1], log); assertEquals([1], log);
log = []; log = [];
class C2 extends class {} { class C2 extends class {} {
...@@ -520,7 +520,7 @@ x()(); ...@@ -520,7 +520,7 @@ x()();
} }
assertThrows(() => new C2, ReferenceError); assertThrows(() => new C2, ReferenceError);
assertEquals([1,1], log); assertEquals([1], log);
} }
{ {
...@@ -696,3 +696,21 @@ x()(); ...@@ -696,3 +696,21 @@ x()();
let x = new X; let x = new X;
assertEquals(1, x.p); assertEquals(1, x.p);
} }
{
let thisInInitializer, thisInConstructor, thisFromArrowFn, arrowFn;
let C = class extends class {} {
field = (thisInInitializer = this, thisFromArrowFn = arrowFn());
constructor() {
arrowFn = () => this;
super();
thisInConstructor = this;
}
};
let c = new C();
assertSame(thisInInitializer, c);
assertSame(thisFromArrowFn, c);
assertSame(thisInConstructor, c);
}
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