Bug 1662559 - Part 17: Change BytecodeEmitter to use the new PrivateOpEmitter class. r=arai

Depends on D108298

Differential Revision: https://phabricator.services.mozilla.com/D108299
This commit is contained in:
Jason Orendorff 2021-04-19 19:28:10 +00:00
parent 10dffc1a2e
commit af06f97c61
8 changed files with 209 additions and 106 deletions

View File

@ -49,12 +49,13 @@
#include "frontend/NameOpEmitter.h" // NameOpEmitter
#include "frontend/ObjectEmitter.h" // PropertyEmitter, ObjectEmitter, ClassEmitter
#include "frontend/OptionalEmitter.h" // OptionalEmitter
#include "frontend/ParseNode.h" // ParseNodeKind, ParseNode and subclasses
#include "frontend/Parser.h" // Parser
#include "frontend/ParserAtom.h" // ParserAtomsTable
#include "frontend/PropOpEmitter.h" // PropOpEmitter
#include "frontend/SourceNotes.h" // SrcNote, SrcNoteType, SrcNoteWriter
#include "frontend/SwitchEmitter.h" // SwitchEmitter
#include "frontend/ParseNode.h" // ParseNodeKind, ParseNode and subclasses
#include "frontend/Parser.h" // Parser
#include "frontend/ParserAtom.h" // ParserAtomsTable
#include "frontend/PrivateOpEmitter.h" // PrivateOpEmitter
#include "frontend/PropOpEmitter.h" // PropOpEmitter
#include "frontend/SourceNotes.h" // SrcNote, SrcNoteType, SrcNoteWriter
#include "frontend/SwitchEmitter.h" // SwitchEmitter
#include "frontend/TaggedParserAtomIndexHasher.h" // TaggedParserAtomIndexHasher
#include "frontend/TDZCheckCache.h" // TDZCheckCache
#include "frontend/TryEmitter.h" // TryEmitter
@ -2091,14 +2092,17 @@ bool BytecodeEmitter::emitCallIncDec(UnaryNode* incDec) {
bool BytecodeEmitter::emitPrivateIncDec(UnaryNode* incDec) {
PrivateMemberAccess* privateExpr = &incDec->kid()->as<PrivateMemberAccess>();
ParseNodeKind kind = incDec->getKind();
ElemOpEmitter eoe(this, ConvertIncDecKind(kind),
ElemOpEmitter::ObjKind::Other, NameVisibility::Private);
if (!emitObjAndKey(&privateExpr->expression(), &privateExpr->privateName(),
eoe)) {
// [stack] OBJ KEY
PrivateOpEmitter xoe(this, ConvertIncDecKind(kind),
privateExpr->privateName().name());
if (!emitTree(&privateExpr->expression())) {
// [stack] OBJ
return false;
}
if (!eoe.emitIncDec()) {
if (!xoe.emitReference()) {
// [stack] OBJ NAME
return false;
}
if (!xoe.emitIncDec()) {
// [stack] RESULT
return false;
}
@ -2848,18 +2852,17 @@ bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target,
case ParseNodeKind::PrivateMemberExpr: {
PrivateMemberAccess* privateExpr = &target->as<PrivateMemberAccess>();
ElemOpEmitter eoe(this, ElemOpEmitter::Kind::SimpleAssignment,
ElemOpEmitter::ObjKind::Other, NameVisibility::Private);
if (!emitObjAndKey(&privateExpr->expression(),
&privateExpr->privateName(), eoe)) {
// [stack] OBJ KEY
PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::SimpleAssignment,
privateExpr->privateName().name());
if (!emitTree(&privateExpr->expression())) {
// [stack] OBJ
return false;
}
*emitted = 2;
if (!eoe.prepareForRhs()) {
// [stack] OBJ KEY
if (!xoe.emitReference()) {
// [stack] OBJ NAME
return false;
}
*emitted = xoe.numReferenceSlots();
break;
}
@ -2996,13 +2999,14 @@ bool BytecodeEmitter::emitSetOrInitializeDestructuring(
case ParseNodeKind::PrivateMemberExpr: {
// The reference is already pushed by emitDestructuringLHSRef.
// [stack] OBJ KEY VAL
ElemOpEmitter eoe(this, ElemOpEmitter::Kind::SimpleAssignment,
ElemOpEmitter::ObjKind::Other, NameVisibility::Private);
if (!eoe.skipObjAndKeyAndRhs()) {
// [stack] OBJ NAME VAL
PrivateMemberAccess* privateExpr = &target->as<PrivateMemberAccess>();
PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::SimpleAssignment,
privateExpr->privateName().name());
if (!xoe.skipReference()) {
return false;
}
if (!eoe.emitAssignment()) {
if (!xoe.emitAssignment()) {
// [stack] VAL
return false;
}
@ -4357,6 +4361,7 @@ bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs,
Maybe<NameOpEmitter> noe;
Maybe<PropOpEmitter> poe;
Maybe<ElemOpEmitter> eoe;
Maybe<PrivateOpEmitter> xoe;
// Deal with non-name assignments.
uint8_t offset = 1;
@ -4442,17 +4447,20 @@ bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs,
}
case ParseNodeKind::PrivateMemberExpr: {
PrivateMemberAccess* privateExpr = &lhs->as<PrivateMemberAccess>();
eoe.emplace(this,
isCompound ? ElemOpEmitter::Kind::CompoundAssignment
: isInit ? ElemOpEmitter::Kind::PropInit
: ElemOpEmitter::Kind::SimpleAssignment,
ElemOpEmitter::ObjKind::Other, NameVisibility::Private);
if (!emitObjAndKey(&privateExpr->expression(),
&privateExpr->privateName(), *eoe)) {
xoe.emplace(this,
isCompound ? PrivateOpEmitter::Kind::CompoundAssignment
: isInit ? PrivateOpEmitter::Kind::PropInit
: PrivateOpEmitter::Kind::SimpleAssignment,
privateExpr->privateName().name());
if (!emitTree(&privateExpr->expression())) {
// [stack] OBJ
return false;
}
if (!xoe->emitReference()) {
// [stack] OBJ KEY
return false;
}
offset += 2;
offset += xoe->numReferenceSlots();
break;
}
case ParseNodeKind::ArrayExpr:
@ -4492,14 +4500,20 @@ bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs,
}
break;
}
case ParseNodeKind::ElemExpr:
case ParseNodeKind::PrivateMemberExpr: {
case ParseNodeKind::ElemExpr: {
if (!eoe->emitGet()) {
// [stack] KEY THIS OBJ ELEM
return false;
}
break;
}
case ParseNodeKind::PrivateMemberExpr: {
if (!xoe->emitGet()) {
// [stack] OBJ KEY VALUE
return false;
}
break;
}
case ParseNodeKind::CallExpr:
// We just emitted a JSOp::ThrowMsg and popped the call's return
// value. Push a random value to make sure the stack depth is
@ -4535,7 +4549,6 @@ bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs,
}
break;
case ParseNodeKind::ElemExpr:
case ParseNodeKind::PrivateMemberExpr:
if (!eoe->prepareForRhs()) {
// [stack] # if Simple Assignment with Super
// [stack] THIS KEY SUPERBASE
@ -4548,6 +4561,9 @@ bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs,
return false;
}
break;
case ParseNodeKind::PrivateMemberExpr:
// no stack adjustment needed
break;
default:
break;
}
@ -4596,14 +4612,19 @@ bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs,
case ParseNodeKind::CallExpr:
// We threw above, so nothing to do here.
break;
case ParseNodeKind::ElemExpr:
case ParseNodeKind::PrivateMemberExpr: {
case ParseNodeKind::ElemExpr: {
if (!eoe->emitAssignment()) {
// [stack] VAL
return false;
}
break;
}
case ParseNodeKind::PrivateMemberExpr:
if (!xoe->emitAssignment()) {
// [stack] VAL
return false;
}
break;
case ParseNodeKind::ArrayExpr:
case ParseNodeKind::ObjectExpr:
if (!emitDestructuringOps(&lhs->as<ListNode>(),
@ -4645,6 +4666,7 @@ bool BytecodeEmitter::emitShortCircuitAssignment(AssignmentNode* node) {
Maybe<NameOpEmitter> noe;
Maybe<PropOpEmitter> poe;
Maybe<ElemOpEmitter> eoe;
Maybe<PrivateOpEmitter> xoe;
int32_t depth = bytecodeSection().stackDepth();
@ -4751,24 +4773,21 @@ bool BytecodeEmitter::emitShortCircuitAssignment(AssignmentNode* node) {
case ParseNodeKind::PrivateMemberExpr: {
PrivateMemberAccess* privateExpr = &lhs->as<PrivateMemberAccess>();
eoe.emplace(this, ElemOpEmitter::Kind::CompoundAssignment,
ElemOpEmitter::ObjKind::Other, NameVisibility::Private);
if (!emitObjAndKey(&privateExpr->expression(),
&privateExpr->privateName(), *eoe)) {
// [stack] OBJ KEY
xoe.emplace(this, PrivateOpEmitter::Kind::CompoundAssignment,
privateExpr->privateName().name());
if (!emitTree(&privateExpr->expression())) {
// [stack] OBJ
return false;
}
if (!eoe->emitGet()) {
// [stack] OBJ KEY LHS
if (!xoe->emitReference()) {
// [stack] OBJ NAME
return false;
}
if (!eoe->prepareForRhs()) {
// [stack] OBJ KEY LHS
if (!xoe->emitGet()) {
// [stack] OBJ NAME LHS
return false;
}
numPushed = 2;
numPushed = xoe->numReferenceSlots();
break;
}
@ -4817,8 +4836,7 @@ bool BytecodeEmitter::emitShortCircuitAssignment(AssignmentNode* node) {
break;
}
case ParseNodeKind::ElemExpr:
case ParseNodeKind::PrivateMemberExpr: {
case ParseNodeKind::ElemExpr: {
if (!eoe->emitAssignment()) {
// [stack] RHS
return false;
@ -4826,6 +4844,13 @@ bool BytecodeEmitter::emitShortCircuitAssignment(AssignmentNode* node) {
break;
}
case ParseNodeKind::PrivateMemberExpr:
if (!xoe->emitAssignment()) {
// [stack] RHS
return false;
}
break;
default:
MOZ_CRASH();
}
@ -7796,8 +7821,8 @@ bool BytecodeEmitter::emitOptionalCalleeAndThis(ParseNode* callee,
case ParseNodeKind::OptionalElemExpr: {
OptionalPropertyByValue* elem = &callee->as<OptionalPropertyByValue>();
bool isSuper = false;
bool isPrivate = elem->key().isKind(ParseNodeKind::PrivateName);
ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper, isPrivate);
MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName));
ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
// [stack] CALLEE THIS
return false;
@ -7807,8 +7832,8 @@ bool BytecodeEmitter::emitOptionalCalleeAndThis(ParseNode* callee,
case ParseNodeKind::ElemExpr: {
PropertyByValue* elem = &callee->as<PropertyByValue>();
bool isSuper = elem->isSuper();
bool isPrivate = elem->key().isKind(ParseNodeKind::PrivateName);
ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper, isPrivate);
MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName));
ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
// [stack] CALLEE THIS
return false;
@ -7820,10 +7845,9 @@ bool BytecodeEmitter::emitOptionalCalleeAndThis(ParseNode* callee,
case ParseNodeKind::OptionalPrivateMemberExpr: {
PrivateMemberAccessBase* privateExpr =
&callee->as<PrivateMemberAccessBase>();
bool isSuper = false;
bool isPrivate = true;
ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper, isPrivate);
if (!emitOptionalPrivateExpression(privateExpr, eoe, oe)) {
PrivateOpEmitter& xoe =
cone.prepareForPrivateCallee(privateExpr->privateName().name());
if (!emitOptionalPrivateExpression(privateExpr, xoe, oe)) {
// [stack] CALLEE THIS
return false;
}
@ -7909,8 +7933,8 @@ bool BytecodeEmitter::emitCalleeAndThis(ParseNode* callee, ParseNode* call,
MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting);
PropertyByValue* elem = &callee->as<PropertyByValue>();
bool isSuper = elem->isSuper();
bool isPrivate = elem->key().isKind(ParseNodeKind::PrivateName);
ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper, isPrivate);
MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName));
ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
if (!emitElemObjAndKey(elem, isSuper, eoe)) {
// [stack] # if Super
// [stack] THIS? THIS KEY
@ -7929,16 +7953,18 @@ bool BytecodeEmitter::emitCalleeAndThis(ParseNode* callee, ParseNode* call,
MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting);
PrivateMemberAccessBase* privateExpr =
&callee->as<PrivateMemberAccessBase>();
bool isSuper = false;
bool isPrivate = true;
ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper, isPrivate);
if (!emitObjAndKey(&privateExpr->expression(),
&privateExpr->privateName(), eoe)) {
// [stack] OBJ? OBJ KEY
PrivateOpEmitter& xoe =
cone.prepareForPrivateCallee(privateExpr->privateName().name());
if (!emitTree(&privateExpr->expression())) {
// [stack] OBJ
return false;
}
if (!eoe.emitGet()) {
// [stack] CALLEE THIS?
if (!xoe.emitReference()) {
// [stack] OBJ NAME
return false;
}
if (!xoe.emitGetForCallOrNew()) {
// [stack] CALLEE THIS
return false;
}
@ -8418,9 +8444,9 @@ bool BytecodeEmitter::emitOptionalTree(
case ParseNodeKind::PrivateMemberExpr:
case ParseNodeKind::OptionalPrivateMemberExpr: {
PrivateMemberAccessBase* privateExpr = &pn->as<PrivateMemberAccessBase>();
ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get,
ElemOpEmitter::ObjKind::Other, NameVisibility::Private);
if (!emitOptionalPrivateExpression(privateExpr, eoe, oe)) {
PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::Get,
privateExpr->privateName().name());
if (!emitOptionalPrivateExpression(privateExpr, xoe, oe)) {
return false;
}
break;
@ -8617,13 +8643,8 @@ bool BytecodeEmitter::emitOptionalElemExpression(PropertyByValueBase* elem,
}
bool BytecodeEmitter::emitOptionalPrivateExpression(
PrivateMemberAccessBase* privateExpr, ElemOpEmitter& eoe,
PrivateMemberAccessBase* privateExpr, PrivateOpEmitter& xoe,
OptionalEmitter& oe) {
if (!eoe.prepareForObj()) {
// [stack]
return false;
}
if (!emitOptionalTree(&privateExpr->expression(), oe)) {
// [stack] OBJ
return false;
@ -8639,18 +8660,13 @@ bool BytecodeEmitter::emitOptionalPrivateExpression(
}
}
if (!eoe.prepareForKey()) {
// [stack] OBJ? OBJ
if (!xoe.emitReference()) {
// [stack] OBJ NAME
return false;
}
if (!emitTree(&privateExpr->privateName())) {
// [stack] OBJ? OBJ KEY
return false;
}
if (!eoe.emitGet()) {
// [stack] ELEM
if (!xoe.emitGet()) {
// [stack] CALLEE THIS # if call
// [stack] VALUE # otherwise
return false;
}
@ -11362,14 +11378,17 @@ bool BytecodeEmitter::emitTree(
case ParseNodeKind::PrivateMemberExpr: {
PrivateMemberAccess* privateExpr = &pn->as<PrivateMemberAccess>();
ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get,
ElemOpEmitter::ObjKind::Other, NameVisibility::Private);
if (!emitObjAndKey(&privateExpr->expression(),
&privateExpr->privateName(), eoe)) {
// [stack] OBJ KEY
PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::Get,
privateExpr->privateName().name());
if (!emitTree(&privateExpr->expression())) {
// [stack] OBJ
return false;
}
if (!eoe.emitGet()) {
if (!xoe.emitReference()) {
// [stack] OBJ NAME
return false;
}
if (!xoe.emitGet()) {
// [stack] VALUE
return false;
}

View File

@ -37,6 +37,7 @@
#include "frontend/ParseNode.h" // ParseNode and subclasses
#include "frontend/Parser.h" // Parser, PropListType
#include "frontend/ParserAtom.h" // TaggedParserAtomIndex
#include "frontend/PrivateOpEmitter.h" // PrivateOpEmitter
#include "frontend/ScriptIndex.h" // ScriptIndex
#include "frontend/SharedContext.h" // SharedContext, TopLevelFunction
#include "frontend/SourceNotes.h" // SrcNoteType
@ -763,7 +764,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
bool isSuper,
OptionalEmitter& oe);
[[nodiscard]] bool emitOptionalPrivateExpression(
PrivateMemberAccessBase* privateExpr, ElemOpEmitter& eoe,
PrivateMemberAccessBase* privateExpr, PrivateOpEmitter& xoe,
OptionalEmitter& oe);
[[nodiscard]] bool emitOptionalCall(CallNode* callNode, OptionalEmitter& oe,
ValueUsage valueUsage);

View File

@ -57,19 +57,30 @@ bool CallOrNewEmitter::emitNameCallee(TaggedParserAtomIndex name) {
}
[[nodiscard]] ElemOpEmitter& CallOrNewEmitter::prepareForElemCallee(
bool isSuperElem, bool isPrivate) {
bool isSuperElem) {
MOZ_ASSERT(state_ == State::Start);
eoe_.emplace(bce_,
isCall() ? ElemOpEmitter::Kind::Call : ElemOpEmitter::Kind::Get,
isSuperElem ? ElemOpEmitter::ObjKind::Super
: ElemOpEmitter::ObjKind::Other,
isPrivate ? NameVisibility::Private : NameVisibility::Public);
NameVisibility::Public);
state_ = State::ElemCallee;
return *eoe_;
}
PrivateOpEmitter& CallOrNewEmitter::prepareForPrivateCallee(
TaggedParserAtomIndex privateName) {
MOZ_ASSERT(state_ == State::Start);
xoe_.emplace(
bce_,
isCall() ? PrivateOpEmitter::Kind::Call : PrivateOpEmitter::Kind::Get,
privateName);
state_ = State::PrivateCallee;
return *xoe_;
}
bool CallOrNewEmitter::prepareForFunctionCallee() {
MOZ_ASSERT(state_ == State::Start);
@ -106,8 +117,9 @@ bool CallOrNewEmitter::prepareForOtherCallee() {
bool CallOrNewEmitter::emitThis() {
MOZ_ASSERT(state_ == State::NameCallee || state_ == State::PropCallee ||
state_ == State::ElemCallee || state_ == State::FunctionCallee ||
state_ == State::SuperCallee || state_ == State::OtherCallee);
state_ == State::ElemCallee || state_ == State::PrivateCallee ||
state_ == State::FunctionCallee || state_ == State::SuperCallee ||
state_ == State::OtherCallee);
bool needsThis = false;
switch (state_) {
@ -128,6 +140,12 @@ bool CallOrNewEmitter::emitThis() {
needsThis = true;
}
break;
case State::PrivateCallee:
xoe_.reset();
if (!isCall()) {
needsThis = true;
}
break;
case State::FunctionCallee:
needsThis = true;
break;

View File

@ -15,6 +15,7 @@
#include "frontend/ElemOpEmitter.h"
#include "frontend/IfEmitter.h"
#include "frontend/ParserAtom.h" // TaggedParserAtomIndex
#include "frontend/PrivateOpEmitter.h"
#include "frontend/PropOpEmitter.h"
#include "frontend/ValueUsage.h"
#include "js/TypeDecls.h"
@ -63,6 +64,16 @@ struct BytecodeEmitter;
// emit(arg);
// cone.emitEnd(1, Some(offset_of_callee));
//
// `callee.#method(arg);`
// CallOrNewEmitter cone(this, JSOp::Call,
// CallOrNewEmitter::ArgumentsKind::Other,
// ValueUsage::WantValue);
// PrivateOpEmitter& xoe = cone.prepareForPrivateCallee();
// ... emit `callee.#method` with `xoe` here...
// cone.prepareForNonSpreadArguments();
// emit(arg);
// cone.emitEnd(1, Some(offset_of_callee));
//
// `(function() { ... })(arg);`
// CallOrNewEmitter cone(this, JSOp::Call,
// CallOrNewEmitter::ArgumentsKind::Other,
@ -159,6 +170,7 @@ class MOZ_STACK_CLASS CallOrNewEmitter {
mozilla::Maybe<PropOpEmitter> poe_;
mozilla::Maybe<ElemOpEmitter> eoe_;
mozilla::Maybe<PrivateOpEmitter> xoe_;
// The state of this emitter.
//
@ -174,6 +186,10 @@ class MOZ_STACK_CLASS CallOrNewEmitter {
// +------------------------->| ElemCallee |----->+
// | +------------+ |
// | |
// | prepareForPrivateCallee +---------------+ v
// +------------------------->| PrivateCallee |-->+
// | +---------------+ |
// | |
// | prepareForFunctionCallee +----------------+ v
// +------------------------->| FunctionCallee |->+
// | +----------------+ |
@ -221,6 +237,9 @@ class MOZ_STACK_CLASS CallOrNewEmitter {
// After calling prepareForElemCallee.
ElemCallee,
// After calling prepareForPrivateCallee.
PrivateCallee,
// After calling prepareForFunctionCallee.
FunctionCallee,
@ -287,8 +306,9 @@ class MOZ_STACK_CLASS CallOrNewEmitter {
public:
[[nodiscard]] bool emitNameCallee(TaggedParserAtomIndex name);
[[nodiscard]] PropOpEmitter& prepareForPropCallee(bool isSuperProp);
[[nodiscard]] ElemOpEmitter& prepareForElemCallee(bool isSuperElem,
bool isPrivateElem);
[[nodiscard]] ElemOpEmitter& prepareForElemCallee(bool isSuperElem);
[[nodiscard]] PrivateOpEmitter& prepareForPrivateCallee(
TaggedParserAtomIndex privateName);
[[nodiscard]] bool prepareForFunctionCallee();
[[nodiscard]] bool emitSuperCallee();
[[nodiscard]] bool prepareForOtherCallee();

View File

@ -149,8 +149,16 @@ bool PrivateOpEmitter::emitGet() {
// [stack] OBJ? OBJ NAME
return false;
}
if (isCompoundAssignment()) {
if (!bce_->emit1(JSOp::Dup2)) {
// [stack] OBJ? OBJ NAME OBJ NAME
return false;
}
}
if (!bce_->emitElemOpBase(JSOp::GetElem, ShouldInstrument::Yes)) {
// [stack] OBJ? VALUE
// [stack] OBJ? OBJ NAME VALUE
return false;
}
}

View File

@ -7,6 +7,16 @@ class B {
return 12;
}
#privF = () => { return 12; }
callPriv() {
return this.#priv();
}
callPrivF() {
return this.#privF();
}
#val = '';
set #x(x) {
this.#val = x + ' haha';
@ -18,8 +28,23 @@ class B {
ef(str) {
return evalInFrame(0, str);
}
callFunc(f) {
f();
}
}
var b = new B();
assertEq(b.ef(`this.#priv();`), 12);
assertEq(b.ef(`this.#x = 'Hi'; this.#x`), 'Hi haha');
assertEq(b.ef("this.callPriv()"), 12);
assertEq(b.ef("this.callPrivF()"), 12);
assertThrowsInstanceOf(() => b.ef(`this.callFunc(() => { this.#privF(); })`), Error);
// See EmitterScope::lookupPrivate for the reasoning here.
assertThrowsInstanceOf(() => b.ef(`this.#privF();`), Error);
assertThrowsInstanceOf(() => b.ef(`var x = () => { return this.#privF(); } x();`), Error);
assertThrowsInstanceOf(() => b.ef(`this.#priv();`), Error);
assertThrowsInstanceOf(() => b.ef(`var x = () => { return this.#priv(); } x();`), Error);
assertThrowsInstanceOf(() => b.ef(`this.#x = 'Hi'; this.#x`), Error);
assertThrowsInstanceOf(() => b.ef(`var x = () => { this.#x = 'Hi'; return this.#x} x();`), Error);

View File

@ -12,4 +12,4 @@ class B {
var b = new B();
assertEq(b.ef(`this.x`), 'his');
assertEq(b.ef(`this.#x`), 12);
assertThrowsInstanceOf(() => b.ef(`this.#x`), Error);

View File

@ -17,6 +17,15 @@ class A {
return o?.#x;
}
static orEqual(o, v) {
o.#x ||= v;
return o.#x;
}
setX(v) {
this.#x = v;
}
compoundInc() {
this.#x += 1;
return this.#x;
@ -65,6 +74,9 @@ for (var i = 0; i < 1000; i++) {
assertEq(a.x(), 11);
assertEq(A.readx(a), 11);
assertEq(a.compoundInc(), 12);
assertEq(A.orEqual(a, 13), 12);
a.setX(null);
assertEq(A.orEqual(a, 12), 12);
assertEq(a.compoundDec(), 11);
assertEq(a.invoke(), 'hi');
assertEq(a.gz(), 'static');