-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Yield as method argument cannot be converted from ES6 #2376
Comments
@concavelenz has told me in the past that this problem is due to a bug in older versions of IE that makes it unsafe for us to rewrite the yield as we need to in cases like this. @concavelenz is there an appropriate open issue for this? Should we close it as infeasible? |
Or allow it only if language output is es5? |
This is also causing issues running closure-compiler on TypeScript's ES2015 async-iterator transpilation. Starting from this ESNext source: function defer(fn) {
return {
async *[Symbol.asyncIterator]() {
for await (let item of await fn()) { yield item; }
}
};
} TS's corresponding ES2015: function defer(fn) {
return {
[Symbol.asyncIterator]() {
return __asyncGenerator(this, arguments, function* _a() {
try {
for (var _a = __asyncValues(yield __await(fn())), _b; _b = yield __await(_a.next()), !_b.done;) {
let item = yield __await(_b.value);
yield item;
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_b && !_b.done && (_c = _a.return)) yield __await(_c.call(_a));
}
finally { if (e_1) throw e_1.error; }
}
var e_1, _c;
});
};
}
} From this issue, it looks like |
@concavelenz explained this last month on an internal mailing list:
So it looks like this is only an issue if the object is a browser object and we're targeting IE (not sure which versions, but I wouldn't be surprised if even IE11 was broken, which would mean ES5 isn't sufficient) and we're worried that the object (or property) might change between the yield and the reentrance. I don't see why |
Thinking more about this, one difficulty about suppression is that it's not clear what it means - because the problem has two roots that are conflicting, any suppression would need to suggest which of the two root causes is being suppressed - either "don't worry, I'm not running in IE" in which case we simply suppress the warning and continue doing what we're already doing, or else "don't worry, this property shouldn't change" in which case we don't try to rewrite it as a call. Maybe the latter could be rewritten in an acceptable form by hand, possibly involving a closure of some sort? (though this wouldn't help the generated code case) |
Finally, my understanding is that TS can produce either ES5 or ES6 code. We're currently working on plumbing ES6 all the way through the compiler, at which point it won't matter if TS's ES6 output isn't transpilable, since you should just send in the ES5 output instead. |
* refactor(asynciterable): Moves await expressions outside for-of statements for closure-compiler TypeScript's ES6 target generates yield statements that google-closure-compiler can't compile. See google/closure-compiler#2376 (comment) for details. * build(gulp): Rewrites the build scripts with gulp for more speed and ease of use
@shicks yep, TS can produce any of ES5/6/Next. Today, we transpile the TS to ES5, then run the ES5 through closure compiler. For the next release of IxJS, we're compiling the TS source to multiple target artifacts (JS version x module format) to make it easier to consume the library from the wide array of available JS bundlers (more here). So we have ES5/6/Next closure compiler, CommonJS, ESModules, SystemJS, and UMD bundles. If possible (and when it's ready) we'd like to run the TS-generated ES6 through CC to generate the ES6 UMD bundle (ES6 in/ES6 out). This will allow us to bypass TS's generator state machine transpilation, ideally leading to a smaller/faster ES6 UMD bundle. For reference, here's the ES5 that TS generates for the example I used before. |
* refactor(asynciterable): Moves await expressions outside for-of statements for closure-compiler TypeScript's ES6 target generates yield statements that google-closure-compiler can't compile. See google/closure-compiler#2376 (comment) for details. * build(gulp): Rewrites the build scripts with gulp for more speed and ease of use * build(gulp): Fix gulp test error output
* refactor(asynciterable): Moves await expressions outside for-of statements for closure-compiler TypeScript's ES6 target generates yield statements that google-closure-compiler can't compile. See google/closure-compiler#2376 (comment) for details. * build(gulp): Rewrites the build scripts with gulp for more speed and ease of use * feat(observable) - fix toObservable * feat(observable): add to/from Observable * build(gulp): Fix gulp test error output * feat(from): Collapse from to include Observable * build(systemjs): Remove SystemJS compilation targets
To be clear the issue is using .call/.apply on browser objects in IE, even if the "this" value is valid for the browser, IE won't let you use that form. At the time the code is transpiled from ES6 to ES5, we have very little information (it currently occurs before type checking) so even knowing if it is an unexported internal type (which would not need protection) would be difficult to do and wouldn't solve issue with "console.log" or "Promise.resolve" which are external. Looking forward, using ES6 output would clearly solve the issue, as would having some flag like "I don't care about IE"/"I know this is safe" in some form or other that allowed the expression decomposer to do what it wants to. As pointed out in the original report, the workaround is to decompose the expression by hand and it would be helpful if the error from the compiler encouraged this. |
@trxcllnt Would it be reasonable to file an issue with the TypeScript compiler that its ES6 output is impossible to transpile safely? Presumably they have more information about the types and could make a better call about how to output this. |
I'd like to know what versions of IE this applies to. If it only applies to versions < 11, then I'd like to add a flag to the compiler to allow this type of decompisition. I believe it also affects class name extends expressions. Other transpilers do this - we should be able to support it. |
Any updates on this? I would love to have a flag to tell the compiler that I understand the risks and to continue anyway. Re changing the Typescript compiler: Part of typescripts design goals is to not change the emit based on type information. |
The compiler now has a flag It's in the release as of v20171203. |
Attempting to compile the following generator yields an error
https://closure-compiler-debugger.appspot.com/#input0%3Dfunction*%2520x()%2520%257B%250A%2520%2520console.log(yield%2520Promise.resolve(12345))%253B%250A%257D%26input1%26conformanceConfig%26externs%26refasterjs-template%26includeDefaultExterns%3D1%26CHECK_SYMBOLS%3D1%26MISSING_PROPERTIES%3D1%26TRANSPILE%3D1%26CHECK_TYPES%3D1%26COMPUTE_FUNCTION_SIDE_EFFECTS%3D1%26INLINE_VARIABLES%3D1%26SMART_NAME_REMOVAL%3D1%26REMOVE_UNUSED_PROTOTYPE_PROPERTIES%3D1%26REMOVE_UNUSED_PROTOTYPE_PROPERTIES_IN_EXTERNS%3D1%26COLLAPSE_PROPERTIES%3D1%26DEVIRTUALIZE_PROTOTYPE_METHODS%3D1%26VARIABLE_RENAMING%3D1%26PROPERTY_RENAMING%3D1%26CLOSURE_PASS%3D1%26GENERATE_EXPORTS%3D1%26PRESERVE_TYPE_ANNOTATIONS%3D1%26PRETTY_PRINT%3D1
Things that do work:
The text was updated successfully, but these errors were encountered: