diff --git a/packages/compiler-cli/BUILD.bazel b/packages/compiler-cli/BUILD.bazel index 4840768b04..09fccb0c68 100644 --- a/packages/compiler-cli/BUILD.bazel +++ b/packages/compiler-cli/BUILD.bazel @@ -41,5 +41,8 @@ npm_package( "ivy-local", "release-with-framework", ], - deps = [":compiler-cli"], + deps = [ + ":compiler-cli", + "//packages/compiler-cli/src/ngcc", + ], ) diff --git a/packages/compiler-cli/package.json b/packages/compiler-cli/package.json index bf12320189..4529592ff2 100644 --- a/packages/compiler-cli/package.json +++ b/packages/compiler-cli/package.json @@ -5,6 +5,7 @@ "main": "index.js", "typings": "index.d.ts", "bin": { + "ivy-ngcc": "./src/ngcc/main-ngcc.js", "ngc": "./src/main.js", "ng-xi18n": "./src/extract_i18n.js" }, @@ -12,7 +13,10 @@ "reflect-metadata": "^0.1.2", "minimist": "^1.2.0", "tsickle": "^0.32.1", - "chokidar": "^1.4.2" + "chokidar": "^1.4.2", + "convert-source-map": "^1.5.1", + "magic-string": "^0.25.0", + "source-map": "^0.6.1" }, "peerDependencies": { "typescript": ">=2.7.2 <2.10", diff --git a/packages/compiler-cli/src/ngcc/BUILD.bazel b/packages/compiler-cli/src/ngcc/BUILD.bazel new file mode 100644 index 0000000000..9b69823c82 --- /dev/null +++ b/packages/compiler-cli/src/ngcc/BUILD.bazel @@ -0,0 +1,21 @@ +package(default_visibility = ["//visibility:public"]) + +load("//tools:defaults.bzl", "ts_library") +load("@build_bazel_rules_nodejs//:defs.bzl", "jasmine_node_test") + +ts_library( + name = "ngcc", + srcs = glob([ + "*.ts", + "**/*.ts", + ]), + module_name = "@angular/compiler-cli/src/ngcc", + deps = [ + "//packages:types", + "//packages/compiler", + "//packages/compiler-cli/src/ngtsc/annotations", + "//packages/compiler-cli/src/ngtsc/host", + "//packages/compiler-cli/src/ngtsc/metadata", + "//packages/compiler-cli/src/ngtsc/transform", + ], +) diff --git a/packages/compiler-cli/src/ngcc/README.md b/packages/compiler-cli/src/ngcc/README.md new file mode 100644 index 0000000000..6a3a3844b2 --- /dev/null +++ b/packages/compiler-cli/src/ngcc/README.md @@ -0,0 +1,30 @@ +# Angular Compatibility Compiler (ngcc) + +This compiler will convert `node_modules` compiled with `ngc`, into `node_modules` which +appear to have been compiled with `ngtsc`. + +This conversion will allow such "legacy" packages to be used by the Ivy rendering engine. + +## Building + +The project is built using Bazel: + +```bash +bazel build //packages/compiler-cli/src/ngcc +``` + +## Unit Testing + +The unit tests are built and run using Bazel: + +```bash +bazel test //packages/compiler-cli/src/ngcc/test +``` + +## Integration Testing + +There are tests that check the behaviour of the overall executable: + +```bash +bazel test //packages/compiler-cli/test/ngcc +``` diff --git a/packages/compiler-cli/src/ngcc/index.ts b/packages/compiler-cli/src/ngcc/index.ts new file mode 100644 index 0000000000..b7c62ac522 --- /dev/null +++ b/packages/compiler-cli/src/ngcc/index.ts @@ -0,0 +1,9 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +export {mainNgcc} from './src/main'; diff --git a/packages/compiler-cli/src/ngcc/main-ngcc.ts b/packages/compiler-cli/src/ngcc/main-ngcc.ts new file mode 100644 index 0000000000..08524a6afa --- /dev/null +++ b/packages/compiler-cli/src/ngcc/main-ngcc.ts @@ -0,0 +1,16 @@ +#!/usr/bin/env node +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {mainNgcc} from './src/main'; + +// CLI entry point +if (require.main === module) { + const args = process.argv.slice(2); + process.exitCode = mainNgcc(args); +} diff --git a/packages/compiler-cli/src/ngcc/src/main.ts b/packages/compiler-cli/src/ngcc/src/main.ts new file mode 100644 index 0000000000..b20388f7e4 --- /dev/null +++ b/packages/compiler-cli/src/ngcc/src/main.ts @@ -0,0 +1,14 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +import {resolve} from 'path'; + +export function mainNgcc(args: string[]): number { + const packagePath = resolve(args[0]); + + return 0; +} diff --git a/packages/compiler-cli/src/ngcc/test/BUILD.bazel b/packages/compiler-cli/src/ngcc/test/BUILD.bazel new file mode 100644 index 0000000000..c54936a989 --- /dev/null +++ b/packages/compiler-cli/src/ngcc/test/BUILD.bazel @@ -0,0 +1,26 @@ +package(default_visibility = ["//visibility:public"]) + +load("//tools:defaults.bzl", "ts_library") +load("@build_bazel_rules_nodejs//:defs.bzl", "jasmine_node_test") + +ts_library( + name = "test_lib", + testonly = 1, + srcs = glob([ + "**/*.ts", + ]), + deps = [ + "//packages/compiler-cli/src/ngcc", + "//packages/compiler-cli/src/ngtsc/host", + "//packages/compiler-cli/src/ngtsc/testing", + ], +) + +jasmine_node_test( + name = "test", + bootstrap = ["angular/tools/testing/init_node_no_angular_spec.js"], + deps = [ + ":test_lib", + "//tools/testing:node_no_angular", + ], +) diff --git a/packages/compiler-cli/test/ngcc/BUILD.bazel b/packages/compiler-cli/test/ngcc/BUILD.bazel new file mode 100644 index 0000000000..9745a3f6bd --- /dev/null +++ b/packages/compiler-cli/test/ngcc/BUILD.bazel @@ -0,0 +1,28 @@ +load("//tools:defaults.bzl", "ts_library") +load("@build_bazel_rules_nodejs//:defs.bzl", "jasmine_node_test") + +# Integration tests +ts_library( + name = "ngcc_lib", + testonly = 1, + srcs = glob([ + "**/*_spec.ts", + ]), + deps = [ + "//packages/compiler-cli/src/ngcc", + "//packages/compiler-cli/test:test_utils", + ], +) + +jasmine_node_test( + name = "ngcc", + bootstrap = ["angular/tools/testing/init_node_no_angular_spec.js"], + data = [ + "//packages/common:npm_package", + "//packages/core:npm_package", + ], + deps = [ + ":ngcc_lib", + "//tools/testing:node_no_angular", + ], +) diff --git a/packages/compiler-cli/test/ngcc/ngcc_spec.ts b/packages/compiler-cli/test/ngcc/ngcc_spec.ts new file mode 100644 index 0000000000..aab460be00 --- /dev/null +++ b/packages/compiler-cli/test/ngcc/ngcc_spec.ts @@ -0,0 +1,88 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as fs from 'fs'; +import * as path from 'path'; +import {cat, find} from 'shelljs'; + +import {mainNgcc} from '../../src/ngcc/src/main'; + +import {TestSupport, isInBazel, setup} from '../test_support'; + +function setupNodeModules(support: TestSupport): void { + const corePath = path.join(process.env.TEST_SRCDIR, 'angular/packages/core/npm_package'); + const commonPath = path.join(process.env.TEST_SRCDIR, 'angular/packages/common/npm_package'); + + const nodeModulesPath = path.join(support.basePath, 'node_modules'); + const angularCoreDirectory = path.join(nodeModulesPath, '@angular/core'); + const angularCommonDirectory = path.join(nodeModulesPath, '@angular/common'); + + // fs.symlinkSync(corePath, angularCoreDirectory); + // fs.symlinkSync(commonPath, angularCommonDirectory); +} + +describe('ngcc behavioral tests', () => { + if (!isInBazel()) { + // These tests should be excluded from the non-Bazel build. + return; + } + + let basePath: string; + let outDir: string; + let write: (fileName: string, content: string) => void; + let errorSpy: jasmine.Spy&((s: string) => void); + + function shouldExist(fileName: string) { + if (!fs.existsSync(path.resolve(outDir, fileName))) { + throw new Error(`Expected ${fileName} to be emitted (outDir: ${outDir})`); + } + } + + function shouldNotExist(fileName: string) { + if (fs.existsSync(path.resolve(outDir, fileName))) { + throw new Error(`Did not expect ${fileName} to be emitted (outDir: ${outDir})`); + } + } + + function getContents(fileName: string): string { + shouldExist(fileName); + const modulePath = path.resolve(outDir, fileName); + return fs.readFileSync(modulePath, 'utf8'); + } + + function writeConfig( + tsconfig: string = + '{"extends": "./tsconfig-base.json", "angularCompilerOptions": {"enableIvy": "ngtsc"}}') { + write('tsconfig.json', tsconfig); + } + + beforeEach(() => { + errorSpy = jasmine.createSpy('consoleError').and.callFake(console.error); + const support = setup(); + basePath = support.basePath; + outDir = path.join(basePath, 'built'); + process.chdir(basePath); + write = (fileName: string, content: string) => { support.write(fileName, content); }; + + setupNodeModules(support); + }); + + it('should run ngcc without errors', () => { + const nodeModulesPath = path.join(basePath, 'node_modules'); + console.error(nodeModulesPath); + const commonPath = path.join(nodeModulesPath, '@angular/common'); + const exitCode = mainNgcc([commonPath]); + + console.warn(find('node_modules_ngtsc').filter(p => p.endsWith('.js') || p.endsWith('map'))); + + console.warn(cat('node_modules_ngtsc/@angular/common/fesm2015/common.js').stdout); + console.warn(cat('node_modules_ngtsc/@angular/common/fesm2015/common.js.map').stdout); + + expect(exitCode).toBe(0); + }); +});