Skip to content

Commit bb1f9b4

Browse files
gregmagolanalexeagle
authored andcommitted
feat(typescript): add JSNamedModuleInfo provider to ts_library outputs (#1215)
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
1 parent f9e48e4 commit bb1f9b4

29 files changed

+480
-367
lines changed

WORKSPACE

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,10 @@ yarn_install(
6767
name = "npm",
6868
# The @npm//:node_modules_filegroup generated by manual_build_file_contents
6969
# is used in the //packages/typescript/test/reference_types_directive:tsconfig_types
70-
# test. For now we're still supporting node_modules as a filegroup tho this
71-
# may change in the future. The default generated //:node_modules target is a
72-
# node_module_library rule which provides NodeModuleInfo and NodeModuleSources
73-
# but that rule is not yet in the public API and we have not yet dropped support
74-
# for filegroup based node_modules target.
70+
# test. For now we're still supporting node_modules as a filegroup tho this may
71+
# change in the future. The default generated //:node_modules target is a node_module_library
72+
# rule which provides NpmPackageInfo but that rule is not yet in the public API and we
73+
# have not yet dropped support for filegroup based node_modules target.
7574
manual_build_file_contents = """
7675
filegroup(
7776
name = "node_modules_filegroup",

examples/angular/patches/@angular+bazel+9.0.0-next.8.patch

Lines changed: 113 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,30 @@
1-
diff --git a/node_modules/@angular/bazel/src/esm5.bzl b/node_modules/@angular/bazel/src/esm5.bzl
2-
index 667f601..7907c12 100755
3-
--- a/node_modules/@angular/bazel/src/esm5.bzl
4-
+++ b/node_modules/@angular/bazel/src/esm5.bzl
5-
@@ -30,7 +30,7 @@ ESM5Info = provider(
1+
diff --git a/node_modules/@angular/bazel/src/external.bzl b/node_modules/@angular/bazel/src/external.bzl
2+
index 4959f22..43f1c96 100755
3+
--- a/node_modules/@angular/bazel/src/external.bzl
4+
+++ b/node_modules/@angular/bazel/src/external.bzl
5+
@@ -14,17 +14,17 @@ load(
6+
_ts_providers_dict_to_struct = "ts_providers_dict_to_struct",
7+
)
8+
load(
9+
- "@build_bazel_rules_nodejs//internal/common:node_module_info.bzl",
10+
- _NodeModuleSources = "NodeModuleSources",
11+
- _collect_node_modules_aspect = "collect_node_modules_aspect",
12+
+ "@build_bazel_rules_nodejs//internal/common:npm_package_info.bzl",
13+
+ _NpmPackageInfo = "NpmPackageInfo",
14+
+ _node_modules_aspect = "node_modules_aspect",
15+
)
16+
load(
17+
"@npm_bazel_typescript//internal:ts_config.bzl",
18+
_TsConfigInfo = "TsConfigInfo",
619
)
720

8-
def _map_closure_path(file):
9-
- result = file.short_path[:-len(".closure.js")]
10-
+ result = file.short_path[:-len(".mjs")]
21+
-NodeModuleSources = _NodeModuleSources
22+
-collect_node_modules_aspect = _collect_node_modules_aspect
23+
+NpmPackageInfo = _NpmPackageInfo
24+
+node_modules_aspect = _node_modules_aspect
1125

12-
# short_path is meant to be used when accessing runfiles in a binary, where
13-
# the CWD is inside the current repo. Therefore files in external repo have a
26+
tsc_wrapped_tsconfig = _tsc_wrapped_tsconfig
27+
COMMON_ATTRIBUTES = _COMMON_ATTRIBUTES
1428
diff --git a/node_modules/@angular/bazel/src/modify_tsconfig.js b/node_modules/@angular/bazel/src/modify_tsconfig.js
1529
index 9d3c491..3c99746 100755
1630
--- a/node_modules/@angular/bazel/src/modify_tsconfig.js
@@ -25,14 +39,23 @@ index 9d3c491..3c99746 100755
2539
fs.writeFileSync(output, JSON.stringify(data));
2640
}
2741
diff --git a/node_modules/@angular/bazel/src/ng_module.bzl b/node_modules/@angular/bazel/src/ng_module.bzl
28-
index 9b88fbb..68217d0 100755
42+
index 9b88fbb..54bf2c7 100755
2943
--- a/node_modules/@angular/bazel/src/ng_module.bzl
3044
+++ b/node_modules/@angular/bazel/src/ng_module.bzl
31-
@@ -20,6 +20,7 @@ load(
45+
@@ -13,13 +13,14 @@ load(
46+
"DEFAULT_NG_COMPILER",
47+
"DEFAULT_NG_XI18N",
48+
"DEPS_ASPECTS",
49+
- "NodeModuleSources",
50+
+ "NpmPackageInfo",
51+
"TsConfigInfo",
52+
- "collect_node_modules_aspect",
53+
+ "node_modules_aspect",
54+
"compile_ts",
3255
"ts_providers_dict_to_struct",
3356
"tsc_wrapped_tsconfig",
3457
)
35-
+load("@build_bazel_rules_nodejs//:providers.bzl", "transitive_js_ecma_script_module_info")
58+
+load("@build_bazel_rules_nodejs//:providers.bzl", "js_ecma_script_module_info", "js_named_module_info")
3659

3760
_FLAT_DTS_FILE_SUFFIX = ".bundle.d.ts"
3861
_R3_SYMBOLS_DTS_FILE = "src/r3_symbols.d.ts"
@@ -54,22 +77,96 @@ index 9b88fbb..68217d0 100755
5477
bundle_index_typings = ctx.actions.declare_file("%s.d.ts" % flat_module_out)
5578
declaration_files.append(bundle_index_typings)
5679
if is_legacy_ngc:
57-
@@ -603,7 +604,17 @@ def ng_module_impl(ctx, ts_compile_actions):
80+
@@ -517,11 +518,11 @@ def _compile_action(ctx, inputs, outputs, dts_bundles_out, messages_out, tsconfi
81+
file_inputs += ctx.attr.tsconfig[TsConfigInfo].deps
82+
83+
# Also include files from npm fine grained deps as action_inputs.
84+
- # These deps are identified by the NodeModuleSources provider.
85+
+ # These deps are identified by the NpmPackageInfo provider.
86+
for d in ctx.attr.deps:
87+
- if NodeModuleSources in d:
88+
+ if NpmPackageInfo in d:
89+
# Note: we can't avoid calling .to_list() on sources
90+
- file_inputs.extend(_filter_ts_inputs(d[NodeModuleSources].sources.to_list()))
91+
+ file_inputs.extend(_filter_ts_inputs(d[NpmPackageInfo].sources.to_list()))
92+
93+
# Collect the inputs and summary files from our deps
94+
action_inputs = depset(
95+
@@ -603,9 +604,23 @@ def ng_module_impl(ctx, ts_compile_actions):
5896
return providers
5997

6098
def _ng_module_impl(ctx):
6199
- return ts_providers_dict_to_struct(ng_module_impl(ctx, compile_ts))
100+
-
101+
-local_deps_aspects = [collect_node_modules_aspect, _collect_summaries_aspect]
62102
+ ts_providers = ng_module_impl(ctx, compile_ts)
63103
+
64104
+ # Add in new JS providers
65105
+ ts_providers["providers"].extend([
66-
+ transitive_js_ecma_script_module_info(
106+
+ js_named_module_info(
107+
+ sources = ts_providers["typescript"]["es5_sources"],
108+
+ deps = ctx.attr.deps,
109+
+ ),
110+
+ js_ecma_script_module_info(
67111
+ sources = ts_providers["typescript"]["es6_sources"],
68112
+ deps = ctx.attr.deps,
69113
+ ),
70114
+ ])
71115
+
72116
+ return ts_providers_dict_to_struct(ts_providers)
117+
+
118+
+local_deps_aspects = [node_modules_aspect, _collect_summaries_aspect]
119+
120+
# Workaround skydoc bug which assumes DEPS_ASPECTS is a str type
121+
[local_deps_aspects.append(a) for a in DEPS_ASPECTS]
122+
diff --git a/node_modules/@angular/bazel/src/ng_package/ng_package.bzl b/node_modules/@angular/bazel/src/ng_package/ng_package.bzl
123+
index 48d7619..ea635bb 100755
124+
--- a/node_modules/@angular/bazel/src/ng_package/ng_package.bzl
125+
+++ b/node_modules/@angular/bazel/src/ng_package/ng_package.bzl
126+
@@ -13,9 +13,8 @@ It packages your library following the Angular Package Format, see the
127+
specification of this format at https://goo.gl/jB3GVv
128+
"""
129+
130+
-load("@build_bazel_rules_nodejs//internal/common:collect_es6_sources.bzl", "collect_es6_sources")
131+
-load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleSources")
132+
-load("@build_bazel_rules_nodejs//internal/common:sources_aspect.bzl", "sources_aspect")
133+
+load("@build_bazel_rules_nodejs//:providers.bzl", "JSEcmaScriptModuleInfo", "JSNamedModuleInfo")
134+
+load("@build_bazel_rules_nodejs//internal/common:npm_package_info.bzl", "NpmPackageInfo")
135+
load(
136+
"@build_bazel_rules_nodejs//internal/rollup:rollup_bundle.bzl",
137+
"ROLLUP_ATTRS",
138+
@@ -207,7 +206,12 @@ def _filter_js_inputs(all_inputs):
139+
def _ng_package_impl(ctx):
140+
npm_package_directory = ctx.actions.declare_directory("%s.ng_pkg" % ctx.label.name)
141+
142+
- esm_2015_files = _filter_out_generated_files(collect_es6_sources(ctx), "js")
143+
+ esm_2015_files = []
144+
+ for dep in ctx.attr.deps:
145+
+ if JSEcmaScriptModuleInfo in dep:
146+
+ esm_2015_files += dep[JSEcmaScriptModuleInfo].sources.to_list()
147+
+
148+
+ esm_2015_files = _filter_out_generated_files(esm_2015_files, "js")
149+
esm5_sources = _filter_out_generated_files(flatten_esm5(ctx), "js")
150+
151+
# These accumulators match the directory names where the files live in the
152+
@@ -347,9 +351,9 @@ def _ng_package_impl(ctx):
153+
node_modules_files = _filter_js_inputs(ctx.files.node_modules)
154+
155+
# Also include files from npm fine grained deps as inputs.
156+
- # These deps are identified by the NodeModuleSources provider.
157+
+ # These deps are identified by the NpmPackageInfo provider.
158+
for d in ctx.attr.deps:
159+
- if NodeModuleSources in d:
160+
+ if NpmPackageInfo in d:
161+
node_modules_files += _filter_js_inputs(d.files)
162+
esm5_rollup_inputs = depset(node_modules_files, transitive = [esm5_sources])
163+
164+
@@ -469,7 +473,7 @@ def _ng_package_impl(ctx):
165+
files = depset([package_dir]),
166+
)]
73167

74-
local_deps_aspects = [collect_node_modules_aspect, _collect_summaries_aspect]
168+
-DEPS_ASPECTS = [esm5_outputs_aspect, sources_aspect]
169+
+DEPS_ASPECTS = [esm5_outputs_aspect]
75170

171+
# Workaround skydoc bug which assumes ROLLUP_DEPS_ASPECTS is a str type
172+
[DEPS_ASPECTS.append(a) for a in ROLLUP_DEPS_ASPECTS]

internal/common/devmode_js_sources.bzl

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
Outputs a manifest file with the sources listed.
1818
"""
1919

20-
load(":sources_aspect.bzl", "sources_aspect")
20+
load("@build_bazel_rules_nodejs//:providers.bzl", "JSNamedModuleInfo")
2121

2222
# Avoid using non-normalized paths (workspace/../other_workspace/path)
2323
def _to_manifest_path(ctx, file):
@@ -27,26 +27,27 @@ def _to_manifest_path(ctx, file):
2727
return ctx.workspace_name + "/" + file.short_path
2828

2929
def _devmode_js_sources_impl(ctx):
30-
files = depset()
31-
32-
for d in ctx.attr.deps:
33-
if hasattr(d, "node_sources"):
34-
files = depset(transitive = [files, d.node_sources])
35-
elif hasattr(d, "files"):
36-
files = depset(transitive = [files, d.files])
30+
sources_depsets = []
31+
for dep in ctx.attr.deps:
32+
if JSNamedModuleInfo in dep:
33+
sources_depsets.append(dep[JSNamedModuleInfo].sources)
34+
if hasattr(dep, "files"):
35+
sources_depsets.append(dep.files)
36+
sources = depset(transitive = sources_depsets)
3737

3838
ctx.actions.write(ctx.outputs.manifest, "".join([
3939
_to_manifest_path(ctx, f) + "\n"
40-
for f in files.to_list()
40+
for f in sources.to_list()
41+
if f.path.endswith(".js") or f.path.endswith(".mjs")
4142
]))
42-
return [DefaultInfo(files = files)]
43+
44+
return [DefaultInfo(files = sources)]
4345

4446
devmode_js_sources = rule(
4547
implementation = _devmode_js_sources_impl,
4648
attrs = {
4749
"deps": attr.label_list(
4850
allow_files = True,
49-
aspects = [sources_aspect],
5051
),
5152
},
5253
outputs = {

internal/common/node_module_info.bzl

Lines changed: 0 additions & 74 deletions
This file was deleted.

internal/common/npm_package_info.bzl

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Copyright 2017 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""NpmPackageInfo providers and apsect to collect node_modules from deps.
16+
"""
17+
18+
# NpmPackageInfo provider is provided by targets that are npm dependencies by the
19+
# `node_module_library` rule as well as other targets that have direct or transitive deps on
20+
# `node_module_library` targets via the `node_modules_aspect` below.
21+
NpmPackageInfo = provider(
22+
doc = "Provides information about npm dependencies",
23+
fields = {
24+
"direct_sources": "Depset of direct source files in this npm package",
25+
"sources": "Depset of direct & transitive source files in this npm package and in its dependencies",
26+
"workspace": "The workspace name that this npm package is provided from",
27+
},
28+
)
29+
30+
def _node_modules_aspect_impl(target, ctx):
31+
providers = []
32+
33+
# provide NpmPackageInfo if it is not already provided there are NpmPackageInfo deps
34+
if not NpmPackageInfo in target:
35+
sources_depsets = []
36+
workspace = None
37+
if hasattr(ctx.rule.attr, "deps"):
38+
for dep in ctx.rule.attr.deps:
39+
if NpmPackageInfo in dep:
40+
if workspace and dep[NpmPackageInfo].workspace != workspace:
41+
fail("All npm dependencies need to come from a single workspace. Found '%s' and '%s'." % (workspace, dep[NpmPackageInfo].workspace))
42+
workspace = dep[NpmPackageInfo].workspace
43+
sources_depsets.append(dep[NpmPackageInfo].sources)
44+
if workspace:
45+
providers.extend([NpmPackageInfo(direct_sources = depset(), sources = depset(transitive = sources_depsets), workspace = workspace)])
46+
47+
return providers
48+
49+
node_modules_aspect = aspect(
50+
_node_modules_aspect_impl,
51+
attr_aspects = ["deps"],
52+
)

0 commit comments

Comments
 (0)