From 35fff2b34e7b3b1170b894dadf50fa8822347e39 Mon Sep 17 00:00:00 2001 From: Greg Magolan Date: Fri, 4 Oct 2019 09:38:42 -0700 Subject: [PATCH] feat(typescript): add JSNamedModuleInfo provider to ts_library outputs All rules that require devmode named sources are updated to use JSNamedModuleInfo. The rules affected are karma, protractor, ts_devserver, ts_proto_library (in labs) & npm_package. Some related non-breaking changes: * node_module_library scripts attribute renamed to named_module_srcs. node_module_library is currently not part of the public API and in user code the npm targets are generated by generate_build_file.ts by yarn_install & npm_install. BREAKING CHANGES: The following breaking changes are from internal details so they should not affect most users. Some some downstream projects, however, such as Angular rely on these internal details and will need to be updated accordingly when updating to the next release. * sources_aspect from /internal/node/node.bzl and /internal/common/sources_aspect.bzl is removed; its functionality was duplicate to what JSNamedModuleInfo providers * NodeModuleSources is removed and its sources field is moved to NpmPackageInfo; sources in the removed scripts field are provided by the JSNamedModuleInfo provider which node_module_library now provides * collect_node_modules_aspect renamed to just node_modules_aspect fix: nodejs_binary doesn't need declaration files --- WORKSPACE | 9 +- .../patches/@angular+bazel+9.0.0-next.8.patch | 129 +++++++++++++++--- internal/common/devmode_js_sources.bzl | 23 ++-- internal/common/node_module_info.bzl | 74 ---------- internal/common/npm_package_info.bzl | 52 +++++++ internal/common/sources_aspect.bzl | 61 --------- internal/linker/link_node_modules.bzl | 6 +- internal/node.bzl | 2 - internal/node/node.bzl | 25 ++-- internal/node/npm_package_bin.bzl | 14 +- internal/npm_install/generate_build_file.js | 14 +- internal/npm_install/generate_build_file.ts | 14 +- internal/npm_install/node_module_library.bzl | 47 ++++--- internal/npm_install/npm_umd_bundle.bzl | 6 +- .../golden/@angular/core/BUILD.bazel.golden | 2 +- internal/npm_package/npm_package.bzl | 40 +++--- internal/rollup/rollup_bundle.bzl | 23 ++-- packages/jasmine/docs/BUILD.bazel | 1 + packages/karma/docs/BUILD.bazel | 1 + packages/karma/src/karma_web_test.bzl | 88 +++++++----- packages/karma/src/web_test.bzl | 4 +- .../labs/src/protobufjs/ts_proto_library.bzl | 7 +- packages/protractor/docs/BUILD.bazel | 1 + .../protractor/src/protractor_web_test.bzl | 71 ++++++---- packages/rollup/src/rollup_bundle.bzl | 10 +- .../typescript/src/internal/build_defs.bzl | 30 ++-- .../src/internal/devserver/ts_devserver.bzl | 37 +++-- .../devmode_consumer/devmode_consumer.bzl | 21 ++- providers.bzl | 35 ++++- 29 files changed, 480 insertions(+), 367 deletions(-) delete mode 100644 internal/common/node_module_info.bzl create mode 100644 internal/common/npm_package_info.bzl delete mode 100644 internal/common/sources_aspect.bzl diff --git a/WORKSPACE b/WORKSPACE index 20a479ac9d..fa44239f0f 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -67,11 +67,10 @@ yarn_install( name = "npm", # The @npm//:node_modules_filegroup generated by manual_build_file_contents # is used in the //packages/typescript/test/reference_types_directive:tsconfig_types - # test. For now we're still supporting node_modules as a filegroup tho this - # may change in the future. The default generated //:node_modules target is a - # node_module_library rule which provides NodeModuleInfo and NodeModuleSources - # but that rule is not yet in the public API and we have not yet dropped support - # for filegroup based node_modules target. + # test. For now we're still supporting node_modules as a filegroup tho this may + # change in the future. The default generated //:node_modules target is a node_module_library + # rule which provides NpmPackageInfo but that rule is not yet in the public API and we + # have not yet dropped support for filegroup based node_modules target. manual_build_file_contents = """ filegroup( name = "node_modules_filegroup", diff --git a/examples/angular/patches/@angular+bazel+9.0.0-next.8.patch b/examples/angular/patches/@angular+bazel+9.0.0-next.8.patch index 00f3ebdeb2..6e275a72d7 100644 --- a/examples/angular/patches/@angular+bazel+9.0.0-next.8.patch +++ b/examples/angular/patches/@angular+bazel+9.0.0-next.8.patch @@ -1,16 +1,30 @@ -diff --git a/node_modules/@angular/bazel/src/esm5.bzl b/node_modules/@angular/bazel/src/esm5.bzl -index 667f601..7907c12 100755 ---- a/node_modules/@angular/bazel/src/esm5.bzl -+++ b/node_modules/@angular/bazel/src/esm5.bzl -@@ -30,7 +30,7 @@ ESM5Info = provider( +diff --git a/node_modules/@angular/bazel/src/external.bzl b/node_modules/@angular/bazel/src/external.bzl +index 4959f22..43f1c96 100755 +--- a/node_modules/@angular/bazel/src/external.bzl ++++ b/node_modules/@angular/bazel/src/external.bzl +@@ -14,17 +14,17 @@ load( + _ts_providers_dict_to_struct = "ts_providers_dict_to_struct", + ) + load( +- "@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", +- _NodeModuleSources = "NodeModuleSources", +- _collect_node_modules_aspect = "collect_node_modules_aspect", ++ "@build_bazel_rules_nodejs//internal/common:npm_package_info.bzl", ++ _NpmPackageInfo = "NpmPackageInfo", ++ _node_modules_aspect = "node_modules_aspect", + ) + load( + "@npm_bazel_typescript//internal:ts_config.bzl", + _TsConfigInfo = "TsConfigInfo", ) - def _map_closure_path(file): -- result = file.short_path[:-len(".closure.js")] -+ result = file.short_path[:-len(".mjs")] +-NodeModuleSources = _NodeModuleSources +-collect_node_modules_aspect = _collect_node_modules_aspect ++NpmPackageInfo = _NpmPackageInfo ++node_modules_aspect = _node_modules_aspect - # short_path is meant to be used when accessing runfiles in a binary, where - # the CWD is inside the current repo. Therefore files in external repo have a + tsc_wrapped_tsconfig = _tsc_wrapped_tsconfig + COMMON_ATTRIBUTES = _COMMON_ATTRIBUTES diff --git a/node_modules/@angular/bazel/src/modify_tsconfig.js b/node_modules/@angular/bazel/src/modify_tsconfig.js index 9d3c491..3c99746 100755 --- a/node_modules/@angular/bazel/src/modify_tsconfig.js @@ -25,14 +39,23 @@ index 9d3c491..3c99746 100755 fs.writeFileSync(output, JSON.stringify(data)); } diff --git a/node_modules/@angular/bazel/src/ng_module.bzl b/node_modules/@angular/bazel/src/ng_module.bzl -index 9b88fbb..68217d0 100755 +index 9b88fbb..54bf2c7 100755 --- a/node_modules/@angular/bazel/src/ng_module.bzl +++ b/node_modules/@angular/bazel/src/ng_module.bzl -@@ -20,6 +20,7 @@ load( +@@ -13,13 +13,14 @@ load( + "DEFAULT_NG_COMPILER", + "DEFAULT_NG_XI18N", + "DEPS_ASPECTS", +- "NodeModuleSources", ++ "NpmPackageInfo", + "TsConfigInfo", +- "collect_node_modules_aspect", ++ "node_modules_aspect", + "compile_ts", "ts_providers_dict_to_struct", "tsc_wrapped_tsconfig", ) -+load("@build_bazel_rules_nodejs//:providers.bzl", "transitive_js_ecma_script_module_info") ++load("@build_bazel_rules_nodejs//:providers.bzl", "js_ecma_script_module_info", "js_named_module_info") _FLAT_DTS_FILE_SUFFIX = ".bundle.d.ts" _R3_SYMBOLS_DTS_FILE = "src/r3_symbols.d.ts" @@ -54,22 +77,96 @@ index 9b88fbb..68217d0 100755 bundle_index_typings = ctx.actions.declare_file("%s.d.ts" % flat_module_out) declaration_files.append(bundle_index_typings) if is_legacy_ngc: -@@ -603,7 +604,17 @@ def ng_module_impl(ctx, ts_compile_actions): +@@ -517,11 +518,11 @@ def _compile_action(ctx, inputs, outputs, dts_bundles_out, messages_out, tsconfi + file_inputs += ctx.attr.tsconfig[TsConfigInfo].deps + + # Also include files from npm fine grained deps as action_inputs. +- # These deps are identified by the NodeModuleSources provider. ++ # These deps are identified by the NpmPackageInfo provider. + for d in ctx.attr.deps: +- if NodeModuleSources in d: ++ if NpmPackageInfo in d: + # Note: we can't avoid calling .to_list() on sources +- file_inputs.extend(_filter_ts_inputs(d[NodeModuleSources].sources.to_list())) ++ file_inputs.extend(_filter_ts_inputs(d[NpmPackageInfo].sources.to_list())) + + # Collect the inputs and summary files from our deps + action_inputs = depset( +@@ -603,9 +604,23 @@ def ng_module_impl(ctx, ts_compile_actions): return providers def _ng_module_impl(ctx): - return ts_providers_dict_to_struct(ng_module_impl(ctx, compile_ts)) +- +-local_deps_aspects = [collect_node_modules_aspect, _collect_summaries_aspect] + ts_providers = ng_module_impl(ctx, compile_ts) + + # Add in new JS providers + ts_providers["providers"].extend([ -+ transitive_js_ecma_script_module_info( ++ js_named_module_info( ++ sources = ts_providers["typescript"]["es5_sources"], ++ deps = ctx.attr.deps, ++ ), ++ js_ecma_script_module_info( + sources = ts_providers["typescript"]["es6_sources"], + deps = ctx.attr.deps, + ), + ]) + + return ts_providers_dict_to_struct(ts_providers) ++ ++local_deps_aspects = [node_modules_aspect, _collect_summaries_aspect] + + # Workaround skydoc bug which assumes DEPS_ASPECTS is a str type + [local_deps_aspects.append(a) for a in DEPS_ASPECTS] +diff --git a/node_modules/@angular/bazel/src/ng_package/ng_package.bzl b/node_modules/@angular/bazel/src/ng_package/ng_package.bzl +index 48d7619..ea635bb 100755 +--- a/node_modules/@angular/bazel/src/ng_package/ng_package.bzl ++++ b/node_modules/@angular/bazel/src/ng_package/ng_package.bzl +@@ -13,9 +13,8 @@ It packages your library following the Angular Package Format, see the + specification of this format at https://goo.gl/jB3GVv + """ + +-load("@build_bazel_rules_nodejs//internal/common:collect_es6_sources.bzl", "collect_es6_sources") +-load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleSources") +-load("@build_bazel_rules_nodejs//internal/common:sources_aspect.bzl", "sources_aspect") ++load("@build_bazel_rules_nodejs//:providers.bzl", "JSEcmaScriptModuleInfo", "JSNamedModuleInfo") ++load("@build_bazel_rules_nodejs//internal/common:npm_package_info.bzl", "NpmPackageInfo") + load( + "@build_bazel_rules_nodejs//internal/rollup:rollup_bundle.bzl", + "ROLLUP_ATTRS", +@@ -207,7 +206,12 @@ def _filter_js_inputs(all_inputs): + def _ng_package_impl(ctx): + npm_package_directory = ctx.actions.declare_directory("%s.ng_pkg" % ctx.label.name) + +- esm_2015_files = _filter_out_generated_files(collect_es6_sources(ctx), "js") ++ esm_2015_files = [] ++ for dep in ctx.attr.deps: ++ if JSEcmaScriptModuleInfo in dep: ++ esm_2015_files += dep[JSEcmaScriptModuleInfo].sources.to_list() ++ ++ esm_2015_files = _filter_out_generated_files(esm_2015_files, "js") + esm5_sources = _filter_out_generated_files(flatten_esm5(ctx), "js") + + # These accumulators match the directory names where the files live in the +@@ -347,9 +351,9 @@ def _ng_package_impl(ctx): + node_modules_files = _filter_js_inputs(ctx.files.node_modules) + + # Also include files from npm fine grained deps as inputs. +- # These deps are identified by the NodeModuleSources provider. ++ # These deps are identified by the NpmPackageInfo provider. + for d in ctx.attr.deps: +- if NodeModuleSources in d: ++ if NpmPackageInfo in d: + node_modules_files += _filter_js_inputs(d.files) + esm5_rollup_inputs = depset(node_modules_files, transitive = [esm5_sources]) + +@@ -469,7 +473,7 @@ def _ng_package_impl(ctx): + files = depset([package_dir]), + )] - local_deps_aspects = [collect_node_modules_aspect, _collect_summaries_aspect] +-DEPS_ASPECTS = [esm5_outputs_aspect, sources_aspect] ++DEPS_ASPECTS = [esm5_outputs_aspect] + # Workaround skydoc bug which assumes ROLLUP_DEPS_ASPECTS is a str type + [DEPS_ASPECTS.append(a) for a in ROLLUP_DEPS_ASPECTS] diff --git a/internal/common/devmode_js_sources.bzl b/internal/common/devmode_js_sources.bzl index f19d32b7c5..90a9482331 100644 --- a/internal/common/devmode_js_sources.bzl +++ b/internal/common/devmode_js_sources.bzl @@ -17,7 +17,7 @@ Outputs a manifest file with the sources listed. """ -load(":sources_aspect.bzl", "sources_aspect") +load("@build_bazel_rules_nodejs//:providers.bzl", "JSNamedModuleInfo") # Avoid using non-normalized paths (workspace/../other_workspace/path) def _to_manifest_path(ctx, file): @@ -27,26 +27,27 @@ def _to_manifest_path(ctx, file): return ctx.workspace_name + "/" + file.short_path def _devmode_js_sources_impl(ctx): - files = depset() - - for d in ctx.attr.deps: - if hasattr(d, "node_sources"): - files = depset(transitive = [files, d.node_sources]) - elif hasattr(d, "files"): - files = depset(transitive = [files, d.files]) + sources_depsets = [] + for dep in ctx.attr.deps: + if JSNamedModuleInfo in dep: + sources_depsets.append(dep[JSNamedModuleInfo].sources) + if hasattr(dep, "files"): + sources_depsets.append(dep.files) + sources = depset(transitive = sources_depsets) ctx.actions.write(ctx.outputs.manifest, "".join([ _to_manifest_path(ctx, f) + "\n" - for f in files.to_list() + for f in sources.to_list() + if f.path.endswith(".js") or f.path.endswith(".mjs") ])) - return [DefaultInfo(files = files)] + + return [DefaultInfo(files = sources)] devmode_js_sources = rule( implementation = _devmode_js_sources_impl, attrs = { "deps": attr.label_list( allow_files = True, - aspects = [sources_aspect], ), }, outputs = { diff --git a/internal/common/node_module_info.bzl b/internal/common/node_module_info.bzl deleted file mode 100644 index 044daed558..0000000000 --- a/internal/common/node_module_info.bzl +++ /dev/null @@ -1,74 +0,0 @@ -# Copyright 2017 The Bazel Authors. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""NodeModuleInfo & NodeModuleSources providers and apsect to collect node_modules from deps. -""" - -# NodeModuleInfo provider is only provided by targets that are npm dependencies by the -# `node_module_library` rule. This provider is currently used by different rules to filter out -# npm dependencies such as -# ``` -# [d for d in ctx.attr.deps if not NodeModuleInfo in d] -# ``` -# in `packages/typescript/internal/build_defs.bzl` or -# ``` -# hasattr(target, "files") and not NodeModuleInfo in target: -# ``` -# in `internal/common/sources_aspect.bzl`. -# Similar filtering is done in downstream repositories such as angular/angular so this provider -# needs to go through a deprecation period before it can be phased out. -NodeModuleInfo = provider( - doc = "Provides information about npm dependencies installed with yarn_install and npm_install rules", - fields = { - "workspace": "The workspace name that the npm dependencies are provided from", - }, -) - -# NodeModuleSources provider is provided by targets that are npm dependencies by the -# `node_module_library` rule as well as other targets that have direct or transitive deps on -# `node_module_library` targets via the `collect_node_modules_aspect` below. -# TODO: rename to NodeModuleSourcesInfo so name doesn't trigger name-conventions warning -# buildozer: disable=name-conventions -NodeModuleSources = provider( - doc = "Provides sources for npm dependencies installed with yarn_install and npm_install rules", - fields = { - "scripts": "Source files that are javascript named-UMD or named-AMD modules for use in rules such as ts_devserver", - "sources": "Source files that are npm dependencies", - "workspace": "The workspace name that the npm dependencies are provided from", - }, -) - -def _collect_node_modules_aspect_impl(target, ctx): - nm_wksp = None - - if NodeModuleSources in target: - return [] - - if hasattr(ctx.rule.attr, "deps"): - sources = depset() - for dep in ctx.rule.attr.deps: - if NodeModuleSources in dep: - if nm_wksp and dep[NodeModuleSources].workspace != nm_wksp: - fail("All npm dependencies need to come from a single workspace. Found '%s' and '%s'." % (nm_wksp, dep[NodeModuleSources].workspace)) - nm_wksp = dep[NodeModuleSources].workspace - sources = depset(transitive = [dep[NodeModuleSources].sources, sources]) - if sources: - return [NodeModuleSources(sources = sources, workspace = nm_wksp)] - - return [] - -collect_node_modules_aspect = aspect( - implementation = _collect_node_modules_aspect_impl, - attr_aspects = ["deps"], -) diff --git a/internal/common/npm_package_info.bzl b/internal/common/npm_package_info.bzl new file mode 100644 index 0000000000..f1967af5e9 --- /dev/null +++ b/internal/common/npm_package_info.bzl @@ -0,0 +1,52 @@ +# Copyright 2017 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""NpmPackageInfo providers and apsect to collect node_modules from deps. +""" + +# NpmPackageInfo provider is provided by targets that are npm dependencies by the +# `node_module_library` rule as well as other targets that have direct or transitive deps on +# `node_module_library` targets via the `node_modules_aspect` below. +NpmPackageInfo = provider( + doc = "Provides information about npm dependencies", + fields = { + "direct_sources": "Depset of direct source files in this npm package", + "sources": "Depset of direct & transitive source files in this npm package and in its dependencies", + "workspace": "The workspace name that this npm package is provided from", + }, +) + +def _node_modules_aspect_impl(target, ctx): + providers = [] + + # provide NpmPackageInfo if it is not already provided there are NpmPackageInfo deps + if not NpmPackageInfo in target: + sources_depsets = [] + workspace = None + if hasattr(ctx.rule.attr, "deps"): + for dep in ctx.rule.attr.deps: + if NpmPackageInfo in dep: + if workspace and dep[NpmPackageInfo].workspace != workspace: + fail("All npm dependencies need to come from a single workspace. Found '%s' and '%s'." % (workspace, dep[NpmPackageInfo].workspace)) + workspace = dep[NpmPackageInfo].workspace + sources_depsets.append(dep[NpmPackageInfo].sources) + if workspace: + providers.extend([NpmPackageInfo(direct_sources = depset(), sources = depset(transitive = sources_depsets), workspace = workspace)]) + + return providers + +node_modules_aspect = aspect( + _node_modules_aspect_impl, + attr_aspects = ["deps"], +) diff --git a/internal/common/sources_aspect.bzl b/internal/common/sources_aspect.bzl deleted file mode 100644 index 2da1c284ed..0000000000 --- a/internal/common/sources_aspect.bzl +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright 2017 The Bazel Authors. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Aspect to collect es5 js sources and scripts from deps. -""" - -load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleInfo", "NodeModuleSources") - -def _sources_aspect_impl(target, ctx): - # TODO(kyliau): node_sources here is a misnomer because it implies that - # the sources have got something to do with node modules. In fact, - # node_sources collects es5 output from typescript and "javascript-like" - # targets that are *not* node modules. This name is kept as-is to maintain - # compatibility with existing rules but should be renamed and cleaned up. - node_sources = depset() - - # dev_scripts is a collection of "scripts" from "node-module-like" targets - # such as `node_module_library` - dev_scripts = depset() - - # Note layering: until we have JS interop providers, this needs to know how to - # get TypeScript outputs. - if hasattr(target, "typescript"): - node_sources = depset(transitive = [node_sources, target.typescript.es5_sources]) - elif hasattr(target, "files") and not NodeModuleInfo in target: - # Sources from npm fine grained deps should not be included - node_sources = depset( - [f for f in target.files.to_list() if f.path.endswith(".js")], - transitive = [node_sources], - ) - - if NodeModuleSources in target: - dev_scripts = depset(target[NodeModuleSources].scripts) - - if hasattr(ctx.rule.attr, "deps"): - for dep in ctx.rule.attr.deps: - if hasattr(dep, "node_sources"): - node_sources = depset(transitive = [node_sources, dep.node_sources]) - if hasattr(dep, "dev_scripts"): - dev_scripts = depset(transitive = [dev_scripts, dep.dev_scripts]) - - return struct( - node_sources = node_sources, - dev_scripts = dev_scripts, - ) - -sources_aspect = aspect( - _sources_aspect_impl, - attr_aspects = ["deps"], -) diff --git a/internal/linker/link_node_modules.bzl b/internal/linker/link_node_modules.bzl index 710286f98c..1a4d2e9e15 100644 --- a/internal/linker/link_node_modules.bzl +++ b/internal/linker/link_node_modules.bzl @@ -10,7 +10,7 @@ linker, which uses the mappings to link a node_modules directory for runtimes to locate all the first-party packages. """ -load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleSources") +load("@build_bazel_rules_nodejs//internal/common:npm_package_info.bzl", "NpmPackageInfo") def _debug(vars, *args): if "VERBOSE_LOGS" in vars.keys(): @@ -42,8 +42,8 @@ def register_node_modules_linker(ctx, args, inputs): # Look through data/deps attributes to find... for dep in getattr(ctx.attr, "data", []) + getattr(ctx.attr, "deps", []): # ...the root directory for the third-party node_modules; we'll symlink the local "node_modules" to it - if NodeModuleSources in dep: - possible_root = "/".join([dep[NodeModuleSources].workspace, "node_modules"]) + if NpmPackageInfo in dep: + possible_root = "/".join([dep[NpmPackageInfo].workspace, "node_modules"]) if not node_modules_root: node_modules_root = possible_root elif node_modules_root != possible_root: diff --git a/internal/node.bzl b/internal/node.bzl index c8115f6f82..cd80d47fdf 100644 --- a/internal/node.bzl +++ b/internal/node.bzl @@ -23,7 +23,5 @@ load( "//internal/common:expand_into_runfiles.bzl", _expand_location_into_runfiles = "expand_location_into_runfiles", ) -load("//internal/common:sources_aspect.bzl", _sources_aspect = "sources_aspect") -sources_aspect = _sources_aspect expand_location_into_runfiles = _expand_location_into_runfiles diff --git a/internal/node/node.bzl b/internal/node/node.bzl index 3cb0dd3cd7..d79216215d 100644 --- a/internal/node/node.bzl +++ b/internal/node/node.bzl @@ -20,10 +20,10 @@ They support module mapping: any targets in the transitive dependencies with a `module_name` attribute can be `require`d by that name. """ -load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleSources", "collect_node_modules_aspect") +load("@build_bazel_rules_nodejs//:providers.bzl", "JSNamedModuleInfo") +load("@build_bazel_rules_nodejs//internal/common:npm_package_info.bzl", "NpmPackageInfo", "node_modules_aspect") load("//internal/common:expand_into_runfiles.bzl", "expand_location_into_runfiles") load("//internal/common:module_mappings.bzl", "module_mappings_runtime_aspect") -load("//internal/common:sources_aspect.bzl", "sources_aspect") load("//internal/common:windows_utils.bzl", "create_windows_native_launcher_script", "is_windows") def _trim_package_node_modules(package_name): @@ -48,8 +48,8 @@ def _compute_node_modules_root(ctx): """ node_modules_root = None if ctx.attr.node_modules: - if NodeModuleSources in ctx.attr.node_modules: - node_modules_root = "/".join([ctx.attr.node_modules[NodeModuleSources].workspace, "node_modules"]) + if NpmPackageInfo in ctx.attr.node_modules: + node_modules_root = "/".join([ctx.attr.node_modules[NpmPackageInfo].workspace, "node_modules"]) elif ctx.files.node_modules: # ctx.files.node_modules is not an empty list workspace = ctx.attr.node_modules.label.workspace_root.split("/")[1] if ctx.attr.node_modules.label.workspace_root else ctx.workspace_name @@ -59,8 +59,8 @@ def _compute_node_modules_root(ctx): "node_modules", ] if f]) for d in ctx.attr.data: - if NodeModuleSources in d: - possible_root = "/".join([d[NodeModuleSources].workspace, "node_modules"]) + if NpmPackageInfo in d: + possible_root = "/".join([d[NpmPackageInfo].workspace, "node_modules"]) if not node_modules_root: node_modules_root = possible_root elif node_modules_root != possible_root: @@ -130,10 +130,10 @@ def _nodejs_binary_impl(ctx): node_modules = depset(ctx.files.node_modules) # Also include files from npm fine grained deps as inputs. - # These deps are identified by the NodeModuleSources provider. + # These deps are identified by the NpmPackageInfo provider. for d in ctx.attr.data: - if NodeModuleSources in d: - node_modules = depset(transitive = [node_modules, d[NodeModuleSources].sources]) + if NpmPackageInfo in d: + node_modules = depset(transitive = [node_modules, d[NpmPackageInfo].sources]) # Using a depset will allow us to avoid flattening files and sources # inside this loop. This should reduce the performances hits, @@ -141,8 +141,9 @@ def _nodejs_binary_impl(ctx): sources = depset() for d in ctx.attr.data: - if hasattr(d, "node_sources"): - sources = depset(transitive = [sources, d.node_sources]) + # TODO: switch to JSModuleInfo when it is available + if JSNamedModuleInfo in d: + sources = depset(transitive = [sources, d[JSNamedModuleInfo].sources]) if hasattr(d, "files"): sources = depset(transitive = [sources, d.files]) @@ -262,7 +263,7 @@ _NODEJS_EXECUTABLE_ATTRS = { "data": attr.label_list( doc = """Runtime dependencies which may be loaded during execution.""", allow_files = True, - aspects = [sources_aspect, module_mappings_runtime_aspect, collect_node_modules_aspect], + aspects = [node_modules_aspect, module_mappings_runtime_aspect], ), "default_env_vars": attr.string_list( doc = """Default environment variables that are added to `configuration_env_vars`. diff --git a/internal/node/npm_package_bin.bzl b/internal/node/npm_package_bin.bzl index 35ec9069a2..bb9e5b5abc 100644 --- a/internal/node/npm_package_bin.bzl +++ b/internal/node/npm_package_bin.bzl @@ -1,5 +1,6 @@ "A generic rule to run a tool that appears in node_modules/.bin" +load("@build_bazel_rules_nodejs//internal/common:npm_package_info.bzl", "NpmPackageInfo", "node_modules_aspect") load("@build_bazel_rules_nodejs//internal/linker:link_node_modules.bzl", "module_mappings_aspect", "register_node_modules_linker") # Note: this API is chosen to match nodejs_binary @@ -7,7 +8,7 @@ load("@build_bazel_rules_nodejs//internal/linker:link_node_modules.bzl", "module _ATTRS = { "outs": attr.output_list(), "args": attr.string_list(mandatory = True), - "data": attr.label_list(allow_files = True, aspects = [module_mappings_aspect]), + "data": attr.label_list(allow_files = True, aspects = [module_mappings_aspect, node_modules_aspect]), "output_dir": attr.bool(), "tool": attr.label( executable = True, @@ -29,6 +30,15 @@ def _expand_location(ctx, s): s = s.replace("$@", "/".join([o for o in outdir_segments if o])) return ctx.expand_location(s, targets = ctx.attr.data) +def _inputs(ctx): + # Also include files from npm fine grained deps as inputs. + # These deps are identified by the NpmPackageInfo provider. + inputs_depsets = [] + for d in ctx.attr.data: + if NpmPackageInfo in d: + inputs_depsets.append(d[NpmPackageInfo].sources) + return depset(ctx.files.data, transitive = inputs_depsets).to_list() + def _impl(ctx): if ctx.attr.output_dir and ctx.attr.outs: fail("Only one of output_dir and outs may be specified") @@ -36,7 +46,7 @@ def _impl(ctx): fail("One of output_dir and outs must be specified") args = ctx.actions.args() - inputs = ctx.files.data[:] + inputs = _inputs(ctx) outputs = [] if ctx.attr.output_dir: outputs = [ctx.actions.declare_directory(ctx.attr.name)] diff --git a/internal/npm_install/generate_build_file.js b/internal/npm_install/generate_build_file.js index a1b7a1fb11..ea809946ff 100644 --- a/internal/npm_install/generate_build_file.js +++ b/internal/npm_install/generate_build_file.js @@ -798,14 +798,14 @@ def _maybe(repo_rule, name, **kwargs): const dtsSources = filterFiles(pkg._files, ['.d.ts']); // TODO(gmagolan): add UMD & AMD scripts to scripts even if not an APF package _but_ only if they // are named? - const scripts = getNgApfScripts(pkg); + const namedSources = getNgApfScripts(pkg); const deps = [pkg].concat(pkg._dependencies.filter(dep => dep !== pkg && !dep._isNested)); - let scriptStarlark = ''; - if (scripts.length) { - scriptStarlark = ` + let namedSourcesStarlark = ''; + if (namedSources.length) { + namedSourcesStarlark = ` # subset of srcs that are javascript named-UMD or named-AMD scripts - scripts = [ - ${scripts.map((f) => `"//:node_modules/${pkg._dir}/${f}",`).join('\n ')} + named_module_srcs = [ + ${namedSources.map((f) => `"//:node_modules/${pkg._dir}/${f}",`).join('\n ')} ],`; } let srcsStarlark = ''; @@ -852,7 +852,7 @@ node_module_library( # circular dependencies errors node_module_library( name = "${pkg._name}__contents", - srcs = [":${pkg._name}__files"],${scriptStarlark} + srcs = [":${pkg._name}__files"],${namedSourcesStarlark} ) # ${pkg._name}__typings is the subset of ${pkg._name}__contents that are declarations diff --git a/internal/npm_install/generate_build_file.ts b/internal/npm_install/generate_build_file.ts index 96fa4d3023..dd3666c1cd 100644 --- a/internal/npm_install/generate_build_file.ts +++ b/internal/npm_install/generate_build_file.ts @@ -888,15 +888,15 @@ function printPackage(pkg: Dep) { const dtsSources = filterFiles(pkg._files, ['.d.ts']); // TODO(gmagolan): add UMD & AMD scripts to scripts even if not an APF package _but_ only if they // are named? - const scripts = getNgApfScripts(pkg); + const namedSources = getNgApfScripts(pkg); const deps = [pkg].concat(pkg._dependencies.filter(dep => dep !== pkg && !dep._isNested)); - let scriptStarlark = ''; - if (scripts.length) { - scriptStarlark = ` + let namedSourcesStarlark = ''; + if (namedSources.length) { + namedSourcesStarlark = ` # subset of srcs that are javascript named-UMD or named-AMD scripts - scripts = [ - ${scripts.map((f: string) => `"//:node_modules/${pkg._dir}/${f}",`).join('\n ')} + named_module_srcs = [ + ${namedSources.map((f: string) => `"//:node_modules/${pkg._dir}/${f}",`).join('\n ')} ],`; } @@ -948,7 +948,7 @@ node_module_library( # circular dependencies errors node_module_library( name = "${pkg._name}__contents", - srcs = [":${pkg._name}__files"],${scriptStarlark} + srcs = [":${pkg._name}__files"],${namedSourcesStarlark} ) # ${pkg._name}__typings is the subset of ${pkg._name}__contents that are declarations diff --git a/internal/npm_install/node_module_library.bzl b/internal/npm_install/node_module_library.bzl index 913fc73f29..007b5871fe 100644 --- a/internal/npm_install/node_module_library.bzl +++ b/internal/npm_install/node_module_library.bzl @@ -15,21 +15,16 @@ """Contains the node_module_library which is used by yarn_install & npm_install. """ -load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleInfo", "NodeModuleSources") +load("@build_bazel_rules_nodejs//:declaration_provider.bzl", "DeclarationInfo") +load("@build_bazel_rules_nodejs//:providers.bzl", "js_named_module_info") +load("@build_bazel_rules_nodejs//internal/common:npm_package_info.bzl", "NpmPackageInfo") def _node_module_library_impl(ctx): workspace = ctx.label.workspace_root.split("/")[1] if ctx.label.workspace_root else ctx.workspace_name - # All files in `srcs` and in `deps` - # TODO(gregmagolan): transitive sources should be collected an aspect to go - # into a NodeModuleSources.transitive_sources - sources = depset(ctx.files.srcs, transitive = [dep.files for dep in ctx.attr.deps]) + direct_sources = depset(ctx.files.srcs) + sources_depsets = [direct_sources] - # scripts are a subset of sources that are javascript named-UMD or named-AMD scripts for - # use in rules such as ts_devserver - scripts = depset(ctx.files.scripts) - - # declarations are a subset of sources that are declaration files declarations = depset([ f for f in ctx.files.srcs @@ -41,12 +36,15 @@ def _node_module_library_impl(ctx): len(f.path.split("/node_modules/")) < 3 and f.path.find("/node_modules/typescript/lib/lib.") == -1 ]) - # transitive_declarations are all .d.ts files in srcs plus those in direct & transitive dependencies - transitive_declarations = depset(transitive = [declarations]) + transitive_declarations_depsets = [declarations] for dep in ctx.attr.deps: - if hasattr(dep, "typescript"): - transitive_declarations = depset(transitive = [transitive_declarations, dep.typescript.transitive_declarations]) + if DeclarationInfo in dep: + transitive_declarations_depsets.append(dep[DeclarationInfo].transitive_declarations) + if NpmPackageInfo in dep: + sources_depsets.append(dep[NpmPackageInfo].sources) + + transitive_declarations = depset(transitive = transitive_declarations_depsets) return struct( typescript = struct( @@ -63,15 +61,20 @@ def _node_module_library_impl(ctx): ), providers = [ DefaultInfo( - files = sources, + files = direct_sources, ), - NodeModuleInfo( + NpmPackageInfo( + direct_sources = direct_sources, + sources = depset(transitive = sources_depsets), workspace = workspace, ), - NodeModuleSources( - sources = sources, - scripts = scripts, - workspace = workspace, + DeclarationInfo( + declarations = declarations, + transitive_declarations = transitive_declarations, + ), + js_named_module_info( + sources = depset(ctx.files.named_module_srcs), + deps = ctx.attr.deps, ), ], ) @@ -83,8 +86,8 @@ node_module_library = rule( doc = "The list of files that comprise the package", allow_files = True, ), - "scripts": attr.label_list( - doc = "A subset of srcs that are javascript named-UMD or named-AMD scripts for use in rules such as ts_devserver", + "named_module_srcs": attr.label_list( + doc = "A subset of srcs that are javascript named-UMD or named-AMD for use in rules such as ts_devserver", allow_files = True, ), "deps": attr.label_list( diff --git a/internal/npm_install/npm_umd_bundle.bzl b/internal/npm_install/npm_umd_bundle.bzl index a62c7129bb..ae15339a0b 100644 --- a/internal/npm_install/npm_umd_bundle.bzl +++ b/internal/npm_install/npm_umd_bundle.bzl @@ -17,7 +17,7 @@ For use by yarn_install and npm_install. Not meant to be part of the public API. """ -load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleSources", "collect_node_modules_aspect") +load("@build_bazel_rules_nodejs//internal/common:npm_package_info.bzl", "NpmPackageInfo", "node_modules_aspect") def _npm_umd_bundle(ctx): if len(ctx.attr.entry_point.files.to_list()) != 1: @@ -33,7 +33,7 @@ def _npm_umd_bundle(ctx): args.add(output.path) args.add_joined(ctx.attr.excluded, join_with = ",") - sources = ctx.attr.package[NodeModuleSources].sources.to_list() + sources = ctx.attr.package[NpmPackageInfo].sources.to_list() # Only pass .js and package.json files as inputs to browserify. # The latter is required for module resolution in some cases. @@ -91,7 +91,7 @@ This target would be then be used instead of the generated `@npm//typeorm:typeor "package": attr.label( doc = """The npm package target""", mandatory = True, - aspects = [collect_node_modules_aspect], + aspects = [node_modules_aspect], ), "_browserify_wrapped": attr.label( executable = True, diff --git a/internal/npm_install/test/golden/@angular/core/BUILD.bazel.golden b/internal/npm_install/test/golden/@angular/core/BUILD.bazel.golden index 336aa504e7..06b3a74433 100644 --- a/internal/npm_install/test/golden/@angular/core/BUILD.bazel.golden +++ b/internal/npm_install/test/golden/@angular/core/BUILD.bazel.golden @@ -677,7 +677,7 @@ node_module_library( node_module_library( name = "core__contents", srcs = [":core__files"], - scripts = [ + named_module_srcs = [ "//:node_modules/@angular/core/bundles/core-testing.umd.js", "//:node_modules/@angular/core/bundles/core.umd.js", ], diff --git a/internal/npm_package/npm_package.bzl b/internal/npm_package/npm_package.bzl index 0cbf203781..8e512dcf87 100644 --- a/internal/npm_package/npm_package.bzl +++ b/internal/npm_package/npm_package.bzl @@ -6,7 +6,8 @@ If all users of your library code use Bazel, they should just add your library to the `deps` of one of their targets. """ -load("//internal/common:sources_aspect.bzl", "sources_aspect") +load("@build_bazel_rules_nodejs//:declaration_provider.bzl", "DeclarationInfo") +load("@build_bazel_rules_nodejs//:providers.bzl", "JSNamedModuleInfo") # Takes a depset of files and returns a corresponding list of file paths without any files # that aren't part of the specified package path. Also include files from external repositories @@ -95,30 +96,28 @@ def create_package(ctx, deps_sources, nested_packages): return package_dir def _npm_package(ctx): - deps_sources = depset() + sources_depsets = [] + for dep in ctx.attr.deps: - transitive = [ - deps_sources, - # Collect whatever is in the "data" - dep.data_runfiles.files, - ] - - if hasattr(dep, "node_sources"): - # For JavaScript-producing rules, gather up the devmode Node.js sources - transitive.append(dep.node_sources) - else: - # For standalone Output File Targets (aspects not invoked on these) - transitive.append(dep.files) + # Collect whatever is in the "data" + sources_depsets.append(dep.data_runfiles.files) + + # Only collect DefaultInfo files (not transitive) + sources_depsets.append(dep.files) + + # All direct & transitive JavaScript-producing deps + # TODO: switch to JSModuleInfo when it is available + if JSNamedModuleInfo in dep: + sources_depsets.append(dep[JSNamedModuleInfo].sources) - # ts_library doesn't include .d.ts outputs in the runfiles - # see comment in rules_typescript/internal/common/compilation.bzl - if hasattr(dep, "typescript"): - transitive.append(dep.typescript.transitive_declarations) + # Include all transitive declerations + if DeclarationInfo in dep: + sources_depsets.append(dep[DeclarationInfo].transitive_declarations) - deps_sources = depset(transitive = transitive) + sources = depset(transitive = sources_depsets) # Note: to_list() should be called once per rule! - package_dir = create_package(ctx, deps_sources.to_list(), ctx.files.packages) + package_dir = create_package(ctx, sources.to_list(), ctx.files.packages) return [DefaultInfo( files = depset([package_dir]), @@ -154,7 +153,6 @@ NPM_PACKAGE_ATTRS = { ), "deps": attr.label_list( doc = """Other targets which produce files that should be included in the package, such as `rollup_bundle`""", - aspects = [sources_aspect], allow_files = True, ), "_packager": attr.label( diff --git a/internal/rollup/rollup_bundle.bzl b/internal/rollup/rollup_bundle.bzl index bbffa23185..d975783b76 100644 --- a/internal/rollup/rollup_bundle.bzl +++ b/internal/rollup/rollup_bundle.bzl @@ -18,7 +18,7 @@ The versions of Rollup and terser are controlled by the Bazel toolchain. You do not need to install them into your project. """ -load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleSources", "collect_node_modules_aspect") +load("@build_bazel_rules_nodejs//internal/common:npm_package_info.bzl", "NpmPackageInfo", "node_modules_aspect") load("//internal/common:collect_es6_sources.bzl", _collect_es2015_sources = "collect_es6_sources") load("//internal/common:module_mappings.bzl", "get_module_mappings") @@ -64,8 +64,8 @@ def _compute_node_modules_root(ctx): """ node_modules_root = None if ctx.attr.node_modules: - if NodeModuleSources in ctx.attr.node_modules: - node_modules_root = "/".join(["external", ctx.attr.node_modules[NodeModuleSources].workspace, "node_modules"]) + if NpmPackageInfo in ctx.attr.node_modules: + node_modules_root = "/".join(["external", ctx.attr.node_modules[NpmPackageInfo].workspace, "node_modules"]) elif ctx.files.node_modules: # ctx.files.node_modules is not an empty list node_modules_root = "/".join([f for f in [ @@ -74,8 +74,8 @@ def _compute_node_modules_root(ctx): "node_modules", ] if f]) for d in ctx.attr.deps: - if NodeModuleSources in d: - possible_root = "/".join(["external", d[NodeModuleSources].workspace, "node_modules"]) + if NpmPackageInfo in d: + possible_root = "/".join(["external", d[NpmPackageInfo].workspace, "node_modules"]) if not node_modules_root: node_modules_root = possible_root elif node_modules_root != possible_root: @@ -210,14 +210,15 @@ def _run_rollup(ctx, sources, config, output, map_output = None): args.add_joined(["%s:%s" % g for g in ctx.attr.globals.items()], join_with = ",") direct_inputs = [config] - direct_inputs += _filter_js_inputs(ctx.files.node_modules) + if hasattr(ctx.attr, "node_modules"): + direct_inputs += _filter_js_inputs(ctx.files.node_modules) # Also include files from npm fine grained deps as inputs. - # These deps are identified by the NodeModuleSources provider. + # These deps are identified by the NpmPackageInfo provider. for d in ctx.attr.deps: - if NodeModuleSources in d: + if NpmPackageInfo in d: # Note: we can't avoid calling .to_list() on sources - direct_inputs += _filter_js_inputs(d[NodeModuleSources].sources.to_list()) + direct_inputs += _filter_js_inputs(d[NpmPackageInfo].sources.to_list()) if ctx.file.license_banner: direct_inputs += [ctx.file.license_banner] @@ -567,9 +568,9 @@ def _rollup_bundle(ctx): # Expose our list of aspects so derivative rules can override the deps attribute and # add their own additional aspects. # If users are in a different repo and load the aspect themselves, they will create -# different Provider symbols (e.g. NodeModuleInfo) and we won't find them. +# different Provider symbols (e.g. NpmPackageInfo) and we won't find them. # So users must use these symbols that are load'ed in rules_nodejs. -ROLLUP_DEPS_ASPECTS = [rollup_module_mappings_aspect, collect_node_modules_aspect] +ROLLUP_DEPS_ASPECTS = [rollup_module_mappings_aspect, node_modules_aspect] ROLLUP_ATTRS = { "srcs": attr.label_list( diff --git a/packages/jasmine/docs/BUILD.bazel b/packages/jasmine/docs/BUILD.bazel index 556c0544f7..0dd1a0fd2e 100644 --- a/packages/jasmine/docs/BUILD.bazel +++ b/packages/jasmine/docs/BUILD.bazel @@ -34,6 +34,7 @@ stardoc( # ``` "//internal/common:bzl", "//internal/node:bzl", + "//:bzl", ], ) diff --git a/packages/karma/docs/BUILD.bazel b/packages/karma/docs/BUILD.bazel index 6cbcd6523f..1b6b13964f 100644 --- a/packages/karma/docs/BUILD.bazel +++ b/packages/karma/docs/BUILD.bazel @@ -35,6 +35,7 @@ stardoc( # ``` "//internal/common:bzl", "//internal/js_library:bzl", + "//:bzl", ], ) diff --git a/packages/karma/src/karma_web_test.bzl b/packages/karma/src/karma_web_test.bzl index c7f2c8c385..2e9a760290 100644 --- a/packages/karma/src/karma_web_test.bzl +++ b/packages/karma/src/karma_web_test.bzl @@ -13,7 +13,8 @@ # limitations under the License. "Unit testing with Karma" -load("@build_bazel_rules_nodejs//internal/common:sources_aspect.bzl", "sources_aspect") +load("@build_bazel_rules_nodejs//:providers.bzl", "JSNamedModuleInfo") +load("@build_bazel_rules_nodejs//internal/common:npm_package_info.bzl", "NpmPackageInfo", "node_modules_aspect") load("@build_bazel_rules_nodejs//internal/js_library:js_library.bzl", "write_amd_names_shim") load("@io_bazel_rules_webtesting//web:web.bzl", "web_test_suite") load("@io_bazel_rules_webtesting//web/internal:constants.bzl", "DEFAULT_WRAPPED_TEST_TAGS") @@ -50,7 +51,7 @@ KARMA_GENERIC_WEB_TEST_ATTRS = dict(COMMON_WEB_TEST_ATTRS, **{ These should be a list of targets which produce JavaScript such as `ts_library`. The files will be loaded in the same order they are declared by that rule.""", allow_files = True, - aspects = [sources_aspect], + aspects = [node_modules_aspect], ), "_conf_tmpl": attr.label( default = Label(_CONF_TMPL), @@ -65,7 +66,6 @@ KARMA_WEB_TEST_ATTRS = dict(KARMA_GENERIC_WEB_TEST_ATTRS, **{ certain attributes of this configuration file. Attributes that are overridden will be outputted to the test log.""", allow_single_file = True, - aspects = [sources_aspect], ), }) @@ -85,6 +85,9 @@ def _write_amd_names_shim(ctx): write_amd_names_shim(ctx.actions, amd_names_shim, ctx.attr.bootstrap) return amd_names_shim +def _filter_js(files): + return [f for f in files if f.extension == "js" or f.extension == "mjs"] + # Generates the karma configuration file for the rule def _write_karma_config(ctx, files, amd_names_shim): configuration = ctx.actions.declare_file( @@ -92,11 +95,15 @@ def _write_karma_config(ctx, files, amd_names_shim): sibling = ctx.outputs.executable, ) - config_file = "" - if hasattr(ctx.file, "config_file"): - config_file = ctx.file.config_file - if hasattr(ctx.attr.config_file, "typescript"): - config_file = ctx.attr.config_file.typescript.es5_sources.to_list()[0] + config_file = None + + # Check for config_file since ts_web_test does not have this attribute + if hasattr(ctx.attr, "config_file") and ctx.attr.config_file: + # TODO: switch to JSModuleInfo when it is available + if JSNamedModuleInfo in ctx.attr.config_file: + config_file = _filter_js(ctx.attr.config_file[JSNamedModuleInfo].direct_sources.to_list())[0] + else: + config_file = ctx.file.config_file # The files in the bootstrap attribute come before the require.js support. # Note that due to frameworks = ['jasmine'], a few scripts will come before @@ -129,19 +136,23 @@ def _write_karma_config(ctx, files, amd_names_shim): # Next we load the "runtime_deps" which we expect to contain named AMD modules # Thus they should come after the require.js script, but before any srcs or deps runtime_files = [] - for d in ctx.attr.runtime_deps: - if not hasattr(d, "typescript"): - # Workaround https://github.com/bazelbuild/rules_nodejs/issues/57 - # We should allow any JS source as long as it yields something that - # can be loaded by require.js - fail("labels in runtime_deps must be created by ts_library") - for src in d.typescript.es5_sources.to_list(): - runtime_files.append(_to_manifest_path(ctx, src)) + for dep in ctx.attr.runtime_deps: + if JSNamedModuleInfo in dep: + for src in dep[JSNamedModuleInfo].direct_sources.to_list(): + runtime_files.append(_to_manifest_path(ctx, src)) + if not JSNamedModuleInfo in dep and not NpmPackageInfo in dep and hasattr(dep, "files"): + # These are javascript files provided by DefaultInfo from a direct + # dep that has no JSNamedModuleInfo provider or NpmPackageInfo + # provider (not an npm dep). These files must be in named AMD or named + # UMD format. + for src in dep.files.to_list(): + runtime_files.append(_to_manifest_path(ctx, src)) # Finally we load the user's srcs and deps user_entries = [ _to_manifest_path(ctx, f) for f in files.to_list() + if f.path.endswith(".js") ] # Expand static_files paths to runfiles for config @@ -187,19 +198,25 @@ def run_karma_web_test(ctx): Returns: The runfiles for the generated action. """ - files = depset(ctx.files.srcs) - for d in ctx.attr.deps + ctx.attr.runtime_deps: - has_node_sources = hasattr(d, "node_sources") - has_dev_scripts = hasattr(d, "dev_scripts") - if has_node_sources: - files = depset(transitive = [files, d.node_sources]) - if has_dev_scripts: - files = depset(transitive = [files, d.dev_scripts]) - if not has_node_sources and not has_dev_scripts and hasattr(d, "files"): - # These are Javascript files directly specified in "deps". - # They are not collected by `sources_aspect` due to the absence of - # `deps` attr. These files must be in named AMD format. - files = depset(transitive = [files, d.files]) + files_depsets = [depset(ctx.files.srcs)] + for dep in ctx.attr.deps + ctx.attr.runtime_deps: + if JSNamedModuleInfo in dep: + files_depsets.append(dep[JSNamedModuleInfo].sources) + if not JSNamedModuleInfo in dep and not NpmPackageInfo in dep and hasattr(dep, "files"): + # These are javascript files provided by DefaultInfo from a direct + # dep that has no JSNamedModuleInfo provider or NpmPackageInfo + # provider (not an npm dep). These files must be in named AMD or named + # UMD format. + files_depsets.append(dep.files) + files = depset(transitive = files_depsets) + + # Also include files from npm fine grained deps as inputs. + # These deps are identified by the NpmPackageInfo provider. + node_modules_depsets = [] + for dep in ctx.attr.deps + ctx.attr.runtime_deps: + if NpmPackageInfo in dep: + node_modules_depsets.append(dep[NpmPackageInfo].sources) + node_modules = depset(transitive = node_modules_depsets) amd_names_shim = _write_amd_names_shim(ctx) @@ -250,11 +267,14 @@ $KARMA ${{ARGV[@]}} ) config_sources = [] - if hasattr(ctx.file, "config_file"): - if ctx.file.config_file: + + # Check for config_file since ts_web_test does not have this attribute + if hasattr(ctx.attr, "config_file") and ctx.attr.config_file: + # TODO: switch to JSModuleInfo when it is available + if JSNamedModuleInfo in ctx.attr.config_file: + config_sources = ctx.attr.config_file[JSNamedModuleInfo].sources.to_list() + else: config_sources = [ctx.file.config_file] - if hasattr(ctx.attr.config_file, "node_sources"): - config_sources = ctx.attr.config_file.node_sources.to_list() runfiles = [ configuration, @@ -270,7 +290,7 @@ $KARMA ${{ARGV[@]}} return ctx.runfiles( files = runfiles, - transitive_files = files, + transitive_files = depset(transitive = [files, node_modules]), ).merge(ctx.attr.karma[DefaultInfo].data_runfiles) def _karma_web_test_impl(ctx): diff --git a/packages/karma/src/web_test.bzl b/packages/karma/src/web_test.bzl index 7ebb58b259..a1c4c59c90 100644 --- a/packages/karma/src/web_test.bzl +++ b/packages/karma/src/web_test.bzl @@ -13,7 +13,7 @@ # limitations under the License. "Common web_test attributes" -load("@build_bazel_rules_nodejs//internal/common:sources_aspect.bzl", "sources_aspect") +load("@build_bazel_rules_nodejs//internal/common:npm_package_info.bzl", "node_modules_aspect") # Attributes shared by any web_test rule (ts_web_test, karma_web_test, protractor_web_test) COMMON_WEB_TEST_ATTRS = { @@ -35,6 +35,6 @@ COMMON_WEB_TEST_ATTRS = { "deps": attr.label_list( doc = "Other targets which produce JavaScript such as `ts_library`", allow_files = True, - aspects = [sources_aspect], + aspects = [node_modules_aspect], ), } diff --git a/packages/labs/src/protobufjs/ts_proto_library.bzl b/packages/labs/src/protobufjs/ts_proto_library.bzl index dc699945da..06b4598648 100644 --- a/packages/labs/src/protobufjs/ts_proto_library.bzl +++ b/packages/labs/src/protobufjs/ts_proto_library.bzl @@ -14,7 +14,7 @@ "Protocol Buffers" load("@build_bazel_rules_nodejs//:declaration_provider.bzl", "DeclarationInfo") -load("@build_bazel_rules_nodejs//:providers.bzl", "JSEcmaScriptModuleInfo") +load("@build_bazel_rules_nodejs//:providers.bzl", "JSEcmaScriptModuleInfo", "JSNamedModuleInfo") def _run_pbjs(actions, executable, output_name, proto_files, suffix = ".js", wrap = "amd", amd_name = ""): js_file = actions.declare_file(output_name + suffix) @@ -118,7 +118,12 @@ def _ts_proto_library(ctx): declarations = declarations, transitive_declarations = declarations, ), + JSNamedModuleInfo( + direct_sources = es5_sources, + sources = es5_sources, + ), JSEcmaScriptModuleInfo( + direct_sources = es6_sources, sources = es6_sources, ), ], diff --git a/packages/protractor/docs/BUILD.bazel b/packages/protractor/docs/BUILD.bazel index 3d1521037a..f4fba32997 100644 --- a/packages/protractor/docs/BUILD.bazel +++ b/packages/protractor/docs/BUILD.bazel @@ -31,6 +31,7 @@ stardoc( # `@build_bazel_rules_nodejs//foo:bzl` style deps are not found # by the doc generator: # ``` + # Exception in thread "main" java.lang.IllegalStateException: File external/npm_bazel_jasmine/jasmine_node_test.bzl imported '@build_bazel_rules_nodejs//internal/common:devmode_js_sources.bzl', yet internal/common/devmode_js_sources.bzl was not found, even at roots [.]. # ``` "//:bzl", "//internal/common:bzl", diff --git a/packages/protractor/src/protractor_web_test.bzl b/packages/protractor/src/protractor_web_test.bzl index 69dfa02b98..75d44bdec8 100644 --- a/packages/protractor/src/protractor_web_test.bzl +++ b/packages/protractor/src/protractor_web_test.bzl @@ -14,7 +14,8 @@ "Run end-to-end tests with Protractor" load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary") -load("@build_bazel_rules_nodejs//internal/common:sources_aspect.bzl", "sources_aspect") +load("@build_bazel_rules_nodejs//:providers.bzl", "JSNamedModuleInfo") +load("@build_bazel_rules_nodejs//internal/common:npm_package_info.bzl", "NpmPackageInfo", "node_modules_aspect") load("@build_bazel_rules_nodejs//internal/common:windows_utils.bzl", "create_windows_native_launcher_script", "is_windows") load("@io_bazel_rules_webtesting//web:web.bzl", "web_test_suite") load("@io_bazel_rules_webtesting//web/internal:constants.bzl", "DEFAULT_WRAPPED_TEST_TAGS") @@ -30,18 +31,34 @@ def _to_manifest_path(ctx, file): else: return ctx.workspace_name + "/" + file.short_path +def _filter_js(files): + return [f for f in files if f.extension == "js" or f.extension == "mjs"] + def _protractor_web_test_impl(ctx): configuration = ctx.actions.declare_file( "%s.conf.js" % ctx.label.name, sibling = ctx.outputs.script, ) - files = depset(ctx.files.srcs) - for d in ctx.attr.deps: - if hasattr(d, "node_sources"): - files = depset(transitive = [files, d.node_sources]) - elif hasattr(d, "files"): - files = depset(transitive = [files, d.files]) + files_depsets = [depset(ctx.files.srcs)] + for dep in ctx.attr.deps: + if JSNamedModuleInfo in dep: + files_depsets.append(dep[JSNamedModuleInfo].sources) + if not JSNamedModuleInfo in dep and not NpmPackageInfo in dep and hasattr(dep, "files"): + # These are javascript files provided by DefaultInfo from a direct + # dep that has no JSNamedModuleInfo provider or NpmPackageInfo + # provider (not an npm dep). These files must be in named AMD or named + # UMD format. + files_depsets.append(dep.files) + files = depset(transitive = files_depsets) + + # Also include files from npm fine grained deps as inputs. + # These deps are identified by the NpmPackageInfo provider. + node_modules_depsets = [] + for dep in ctx.attr.deps: + if NpmPackageInfo in dep: + node_modules_depsets.append(dep[NpmPackageInfo].sources) + node_modules = depset(transitive = node_modules_depsets) specs = [ _to_manifest_path(ctx, f) @@ -49,24 +66,26 @@ def _protractor_web_test_impl(ctx): ] configuration_sources = [] - if ctx.file.configuration: - configuration_sources = [ctx.file.configuration] - if hasattr(ctx.attr.configuration, "node_sources"): - configuration_sources = ctx.attr.configuration.node_sources.to_list() - - configuration_file = ctx.file.configuration - if hasattr(ctx.attr.configuration, "typescript"): - configuration_file = ctx.attr.configuration.typescript.es5_sources.to_list()[0] + configuration_file = None + if ctx.attr.configuration: + # TODO: switch to JSModuleInfo when it is available + if JSNamedModuleInfo in ctx.attr.configuration: + configuration_sources = ctx.attr.configuration[JSNamedModuleInfo].sources.to_list() + configuration_file = _filter_js(ctx.attr.configuration[JSNamedModuleInfo].direct_sources.to_list())[0] + else: + configuration_sources = [ctx.file.configuration] + configuration_file = ctx.file.configuration on_prepare_sources = [] - if ctx.file.on_prepare: - on_prepare_sources = [ctx.file.on_prepare] - if hasattr(ctx.attr.on_prepare, "node_sources"): - on_prepare_sources = ctx.attr.on_prepare.node_sources.to_list() - - on_prepare_file = ctx.file.on_prepare - if hasattr(ctx.attr.on_prepare, "typescript"): - on_prepare_file = ctx.attr.on_prepare.typescript.es5_sources.to_list()[0] + on_prepare_file = None + if ctx.attr.on_prepare: + # TODO: switch to JSModuleInfo when it is available + if JSNamedModuleInfo in ctx.attr.on_prepare: + on_prepare_sources = ctx.attr.on_prepare[JSNamedModuleInfo].sources.to_list() + on_prepare_file = _filter_js(ctx.attr.on_prepare[JSNamedModuleInfo].direct_sources.to_list())[0] + else: + on_prepare_sources = [ctx.file.on_prepare] + on_prepare_file = ctx.file.on_prepare ctx.actions.expand_template( output = configuration, @@ -127,7 +146,7 @@ $PROTRACTOR $CONF files = depset([ctx.outputs.script]), runfiles = ctx.runfiles( files = runfiles, - transitive_files = files, + transitive_files = depset(transitive = [files, node_modules]), # Propagate protractor_bin and its runfiles collect_data = True, collect_default = True, @@ -149,7 +168,6 @@ _protractor_web_test = rule( "configuration": attr.label( doc = "Protractor configuration file", allow_single_file = True, - aspects = [sources_aspect], ), "data": attr.label_list( doc = "Runtime dependencies", @@ -159,7 +177,6 @@ _protractor_web_test = rule( If the script exports a function which returns a promise, protractor will wait for the promise to resolve before beginning tests.""", allow_single_file = True, - aspects = [sources_aspect], ), "protractor": attr.label( doc = "Protractor executable target", @@ -176,7 +193,7 @@ _protractor_web_test = rule( "deps": attr.label_list( doc = "Other targets which produce JavaScript such as `ts_library`", allow_files = True, - aspects = [sources_aspect], + aspects = [node_modules_aspect], ), "_conf_tmpl": attr.label( default = Label(_CONF_TMPL), diff --git a/packages/rollup/src/rollup_bundle.bzl b/packages/rollup/src/rollup_bundle.bzl index 0e3babd356..393b513c15 100644 --- a/packages/rollup/src/rollup_bundle.bzl +++ b/packages/rollup/src/rollup_bundle.bzl @@ -1,7 +1,7 @@ "Rules for running Rollup under Bazel" load("@build_bazel_rules_nodejs//:providers.bzl", "JSEcmaScriptModuleInfo") -load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleSources", "collect_node_modules_aspect") +load("@build_bazel_rules_nodejs//internal/common:npm_package_info.bzl", "NpmPackageInfo", "node_modules_aspect") load("@build_bazel_rules_nodejs//internal/linker:link_node_modules.bzl", "module_mappings_aspect", "register_node_modules_linker") _DOC = """Runs the Rollup.js CLI under Bazel. @@ -152,7 +152,7 @@ Passed to the [`--sourcemap` option](https://github.com/rollup/rollup/blob/maste values = ["inline", "true", "false"], ), "deps": attr.label_list( - aspects = [module_mappings_aspect, collect_node_modules_aspect], + aspects = [module_mappings_aspect, node_modules_aspect], doc = """Other libraries that are required by the code, or by the rollup.config.js""", ), } @@ -250,9 +250,9 @@ def _rollup_bundle(ctx): deps_depsets.append(dep.files) # Also include files from npm deps as inputs. - # These deps are identified by the NodeModuleSources provider. - if NodeModuleSources in dep: - deps_depsets.append(dep[NodeModuleSources].sources) + # These deps are identified by the NpmPackageInfo provider. + if NpmPackageInfo in dep: + deps_depsets.append(dep[NpmPackageInfo].sources) deps_inputs = depset(transitive = deps_depsets).to_list() inputs = _filter_js(ctx.files.entry_point) + _filter_js(ctx.files.entry_points) + ctx.files.srcs + deps_inputs diff --git a/packages/typescript/src/internal/build_defs.bzl b/packages/typescript/src/internal/build_defs.bzl index ee05d52274..fda8e3278a 100644 --- a/packages/typescript/src/internal/build_defs.bzl +++ b/packages/typescript/src/internal/build_defs.bzl @@ -14,8 +14,8 @@ "TypeScript compilation" -load("@build_bazel_rules_nodejs//:providers.bzl", "js_ecma_script_module_info") -load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleSources", "collect_node_modules_aspect") +load("@build_bazel_rules_nodejs//:providers.bzl", "js_ecma_script_module_info", "js_named_module_info") +load("@build_bazel_rules_nodejs//internal/common:npm_package_info.bzl", "NpmPackageInfo", "node_modules_aspect") # pylint: disable=unused-argument # pylint: disable=missing-docstring @@ -46,7 +46,7 @@ def _trim_package_node_modules(package_name): # but wouldn't work for other rules like nodejs_binary def _uses_bazel_managed_node_modules(ctx): # If the user put a filegroup as the node_modules it will have no provider - return NodeModuleSources in ctx.attr.node_modules + return NpmPackageInfo in ctx.attr.node_modules # This function is similar but slightly different than _compute_node_modules_root # in /internal/node/node.bzl. TODO(gregmagolan): consolidate these functions @@ -61,8 +61,8 @@ def _compute_node_modules_root(ctx): """ node_modules_root = None if ctx.attr.node_modules: - if NodeModuleSources in ctx.attr.node_modules: - node_modules_root = "/".join(["external", ctx.attr.node_modules[NodeModuleSources].workspace, "node_modules"]) + if NpmPackageInfo in ctx.attr.node_modules: + node_modules_root = "/".join(["external", ctx.attr.node_modules[NpmPackageInfo].workspace, "node_modules"]) elif ctx.files.node_modules: # ctx.files.node_modules is not an empty list node_modules_root = "/".join([f for f in [ @@ -71,8 +71,8 @@ def _compute_node_modules_root(ctx): "node_modules", ] if f]) for d in ctx.attr.deps: - if NodeModuleSources in d: - possible_root = "/".join(["external", d[NodeModuleSources].workspace, "node_modules"]) + if NpmPackageInfo in d: + possible_root = "/".join(["external", d[NpmPackageInfo].workspace, "node_modules"]) if not node_modules_root: node_modules_root = possible_root elif node_modules_root != possible_root: @@ -118,11 +118,11 @@ def _compile_action(ctx, inputs, outputs, tsconfig_file, node_opts, description action_inputs.extend(_filter_ts_inputs(ctx.files.node_modules)) # Also include files from npm fine grained deps as action_inputs. - # These deps are identified by the NodeModuleSources provider. + # These deps are identified by the NpmPackageInfo provider. for d in ctx.attr.deps: - if NodeModuleSources in d: + if NpmPackageInfo in d: # Note: we can't avoid calling .to_list() on sources - action_inputs.extend(_filter_ts_inputs(d[NodeModuleSources].sources.to_list())) + action_inputs.extend(_filter_ts_inputs(d[NpmPackageInfo].sources.to_list())) if ctx.file.tsconfig: action_inputs.append(ctx.file.tsconfig) @@ -275,12 +275,16 @@ def _ts_library_impl(ctx): # See design doc https://docs.google.com/document/d/1ggkY5RqUkVL4aQLYm7esRW978LgX3GUCnQirrk5E1C0/edit# # and issue https://github.com/bazelbuild/rules_nodejs/issues/57 for more details. ts_providers["providers"].extend([ + js_named_module_info( + sources = ts_providers["typescript"]["es5_sources"], + deps = ctx.attr.deps, + ), js_ecma_script_module_info( sources = ts_providers["typescript"]["es6_sources"], deps = ctx.attr.deps, ), - # TODO: Add remaining shared JS providers from design doc - # (JSModuleInfo and JSNamedModuleInfo) and remove legacy "typescript" provider + # TODO: Add remaining shared JS provider from design doc + # (JSModuleInfo) and remove legacy "typescript" provider # once it is no longer needed. ]) @@ -412,7 +416,7 @@ either: doc = "If using tsickle, instruct it to translate types to ClosureJS format", ), "deps": attr.label_list( - aspects = DEPS_ASPECTS + [collect_node_modules_aspect], + aspects = DEPS_ASPECTS + [node_modules_aspect], doc = "Compile-time dependencies, typically other ts_library targets", ), }), diff --git a/packages/typescript/src/internal/devserver/ts_devserver.bzl b/packages/typescript/src/internal/devserver/ts_devserver.bzl index 66a80c35b8..04959b8439 100644 --- a/packages/typescript/src/internal/devserver/ts_devserver.bzl +++ b/packages/typescript/src/internal/devserver/ts_devserver.bzl @@ -14,7 +14,8 @@ "Simple development server" -load("@build_bazel_rules_nodejs//internal/common:sources_aspect.bzl", "sources_aspect") +load("@build_bazel_rules_nodejs//:providers.bzl", "JSNamedModuleInfo") +load("@build_bazel_rules_nodejs//internal/common:npm_package_info.bzl", "NpmPackageInfo", "node_modules_aspect") load( "@build_bazel_rules_nodejs//internal/js_library:js_library.bzl", "write_amd_names_shim", @@ -33,15 +34,25 @@ def _to_manifest_path(ctx, file): return ctx.workspace_name + "/" + file.short_path def _ts_devserver(ctx): - files = depset() - dev_scripts = depset() - for d in ctx.attr.deps: - if hasattr(d, "node_sources"): - files = depset(transitive = [files, d.node_sources]) - elif hasattr(d, "files"): - files = depset(transitive = [files, d.files]) - if hasattr(d, "dev_scripts"): - dev_scripts = depset(transitive = [dev_scripts, d.dev_scripts]) + files_depsets = [] + for dep in ctx.attr.deps: + if JSNamedModuleInfo in dep: + files_depsets.append(dep[JSNamedModuleInfo].sources) + if not JSNamedModuleInfo in dep and not NpmPackageInfo in dep and hasattr(dep, "files"): + # These are javascript files provided by DefaultInfo from a direct + # dep that has no JSNamedModuleInfo provider or NpmPackageInfo + # provider (not an npm dep). These files must be in named AMD or named + # UMD format. + files_depsets.append(dep.files) + files = depset(transitive = files_depsets) + + # Also include files from npm fine grained deps as inputs. + # These deps are identified by the NpmPackageInfo provider. + node_modules_depsets = [] + for dep in ctx.attr.deps: + if NpmPackageInfo in dep: + node_modules_depsets.append(dep[NpmPackageInfo].sources) + node_modules = depset(transitive = node_modules_depsets) if ctx.label.workspace_root: # We need the workspace_name for the target being visited. @@ -59,6 +70,7 @@ def _ts_devserver(ctx): ctx.actions.write(ctx.outputs.manifest, "".join([ workspace_name + "/" + f.short_path + "\n" for f in files.to_list() + if f.path.endswith(".js") ])) amd_names_shim = ctx.actions.declare_file( @@ -75,7 +87,6 @@ def _ts_devserver(ctx): script_files.append(ctx.file._requirejs_script) script_files.append(amd_names_shim) script_files.extend(ctx.files.scripts) - script_files.extend(dev_scripts.to_list()) ctx.actions.write(ctx.outputs.scripts_manifest, "".join([ workspace_name + "/" + f.short_path + "\n" for f in script_files @@ -128,7 +139,7 @@ def _ts_devserver(ctx): files = devserver_runfiles, # We don't expect executable targets to depend on the devserver, but if they do, # they can see the JavaScript code. - transitive_files = depset(ctx.files.data, transitive = [files]), + transitive_files = depset(ctx.files.data, transitive = [files, node_modules]), collect_data = True, collect_default = True, ), @@ -192,7 +203,7 @@ ts_devserver = rule( "deps": attr.label_list( doc = "Targets that produce JavaScript, such as `ts_library`", allow_files = True, - aspects = [sources_aspect], + aspects = [node_modules_aspect], ), "_bash_runfile_helpers": attr.label(default = Label("@bazel_tools//tools/bash/runfiles")), "_injector": attr.label( diff --git a/packages/typescript/test/devmode_consumer/devmode_consumer.bzl b/packages/typescript/test/devmode_consumer/devmode_consumer.bzl index b23a4b421d..ed90e109cf 100644 --- a/packages/typescript/test/devmode_consumer/devmode_consumer.bzl +++ b/packages/typescript/test/devmode_consumer/devmode_consumer.bzl @@ -15,26 +15,23 @@ """Example of a rule that requires es2015 (devmode) inputs. """ -load("@build_bazel_rules_nodejs//internal/common:sources_aspect.bzl", "sources_aspect") +load("@build_bazel_rules_nodejs//:providers.bzl", "JSNamedModuleInfo") def _devmode_consumer(ctx): - files = depset() - - # Since we apply the sources_aspect to our deps below, we can iterate through - # the deps and grab the attribute attached by that aspect, which is called - # "node_sources". - # See https://github.com/bazelbuild/rules_nodejs/blob/master/internal/node.bzl - for d in ctx.attr.deps: - files = depset(transitive = [files, d.node_sources]) + sources_depsets = [] + for dep in ctx.attr.deps: + if JSNamedModuleInfo in dep: + sources_depsets.append(dep[JSNamedModuleInfo].sources) + sources = depset(transitive = sources_depsets) return [DefaultInfo( - files = files, - runfiles = ctx.runfiles(files.to_list()), + files = sources, + runfiles = ctx.runfiles(transitive_files = sources), )] devmode_consumer = rule( implementation = _devmode_consumer, attrs = { - "deps": attr.label_list(aspects = [sources_aspect]), + "deps": attr.label_list(), }, ) diff --git a/providers.bzl b/providers.bzl index db2ba512b0..f78b900a9d 100644 --- a/providers.bzl +++ b/providers.bzl @@ -22,6 +22,37 @@ If users really need to produce both in a single build, they'll need two rules w differing 'debug' attributes. """ +JSNamedModuleInfo = provider( + doc = """JavaScript files whose module name is self-contained. + +For example named AMD/UMD or goog.module format. +These files can be efficiently served with the concatjs bundler. +These outputs should be named "foo.umd.js" +(note that renaming it from "foo.js" doesn't affect the module id) + +Historical note: this was the typescript.es5_sources output. +""", + fields = { + "direct_sources": "Depset of direct JavaScript files and sourcemaps", + "sources": "Depset of direct and transitive JavaScript files and sourcemaps", + }, +) + +def js_named_module_info(sources, deps = []): + """Constructs a JSNamedModuleInfo including all transitive sources from JSNamedModuleInfo providers in a list of deps. + +Returns a single JSNamedModuleInfo. +""" + transitive_depsets = [sources] + for dep in deps: + if JSNamedModuleInfo in dep: + transitive_depsets.append(dep[JSNamedModuleInfo].sources) + + return JSNamedModuleInfo( + direct_sources = sources, + sources = depset(transitive = transitive_depsets), + ) + JSEcmaScriptModuleInfo = provider( doc = """JavaScript files (and sourcemaps) that are intended to be consumed by downstream tooling. @@ -31,8 +62,8 @@ TODO: should we require that? Historical note: this was the typescript.es6_sources output""", fields = { - "direct_sources": "depset of direct JavaScript files and sourcemaps", - "sources": "depset of direct and transitive JavaScript files and sourcemaps", + "direct_sources": "Depset of direct JavaScript files and sourcemaps", + "sources": "Depset of direct and transitive JavaScript files and sourcemaps", }, )