豆豆友情提示:这是一个非官方 GitHub 代理镜像,主要用于网络测试或访问加速。请勿在此进行登录、注册或处理任何敏感信息。进行这些操作请务必访问官方网站 github.com。 Raw 内容也通过此代理提供。
Skip to content

Commit 07c1c19

Browse files
committed
feat(bazel): support using es2020 in spec-bundled tests
We currently set the default spec-bundle target to es2016 to work around the ZoneJS async/await native syntax issue. We can default to ES2020 consistently and just downlevel async/await, similar to how the Angular CLI would do it.
1 parent 734fd03 commit 07c1c19

File tree

5 files changed

+111
-3
lines changed

5 files changed

+111
-3
lines changed

bazel/spec-bundling/bundle-config.bzl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
def _spec_bundle_config_file_impl(ctx):
22
run_angular_linker = ctx.attr.run_angular_linker
3+
downlevel_async_await = ctx.attr.downlevel_async_await
34
linker_unknown_declaration_handling = ctx.attr.linker_unknown_declaration_handling
45

56
ctx.actions.expand_template(
67
template = ctx.file._template,
78
output = ctx.outputs.output_name,
89
substitutions = {
910
"TMPL_RUN_LINKER": "true" if run_angular_linker else "false",
11+
"TMPL_DOWNLEVEL_ASYNC_AWAIT": "true" if downlevel_async_await else "false",
1012
"TMPL_LINKER_UNKNOWN_DECLARATION_HANDLING": ("'%s'" % linker_unknown_declaration_handling) if linker_unknown_declaration_handling else "undefined",
1113
},
1214
)
@@ -19,6 +21,10 @@ spec_bundle_config_file = rule(
1921
doc = "Whether the Angular linker should process all files.",
2022
default = False,
2123
),
24+
"downlevel_async_await": attr.bool(
25+
doc = "Whether to downlevel async/await syntax.",
26+
default = True,
27+
),
2228
"output_name": attr.output(
2329
mandatory = True,
2430
doc = "Name of the file where the config should be written to.",

bazel/spec-bundling/esbuild.config-tmpl.mjs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,23 @@ async function fetchAndCreateLinkerEsbuildPlugin() {
2626
// Based on the Bazel action and its substitutions, we run the linker for all inputs.
2727
const plugins = TMPL_RUN_LINKER ? [await fetchAndCreateLinkerEsbuildPlugin()] : [];
2828

29+
// List of supported features as per ESBuild. See:
30+
// https://esbuild.github.io/api/#supported.
31+
const supported = {};
32+
33+
// Async/Await can be downleveled so that ZoneJS can intercept. See:
34+
// https://github.com/angular/angular-cli/blob/afe9feaa45913/packages/angular_devkit/build_angular/src/builders/browser-esbuild/index.ts#L313-L318.
35+
if (TMPL_DOWNLEVEL_ASYNC_AWAIT) {
36+
supported['async-await'] = false;
37+
}
38+
2939
export default {
3040
// `tslib` sets the `module` condition to resolve to ESM.
3141
conditions: ['es2020', 'es2015', 'module'],
3242
// This ensures that we prioritize ES2020. RxJS would otherwise use the ESM5 output.
3343
mainFields: ['es2020', 'es2015', 'module', 'main'],
3444
// Addition of `.mjs` to the non-jsx defaults. https://esbuild.github.io/api/#resolve-extensions
3545
resolveExtensions: ['.mjs', '.js', '.json'],
46+
supported,
3647
plugins,
3748
};

bazel/spec-bundling/spec-bundle.bzl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ def spec_bundle(
1010
bootstrap = [],
1111
run_angular_linker = False,
1212
linker_unknown_declaration_handling = None,
13-
# We cannot use `ES2017` or higher as that would result in `async/await` not being downleveled.
14-
# ZoneJS needs to be able to intercept these as otherwise change detection would not work properly.
15-
target = "es2016",
13+
target = "es2020",
14+
# For ZoneJS compatibility, async/await is downleveled.
15+
downlevel_async_await = True,
1616
external = [],
1717
workspace_name = None):
1818
"""Macro that will bundle all test files with their respective transitive dependencies.
@@ -30,6 +30,7 @@ def spec_bundle(
3030
ending with `init.js` are picked up.
3131
target: Target ECMAScript to use for the specs bundle.
3232
run_angular_linker: Whether the Angular linker should process the bundled code.
33+
downlevel_async_await: Whether async/await native syntax should be downleveled.
3334
linker_unknown_declaration_handling: Control how unknown partial declarations should be
3435
treated. This passes through to the `unknownDeclarationVersionHandling` linker plugin option.
3536
external: List of modules/packages which should not be bundled.
@@ -55,6 +56,7 @@ def spec_bundle(
5556
testonly = True,
5657
output_name = "%s_config.mjs" % name,
5758
run_angular_linker = run_angular_linker,
59+
downlevel_async_await = downlevel_async_await,
5860
linker_unknown_declaration_handling = linker_unknown_declaration_handling,
5961
)
6062

bazel/spec-bundling/test/BUILD.bazel

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,21 @@ load("@npm//@bazel/jasmine:index.bzl", "jasmine_node_test")
44
load("//bazel/spec-bundling:index.bzl", "spec_bundle")
55
load("//tools:defaults.bzl", "ts_library")
66

7+
ts_library(
8+
name = "test_async_await_lib",
9+
testonly = True,
10+
srcs = ["async-await.spec.ts"],
11+
deps = [
12+
"@npm//@angular/core",
13+
"@npm//@angular/platform-browser-dynamic",
14+
"@npm//@types/jasmine",
15+
"@npm//@types/jsdom",
16+
"@npm//@types/node",
17+
"@npm//jsdom",
18+
"@npm//zone.js",
19+
],
20+
)
21+
722
ts_library(
823
name = "test_lib_apf",
924
testonly = True,
@@ -46,6 +61,14 @@ spec_bundle(
4661
deps = [":test_lib_invalid_linker_declaration"],
4762
)
4863

64+
spec_bundle(
65+
name = "test_bundle_async_await",
66+
external = ["jsdom"],
67+
platform = "node",
68+
run_angular_linker = True,
69+
deps = [":test_async_await_lib"],
70+
)
71+
4972
jasmine_node_test(
5073
name = "test",
5174
deps = [
@@ -66,3 +89,11 @@ jasmine_node_test(
6689
":test_bundle_invalid_declaration_linker",
6790
],
6891
)
92+
93+
jasmine_node_test(
94+
name = "test_async_await",
95+
deps = [
96+
":test_bundle_async_await",
97+
"@npm//jsdom",
98+
],
99+
)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import 'zone.js';
2+
import 'zone.js/testing';
3+
4+
import {JSDOM} from 'jsdom';
5+
import {Component} from '@angular/core';
6+
import {fakeAsync, flush, TestBed, waitForAsync} from '@angular/core/testing';
7+
import {
8+
BrowserDynamicTestingModule,
9+
platformBrowserDynamicTesting,
10+
} from '@angular/platform-browser-dynamic/testing';
11+
12+
describe('native async/await downleveled', () => {
13+
beforeAll(() => {
14+
const {window} = new JSDOM();
15+
16+
(global as any).window = window;
17+
(global as any).document = window.document;
18+
(global as any).Node = window.Node;
19+
(global as any).MouseEvent = window.MouseEvent;
20+
21+
TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
22+
});
23+
24+
it('should properly detect changes', fakeAsync(() => {
25+
TestBed.configureTestingModule({
26+
declarations: [AppComponent],
27+
});
28+
const fixture = TestBed.createComponent(AppComponent);
29+
const el = fixture.nativeElement as HTMLElement;
30+
31+
fixture.detectChanges();
32+
el.dispatchEvent(new MouseEvent('click'));
33+
fixture.detectChanges();
34+
35+
// Flush the timeout macrotask from the click handler.
36+
// Then we attempt detecting changes.
37+
flush();
38+
fixture.detectChanges();
39+
40+
expect(el.textContent).toBe('Yes');
41+
}));
42+
});
43+
44+
@Component({
45+
selector: 'app-component',
46+
template: `<span>{{ triggered ? 'Yes' : 'No' }}</span>`,
47+
host: {
48+
'(click)': 'click()',
49+
},
50+
})
51+
class AppComponent {
52+
triggered = false;
53+
54+
async click() {
55+
await new Promise((resolve) => setTimeout(resolve, 500));
56+
this.triggered = true;
57+
}
58+
}

0 commit comments

Comments
 (0)