Skip to content

Commit

Permalink
Improve coverage for reference type in various contexts
Browse files Browse the repository at this point in the history
Missing coverage encountered while implementing
<tc39/ecma262#3307> in SpiderMonkey.

Ensure environment lookups are performed in the correct order:
- keyed-destructuring-property-reference-target-evaluation-order-with-bindings.js

Ensure `delete super[elem]` steps are correctly performed:
- delete/super-property-topropertykey.js
- delete/super-property-uninitialized-this.js

Ensure ToPropertyKey for computed property names in object literals
correctly performed:
- object/computed-property-name-topropertykey-before-value-evaluation.js

Ensure `GetSuperBase` is executed before `ToPropertKey`:
- super/prop-expr-getsuperbase-before-topropertykey-*

Ensure `GetThisBinding` is executed first:
- super/prop-expr-uninitialized-this-*
  • Loading branch information
anba committed Sep 2, 2024
1 parent b69e9d5 commit 3ec4db9
Show file tree
Hide file tree
Showing 13 changed files with 681 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-destructuring-binding-patterns-runtime-semantics-propertybindinginitialization
description: >
Ensure correct evaluation order for binding lookups when destructuring target is var-binding.
info: |
14.3.3.1 Runtime Semantics: PropertyBindingInitialization
BindingProperty : PropertyName : BindingElement
1. Let P be ? Evaluation of PropertyName.
2. Perform ? KeyedBindingInitialization of BindingElement with arguments value, environment, and P.
...
14.3.3.3 Runtime Semantics: KeyedBindingInitialization
SingleNameBinding : BindingIdentifier Initializer_opt
1. Let bindingId be the StringValue of BindingIdentifier.
2. Let lhs be ? ResolveBinding(bindingId, environment).
3. Let v be ? GetV(value, propertyName).
4. If Initializer is present and v is undefined, then
...
b. Else,
i. Let defaultValue be ? Evaluation of Initializer.
ii. Set v to ? GetValue(defaultValue).
...
6. Return ? InitializeReferencedBinding(lhs, v).
9.4.2 ResolveBinding ( name [ , env ] )
...
4. Return ? GetIdentifierReference(env, name, strict).
9.1.2.1 GetIdentifierReference ( env, name, strict )
...
2. Let exists be ? env.HasBinding(name).
...
includes: [compareArray.js]
features: [Proxy]
flags: [noStrict]
---*/

var log = [];

var targetKey = {
toString: () => {
log.push("targetKey");
return "q";
}
};

var sourceKey = {
toString: () => {
log.push("sourceKey");
return "p";
}
};

var source = {
get p() {
log.push("get source");
return undefined;
}
};

var target = {
set q(v) {
log.push("set target:");
},
};

var env = new Proxy({}, {
has(t, pk) {
log.push("binding::" + pk);
}
});

var defaultValue = 0;

var varTarget;

with (env) {
var {
[sourceKey]: varTarget = defaultValue
} = source;
}

assert.compareArray(log, [
"binding::source",
"binding::sourceKey",
"sourceKey",
"binding::varTarget",
"get source",
"binding::defaultValue",
]);
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-runtime-semantics-propertydestructuringassignmentevaluation
description: >
Ensure correct evaluation order for binding lookups when destructuring target is var-binding.
info: |
13.15.5.3 Runtime Semantics: PropertyDestructuringAssignmentEvaluation
AssignmentProperty : PropertyName : AssignmentElement
1. Let name be ? Evaluation of PropertyName.
2. Perform ? KeyedDestructuringAssignmentEvaluation of AssignmentElement with arguments value and name.
...
13.15.5.6 Runtime Semantics: KeyedDestructuringAssignmentEvaluation
AssignmentElement : DestructuringAssignmentTarget Initializer_opt
1. If DestructuringAssignmentTarget is neither an ObjectLiteral nor an ArrayLiteral, then
a. Let lRef be ? Evaluation of DestructuringAssignmentTarget.
2. Let v be ? GetV(value, propertyName).
3. If Initializer is present and v is undefined, then
...
b. Else,
i. Let defaultValue be ? Evaluation of Initializer.
ii. Let rhsValue be ? GetValue(defaultValue).
...
6. Return ? PutValue(lRef, rhsValue).
includes: [compareArray.js]
features: [Proxy]
flags: [noStrict]
---*/

var log = [];

var targetKey = {
toString: () => {
log.push("targetKey");
return "q";
}
};

var sourceKey = {
toString: () => {
log.push("sourceKey");
return "p";
}
};

var source = {
get p() {
log.push("get source");
return undefined;
}
};

var target = {
set q(v) {
log.push("set target");
},
};

var env = new Proxy({}, {
has(t, pk) {
log.push("binding::" + pk);
}
});

var defaultValue = 0;

with (env) {
({
[sourceKey]: target[targetKey] = defaultValue
} = source);
}

assert.compareArray(log, [
"binding::source",
"binding::sourceKey",
"sourceKey",
"binding::target",
"binding::targetKey",
"get source",
"binding::defaultValue",
"targetKey",
"set target",
]);
32 changes: 32 additions & 0 deletions test/language/expressions/delete/super-property-topropertykey.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-delete-operator-runtime-semantics-evaluation
description: >
ToPropertyKey not performed when deleting a super reference.
info: |
13.5.1.2 Runtime Semantics: Evaluation
UnaryExpression : delete UnaryExpression
1. Let ref be ? Evaluation of UnaryExpression.
...
4. If IsPropertyReference(ref) is true, then
...
b. If IsSuperReference(ref) is true, throw a ReferenceError exception.
---*/

var key = {
toString() {
throw new Test262Error("ToPropertyKey performed");
}
};

var obj = {
m() {
delete super[key];
}
};

assert.throws(ReferenceError, () => obj.m());
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-delete-operator-runtime-semantics-evaluation
description: >
Element expression in delete super not evaluated when this is uninitialized.
info: |
13.5.1.2 Runtime Semantics: Evaluation
UnaryExpression : delete UnaryExpression
1. Let ref be ? Evaluation of UnaryExpression.
...
13.3.7.1 Runtime Semantics: Evaluation
SuperProperty : super [ Expression ]
...
2. Let actualThis be ? env.GetThisBinding().
3. Let propertyNameReference be ? Evaluation of Expression.
...
9.1.1.3.4 GetThisBinding ( )
...
2. If envRec.[[ThisBindingStatus]] is uninitialized, throw a ReferenceError exception.
...
---*/

class Base {
constructor() {
throw new Test262Error("base constructor called");
}
}

class Derived extends Base {
constructor() {
delete super[(super(), 0)];
}
}

assert.throws(ReferenceError, () => new Derived);
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-runtime-semantics-propertydefinitionevaluation
description: >
ToPropertyKey is performed before evaluating the value expression.
info: |
13.2.5.5 Runtime Semantics: PropertyDefinitionEvaluation
PropertyDefinition : PropertyName : AssignmentExpression
1. Let propKey be ? Evaluation of PropertyName.
...
6. Else,
a. Let exprValueRef be ? Evaluation of AssignmentExpression.
b. Let propValue be ? GetValue(exprValueRef).
...
9. Perform ! CreateDataPropertyOrThrow(object, propKey, propValue).
...
13.2.5.4 Runtime Semantics: Evaluation
ComputedPropertyName : [ AssignmentExpression ]
1. Let exprValue be ? Evaluation of AssignmentExpression.
2. Let propName be ? GetValue(exprValue).
3. Return ? ToPropertyKey(propName).
---*/

var value = "bad";

var key = {
toString() {
value = "ok";
return "p";
}
};

var obj = {
[key]: value
};

assert.sameValue(obj.p, "ok");
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-super-keyword-runtime-semantics-evaluation
description: >
GetSuperBase is performed before ToPropertyKey in GetValue.
info: |
13.3.7.1 Runtime Semantics: Evaluation
SuperProperty : super [ Expression ]
...
2. Let actualThis be ? env.GetThisBinding().
3. Let propertyNameReference be ? Evaluation of Expression.
4. Let propertyNameValue be ? GetValue(propertyNameReference).
...
7. Return ? MakeSuperPropertyReference(actualThis, propertyNameValue, strict).
13.3.7.3 MakeSuperPropertyReference ( actualThis, propertyKey, strict )
1. Let env be GetThisEnvironment().
...
3. Let baseValue be ? env.GetSuperBase().
...
6.2.5.5 GetValue ( V )
...
3. If IsPropertyReference(V) is true, then
...
c. If V.[[ReferencedName]] is not a property key, then
i. Set V.[[ReferencedName]] to ? ToPropertyKey(V.[[ReferencedName]]).
d. Return ? baseObj.[[Get]](V.[[ReferencedName]], GetThisValue(V)).
...
---*/

var proto = {
p: "ok",
};

var proto2 = {
p: "bad",
};

var obj = {
__proto__: proto,
m() {
return super[key];
}
};

var key = {
toString() {
Object.setPrototypeOf(obj, proto2);
return "p";
}
};

assert.sameValue(obj.m(), "ok");
Loading

0 comments on commit 3ec4db9

Please sign in to comment.