Skip to content

Commit

Permalink
Ensure ToPropertyKey happens earlier when assigning computed keys. Fixes
Browse files Browse the repository at this point in the history
 dop251#312.

Signed-off-by: Gabri <[email protected]>
  • Loading branch information
dop251 authored and Gabri3l committed Jan 24, 2022
1 parent c8bd2d4 commit cfff9ec
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 8 deletions.
4 changes: 3 additions & 1 deletion compiler_expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -1682,6 +1682,7 @@ func (e *compiledObjectLiteral) emitGetter(putOnStack bool) {
}
}
if computed {
e.c.emit(_toPropertyKey{})
valueExpr.emitGetter(true)
switch prop.Kind {
case ast.PropertyKindValue, ast.PropertyKindMethod:
Expand Down Expand Up @@ -2071,6 +2072,7 @@ func (c *compiler) emitObjectPattern(pattern *ast.ObjectPattern, emitAssign func
case *ast.PropertyKeyed:
c.emit(dup)
c.compileExpression(prop.Key).emitGetter(true)
c.emit(_toPropertyKey{})
var target ast.Expression
var initializer ast.Expression
if e, ok := prop.Value.(*ast.AssignExpression); ok {
Expand All @@ -2080,7 +2082,7 @@ func (c *compiler) emitObjectPattern(pattern *ast.ObjectPattern, emitAssign func
target = prop.Value
}
c.emitAssign(target, c.compilePatternInitExpr(func() {
c.emit(getElem)
c.emit(getKey)
}, initializer, prop.Idx0()), emitAssign)
default:
c.throwSyntaxError(int(prop.Idx0()-1), "Unsupported AssignmentProperty type: %T", prop)
Expand Down
42 changes: 39 additions & 3 deletions compiler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3588,12 +3588,22 @@ func TestObjectAssignmentPatternEvalOrder(t *testing.T) {
function prop1() {
trace += "prop1(),"
return "a";
return {
toString: function() {
trace += "prop1-to-string(),";
return "a";
}
}
}
function prop2() {
trace += "prop2(),";
return "b";
return {
toString: function() {
trace += "prop2-to-string(),";
return "b";
}
}
}
function target() {
Expand All @@ -3609,7 +3619,7 @@ func TestObjectAssignmentPatternEvalOrder(t *testing.T) {
}
trace;
`
testScript1(SCRIPT, asciiString("src(),prop1(),target(),get a,prop2(),"), t)
testScript1(SCRIPT, asciiString("src(),prop1(),prop1-to-string(),target(),get a,prop2(),prop2-to-string(),"), t)
}

func TestArrayAssignmentPatternEvalOrder(t *testing.T) {
Expand Down Expand Up @@ -3733,6 +3743,32 @@ func TestObjLiteralComputedKeys(t *testing.T) {
testScript1(SCRIPT, _undefined, t)
}

func TestObjLiteralComputedKeysEvalOrder(t *testing.T) {
const SCRIPT = `
let trace = [];
function key() {
trace.push("key");
return {
toString: function() {
trace.push("key-toString");
return "key";
}
}
}
function val() {
trace.push("val");
return "val";
}
const _ = {
[key()]: val(),
}
trace.join(",");
`
testScript1(SCRIPT, asciiString("key,key-toString,val"), t)
}

func TestArrayAssignPattern(t *testing.T) {
const SCRIPT = `
let a, b;
Expand Down
1 change: 1 addition & 0 deletions tc39_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ var (
"sec-evaldeclarationinstantiation",
"sec-integer-indexed-exotic-objects-defineownproperty-p-desc",
"sec-destructuring-binding-patterns",
"sec-runtime-semantics-keyeddestructuringassignmentevaluation",
}
)

Expand Down
34 changes: 30 additions & 4 deletions vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,14 @@ func (j jump) exec(vm *vm) {
vm.pc += int(j)
}

type _toPropertyKey struct{}

func (_toPropertyKey) exec(vm *vm) {
p := vm.sp - 1
vm.stack[p] = toPropertyKey(vm.stack[p])
vm.pc++
}

type _getElemRef struct{}

var getElemRef _getElemRef
Expand Down Expand Up @@ -1287,7 +1295,7 @@ var setElem1 _setElem1

func (_setElem1) exec(vm *vm) {
obj := vm.stack[vm.sp-3].ToObject(vm.r)
propName := toPropertyKey(vm.stack[vm.sp-2])
propName := vm.stack[vm.sp-2]
val := vm.stack[vm.sp-1]

obj.setOwn(propName, val, true)
Expand All @@ -1302,7 +1310,7 @@ var setElem1Named _setElem1Named

func (_setElem1Named) exec(vm *vm) {
obj := vm.stack[vm.sp-3].ToObject(vm.r)
propName := toPropertyKey(vm.stack[vm.sp-2])
propName := vm.stack[vm.sp-2]
val := vm.stack[vm.sp-1]
vm.r.toObject(val).self.defineOwnPropertyStr("name", PropertyDescriptor{
Value: propName,
Expand Down Expand Up @@ -1547,7 +1555,7 @@ var setPropGetter1 _setPropGetter1

func (s _setPropGetter1) exec(vm *vm) {
obj := vm.r.toObject(vm.stack[vm.sp-3])
propName := toPropertyKey(vm.stack[vm.sp-2])
propName := vm.stack[vm.sp-2]
val := vm.stack[vm.sp-1]
vm.r.toObject(val).self.defineOwnPropertyStr("name", PropertyDescriptor{
Value: asciiString("get ").concat(stringValueFromRaw(val.string())),
Expand All @@ -1572,7 +1580,7 @@ var setPropSetter1 _setPropSetter1

func (s _setPropSetter1) exec(vm *vm) {
obj := vm.r.toObject(vm.stack[vm.sp-3])
propName := toPropertyKey(vm.stack[vm.sp-2])
propName := vm.stack[vm.sp-2]
val := vm.stack[vm.sp-1]

vm.r.toObject(val).self.defineOwnPropertyStr("name", PropertyDescriptor{
Expand Down Expand Up @@ -1641,6 +1649,24 @@ func (_getElem) exec(vm *vm) {
vm.pc++
}

type _getKey struct{}

var getKey _getKey

func (_getKey) exec(vm *vm) {
v := vm.stack[vm.sp-2]
obj := v.baseObject(vm.r)
propName := vm.stack[vm.sp-1]
if obj == nil {
panic(vm.r.NewTypeError("Cannot read property '%s' of undefined", propName.String()))
}

vm.stack[vm.sp-2] = nilSafe(obj.get(propName, v))

vm.sp--
vm.pc++
}

type _getElemCallee struct{}

var getElemCallee _getElemCallee
Expand Down

0 comments on commit cfff9ec

Please sign in to comment.