[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/1014383 Reviewed-by: Mythri Alle <mythria@chromium.org> Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org> Cr-Commit-Position: refs/heads/master@{#52646}
This commit is contained in:
parent
a0a4c71e3f
commit
eb4ebf98c9
@ -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
|
||||
// don't emit code to load and call the initializer if not
|
||||
// required.
|
||||
|
@ -3424,24 +3424,12 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) {
|
||||
Call::PossiblyEval is_possibly_eval =
|
||||
CheckPossibleEvalCall(result, scope());
|
||||
|
||||
bool is_super_call = result->IsSuperCallReference();
|
||||
if (spread_pos.IsValid()) {
|
||||
result = impl()->SpreadCall(result, args, pos, is_possibly_eval);
|
||||
} else {
|
||||
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();
|
||||
break;
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ snippet: "
|
||||
test = new B().constructor;
|
||||
})();
|
||||
"
|
||||
frame size: 5
|
||||
frame size: 6
|
||||
parameter count: 1
|
||||
bytecode array length: 40
|
||||
bytecodes: [
|
||||
@ -116,14 +116,14 @@ bytecodes: [
|
||||
B(Star), R(4),
|
||||
B(Ldar), R(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),
|
||||
/* 118 E> */ B(ThrowSuperAlreadyCalledIfNotHole),
|
||||
B(Mov), R(2), R(this),
|
||||
B(ThrowSuperAlreadyCalledIfNotHole),
|
||||
B(Mov), R(5), R(this),
|
||||
/* 128 S> */ B(Ldar), R(this),
|
||||
B(ThrowSuperNotCalledIfHole),
|
||||
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(ThrowSuperNotCalledIfHole),
|
||||
/* 141 S> */ B(Return),
|
||||
@ -147,7 +147,7 @@ snippet: "
|
||||
test = new B().constructor;
|
||||
})();
|
||||
"
|
||||
frame size: 4
|
||||
frame size: 5
|
||||
parameter count: 1
|
||||
bytecode array length: 36
|
||||
bytecodes: [
|
||||
@ -157,14 +157,14 @@ bytecodes: [
|
||||
B(GetSuperConstructor), R(3),
|
||||
B(Ldar), R(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),
|
||||
/* 117 E> */ B(ThrowSuperAlreadyCalledIfNotHole),
|
||||
B(Mov), R(2), R(this),
|
||||
B(ThrowSuperAlreadyCalledIfNotHole),
|
||||
B(Mov), R(4), R(this),
|
||||
/* 126 S> */ B(Ldar), R(this),
|
||||
B(ThrowSuperNotCalledIfHole),
|
||||
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(ThrowSuperNotCalledIfHole),
|
||||
/* 139 S> */ B(Return),
|
||||
|
@ -49,7 +49,7 @@ snippet: "
|
||||
test = new B(1, 2, 3).constructor;
|
||||
})();
|
||||
"
|
||||
frame size: 8
|
||||
frame size: 9
|
||||
parameter count: 1
|
||||
bytecode array length: 40
|
||||
bytecodes: [
|
||||
@ -65,10 +65,10 @@ bytecodes: [
|
||||
B(Ldar), R(0),
|
||||
B(Mov), R(2), R(7),
|
||||
/* 140 E> */ B(ConstructWithSpread), R(5), R(6), U8(2), U8(0),
|
||||
B(Star), R(4),
|
||||
B(Star), R(8),
|
||||
B(Ldar), R(this),
|
||||
/* 140 E> */ B(ThrowSuperAlreadyCalledIfNotHole),
|
||||
B(Mov), R(4), R(this),
|
||||
B(ThrowSuperAlreadyCalledIfNotHole),
|
||||
B(Mov), R(8), R(this),
|
||||
B(Ldar), R(this),
|
||||
B(ThrowSuperNotCalledIfHole),
|
||||
/* 159 S> */ B(Return),
|
||||
@ -142,10 +142,10 @@ bytecodes: [
|
||||
B(Mov), R(6), R(9),
|
||||
B(Mov), R(0), R(10),
|
||||
/* 140 E> */ B(CallJSRuntime), U8(%reflect_construct), R(8), U8(3),
|
||||
B(Star), R(4),
|
||||
B(Star), R(11),
|
||||
B(Ldar), R(this),
|
||||
/* 140 E> */ B(ThrowSuperAlreadyCalledIfNotHole),
|
||||
B(Mov), R(4), R(this),
|
||||
B(ThrowSuperAlreadyCalledIfNotHole),
|
||||
B(Mov), R(11), R(this),
|
||||
B(Ldar), R(this),
|
||||
B(ThrowSuperNotCalledIfHole),
|
||||
/* 162 S> */ B(Return),
|
||||
|
@ -507,7 +507,7 @@ x()();
|
||||
}
|
||||
|
||||
assertThrows(() => new C1, ReferenceError);
|
||||
assertEquals([1,1], log);
|
||||
assertEquals([1], log);
|
||||
|
||||
log = [];
|
||||
class C2 extends class {} {
|
||||
@ -520,7 +520,7 @@ x()();
|
||||
}
|
||||
|
||||
assertThrows(() => new C2, ReferenceError);
|
||||
assertEquals([1,1], log);
|
||||
assertEquals([1], log);
|
||||
}
|
||||
|
||||
{
|
||||
@ -696,3 +696,21 @@ x()();
|
||||
let x = new X;
|
||||
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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user