소스 검색

Fixed callee expressions in optional chains. Fixes #385.

Dmitry Panov 3 년 전
부모
커밋
e1eca0b61f
3개의 변경된 파일31개의 추가작업 그리고 0개의 파일을 삭제
  1. 5 0
      compiler_expr.go
  2. 13 0
      compiler_test.go
  3. 13 0
      vm.go

+ 5 - 0
compiler_expr.go

@@ -2015,6 +2015,8 @@ func (c *compiler) emitCallee(callee compiledExpr) (calleeName unistring.String)
 		c.endOptChain()
 	case *compiledOptional:
 		c.emitCallee(callee.expr)
+		c.block.conts = append(c.block.conts, len(c.p.code))
+		c.emit(nil)
 	default:
 		c.emit(loadUndef)
 		callee.emitGetter(true)
@@ -2458,6 +2460,9 @@ func (c *compiler) endOptChain() {
 	for _, item := range c.block.breaks {
 		c.p.code[item] = jopt(lbl - item)
 	}
+	for _, item := range c.block.conts {
+		c.p.code[item] = joptc(lbl - item)
+	}
 	c.block = c.block.outer
 }
 

+ 13 - 0
compiler_test.go

@@ -4716,6 +4716,19 @@ func TestAssignBeforeInit(t *testing.T) {
 	testScriptWithTestLib(SCRIPT, _undefined, t)
 }
 
+func TestOptChainCallee(t *testing.T) {
+	const SCRIPT = `
+	var a;
+	assert.sameValue(a?.(true), undefined);
+	a = null;
+	assert.sameValue(a?.(), undefined);
+	var o = {n: null};
+	assert.sameValue(o.m?.(true), undefined);
+	assert.sameValue(o.n?.(true), undefined);
+	`
+	testScriptWithTestLib(SCRIPT, _undefined, t)
+}
+
 /*
 func TestBabel(t *testing.T) {
 	src, err := ioutil.ReadFile("babel7.js")

+ 13 - 0
vm.go

@@ -3376,6 +3376,19 @@ func (j jopt) exec(vm *vm) {
 	}
 }
 
+type joptc int32
+
+func (j joptc) exec(vm *vm) {
+	switch vm.stack[vm.sp-1].(type) {
+	case valueNull, valueUndefined, memberUnresolved:
+		vm.sp--
+		vm.stack[vm.sp-1] = _undefined
+		vm.pc += int(j)
+	default:
+		vm.pc++
+	}
+}
+
 type jcoalesc int32
 
 func (j jcoalesc) exec(vm *vm) {