diff --git a/packages/bazel/src/api-extractor/index.ts b/packages/bazel/src/api-extractor/index.ts index 4df9ecd8f7..2d327e4970 100644 --- a/packages/bazel/src/api-extractor/index.ts +++ b/packages/bazel/src/api-extractor/index.ts @@ -114,5 +114,19 @@ api-extractor: running with } const [tsConfig, entryPoint, dtsBundleOut] = process.argv.slice(2); - process.exitCode = runMain(tsConfig, entryPoint, dtsBundleOut); + const entryPoints = entryPoint.split(','); + const dtsBundleOuts = dtsBundleOut.split(','); + + if (entryPoints.length !== entryPoints.length) { + throw new Error( + `Entry points count (${entryPoints.length}) does not match Bundle out count (${dtsBundleOuts.length})`); + } + + for (let i = 0; i < entryPoints.length; i++) { + process.exitCode = runMain(tsConfig, entryPoints[i], dtsBundleOuts[i]); + + if (process.exitCode !== 0) { + break; + } + } } diff --git a/packages/bazel/src/ng_module.bzl b/packages/bazel/src/ng_module.bzl index 416927ff3d..07685f90fe 100644 --- a/packages/bazel/src/ng_module.bzl +++ b/packages/bazel/src/ng_module.bzl @@ -21,6 +21,7 @@ load( ) _FLAT_DTS_FILE_SUFFIX = ".bundle.d.ts" +_R3_SYMBOLS_DTS_FILE = "src/r3_symbols.d.ts" def compile_strategy(ctx): """Detect which strategy should be used to implement ng_module. @@ -142,6 +143,25 @@ def _should_produce_dts_bundle(ctx): # see: https://github.com/Microsoft/web-build-tools/issues/1029 return _is_legacy_ngc(ctx) and hasattr(ctx.attr, "bundle_dts") and ctx.attr.bundle_dts +def _should_produce_r3_symbols_bundle(ctx): + """Should we produce r3_symbols bundle. + + NGCC relies on having r3_symbols file. This file is located in @angular/core + And should only be included when bundling core in legacy mode. + + Args: + ctx: skylark rule execution context + + Returns: + true when we should produce r3_symbols dts. + """ + + # iif we are compiling @angular/core with ngc we should add this addition dts bundle + # because ngcc relies on having this file. + # see: https://github.com/angular/angular/blob/84406e4d6d93b28b23efbb1701bc5ae1084da67b/packages/compiler-cli/src/ngcc/src/packages/entry_point_bundle.ts#L56 + # todo: alan-agius4: remove when ngcc doesn't need this anymore + return _is_legacy_ngc(ctx) and ctx.attr.module_name == "@angular/core" + def _should_produce_flat_module_outs(ctx): """Should we produce flat module outputs. @@ -221,13 +241,16 @@ def _expected_outs(ctx): if not _is_bazel(): metadata_files += [ctx.actions.declare_file(basename + ext) for ext in metadata] - dts_bundle = None + dts_bundles = None if _should_produce_dts_bundle(ctx): # We need to add a suffix to bundle as it might collide with the flat module dts. # The flat module dts out contains several other exports - # https://github.com/angular/angular/blob/master/packages/compiler-cli/src/metadata/index_writer.ts#L18 + # https://github.com/angular/angular/blob/84406e4d6d93b28b23efbb1701bc5ae1084da67b/packages/compiler-cli/src/metadata/index_writer.ts#L18 # the file name will be like 'core.bundle.d.ts' - dts_bundle = ctx.actions.declare_file(ctx.label.name + _FLAT_DTS_FILE_SUFFIX) + dts_bundles = [ctx.actions.declare_file(ctx.label.name + _FLAT_DTS_FILE_SUFFIX)] + + if _should_produce_r3_symbols_bundle(ctx): + dts_bundles.append(ctx.actions.declare_file(_R3_SYMBOLS_DTS_FILE.replace(".d.ts", _FLAT_DTS_FILE_SUFFIX))) # We do this just when producing a flat module index for a publishable ng_module if _should_produce_flat_module_outs(ctx): @@ -254,7 +277,7 @@ def _expected_outs(ctx): declarations = declaration_files, summaries = summary_files, metadata = metadata_files, - dts_bundle = dts_bundle, + dts_bundles = dts_bundles, bundle_index_typings = bundle_index_typings, i18n_messages = i18n_messages_files, ) @@ -337,7 +360,7 @@ def ngc_compile_action( node_opts, locale = None, i18n_args = [], - dts_bundle_out = None): + dts_bundles_out = None): """Helper function to create the ngc action. This is exposed for google3 to wire up i18n replay rules, and is not intended @@ -353,7 +376,7 @@ def ngc_compile_action( node_opts: list of strings, extra nodejs options. locale: i18n locale, or None i18n_args: additional command-line arguments to ngc - dts_bundle_out: produced flattened dts file + dts_bundles_out: produced flattened dts file Returns: the parameters of the compilation which will be used to replay the ngc action for i18N. @@ -412,25 +435,28 @@ def ngc_compile_action( mnemonic = "Angular2MessageExtractor", ) - if dts_bundle_out != None: + if dts_bundles_out != None: # combine the inputs and outputs and filter .d.ts and json files filter_inputs = [f for f in inputs + outputs if f.path.endswith(".d.ts") or f.path.endswith(".json")] if _should_produce_flat_module_outs(ctx): - dts_entry_point = "%s.d.ts" % _flat_module_out_file(ctx) + dts_entry_points = ["%s.d.ts" % _flat_module_out_file(ctx)] else: - dts_entry_point = ctx.attr.entry_point.replace(".ts", ".d.ts") + dts_entry_points = [ctx.attr.entry_point.replace(".ts", ".d.ts")] + + if _should_produce_r3_symbols_bundle(ctx): + dts_entry_points.append(_R3_SYMBOLS_DTS_FILE) ctx.actions.run( progress_message = "Bundling DTS %s" % str(ctx.label), mnemonic = "APIExtractor", executable = ctx.executable._api_extractor, inputs = filter_inputs, - outputs = [dts_bundle_out], + outputs = dts_bundles_out, arguments = [ tsconfig_file.path, - "/".join([ctx.bin_dir.path, ctx.label.package, dts_entry_point]), - dts_bundle_out.path, + ",".join(["/".join([ctx.bin_dir.path, ctx.label.package, f]) for f in dts_entry_points]), + ",".join([f.path for f in dts_bundles_out]), ], ) @@ -454,7 +480,7 @@ def _filter_ts_inputs(all_inputs): if f.path.endswith(".js") or f.path.endswith(".ts") or f.path.endswith(".json") ] -def _compile_action(ctx, inputs, outputs, dts_bundle_out, messages_out, tsconfig_file, node_opts): +def _compile_action(ctx, inputs, outputs, dts_bundles_out, messages_out, tsconfig_file, node_opts): # Give the Angular compiler all the user-listed assets file_inputs = list(ctx.files.assets) @@ -483,7 +509,7 @@ def _compile_action(ctx, inputs, outputs, dts_bundle_out, messages_out, tsconfig ], ) - return ngc_compile_action(ctx, ctx.label, action_inputs, outputs, messages_out, tsconfig_file, node_opts, None, [], dts_bundle_out) + return ngc_compile_action(ctx, ctx.label, action_inputs, outputs, messages_out, tsconfig_file, node_opts, None, [], dts_bundles_out) def _prodmode_compile_action(ctx, inputs, outputs, tsconfig_file, node_opts): outs = _expected_outs(ctx) @@ -492,7 +518,7 @@ def _prodmode_compile_action(ctx, inputs, outputs, tsconfig_file, node_opts): def _devmode_compile_action(ctx, inputs, outputs, tsconfig_file, node_opts): outs = _expected_outs(ctx) compile_action_outputs = outputs + outs.devmode_js + outs.declarations + outs.summaries + outs.metadata - _compile_action(ctx, inputs, compile_action_outputs, outs.dts_bundle, None, tsconfig_file, node_opts) + _compile_action(ctx, inputs, compile_action_outputs, outs.dts_bundles, None, tsconfig_file, node_opts) def _ts_expected_outs(ctx, label, srcs_files = []): # rules_typescript expects a function with two or more arguments, but our @@ -553,8 +579,8 @@ def ng_module_impl(ctx, ts_compile_actions): flat_module_out_file = _flat_module_out_file(ctx), ) - if outs.dts_bundle != None: - providers["dts_bundle"] = outs.dts_bundle + if outs.dts_bundles != None: + providers["dts_bundles"] = outs.dts_bundles return providers diff --git a/packages/bazel/src/ng_package/ng_package.bzl b/packages/bazel/src/ng_package/ng_package.bzl index c1b4c64492..1fe0d5a365 100644 --- a/packages/bazel/src/ng_package/ng_package.bzl +++ b/packages/bazel/src/ng_package/ng_package.bzl @@ -229,8 +229,8 @@ def _ng_package_impl(ctx): # fallback to a reasonable default flat_module_out_file = "index.js" - if hasattr(dep, "dts_bundle"): - bundled_type_definitions.append(dep.dts_bundle) + if hasattr(dep, "dts_bundles"): + bundled_type_definitions += dep.dts_bundles elif len(type_definitions) == 0: # Filter out all TypeScript definitions generated by NGC as well as definition files # that do not belong to the current package. We only want to package types that belong diff --git a/packages/bazel/test/ng_package/core_package.spec.ts b/packages/bazel/test/ng_package/core_package.spec.ts index 7d231884fe..a30e27eab5 100644 --- a/packages/bazel/test/ng_package/core_package.spec.ts +++ b/packages/bazel/test/ng_package/core_package.spec.ts @@ -27,13 +27,9 @@ function p(templateStringArray: TemplateStringsArray) { return path.join(...segments); } - describe('@angular/core ng_package', () => { - describe('misc root files', () => { - describe('README.md', () => { - it('should have a README.md file with basic info', () => { expect(shx.cat('README.md')).toContain(`Angular`); expect(shx.cat('README.md')).toContain(`https://github.com/angular/angular`); @@ -41,17 +37,13 @@ describe('@angular/core ng_package', () => { }); }); - describe('primary entry-point', () => { - describe('package.json', () => { - const packageJson = 'package.json'; it('should have a package.json file', () => { expect(shx.grep('"name":', packageJson)).toContain(`@angular/core`); }); - it('should contain correct version number with the PLACEHOLDER string replaced', () => { expect(shx.grep('"version":', packageJson)).toMatch(/\d+\.\d+\.\d+(?!-PLACEHOLDER)/); }); @@ -72,31 +64,33 @@ describe('@angular/core ng_package', () => { }); }); - describe('typescript support', () => { - it('should have an index d.ts file', - () => { expect(shx.cat('core.d.ts')).toContain(`export *`); }); + if (ivyEnabled) { + it('should have an index d.ts file', + () => { expect(shx.cat('core.d.ts')).toContain(`export *`); }); - it('should not have amd module names', - () => { expect(shx.cat('public_api.d.ts')).not.toContain(' { expect(shx.cat('public_api.d.ts')).not.toContain(' { expect(shx.cat('core.d.ts')).toContain('export declare'); }); + it('should have an r3_symbols d.ts file', + () => { expect(shx.cat('src/r3_symbols.d.ts')).toContain('export declare'); }); + } }); - describe('closure', () => { it('should contain externs', () => { expect(shx.cat('src/testability/testability.externs.js')).toContain('/** @externs */'); }); }); - obsoleteInIvy('metadata files are no longer needed or produced in Ivy') .describe('angular metadata', () => { - it('should have metadata.json files', () => { expect(shx.cat('core.metadata.json')).toContain(`"__symbolic":"module"`); }); }); - describe('fesm2015', () => { it('should have a fesm15 file in the /fesm2015 directory', () => { expect(shx.cat('fesm2015/core.js')).toContain(`export {`); }); @@ -117,9 +111,7 @@ describe('@angular/core ng_package', () => { }); }); - describe('fesm5', () => { - it('should have a fesm5 file in the /fesm5 directory', () => { expect(shx.cat('fesm5/core.js')).toContain(`export {`); }); @@ -151,7 +143,6 @@ describe('@angular/core ng_package', () => { () => { expect(shx.cat('fesm5/core.js')).toMatch('export {.*makeParamDecorator'); }); }); - describe('esm2015', () => { it('should not contain any *.ngfactory.js files', () => { expect(shx.find('esm2015').filter(f => f.endsWith('.ngfactory.js'))).toEqual([]); @@ -162,7 +153,6 @@ describe('@angular/core ng_package', () => { }); }); - describe('esm5', () => { it('should not contain any *.ngfactory.js files', () => { expect(shx.find('esm5').filter(f => f.endsWith('.ngfactory.js'))).toEqual([]); }); @@ -171,9 +161,7 @@ describe('@angular/core ng_package', () => { () => { expect(shx.find('esm5').filter(f => f.endsWith('.ngsummary.js'))).toEqual([]); }); }); - describe('umd', () => { - it('should have a umd file in the /bundles directory', () => { expect(shx.ls('bundles/core.umd.js').length).toBe(1, 'File not found'); }); @@ -204,7 +192,6 @@ describe('@angular/core ng_package', () => { describe('secondary entry-point', () => { describe('package.json', () => { - const packageJson = p `testing/package.json`; it('should have a package.json file', @@ -222,9 +209,15 @@ describe('@angular/core ng_package', () => { }); describe('typings', () => { - const typingsFile = p `testing/index.d.ts`; - it('should have a typings file', - () => { expect(shx.cat(typingsFile)).toContain(`export * from './public_api';`); }); + if (ivyEnabled) { + const typingsFile = p `testing/index.d.ts`; + it('should have a typings file', + () => { expect(shx.cat(typingsFile)).toContain(`export * from './public_api';`); }); + } else { + const typingsFile = p `testing/testing.d.ts`; + it('should have a typings file', + () => { expect(shx.cat(typingsFile)).toContain('export declare'); }); + } obsoleteInIvy( 'now that we don\'t need metadata files, we don\'t need these redirects to help resolve paths to them') @@ -268,7 +261,6 @@ describe('@angular/core ng_package', () => { }); describe('umd', () => { - it('should have a umd file in the /bundles directory', () => { expect(shx.ls('bundles/core-testing.umd.js').length).toBe(1, 'File not found'); }); @@ -292,7 +284,6 @@ describe('@angular/core ng_package', () => { it('should define ng global symbols', () => { expect(shx.cat('bundles/core-testing.umd.js')).toContain('global.ng.core.testing = {}'); }); - }); }); }); diff --git a/packages/core/BUILD.bazel b/packages/core/BUILD.bazel index e67e93dc22..a722331a72 100644 --- a/packages/core/BUILD.bazel +++ b/packages/core/BUILD.bazel @@ -10,8 +10,6 @@ ng_module( "src/**/*.ts", ], ), - # PR to support this https://github.com/angular/angular/pull/28884 - bundle_dts = False, deps = [ "//packages:types", "//packages/core/src/compiler", diff --git a/packages/core/src/render3/definition.ts b/packages/core/src/render3/definition.ts index 87d644ab6c..5f6bc7eb5d 100644 --- a/packages/core/src/render3/definition.ts +++ b/packages/core/src/render3/definition.ts @@ -19,7 +19,9 @@ import {stringify} from '../util/stringify'; import {EMPTY_ARRAY, EMPTY_OBJ} from './empty'; import {NG_COMPONENT_DEF, NG_DIRECTIVE_DEF, NG_MODULE_DEF, NG_PIPE_DEF} from './fields'; import {BaseDef, ComponentDef, ComponentDefFeature, ComponentTemplate, ComponentType, ContentQueriesFunction, DirectiveDef, DirectiveDefFeature, DirectiveType, DirectiveTypesOrFactory, FactoryFn, HostBindingsFunction, PipeDef, PipeType, PipeTypesOrFactory, ViewQueriesFunction} from './interfaces/definition'; -import {CssSelectorList} from './interfaces/projection'; +// while SelectorFlags is unused here, it's required so that types don't get resolved lazily +// see: https://github.com/Microsoft/web-build-tools/issues/1050 +import {CssSelectorList, SelectorFlags} from './interfaces/projection'; let _renderCompCount = 0; diff --git a/packages/core/testing/BUILD.bazel b/packages/core/testing/BUILD.bazel index 5095757d46..8009d9f276 100644 --- a/packages/core/testing/BUILD.bazel +++ b/packages/core/testing/BUILD.bazel @@ -9,8 +9,6 @@ ng_module( srcs = glob( ["**/*.ts"], ), - # PR to support this https://github.com/angular/angular/pull/28884 - bundle_dts = False, deps = [ "//packages:types", "//packages/compiler",