Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign upSpec bug with object rest destructuring assignment #1130
Comments
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
anba
Mar 6, 2018
Contributor
Agreed. ObjectAssignmentPattern : { AssignmentRestProperty } and ObjectAssignmentPattern : { AssignmentPropertyList , AssignmentRestProperty } should both invoke RequireObjectCoercible as the first step.
|
Agreed. |
ljharb
added
spec bug
good first patch
labels
Mar 6, 2018
musgravejw
referenced this issue
Apr 5, 2018
Merged
Normative: specify RequireObjectCoercible as first step in destructuring assignment semantics #1163
woess
changed the title from
Possible spec bug with object rest destructuring assignment
to
Spec bug with object rest destructuring assignment
Apr 5, 2018
woess
referenced this issue
Apr 9, 2018
Open
Wrong section/description in destructuring assignment tests #1508
This comment was marked as off-topic.
Show comment
Hide comment
This comment was marked as off-topic.
1020431880
commented
Apr 12, 2018
|
你好啊,老铁 |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
|
Agree with what was said above. Cc @sebmarkbage @keithamus |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
sebmarkbage
Apr 12, 2018
Contributor
Hm. I don't think RequireObjectCoercible is the right thing here because it doesn't handle the case when it is a string or number. The ToObject operations deeply nested handles that.
For normal destructuring, this ToObject happens within the GetValue operation for each property access. So it happens multiple times.
Which is observable:
var xObj;
var yObj;
Object.defineProperty(
String.prototype,
'x',
{
get() {
xObj = this;
}
}
);
Object.defineProperty(
String.prototype,
'y',
{
get() {
yObj = this;
}
}
);
var { x, y } = "foo";
console.log(xObj === yObj); // falseKeeping in line with that CopyDataProperties does the ToObject operation for the rest property. So there will be one more for that one.
However, there is a special case in CopyDataProperties for null/undefined so it doesn't get passed to ToObject. So in this case, this is not a spec bug - the test case is wrong. This should not throw a type error.
If we wanted to change this we should refactor CopyDataProperties to not special case null/undefined but it is important for the spread operation where null/undefined should be silently ignored.
(I kind of think that we should change the semantics to do an early ToObject and only one per destructuring instead of multiple but that's a bigger breaking change. But that would also fix this.)
|
Hm. I don't think RequireObjectCoercible is the right thing here because it doesn't handle the case when it is a string or number. The ToObject operations deeply nested handles that. For normal destructuring, this ToObject happens within the GetValue operation for each property access. So it happens multiple times. Which is observable: var xObj;
var yObj;
Object.defineProperty(
String.prototype,
'x',
{
get() {
xObj = this;
}
}
);
Object.defineProperty(
String.prototype,
'y',
{
get() {
yObj = this;
}
}
);
var { x, y } = "foo";
console.log(xObj === yObj); // falseKeeping in line with that CopyDataProperties does the ToObject operation for the rest property. So there will be one more for that one. However, there is a special case in CopyDataProperties for null/undefined so it doesn't get passed to ToObject. So in this case, this is not a spec bug - the test case is wrong. This should not throw a type error. If we wanted to change this we should refactor CopyDataProperties to not special case null/undefined but it is important for the spread operation where null/undefined should be silently ignored. (I kind of think that we should change the semantics to do an early ToObject and only one per destructuring instead of multiple but that's a bigger breaking change. But that would also fix this.) |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
anba
Apr 12, 2018
Contributor
Hm. I don't think RequireObjectCoercible is the right thing here because it doesn't handle the case when it is a string or number. The ToObject operations deeply nested handles that.
var {...x} = null; already throws a TypeError. This issue is to make destructuring assignment consistent with destructuring binding, so that ({...x} = null); also throws a TypeError. Not throwing for ({...x} = null); is also inconsistent with var {} = null; or ({} = null);, which both also already do throw a TypeError.
The observable multiple calls to ToObject in GetValue only matter for non-strict code, in strict code implementers can optimize away the ToObject call if wished.
The observable multiple calls to ToObject in GetValue only matter for non-strict code, in strict code implementers can optimize away the ToObject call if wished. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
leobalter
Apr 12, 2018
Member
I agree this should have a spec fix for the consistency pointed by @anba. The test is slightly wrong with the current spec because it followed consistency with the var {...x} = null;. Also, a fix would reflect the current implementations:
eshost -x 'var rest; ({...rest} = null); print(rest)'
#### d8
TypeError: Cannot destructure 'undefined' or 'null'.
#### ch (no unflagged support yet for Obj Rest in the latest Release)
SyntaxError: Expected identifier, string or number
#### jsshell
TypeError: null has no properties
#### jsc
TypeError: Right side of assignment cannot be destructured
|
I agree this should have a spec fix for the consistency pointed by @anba. The test is slightly wrong with the current spec because it followed consistency with the
|
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
sebmarkbage
Apr 12, 2018
Contributor
I see. ObjectAssignmentPattern: {AssignmentPropertyList} and equivalent binding patterns already has RequireObjectCoercible. As along as it is consistently always before any ToObject from GetValue, that seems fine to me then.
|
I see. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
|
Fixed by #1163. |
woess commentedMar 6, 2018
Consider this test case from test262 which expects a TypeError:
The problem: I cannot find the corresponding passage in the spec.
I believe that 12.15.5.2 Runtime Semantics: DestructuringAssignmentEvaluation is missing a
Perform ? RequireObjectCoercible(value).as first step.I'll walk you through the path I took, so you can correct me if I went wrong somewhere.