diff --git a/.circleci/config.yml b/.circleci/config.yml index b24e3cbf5547..ebfd18ab4ddf 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -197,8 +197,7 @@ jobs: # Exclude release and docs packages here as those will be built within # the "build_release_packages" and "publish_snapshots" jobs. - # TODO(devversion): remove target exclusion once https://github.com/bazelbuild/rules_nodejs/pull/2646 is available. - - run: bazel build --build_tag_filters=-docs-package,-release-package -- src/... -//src/e2e-app:devserver_with_linked_declarations.MF + - run: bazel build --build_tag_filters=-docs-package,-release-package -- src/... - *slack_notify_on_failure # ----------------------------------- @@ -220,8 +219,7 @@ jobs: # Exclude release and docs packages here as those will be built within # the "build_release_packages" and "publish_snapshots" jobs. - # TODO(devversion): remove target exclusion once https://github.com/bazelbuild/rules_nodejs/pull/2646 is available. - - run: bazel build --build_tag_filters=-docs-package,-release-package --config=view-engine -- src/... -//src/e2e-app:devserver_with_linked_declarations.MF + - run: bazel build --build_tag_filters=-docs-package,-release-package --config=view-engine -- src/... - *slack_notify_on_failure # -------------------------------------------------------------------------------------------- @@ -283,8 +281,7 @@ jobs: - *yarn_install - *setup_bazel_binary - # TODO(devversion): remove target exclusion once https://github.com/bazelbuild/rules_nodejs/pull/2646 is available. - - run: bazel test --build_tag_filters=-e2e --test_tag_filters=-e2e --build_tests_only -- src/... -//src/e2e-app:devserver_with_linked_declarations.MF + - run: bazel test --build_tag_filters=-e2e --test_tag_filters=-e2e --build_tests_only -- src/... - *slack_notify_on_failure # ---------------------------------------------------------------------------- @@ -536,8 +533,7 @@ jobs: - *yarn_install_loose_lockfile - *setup_bazel_binary - # TODO(devversion): remove target exclusion once https://github.com/bazelbuild/rules_nodejs/pull/2646 is available. - - run: bazel test --build_tag_filters=-e2e --test_tag_filters=-e2e --build_tests_only -- src/... -//src/e2e-app:devserver_with_linked_declarations.MF + - run: bazel test --build_tag_filters=-e2e --test_tag_filters=-e2e --build_tests_only -- src/... - *slack_notify_on_failure # ---------------------------------------------------------------------------- @@ -558,8 +554,7 @@ jobs: - *setup_bazel_binary # Run project tests with NGC and View Engine. - # TODO(devversion): remove target exclusion once https://github.com/bazelbuild/rules_nodejs/pull/2646 is available. - - run: bazel test --build_tag_filters=-docs-package,-e2e --test_tag_filters=-e2e --config=view-engine --build_tests_only -- src/... -//src/e2e-app:devserver_with_linked_declarations.MF + - run: bazel test --build_tag_filters=-docs-package,-e2e --test_tag_filters=-e2e --config=view-engine --build_tests_only -- src/... - *slack_notify_on_failure # ---------------------------------------------------------------------------- @@ -580,8 +575,7 @@ jobs: - *setup_bazel_binary # Run project tests with NGC and View Engine. - # TODO(devversion): remove target exclusion once https://github.com/bazelbuild/rules_nodejs/pull/2646 is available. - - run: bazel test --build_tag_filters=-docs-package,-e2e --test_tag_filters=-e2e --config=view-engine --build_tests_only -- src/... -//src/e2e-app:devserver_with_linked_declarations.MF + - run: bazel test --build_tag_filters=-docs-package,-e2e --test_tag_filters=-e2e --config=view-engine --build_tests_only -- src/... - *slack_notify_on_failure # ---------------------------------------------------------------------------- @@ -654,8 +648,7 @@ jobs: # Setup the components repository to use the MDC snapshot builds. # Run project tests with the MDC canary builds. - # TODO(devversion): remove target exclusion once https://github.com/bazelbuild/rules_nodejs/pull/2646 is available. - - run: bazel test --build_tag_filters=-docs-package,-e2e --test_tag_filters=-e2e --build_tests_only -- src/... -//src/e2e-app:devserver_with_linked_declarations.MF + - run: bazel test --build_tag_filters=-docs-package,-e2e --test_tag_filters=-e2e --build_tests_only -- src/... - *slack_notify_on_failure # ---------------------------------------------------------------------------------------- diff --git a/package.json b/package.json index 574eba9930c3..f017975a3395 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "approve-size-tests": "node ./scripts/approve-size-golden.js", "integration-tests": "bazel test --test_tag_filters=-view-engine-only,-linker-integration-test --build_tests_only -- //integration/... -//integration/size-test/...", "integration-tests:view-engine": "bazel test --test_tag_filters=view-engine-only --build_tests_only -- //integration/... -//integration/size-test/...", - "integration-tests:partial-ivy": "bazel test --//tools:partial_compilation=True --test_tag_filters=partial-compilation-integration --build_tests_only -- //integration/... //src/...", + "integration-tests:partial-ivy": "bazel test --//tools:partial_compilation=True --test_tag_filters=partial-compilation-integration,-firefox --build_tests_only -- //integration/... //src/...", "integration-tests:size-test": "bazel test //integration/size-test/...", "check-mdc-tests": "ts-node --project scripts/tsconfig.json scripts/check-mdc-tests.ts", "check-mdc-exports": "ts-node --project scripts/tsconfig.json scripts/check-mdc-exports.ts", diff --git a/src/e2e-app/BUILD.bazel b/src/e2e-app/BUILD.bazel index a022118f0280..2230fb14b3da 100644 --- a/src/e2e-app/BUILD.bazel +++ b/src/e2e-app/BUILD.bazel @@ -1,4 +1,3 @@ -load("@npm//@bazel/rollup:index.bzl", "rollup_bundle") load("@npm//@bazel/concatjs:index.bzl", "concatjs_devserver") load("//:packages.bzl", "getAngularUmdTargets") load("//tools:defaults.bzl", "ng_module", "sass_binary") @@ -117,45 +116,3 @@ concatjs_devserver( tags = ["manual"], deps = [":e2e-app"], ) - -# Bundles the `e2e-app` using rollup while running the Angular linker to transform -# partial declarations to their corresponding Angular definitions. This target should -# only be run if the e2e-app is built in partial compilation mode. Technically this -# target could be run with full compilation mode too, but we want to raise an error if -# the partial compilation is not enabled (as the mode has been forgotten most likely). -rollup_bundle( - name = "linked_app_bundle", - testonly = True, - config_file = ":rollup-with-linker.config.js", - entry_points = { - "main.ts": "bundle", - }, - sourcemap = "false", - tags = ["manual"], - deps = select( - { - # We rely on the partial compilation build setting here to ensure that the target - # cannot be built if partial compilation is not enabled. - "//tools:partial_compilation_enabled": [ - ":e2e-app", - "@npm//rollup-plugin-node-resolve", - "@npm//@angular/compiler-cli", - "@npm//@rollup/plugin-babel", - "@npm//@rollup/plugin-commonjs", - "@npm//glob", - ], - }, - no_match_error = "Partial compilation needs to be enabled. The following flag enables partial " + - "compilation: --//tools:partial_compilation=True", - ), -) - -# Basic web server that serves the e2e-app processed by the Angular linker. -concatjs_devserver( - name = "devserver_with_linked_declarations", - testonly = True, - additional_root_paths = ["npm/node_modules"], - port = 4200, - static_files = [":linked_app_bundle"] + devserverIndexHtmlDependencies, - tags = ["manual"], -) diff --git a/src/e2e-app/rollup-with-linker.config.js b/src/e2e-app/rollup-with-linker.config.js deleted file mode 100644 index a899a527c4d4..000000000000 --- a/src/e2e-app/rollup-with-linker.config.js +++ /dev/null @@ -1,76 +0,0 @@ -const node = require('rollup-plugin-node-resolve'); -const {ConsoleLogger, LogLevel} = require("@angular/compiler-cli/src/ngtsc/logging"); -const {NodeJSFileSystem} = require("@angular/compiler-cli/src/ngtsc/file_system"); -const {createEs2015LinkerPlugin} = require('@angular/compiler-cli/linker/babel'); -const {babel} = require('@rollup/plugin-babel'); -const commonjs = require('@rollup/plugin-commonjs'); -const {sync: globSync} = require('glob'); -const {join} = require('path'); - -/** File system used by the Angular linker plugin. */ -const fileSystem = new NodeJSFileSystem(); -/** Logger used by the Angular linker plugin. */ -const logger = new ConsoleLogger(LogLevel.info); -/** Babel plugin that runs the Angular linker. */ -const linkerPlugin = createEs2015LinkerPlugin({fileSystem, logger}); - -/** - * Custom rollup plugin that enables bundling of the component examples which are - * usually loaded lazily. We cannot use lazy loading here as we want to process - * all sources with the linker, and rollup isn't able to process dynamic imports - * which are not statically analyzable. We work around this by transforming the - * dynamic non-static imports to statically analyzable dynamic imports that can be - * processed by rollup. e.g. "import(`@angular/components-examples/${module}/index.js`") - * will be transformed into an object that merges exports from all possible `${module}` values. - */ -const lazyExamplesPlugin = { - transform: (code, id) => { - if (!id.includes('load-example.mjs')) { - return; - } - - // In Bazel actions, the exec root is the current working directory. - const execRoot = process.cwd(); - const examplesPackageDir = join(execRoot, 'node_modules/@angular/components-examples'); - const moduleImports = globSync('*/**/index?(.ngfactory).mjs', {cwd: examplesPackageDir}) - .map(m => `...yield import("@angular/components-examples/${m}")`); - - // Replaces the call to `loadModuleWithFactory` with a statically analyzable object literal that can - // be processed by rollup. We merge all exports of the examples to a single object literal to avoid - // dynamic non-analyzable imports that rollup cannot handle. - return code.replace(/yield loadModuleWithFactory\([^)]+\);/, ` - { - moduleExports: {${moduleImports.join(',')}}, - moduleFactoryExports: {${moduleImports.join(',')}}, - } - `); - }, -} - -module.exports = { - output: { - // Inline all dynamic imports in order to avoid generating multiple chunks. Multiple chunks - // would require enabling `output_dir` which would inherently complicate the devserver setup. - inlineDynamicImports: true, - }, - plugins: [ - commonjs(), - node({ - // The e2e-app runs with Ivy. We need to ensure the NGCC processed entry points are - // loaded for the Angular dependencies. - mainFields: ['es2015_ivy_ngcc', 'module_ivy_ngcc','es2015', 'module'], - }), - lazyExamplesPlugin, - babel({ - plugins: [linkerPlugin], - // There should be no babel helpers required as we process JavaScript code that has - // been generated by TypeScript and uses tslib. We still set this option explicitly - // to avoid a warning by Babel. Also in case there are unprocessed helpers, this - // ensures that the bundle works in the browser as expected. - babelHelpers: 'bundled', - // Due to the large size of referenced files and the potential slow-down, we avoid compression - // by the Babel plugin. - compact: false - }), - ], -}; diff --git a/src/e2e-app/test_suite.bzl b/src/e2e-app/test_suite.bzl index b0431f25e329..e854ca93c718 100644 --- a/src/e2e-app/test_suite.bzl +++ b/src/e2e-app/test_suite.bzl @@ -1,6 +1,6 @@ load("//tools:defaults.bzl", "protractor_web_test_suite") -def e2e_test_suite(name, data = [], tags = ["e2e", "partial-compilation-integration"], deps = []): +def e2e_test_suite(name, data = [], tags = ["e2e"], deps = []): protractor_web_test_suite( name = name, configuration = "//src/e2e-app:protractor.conf.js", @@ -9,12 +9,7 @@ def e2e_test_suite(name, data = [], tags = ["e2e", "partial-compilation-integrat "@npm//@axe-core/webdriverjs", ] + data, on_prepare = "//src/e2e-app:start-devserver.js", - # Based on whether the partial compilation mode is enabled, test either with the default e2e-app - # server, or test with a server that processed all sources with the Angular linker. - server = select({ - "//conditions:default": "//src/e2e-app:devserver", - "//tools:partial_compilation_enabled": "//src/e2e-app:devserver_with_linked_declarations", - }), + server = "//src/e2e-app:devserver", tags = tags, deps = deps, ) diff --git a/tools/defaults.bzl b/tools/defaults.bzl index 1f677373e74a..e7f17d771d6c 100644 --- a/tools/defaults.bzl +++ b/tools/defaults.bzl @@ -9,6 +9,7 @@ load("@npm//@bazel/typescript:index.bzl", _ts_library = "ts_library") load("//:packages.bzl", "VERSION_PLACEHOLDER_REPLACEMENTS", "getAngularUmdTargets") load("//:rollup-globals.bzl", "ROLLUP_GLOBALS") load("//tools/markdown-to-html:index.bzl", _markdown_to_html = "markdown_to_html") +load("//tools/linker-process:index.bzl", "linker_process") _DEFAULT_TSCONFIG_BUILD = "//src:bazel-tsconfig-build.json" _DEFAULT_TSCONFIG_TEST = "//src:tsconfig-test" @@ -161,8 +162,22 @@ def ng_e2e_test_library(deps = [], tsconfig = None, **kwargs): def karma_web_test_suite(name, **kwargs): web_test_args = {} + test_deps = ["//tools/rxjs:rxjs_umd_modules"] + kwargs.get("deps", []) + kwargs["srcs"] = ["@npm//:node_modules/tslib/tslib.js"] + getAngularUmdTargets() + kwargs.get("srcs", []) - kwargs["deps"] = ["//tools/rxjs:rxjs_umd_modules"] + kwargs.get("deps", []) + kwargs["tags"] = ["partial-compilation-integration"] + kwargs.get("tags", []) + kwargs["deps"] = select({ + # Based on whether partial compilation is enabled, use the linker processed dependencies. + "//tools:partial_compilation_enabled": ["%s_linker_processed_deps" % name], + "//conditions:default": test_deps, + }) + + linker_process( + name = "%s_linker_processed_deps" % name, + srcs = test_deps, + testonly = True, + tags = ["manual"], + ) # Set up default browsers if no explicit `browsers` have been specified. if not hasattr(kwargs, "browsers"): diff --git a/tools/linker-process/BUILD.bazel b/tools/linker-process/BUILD.bazel new file mode 100644 index 000000000000..ee77beb5cfe1 --- /dev/null +++ b/tools/linker-process/BUILD.bazel @@ -0,0 +1,30 @@ +load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary") +load("//tools:defaults.bzl", "ts_library") + +package(default_visibility = ["//visibility:public"]) + +ts_library( + name = "sources", + srcs = glob(["**/*.ts"]), + deps = [ + "@npm//@angular/compiler-cli", + "@npm//@babel/core", + "@npm//@babel/traverse", + "@npm//@types/node", + ], +) + +# Exposes the `linker-process` tool as executable so that it can be used as +# build tool (for `ctx.actions.run`) within the `linker_process` custom Bazel rule. +nodejs_binary( + name = "linker-process", + data = [ + ":sources", + ], + entry_point = ":linker-process.ts", + templated_args = [ + # TODO(josephperrott): update dependency usages to no longer need bazel patch module resolver + # See: https://github.com/bazelbuild/rules_nodejs/wiki#--bazel_patch_module_resolver-now-defaults-to-false-2324 + "--bazel_patch_module_resolver", + ], +) diff --git a/tools/linker-process/index.bzl b/tools/linker-process/index.bzl new file mode 100644 index 000000000000..f551a5c0a79e --- /dev/null +++ b/tools/linker-process/index.bzl @@ -0,0 +1,100 @@ +""" + Exposes a custom Bazel rule for processing sources, which are extracted from Bazel + targets, with the Angular linker plugin. +""" + +load("@build_bazel_rules_nodejs//:providers.bzl", "JSModuleInfo", "JSNamedModuleInfo") + +""" +Gets the Bazel manifest path for a given file. Manifest paths are used within Bazel runfile +manifests and are formatted as followed: `/` +""" + +def _to_manifest_path(ctx, file): + # If a file resides outside of the current workspace, we omit the leading `../` + # segment as the rest will contain the workspace name. e.g. `../npm/node_modules/<..>`. + if file.short_path.startswith("../"): + return file.short_path[3:] + else: + return ctx.workspace_name + "/" + file.short_path + +"""Extracts all source files from the specified list of dependencies.""" + +def _extract_source_files(deps): + depsets = [] + for dep in deps: + if JSNamedModuleInfo in dep: + depsets.append(dep[JSNamedModuleInfo].sources) + elif JSModuleInfo in dep: + depsets.append(dep[JSModuleInfo].sources) + elif hasattr(dep, "files"): + depsets.append(dep.files) + return depset(transitive = depsets) + +def _linker_process(ctx): + args = ctx.actions.args() + sources = _extract_source_files(ctx.attr.srcs) + tmp_dir_name = ctx.label.name + + # The output directory manifest path. e.g `angular_material/src/cdk/a11y/linker_processed`. + output_dir_manifest_path = "%s/%s/%s" % (ctx.workspace_name, ctx.label.package, tmp_dir_name) + + # The output directory exec path. e.g `bazel_out/<..>/src/cdk/a11y/linker_processed`. + output_dir_exec_path = "%s/%s/%s" % (ctx.bin_dir.path, ctx.label.package, tmp_dir_name) + + # Given the sources being transformed and written to a new location, the AMD module names + # need to be rewritten. This file maps AMD modules as per the new location to the AMD modules + # as they appear in the sources. i.e. we generate AMD module aliases. + amd_module_mapping_file = ctx.actions.declare_file("%s/_module_mappings.js" % tmp_dir_name) + + args.add(output_dir_exec_path) + args.add(output_dir_manifest_path) + args.add(amd_module_mapping_file.path) + + outputs = [amd_module_mapping_file] + + # Iterate through the determined sources and pass them to the tool as argument. + for input_file in sources.to_list(): + output_pkg_path = _to_manifest_path(ctx, input_file) + args.add("%s:%s" % (input_file.path, output_pkg_path)) + outputs.append(ctx.actions.declare_file("%s/%s" % (tmp_dir_name, output_pkg_path))) + + # Support passing arguments through a parameter file. This is necessary because on Windows + # there is an argument limit and we need to handle a large amount of input files. Bazel + # switches between parameter file and normal argument passing based on the operating system. + # Read more here: https://docs.bazel.build/versions/master/skylark/lib/Args.html#use_param_file + args.use_param_file(param_file_arg = "--param-file=%s", use_always = True) + + ctx.actions.run( + inputs = sources, + outputs = outputs, + executable = ctx.executable._linker_process_tool, + arguments = [args], + progress_message = "NgLinkerProcess", + ) + + outputs_depset = depset(outputs) + + return [ + DefaultInfo(files = outputs_depset), + ] + +""" + Rule definition for the "linker_process" rule that can process a list of targets + with the Angular linker. The processed files can be retrieved through the default + files provider, or through the `JSNamedModuleInfo` provider. +""" +linker_process = rule( + implementation = _linker_process, + attrs = { + "srcs": attr.label_list( + allow_files = True, + doc = """List of sources that should be processed with the Angular linker.""", + ), + "_linker_process_tool": attr.label( + default = Label("//tools/linker-process"), + executable = True, + cfg = "host", + ), + }, +) diff --git a/tools/linker-process/linker-process.ts b/tools/linker-process/linker-process.ts new file mode 100644 index 000000000000..42c2bc4b82c5 --- /dev/null +++ b/tools/linker-process/linker-process.ts @@ -0,0 +1,139 @@ +import {readFileSync, writeFileSync} from 'fs'; +import {join} from 'path'; + +// These imports to `@angular/compiler-cli` need to explicitly specify the `.js` extension as +// otherwise the Bazel NodeJS module resolution would end up resolving the ESM2015 `.mjs` files. +const {NodeJSFileSystem} = require('@angular/compiler-cli/src/ngtsc/file_system/index.js'); +const {ConsoleLogger, LogLevel} = require('@angular/compiler-cli/src/ngtsc/logging/index.js'); +const {createEs2015LinkerPlugin} = require('@angular/compiler-cli/linker/babel/index.js'); + +// There are no types installed for these packages. +const babel = require('@babel/core'); +const {default: traverse} = require('@babel/traverse'); + +/** File system used by the Angular linker plugin. */ +const fileSystem = new NodeJSFileSystem(); +/** Logger used by the Angular linker plugin. */ +const logger = new ConsoleLogger(LogLevel.info); + +/** Basic interface describing a Babel AST node path. */ +interface NodePath { + type: string; + parentPath: NodePath|undefined; + node: any; + buildCodeFrameError(message: string, ctor: T): T; +} + +/** + * Determines the command line arguments for the current Bazel action. Since this action can + * have a large set of input files, Bazel may write the arguments into a parameter file. + * This function is responsible for handling normal argument passing or Bazel parameter files. + * Read more here: https://docs.bazel.build/versions/master/skylark/lib/Args.html#use_param_file + */ +function getBazelActionArguments() { + const args = process.argv.slice(2); + + // If Bazel uses a parameter file, we've specified that it passes the file in the following + // format: "arg0 arg1 --param-file={path_to_param_file}" + if (args[0].startsWith('--param-file=')) { + return readFileSync(args[0].split('=')[1], 'utf8').trim().split('\n'); + } + + return args; +} + +/** Naively checks whether this node path resolves to an Angular declare invocation. */ +function isNgDeclareCallExpression(nodePath: NodePath): boolean { + if (!nodePath.node.name.startsWith('ɵɵngDeclare')) { + return false; + } + + // Expect the `ngDeclare` identifier to be used as part of a property access that + // is invoked within a call expression. e.g. `i0.ɵɵngDeclare<>`. + return nodePath.parentPath?.type === 'MemberExpression' && + nodePath.parentPath.parentPath?.type === 'CallExpression'; +} + +/** Gets the AMD module name for a given Bazel manifest path */ +function manifestPathToAmdName(manifestPath: string): string { + return manifestPath.substring(0, manifestPath.lastIndexOf('.')); +} + +/** Generates a JavaScript file that maps certain AMD modules to their associate. */ +function generateAmdModuleMappingFile(mappings: Map): string { + let amdMappingFileContent = ` + function registerAlias(oldModuleName, newModuleName) { + define(newModuleName, ['require', 'exports', oldModuleName], (require, exports) => { + var source = require(oldModuleName); + Object.keys(source).forEach(function(key) { + exports[key] = source[key]; + }); + }); + } + `; + + for (const [oldModuleName, newModuleName] of mappings.entries()) { + amdMappingFileContent += `registerAlias("${oldModuleName}", "${newModuleName}");\n`; + } + + return amdMappingFileContent; +} + +/** Processes the given file with the Angular linker plugin. */ +function processFileWithLinker(diskFilePath: string, fileContent: string): string { + // We run the linker with JIT mode so that the processed Angular declarations could be + // run within unit tests that rely on JIT information to be available. + const linkerPlugin = createEs2015LinkerPlugin({fileSystem, logger, linkerJitMode: true}); + const {code, ast} = babel.transformSync(fileContent, { + ast: true, + filename: diskFilePath, + filenameRelative: diskFilePath, + plugins: [linkerPlugin], + compact: false, + }); + + // Naively check if there are any Angular declarations left that haven't been linked. + traverse(ast, { + Identifier: (astPath: NodePath) => { + if (isNgDeclareCallExpression(astPath)) { + throw astPath.buildCodeFrameError( + 'Found Angular declaration that has not been linked.', Error); + } + } + }); + + return code; +} + +if (require.main === module) { + const [outputDirExecPath, outputDirManifestPath, amdMappingFileExecPath, ...inputFiles] = + getBazelActionArguments(); + const amdModuleMappings = new Map(); + + for (const inputFileArg of inputFiles) { + const [inputFileExecPath, manifestPath] = inputFileArg.split(':'); + const outputExecPath = join(outputDirExecPath, manifestPath); + const manifestOutputPath = `${outputDirManifestPath}/${manifestPath}`; + const fileContent = readFileSync(inputFileExecPath, 'utf8'); + const oldAmdModuleName = manifestPathToAmdName(manifestPath); + const newAmdModuleName = manifestPathToAmdName(manifestOutputPath); + const processedContent = processFileWithLinker(inputFileExecPath, fileContent); + + // Keep track of the old AMD module name, and the expected new one. The AMD module + // names are based on the file location within the repository. This matches the + // AMD module names being generated by the NodeJS Bazel rules. + amdModuleMappings.set(oldAmdModuleName, newAmdModuleName); + + writeFileSync(outputExecPath, processedContent); + } + + // Generate a mapping file for AMD module names. Given we move sources to a new location, their + // existing AMD module names like `angular_material/src/cdk/a11y/a11y.spec` are no longer valid. + // Since we do not want to modify the AMD module code directly (and rewrite potential imports), + // we keep the original AMD module names, but also generate a new file that maps the "new" AMD + // module names (based on their new location) to the old AMD modules. This is necessary so that + // imports continue to work, and that tests can be run within the `karma_web_test` rule. + // https://github.com/bazelbuild/rules_nodejs/blob/a611b600b5d2f1242ee615ac4b1c8cd03d0c3b03/packages/concatjs/web_test/karma.conf.js#L310-L319 + const mappingContent = generateAmdModuleMappingFile(amdModuleMappings); + writeFileSync(amdMappingFileExecPath, mappingContent); +} diff --git a/tools/tsconfig-ci.json b/tools/tsconfig-ci.json index a0ac1216c4cc..8ca964ba351d 100644 --- a/tools/tsconfig-ci.json +++ b/tools/tsconfig-ci.json @@ -10,6 +10,7 @@ "lib": ["es2015"], "skipLibCheck": true, // Don't emit to the file system, because we only want to check for compilation errors. - "noEmit": true + "noEmit": true, + "downlevelIteration": true } }