-
Notifications
You must be signed in to change notification settings - Fork 25.3k
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
fix(ngcc): several fixes #34169
fix(ngcc): several fixes #34169
Conversation
You can preview 5fdc4a2 at https://pr34169-5fdc4a2.ngbuilds.io/. |
You can preview 263efda at https://pr34169-263efda.ngbuilds.io/. |
263efda
to
8077ce1
Compare
You can preview 8077ce1 at https://pr34169-8077ce1.ngbuilds.io/. |
8077ce1
to
b0cc9d9
Compare
You can preview b0cc9d9 at https://pr34169-b0cc9d9.ngbuilds.io/. |
b0cc9d9
to
a45d1bb
Compare
You can preview a45d1bb at https://pr34169-a45d1bb.ngbuilds.io/. |
a45d1bb
to
363218f
Compare
You can preview 363218f at https://pr34169-363218f.ngbuilds.io/. |
363218f
to
08f17b8
Compare
You can preview 08f17b8 at https://pr34169-08f17b8.ngbuilds.io/. |
08f17b8
to
e28ac70
Compare
You can preview e28ac70 at https://pr34169-e28ac70.ngbuilds.io/. |
typo in the 2nd to last commit: |
typos in the last commit:
I think this should be And also |
typo in 5th commit: By failing to recongize |
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.
Reviewed all but the last comment.
// ([source](https://github.com/microsoft/TypeScript/blob/d7c83f023/src/compiler/transformers/module/module.ts#L1796-L1797)). | ||
// So, theoretically, we only care about the formats `__export(require('...'))` and | ||
// `tslib.__exportStar(require('...'), exports)`. | ||
// The accepts the other two formats (`__exportStar(...)` and `tslib.__export(...)`) to be |
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.
typo: This accepts
fnName = statement.expression.expression.name.text; | ||
} | ||
|
||
// Esnure the called function is either `__export()` or `__exportStar()`. |
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.
typ: Ensure
// tslib_1.__exportStar(require('...'), exports); | ||
reExportsWithImportedHelper?: string[]; | ||
} | ||
|
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: I prefer not to clutter the start of a test file with supporting stuff (like helper functions and interfaces) since it makes it more difficult to quickly get to the tests when browsing later. Since interfaces are always hoisted, can we move this down below the describe
block?
ts.isPropertyAssignment(prop) && isRequireCall(prop.initializer)) | ||
.map(prop => prop.initializer); | ||
|
||
requireCalls.push(...requireCallsFromProperties); |
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: this could be more simple and not require intermediate arrays to be created:
stmt.expression.right.properties.forEach(prop => {
if(ts.isPropertyAssignment(prop) && isRequireCall(prop.initializer)) {
requireCalls.push(prop.initializer);
}
});
], | ||
ts.createArrayTypeNode(ts.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)), undefined), | ||
viaModule: null, | ||
}; |
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: I would put this whole block into its own function (e..g createSynthesizedHelperDeclaration(id)
) with the big comment converted to JSDOC comment. This will keep the calling function much smaller and more readable.
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 PR looks great! Regarding the last commit, I can accept this approach. I don't know what other ideas you had. One thought is if we could create a new thing called a LazyFunction
, which we would match code of the form (this && this.<fn>) || function () { ... }
, which could then be visited more intelligently in the StaticInterpreter?
@gkalpak is this PR nearly ready? Is it worth splitting out the non-contentious bits so that we can land them this week? |
I'll split the non-contentious bits into a separate PR this week 👍 |
e28ac70
to
2b6e20e
Compare
Previously, the `CommonJsReflectionHost` would only recognize re-exports of the form `__export(require('...'))`. This is what re-exports look like, when the TS helpers are emitted inline (i.e. when compiling with the default [TS compiler options][1] that include `noEmitHelpers: false` and `importHelpers: false`). However, when compiling with `importHelpers: true` and [tslib][2] (which is the recommended way for optimized bundles), the re-exports will look like: `tslib_1.__exportStar(require('...'), exports)` These types of re-exports where previously not recognized by `CommonJsReflectionHost` and thus ignored. This commit fixes this by ensuring both re-export formats are recognized. [1]: https://www.typescriptlang.org/docs/handbook/compiler-options.html [2]: https://www.npmjs.com/package/tslib
Previously, `CommonJsDependencyHost.findDependencies()` would only find dependencies via imports of the form `var foo = require('...');` or `var foo = require('...'), bar = require('...');` However, CommonJS files can have imports in many different forms. By failing to recognize other forms of imports, the associated dependencies were missed, which in turn resulted in entry-points being compiled out-of-order and failing due to that. While we cannot easily capture all different types of imports, this commit enhances `CommonJsDependencyHost` to recognize the following common forms of imports: - Imports in property assignments. E.g.: `exports.foo = require('...');` or `module.exports = {foo: require('...')};` - Imports for side-effects only. E.g.: `require('...');` - Star re-exports (with both emitted and imported heleprs). E.g.: `__export(require('...'));` or `tslib_1.__exportStar(require('...'), exports);`
In ES5 code, TypeScript requires certain helpers (such as `__spreadArrays()`) to be able to support ES2015+ features. These helpers can be either imported from `tslib` (by setting the `importHelpers` TS compiler option to `true`) or emitted inline (by setting the `importHelpers` and `noEmitHelpers` TS compiler options to `false`, which is also the default value for both). Ngtsc's `StaticInterpreter` (which is also used during ngcc processing) is able to statically evaluate some of these helpers (currently `__spread()` and `__spreadArrays()`), as long as `ReflectionHost#getDefinitionOfFunction()` correctly detects the declaration of the helper. For this to happen, the left-hand size of the corresponding call expression (i.e. `__spread(...)` or `tslib.__spread(...)`) must be evaluated as a function declaration for `getDefinitionOfFunction()` to be called with. In the case of imported helpers, the `tslib.__someHelper` expression was resolved to a function declaration of the form `export declare function __someHelper(...args: any[][]): any[];`, which allows `getDefinitionOfFunction()` to correctly map it to a TS helper. In contrast, in the case of emitted helpers (and regardless of the module format: `CommonJS`, `ESNext`, `UMD`, etc.)), the `__someHelper` identifier was resolved to a variable declaration of the form `var __someHelper = (this && this.__someHelper) || function () { ... }`, which upon further evaluation was categorized as a `DynamicValue` (prohibiting further evaluation by the `getDefinitionOfFunction()`). As a result of the above, TypeScript helpers were not evaluated in ES5 code. --- This commit fixes this by detecting such helpers in `Esm5ReflectionHost#getDeclarationOfIdentifier()` and (instead of the actual variable declaration) return a synthesized function declaration, identical to the one that would have been returned for the imported helper. This allows `getDefinitionOfFunction()` to correctly map it to a TS helper, allowing `StaticInterpreter` to statically evaluate the associated call expression.
2b6e20e
to
8c37785
Compare
@petebacondarwin: FYI, I have addressed your comments (in I need to further split this into more PRs (for easier reviewing) and add similar fixes for UMD (where appropriate). |
You can preview 8c37785 at https://pr34169-8c37785.ngbuilds.io/. |
With all the "spin-off" PRs merged, the only remaining fix for this PR is to correctly detect emitted TS helpers in ES5 (i.e. 0b89f17). (I need to clean it up or possibly rework the approach.) This will also fix processing |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
This PR includes several ngcc fixes. With these fixes, ngcc should be able to successfully process NativeScript. See individual commits for details.
Jira issue: FW-1689
TODO:
StaticInterpreter
(and how to fix it).