diff --git a/packages/compiler-cli/ngcc/src/host/commonjs_host.ts b/packages/compiler-cli/ngcc/src/host/commonjs_host.ts index ca3d6532c6..a2f8012b0a 100644 --- a/packages/compiler-cli/ngcc/src/host/commonjs_host.ts +++ b/packages/compiler-cli/ngcc/src/host/commonjs_host.ts @@ -14,7 +14,7 @@ import {Declaration, Import} from '../../../src/ngtsc/reflection'; import {BundleProgram} from '../packages/bundle_program'; import {FactoryMap, isDefined} from '../utils'; -import {DefinePropertyReexportStatement, ExportDeclaration, ExportStatement, extractGetterFnExpression, findNamespaceOfIdentifier, findRequireCallReference, isDefinePropertyReexportStatement, isExportStatement, isExternalImport, isRequireCall, isWildcardReexportStatement, RequireCall, WildcardReexportStatement} from './commonjs_umd_utils'; +import {DefinePropertyReexportStatement, ExportDeclaration, ExportsStatement, extractGetterFnExpression, findNamespaceOfIdentifier, findRequireCallReference, isDefinePropertyReexportStatement, isExportsStatement, isExternalImport, isRequireCall, isWildcardReexportStatement, RequireCall, WildcardReexportStatement} from './commonjs_umd_utils'; import {Esm5ReflectionHost} from './esm5_host'; import {NgccClassSymbol} from './ngcc_host'; @@ -98,7 +98,7 @@ export class CommonJsReflectionHost extends Esm5ReflectionHost { private computeExportsOfCommonJsModule(sourceFile: ts.SourceFile): Map { const moduleMap = new Map(); for (const statement of this.getModuleStatements(sourceFile)) { - if (isExportStatement(statement)) { + if (isExportsStatement(statement)) { const exportDeclaration = this.extractBasicCommonJsExportDeclaration(statement); moduleMap.set(exportDeclaration.name, exportDeclaration.declaration); } else if (isWildcardReexportStatement(statement)) { @@ -116,7 +116,7 @@ export class CommonJsReflectionHost extends Esm5ReflectionHost { return moduleMap; } - private extractBasicCommonJsExportDeclaration(statement: ExportStatement): ExportDeclaration { + private extractBasicCommonJsExportDeclaration(statement: ExportsStatement): ExportDeclaration { const exportExpression = statement.expression.right; const name = statement.expression.left.name.text; return this.extractCommonJsExportDeclaration(name, exportExpression); diff --git a/packages/compiler-cli/ngcc/src/host/commonjs_umd_utils.ts b/packages/compiler-cli/ngcc/src/host/commonjs_umd_utils.ts index 7374871584..1a1652832b 100644 --- a/packages/compiler-cli/ngcc/src/host/commonjs_umd_utils.ts +++ b/packages/compiler-cli/ngcc/src/host/commonjs_umd_utils.ts @@ -8,22 +8,13 @@ import * as ts from 'typescript'; import {Declaration} from '../../../src/ngtsc/reflection'; - +import {isAssignment} from '../../../src/ngtsc/util/src/typescript'; export interface ExportDeclaration { name: string; declaration: Declaration; } -export interface ExportStatement extends ts.ExpressionStatement { - expression: ts.BinaryExpression&{ - left: ts.PropertyAccessExpression & - { - expression: ts.Identifier - } - }; -} - /** * A CommonJS or UMD wildcard re-export statement. * @@ -59,6 +50,9 @@ export interface DefinePropertyReexportStatement extends ts.ExpressionStatement {arguments: [ts.Identifier, ts.StringLiteral, ts.ObjectLiteralExpression]}; } +/** + * A call expression that has a string literal for its first argument. + */ export interface RequireCall extends ts.CallExpression { arguments: ts.CallExpression['arguments']&[ts.StringLiteral]; } @@ -90,18 +84,6 @@ export function findRequireCallReference(id: ts.Identifier, checker: ts.TypeChec return initializer && isRequireCall(initializer) ? initializer : null; } -/** - * Check whether the specified `ts.Statement` is an export statement, i.e. an expression statement - * of the form: `exports. = ` - */ -export function isExportStatement(stmt: ts.Statement): stmt is ExportStatement { - return ts.isExpressionStatement(stmt) && ts.isBinaryExpression(stmt.expression) && - (stmt.expression.operatorToken.kind === ts.SyntaxKind.EqualsToken) && - ts.isPropertyAccessExpression(stmt.expression.left) && - ts.isIdentifier(stmt.expression.left.expression) && - stmt.expression.left.expression.text === 'exports'; -} - /** * Check whether the specified `ts.Statement` is a wildcard re-export statement. * I.E. an expression statement of one of the following forms: @@ -194,6 +176,12 @@ export function isDefinePropertyReexportStatement(stmt: ts.Statement): prop => prop.name !== undefined && ts.isIdentifier(prop.name) && prop.name.text === 'get')); } +/** + * Extract the "value" of the getter in a `defineProperty` statement. + * + * This will return the `ts.Expression` value of a single `return` statement in the `get` method + * of the property definition object, or `null` if that is not possible. + */ export function extractGetterFnExpression(statement: DefinePropertyReexportStatement): ts.Expression|null { const args = statement.expression.arguments; @@ -220,6 +208,59 @@ export function isRequireCall(node: ts.Node): node is RequireCall { ts.isStringLiteral(node.arguments[0]); } +/** + * Check whether the specified `path` is an "external" import. + * In other words, that it comes from a entry-point outside the current one. + */ export function isExternalImport(path: string): boolean { return !/^\.\.?(\/|$)/.test(path); } + +/** + * A UMD/CommonJS style export declaration of the form `exports.`. + */ +export interface ExportsDeclaration extends ts.PropertyAccessExpression { + name: ts.Identifier; + expression: ts.Identifier; + parent: ExportsAssignment; +} + +/** + * Check whether the specified `node` is a property access expression of the form + * `exports.`. + */ +export function isExportsDeclaration(expr: ts.Node): expr is ExportsDeclaration { + return expr.parent && isExportsAssignment(expr.parent); +} + +/** + * A UMD/CommonJS style export assignment of the form `exports. = `. + */ +export interface ExportsAssignment extends ts.BinaryExpression { + left: ExportsDeclaration; +} + +/** + * Check whether the specified `node` is an assignment expression of the form + * `exports. = `. + */ +export function isExportsAssignment(expr: ts.Node): expr is ExportsAssignment { + return isAssignment(expr) && ts.isPropertyAccessExpression(expr.left) && + ts.isIdentifier(expr.left.expression) && expr.left.expression.text === 'exports' && + ts.isIdentifier(expr.left.name); +} + +/** + * An expression statement of the form `exports. = ;`. + */ +export interface ExportsStatement extends ts.ExpressionStatement { + expression: ExportsAssignment; +} + +/** + * Check whether the specified `stmt` is an expression statement of the form + * `exports. = ;`. + */ +export function isExportsStatement(stmt: ts.Node): stmt is ExportsStatement { + return ts.isExpressionStatement(stmt) && isExportsAssignment(stmt.expression); +} diff --git a/packages/compiler-cli/ngcc/src/host/umd_host.ts b/packages/compiler-cli/ngcc/src/host/umd_host.ts index 5a4b73ed70..d91805e0cb 100644 --- a/packages/compiler-cli/ngcc/src/host/umd_host.ts +++ b/packages/compiler-cli/ngcc/src/host/umd_host.ts @@ -14,7 +14,7 @@ import {Declaration, Import} from '../../../src/ngtsc/reflection'; import {BundleProgram} from '../packages/bundle_program'; import {FactoryMap, getTsHelperFnFromIdentifier, stripExtension} from '../utils'; -import {DefinePropertyReexportStatement, ExportDeclaration, ExportStatement, extractGetterFnExpression, findNamespaceOfIdentifier, findRequireCallReference, isDefinePropertyReexportStatement, isExportStatement, isExternalImport, isRequireCall, isWildcardReexportStatement, WildcardReexportStatement} from './commonjs_umd_utils'; +import {DefinePropertyReexportStatement, ExportDeclaration, ExportsStatement, extractGetterFnExpression, findNamespaceOfIdentifier, findRequireCallReference, isDefinePropertyReexportStatement, isExportsStatement, isExternalImport, isRequireCall, isWildcardReexportStatement, WildcardReexportStatement} from './commonjs_umd_utils'; import {Esm5ReflectionHost} from './esm5_host'; import {stripParentheses} from './utils'; @@ -90,7 +90,7 @@ export class UmdReflectionHost extends Esm5ReflectionHost { private computeExportsOfUmdModule(sourceFile: ts.SourceFile): Map|null { const moduleMap = new Map(); for (const statement of this.getModuleStatements(sourceFile)) { - if (isExportStatement(statement)) { + if (isExportsStatement(statement)) { const exportDeclaration = this.extractBasicUmdExportDeclaration(statement); moduleMap.set(exportDeclaration.name, exportDeclaration.declaration); } else if (isWildcardReexportStatement(statement)) { @@ -132,7 +132,7 @@ export class UmdReflectionHost extends Esm5ReflectionHost { return importPath; } - private extractBasicUmdExportDeclaration(statement: ExportStatement): ExportDeclaration { + private extractBasicUmdExportDeclaration(statement: ExportsStatement): ExportDeclaration { const name = statement.expression.left.name.text; const exportExpression = statement.expression.right; return this.extractUmdExportDeclaration(name, exportExpression);