Compare commits

...

30 Commits

Author SHA1 Message Date
aac7ab7f36 fix shrinkwrap 2016-08-26 14:44:07 -07:00
5447430c3a WIP repackaging
- move esm to main
- remove testing esm output
- index.js is bundle
2016-08-26 14:44:07 -07:00
8b52b2f415 increase platform-server test timeout again 2016-08-26 14:43:38 -07:00
db19e8200f fix packaging with ts_compat, also fixed e2e tests 2016-08-26 14:43:38 -07:00
4af0656dee bazel: tsc-wrapped and tool tests 2016-08-26 14:43:37 -07:00
5a61b0e995 bazel: travis scripts 2016-08-26 14:43:37 -07:00
ff6f5d1af6 bazel: cleanup (router tsconfig.json) 2016-08-26 14:43:37 -07:00
2d0076195b bazel: build benchpress 2016-08-26 14:43:37 -07:00
439783d64d bazel: migrate multiple e2e tests 2016-08-26 14:43:37 -07:00
545636caaa bazel: developer doc update 2016-08-26 14:43:37 -07:00
272b147e44 bazel: mark platform-server test as flaky 2016-08-26 14:43:37 -07:00
779423c27a bazel: ibazel and bazel-run.sh 2016-08-26 14:43:36 -07:00
ec4a53e44d bazel: check cycle test 2016-08-26 14:43:36 -07:00
5ed72a8a6c bazel: public api spec 2016-08-26 14:43:36 -07:00
3cc1a803f6 bazel: dts downleveling and npm packaging 2016-08-26 14:43:36 -07:00
954d04a69d bazel: protractor playground 2016-08-26 14:43:34 -07:00
5af7b0cdc2 bazel: umd bundle 2016-08-26 13:56:33 -07:00
47935dd5cd bazel: karma (watch is broken) 2016-08-26 13:56:32 -07:00
b5f97b0410 bazel: compiler codegen test 2016-08-26 13:56:14 -07:00
fb3b490198 bazel: jasmine tests and compile all tests 2016-08-26 13:56:11 -07:00
d4107ef2e3 bazel: basic package compilation 2016-08-26 13:41:30 -07:00
29bea34169 bazel: node_modules_index, typescript, ts persistent worker 2016-08-26 13:41:29 -07:00
117da538ae bazel: nodejs rules 2016-08-26 13:41:29 -07:00
3b36692f26 bazel: basic workspace 2016-08-26 13:41:29 -07:00
fef78646b7 fixes for tsc 2.0 2016-08-26 13:41:28 -07:00
4e2bb7e2b7 ~~~ core test fixes 2016-08-26 13:41:28 -07:00
811fcb3556 ~~~ tsc-wrapped test fixes 2016-08-26 12:04:33 -07:00
7a539d92ab ~~~ fix test bindings again lol 2016-08-26 12:04:33 -07:00
884cf2df33 ~~~ fix some tests 2016-08-26 12:03:57 -07:00
23a942ddec test boundary refactoring and main() invocation (0826) 2016-08-26 12:02:42 -07:00
355 changed files with 8493 additions and 2152 deletions

11
.bazelrc Normal file
View File

@ -0,0 +1,11 @@
# This prevents the compiler codegen step from requiring certain packages from
# being built twice -- one for host and one for target.
#
# In any case, since we don't have architecture dependent outputs, setting this
# to false will not be a problem.
build --distinct_host_configuration=false
build --verbose_failures --show_task_finish
test --test_output=errors --keep_going
build --strategy=TypeScriptCompile=worker --worker_max_instances=2

4
.gitignore vendored
View File

@ -47,3 +47,7 @@ npm-debug.log
# rollup-test output
/modules/rollup-test/dist/
# bazel runtime folders
/bazel-*
!bazel-run.sh

View File

@ -1,7 +1,9 @@
language: node_js
# We have to use the Java image to get access to java 8, which is required for
# bazel.
language: java
sudo: false
node_js:
- '5.4.1'
jdk:
- oraclejdk8
addons:
# firefox: "38.0"
@ -11,6 +13,10 @@ addons:
- ubuntu-toolchain-r-test
packages:
- g++-4.8
# The following are needed for bazel.
- pkg-config
- zip
- unzip
branches:
except:
@ -20,6 +26,7 @@ cache:
directories:
- ./node_modules
- ./.chrome/chromium
- $HOME/bazel-cache
# - $HOME/.pub-cache
@ -43,8 +50,8 @@ env:
- CI_MODE=e2e
- CI_MODE=saucelabs_required
- CI_MODE=browserstack_required
- CI_MODE=saucelabs_optional
- CI_MODE=browserstack_optional
# - CI_MODE=saucelabs_optional
# - CI_MODE=browserstack_optional
matrix:
fast_finish: true
@ -60,7 +67,7 @@ before_script:
script:
- ./scripts/ci-lite/build.sh && ./scripts/ci-lite/test.sh
- ./scripts/ci-lite/test.sh
after_script:
- ./scripts/ci-lite/cleanup.sh

920
BUILD Normal file
View File

@ -0,0 +1,920 @@
package(default_visibility=["//visibility:public"])
load("//build_defs:nodejs.bzl", "nodejs_binary", "nodejs_test")
load("//build_defs:typescript.bzl", "ts_library", "ts_ext_library")
load("//build_defs:jasmine.bzl", "jasmine_node_test")
load("//build_defs:karma.bzl", "karma_test")
load("//build_defs:bundle.bzl", "js_bundle")
load("//build_defs:protractor.bzl", "protractor_test")
load("//build_defs:ts_api_guardian.bzl", "public_api", "public_api_test")
load("//build_defs:npm_package.bzl", "ts_npm_package")
# This imports node_modules targets from a generated file.
load("//build_defs:node_modules_index.bzl", "node_modules_index")
node_modules_index(glob)
###############################################################################
# Tools
###############################################################################
nodejs_binary(
name = "tsc-wrapped_bootstrap",
srcs = [
'tools/@angular/tsc-wrapped/bootstrap.js',
'//:typescript',
'//:minimist',
],
entry_point = 'tools/@angular/tsc-wrapped/bootstrap.js',
)
ts_library(
name = "tsc-wrapped",
srcs = glob(
[
"tools/@angular/tsc-wrapped/index.ts",
"tools/@angular/tsc-wrapped/src/**/*.ts",
],
),
deps = [
"//:_types_node",
"//:typescript",
"//:tsickle",
],
data = [
"tools/@angular/tsc-wrapped/worker_protocol.proto",
"//:minimist",
"//:bytebuffer",
"//:protobufjs",
],
tsconfig = "tools/@angular/tsc-wrapped/tsconfig.json",
compiler = "//:tsc-wrapped_bootstrap",
module_name = "@angular/tsc-wrapped",
root_dir = "tools/@angular/tsc-wrapped",
)
ts_library(
name = "tsc-wrapped_test_module",
srcs = glob(["tools/@angular/tsc-wrapped/test/**/*.ts"]),
deps = [
"//:_types_jasmine",
"//:typescript",
"//:tsc-wrapped",
],
tsconfig = "tools/@angular/tsc-wrapped/tsconfig.json",
root_dir = "tools/@angular/tsc-wrapped/test",
is_leaf = True,
)
jasmine_node_test(
name = "tsc-wrapped_test",
srcs = [":tsc-wrapped_test_module"],
size = "small",
args = ["--node_path=modules:tools"],
)
nodejs_binary(
name = "tsc-wrapped_bin",
srcs = [":tsc-wrapped"],
entry_point = "tools/@angular/tsc-wrapped/src/worker.js",
)
test_suite(
name = "tool_tests",
tests = [
"//:tsc-wrapped_test",
"//tools/ibazel:ibazel_test",
"//build_defs/tests/typescript:assert_test",
"//build_defs/tests/nodejs:all_tests",
],
)
###############################################################################
# Packages
###############################################################################
ts_library(
name = "jasmine_helper",
srcs = [
"modules/jasmine_helper.ts"
],
deps = [
"//:core",
"//:platform-server",
],
data = [
"//:source-map-support",
"//:reflect-metadata",
"//:zone.js",
"//:parse5",
],
tsconfig = "modules/tsconfig.json",
)
ts_ext_library(
name = "es6-subset",
declarations = ["modules/es6-subset.d.ts"],
ambient = True,
entry_point = "modules/es6-subset.d.ts",
)
ts_ext_library(
name = "dummy_system",
declarations = ["modules/system.d.ts"],
ambient = True,
entry_point = "modules/system.d.ts",
)
ts_library(
name = "facade",
srcs = glob(["modules/@angular/facade/src/**/*.ts"]),
deps = [
"//:zone.js",
"//:rxjs",
"//:es6-subset",
],
tsconfig = "modules/tsconfig.json",
module_name = "@angular/facade",
root_dir = "modules/@angular/facade",
)
ts_library(
name = "common",
srcs = glob(
["modules/@angular/common/**/*.ts"],
exclude = ["modules/@angular/common/test/**/*.ts"]),
deps = [
"//:zone.js",
"//:core",
"//:es6-subset",
],
tsconfig = "modules/@angular/common/tsconfig-es5.json",
module_name = "@angular/common",
)
ts_library(
name = "common_test_module",
srcs = glob(["modules/@angular/common/test/**/*.ts"]),
deps = [
"//:_types_node",
"//:_types_jasmine",
"//:zone.js",
"//:core",
"//:common",
"//:compiler",
"//:platform-browser",
"//:platform-browser-dynamic",
"//:platform-server",
"//:facade",
"//:es6-subset",
],
deps_use_internal = [
"//:common",
],
tsconfig = "modules/tsconfig.json",
root_dir = "modules/@angular/common/test",
is_leaf = True,
)
ts_library(
name = "compiler-cli",
srcs = glob(
["modules/@angular/compiler-cli/**/*.ts"],
exclude = [
"modules/@angular/compiler-cli/test/**/*.ts",
"modules/@angular/compiler-cli/integrationtest/**/*.ts",
]),
deps = [
"//:_types_node",
"//:_types_jasmine",
"//:zone.js",
"//:core",
"//:common",
"//:compiler",
"//:platform-server",
"//:platform-browser",
"//:tsc-wrapped",
],
tsconfig = "modules/@angular/compiler-cli/tsconfig-es5.json",
module_name = "@angular/compiler-cli",
)
ts_library(
name = "compiler-cli_test_module",
srcs = glob(["modules/@angular/compiler-cli/test/**/*.ts"]),
deps = [
"//:_types_node",
"//:_types_jasmine",
"//:zone.js",
"//:core",
"//:platform-browser",
"//:platform-browser-dynamic",
"//:compiler-cli",
"//:tsc-wrapped",
"//:facade",
],
deps_use_internal = [
"//:compiler-cli",
],
tsconfig = "modules/tsconfig.json",
root_dir = "modules/@angular/compiler-cli/test",
is_leaf = True,
)
ts_library(
name = "compiler",
srcs = glob(
["modules/@angular/compiler/**/*.ts"],
exclude = ["modules/@angular/compiler/test/**/*.ts"]),
deps = [
"//:zone.js",
"//:core",
],
tsconfig = "modules/@angular/compiler/tsconfig-es5.json",
module_name = "@angular/compiler",
)
ts_library(
name = "compiler_test_module",
srcs = glob(["modules/@angular/compiler/test/**/*.ts"]),
deps = [
"//:_types_node",
"//:_types_jasmine",
"//:zone.js",
"//:core",
"//:common",
"//:platform-browser",
"//:platform-browser-dynamic",
"//:compiler",
"//:facade",
"//:es6-subset",
],
deps_use_internal = [
"//:compiler",
],
tsconfig = "modules/tsconfig.json",
root_dir = "modules/@angular/compiler/test",
# Required for compiling codegen.
module_name = "@angular/compiler/test",
)
nodejs_binary(
name = "compiler_test_codegen_bin",
srcs = [":compiler_test_module"],
deps = [
"reflect-metadata",
],
entry_point = "modules/@angular/compiler/test/output/output_emitter_codegen.js",
)
genrule(
name = "compiler_test_codegen_ts",
outs = [
"modules/@angular/compiler/test/output/output_emitter_generated_typed.ts",
"modules/@angular/compiler/test/output/output_emitter_generated_untyped.ts",
],
tools = [
# This has to be put in tools so that its runfiles tree is also built.
":compiler_test_codegen_bin",
],
cmd = "$(location :compiler_test_codegen_bin) --node_path=modules/ $(OUTS)",
output_to_bindir = True,
)
ts_library(
name = "compiler_test_codegen_js",
srcs = [":compiler_test_codegen_ts"],
deps = [
":core",
":compiler",
":compiler_test_module",
],
tsconfig = "tools/cjs-jasmine/tsconfig-output_emitter_codegen.json",
root_dir = "modules/@angular/compiler/test",
)
ts_library(
name = "core",
srcs = glob(
["modules/@angular/core/**/*.ts"],
exclude = ["modules/@angular/core/test/**/*.ts"]),
deps = [
"//:_types_node",
"//:_types_jasmine",
"//:zone.js",
"//:rxjs",
"//:dummy_system",
],
tsconfig = "modules/@angular/core/tsconfig-es5.json",
module_name = "@angular/core",
)
ts_library(
name = "core_test_module",
srcs = glob(["modules/@angular/core/test/**/*.ts"]),
deps = [
"//:_types_node",
"//:_types_jasmine",
"//:zone.js",
"//:common",
"//:compiler",
"//:platform-browser",
"//:platform-browser-dynamic",
"//:core",
"//:facade",
"//:es6-subset",
],
deps_use_internal = [
"//:core",
],
tsconfig = "modules/tsconfig.json",
root_dir = "modules/@angular/core/test",
is_leaf = True,
)
ts_library(
name = "forms",
srcs = glob(
["modules/@angular/forms/**/*.ts"],
exclude = ["modules/@angular/forms/test/**/*.ts"]),
deps = [
"//:zone.js",
"//:core",
"//:common",
"//:compiler",
],
tsconfig = "modules/@angular/forms/tsconfig-es5.json",
module_name = "@angular/forms",
)
ts_library(
name = "forms_test_module",
srcs = glob(
["modules/@angular/forms/test/**/*.ts"]),
deps = [
"//:_types_node",
"//:_types_jasmine",
"//:zone.js",
"//:core",
"//:common",
"//:platform-browser",
"//:platform-browser-dynamic",
"//:forms",
"//:facade",
],
deps_use_internal = [
"//:forms",
],
tsconfig = "modules/tsconfig.json",
root_dir = "modules/@angular/forms/test",
is_leaf = True,
)
ts_library(
name = "http",
srcs = glob(
["modules/@angular/http/**/*.ts"],
exclude = ["modules/@angular/http/test/**/*.ts"]),
deps = [
"//:zone.js",
"//:core",
"//:common",
"//:platform-browser",
],
tsconfig = "modules/@angular/http/tsconfig-es5.json",
module_name = "@angular/http",
)
ts_library(
name = "platform-browser",
srcs = glob(
["modules/@angular/platform-browser/**/*.ts"],
exclude = ["modules/@angular/platform-browser/test/**/*.ts"]),
deps = [
"//:_types_hammerjs",
"//:_types_jasmine",
"//:_types_protractor",
"//:zone.js",
"//:_types_selenium-webdriver",
"//:core",
"//:common",
"//:facade",
],
tsconfig = "modules/@angular/platform-browser/tsconfig-es5.json",
module_name = "@angular/platform-browser",
)
ts_library(
name = "platform-browser_test_module",
srcs = glob(["modules/@angular/platform-browser/test/**/*.ts"]),
data = glob(
[
"modules/@angular/platform-browser/test/static_assets/**",
"modules/@angular/platform-browser/test/browser/static_assets/**",
]),
deps = [
"//:_types_node",
"//:_types_jasmine",
"//:zone.js",
"//:common",
"//:compiler",
"//:platform-browser",
"//:platform-browser-dynamic",
"//:core",
],
deps_use_internal = [
"//:core",
"//:platform-browser",
],
tsconfig = "modules/tsconfig.json",
root_dir = "modules/@angular/platform-browser/test",
is_leaf = True,
)
ts_library(
name = "http_test_module",
srcs = glob(["modules/@angular/http/test/**/*.ts"]),
deps = [
"//:_types_node",
"//:_types_jasmine",
"//:zone.js",
"//:core",
"//:common",
"//:platform-browser",
"//:platform-browser-dynamic",
"//:http",
"//:facade",
],
deps_use_internal = [
"//:http",
],
tsconfig = "modules/tsconfig.json",
root_dir = "modules/@angular/http/test",
is_leaf = True,
)
ts_library(
name = "platform-browser-dynamic",
srcs = glob(
["modules/@angular/platform-browser-dynamic/**/*.ts"],
exclude = ["modules/@angular/platform-browser-dynamic/test/**/*.ts"]),
deps = [
"//:_types_jasmine",
"//:zone.js",
"//:core",
"//:common",
"//:compiler",
"//:platform-browser",
],
tsconfig = "modules/@angular/platform-browser-dynamic/tsconfig-es5.json",
module_name = "@angular/platform-browser-dynamic",
)
ts_library(
name = "platform-browser-dynamic_test_module",
srcs = glob(["modules/@angular/platform-browser-dynamic/test/**/*.ts"]),
deps = [
"//:_types_node",
"//:_types_jasmine",
"//:zone.js",
"//:core",
"//:compiler",
"//:platform-browser",
"//:platform-browser-dynamic",
"//:facade",
],
deps_use_internal = [
"//:platform-browser-dynamic",
],
tsconfig = "modules/tsconfig.json",
root_dir = "modules/@angular/platform-browser-dynamic/test",
is_leaf = True,
)
ts_library(
name = "platform-server",
srcs = glob(
["modules/@angular/platform-server/**/*.ts"],
exclude = [
"modules/@angular/platform-server/platform_browser_dynamic_testing_private.ts",
"modules/@angular/platform-server/test/**/*.ts",
]),
deps = [
"//:_types_jasmine",
"//:_types_node",
"//:zone.js",
"//:core",
"//:common",
"//:compiler",
"//:platform-browser",
"//:platform-browser-dynamic",
],
tsconfig = "modules/@angular/platform-server/tsconfig-es5.json",
module_name = "@angular/platform-server",
)
ts_library(
name = "platform-server_test_module",
srcs = glob(["modules/@angular/platform-server/test/**/*.ts"]),
deps = [
"//:_types_node",
"//:_types_jasmine",
"//:zone.js",
"//:core",
"//:platform-browser",
"//:platform-browser-dynamic",
"//:platform-server",
"//:facade",
],
deps_use_internal = [
"//:platform-server",
],
tsconfig = "modules/tsconfig.json",
root_dir = "modules/@angular/platform-server/test",
is_leaf = True,
)
ts_library(
name = "router",
srcs = glob(
["modules/@angular/router/**/*.ts"],
exclude = ["modules/@angular/router/test/**/*.ts"]),
deps = [
"//:_types_node",
"//:_types_jasmine",
"//:zone.js",
"//:core",
"//:common",
"//:compiler",
"//:platform-browser",
"//:platform-browser-dynamic",
],
tsconfig = "modules/@angular/router/tsconfig-es5.json",
module_name = "@angular/router",
)
ts_library(
name = "router_test_module",
srcs = glob(["modules/@angular/router/test/**/*.ts"]),
deps = [
"//:_types_node",
"//:_types_jasmine",
"//:zone.js",
"//:core",
"//:common",
"//:router",
"//:platform-browser",
"//:facade",
],
deps_use_internal = [
"//:router",
],
tsconfig = "modules/tsconfig.json",
root_dir = "modules/@angular/router/test",
is_leaf = True,
)
ts_library(
name = "upgrade",
srcs = glob(
["modules/@angular/upgrade/**/*.ts"],
exclude = ["modules/@angular/upgrade/test/**/*.ts"]),
deps = [
"//:zone.js",
"//:core",
"//:common",
"//:compiler",
"//:platform-browser",
"//:platform-browser-dynamic",
],
tsconfig = "modules/@angular/upgrade/tsconfig-es5.json",
module_name = "@angular/upgrade",
)
ts_library(
name = "upgrade_test_module",
srcs = glob(["modules/@angular/upgrade/test/**/*.ts"]),
deps = [
"//:_types_node",
"//:_types_jasmine",
"//:zone.js",
"//:core",
"//:platform-browser",
"//:upgrade",
"//:facade",
],
deps_use_internal = [
"//:upgrade",
],
tsconfig = "modules/tsconfig.json",
root_dir = "modules/@angular/upgrade/test",
is_leaf = True,
)
jasmine_node_test(
name = "compiler_test",
srcs = [":compiler_test_module", ":compiler_test_codegen_js"],
helpers = [":jasmine_helper"],
size = "small",
args = ["--node_path=modules:tools"],
)
JASMINE_TESTABLE = [
"core",
"common",
"compiler",
"compiler-cli",
"http",
"platform-server",
"router",
]
[
jasmine_node_test(
name = pkg + "_test",
srcs = [":{}_test_module".format(pkg)],
helpers = [":jasmine_helper"],
size = "small",
args = ["--node_path=modules:tools"],
flaky = pkg == "platform-server",
)
for pkg in JASMINE_TESTABLE
if pkg != "compiler"
]
test_suite(
name = "jasmine_tests",
tests = [":{}_test".format(p) for p in JASMINE_TESTABLE],
)
ts_library(
name = "empty_module",
srcs = ["modules/empty.ts"],
tsconfig = "modules/tsconfig.json",
)
KARMA_DATA = [
":es6-shim",
":karma-browserstack-launcher",
":karma-chrome-launcher",
":karma-jasmine",
":karma-sauce-launcher",
":karma-sourcemap-loader",
":reflect-metadata",
":source-map",
":systemjs",
]
karma_test(
name = "karma_test",
srcs = [
":core_test_module",
":common_test_module",
":compiler_test_module",
":compiler_test_codegen_js",
":forms_test_module",
":http_test_module",
":platform-browser_test_module",
":platform-browser-dynamic_test_module",
":platform-server_test_module",
":upgrade_test_module",
":empty_module",
"shims_for_IE.js",
"test-main.js",
],
data = KARMA_DATA + [
":angular",
"browser-providers.conf.js",
"tools/karma/reporter.js",
"tools/karma/ibazel_watcher.js",
],
config = "karma-js.conf.js",
local = True,
)
karma_test(
name = "router_karma_test",
srcs = [
":router_test_module",
"modules/@angular/router/karma-test-shim.js",
],
data = KARMA_DATA + [
"browser-providers.conf.js",
"tools/karma/ibazel_watcher.js",
],
config = "modules/@angular/router/karma.conf.js",
size = "small",
local = True,
)
###############################################################################
# Packaging and end to end tests
###############################################################################
ESM_PACKAGES = [
"core",
"common",
"compiler",
"forms",
"http",
"platform-browser",
"platform-browser-dynamic",
"platform-server",
"router",
"upgrade",
]
NON_ESM_PACKAGES = [
"compiler-cli",
]
ALL_PACKAGES = ESM_PACKAGES + NON_ESM_PACKAGES + ["tsc-wrapped"]
[
js_bundle(
name = pkg + "_bundle",
srcs = [":" + pkg],
output = "modules/@angular/{}/dist/index.js".format(pkg, pkg),
entry_point = "modules/@angular/{}/esm/index.js".format(pkg),
rollup_config = "modules/@angular/{}/rollup.config.js".format(pkg),
banner = "modules/@angular/license-banner.txt",
)
for pkg in ESM_PACKAGES
]
ts_npm_package(
name = "tsc-wrapped_package",
srcs = [":tsc-wrapped"],
manifest = "tools/@angular/tsc-wrapped/package.json",
module_name = "@angular/tsc-wrapped",
strip_prefix = "/tools/@angular/tsc-wrapped/dist",
esm = False,
)
[
ts_npm_package(
name = pkg + "_package",
srcs = [":{}".format(pkg)],
data = [":{}_bundle".format(pkg)] if pkg in ESM_PACKAGES else [],
manifest = "modules/@angular/{}/package.json".format(pkg),
module_name = "@angular/" + pkg,
# Prefix / avoids bug https://github.com/bazelbuild/bazel/issues/1604
strip_prefix = "/modules/@angular/{}/dist".format(pkg),
esm = pkg in ESM_PACKAGES,
)
for pkg in ESM_PACKAGES + NON_ESM_PACKAGES
]
filegroup(
name = "all_packages",
srcs = [":{}_package".format(p) for p in ALL_PACKAGES],
)
ts_library(
name = "playground",
srcs = glob(["modules/playground/src/**/*.ts"]),
deps = [
"//:core",
"//:common",
"//:forms",
"//:http",
"//:platform-browser",
"//:platform-browser-dynamic",
"//:router",
"//:upgrade",
"//:facade",
],
data = glob(
["modules/playground/src/**/*"],
exclude = ["modules/playground/src/**/*.ts"],
),
tsconfig = "modules/tsconfig.json",
)
ts_library(
name = "e2e_util",
srcs = glob(["modules/e2e_util/**/*.ts"]),
deps = [
"//:_types_node",
"//:_types_protractor",
"//:_types_selenium-webdriver",
],
tsconfig = "modules/tsconfig.json",
root_dir = "modules/e2e_util",
module_name = "e2e_util",
)
ts_library(
name = "playground_test_module",
srcs = glob(["modules/playground/e2e_test/**/*.ts"]),
deps = [
"//:_types_jasmine",
"//:e2e_util",
],
tsconfig = "modules/tsconfig.json",
is_leaf = True,
)
protractor_test(
name = "playground_test",
srcs = [":playground_test_module"],
data = [":{}_bundle".format(p) for p in ESM_PACKAGES] + [
":core", # Needed for @angular/core/src/facade
":facade",
":playground",
":core-js",
":zone.js",
":systemjs",
":base64-js",
":reflect-metadata",
":rxjs",
":angular",
"favicon.ico",
],
config = "protractor-bazel.conf.js",
local = True,
args = ["--node_path=modules:tools"],
)
public_api(
name = "public_api",
srcs = [
":core_compat",
":common_compat",
":platform-browser_compat",
":platform-browser-dynamic_compat",
":platform-server_compat",
":http_compat",
":forms_compat",
":router_compat",
":upgrade_compat",
],
entry_points = [
"modules/@angular/core/compat/index.d.ts",
"modules/@angular/core/compat/testing.d.ts",
"modules/@angular/common/compat/index.d.ts",
"modules/@angular/common/compat/testing.d.ts",
"modules/@angular/upgrade/compat/index.d.ts",
"modules/@angular/platform-browser/compat/index.d.ts",
"modules/@angular/platform-browser/compat/testing.d.ts",
"modules/@angular/platform-browser-dynamic/compat/index.d.ts",
"modules/@angular/platform-browser-dynamic/compat/testing.d.ts",
"modules/@angular/platform-server/compat/index.d.ts",
"modules/@angular/platform-server/compat/testing.d.ts",
"modules/@angular/http/compat/index.d.ts",
"modules/@angular/http/compat/testing.d.ts",
"modules/@angular/forms/compat/index.d.ts",
"modules/@angular/router/compat/index.d.ts",
],
root_dir = "modules/@angular",
out_dir = "tools/public_api_guard",
arguments = [
"--stripExportPattern ^__",
"--allowModuleIdentifiers jasmine",
"--allowModuleIdentifiers protractor",
"--allowModuleIdentifiers angular",
"--onStabilityMissing error",
],
)
public_api_test(
name = "public_api_test",
srcs = glob(["tools/public_api_guard/**/*"]),
public_api = ":public_api",
size = "small",
)
nodejs_test(
name = "check_cycle_test",
srcs = [
"//build_defs:check_cycle.js",
],
deps = [
":madge",
],
entry_point = "check_cycle.js",
data = [
":core",
":common",
":compiler",
":compiler-cli",
":forms",
":http",
":platform-browser",
":platform-browser-dynamic",
":platform-server",
":router",
":upgrade",
":tsc-wrapped",
],
size = "small",
)
sh_test(
name = "offline_compiler_test",
srcs = ["scripts/ci-lite/offline_compiler_test.sh"],
data = [
"//:all_packages",
"package.json",
] + glob(["modules/@angular/compiler-cli/integrationtest/**"]),
# This currently uses external npm, so we need an unsandboxed environment.
# If your npm is not in the standard PATH, you will also need to pass the
# flag --test_env=PATH to "bazel test".
local = True,
)

View File

@ -27,7 +27,9 @@ following products on your development machine:
source or as a pre-packaged bundle.
* [Java Development Kit](http://www.oracle.com/technetwork/es/java/javase/downloads/index.html) which is used
to execute the selenium standalone server for e2e testing.
to run Bazel and execute the selenium standalone server for e2e testing. JDK version 8 is required.
* [Bazel](https://bazel.io) is used to build and test Angular packages.
## Getting the Sources
@ -59,21 +61,6 @@ Next, install the JavaScript modules needed to build and test Angular:
npm install
```
**Optional**: In this document, we make use of project local `npm` package scripts and binaries
(stored under `./node_modules/.bin`) by prefixing these command invocations with `$(npm bin)`; in
particular `gulp` and `protractor` commands. If you prefer, you can drop this path prefix by either:
*Option 1*: globally installing these two packages as follows:
* `npm install -g gulp` (you might need to prefix this command with `sudo`)
* `npm install -g protractor` (you might need to prefix this command with `sudo`)
Since global installs can become stale, and required versions can vary by project, we avoid their
use in these instructions.
*Option 2*: defining a bash alias like `alias nbin='PATH=$(npm bin):$PATH'` as detailed in this
[Stackoverflow answer](http://stackoverflow.com/questions/9679932/how-to-use-package-installed-locally-in-node-modules/15157360#15157360) and used like this: e.g., `nbin gulp build`.
## Windows only
In order to create the right symlinks, run **as administrator**:
@ -91,26 +78,34 @@ Before submitting a PR, do not forget to remove them:
To build Angular run:
```shell
./build.sh
bazel build :all_packages
```
* Results are put in the dist folder.
To build individual modules, use `:<package_name>_package`, e.g.
`:core_package`.
* The npm build artifacts are put in the bazel-bin/ folder as tarballs.
## Running Tests Locally
To run tests:
```shell
$ ./test.sh node # Run all angular tests on node
$ bazel test :jasmine_tests # Run all angular tests on node
$ ./test.sh browser # Run all angular tests in browser
$ ./test.sh browserNoRouter # Optionally run all angular tests without router in browser
$ bazel test :karma_test # Run all angular tests except router in browser
$ bazel test :router_karma_test # Run angular router tests in browser
$ ./test.sh tools # Run angular tooling (not framework) tests
# If you are on Linux, you will need to add `--test_env=DISPLAY` at the end of the Bazel command so that
# Chrome will be able to launch successfully. For example:
$ bazel test :karma_test --test_env=DISPLAY
# Alternatively, use `bazel run` instead:
$ bazel run :karma_test
```
You should execute the 3 test suites before submitting a PR to github.
You should execute the 2 test suites before submitting a PR to github.
All the tests are executed on our Continuous Integration infrastructure and a PR could only be merged once the tests pass.
- CircleCI fails if your code is not formatted properly,
@ -121,10 +116,10 @@ All the tests are executed on our Continuous Integration infrastructure and a PR
If you happen to modify the public API of Angular, API golden files must be updated using:
``` shell
$ gulp public-api:update
$ bazel run :public_api
```
Note: The command `./test.sh tools` fails when the API doesn't match the golden files.
Note: The command `bazel test :public_api_test` fails when the API doesn't match the golden files.
## Formatting your source code
@ -137,4 +132,30 @@ You can automatically format your code by running:
$ gulp format
```
## Incremental development
To watch files and automatically rebuild, use `./ibazel` instead of the `bazel` command. For example:
``` shell
$ ./ibazel build :core # Automatically recompiles core in ES5
$ ./ibazel build :jasmine_tests # Automatically reruns all tests on node
```
To debug tests:
``` shell
$ ./bazel-run.sh run :core_test --node_options=debug
# Runs the core test suite in `node debug`
$ ./ibazel run :karma_test_local # Runs karma in watch mode
$ ./ibazel run :router_karma_test_local
$ ./ibazel run :playground_test -- --serve-only
# Runs the development server for e2e tests
```
* `./bazel-run.sh` is a variant of `bazel run` that connects stdin, and can be used for running
node in debug mode.
See [Bazel README](https://github.com/angular/angular/blob/master/build_defs/README.md) for inner workings
of the build system.

7
WORKSPACE Normal file
View File

@ -0,0 +1,7 @@
workspace(name="angular")
load("//build_defs:nodejs_workspace.bzl", "nodejs_workspace")
nodejs_workspace(
name = "nodejs",
)

49
bazel-run.sh Executable file
View File

@ -0,0 +1,49 @@
#!/bin/bash
# Copied from https://github.com/bazelbuild/bazel/blob/master/scripts/bazel-run.sh
#
# Copyright 2016 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.
#
USAGE='bazel-run.sh [<bazel option>...] <target> [ -- [<target option>]... ]'
DESCRIPTION='
Builds and runs the command generated by "bazel run" in the calling
terminal. The command is run as a grandchild of the current shell,
not from the Bazel server. Therefore, the program will have a controlling terminal, and
the Bazel lock is released before running the command.'
function usage() {
echo "$USAGE" "$DESCRIPTION" >&2
}
function die() {
echo "$1"
exit 1
}
function cleanup() {
rm "$runcmd"
}
[ $# -gt 0 ] || { usage; exit 1; }
runcmd="$(mktemp /tmp/bazel-run.XXXXXX)" || die "Could not create tmp file"
trap "cleanup" EXIT
bazel run --script_path="$runcmd" "$@" || exit $?
[ -x "$runcmd" ] || die "File $runcmd not executable"
"$runcmd"

9
build_defs/BUILD Normal file
View File

@ -0,0 +1,9 @@
exports_files([
"nodejs_launcher_template.sh",
"jasmine_launcher_template.sh",
"karma_launcher_template.sh",
"rollup_config_template.js",
"protractor_launcher_template.sh",
"ts_api_guardian_launcher_template.sh",
"check_cycle.js",
])

126
build_defs/bundle.bzl Normal file
View File

@ -0,0 +1,126 @@
load("//build_defs:utils.bzl", "join_paths", "pick_file")
def _js_bundle_impl(ctx):
"""
Rule for creating a minified bundle for JavaScript web libraries. This
includes tree-shaking with Rollup.js, down-transpiling to ES5 with TypeScript,
and minifying with UglifyJS.
Args:
srcs: Target containing the source library.
deps: JavaScript targets which the tests depend on.
rollup_config: Required. Rollup.js config file to use.
entry_point: Path to the entrypoint file for tree-shaking, relative to
the package. The entry_point should be inside the first "srcs" target.
output: Filename of the gen .js file, relative to the package. For
example, if you specify bundle.js, bundle.js and bundle.min.js will be
created.
banner: File to prepend to the gen files. Useful for e.g. copyright
banners.
"""
output = (ctx.attr.output or ctx.label.name + ".js")
output_base = output[:output.rfind(".")]
# gen_esm_js = ctx.new_file(output_base + ".esm.js")
# gen_esm_js_map = ctx.new_file(output_base + ".esm.js.map")
gen_js = ctx.new_file(output_base + ".js")
gen_js_map = ctx.new_file(output_base + ".js.map")
gen_min_js = ctx.new_file(output_base + ".min.js")
gen_min_js_map = ctx.new_file(output_base + ".min.js.map")
config_file = ctx.new_file("%s_rollup.config.js" % ctx.label.name)
config_to_workspace = "/".join(
[".." for x in ctx.configuration.bin_dir.path.split("/") if x] +
[".." for x in ctx.label.package.split("/") if x])
esm_inputs = []
for src in ctx.attr.srcs:
esm_inputs += src.javascript_esm.files + src.javascript_esm.source_maps
main_src = ctx.attr.srcs[0]
entry_point = pick_file(esm_inputs, main_src.label, ctx.attr.entry_point)
ctx.template_action(
template = ctx.file._rollup_config_template,
output = config_file,
substitutions = {
"{{base_config}}": join_paths(config_to_workspace, ctx.file.rollup_config.path),
# Unlike tsc, rollup does not resolve paths relative to
# rollup.config.js.
"{{prefixes}}": "\"\", \"{}\", \"{}\"".format(
ctx.configuration.bin_dir.path, ctx.configuration.genfiles_dir.path),
"{{entry}}": "./" + entry_point.path,
"{{dest}}": gen_js.path,
"{{banner}}": (ctx.file.banner.path if ctx.attr.banner else ""),
},
)
ctx.action(
progress_message = "Tree shaking %s" % ctx,
inputs = esm_inputs + ctx.files.rollup_config + ctx.files.banner + [config_file],
outputs = [gen_js, gen_js_map],
executable = ctx.executable._rollup,
arguments = ["-c", config_file.path],
)
# tsc_cmd = [ctx.executable._tsc.path, "--noResolve", "--target", "es5", "--allowJs", "--typeRoots",
# "[]", "--sourceMap", "--inlineSources", "--outFile", gen_js.path, gen_esm_js.path]
# ctx.action(
# progress_message = "Compiling ES6 %s" % ctx,
# inputs = [gen_esm_js, gen_esm_js_map] + list(ctx.attr._tsc.default_runfiles.files),
# outputs = [gen_js, gen_js_map],
# executable = ctx.executable._flatten_sourcemap,
# arguments = [gen_js.path, "--"] + tsc_cmd,
# )
ctx.action(
progress_message = "Minifying bundle of %s" % ctx,
inputs = [gen_js, gen_js_map] + ctx.files.banner,
outputs = [gen_min_js, gen_min_js_map],
executable = ctx.executable._uglifyjs,
arguments = (
(["--preamble-file", ctx.file.banner.path] if ctx.attr.banner else []) +
["--compress", "--screw-ie8", "--in-source-map", gen_js_map.path,
"--source-map-include-sources", "--output", gen_min_js.path, "--source-map-url",
gen_min_js_map.basename, "--source-map", gen_min_js_map.path, gen_js.path]
),
)
files = [gen_js, gen_js_map, gen_min_js, gen_min_js_map]
return struct(
files = set(files),
runfiles = ctx.runfiles(
files = files,
# TODO: Investigate why setting collect_data = True will serve the
# source *.js files.
collect_data = False,
collect_default = False,
),
)
js_bundle = rule(
implementation = _js_bundle_impl,
attrs = {
"srcs": attr.label_list(allow_files=True, mandatory=True),
"deps": attr.label_list(),
"rollup_config": attr.label(allow_files=True, single_file=True, mandatory=True),
"entry_point": attr.string(default="index.js"),
"output": attr.string(),
"banner": attr.label(allow_files=True, single_file=True),
"_rollup": attr.label(default=Label("//:rollup_bin"), executable=True),
"_uglifyjs": attr.label(
default=Label("//build_defs/tools:uglifyjs_wrapped"), executable=True),
"_tsc": attr.label(default=Label("//:tsc_bin"), executable=True),
"_flatten_sourcemap": attr.label(
default=Label("//build_defs/tools:flatten_sourcemap"), executable=True),
"_rollup_config_template": attr.label(
default = Label("//build_defs:rollup_config_template.js"),
allow_files = True,
single_file = True,
),
},
)

16
build_defs/check_cycle.js Normal file
View File

@ -0,0 +1,16 @@
'use strict';
const madge = require('madge');
const dependencyObject = madge([process.env.RUNFILES + '/modules/'], {
format: 'cjs',
extensions: ['.js'],
onParseFile: function(data) { data.src = data.src.replace(/\/\* circular \*\//g, '//'); }
});
const circularDependencies = dependencyObject.circular().getArray();
if (circularDependencies.length > 0) {
console.log('Found circular dependencies!');
console.log(circularDependencies);
process.exit(1);
}

69
build_defs/jasmine.bzl Normal file
View File

@ -0,0 +1,69 @@
load("//build_defs:utils.bzl", "pseudo_json_encode")
def _jasmine_node_test_impl(ctx):
"""
Rule for running Jasmine tests on NodeJS.
Args:
srcs: The targets containing the spec files.
deps: JavaScript targets which the tests depend on.
data: Data files which the tests depend on.
helpers: List of JavaScript targets to be loaded as helpers.
"""
# This rule works by creating a Jasmine config file with a list of helper and
# spec files, then creating a launcher shell script that runs Jasmine CLI with
# the said config file.
config_file = ctx.new_file("%s_jasmine.json" % ctx.label.name)
ctx.file_action(
output = config_file,
content = pseudo_json_encode({
"spec_dir": ".",
"spec_files": [f.short_path for f in ctx.files.srcs if f.short_path.endswith(".js")],
"helpers": [f.short_path for f in ctx.files.helpers if f.short_path.endswith(".js")],
}),
)
ctx.template_action(
template = ctx.file._launcher_template,
output = ctx.outputs.executable,
substitutions = {
"{{jasmine}}": ctx.executable._jasmine.short_path,
"{{config}}": config_file.short_path,
},
executable = True,
)
transitive_files = set(ctx.attr._jasmine.default_runfiles.files)
for helper in ctx.attr.helpers:
transitive_files += set(helper.default_runfiles.files)
return struct(
files = set([ctx.outputs.executable]),
runfiles = ctx.runfiles(
files = ctx.files.srcs + ctx.files._jasmine + [config_file] + ctx.files.helpers,
transitive_files = transitive_files,
collect_data = True,
collect_default = True,
),
)
jasmine_node_test = rule(
implementation = _jasmine_node_test_impl,
executable = True,
test = True,
attrs = {
"srcs": attr.label_list(allow_files=True),
"deps": attr.label_list(),
"data": attr.label_list(allow_files=True, cfg=DATA_CFG),
"helpers": attr.label_list(default=[], allow_files=True),
"_jasmine": attr.label(default=Label("//:jasmine_bin"), executable=True),
"_launcher_template": attr.label(
default = Label("//build_defs:jasmine_launcher_template.sh"),
allow_files = True,
single_file = True,
),
},
)

View File

@ -0,0 +1,21 @@
#!/usr/bin/env bash
set -e
if [[ -z "${RUNFILES}" ]]; then
case "${0}" in
/*) self="${0}" ;;
*) self="${PWD}/${0}" ;;
esac
if [[ -n "${TEST_SRCDIR}" ]]; then
export RUNFILES="${TEST_SRCDIR}/angular"
elif [[ -d "${self}.runfiles" ]]; then
export RUNFILES="${self}.runfiles/angular"
else
echo "Runfiles directory not found." >&2
exit 1
fi
fi
cd "${RUNFILES}" && "${RUNFILES}/{{jasmine}}" --color "JASMINE_CONFIG_PATH=${RUNFILES}/{{config}}" "$@"

75
build_defs/karma.bzl Normal file
View File

@ -0,0 +1,75 @@
_KARMA_TEST_ATTRS = {
"srcs": attr.label_list(allow_files=True),
"deps": attr.label_list(),
"data": attr.label_list(allow_files=True, cfg=DATA_CFG),
"config": attr.label(allow_files=True, single_file=True, mandatory=True),
"_karma": attr.label(default=Label("//:karma_bin"), executable=True),
"_launcher_template": attr.label(
default = Label("//build_defs:karma_launcher_template.sh"),
allow_files = True,
single_file = True,
),
}
def _karma_test_impl(ctx, karma_args="--single-run"):
"""
Rule for running Karma tests.
Args:
srcs: The targets containing the spec files.
deps: JavaScript targets which the tests depend on.
data: Data files which the tests depend on.
config: Required. Karma config file to use.
Due to the complexity of Karma config files, this rule does not do the heavy
lifting of creating that config file. Instead, the user has to point to the
right files. Files specified in Karma must be a subset of files depended upon
in the karma_test definition.
This rule additionally creates a <name>_local target, which runs Karma in
watch mode. This can be combined with ibazel for incremental development.
"""
ctx.template_action(
template = ctx.file._launcher_template,
output = ctx.outputs.executable,
substitutions = {
"{{karma}}": ctx.executable._karma.short_path,
"{{config}}": ctx.file.config.short_path,
"{{args}}": karma_args,
},
executable = True,
)
return struct(
files = set([ctx.outputs.executable]),
runfiles = ctx.runfiles(
files = ctx.files.srcs + ctx.files._karma + ctx.files.config,
transitive_files = set(ctx.attr._karma.default_runfiles.files),
collect_data = True,
collect_default = True,
),
)
_karma_test = rule(
implementation = _karma_test_impl,
executable = True,
test = True,
attrs = _KARMA_TEST_ATTRS,
)
def _karma_test_local_impl(ctx):
return _karma_test_impl(ctx, karma_args = "")
_karma_test_local = rule(
implementation = _karma_test_local_impl,
executable = True,
attrs = _KARMA_TEST_ATTRS,
)
def karma_test(*, name, timeout=None, size=None, flaky=None, shard_count=None, local=None,
tags=None, **kwargs):
tags = tags or []
_karma_test(name=name, timeout=timeout, size=size, flaky=flaky, shard_count=shard_count,
local=local, tags=tags, **kwargs)
_karma_test_local(name=name + "_local", tags=tags + ["ibazel_notify_changes"], **kwargs)

View File

@ -0,0 +1,21 @@
#!/usr/bin/env bash
set -e
if [[ -z "${RUNFILES}" ]]; then
case "${0}" in
/*) self="${0}" ;;
*) self="${PWD}/${0}" ;;
esac
if [[ -n "${TEST_SRCDIR}" ]]; then
export RUNFILES="${TEST_SRCDIR}/angular"
elif [[ -d "${self}.runfiles" ]]; then
export RUNFILES="${self}.runfiles/angular"
else
echo "Runfiles directory not found." >&2
exit 1
fi
fi
cd "${RUNFILES}" && "${RUNFILES}/{{karma}}" start "${RUNFILES}/{{config}}" {{args}} "$@"

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,221 @@
#!/usr/bin/env node
'use strict';
const fs = require('fs');
const path = require('path');
function printUsageAndExit() {
console.error(`Usage: ${process.argv[0]} ${process.argv[1]}
<package root location> [output file] [--verify]
For each dependency in package.json, resolve the dependencies required by that
package and serialize the dependency graph into a Bazel macro using
nodejs_module, nodejs_binary and ts_ext_library.`);
process.exit(1);
}
function main() {
const root = process.argv[2];
if (!root) {
printUsageAndExit();
}
const nodeModules = path.join(root, 'node_modules');
const packageJson = JSON.parse(fs.readFileSync(path.join(root, 'package.json')));
// Only create targets for direct dependencies
const targets =
Object.keys(readDependencies(packageJson, ['dependencies', 'devDependencies'])).sort();
const packages = traceNodeModules(nodeModules);
const packageMap = {};
for (const pkg of packages) {
packageMap[pkg] = tracePackage(path.join(nodeModules, pkg));
}
const targetDefs = targets.map(target => {
// Find out the set of dependencies and classify them into targets (deps)
// and non-targets (srcs)
return {
name: target,
srcs: Object.keys(collectSrcs(target)).sort().map(src => 'node_modules/' + src),
deps: Object.keys(packageMap[target].deps).sort().filter(dep => targets.indexOf(dep) !== -1),
typings: packageMap[target].typings,
};
});
let output = `load("//build_defs:nodejs.bzl", "nodejs_module", "nodejs_binary")
load("//build_defs:typescript.bzl", "ts_ext_library")
def node_modules_index(glob):
`;
for (const def of targetDefs) {
let fn;
const args = {
name: `"${escapeName(def.name)}"`,
srcs: `[${def.srcs.map(src => `"${src}"`).join(', ')}]`,
};
if (!def.typings) {
fn = 'nodejs_module';
args.deps = `[${def.deps.map(dep => `":${escapeName(dep)}"`).join(', ')}]`;
} else {
fn = 'ts_ext_library';
// ts_ext_library "deps" must be typescript targets
// make the non-typescript targets put in "data"
const tsDeps = def.deps.filter(dep => !!dep.typings);
const nodeDeps = def.deps.filter(dep => !dep.typings);
args.deps = `[${tsDeps.map(dep => `":${escapeName(dep)}"`).join(', ')}]`;
args.data = `[${nodeDeps.map(dep => `":${escapeName(dep)}"`).join(', ')}]`;
args.declarations = `glob(["${path.join('node_modules', def.name, '**/*.d.ts')}"])`;
args.ambient = def.typings.ambient ? 'True' : 'False';
args.entry_point = `"${path.join('node_modules', def.name, def.typings.path)}"`;
args.root_dir = `"${path.join('node_modules', def.name)}"`;
}
output += ` ${fn}(${Object.keys(args).map(k => `${k}=${args[k]}`).join(', ')})\n`;
}
let binaries = [];
let nodeBinDir = path.join(nodeModules, '.bin');
try {
binaries = fs.readdirSync(nodeBinDir);
} catch (err) {
}
for (const name of binaries) {
let link;
try {
link = fs.readlinkSync(path.join(nodeBinDir, name));
} catch (err) {
}
if (link) {
// For each binary found, check if the binary is from a direct
// dependency
// If so, create a nodejs_binary target for that, pointing to the actual
// entrypoint file.
const executable = path.join(nodeBinDir, link);
const pkg = path.relative(nodeModules, executable).split(path.sep)[0];
const executableInPackage = path.relative(path.join(nodeModules, pkg), executable);
if (targets.indexOf(pkg) !== -1) {
const args = {
name: `"${escapeName(name)}_bin"`,
srcs: `[":${escapeName(pkg)}"]`,
entry_point: `"${path.join('node_modules', pkg, executableInPackage)}"`
};
output += ` nodejs_binary(${Object.keys(args).map(k => `${k}=${args[k]}`).join(', ')})\n`;
}
}
}
if (process.argv[3]) {
if (process.argv[4] === '--verify') {
if (fs.readFileSync(process.argv[3]).toString() !== output) {
console.error(
`Error: ${process.argv[3]} is outdated. Please run:\n\n` +
process.argv.slice(0, 4).join(' '));
process.exit(1);
}
} else {
fs.writeFileSync(process.argv[3], output);
}
} else {
process.stdout.write(output);
}
function collectSrcs(target, visited) {
const isFirst = !visited;
visited = visited || {};
return Object
.keys(packageMap[target].deps)
// If the package is a target,
// a) it is a direct dependency: ignore it since it will be in "deps"
// b) otherwise: collect its dependencies to "srcs" too
.filter(dep => (!isFirst || targets.indexOf(dep) === -1) && !visited.hasOwnProperty(target))
.map(dep => collectSrcs(dep, Object.assign({[target]: true}, visited)))
.reduce((a, b) => Object.assign(a, b), {[target]: true});
}
}
function traceNodeModules(nodeModules) {
const packages = [];
for (const dir of fs.readdirSync(nodeModules)) {
if (dir[0] === '@') {
for (const subdir of fs.readdirSync(path.join(nodeModules, dir))) {
const pkg = dir + '/' + subdir;
if (fs.statSync(path.join(nodeModules, pkg)).isDirectory()) {
packages.push(pkg);
}
}
} else {
if (fs.statSync(path.join(nodeModules, dir)).isDirectory()) {
packages.push(dir);
}
}
}
return packages;
}
/**
* Finds the "external" dependencies given the package directory.
* External means that it is from outside of the package directory.
*/
function tracePackage(packageDir) {
let packageJson;
try {
packageJson = JSON.parse(fs.readFileSync(path.join(packageDir, 'package.json')));
} catch (err) {
}
if (packageJson) {
const deps = readDependencies(packageJson);
const internalNodeModules = path.join(packageDir, 'node_modules');
const internalDeps =
fs.existsSync(internalNodeModules) ? traceNodeModules(internalNodeModules) : [];
for (const dep of internalDeps) {
Object.assign(deps, tracePackage(path.join(internalNodeModules, dep)).deps);
}
for (const dep of internalDeps) {
delete deps[dep];
}
let typings = null;
let typingsPath;
// Collect d.ts file info if "typings" or "types" is defined
if (typeof packageJson.typings === 'string') typingsPath = packageJson.typings;
else if (typeof packageJson.types === 'string') typingsPath = packageJson.types;
if (typingsPath) {
if (!typingsPath.match(/\.ts$/)) {
typingsPath += '.d.ts';
}
// Apply the heuristic that anything in @types is ambient
const looksAmbient = packageDir.indexOf('/@types/') !== -1;
// Remove the ./ prefix with normalize
typings = {path: path.normalize(typingsPath), ambient: looksAmbient};
}
return {deps: deps, typings: typings};
} else {
// Assume no deps if package.json does not exist / is malformed
return {deps: {}, typings: null};
}
}
function readDependencies(packageJson, types) {
types = types || ['dependencies', 'optionalDependencies', 'peerDependencies'];
return types.map(type => packageJson[type]).reduce((a, b) => Object.assign(a, b), {});
}
function escapeName(name) {
return name.replace(/@|!/g, '_').replace(/\//g, '_');
}
main();

128
build_defs/nodejs.bzl Normal file
View File

@ -0,0 +1,128 @@
load("//build_defs:utils.bzl", "join_paths", "pick_file_in_dir")
_NODEJS_MODULE_ATTRS = {
"srcs": attr.label_list(allow_files=True, mandatory=True, cfg=DATA_CFG),
"deps": attr.label_list(providers=["nodejs"], cfg=DATA_CFG),
"data": attr.label_list(allow_files=True, cfg=DATA_CFG),
}
_NODEJS_EXECUTABLE_ATTRS = _NODEJS_MODULE_ATTRS + {
"entry_point": attr.string(mandatory=True),
"_nodejs": attr.label(
default = Label("@nodejs//:nodejs"),
allow_files = True,
executable = True,
),
"_launcher_template": attr.label(
default = Label("//build_defs:nodejs_launcher_template.sh"),
allow_files = True,
single_file = True,
),
}
def _nodejs_module_impl(ctx):
"""nodejs_module
Rule for defining a Node.js module.
Args:
srcs: Required. A list of source files that make up the module. The general
assumption is that this should be CommonJS files that can run directly on
Node.js.
deps: A list of Node.js modules that this module depends on.
Unfortunately, since we do not patch require() currently, the Node.js rules
cannot do anything to ensure that modules are resolved at runtime.
The Node.js wrapper, however, provides these command line arguments:
--node_options=--foo_option=bar
Passes --foo_option=bar to Node.js as startup options.
--node_path=path/to/foo:path/to/bar
Adds the specified paths to NODE_PATH after resolving them relative to
runfiles.
You can use them with the "args" kwarg in any Node.js-based target. A
convenient option is --node_options=debug, which launches the target in a
debugger. Note that however, you have to use `bazel-run.sh` to do that in
order to connect stdin.
Note that Node.js resolves symlinks when loading modules, which is wrong in
our bazel environment, since it resolves symlinks that may cross the runfiles
boundary. We may be able to use the Node.js flag "--preserve-symlinks"
introduced in Node.js 6.2. See https://github.com/nodejs/node/pull/6537
"""
return struct(
files = set(ctx.files.srcs),
runfiles = ctx.runfiles(
files = ctx.files.srcs,
collect_data = True,
collect_default = True,
),
nodejs = struct(),
javascript = struct(
files = ctx.files.srcs,
),
)
nodejs_module = rule(
implementation = _nodejs_module_impl,
attrs = _NODEJS_MODULE_ATTRS,
)
def _nodejs_binary_impl(ctx):
"""nodejs_binary
Rule for defining a Node.js binary. This creates an executable version of
a Node.js module.
Args:
srcs: Required. A list of source files that make up the module.
deps: A list of Node.js modules that this module depends on.
data: A list of extra files or targets to include in runfiles.
entry_point: The main JavaScript file to run. This is resolved relative to
the package of the first "srcs" target.
"""
main_src = ctx.attr.srcs[0]
entry_point_file, entry_point_relative_path = pick_file_in_dir(
main_src.files, main_src.label, ctx.attr.entry_point)
ctx.template_action(
template = ctx.file._launcher_template,
output = ctx.outputs.executable,
substitutions = {
"{{nodejs}}": ctx.executable._nodejs.short_path,
"{{entry_point}}": join_paths(entry_point_file.short_path, entry_point_relative_path),
},
executable = True,
)
return struct(
files = set([ctx.outputs.executable]),
runfiles = ctx.runfiles(
files = ctx.files.srcs + ctx.files._nodejs,
collect_data = True,
collect_default = True,
),
nodejs = struct(),
javascript = struct(
files = ctx.files.srcs,
),
)
nodejs_binary = rule(
implementation = _nodejs_binary_impl,
executable = True,
attrs = _NODEJS_EXECUTABLE_ATTRS,
)
"""nodejs_test
A variant of nodejs_binary with "test=True".
"""
nodejs_test = rule(
implementation = _nodejs_binary_impl,
test = True,
attrs = _NODEJS_EXECUTABLE_ATTRS,
)

View File

@ -0,0 +1,42 @@
#!/usr/bin/env bash
set -e
if [[ -z "${RUNFILES}" ]]; then
case "${0}" in
/*) self="${0}" ;;
*) self="${PWD}/${0}" ;;
esac
if [[ -n "${TEST_SRCDIR}" ]]; then
export RUNFILES="${TEST_SRCDIR}/angular"
elif [[ -d "${self}.runfiles" ]]; then
export RUNFILES="${self}.runfiles/angular"
else
echo "Runfiles directory not found." >&2
exit 1
fi
fi
# Parse Node.js startup options and our runfiles-relative NODE_PATH option
args=()
node_options=()
runfiles_node_path=()
for arg in "$@"; do
case "${arg}" in
--node_options=*)
node_options+=( "${arg#--node_options=}" )
;;
--node_path=*)
runfiles_node_path=( $(IFS=":"; echo ${arg#--node_path=}) )
;;
*)
args+=( "${arg}" )
;;
esac
done
export NODE_PATH="$(for P in "${runfiles_node_path[@]}"; do echo -n "${RUNFILES}/${P}:"; done)${NODE_PATH}"
"${RUNFILES}/{{nodejs}}" "${node_options[@]}" "${RUNFILES}/{{entry_point}}" "${args[@]}"

View File

@ -0,0 +1,33 @@
_ROOT_BUILD_FILE = """\
package(default_visibility=["//visibility:public"])
alias(
name = "nodejs",
actual = "//:nodejs_bin",
)
"""
def _nodejs_workspace_impl(ctx):
"""
Workspace rule that pulls in the node binary. The binary will be available as
//:nodejs in the workspace.
Args:
binary: The name of the node executable in path.
"""
node = ctx.which(ctx.attr.binary)
if node == None:
fail("Node.js not found in path.")
ctx.symlink(node, "nodejs_bin")
# The generated alias is executable because the source file is executable.
ctx.file("BUILD", _ROOT_BUILD_FILE, False)
nodejs_workspace = repository_rule(
_nodejs_workspace_impl,
attrs = {
"binary": attr.string(default="node"),
},
)

118
build_defs/npm_package.bzl Normal file
View File

@ -0,0 +1,118 @@
load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar")
load("//build_defs:utils.bzl", "join_paths", "map_files")
# Remove testing code since we will be using the bundle.
# Ideally we would like to break up main and testing into separate compilation
# units.
def _remove_testing_and_index(ctx, package_dir, files):
testing = join_paths(ctx.label.workspace_root, ctx.label.package, package_dir, "testing")
index = join_paths(ctx.label.workspace_root, ctx.label.package, package_dir, "index.")
return [f for f in files
if not f.short_path.startswith(testing) and not f.short_path.startswith(index)]
def _ts_npm_package_impl(ctx):
files = set()
if len(ctx.attr.srcs) != 1:
fail("srcs must be a singleton list", "srcs")
src = ctx.attr.srcs[0]
provider = src.typescript.esm if ctx.attr.esm else src.typescript
root_dir = provider.package_dir
out_dir = join_paths(src.typescript.package_dir, "dist")
# Assume the input is in bin_dir, except for package.json
abs_root_dir = join_paths(ctx.configuration.bin_dir.path, ctx.label.workspace_root,
ctx.label.package, root_dir)
abs_out_dir = join_paths(ctx.configuration.bin_dir.path, ctx.label.workspace_root,
ctx.label.package, out_dir)
copy_src = provider.files + provider.metadata + provider.source_maps
if ctx.attr.esm:
copy_src = _remove_testing_and_index(ctx, root_dir, copy_src)
copy_dest = map_files(ctx, copy_src, root_dir, out_dir)
ctx.action(
progress_message = "Copying files for {}".format(ctx.label),
inputs = copy_src,
outputs = copy_dest,
executable = ctx.executable._copy,
arguments = ["--rootDir", abs_root_dir, "--outDir", abs_out_dir] + [f.path for f in copy_src],
)
manifest_src = ctx.file.manifest
manifest_dest = ctx.new_file(join_paths(out_dir, "package.json"))
ctx.action(
progress_message = "Copying files for {}".format(ctx.label),
inputs = [manifest_src],
outputs = [manifest_dest],
command = ["cp", manifest_src.path, manifest_dest.path],
)
downlevel_src = provider.declarations
if ctx.attr.esm:
downlevel_src = _remove_testing_and_index(ctx, root_dir, downlevel_src)
downlevel_dest = map_files(ctx, downlevel_src, root_dir, out_dir)
ctx.action(
progress_message = "Downleveling .d.ts files for {}".format(ctx.label),
inputs = downlevel_src,
outputs = downlevel_dest,
executable = ctx.executable._downlevel_declaration,
arguments = ["--node_path=tools", "--rootDir", abs_root_dir, "--outDir", abs_out_dir] +
[f.path for f in downlevel_src],
)
# Assume that data is already at the right location
files = [manifest_dest] + copy_dest + downlevel_dest + ctx.files.data
return struct(
files = set(files),
runfiles = ctx.runfiles(
files = list(files),
),
)
_ts_npm_package = rule(
implementation = _ts_npm_package_impl,
attrs = {
"srcs": attr.label_list(providers=["typescript"]),
"data": attr.label_list(allow_files=True, cfg=DATA_CFG),
"manifest": attr.label(allow_files=True, single_file=True, mandatory=True),
"module_name": attr.string(),
"esm": attr.bool(default=True),
"_copy": attr.label(default=Label("//build_defs/tools:copy"), executable=True),
"_downlevel_declaration": attr.label(
default=Label("//build_defs/tools:downlevel_declaration"), executable=True),
},
)
def ts_npm_package(*, name, strip_prefix, extension=None, package_dir=None, files=[],
mode=None, modes=None, symlinks=None, **kwargs):
"""
Rule to create an npm package from a ts_library target.
Args:
srcs: The ts_library target.
data: Data files to be packaged.
manifest: The package.json to be packaged.
module_name: The ES module name of the module.
strip_prefix: Required. The directory which files in the tarball should be relative to.
extension, package_dir, files, mode, modes, symlinks:
The corresponding argument in pkg_tar.
"""
_ts_npm_package(
name = name + "_files",
**kwargs
)
pkg_tar(
name = name,
extension = extension,
strip_prefix = strip_prefix,
package_dir = package_dir,
mode = mode,
modes = modes,
symlinks = symlinks,
files = [":{}_files".format(name)] + files,
)

64
build_defs/protractor.bzl Normal file
View File

@ -0,0 +1,64 @@
def _protractor_test_impl(ctx):
"""
Rule for running Protractor tests.
Args:
srcs: The targets containing the spec files.
deps: JavaScript targets which the tests depend on.
data: Data files which the tests depend on. This should include all client-
side files required for the tests.
config: Required. Protractor config file to use.
When this rule is run, the runfiles tree will be served at port 8000, rooted
at the workspace. Protractor tests can make use of this server. Additionally,
you can pass in the argument --serve-only to only run the server, e.g.:
$ bazel run :foo_e2e_test -- --serve-only
"""
ctx.template_action(
template = ctx.file._launcher_template,
output = ctx.outputs.executable,
substitutions = {
"{{protractor}}": ctx.executable._protractor.short_path,
"{{config}}": ctx.file.config.short_path,
"{{serve_runfiles}}": ctx.executable._serve_runfiles.short_path,
},
executable = True,
)
return struct(
files = set([ctx.outputs.executable]),
runfiles = ctx.runfiles(
files = ctx.files.srcs + ctx.files._protractor + ctx.files._serve_runfiles + ctx.files.config,
transitive_files = set(ctx.attr._protractor.default_runfiles.files) + set(ctx.attr._serve_runfiles.default_runfiles.files),
collect_data = True,
collect_default = True,
),
)
_protractor_test = rule(
implementation = _protractor_test_impl,
executable = True,
test = True,
attrs = {
"srcs": attr.label_list(allow_files=True),
"deps": attr.label_list(),
"data": attr.label_list(allow_files=True, cfg=DATA_CFG),
"config": attr.label(allow_files=True, single_file=True, mandatory=True),
"_protractor": attr.label(default=Label("//:protractor_bin"), executable=True),
"_serve_runfiles": attr.label(
default = Label("//build_defs/tools:serve_runfiles"),
executable = True,
),
"_launcher_template": attr.label(
default = Label("//build_defs:protractor_launcher_template.sh"),
allow_files = True,
single_file = True,
),
},
)
def protractor_test(*, tags=None, **kwargs):
tags = tags or []
_protractor_test(tags=tags + ["ibazel_notify_changes"], **kwargs)

View File

@ -0,0 +1,55 @@
#!/usr/bin/env bash
set -e
if [[ -z "${RUNFILES}" ]]; then
case "${0}" in
/*) self="${0}" ;;
*) self="${PWD}/${0}" ;;
esac
if [[ -n "${TEST_SRCDIR}" ]]; then
export RUNFILES="${TEST_SRCDIR}/angular"
elif [[ -d "${self}.runfiles" ]]; then
export RUNFILES="${self}.runfiles/angular"
else
echo "Runfiles directory not found." >&2
exit 1
fi
fi
"${RUNFILES}/{{serve_runfiles}}" &
SERVER_PID="$!"
# Kill the server if we get interrupted.
trap "kill ${SERVER_PID}" SIGINT SIGTERM
for arg in "$@"; do
case "${arg}" in
--serve-only)
SERVE_ONLY=1
;;
esac
done
if [[ -n "${SERVE_ONLY}" ]]; then
wait
else
# Run once.
"${RUNFILES}/{{protractor}}" "${RUNFILES}/{{config}}" "$@"
# Automatically rerun if told to do so
if [[ "${IBAZEL_NOTIFY_CHANGES}" == "y" ]]; then
while read line; do
case "${line}" in
"IBAZEL_BUILD_STARTED")
;;
"IBAZEL_BUILD_COMPLETED SUCCEEDED")
"${RUNFILES}/{{protractor}}" "${RUNFILES}/{{config}}" "$@"
;;
"IBAZEL_BUILD_COMPLETED FAILED")
;;
esac
done
fi
fi

View File

@ -0,0 +1,45 @@
'use strict';
import * as fs from 'fs';
import * as path from 'path';
import baseConfig from '{{base_config}}';
const prefixes = [{{prefixes}}];
/**
* A Rollup plugin that (wrongly) assumes that source maps can be found by
* suffixing ".map" and tries to do that.
*/
class LoadSourceMapHeuristicPlugin {
load(id) {
const code = fs.readFileSync(id).toString();
let map;
try {
map = fs.readFileSync(id + '.map').toString();
} catch (err) {
}
return {code: code, map: map};
}
}
const config = Object.assign({}, baseConfig, {
entry: '{{entry}}',
dest: '{{dest}}',
sourceMap: true,
banner: '{{banner}}' ? fs.readFileSync('{{banner}}').toString() : '',
// Make rollup shut up.
onwarn: msg => {
if (!msg.match(/as external dependency$/)) {
console.log(msg);
}
},
plugins: (baseConfig.plugins || []).concat([new LoadSourceMapHeuristicPlugin()])
});
export default config;

View File

@ -0,0 +1,53 @@
load("//build_defs:nodejs.bzl", "nodejs_module", "nodejs_test")
# nodejs_{binary,test} should be runnable.
nodejs_test(
name = "do_nothing",
srcs = ["do_nothing.js"],
entry_point = "do_nothing.js",
size = "small",
)
# nodejs_{binary,test} should support entrypoint inside a directory file.
nodejs_test(
name = "inside_directory",
srcs = ["dir"],
entry_point = "dir/index.js",
size = "small",
)
# nodejs_{binary,test} should support node_options.
nodejs_test(
name = "node_options",
srcs = ["node_options.js"],
entry_point = "node_options.js",
args = ["--node_options=--expose-gc"],
size = "small",
)
# nodejs_module should be accessible from downstream dependencies.
nodejs_module(
name = "foo-module",
srcs = ["foo-module/index.js"],
)
nodejs_test(
name = "use_relative",
srcs = ["use_relative.js"],
entry_point = "use_relative.js",
size = "small",
)
# nodejs_{binary,test} should support node_path.
nodejs_test(
name = "use_absolute",
srcs = ["use_absolute.js"],
deps = ["foo-module"],
entry_point = "use_absolute.js",
args = ["--node_path=build_defs/tests/nodejs"],
size = "small",
)
test_suite(
name = "all_tests",
)

View File

View File

View File

@ -0,0 +1,3 @@
'use strict';
module.exports = 'foo';

View File

@ -0,0 +1,5 @@
'use strict';
const assert = require('assert');
assert.equal(typeof global.gc, 'function');

View File

@ -0,0 +1,7 @@
'use strict';
const assert = require('assert');
const foo = require('foo-module');
assert.equal(foo, 'foo');

View File

@ -0,0 +1,7 @@
'use strict';
const assert = require('assert');
const foo = require('./foo-module');
assert.equal(foo, 'foo');

View File

@ -0,0 +1,168 @@
load("//build_defs:typescript.bzl", "ts_library", "ts_ext_library")
load("//build_defs:nodejs.bzl", "nodejs_test")
# ts_library should reject empty srcs. (FAIL)
ts_library(
name = "nothing_FAIL",
srcs = glob(["blackhole/**/*.ts"]),
tsconfig = "tsconfig.json",
tags = ["manual"],
)
# ts_library should build a module at a normal position.
ts_library(
name = "basic",
srcs = glob(["*.ts"]),
tsconfig = "tsconfig.json",
)
# ts_library should default root_dir to tsconfig.json location.
# ts_library should support aliasing modules.
ts_library(
name = "nested",
srcs = ["nested/@nested/index.ts"],
# Interestingly, paths starting with "@" will be recognized as a special
# label, so we cannot address "@nested/tsconfig.json" directly.
tsconfig = "nested/@nested/tsconfig.json",
module_name = "@nested/nested",
)
# ts_library should support importing deps modules.
# ts_library should support importing sub-modules.
ts_library(
name = "importing_modules",
srcs = ["importing_modules/index.ts"],
deps = [":basic", ":nested"],
tsconfig = "tsconfig.json",
root_dir = "importing_modules",
)
ts_library(
name = "internal_stuff",
srcs = ["internal_stuff/index.ts"],
tsconfig = "tsconfig.json",
root_dir = "internal_stuff",
)
# ts_library should not use @internal declarations by default. (FAIL)
ts_library(
name = "use_internal_wrong_FAIL",
srcs = ["use_internal/index.ts"],
deps = [":internal_stuff"],
tsconfig = "tsconfig.json",
root_dir = "use_internal",
out_dir = "use_internal_wrong",
tags = ["manual"],
)
# ts_library should check that deps_use_internal is a subset of deps. (FAIL)
ts_library(
name = "use_internal_subset_FAIL",
srcs = ["use_internal/index.ts"],
deps_use_internal = [":internal_stuff"],
tsconfig = "tsconfig.json",
root_dir = "use_internal",
out_dir = "use_internal_wrong",
tags = ["manual"],
)
# ts_library should support using @internal declarations.
ts_library(
name = "use_internal",
srcs = ["use_internal/index.ts"],
deps = [":internal_stuff"],
deps_use_internal = [":internal_stuff"],
tsconfig = "tsconfig.json",
root_dir = "use_internal",
)
# ts_library should make transitive declarations available.
ts_library(
name = "use_transitive",
srcs = ["use_transitive/index.ts"],
deps = [":use_internal"],
tsconfig = "tsconfig.json",
root_dir = "use_transitive",
)
# ts_library should load ambient declarations from ts_ext_library.
ts_ext_library(
name = "ambient",
declarations = glob(["ambient/*.d.ts"]),
root_dir = "ambient",
ambient = True,
entry_point = "ambient/index.d.ts",
)
ts_library(
name = "use_ambient",
srcs = ["use_ambient/index.ts"],
deps = [":ambient"],
tsconfig = "tsconfig.json",
root_dir = "use_ambient",
)
# ts_library should load non-ambient declarations from ts_ext_library.
ts_ext_library(
name = "non_ambient",
declarations = glob(["non_ambient/*.d.ts"]),
root_dir = "non_ambient",
ambient = False,
entry_point = "non_ambient/index.d.ts",
)
ts_library(
name = "use_non_ambient",
srcs = ["use_non_ambient/index.ts"],
deps = [":non_ambient"],
tsconfig = "tsconfig.json",
root_dir = "use_non_ambient",
)
# ts_library should make transitive ambient declarations available.
ts_library(
name = "use_transitive_ambient",
srcs = ["use_transitive_ambient/index.ts"],
deps = [":use_ambient"],
tsconfig = "tsconfig.json",
root_dir = "use_transitive_ambient",
)
# ts_library should support using only generated sources.
genrule(
name = "generated_source",
outs = ["use_generated_source/index.ts"],
cmd = "echo \"export const useGeneratedSource = 'useGeneratedSource';\" > $@",
)
ts_library(
name = "use_generated_source",
srcs = [":generated_source"],
tsconfig = "tsconfig.json",
root_dir = "use_generated_source",
)
# ts_library should be usable in nodejs_binary.
ts_library(
name = "assert",
srcs = ["assert/index.ts"],
deps = [
# Do not test basic and nested since they are too troublesome to set up
# NODE_PATH for.
":use_internal",
":use_transitive",
":use_ambient",
":use_transitive_ambient",
":use_generated_source",
],
tsconfig = "tsconfig.json",
root_dir = "assert",
)
nodejs_test(
name = "assert_test",
srcs = [":assert"],
entry_point = "assert/index.js",
size = "small",
args = ["--node_path=build_defs/tests/typescript"],
)

View File

@ -0,0 +1,3 @@
import './process';
declare const process: any;

View File

@ -0,0 +1 @@
declare const process: any;

View File

@ -0,0 +1,15 @@
import {useInternal} from 'use_internal';
import {useTransitive} from 'use_transitive';
import {useAmbient} from 'use_ambient';
import {useTransitiveAmbient} from 'use_transitive_ambient';
import {useGeneratedSource} from 'use_generated_source';
// We cannot use @types/node since we already declared process: any.
declare const require: any;
const assert: any = require('assert');
assert.equal(useInternal, 'new A().b');
assert.equal(useTransitive, 'new A().c');
assert.equal(useAmbient, process.cwd());
assert.equal(useTransitiveAmbient, process.cwd());
assert.equal(useGeneratedSource, 'useGeneratedSource');

View File

@ -0,0 +1,11 @@
// import module at package root
import {basic} from 'basic';
// import module in a subdir from an alias
import {nested} from '@nested/nested';
// import file from module
import {sub} from 'basic/sub';
export const importingModules = basic + nested + sub;

View File

@ -0,0 +1 @@
export const basic = 'basic';

View File

@ -0,0 +1,4 @@
export class A {
/** @internal */ b = 'new A().b';
c = 'new A().c';
}

View File

@ -0,0 +1 @@
export const nested = 'nested';

View File

@ -0,0 +1,8 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"sourceMap": false
}
}

View File

@ -0,0 +1 @@
export declare const foo: string;

View File

@ -0,0 +1 @@
export * from './foo';

View File

@ -0,0 +1 @@
export const sub = 'sub';

View File

@ -0,0 +1,8 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"sourceMap": false
}
}

View File

@ -0,0 +1 @@
export const useAmbient = process.cwd();

View File

@ -0,0 +1,6 @@
import {A} from 'internal_stuff';
export class B extends A {
}
export const useInternal = new A().b;

View File

@ -0,0 +1 @@
import {foo} from 'non_ambient';

View File

@ -0,0 +1,4 @@
import {B} from 'use_internal';
// c is an inherited property from A
export const useTransitive = new B().c;

View File

@ -0,0 +1 @@
export const useTransitiveAmbient = process.cwd();

52
build_defs/tools/BUILD Normal file
View File

@ -0,0 +1,52 @@
package(default_visibility=["//visibility:public"])
load("//build_defs:nodejs.bzl", "nodejs_binary")
nodejs_binary(
name = "serve_runfiles",
srcs = ["serve_runfiles.js"],
deps = [
"//:gulp-connect",
"//:cors",
],
entry_point = "serve_runfiles.js",
)
nodejs_binary(
name = "merge_tsconfig",
srcs = ["merge_tsconfig.js"],
deps = ["//:typescript"],
entry_point = "merge_tsconfig.js",
)
sh_binary(
name = "uglifyjs_wrapped",
srcs = ["uglifyjs_wrapped.sh"],
data = ["//:uglifyjs_bin"],
)
nodejs_binary(
name = "flatten_sourcemap",
srcs = ["flatten_sourcemap.js"],
data = ["//:source-map", "//:tsc_bin"],
entry_point = "flatten_sourcemap.js",
)
nodejs_binary(
name = "copy",
srcs = ["copy.js"],
deps = [
"//:minimist",
],
entry_point = "copy.js",
)
nodejs_binary(
name = "downlevel_declaration",
srcs = ["downlevel_declaration.js"],
deps = [
"//:minimist",
"//:tsc-wrapped",
],
entry_point = "downlevel_declaration.js",
)

23
build_defs/tools/copy.js Normal file
View File

@ -0,0 +1,23 @@
'use strict';
const fs = require('fs');
const minimist = require('minimist');
const path = require('path');
function main(argv) {
const args = minimist(argv);
const rootDir = path.resolve(args.rootDir);
const outDir = path.resolve(args.outDir);
for (const fileName of args._) {
const input = path.resolve(fileName);
if (input.substr(0, rootDir.length) !== rootDir) {
throw new Error(`${input} not in ${rootDir}`);
}
const output = path.join(outDir, input.substr(rootDir.length));
// Simply let error propagate and crash the process
fs.createReadStream(input).pipe(fs.createWriteStream(output));
}
}
main(process.argv.slice(2));

View File

@ -0,0 +1,30 @@
'use strict';
const fs = require('fs');
const minimist = require('minimist');
const path = require('path');
const ts = require('typescript');
const downlevelDeclaration =
require('@angular/tsc-wrapped/src/dts_downleveler').downlevelDeclaration;
function main(argv) {
const args = minimist(argv);
const rootDir = path.resolve(args.rootDir);
const outDir = path.resolve(args.outDir);
for (const fileName of args._) {
const input = path.resolve(fileName);
if (input.substr(0, rootDir.length) !== rootDir) {
throw new Error(`${input} not in ${rootDir}`);
}
const output = path.join(outDir, input.substr(rootDir.length));
const inContent = fs.readFileSync(input).toString();
const outContent = downlevelDeclaration(input, inContent, ts.ScriptTarget.ES2015);
fs.writeFileSync(output, outContent);
}
}
main(process.argv.slice(2));

View File

@ -0,0 +1,108 @@
'use strict';
const childProcess = require('child_process');
const fs = require('fs');
const sourceMap = require('source-map'), SourceMapConsumer = sourceMap.SourceMapConsumer,
SourceMapGenerator = sourceMap.SourceMapGenerator;
const path = require('path');
const SOURCE_MAPPING_URL_REGEXP = /^\/\/# sourceMappingURL=(.*)$/;
function printUsageAndExit() {
console.error(`Usage: ${process.argv[0]} ${process.argv[1]} <input .js file> [-- <command...>]
Takes an input JavaScript file that has at the end of the file a list of
//# sourceMappingURL=<source map location>
tokens overwrites it and its source map with a flattened source map.
Optionally runs the specified command before doing so.`);
process.exit(1);
}
function main(fileName) {
const lines = fs.readFileSync(fileName).toString().split('\n');
if (!lines[lines.length - 1]) {
// Remove Last EOL
lines.pop();
}
const sourceMaps = [];
let i;
for (i = lines.length - 1; i >= 0; i--) {
const match = lines[i].match(SOURCE_MAPPING_URL_REGEXP);
if (match) {
sourceMaps.unshift(match[1].trim());
} else {
break;
}
}
const contents = lines.slice(0, i + 1);
const maps = sourceMaps.map(m => {
const mapName = path.join(path.dirname(fileName), m);
const sourceMap = JSON.parse(fs.readFileSync(mapName).toString());
return {fileName: mapName, sourceMap: sourceMap, consumer: new SourceMapConsumer(sourceMap)};
});
const firstMap = maps.shift();
// Create an empty source map with the inline sources that we want to keep
const generator = SourceMapGenerator.fromSourceMap(new SourceMapConsumer({
version: 3,
file: path.basename(fileName),
sourceRoot: '',
sources: firstMap.sourceMap.sources,
sourcesContent: firstMap.sourceMap.sourcesContent,
mappings: ''
}));
for (const map of maps) {
if (map.sourceMap.sources.length !== 1) {
throw new Error(
`${map.fileName} has more than one source. Subsequent source maps must only be 1-to-1 mappings!`);
}
}
firstMap.consumer.eachMapping(firstMapping => {
const original = {line: firstMapping.originalLine, column: firstMapping.originalColumn};
let finals = [{line: firstMapping.generatedLine, column: firstMapping.generatedColumn}];
for (const map of maps) {
finals = finals
.map(
loc => map.consumer.generatedPositionFor(
{source: map.sourceMap.sources[0], line: loc.line, column: loc.column}))
.filter(loc => loc.line !== null && loc.column !== null)
}
for (const loc of finals) {
generator.addMapping({
source: firstMapping.source,
original: original,
generated: loc,
name: firstMapping.name
});
}
});
fs.writeFileSync(maps[maps.length - 1].fileName, generator.toString());
// Match the TypeScript behavior that no EOL is emitted
fs.writeFileSync(fileName, contents.join('\n'));
}
if (process.argv.length >= 3) {
if (process.argv.length > 3) {
const cmdArgs = process.argv.slice(3);
if (cmdArgs[0] === '--') {
cmdArgs.shift();
}
const result =
childProcess.spawnSync(process.argv[4], process.argv.slice(5), {stdio: 'inherit'});
if (result.status !== 0) {
process.exit(result.status);
}
}
main(process.argv[2]);
} else {
printUsageAndExit();
}

View File

@ -0,0 +1,104 @@
'use strict';
const fs = require('fs');
const ts = require('typescript');
function main(argv) {
if (!argv.length) {
console.error(`Usage: ${process.argv[0]} ${process.argv[1]}
[--out <out file>] [<--file <file>|<json string>>...]
Merges multiple portions of tsconfig.json in a way that the output tsconfig.json
is semantically valid.`);
process.exit(1);
}
const tsconfig = {};
let out = null;
while (argv.length) {
const arg = argv.shift();
if (arg === '--file') {
const file = argv.shift();
mergeTsconfig(tsconfig, parse(file, fs.readFileSync(file).toString()));
} else if (arg === '--out') {
out = argv.shift();
} else {
mergeTsconfig(tsconfig, parse(/* fileName */ '<input argument>', arg));
}
}
normalizeTsconfig(tsconfig);
if (out) {
fs.writeFileSync(out, JSON.stringify(tsconfig, null, 2));
} else {
console.log(JSON.stringify(tsconfig, null, 2));
}
}
function mergeTsconfig(merged, next) {
// File lists are not merged but replaced.
if ((merged.files || merged.include || merged.exclude) &&
(next.files || next.include || next.exclude)) {
delete merged.files;
delete merged.include;
delete merged.exclude;
}
if (merged.compilerOptions && next.compilerOptions) {
// Path mappings are not merged but replaced.
if (merged.compilerOptions.paths && next.compilerOptions.paths) {
delete merged.compilerOptions.paths;
}
}
deepMerge(merged, next);
}
function normalizeTsconfig(tsconfig) {
const compilerOptions = tsconfig.compilerOptions;
if (!compilerOptions.sourceMap && !compilerOptions.inlineSourceMap) {
// These options require sourceMap or inlineSourceMap to be set.
delete compilerOptions.inlineSources;
delete compilerOptions.mapRoot;
delete compilerOptions.sourceRoot;
}
}
function deepMerge(x, y) {
if (Array.isArray(x) && Array.isArray(y)) {
for (const i of y) {
if (x.indexOf(i) === -1) {
x.push(i);
}
}
} else {
for (const key in x) {
if (key in y) {
if (typeof x[key] === 'object' && typeof y[key] === 'object') {
deepMerge(x[key], y[key]);
} else {
x[key] = y[key];
}
}
}
for (const key in y) {
if (!(key in x)) {
x[key] = y[key];
}
}
}
}
function parse(fileName, jsonText) {
// This parses a JSON-ish file with comments.
const result = ts.parseConfigFileTextToJson(fileName, jsonText);
if (result.error) {
throw new Error(result.error.messageText);
}
return result.config;
}
main(process.argv.slice(2));

View File

@ -0,0 +1,14 @@
'use strict';
const connect = require('gulp-connect');
const cors = require('cors');
console.log(`Serving ${process.env.RUNFILES}`);
connect.server({
root: `${process.env.RUNFILES}`,
port: 8000,
livereload: false,
open: false,
middleware: (connect, opt) => [cors()],
});

View File

@ -0,0 +1,37 @@
#!/usr/bin/env bash
# This wrapper adds --preamble-file option to uglifyjs.
set -e
if [[ -z "${RUNFILES}" ]]; then
case "${0}" in
/*) self="${0}" ;;
*) self="${PWD}/${0}" ;;
esac
if [[ -n "${TEST_SRCDIR}" ]]; then
export RUNFILES="${TEST_SRCDIR}/angular"
elif [[ -d "${self}.runfiles" ]]; then
export RUNFILES="${self}.runfiles/angular"
else
echo "Runfiles directory not found." >&2
exit 1
fi
fi
ARGS=()
while [[ $# -gt 0 ]]; do
case "$1" in
--preamble-file)
shift
ARGS+=( "--preamble" "$(cat "${1}")" )
;;
*)
ARGS+=( "${1}" )
;;
esac
shift
done
"${RUNFILES}/uglifyjs_bin" "${ARGS[@]}"

View File

@ -0,0 +1,114 @@
load("//build_defs:utils.bzl", "pick_file")
def _public_api_impl(ctx):
"""
Rule for generating golden files with ts-api-guardian.
Args:
srcs: The ts_library targets containing the ts files.
entry_points: The paths for entrypoint files.
"""
entry_points = []
declaration_files = []
for src in ctx.attr.srcs:
declaration_files += src.typescript.declarations
entry_points = [pick_file(declaration_files, ctx.label, ep) for ep in ctx.attr.entry_points]
ctx.template_action(
template = ctx.file._launcher_template,
output = ctx.outputs.executable,
substitutions = {
"{{ts_api_guardian}}": ctx.executable._ts_api_guardian.short_path,
"{{mode}}": "out",
"{{root_dir}}": ctx.attr.root_dir,
"{{golden_dir}}": ctx.attr.out_dir,
"{{arguments}}": " ".join(ctx.attr.arguments),
"{{entry_points}}": " ".join([f.short_path for f in entry_points]),
},
executable = True,
)
return struct(
files = set([ctx.outputs.executable]),
runfiles = ctx.runfiles(
files = declaration_files + ctx.files._ts_api_guardian,
transitive_files = set(ctx.attr._ts_api_guardian.default_runfiles.files),
),
public_api = struct(
srcs = declaration_files,
root_dir = ctx.attr.root_dir,
golden_dir = ctx.attr.out_dir,
arguments = " ".join(ctx.attr.arguments),
entry_points = entry_points,
),
)
public_api = rule(
implementation = _public_api_impl,
executable = True,
attrs = {
"srcs": attr.label_list(allow_files=True),
"entry_points": attr.string_list(mandatory=True),
"root_dir": attr.string(default="."),
"out_dir": attr.string(mandatory=True),
"arguments": attr.string_list(),
"_ts_api_guardian": attr.label(default=Label("//:ts-api-guardian_bin"), executable=True),
"_launcher_template": attr.label(
default = Label("//build_defs:ts_api_guardian_launcher_template.sh"),
allow_files = True,
single_file = True,
),
},
)
def _public_api_test_impl(ctx):
"""
Rule for running ts-api-guardian test.
Args:
public_api: The corresponding public_api target.
"""
public_api = ctx.attr.public_api.public_api
ctx.template_action(
template = ctx.file._launcher_template,
output = ctx.outputs.executable,
substitutions = {
"{{ts_api_guardian}}": ctx.executable._ts_api_guardian.short_path,
"{{mode}}": "verify",
"{{root_dir}}": public_api.root_dir,
"{{golden_dir}}": public_api.golden_dir,
"{{arguments}}": public_api.arguments,
"{{entry_points}}": " ".join([f.short_path for f in public_api.entry_points]),
},
executable = True,
)
return struct(
files = set([ctx.outputs.executable]),
runfiles = ctx.runfiles(
files = ctx.files.srcs + public_api.srcs + ctx.files._ts_api_guardian + ctx.files.public_api,
transitive_files = set(ctx.attr._ts_api_guardian.default_runfiles.files),
),
)
public_api_test = rule(
implementation = _public_api_test_impl,
executable = True,
test = True,
attrs = {
"srcs": attr.label_list(allow_files=True),
"public_api": attr.label(providers=["public_api"], mandatory=True),
"_ts_api_guardian": attr.label(default=Label("//:ts-api-guardian_bin"), executable=True),
"_launcher_template": attr.label(
default = Label("//build_defs:ts_api_guardian_launcher_template.sh"),
allow_files = True,
single_file = True,
),
},
)

View File

@ -0,0 +1,44 @@
#!/usr/bin/env bash
set -e
if [[ -z "${RUNFILES}" ]]; then
case "${0}" in
/*) self="${0}" ;;
*) self="${PWD}/${0}" ;;
esac
if [[ -n "${TEST_SRCDIR}" ]]; then
export RUNFILES="${TEST_SRCDIR}/angular"
elif [[ -d "${self}.runfiles" ]]; then
export RUNFILES="${self}.runfiles/angular"
else
echo "Runfiles directory not found." >&2
exit 1
fi
fi
if [[ "{{mode}}" == "out" ]]; then
# For out, we need to write to execroot
# We use a WORKSPACE file to determine workspace root
WORKSPACE="${0}"
while [[ ${#WORKSPACE} > 1 ]] && ! [[ -h "${WORKSPACE}/WORKSPACE" ]]; do
WORKSPACE="$(dirname "${WORKSPACE}")"
done
if [[ -z "${WORKSPACE}" ]] || [[ "${WORKSPACE}" == .* ]]; then
echo "Cannot locate execroot." >&2
exit 1
fi
GOLDEN_DIR="${WORKSPACE}/{{golden_dir}}"
else
# For verify, we can just use the copy in runfiles
GOLDEN_DIR="{{golden_dir}}"
fi
# entry_points are relative to RUNFILES, so we have to cd to there
cd ${RUNFILES}
"./{{ts_api_guardian}}" \
--rootDir {{root_dir}} --{{mode}}Dir "${GOLDEN_DIR}" --color {{arguments}} {{entry_points}}

439
build_defs/typescript.bzl Normal file
View File

@ -0,0 +1,439 @@
load("//build_defs:utils.bzl", "join_paths", "normalize_path", "map_files", "drop_dir",
"pseudo_json_encode", "pick_file_in_dir", "pick_provider")
def _ts_library_impl(ctx):
"""ts_library
Rule to compile TypeScript code.
Args:
deps: ts_* dependencies.
deps_use_internal: ts_library dependencies for which @internal declarations
should be used. Must be a subset of deps. Note that if this target is used
downstream, you should ensure that the resultant declarations will be
compatible with upstream declarations when all @internal's are stripped.
module_name: The module name of the package. Defaults to the target name.
root_dir: The TypeScript rootDir relative to the package. Defaults to the
location of the tsconfig.json file.
out_dir: The TypeScript outDir relative to the package. Defaults to
root_dir.
source_map: Corresponds to sourceMap in TypeScript.
inline_source_map: Corresponds to inlineSourceMap in TypeScript.
is_leaf: Declares that this ts_library will not be depended on by other
TypeScript libraries. This disables declaration and metadata generation.
"""
# Directory structure:
# bazel-angular/ (execroot)
# bazel-out/foo/bin/
# path-to-package/
# out/dir/
# *.js, *.d.ts, *.metadata.json
# esm/*.js
# internal/*.d.ts
# target-label_flavor_tsconfig.json
# path-to-package/
# *.ts
# *.d.ts
# tsconfig.json
# Merged tree: (e.g. in runfiles)
# path-to-package/
# *.ts
# out/dir/ (if any)
# *.js, *.d.ts, *.metadata.json
# esm/*.js, *.d.ts, *.metadata.json
# internal/*.d.ts, *.metadata.json
for src in ctx.attr.srcs:
if src.label.package != ctx.label.package:
# Sources can be in sub-folders, but not in sub-packages.
fail("Sources must be in the same package as the ts_library rule, " +
"but {} is not in {}".format(src.label, ctx.label.package), "srcs")
for dep in ctx.attr.deps:
if dep.typescript.is_leaf:
fail("{} is a leaf library and cannot be depended on".format(dep.label), "deps")
for dep in ctx.attr.deps_use_internal:
if dep not in ctx.attr.deps:
fail("deps_use_internal must be a subset of deps", "deps_use_internal")
if not hasattr(dep.typescript, 'internal'):
fail("dep {} does not have @internal declarations.".format(dep.label),
"deps_use_internal")
if not ctx.files.srcs:
fail("No source file found", "srcs")
# Find out the correct rootDir to use. This allows using generated files as
# input, which is needed e.g. for compiler codegen test.
# Note that despite the name, TypeScript does not use rootDirs to compute the
# output path.
source_roots = list(set([src.root.path for src in ctx.files.srcs]))
if len(source_roots) > 1:
fail("Mixing source and generated files as input is not supported.", "srcs")
# There are four types of input files:
# - *.ts files in srcs: load with "files"
# - *.d.ts files in srcs: load with "files" (We need this for convenience in
# e.g. playground e2e tests)
# - Non-ambient *.d.ts files: load with "compilerOptions"."paths" (tc_paths)
# - Module/bunbled *.d.ts files: load main file with "files" (tc_types)
#
# Regardless of the type, all of them have to be specified as inputs to the
# bazel action.
# These values are propagated transitively to downstream packages.
# tc: transitive closure
tc_declarations, tc_types, tc_paths = set(), set(), {}
tc_declarations_internal, tc_paths_internal = set(), {}
for dep in ctx.attr.deps:
tc_declarations += dep.typescript.tc_declarations
tc_types += dep.typescript.tc_types
tc_paths.update(dep.typescript.tc_paths)
if dep not in ctx.attr.deps_use_internal:
tc_declarations_internal += dep.typescript.tc_declarations
tc_paths_internal.update(dep.typescript.tc_paths)
for dep in ctx.attr.deps:
# Do this after the normal stuff so that the @internal transitive closure
# will take precedence in the tc_paths_internal dict.
if dep in ctx.attr.deps_use_internal:
tc_declarations_internal += dep.typescript.internal.tc_declarations
tc_paths_internal.update(dep.typescript.internal.tc_paths)
# Notice that the paths in the tsconfig.json should be relative to the file.
tsconfig_to_workspace = "/".join(
[".." for x in join_paths(ctx.configuration.bin_dir.path, ctx.label.package).split("/")])
# These two are package-relative.
# normalize_path handles the case where root_dir/out_dir is set to ".".
# TypeScript notoriously doesn't work with paths with /./ in the middle.
root_dir = normalize_path(
ctx.attr.root_dir or drop_dir(ctx.file.tsconfig.dirname, ctx.label.package))
out_dir = normalize_path(ctx.attr.out_dir or root_dir)
# These correspond to keys in tsconfig.json.
ts_files = [f for f in ctx.files.srcs if not f.short_path.endswith(".d.ts")]
base_tsconfig = {
"compilerOptions": {
"rootDir": join_paths(
tsconfig_to_workspace, source_roots[0], ctx.label.package, root_dir),
"paths": {module: [join_paths(tsconfig_to_workspace, path)]
for module, path in tc_paths_internal.items()},
# Required to use paths.
"baseUrl": ".",
"skipLibCheck": True,
"stripInternal": True,
"declaration": not ctx.attr.is_leaf,
# All dependencies should be loaded with "deps", so we don't need the
# node-style resolution nor @types resolution. This also improves
# consistency in sandboxed and unsandboxed environments.
"moduleResolution": "classic",
"typeRoots": [],
# TODO: fix the path encoded in .js.map
"sourceMap": ctx.attr.source_map,
"inlineSourceMap": ctx.attr.inline_source_map,
},
"angularCompilerOptions": {
"skipMetadataEmit": ctx.attr.is_leaf,
},
"files": ([join_paths(tsconfig_to_workspace, f.path) for f in ctx.files.srcs] +
[join_paths(tsconfig_to_workspace, path) for path in tc_types]),
}
tsc_action_args = dict(
ctx = ctx,
inputs = ctx.files.srcs + list(tc_declarations_internal),
ts_files = ts_files,
root_dir = root_dir,
out_dir = out_dir,
)
has_source_map = ctx.attr.source_map and not ctx.attr.inline_source_map
is_tsc_wrapped = "bootstrap" not in ctx.executable.compiler.path
is_leaf = ctx.attr.is_leaf
tsconfig = _tsconfig_action(
ctx = ctx,
prefix = "",
input_tsconfig = ctx.file.tsconfig,
mixin_tsconfig = _tsconfig_with(base_tsconfig, {"outDir": out_dir}),
)
gen_js, gen_d_ts, gen_meta, gen_js_map = _tsc_action(
prefix = "",
gen_config = (True, not is_leaf, not is_leaf and is_tsc_wrapped, has_source_map),
tsconfig = tsconfig,
**tsc_action_args
)
tsconfig_esm = _tsconfig_action(
ctx = ctx,
prefix = "esm",
input_tsconfig = ctx.file.tsconfig,
mixin_tsconfig = _tsconfig_with(base_tsconfig, {
"module": "es2015",
"outDir": join_paths(out_dir, "esm"),
}),
)
gen_js_esm, gen_d_ts_esm, gen_meta_esm, gen_js_map_esm = _tsc_action(
prefix = "esm",
gen_config = (True, not is_leaf, not is_leaf and is_tsc_wrapped, has_source_map),
tsconfig = tsconfig_esm,
**tsc_action_args
)
tsconfig_internal = _tsconfig_action(
ctx = ctx,
prefix = "internal",
input_tsconfig = ctx.file.tsconfig,
mixin_tsconfig = _tsconfig_with(base_tsconfig, {
"stripInternal": False,
"sourceMap": False,
"inlineSourceMap": False,
"outDir": join_paths(out_dir, "internal"),
}),
)
if not is_leaf:
_, gen_d_ts_internal, gen_meta_internal, _ = _tsc_action(
prefix = "internal",
gen_config = (False, True, is_tsc_wrapped, False),
tsconfig = tsconfig_internal,
**tsc_action_args
)
else:
gen_d_ts_internal, gen_meta_internal = [], []
module_name = ctx.attr.module_name or ctx.label.name
abs_package = join_paths(ctx.configuration.bin_dir.path, ctx.label.workspace_root,
ctx.label.package, out_dir)
return struct(
files = set(gen_js),
runfiles = ctx.runfiles(
files = gen_js + gen_js_map,
collect_default = True,
collect_data = True,
),
typescript = struct(
files = gen_js,
module_name = module_name,
# The rootDir relative to the current package.
package_dir = out_dir,
# The declarations of the current module
declarations = gen_d_ts,
source_maps = gen_js_map,
metadata = gen_meta,
# All declaration files in the transitive closure
tc_declarations = tc_declarations + gen_d_ts,
# Paths to declaration files to be loaded explicitly with "files",
# relative to workspace.
tc_types = tc_types,
# Mapping to declaration files to be loaded implicitly with "paths",
# relative to workspace.
tc_paths = _merge_dict(tc_paths, {
# We simply assume an index.d.ts exists. TypeScript will give the
# same "Cannot find module" if it isn't true.
module_name: join_paths(abs_package, "index"),
module_name + "/*": join_paths(abs_package, "*"),
}),
# The @internal variant of the declaration files. Optional.
internal = struct(
package_dir = join_paths(out_dir, "internal"),
declarations = gen_d_ts_internal,
tc_declarations = tc_declarations_internal + gen_d_ts_internal,
tc_paths = _merge_dict(tc_paths_internal, {
module_name: join_paths(abs_package, "internal/index"),
module_name + "/*": join_paths(abs_package, "internal/*"),
}),
),
# This struct exists solely for npm_package to work simpler.
# TypeScript-agnostic tools should use javascript_esm.
esm = struct(
files = gen_js_esm,
source_maps = gen_js_map_esm,
declarations = gen_d_ts_esm,
metadata = gen_meta_esm,
module_name = module_name,
package_dir = join_paths(out_dir, "esm"),
),
is_leaf = is_leaf,
),
nodejs = struct(),
javascript = struct(
files = gen_js + gen_js_map,
source_maps = gen_js_map,
module_name = module_name,
package_dir = out_dir,
),
javascript_esm = struct(
files = gen_js_esm,
source_maps = gen_js_map_esm,
module_name = module_name,
package_dir = join_paths(out_dir, "esm"),
),
)
def _tsconfig_with(base, compiler_options={}, angular_compiler_options={}):
return _merge_dict(base, {
"compilerOptions": _merge_dict(base["compilerOptions"], compiler_options),
"angularCompilerOptions": _merge_dict(
base["angularCompilerOptions"], angular_compiler_options),
})
def _tsconfig_action(*, ctx, prefix, input_tsconfig, mixin_tsconfig):
tsconfig = ctx.new_file(ctx.label.name + ("_" + prefix if prefix else "") + "_tsconfig.json")
target_name = "{}{}".format(ctx.label, " ({})".format(prefix) if prefix else "")
ctx.action(
progress_message = "Generating tsconfig.json for {}".format(target_name),
inputs = [input_tsconfig],
outputs = [tsconfig],
executable = ctx.executable._merge_tsconfig,
arguments = ["--file", input_tsconfig.path, pseudo_json_encode(mixin_tsconfig), "--out",
tsconfig.path],
)
return tsconfig
def _tsc_action(*, ctx, inputs, ts_files, root_dir, out_dir, prefix, gen_config, tsconfig):
real_out_dir = join_paths(out_dir, prefix)
has_js, has_d_ts, has_meta, has_js_map = gen_config
gen_js = map_files(ctx, ts_files, root_dir, real_out_dir, ".js") if has_js else []
gen_d_ts = map_files(ctx, ts_files, root_dir, real_out_dir, ".d.ts") if has_d_ts else []
gen_meta = map_files(ctx, ts_files, root_dir, real_out_dir, ".metadata.json") if has_meta else []
gen_js_map = map_files(ctx, ts_files, root_dir, real_out_dir, ".js.map") if has_js_map else []
is_tsc_wrapped = "bootstrap" not in ctx.executable.compiler.path
target_name = "{}{}".format(ctx.label, " ({})".format(prefix) if prefix else "")
ctx.action(
progress_message = "Compiling TypeScript {}".format(target_name),
mnemonic = "TypeScriptCompile",
inputs = inputs + [tsconfig],
outputs = gen_js + gen_d_ts + gen_meta + gen_js_map,
executable = ctx.executable.compiler,
arguments = ["@@" + tsconfig.path] if is_tsc_wrapped else ["--project", tsconfig.path],
execution_requirements = {"supports-workers": "1"} if is_tsc_wrapped else {},
)
return gen_js, gen_d_ts, gen_meta, gen_js_map
_ts_library = rule(
_ts_library_impl,
attrs = {
"compiler": attr.label(
default = Label("//:tsc-wrapped_bin"),
executable = True,
single_file = True,
),
"tsconfig": attr.label(allow_files=True, single_file=True, mandatory=True),
"srcs": attr.label_list(
allow_files = FileType([
".ts", # This also implicitly accepts .d.ts.
".tsx",
]),
mandatory = True,
),
"deps": attr.label_list(providers=["typescript"]),
"deps_use_internal": attr.label_list(providers=["typescript"]),
"data": attr.label_list(allow_files=True, cfg=DATA_CFG),
"module_name": attr.string(),
"root_dir": attr.string(default=""),
"out_dir": attr.string(default=""),
"source_map": attr.bool(default=True),
"inline_source_map": attr.bool(default=False),
"is_leaf": attr.bool(default=False),
"_merge_tsconfig": attr.label(
default = Label("//build_defs/tools:merge_tsconfig"),
executable = True,
),
},
)
def ts_library(*, name, **kwargs):
_ts_library(name=name, **kwargs)
pick_provider(name=name + "_esm", srcs=[":" + name], providers=["javascript_esm.files"])
def _merge_dict(a, *args):
ret = dict(a)
for d in args:
ret.update(d)
return ret
def _ts_ext_library_impl(ctx):
"""ts_ext_library
Basically a nodejs_module with d.ts files.
"""
module_name = ctx.attr.module_name or ctx.label.name
# The d.ts files of a ts_ext_library rule lives in the source directory
# instead of the bin directory
abs_package = join_paths(ctx.label.workspace_root, ctx.label.package, ctx.attr.root_dir)
if (not ctx.attr.entry_point and len(ctx.files.declarations) == 1 and
ctx.files.declarations[0].path.endswith(".d.ts")):
entry_point_file, entry_point_relative_path = ctx.files.declarations, ""
else:
entry_point_file, entry_point_relative_path = pick_file_in_dir(
ctx.files.declarations, ctx.label, ctx.attr.entry_point or "index.d.ts")
tc_declarations, tc_types, tc_paths = set(), set(), {}
tc_declarations_internal, tc_paths_internal = set(), {}
for dep in ctx.attr.deps:
tc_declarations += dep.typescript.tc_declarations
tc_types += dep.typescript.tc_types
tc_paths.update(dep.typescript.tc_paths)
return struct(
files = set(ctx.files.srcs),
runfiles = ctx.runfiles(
files = ctx.files.srcs,
collect_data = True,
collect_default = True,
),
typescript = struct(
module_name = module_name,
package_dir = ctx.attr.root_dir,
declarations = ctx.files.declarations,
tc_declarations = tc_declarations + ctx.files.declarations,
tc_types =
tc_types + set([join_paths(entry_point_file.path, entry_point_relative_path)]),
tc_paths = _merge_dict(tc_paths, {
module_name: join_paths(entry_point_file.path, entry_point_relative_path),
module_name + "/*": join_paths(abs_package, "*"),
} if not ctx.attr.ambient else {}),
is_leaf = False,
),
nodejs = struct(),
javascript = struct(
files = ctx.files.srcs,
module_name = module_name,
package_dir = ctx.attr.root_dir,
),
)
ts_ext_library = rule(
_ts_ext_library_impl,
attrs = {
"srcs": attr.label_list(allow_files=True),
"deps": attr.label_list(providers=["typescript"], cfg=DATA_CFG),
"data": attr.label_list(allow_files=True, cfg=DATA_CFG),
"declarations": attr.label_list(allow_files=FileType([".d.ts"]), mandatory=True),
"ambient": attr.bool(mandatory=True),
"module_name": attr.string(),
"root_dir": attr.string(default=""),
"entry_point": attr.string(),
}
)

151
build_defs/utils.bzl Normal file
View File

@ -0,0 +1,151 @@
def join_paths(*paths):
segments = []
for path in paths:
segments += path.split("/")
return "/".join([seg for seg in segments if seg])
def normalize_path(path):
segments = []
for seg in path.split("/"):
if seg == "..":
if segments:
segments.pop()
else:
segments.append("..")
elif seg and seg != ".":
segments.append(seg)
return "/".join(segments)
def drop_dir(path, directory):
if not path.startswith(directory):
fail("Path \"%s\" does not reside in directory \"%s\"" % (path, directory))
if directory:
return path[len(directory) + 1:]
else:
return path
def map_files(ctx, files, root_dir, out_dir, ext=None):
"""Creates a list of output files given directory and the extension.
root_dir and out_dir are specified relative to the package.
"""
ret = []
for f in files:
path_in_package = drop_dir(f.short_path, ctx.label.package)
if ext != None:
path_in_package_without_ext = path_in_package[:path_in_package.rfind(".")]
filename = join_paths(out_dir, drop_dir(path_in_package_without_ext, root_dir) + ext)
else:
filename = join_paths(out_dir, drop_dir(path_in_package, root_dir))
ret.append(ctx.new_file(filename))
return ret
def pick_file(files, base_label, path, attr=None):
"""Returns the file within the target which matches the specified package-
relative path.
Args:
files: A list of files to check.
base_label: The label of the package of interest.
path: The path of the needed file relative to `base_label`.
"""
match, remainder_path = pick_file_in_dir(files, base_label, path, attr)
if remainder_path:
fail("Cannot find '{}' in package '{}'. Available files are: \n{}".format(
path, base_label.package, "\n".join([f.path for f in files])), attr)
return match
def pick_file_in_dir(files, base_label, path, attr=None):
"""Finds the file or directory containing the file specified by
`base_label` and `path` inside the list `files`.
Returns a tuple (file, path) where file is the found file or directory
and path is the remaining path to be appended in order to get to the actual
file.
This is used to perform best-effort analysis-phase checking of a file
addressed by a path within a target, e.g. for entry_point in nodejs_binary.
Args:
files: A list of files to check.
base_label: The label of the package of interest.
path: The path of the needed file relative to `base_label`.
"""
short_path = join_paths(base_label.package, path)
# We assume that a parent directory of an input file is not also an input
# file.
matches = [f for f in files
if short_path == f.short_path or short_path.startswith(f.short_path + "/")]
if not matches:
fail("Cannot find '{}' in package '{}'. Available files are: \n{}".format(
path, base_label.package, "\n".join([f.path for f in files])), attr)
if len(matches) > 1:
# We neglect cases whether two files in a target come from different
# workspaces.
fail("Multiple matches of '{}' found in package '{}'!".format(path, base_label.package), attr)
remainder_path = short_path[len(matches[0].short_path) + 1:]
return (matches[0], remainder_path)
def pseudo_json_encode(dictionary):
# We abuse the fact that str() of a dict is almost a valid JSON object, and
# that we do not use characters requiring escaping.
return str(dictionary).replace("True", "true").replace("False", "false")
def _pick_provider_impl(ctx):
"""pick_provider
Rule that serves as an escape hatch for complex Skylark-based rules to easily
expose multiple targets that correspond to a subset of the provider. This
allows genrules or macros to build upon these targets.
Args:
srcs: The targets to pick the provider from.
providers: A list of dotted keys to pick under the target. The files in that
path will be collected.
"""
files = set()
for src in ctx.attr.srcs:
for provider in ctx.attr.providers:
keys = provider.split(".")
out = src
for k in keys:
if not hasattr(out, k):
fail("Target {} does not have provider \"{}\"".format(src.label, provider), "srcs")
out = getattr(out, k)
files += out
return struct(
files = files,
runfiles = ctx.runfiles(
files = list(files),
collect_default = True,
collect_data = True,
),
)
pick_provider = rule(
_pick_provider_impl,
attrs = {
"srcs": attr.label_list(mandatory=True),
"providers": attr.string_list(mandatory=True),
},
)

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

12
ibazel Executable file
View File

@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -e
ibazel_path=$(dirname "${0}")/bazel-bin/tools/ibazel/ibazel_bin
if ! [[ -x "${ibazel_path}" ]]; then
echo "Building ibazel..."
bazel build tools/ibazel:ibazel_bin
fi
"${ibazel_path}" "$@"

View File

@ -1,17 +1,19 @@
var browserProvidersConf = require('./browser-providers.conf.js');
var internalAngularReporter = require('./tools/karma/reporter.js');
var ibazelWatcher = require('./tools/karma/ibazel_watcher.js');
// Karma configuration
// Generated on Thu Sep 25 2014 11:52:02 GMT-0700 (PDT)
module.exports = function(config) {
config.set({
frameworks: ['jasmine'],
frameworks: ['jasmine', 'ibazel_watcher'],
files: [
// Sources and specs.
// Loaded through the System loader, in `test-main.js`.
{pattern: 'dist/all/@angular/**/*.js', included: false, watched: true},
{pattern: 'modules/@angular/**/*.js', included: false, watched: true},
{pattern: 'modules/@angular/**/*.js.map', included: false, watched: true},
'node_modules/core-js/client/core.js',
// include Angular v1 for upgrade module testing
@ -30,20 +32,19 @@ module.exports = function(config) {
'node_modules/systemjs/dist/system.src.js',
{pattern: 'node_modules/rxjs/**', included: false, watched: false, served: true},
'node_modules/reflect-metadata/Reflect.js',
'tools/build/file2modulename.js',
// 'tools/build/file2modulename.js',
'test-main.js',
{pattern: 'dist/all/empty.*', included: false, watched: false},
{pattern: 'modules/empty.*', included: false, watched: false},
{pattern: 'modules/@angular/platform-browser/test/static_assets/**', included: false, watched: false},
{pattern: 'modules/@angular/platform-browser/test/browser/static_assets/**', included: false, watched: false}
],
exclude: [
'dist/all/@angular/**/e2e_test/**',
'dist/all/@angular/examples/**',
'dist/all/@angular/router/**',
'dist/all/@angular/compiler-cli/**',
'dist/all/angular1_router.js',
'dist/all/@angular/platform-browser/testing/e2e_util.js'
'modules/@angular/**/e2e_test/**',
'modules/@angular/examples/**',
'modules/@angular/compiler-cli/**',
'modules/angular1_router.js',
'modules/@angular/platform-browser/testing/e2e_util.js'
],
customLaunchers: browserProvidersConf.customLaunchers,
@ -54,7 +55,8 @@ module.exports = function(config) {
'karma-sauce-launcher',
'karma-chrome-launcher',
'karma-sourcemap-loader',
internalAngularReporter
internalAngularReporter,
ibazelWatcher
],
preprocessors: {

View File

@ -11,7 +11,7 @@ import {Component} from '@angular/core';
import {ComponentFixture, TestBed, async} from '@angular/core/testing';
import {beforeEach, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
import {ListWrapper, StringMapWrapper} from '../../src/facade/collection';
import {ListWrapper, StringMapWrapper} from '@angular/facade/src/collection';
function detectChangesAndCheck(fixture: ComponentFixture<any>, classes: string) {
fixture.detectChanges();
@ -389,3 +389,5 @@ class TestComponent {
constructor() { this.setExpr.add('foo'); }
}
main();

View File

@ -12,7 +12,7 @@ import {TestBed, async} from '@angular/core/testing';
import {By} from '@angular/platform-browser/src/dom/debug/by';
import {expect} from '@angular/platform-browser/testing/matchers';
import {ListWrapper} from '../../src/facade/collection';
import {ListWrapper} from '@angular/facade/src/collection';
let thisArg: any;
@ -433,3 +433,5 @@ class ComponentUsingTestComponent {
items: any;
constructor() { this.items = [1, 2]; }
}
main();

View File

@ -183,3 +183,5 @@ class TestComponent {
this.functionCondition = function(s: any, n: any): boolean { return s == 'foo' && n == 1; };
}
}
main();

View File

@ -143,3 +143,5 @@ class TestLocalization extends NgLocalization {
class TestComponent {
switchValue: number = null;
}
main();

View File

@ -153,3 +153,5 @@ export function main() {
class TestComponent {
expr: any;
}
main();

View File

@ -158,3 +158,5 @@ class TestComponent {
this.when2 = null;
}
}
main();

View File

@ -163,3 +163,5 @@ class TestComponent {
currentTplRef: TemplateRef<any>;
context: any = {foo: 'bar'};
}
main();

View File

@ -62,3 +62,5 @@ class TestComponent {
text: string;
constructor() { this.text = 'foo'; }
}
main();

View File

@ -11,7 +11,7 @@ import {TestBed} from '@angular/core/testing';
import {AsyncTestCompleter, afterEach, beforeEach, ddescribe, describe, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {expect} from '@angular/platform-browser/testing/matchers';
import {NgLocaleLocalization, NgLocalization, getPluralCategory} from '../src/localization';
import {NgLocaleLocalization, NgLocalization, getPluralCategory} from '@angular/common/src/localization';
export function main() {
@ -155,4 +155,5 @@ class FrLocalization extends NgLocalization {
return 'other';
}
}
}
}
main();

View File

@ -12,8 +12,8 @@ import {AsyncTestCompleter, afterEach, beforeEach, ddescribe, describe, expect,
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {browserDetection} from '@angular/platform-browser/testing/browser_util';
import {EventEmitter} from '../../src/facade/async';
import {isBlank} from '../../src/facade/lang';
import {EventEmitter} from '@angular/facade/src/async';
import {isBlank} from '@angular/facade/src/lang';
import {SpyChangeDetectorRef} from '../spies';
export function main() {
@ -216,3 +216,5 @@ export function main() {
});
});
}
main();

View File

@ -11,7 +11,7 @@ import {PipeResolver} from '@angular/compiler/src/pipe_resolver';
import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing/testing_internal';
import {browserDetection} from '@angular/platform-browser/testing/browser_util';
import {DateWrapper} from '../../src/facade/lang';
import {DateWrapper} from '@angular/facade/src/lang';
export function main() {
describe('DatePipe', () => {
@ -104,3 +104,5 @@ export function main() {
}
});
}
main();

View File

@ -66,3 +66,5 @@ export function main() {
class TestLocalization extends NgLocalization {
getPluralCategory(value: number): string { return value > 1 && value < 6 ? 'many' : 'other'; }
}
main();

View File

@ -47,3 +47,5 @@ export function main() {
});
}
main();

View File

@ -11,7 +11,7 @@ import {Component} from '@angular/core';
import {TestBed, async} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/matchers';
import {Json, StringWrapper} from '../../src/facade/lang';
import {Json, StringWrapper} from '@angular/facade/src/lang';
export function main() {
describe('JsonPipe', () => {
@ -79,3 +79,5 @@ export function main() {
});
});
}
main();

View File

@ -40,3 +40,5 @@ export function main() {
});
}
main();

View File

@ -82,3 +82,5 @@ export function main() {
}
});
}
main();

View File

@ -111,3 +111,5 @@ export function main() {
});
});
}
main();

View File

@ -41,3 +41,5 @@ export function main() {
});
}
main();

View File

@ -0,0 +1,2 @@
///<reference path="node_modules/@types/jasmine/index.d.ts"/>
///<reference path="node_modules/@types/node/index.d.ts"/>

View File

@ -8,7 +8,7 @@
import * as ts from 'typescript';
import {ReflectorHostContext} from '../src/reflector_host';
import {ReflectorHostContext} from '@angular/compiler-cli/src/reflector_host';
export type Entry = string | Directory;
@ -61,6 +61,15 @@ export class MockContext implements ReflectorHostContext {
}
return current;
}
getDirectories(path: string): string[] {
const dir = this.getEntry(path);
if (typeof dir !== 'object') {
return [];
} else {
return Object.keys(dir).filter(key => typeof dir[key] === 'object');
}
}
}
function normalize(parts: string[]): string[] {
@ -117,4 +126,8 @@ export class MockCompilerHost implements ts.CompilerHost {
useCaseSensitiveFileNames(): boolean { return false; }
getNewLine(): string { return '\n'; }
getDirectories(path: string): string[] {
return this.context.getDirectories(path);
}
}

View File

@ -9,7 +9,7 @@
import {beforeEach, ddescribe, describe, expect, iit, it} from '@angular/core/testing/testing_internal';
import * as ts from 'typescript';
import {ReflectorHost} from '../src/reflector_host';
import {ReflectorHost} from '@angular/compiler-cli/src/reflector_host';
import {Directory, Entry, MockCompilerHost, MockContext} from './mocks';

View File

@ -9,10 +9,10 @@
import {AnimationMetadata, animate, group, sequence, style, transition, trigger} from '@angular/core';
import {AsyncTestCompleter, beforeEach, beforeEachProviders, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
import {StringMapWrapper} from '../../../platform-browser-dynamic/src/facade/collection';
import {AnimationCompiler, CompiledAnimationTriggerResult} from '../../src/animation/animation_compiler';
import {CompileAnimationEntryMetadata, CompileDirectiveMetadata, CompileTemplateMetadata, CompileTypeMetadata} from '../../src/compile_metadata';
import {CompileMetadataResolver} from '../../src/metadata_resolver';
import {StringMapWrapper} from '@angular/platform-browser-dynamic/src/facade/collection';
import {AnimationCompiler, CompiledAnimationTriggerResult} from '@angular/compiler/src/animation/animation_compiler';
import {CompileAnimationEntryMetadata, CompileDirectiveMetadata, CompileTemplateMetadata, CompileTypeMetadata} from '@angular/compiler/src/compile_metadata';
import {CompileMetadataResolver} from '@angular/compiler/src/metadata_resolver';
export function main() {
describe('RuntimeAnimationCompiler', () => {
@ -77,3 +77,5 @@ export function main() {
});
});
}
main();

View File

@ -10,11 +10,11 @@ import {AnimationAnimateMetadata, AnimationGroupMetadata, AnimationMetadata, Ani
import {AsyncTestCompleter, beforeEach, beforeEachProviders, ddescribe, describe, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
import {expect} from '@angular/platform-browser/testing/matchers';
import {FILL_STYLE_FLAG, flattenStyles} from '../../core_private';
import {AnimationAst, AnimationEntryAst, AnimationGroupAst, AnimationKeyframeAst, AnimationSequenceAst, AnimationStateTransitionAst, AnimationStepAst, AnimationStylesAst} from '../../src/animation/animation_ast';
import {parseAnimationEntry} from '../../src/animation/animation_parser';
import {StringMapWrapper} from '../../src/facade/collection';
import {CompileMetadataResolver} from '../../src/metadata_resolver';
import {FILL_STYLE_FLAG, flattenStyles} from '@angular/compiler/core_private';
import {AnimationAst, AnimationEntryAst, AnimationGroupAst, AnimationKeyframeAst, AnimationSequenceAst, AnimationStateTransitionAst, AnimationStepAst, AnimationStylesAst} from '@angular/compiler/src/animation/animation_ast';
import {parseAnimationEntry} from '@angular/compiler/src/animation/animation_parser';
import {StringMapWrapper} from '@angular/facade/src/collection';
import {CompileMetadataResolver} from '@angular/compiler/src/metadata_resolver';
export function main() {
describe('parseAnimationEntry', () => {
@ -416,3 +416,5 @@ export function main() {
});
});
}
main();

View File

@ -6,9 +6,9 @@
* found in the LICENSE file at https://angular.io/license
*/
import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '../../../core/testing/testing_internal';
import {CssLexer, CssLexerMode, CssScannerError, CssToken, CssTokenType} from '../../src/css_parser/css_lexer';
import {isPresent} from '../../src/facade/lang';
import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing/testing_internal';
import {CssLexer, CssLexerMode, CssScannerError, CssToken, CssTokenType} from '@angular/compiler/src/css_parser/css_lexer';
import {isPresent} from '@angular/facade/src/lang';
export function main() {
function tokenize(
@ -375,3 +375,5 @@ export function main() {
});
});
}
main();

View File

@ -7,10 +7,10 @@
*/
import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '../../../core/testing/testing_internal';
import {CssBlockAst, CssBlockDefinitionRuleAst, CssBlockRuleAst, CssDefinitionAst, CssInlineRuleAst, CssKeyframeDefinitionAst, CssKeyframeRuleAst, CssMediaQueryRuleAst, CssSelectorRuleAst, CssStyleSheetAst, CssStyleValueAst} from '../../src/css_parser/css_ast';
import {BlockType, CssParseError, CssParser, CssToken, ParsedCssResult} from '../../src/css_parser/css_parser';
import {ParseLocation} from '../../src/parse_util';
import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing/testing_internal';
import {CssBlockAst, CssBlockDefinitionRuleAst, CssBlockRuleAst, CssDefinitionAst, CssInlineRuleAst, CssKeyframeDefinitionAst, CssKeyframeRuleAst, CssMediaQueryRuleAst, CssSelectorRuleAst, CssStyleSheetAst, CssStyleValueAst} from '@angular/compiler/src/css_parser/css_ast';
import {BlockType, CssParseError, CssParser, CssToken, ParsedCssResult} from '@angular/compiler/src/css_parser/css_parser';
import {ParseLocation} from '@angular/compiler/src/parse_util';
export function assertTokens(tokens: CssToken[], valuesArr: string[]) {
for (var i = 0; i < tokens.length; i++) {
@ -800,3 +800,5 @@ export function main() {
});
});
}
main();

View File

@ -7,10 +7,10 @@
*/
import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '../../../core/testing/testing_internal';
import {CssAst, CssAstVisitor, CssAtRulePredicateAst, CssBlockAst, CssBlockDefinitionRuleAst, CssBlockRuleAst, CssDefinitionAst, CssInlineRuleAst, CssKeyframeDefinitionAst, CssKeyframeRuleAst, CssMediaQueryRuleAst, CssPseudoSelectorAst, CssRuleAst, CssSelectorAst, CssSelectorRuleAst, CssSimpleSelectorAst, CssStyleSheetAst, CssStyleValueAst, CssStylesBlockAst, CssUnknownRuleAst, CssUnknownTokenListAst} from '../../src/css_parser/css_ast';
import {BlockType, CssParseError, CssParser, CssToken} from '../../src/css_parser/css_parser';
import {isPresent} from '../../src/facade/lang';
import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing/testing_internal';
import {CssAst, CssAstVisitor, CssAtRulePredicateAst, CssBlockAst, CssBlockDefinitionRuleAst, CssBlockRuleAst, CssDefinitionAst, CssInlineRuleAst, CssKeyframeDefinitionAst, CssKeyframeRuleAst, CssMediaQueryRuleAst, CssPseudoSelectorAst, CssRuleAst, CssSelectorAst, CssSelectorRuleAst, CssSimpleSelectorAst, CssStyleSheetAst, CssStyleValueAst, CssStylesBlockAst, CssUnknownRuleAst, CssUnknownTokenListAst} from '@angular/compiler/src/css_parser/css_ast';
import {BlockType, CssParseError, CssParser, CssToken} from '@angular/compiler/src/css_parser/css_parser';
import {isPresent} from '@angular/facade/src/lang';
function _assertTokens(tokens: CssToken[], valuesArr: string[]): void {
expect(tokens.length).toEqual(valuesArr.length);
@ -320,3 +320,5 @@ export function main() {
});
});
}
main();

View File

@ -141,3 +141,5 @@ class DirectiveWithAfterViewInitMethod {
class DirectiveWithAfterViewCheckedMethod {
ngAfterViewChecked() {}
}
main();

View File

@ -444,3 +444,5 @@ function programResourceLoaderSpy(spy: SpyResourceLoader, results: {[key: string
}
});
}
main();

View File

@ -9,8 +9,8 @@
import {Component, ComponentMetadata, Directive, Injector} from '@angular/core';
import {TestBed, inject} from '@angular/core/testing';
import {ViewMetadata} from '../core_private';
import {MockDirectiveResolver} from '../testing';
import {ViewMetadata} from '@angular/compiler/core_private';
import {MockDirectiveResolver} from '@angular/compiler/testing';
export function main() {
describe('MockDirectiveResolver', () => {
@ -95,3 +95,5 @@ class SomeComponent {
@Directive({selector: 'some-other-directive'})
class SomeOtherDirective {
}
main();

View File

@ -232,3 +232,5 @@ export function main() {
});
});
}
main();

View File

@ -246,3 +246,5 @@ export function main() {
});
});
}
main();

View File

@ -11,7 +11,7 @@ import {Lexer} from '@angular/compiler/src/expression_parser/lexer';
import {Parser, TemplateBindingParseResult} from '@angular/compiler/src/expression_parser/parser';
import {expect} from '@angular/platform-browser/testing/matchers';
import {isBlank, isPresent} from '../../src/facade/lang';
import {isBlank, isPresent} from '@angular/facade/src/lang';
import {unparse} from './unparser';
import {validate} from './validator';
@ -541,3 +541,5 @@ export function main() {
});
});
}
main();

View File

@ -6,9 +6,9 @@
* found in the LICENSE file at https://angular.io/license
*/
import {AST, AstVisitor, Binary, BindingPipe, Chain, Conditional, EmptyExpr, FunctionCall, ImplicitReceiver, Interpolation, KeyedRead, KeyedWrite, LiteralArray, LiteralMap, LiteralPrimitive, MethodCall, PrefixNot, PropertyRead, PropertyWrite, Quote, SafeMethodCall, SafePropertyRead} from '../../src/expression_parser/ast';
import {StringWrapper, isPresent, isString} from '../../src/facade/lang';
import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from '../../src/ml_parser/interpolation_config';
import {AST, AstVisitor, Binary, BindingPipe, Chain, Conditional, EmptyExpr, FunctionCall, ImplicitReceiver, Interpolation, KeyedRead, KeyedWrite, LiteralArray, LiteralMap, LiteralPrimitive, MethodCall, PrefixNot, PropertyRead, PropertyWrite, Quote, SafeMethodCall, SafePropertyRead} from '@angular/compiler/src/expression_parser/ast';
import {StringWrapper, isPresent, isString} from '@angular/facade/src/lang';
import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from '@angular/compiler/src/ml_parser/interpolation_config';
class Unparser implements AstVisitor {
private static _quoteRegExp = /"/g;

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {AST, Binary, BindingPipe, Chain, Conditional, EmptyExpr, FunctionCall, ImplicitReceiver, Interpolation, KeyedRead, KeyedWrite, LiteralArray, LiteralMap, LiteralPrimitive, MethodCall, ParseSpan, PrefixNot, PropertyRead, PropertyWrite, Quote, RecursiveAstVisitor, SafeMethodCall, SafePropertyRead} from '../../src/expression_parser/ast';
import {AST, Binary, BindingPipe, Chain, Conditional, EmptyExpr, FunctionCall, ImplicitReceiver, Interpolation, KeyedRead, KeyedWrite, LiteralArray, LiteralMap, LiteralPrimitive, MethodCall, ParseSpan, PrefixNot, PropertyRead, PropertyWrite, Quote, RecursiveAstVisitor, SafeMethodCall, SafePropertyRead} from '@angular/compiler/src/expression_parser/ast';
import {unparse} from './unparser';

View File

@ -8,7 +8,7 @@
import {beforeEach, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
import {sha1} from '../../src/i18n/digest';
import {sha1} from '@angular/compiler/src/i18n/digest';
export function main(): void {
describe('sha1', () => {
@ -56,3 +56,5 @@ export function main(): void {
});
});
}
main();

View File

@ -8,13 +8,13 @@
import {beforeEach, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
import {digestMessage, serializeNodes as serializeI18nNodes} from '../../src/i18n/digest';
import {extractMessages, mergeTranslations} from '../../src/i18n/extractor_merger';
import * as i18n from '../../src/i18n/i18n_ast';
import {TranslationBundle} from '../../src/i18n/translation_bundle';
import * as html from '../../src/ml_parser/ast';
import {HtmlParser} from '../../src/ml_parser/html_parser';
import {DEFAULT_INTERPOLATION_CONFIG} from '../../src/ml_parser/interpolation_config';
import {digestMessage, serializeNodes as serializeI18nNodes} from '@angular/compiler/src/i18n/digest';
import {extractMessages, mergeTranslations} from '@angular/compiler/src/i18n/extractor_merger';
import * as i18n from '@angular/compiler/src/i18n/i18n_ast';
import {TranslationBundle} from '@angular/compiler/src/i18n/translation_bundle';
import * as html from '@angular/compiler/src/ml_parser/ast';
import {HtmlParser} from '@angular/compiler/src/ml_parser/html_parser';
import {DEFAULT_INTERPOLATION_CONFIG} from '@angular/compiler/src/ml_parser/interpolation_config';
import {serializeNodes as serializeHtmlNodes} from '../ml_parser/ast_serializer_spec';
export function main() {
@ -443,3 +443,5 @@ function extractErrors(
return errors.map((e): [string, string] => [e.msg, e.span.toString()]);
}
main();

View File

@ -10,9 +10,9 @@ import {extractMessages} from '@angular/compiler/src/i18n/extractor_merger';
import {Message} from '@angular/compiler/src/i18n/i18n_ast';
import {ddescribe, describe, expect, iit, it} from '@angular/core/testing/testing_internal';
import {serializeNodes} from '../../src/i18n/digest';
import {HtmlParser} from '../../src/ml_parser/html_parser';
import {DEFAULT_INTERPOLATION_CONFIG} from '../../src/ml_parser/interpolation_config';
import {serializeNodes} from '@angular/compiler/src/i18n/digest';
import {HtmlParser} from '@angular/compiler/src/ml_parser/html_parser';
import {DEFAULT_INTERPOLATION_CONFIG} from '@angular/compiler/src/ml_parser/interpolation_config';
export function main() {
describe('I18nParser', () => {
@ -332,3 +332,5 @@ function _extractMessages(
parseResult.rootNodes, DEFAULT_INTERPOLATION_CONFIG, implicitTags, implicitAttrs)
.messages;
}
main();

View File

@ -201,3 +201,5 @@ const XMB = `
</msg>
<msg id="93a30c67d4e6c9b37aecfe2ac0f2b5d366d7b520">it <ph name="START_BOLD_TEXT"><ex>&lt;b&gt;</ex></ph>should<ph name="CLOSE_BOLD_TEXT"><ex>&lt;/b&gt;</ex></ph> work</msg>
</messagebundle>`;
main();

Some files were not shown because too many files have changed in this diff Show More