Selaa lähdekoodia

Fixed this binding initialisation. Fixes #415.

Dmitry Panov 3 vuotta sitten
vanhempi
commit
a070957bbe
3 muutettua tiedostoa jossa 49 lisäystä ja 2 poistoa
  1. 1 0
      compiler.go
  2. 2 2
      compiler_expr.go
  3. 46 0
      compiler_test.go

+ 1 - 0
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)

+ 2 - 2
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++

+ 46 - 0
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")