Skip to content

Commit cb187b0

Browse files
committed
Fixed extra value left on stack when 'this' escapes to stash.
1 parent bcd7cc6 commit cb187b0

File tree

3 files changed

+89
-1
lines changed

3 files changed

+89
-1
lines changed

compiler.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,8 @@ func (s *scope) finaliseVarAlloc(stackOffset int) (stashSize, stackSize int) {
649649
*ap = loadThisStash(idx)
650650
case initStack:
651651
*ap = initStash(idx)
652+
case initStackP:
653+
*ap = initStashP(idx)
652654
case resolveThisStack:
653655
*ap = resolveThisStash(idx)
654656
case _ret:
@@ -665,6 +667,8 @@ func (s *scope) finaliseVarAlloc(stackOffset int) (stashSize, stackSize int) {
665667
*ap = loadStash(idx)
666668
case initStack:
667669
*ap = initStash(idx)
670+
case initStackP:
671+
*ap = initStashP(idx)
668672
default:
669673
s.c.assert(false, s.c.p.sourceOffset(pc), "Unsupported instruction for 'this'")
670674
}
@@ -734,6 +738,8 @@ func (s *scope) finaliseVarAlloc(stackOffset int) (stashSize, stackSize int) {
734738
*ap = loadThisStack{}
735739
case initStack:
736740
// no-op
741+
case initStackP:
742+
// no-op
737743
case resolveThisStack:
738744
// no-op
739745
case _ret:

compiler_expr.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1685,6 +1685,7 @@ func (e *compiledFunctionLiteral) compile() (prg *Program, name unistring.String
16851685
}
16861686
}
16871687

1688+
needInitThis := false
16881689
if thisBinding != nil {
16891690
if !s.isDynamic() && thisBinding.useCount() == 0 {
16901691
s.deleteBinding(thisBinding)
@@ -1693,13 +1694,15 @@ func (e *compiledFunctionLiteral) compile() (prg *Program, name unistring.String
16931694
if thisBinding.inStash || s.isDynamic() {
16941695
delta++
16951696
thisBinding.emitInitAtScope(s, preambleLen-delta)
1697+
needInitThis = true
16961698
}
16971699
}
16981700
}
16991701

17001702
stashSize, stackSize := s.finaliseVarAlloc(0)
17011703

1702-
if thisBinding != nil && thisBinding.inStash && (!s.argsInStash || stackSize > 0) {
1704+
if needInitThis && (s.numArgs > 0 && !s.argsInStash || stackSize > 0) {
1705+
code[preambleLen-delta] = initStashP(code[preambleLen-delta].(initStash))
17031706
delta++
17041707
code[preambleLen-delta] = loadStack(0)
17051708
} // otherwise, 'this' will be at stack[sp-1], no need to load

compiler_test.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5886,6 +5886,85 @@ func TestNestedDestructArray(t *testing.T) {
58865886
testScriptWithTestLib(SCRIPT, _undefined, t)
58875887
}
58885888

5889+
func TestThisInStash(t *testing.T) {
5890+
const SCRIPT = `
5891+
function f() {
5892+
globalThis.x = () => this; // move 'this' to stash
5893+
5894+
{
5895+
try {
5896+
throw new Error("boo!");
5897+
} catch (e) {
5898+
if (e.message !== 'boo!') {
5899+
throw new Error("unexpected exception value");
5900+
}
5901+
}
5902+
}
5903+
}
5904+
5905+
function f1() {
5906+
globalThis.x = () => this; // move 'this' to stash
5907+
var v; // introduce a stack variable
5908+
5909+
{
5910+
try {
5911+
throw new Error("boo!");
5912+
} catch (e) {
5913+
if (e.message !== 'boo!') {
5914+
throw new Error("unexpected exception value");
5915+
}
5916+
}
5917+
}
5918+
}
5919+
5920+
f();
5921+
f1();
5922+
`
5923+
testScript(SCRIPT, _undefined, t)
5924+
}
5925+
5926+
func TestThisInStashCtor(t *testing.T) {
5927+
const SCRIPT = `
5928+
class C extends Object {
5929+
constructor() {
5930+
super();
5931+
globalThis.x = () => this; // move 'this' to stash
5932+
{
5933+
try {
5934+
throw new Error("boo!");
5935+
} catch (e) {
5936+
if (e.message !== 'boo!') {
5937+
throw new Error("unexpected exception value");
5938+
}
5939+
}
5940+
}
5941+
}
5942+
}
5943+
5944+
class C1 extends Object {
5945+
constructor() {
5946+
super();
5947+
globalThis.x = () => this; // move 'this' to stash
5948+
var v; // introduce a stack variable
5949+
{
5950+
try {
5951+
throw new Error("boo!");
5952+
} catch (e) {
5953+
if (e.message !== 'boo!') {
5954+
throw new Error("unexpected exception value");
5955+
}
5956+
}
5957+
}
5958+
}
5959+
}
5960+
5961+
new C();
5962+
new C1();
5963+
undefined;
5964+
`
5965+
testScript(SCRIPT, _undefined, t)
5966+
}
5967+
58895968
/*
58905969
func TestBabel(t *testing.T) {
58915970
src, err := os.ReadFile("babel7.js")

0 commit comments

Comments
 (0)