-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Object rest #12028
Object rest #12028
Conversation
Missed previously, just got the baselines
@ahejlsberg @mhegazy do you want to take a look at this after the object-spread PR? |
} | ||
for (const prop of getPropertiesOfType(source)) { | ||
const inNamesToRemove = prop.name in names; | ||
const isPrivate = getDeclarationModifierFlagsFromSymbol(prop) & (ModifierFlags.Private | ModifierFlags.Protected); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why are we removing private? it will exist at runtime, we do not create it as enumerable: false, and it not a parent property.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well.. this is actually different from what we do with keyof
where we filter privates as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spread also removes privates. It's the right thing to do there, and I think it is here too:
class P { private p: number }
let p: P;
var { ...exposed } = p;
I don't think exposed
should be an easy way to get all of P
's private members.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure you have @rbuckton look at the emitter changes.
while (root && root.kind !== SyntaxKind.BinaryExpression) { | ||
root = root.parent; | ||
} | ||
emitFlags |= root && isDestructuringAssignment(root) ? NodeFlags.HasRestAttribute : NodeFlags.HasSpreadAttribute; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not 100% sure this is right. You might be walking up from the right side of a destructuring assignment, in which case the spread is actually a spread.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I improved it to check that the relation between root and parent is that the object literal is the lefthand side.
const restHelper = ` | ||
var __rest = (this && this.__rest) || function (s, e) { | ||
var t = {}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No blank lines in the helpers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
) | ||
); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, that's an awful lot of code. I'm surprised it takes this much, but I'm not familiar enough with the new emitter to truly evaluate this. Make sure you have @rbuckton take a look.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's copied from ES2015's function and for-of transforms, then simplified. I'll go back and see whether the two can share the code better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved a lot of shared code from ES2015 and ESNext to factory.ts. ESNext is a lot shorter now.
const restHelper = ` | ||
var __rest = (this && this.__rest) || function (s, e) { | ||
var t = {}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit. remove empty line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
1. Remove extra line in __rest shim. 2. Improve __rest vs __assign check for destructuring assignment.
Saves a lot of duplicated code
It is shared by es2015 and esNext transformers. This commit just adds a convertObjectRest flag to be passed on to flattenDestructuring functions, as well as adding necessary parameters to use the code outside a transformer.
* Transforms the body of a function-like node. | ||
* | ||
* @param node A function-like node. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the only changes here are to add extra parameters needed to use transformFunctionBody and friends outside of a transformer, and to pass along convertObjectRest to flattenParameterDestructuring
.
// | ||
// for (let v of arr) { } | ||
// | ||
// we don't want to emit a temporary variable for the RHS, just use it directly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the only changes to convertForOf are
- in creating
counter
andelementAccess
- calling flattenParameterDestructuring with
convertObjectRest
- calling
createForOf
vscreateFor
depending on whetherconvertObjectRest
is true.
Otherwise it's just moved from es2015
@dotnet-bot test this please |
Previously array destructuring inside an object destructuring with an object rest would downlevel the array destructuring to ES5. This breaks if the code that targets ES2015 is using iterators instead of arrays since iterators don't support [0] or .slice that the ES5 emit uses.
Now with object destructuring inside array destructuring inside object destructuring! Each with their own array/object rest! Also updates baselines.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The emit looks good, based on our offline discussion of the runtime semantics.
@@ -42,6 +42,14 @@ var __assign = (this && this.__assign) || Object.assign || function(t) { | |||
return t; | |||
};`; | |||
|
|||
const restHelper = ` | |||
var __rest = (this && this.__rest) || function (s, e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we will need to add this to https://github.com/Microsoft/tslib
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also you will need a check in checker.ts for __rest and __assign, and add some tests for these.
Great success! |
Wohoo! Awesome :) |
How is the object spread operator going to deal with nested objects? Babel-kindaof-bugged example:
|
@damianobarbati This is the correct behavior. That's how it works. |
Ok, just like current array spread operator then. Thanks @alitaheri |
Leaves #10727 still open
Fixes #2103
Add object rest syntax as specified in the stage 3 proposal.
Note:
transformers/esnext.ts
and the build file updates. I expect object-spread to go in first so it shouldn't make a difference.