From 5940b05e9ff078788b3e46348491c91d952a2d27 Mon Sep 17 00:00:00 2001 From: Dmitry Panov Date: Wed, 27 Jul 2022 09:46:19 +0100 Subject: [PATCH] Fixed this binding initialisation. Fixes #415. (cherry picked from commit a070957bbee3b9f34e92638b7bea615e5b074050) --- compiler.go | 1 + compiler_expr.go | 4 ++-- compiler_test.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/compiler.go b/compiler.go index 0595483a..280f2420 100644 --- a/compiler.go +++ b/compiler.go @@ -431,6 +431,7 @@ func (p *Program) _dumpCode(indent string, logger func(format string, args ...in if f.initFields != nil { dumpInitFields(f.initFields) } + prg = f.ctor case *newStaticFieldInit: if f.initFields != nil { dumpInitFields(f.initFields) diff --git a/compiler_expr.go b/compiler_expr.go index 288bfb41..86683504 100644 --- a/compiler_expr.go +++ b/compiler_expr.go @@ -1615,10 +1615,10 @@ func (e *compiledFunctionLiteral) compile() (prg *Program, name unistring.String stashSize, stackSize := s.finaliseVarAlloc(0) - if stackSize > 0 && thisBinding != nil && thisBinding.inStash { + if thisBinding != nil && thisBinding.inStash && (!s.argsInStash || stackSize > 0) { delta++ code[preambleLen-delta] = loadStack(0) - } + } // otherwise, 'this' will be at stack[sp-1], no need to load if !s.strict && thisBinding != nil { delta++ diff --git a/compiler_test.go b/compiler_test.go index 8fba3ab6..1b0d0b62 100644 --- a/compiler_test.go +++ b/compiler_test.go @@ -5502,6 +5502,52 @@ func TestKeywordsAsLabels(t *testing.T) { testScript(SCRIPT, _undefined, t) } +func TestThisResolutionWithArg(t *testing.T) { + const SCRIPT = ` + let capture; + function f(arg) { + capture = () => this; // move 'this' to stash + return [this, arg]; + } + const _this = {}; + const arg = {}; + const [_this1, arg1] = f.call(_this, arg); + _this1 === _this && arg1 === arg; + ` + testScript(SCRIPT, valueTrue, t) +} + +func TestThisResolutionArgInStash(t *testing.T) { + const SCRIPT = ` + let capture; + function f(arg) { + capture = () => this + arg; // move 'this' and arguments to stash + return [this, arg]; + } + const _this = {}; + const arg = {}; + const [_this1, arg1] = f.call(_this, arg); + _this1 === _this && arg1 === arg; + ` + testScript(SCRIPT, valueTrue, t) +} + +func TestThisResolutionWithStackVar(t *testing.T) { + const SCRIPT = ` + let capture; + function f(arg) { + const _ = 1; // a stack variable + capture = () => this + arg; // move 'this' and arguments to stash + return [this, arg]; + } + const _this = {}; + const arg = {}; + const [_this1, arg1] = f.call(_this, arg); + _this1 === _this && arg1 === arg; + ` + testScript(SCRIPT, valueTrue, t) +} + /* func TestBabel(t *testing.T) { src, err := ioutil.ReadFile("babel7.js")