Compare commits
30 Commits
master
...
do-not-del
Author | SHA1 | Date | |
---|---|---|---|
aac7ab7f36 | |||
5447430c3a | |||
8b52b2f415 | |||
db19e8200f | |||
4af0656dee | |||
5a61b0e995 | |||
ff6f5d1af6 | |||
2d0076195b | |||
439783d64d | |||
545636caaa | |||
272b147e44 | |||
779423c27a | |||
ec4a53e44d | |||
5ed72a8a6c | |||
3cc1a803f6 | |||
954d04a69d | |||
5af7b0cdc2 | |||
47935dd5cd | |||
b5f97b0410 | |||
fb3b490198 | |||
d4107ef2e3 | |||
29bea34169 | |||
117da538ae | |||
3b36692f26 | |||
fef78646b7 | |||
4e2bb7e2b7 | |||
811fcb3556 | |||
7a539d92ab | |||
884cf2df33 | |||
23a942ddec |
11
.bazelrc
Normal file
11
.bazelrc
Normal 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
4
.gitignore
vendored
@ -47,3 +47,7 @@ npm-debug.log
|
||||
|
||||
# rollup-test output
|
||||
/modules/rollup-test/dist/
|
||||
|
||||
# bazel runtime folders
|
||||
/bazel-*
|
||||
!bazel-run.sh
|
||||
|
19
.travis.yml
19
.travis.yml
@ -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
920
BUILD
Normal 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,
|
||||
)
|
73
DEVELOPER.md
73
DEVELOPER.md
@ -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
7
WORKSPACE
Normal 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
49
bazel-run.sh
Executable 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
9
build_defs/BUILD
Normal 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
126
build_defs/bundle.bzl
Normal 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
16
build_defs/check_cycle.js
Normal 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
69
build_defs/jasmine.bzl
Normal 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,
|
||||
),
|
||||
},
|
||||
)
|
21
build_defs/jasmine_launcher_template.sh
Normal file
21
build_defs/jasmine_launcher_template.sh
Normal 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
75
build_defs/karma.bzl
Normal 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)
|
21
build_defs/karma_launcher_template.sh
Normal file
21
build_defs/karma_launcher_template.sh
Normal 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}} "$@"
|
133
build_defs/node_modules_index.bzl
Normal file
133
build_defs/node_modules_index.bzl
Normal file
File diff suppressed because one or more lines are too long
221
build_defs/node_modules_indexer.js
Normal file
221
build_defs/node_modules_indexer.js
Normal 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
128
build_defs/nodejs.bzl
Normal 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,
|
||||
)
|
42
build_defs/nodejs_launcher_template.sh
Normal file
42
build_defs/nodejs_launcher_template.sh
Normal 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[@]}"
|
33
build_defs/nodejs_workspace.bzl
Normal file
33
build_defs/nodejs_workspace.bzl
Normal 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
118
build_defs/npm_package.bzl
Normal 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
64
build_defs/protractor.bzl
Normal 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)
|
55
build_defs/protractor_launcher_template.sh
Normal file
55
build_defs/protractor_launcher_template.sh
Normal 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
|
45
build_defs/rollup_config_template.js
Normal file
45
build_defs/rollup_config_template.js
Normal 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;
|
53
build_defs/tests/nodejs/BUILD
Normal file
53
build_defs/tests/nodejs/BUILD
Normal 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",
|
||||
)
|
0
build_defs/tests/nodejs/dir/index.js
Normal file
0
build_defs/tests/nodejs/dir/index.js
Normal file
0
build_defs/tests/nodejs/do_nothing.js
Normal file
0
build_defs/tests/nodejs/do_nothing.js
Normal file
3
build_defs/tests/nodejs/foo-module/index.js
Normal file
3
build_defs/tests/nodejs/foo-module/index.js
Normal file
@ -0,0 +1,3 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = 'foo';
|
5
build_defs/tests/nodejs/node_options.js
Normal file
5
build_defs/tests/nodejs/node_options.js
Normal file
@ -0,0 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
|
||||
assert.equal(typeof global.gc, 'function');
|
7
build_defs/tests/nodejs/use_absolute.js
Normal file
7
build_defs/tests/nodejs/use_absolute.js
Normal file
@ -0,0 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
|
||||
const foo = require('foo-module');
|
||||
|
||||
assert.equal(foo, 'foo');
|
7
build_defs/tests/nodejs/use_relative.js
Normal file
7
build_defs/tests/nodejs/use_relative.js
Normal file
@ -0,0 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
|
||||
const foo = require('./foo-module');
|
||||
|
||||
assert.equal(foo, 'foo');
|
168
build_defs/tests/typescript/BUILD
Normal file
168
build_defs/tests/typescript/BUILD
Normal 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"],
|
||||
)
|
3
build_defs/tests/typescript/ambient/index.d.ts
vendored
Normal file
3
build_defs/tests/typescript/ambient/index.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
import './process';
|
||||
|
||||
declare const process: any;
|
1
build_defs/tests/typescript/ambient/process.d.ts
vendored
Normal file
1
build_defs/tests/typescript/ambient/process.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
declare const process: any;
|
15
build_defs/tests/typescript/assert/index.ts
Normal file
15
build_defs/tests/typescript/assert/index.ts
Normal 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');
|
11
build_defs/tests/typescript/importing_modules/index.ts
Normal file
11
build_defs/tests/typescript/importing_modules/index.ts
Normal 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;
|
1
build_defs/tests/typescript/index.ts
Normal file
1
build_defs/tests/typescript/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export const basic = 'basic';
|
4
build_defs/tests/typescript/internal_stuff/index.ts
Normal file
4
build_defs/tests/typescript/internal_stuff/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export class A {
|
||||
/** @internal */ b = 'new A().b';
|
||||
c = 'new A().c';
|
||||
}
|
1
build_defs/tests/typescript/nested/@nested/index.ts
Normal file
1
build_defs/tests/typescript/nested/@nested/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export const nested = 'nested';
|
8
build_defs/tests/typescript/nested/@nested/tsconfig.json
Normal file
8
build_defs/tests/typescript/nested/@nested/tsconfig.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"noImplicitAny": false,
|
||||
"sourceMap": false
|
||||
}
|
||||
}
|
1
build_defs/tests/typescript/non_ambient/foo.d.ts
vendored
Normal file
1
build_defs/tests/typescript/non_ambient/foo.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export declare const foo: string;
|
1
build_defs/tests/typescript/non_ambient/index.d.ts
vendored
Normal file
1
build_defs/tests/typescript/non_ambient/index.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export * from './foo';
|
1
build_defs/tests/typescript/sub.ts
Normal file
1
build_defs/tests/typescript/sub.ts
Normal file
@ -0,0 +1 @@
|
||||
export const sub = 'sub';
|
8
build_defs/tests/typescript/tsconfig.json
Normal file
8
build_defs/tests/typescript/tsconfig.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"noImplicitAny": false,
|
||||
"sourceMap": false
|
||||
}
|
||||
}
|
1
build_defs/tests/typescript/use_ambient/index.ts
Normal file
1
build_defs/tests/typescript/use_ambient/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export const useAmbient = process.cwd();
|
6
build_defs/tests/typescript/use_internal/index.ts
Normal file
6
build_defs/tests/typescript/use_internal/index.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import {A} from 'internal_stuff';
|
||||
|
||||
export class B extends A {
|
||||
}
|
||||
|
||||
export const useInternal = new A().b;
|
1
build_defs/tests/typescript/use_non_ambient/index.ts
Normal file
1
build_defs/tests/typescript/use_non_ambient/index.ts
Normal file
@ -0,0 +1 @@
|
||||
import {foo} from 'non_ambient';
|
4
build_defs/tests/typescript/use_transitive/index.ts
Normal file
4
build_defs/tests/typescript/use_transitive/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import {B} from 'use_internal';
|
||||
|
||||
// c is an inherited property from A
|
||||
export const useTransitive = new B().c;
|
@ -0,0 +1 @@
|
||||
export const useTransitiveAmbient = process.cwd();
|
52
build_defs/tools/BUILD
Normal file
52
build_defs/tools/BUILD
Normal 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
23
build_defs/tools/copy.js
Normal 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));
|
30
build_defs/tools/downlevel_declaration.js
Normal file
30
build_defs/tools/downlevel_declaration.js
Normal 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));
|
108
build_defs/tools/flatten_sourcemap.js
Normal file
108
build_defs/tools/flatten_sourcemap.js
Normal 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();
|
||||
}
|
104
build_defs/tools/merge_tsconfig.js
Normal file
104
build_defs/tools/merge_tsconfig.js
Normal 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));
|
14
build_defs/tools/serve_runfiles.js
Normal file
14
build_defs/tools/serve_runfiles.js
Normal 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()],
|
||||
});
|
37
build_defs/tools/uglifyjs_wrapped.sh
Executable file
37
build_defs/tools/uglifyjs_wrapped.sh
Executable 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[@]}"
|
114
build_defs/ts_api_guardian.bzl
Normal file
114
build_defs/ts_api_guardian.bzl
Normal 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,
|
||||
),
|
||||
},
|
||||
)
|
44
build_defs/ts_api_guardian_launcher_template.sh
Normal file
44
build_defs/ts_api_guardian_launcher_template.sh
Normal 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
439
build_defs/typescript.bzl
Normal 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
151
build_defs/utils.bzl
Normal 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
BIN
favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
12
ibazel
Executable file
12
ibazel
Executable 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}" "$@"
|
@ -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: {
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -183,3 +183,5 @@ class TestComponent {
|
||||
this.functionCondition = function(s: any, n: any): boolean { return s == 'foo' && n == 1; };
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
|
@ -143,3 +143,5 @@ class TestLocalization extends NgLocalization {
|
||||
class TestComponent {
|
||||
switchValue: number = null;
|
||||
}
|
||||
|
||||
main();
|
||||
|
@ -153,3 +153,5 @@ export function main() {
|
||||
class TestComponent {
|
||||
expr: any;
|
||||
}
|
||||
|
||||
main();
|
||||
|
@ -158,3 +158,5 @@ class TestComponent {
|
||||
this.when2 = null;
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
|
@ -163,3 +163,5 @@ class TestComponent {
|
||||
currentTplRef: TemplateRef<any>;
|
||||
context: any = {foo: 'bar'};
|
||||
}
|
||||
|
||||
main();
|
||||
|
@ -62,3 +62,5 @@ class TestComponent {
|
||||
text: string;
|
||||
constructor() { this.text = 'foo'; }
|
||||
}
|
||||
|
||||
main();
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -66,3 +66,5 @@ export function main() {
|
||||
class TestLocalization extends NgLocalization {
|
||||
getPluralCategory(value: number): string { return value > 1 && value < 6 ? 'many' : 'other'; }
|
||||
}
|
||||
|
||||
main();
|
||||
|
@ -47,3 +47,5 @@ export function main() {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
main();
|
||||
|
@ -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();
|
||||
|
@ -40,3 +40,5 @@ export function main() {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
main();
|
||||
|
@ -82,3 +82,5 @@ export function main() {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
main();
|
||||
|
@ -111,3 +111,5 @@ export function main() {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
main();
|
||||
|
@ -41,3 +41,5 @@ export function main() {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
main();
|
||||
|
2
modules/@angular/compiler-cli/integrationtest/types.d.ts
vendored
Normal file
2
modules/@angular/compiler-cli/integrationtest/types.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
///<reference path="node_modules/@types/jasmine/index.d.ts"/>
|
||||
///<reference path="node_modules/@types/node/index.d.ts"/>
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -141,3 +141,5 @@ class DirectiveWithAfterViewInitMethod {
|
||||
class DirectiveWithAfterViewCheckedMethod {
|
||||
ngAfterViewChecked() {}
|
||||
}
|
||||
|
||||
main();
|
||||
|
@ -444,3 +444,5 @@ function programResourceLoaderSpy(spy: SpyResourceLoader, results: {[key: string
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
main();
|
||||
|
@ -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();
|
||||
|
@ -232,3 +232,5 @@ export function main() {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
main();
|
||||
|
@ -246,3 +246,5 @@ export function main() {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
main();
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -201,3 +201,5 @@ const XMB = `
|
||||
</msg>
|
||||
<msg id="93a30c67d4e6c9b37aecfe2ac0f2b5d366d7b520">it <ph name="START_BOLD_TEXT"><ex><b></ex></ph>should<ph name="CLOSE_BOLD_TEXT"><ex></b></ex></ph> work</msg>
|
||||
</messagebundle>`;
|
||||
|
||||
main();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user