aot-compiler.js 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. "use strict";
  2. var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
  3. return new (P || (P = Promise))(function (resolve, reject) {
  4. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  5. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  6. function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
  7. step((generator = generator.apply(thisArg, _arguments || [])).next());
  8. });
  9. };
  10. var __generator = (this && this.__generator) || function (thisArg, body) {
  11. var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
  12. return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
  13. function verb(n) { return function (v) { return step([n, v]); }; }
  14. function step(op) {
  15. if (f) throw new TypeError("Generator is already executing.");
  16. while (_) try {
  17. if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
  18. if (y = 0, t) op = [0, t.value];
  19. switch (op[0]) {
  20. case 0: case 1: t = op; break;
  21. case 4: _.label++; return { value: op[1], done: false };
  22. case 5: _.label++; y = op[1]; op = [0]; continue;
  23. case 7: op = _.ops.pop(); _.trys.pop(); continue;
  24. default:
  25. if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
  26. if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
  27. if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
  28. if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
  29. if (t[2]) _.ops.pop();
  30. _.trys.pop(); continue;
  31. }
  32. op = body.call(thisArg, _);
  33. } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
  34. if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
  35. }
  36. };
  37. Object.defineProperty(exports, "__esModule", { value: true });
  38. var path_1 = require("path");
  39. require("reflect-metadata");
  40. var typescript_1 = require("typescript");
  41. var hybrid_file_system_factory_1 = require("../util/hybrid-file-system-factory");
  42. var compiler_host_factory_1 = require("./compiler-host-factory");
  43. var utils_1 = require("./utils");
  44. var logger_1 = require("../logger/logger");
  45. var logger_diagnostics_1 = require("../logger/logger-diagnostics");
  46. var logger_typescript_1 = require("../logger/logger-typescript");
  47. var transpile_1 = require("../transpile");
  48. var errors_1 = require("../util/errors");
  49. var helpers_1 = require("../util/helpers");
  50. function runAot(context, options) {
  51. return __awaiter(this, void 0, void 0, function () {
  52. var tsConfig, angularCompilerOptions, aggregateCompilerOption, fileSystem, compilerHost, tsProgram, mailFilePath, mainFile, modifiedBootstrapContent;
  53. return __generator(this, function (_a) {
  54. switch (_a.label) {
  55. case 0:
  56. tsConfig = transpile_1.getTsConfig(context);
  57. angularCompilerOptions = Object.assign({}, {
  58. basePath: options.rootDir,
  59. genDir: options.rootDir,
  60. entryPoint: options.entryPoint
  61. });
  62. aggregateCompilerOption = Object.assign(tsConfig.options, angularCompilerOptions);
  63. fileSystem = hybrid_file_system_factory_1.getInstance(false);
  64. compilerHost = compiler_host_factory_1.getInMemoryCompilerHostInstance(tsConfig.options);
  65. tsProgram = typescript_1.createProgram(tsConfig.fileNames, tsConfig.options, compilerHost);
  66. logger_diagnostics_1.clearDiagnostics(context, logger_diagnostics_1.DiagnosticsType.TypeScript);
  67. if (!isNg5(context.angularVersion)) return [3 /*break*/, 2];
  68. return [4 /*yield*/, runNg5Aot(context, tsConfig, aggregateCompilerOption, compilerHost)];
  69. case 1:
  70. _a.sent();
  71. return [3 /*break*/, 4];
  72. case 2: return [4 /*yield*/, runNg4Aot({
  73. angularCompilerOptions: aggregateCompilerOption,
  74. cliOptions: {
  75. i18nFile: undefined,
  76. i18nFormat: undefined,
  77. locale: undefined,
  78. basePath: options.rootDir,
  79. missingTranslation: null
  80. },
  81. program: tsProgram,
  82. compilerHost: compilerHost,
  83. compilerOptions: tsConfig.options
  84. })];
  85. case 3:
  86. _a.sent();
  87. _a.label = 4;
  88. case 4:
  89. errorCheckProgram(context, tsConfig, compilerHost, tsProgram);
  90. mailFilePath = isNg5(context.angularVersion) ? helpers_1.changeExtension(options.entryPoint, '.js') : options.entryPoint;
  91. mainFile = context.fileCache.get(mailFilePath);
  92. modifiedBootstrapContent = replaceBootstrap(mainFile, options.appNgModulePath, options.appNgModuleClass, options);
  93. mainFile.content = modifiedBootstrapContent;
  94. if (isTranspileRequired(context.angularVersion)) {
  95. transpileFiles(context, tsConfig, fileSystem);
  96. }
  97. return [2 /*return*/];
  98. }
  99. });
  100. });
  101. }
  102. exports.runAot = runAot;
  103. function errorCheckProgram(context, tsConfig, compilerHost, cachedProgram) {
  104. // Create a new Program, based on the old one. This will trigger a resolution of all
  105. // transitive modules, which include files that might just have been generated.
  106. var program = typescript_1.createProgram(tsConfig.fileNames, tsConfig.options, compilerHost, cachedProgram);
  107. var globalDiagnostics = program.getGlobalDiagnostics();
  108. var tsDiagnostics = program.getSyntacticDiagnostics()
  109. .concat(program.getSemanticDiagnostics())
  110. .concat(program.getOptionsDiagnostics());
  111. if (globalDiagnostics.length) {
  112. var diagnostics = logger_typescript_1.runTypeScriptDiagnostics(context, globalDiagnostics);
  113. logger_diagnostics_1.printDiagnostics(context, logger_diagnostics_1.DiagnosticsType.TypeScript, diagnostics, true, false);
  114. throw new errors_1.BuildError(new Error('Failed to transpile TypeScript'));
  115. }
  116. if (tsDiagnostics.length) {
  117. var diagnostics = logger_typescript_1.runTypeScriptDiagnostics(context, tsDiagnostics);
  118. logger_diagnostics_1.printDiagnostics(context, logger_diagnostics_1.DiagnosticsType.TypeScript, diagnostics, true, false);
  119. throw new errors_1.BuildError(new Error('Failed to transpile TypeScript'));
  120. }
  121. return program;
  122. }
  123. function replaceBootstrap(mainFile, appNgModulePath, appNgModuleClass, options) {
  124. if (!mainFile) {
  125. throw new errors_1.BuildError(new Error("Could not find entry point (bootstrap file) " + options.entryPoint));
  126. }
  127. var modifiedFileContent = null;
  128. try {
  129. logger_1.Logger.debug('[AotCompiler] compile: Dynamically changing entry point content to AOT mode content');
  130. modifiedFileContent = utils_1.replaceBootstrapImpl(mainFile.path, mainFile.content, appNgModulePath, appNgModuleClass);
  131. }
  132. catch (ex) {
  133. logger_1.Logger.debug("Failed to parse bootstrap: ", ex.message);
  134. logger_1.Logger.warn("Failed to parse and update " + options.entryPoint + " content for AoT compilation.\n For now, the default fallback content will be used instead.\n Please consider updating " + options.entryPoint + " with the content from the following link:\n https://github.com/ionic-team/ionic2-app-base/tree/master/src/app/main.ts");
  135. modifiedFileContent = utils_1.getFallbackMainContent();
  136. }
  137. return modifiedFileContent;
  138. }
  139. function isTranspileRequired(angularVersion) {
  140. return angularVersion.major <= 4;
  141. }
  142. exports.isTranspileRequired = isTranspileRequired;
  143. function transpileFiles(context, tsConfig, fileSystem) {
  144. var tsFiles = context.fileCache.getAll().filter(function (file) { return path_1.extname(file.path) === '.ts' && file.path.indexOf('.d.ts') === -1; });
  145. for (var _i = 0, tsFiles_1 = tsFiles; _i < tsFiles_1.length; _i++) {
  146. var tsFile = tsFiles_1[_i];
  147. logger_1.Logger.debug("[AotCompiler] transpileFiles: Transpiling file " + tsFile.path + " ...");
  148. var transpileOutput = transpileFileContent(tsFile.path, tsFile.content, tsConfig.options);
  149. var diagnostics = logger_typescript_1.runTypeScriptDiagnostics(context, transpileOutput.diagnostics);
  150. if (diagnostics.length) {
  151. // darn, we've got some things wrong, transpile failed :(
  152. logger_diagnostics_1.printDiagnostics(context, logger_diagnostics_1.DiagnosticsType.TypeScript, diagnostics, true, true);
  153. throw new errors_1.BuildError(new Error('Failed to transpile TypeScript'));
  154. }
  155. var jsFilePath = helpers_1.changeExtension(tsFile.path, '.js');
  156. fileSystem.addVirtualFile(jsFilePath, transpileOutput.outputText);
  157. fileSystem.addVirtualFile(jsFilePath + '.map', transpileOutput.sourceMapText);
  158. logger_1.Logger.debug("[AotCompiler] transpileFiles: Transpiling file " + tsFile.path + " ... DONE");
  159. }
  160. }
  161. exports.transpileFiles = transpileFiles;
  162. function transpileFileContent(fileName, sourceText, options) {
  163. var transpileOptions = {
  164. compilerOptions: options,
  165. fileName: fileName,
  166. reportDiagnostics: true
  167. };
  168. return typescript_1.transpileModule(sourceText, transpileOptions);
  169. }
  170. function isNg5(version) {
  171. return version.major >= 5;
  172. }
  173. exports.isNg5 = isNg5;
  174. function runNg4Aot(options) {
  175. return __awaiter(this, void 0, void 0, function () {
  176. var module;
  177. return __generator(this, function (_a) {
  178. switch (_a.label) {
  179. case 0: return [4 /*yield*/, Promise.resolve().then(function () { return require('@angular/compiler-cli'); })];
  180. case 1:
  181. module = _a.sent();
  182. return [4 /*yield*/, module.__NGTOOLS_PRIVATE_API_2.codeGen({
  183. angularCompilerOptions: options.angularCompilerOptions,
  184. basePath: options.cliOptions.basePath,
  185. program: options.program,
  186. host: options.compilerHost,
  187. compilerOptions: options.compilerOptions,
  188. i18nFile: options.cliOptions.i18nFile,
  189. i18nFormat: options.cliOptions.i18nFormat,
  190. locale: options.cliOptions.locale,
  191. readResource: function (fileName) {
  192. return helpers_1.readFileAsync(fileName);
  193. }
  194. })];
  195. case 2: return [2 /*return*/, _a.sent()];
  196. }
  197. });
  198. });
  199. }
  200. exports.runNg4Aot = runNg4Aot;
  201. function runNg5Aot(context, tsConfig, aggregateCompilerOptions, compilerHost) {
  202. return __awaiter(this, void 0, void 0, function () {
  203. var ngTools2, angularCompilerHost, program, transformations, transformers, result, tsDiagnostics, angularDiagnostics, diagnostics, diagnostics;
  204. return __generator(this, function (_a) {
  205. switch (_a.label) {
  206. case 0: return [4 /*yield*/, Promise.resolve().then(function () { return require('@angular/compiler-cli/ngtools2'); })];
  207. case 1:
  208. ngTools2 = _a.sent();
  209. angularCompilerHost = ngTools2.createCompilerHost({ options: aggregateCompilerOptions, tsHost: compilerHost });
  210. program = ngTools2.createProgram({
  211. rootNames: tsConfig.fileNames,
  212. options: aggregateCompilerOptions,
  213. host: angularCompilerHost,
  214. oldProgram: null
  215. });
  216. return [4 /*yield*/, program.loadNgStructureAsync()];
  217. case 2:
  218. _a.sent();
  219. transformations = [];
  220. transformers = {
  221. beforeTs: transformations
  222. };
  223. result = program.emit({ emitFlags: ngTools2.EmitFlags.Default, customTransformers: transformers });
  224. tsDiagnostics = program.getTsSyntacticDiagnostics()
  225. .concat(program.getTsOptionDiagnostics())
  226. .concat(program.getTsSemanticDiagnostics());
  227. angularDiagnostics = program.getNgStructuralDiagnostics()
  228. .concat(program.getNgOptionDiagnostics());
  229. if (tsDiagnostics.length) {
  230. diagnostics = logger_typescript_1.runTypeScriptDiagnostics(context, tsDiagnostics);
  231. logger_diagnostics_1.printDiagnostics(context, logger_diagnostics_1.DiagnosticsType.TypeScript, diagnostics, true, false);
  232. throw new errors_1.BuildError(new Error('The Angular AoT build failed. See the issues above'));
  233. }
  234. if (angularDiagnostics.length) {
  235. diagnostics = logger_typescript_1.runTypeScriptDiagnostics(context, angularDiagnostics);
  236. logger_diagnostics_1.printDiagnostics(context, logger_diagnostics_1.DiagnosticsType.TypeScript, diagnostics, true, false);
  237. throw new errors_1.BuildError(new Error('The Angular AoT build failed. See the issues above'));
  238. }
  239. return [2 /*return*/];
  240. }
  241. });
  242. });
  243. }
  244. exports.runNg5Aot = runNg5Aot;