From 6b00b4ad60f61339dd4af3efd8f1b7fe91c9ae5c Mon Sep 17 00:00:00 2001 From: Yannic Bonenberger Date: Sun, 28 Jun 2020 01:25:56 +0200 Subject: [PATCH] Remove (deprecated) implicit outputs, part 1 The `outputs` parameter on the `rule()` function has been deprecated and will be removed in a future version of Bazel. See https://github.com/bazelbuild/bazel/issues/7977 for context. --- closure/compiler/closure_js_binary.bzl | 70 +++++++--- closure/compiler/closure_js_library.bzl | 40 +++--- closure/compiler/test/BUILD | 79 +++++------ closure/compiler/test/closure_js_deps/BUILD | 2 +- .../test/exports_and_entry_points/BUILD | 63 +++++---- ...xported_function_will_go_in_binary_test.js | 35 +++++ ..._that_executes_code_in_global_namespace.js | 1 + ...is_listed_in_entry_points_code_shows_up.js | 1 + ...t_listed_in_entry_points_code_goes_poof.js | 1 + ...xported_function_will_go_in_binary_test.js | 64 +++++++++ .../es6_with_arrow_function_gets_expanded.js | 1 + .../es6_with_const_keyword_gets_removed.js | 1 + .../extern_file_names_didnt_collapse.js | 1 + closure/compiler/test/golden/minification.js | 1 + .../test/golden/minification_with_wrapper.js | 1 + .../golden/multiline_output_wrapper_test.js | 2 + .../golden/output_wrapper_dash_dash_space.js | 1 + ...esn_contain_weird_bazel_directories.js.map | 9 ++ ...wrapper_has_different_mapping_codes.js.map | 9 ++ .../strict_output_language_adds_use_strict.js | 1 + closure/compiler/test/js_zip/BUILD | 14 +- .../golden/zip_files_are_suppressable.js | 1 + .../golden/zip_files_works_correctly.js | 1 + closure/compiler/test/reports/BUILD | 14 +- .../golden/property_renaming_report.txt | 1 + .../property_without_quotes_gets_renamed.js | 1 + .../test/strict_dependency_checking/BUILD | 15 ++- ...tly_when_referenced_without_root_prefix.js | 1 + .../es6_relative_imports_work_correctly.js | 1 + closure/defs.bzl | 4 +- closure/private/expected_output_test.bzl | 123 ++++++++++++++++++ closure/stylesheets/test/BUILD | 7 +- ...y_goog_get_css_name_calls_get_rewritten.js | 1 + 33 files changed, 427 insertions(+), 140 deletions(-) create mode 100644 closure/compiler/test/exports_and_entry_points/es6_exported_function_will_go_in_binary_test.js create mode 100644 closure/compiler/test/exports_and_entry_points/golden/file_without_namespaces_exports_or_entry_points_produces_binary_that_executes_code_in_global_namespace.js create mode 100644 closure/compiler/test/exports_and_entry_points/golden/strict_mode_global_code_is_listed_in_entry_points_code_shows_up.js create mode 100644 closure/compiler/test/exports_and_entry_points/golden/strict_mode_global_code_not_listed_in_entry_points_code_goes_poof.js create mode 100644 closure/compiler/test/exports_and_entry_points/goog_exported_function_will_go_in_binary_test.js create mode 100644 closure/compiler/test/golden/es6_with_arrow_function_gets_expanded.js create mode 100644 closure/compiler/test/golden/es6_with_const_keyword_gets_removed.js create mode 100644 closure/compiler/test/golden/extern_file_names_didnt_collapse.js create mode 100644 closure/compiler/test/golden/minification.js create mode 100644 closure/compiler/test/golden/minification_with_wrapper.js create mode 100644 closure/compiler/test/golden/multiline_output_wrapper_test.js create mode 100644 closure/compiler/test/golden/output_wrapper_dash_dash_space.js create mode 100644 closure/compiler/test/golden/sourcemap_doesn_contain_weird_bazel_directories.js.map create mode 100644 closure/compiler/test/golden/sourcemap_with_wrapper_has_different_mapping_codes.js.map create mode 100644 closure/compiler/test/golden/strict_output_language_adds_use_strict.js create mode 100644 closure/compiler/test/js_zip/golden/zip_files_are_suppressable.js create mode 100644 closure/compiler/test/js_zip/golden/zip_files_works_correctly.js create mode 100644 closure/compiler/test/reports/golden/property_renaming_report.txt create mode 100644 closure/compiler/test/reports/golden/property_without_quotes_gets_renamed.js create mode 100644 closure/compiler/test/strict_dependency_checking/golden/es6_modules_with_root_paths_compile_correctly_when_referenced_without_root_prefix.js create mode 100644 closure/compiler/test/strict_dependency_checking/golden/es6_relative_imports_work_correctly.js create mode 100644 closure/private/expected_output_test.bzl create mode 100644 closure/stylesheets/test/golden/js_binary_references_css_binary_goog_get_css_name_calls_get_rewritten.js diff --git a/closure/compiler/closure_js_binary.bzl b/closure/compiler/closure_js_binary.bzl index 1469058ef9..1e56f78d58 100644 --- a/closure/compiler/closure_js_binary.bzl +++ b/closure/compiler/closure_js_binary.bzl @@ -33,6 +33,23 @@ load( "closure_js_aspect", ) +JavaScriptBinaryInfo = provider( + doc = "Encapsulates information provided by `closure_js_binary`.", + fields = { + "output": """ +Primary output file. +""".strip(), + "sourcemap": """ +The sourcemap file. +""".strip(), + "property_renaming_report": """ +File containing a serialized version of the property renaming map. + +If `compilation_level` is not `ADVANCED`, this is an empty file. +""".strip(), + }, +) + _dependency_mode_warning = '\n'.join([ "{target}: dependency_mode={old_mode} is deprecated and will be " + "removed soon; prefer to use its equivalent {new_mode}.", @@ -77,11 +94,19 @@ def _impl(ctx): _validate_css_graph(ctx, js) + output = ctx.actions.declare_file("{}.js".format(ctx.attr.name)) + sourcemap = ctx.actions.declare_file("{}.js.map".format(ctx.attr.name)) + + if ctx.outputs.property_renaming_report: + property_renaming_report = ctx.outputs.property_renaming_report + else: + property_renaming_report = ctx.actions.declare_file("{}.property_renaming_report.txt".format(ctx.attr.name)) + # This is the list of files we'll be generating. - outputs = [ctx.outputs.bin, ctx.outputs.map, ctx.outputs.stderr] + outputs = [output, sourcemap, ctx.outputs.stderr] # This is the subset of that list we'll report to parent rules. - files = [ctx.outputs.bin, ctx.outputs.map] + files = [output, sourcemap] # JsCompiler is thin veneer over the Closure compiler. It's configured with a # superset of its flags. It introduces a private testing API, allows per-file @@ -91,9 +116,9 @@ def _impl(ctx): args = [ "JsCompiler", "--js_output_file", - ctx.outputs.bin.path, + output.path, "--create_source_map", - ctx.outputs.map.path, + sourcemap.path, "--output_errors", ctx.outputs.stderr.path, "--language_in", @@ -138,7 +163,7 @@ def _impl(ctx): js_module_roots = sort_roots( depset(transitive = [ find_js_module_roots( - [ctx.outputs.bin], + [output], ctx.workspace_name, ctx.label, getattr(ctx.attr, "includes", []), @@ -155,7 +180,7 @@ def _impl(ctx): # stored within the same directory as the compiled JS binary; therefore, the # JSON sourcemap file should cite that file as relative to itself. args.append("--source_map_location_mapping") - args.append("%s|%s" % (ctx.outputs.bin.path, ctx.outputs.bin.basename)) + args.append("%s|%s" % (output.path, output.basename)) # By default we're going to include the raw sources in the .js.map file. This # can be disabled with the nodefs attribute. @@ -205,12 +230,16 @@ def _impl(ctx): if ctx.attr.output_wrapper == "(function(){%output%}).call(this);": args.append("--assume_function_wrapper") - if ctx.outputs.property_renaming_report: - report = ctx.outputs.property_renaming_report - files.append(report) - outputs.append(report) + if ("ADVANCED" == ctx.attr.compilation_level) and (not ctx.attr.internal_expect_failure): + files.append(property_renaming_report) + outputs.append(property_renaming_report) args.append("--property_renaming_report") - args.append(report.path) + args.append(property_renaming_report.path) + else: + ctx.actions.write( + output = property_renaming_report, + content = "", + ) # All sources must conform to these protos. for config in ctx.files.conformance: @@ -268,7 +297,7 @@ def _impl(ctx): execution_requirements = {"supports-workers": "1"}, progress_message = "Compiling %d JavaScript files to %s" % ( len(js.srcs.to_list()), - ctx.outputs.bin.short_path, + output.short_path, ), ) @@ -280,8 +309,8 @@ def _impl(ctx): files = depset(files), closure_js_library = js, closure_js_binary = struct( - bin = ctx.outputs.bin, - map = ctx.outputs.map, + bin = output, + map = sourcemap, language = ctx.attr.language, ), runfiles = ctx.runfiles( @@ -292,6 +321,17 @@ def _impl(ctx): collect_runfiles(ctx.attr.data), ]), ), + + # Modern-stype providers. + # + # TODO(yannic): Remove legacy providers. + providers = [ + JavaScriptBinaryInfo( + output = output, + sourcemap = sourcemap, + property_renaming_report = property_renaming_report, + ), + ], ) def _validate_css_graph(ctx, js): @@ -345,8 +385,6 @@ closure_js_binary = rule( "internal_expect_warnings": attr.bool(default = False), }, **CLOSURE_JS_TOOLCHAIN_ATTRS), outputs = { - "bin": "%{name}.js", - "map": "%{name}.js.map", "stderr": "%{name}-stderr.txt", }, ) diff --git a/closure/compiler/closure_js_library.bzl b/closure/compiler/closure_js_library.bzl index 2e38db637d..c1e524b609 100644 --- a/closure/compiler/closure_js_library.bzl +++ b/closure/compiler/closure_js_library.bzl @@ -104,7 +104,6 @@ def _closure_js_library_impl( # and will be replaced with |actions.declare_file()| soon. deprecated_info_file = None, deprecated_stderr_file = None, - deprecated_ijs_file = None, deprecated_typecheck_file = None): # TODO(yannic): Figure out how to modify |find_js_module_roots| # so that we won't need |workspace_name| anymore. @@ -150,11 +149,8 @@ def _closure_js_library_impl( deprecated_stderr_file, "%s-stderr.txt" % label.name, ) - ijs_file = _maybe_declare_file( - actions, - deprecated_ijs_file, - "%s.i.js" % label.name, - ) + + ijs_file = ctx.actions.declare_file("{}.i.js".format(label.name)) if not no_closure_library: deps = deps + closure_library_base @@ -403,24 +399,23 @@ def _closure_js_library(ctx): srcs = ctx.files.externs + srcs library = _closure_js_library_impl( - ctx, - srcs, - ctx.attr.deps, - ctx.attr.testonly, - ctx.attr.suppress, - ctx.attr.lenient, - ctx.attr.convention, - getattr(ctx.attr, "includes", []), - ctx.attr.exports, - ctx.files.internal_descriptors, - ctx.attr.no_closure_library, - ctx.attr.internal_expect_failure, + ctx = ctx, + srcs = srcs, + deps = ctx.attr.deps, + testonly = ctx.attr.testonly, + suppress = ctx.attr.suppress, + lenient = ctx.attr.lenient, + convention = ctx.attr.convention, + includes = getattr(ctx.attr, "includes", []), + exports = ctx.attr.exports, + internal_descriptors = ctx.files.internal_descriptors, + no_closure_library = ctx.attr.no_closure_library, + internal_expect_failure = ctx.attr.internal_expect_failure, # Deprecated output files. - ctx.outputs.info, - ctx.outputs.stderr, - ctx.outputs.ijs, - ctx.outputs.typecheck, + deprecated_info_file = ctx.outputs.info, + deprecated_stderr_file = ctx.outputs.stderr, + deprecated_typecheck_file = ctx.outputs.typecheck, ) return struct( @@ -476,7 +471,6 @@ closure_js_library = rule( outputs = { "info": "%{name}.pbtxt", "stderr": "%{name}-stderr.txt", - "ijs": "%{name}.i.js", "typecheck": "%{name}_typecheck", # dummy output file }, ) diff --git a/closure/compiler/test/BUILD b/closure/compiler/test/BUILD index e16a705b2d..8604742ac2 100644 --- a/closure/compiler/test/BUILD +++ b/closure/compiler/test/BUILD @@ -16,6 +16,7 @@ package(default_testonly = True) licenses(["notice"]) # Apache 2.0 +load("//closure/private:expected_output_test.bzl", "closure_js_binary_output_test", "closure_js_binary_sourcemap_test") load("//closure/private:file_test.bzl", "file_test") load("//closure:defs.bzl", "closure_js_binary", "closure_js_library") @@ -30,24 +31,16 @@ closure_js_binary( deps = [":hello_lib"], ) -file_test( +closure_js_binary_output_test( name = "minification", - content = "console.log(\"hello world\");\n", - file = "hello_bin.js", + expected_output = "golden/minification.js", + target = ":hello_bin", ) -file_test( +closure_js_binary_sourcemap_test( name = "sourcemap_doesntContainWeirdBazelDirectories", - content = ("{\n" + - "\"version\":3,\n" + - "\"file\":\"hello_bin.js\",\n" + - "\"lineCount\":1,\n" + - "\"mappings\":\"AAgBAA,OAAA,CAAUC,GAAV,CAAgB,aAAhB;\",\n" + - "\"sources\":[\"/closure/compiler/test/hello.js\"],\n" + - "\"sourcesContent\":[\"// Copyright 2016 The Closure Rules Authors. All rights reserved.\\n//\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\");\\n// you may not use this file except in compliance with the License.\\n// You may obtain a copy of the License at\\n//\\n// http://www.apache.org/licenses/LICENSE-2.0\\n//\\n// Unless required by applicable law or agreed to in writing, software\\n// distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\\n// See the License for the specific language governing permissions and\\n// limitations under the License.\\n\\n// hello world\\n\\nconsole . log ( 'hello world' ) ;\\n\"],\n" + - "\"names\":[\"console\",\"log\"]\n" + - "}\n"), - file = "hello_bin.js.map", + expected_output = "golden/sourcemap_doesn_contain_weird_bazel_directories.js.map", + target = ":hello_bin", ) # Make sure bazel doesn't complain about some outputs not created. @@ -64,24 +57,16 @@ closure_js_binary( deps = [":hello_lib"], ) -file_test( - name = "minificationWithWrapper", - content = "(function(){console.log(\"hello world\");}).call(this);\n", - file = "hello_wrap_bin.js", +closure_js_binary_output_test( + name = "minification_with_wrapper", + expected_output = "golden/minification_with_wrapper.js", + target = ":hello_wrap_bin", ) -file_test( +closure_js_binary_sourcemap_test( name = "sourcemapWithWrapper_hasDifferentMappingCodes", - content = "{\n" + - "\"version\":3,\n" + - "\"file\":\"hello_wrap_bin.js\",\n" + - "\"lineCount\":1,\n" + - "\"mappings\":\"A,YAgBAA,OAAA,CAAUC,GAAV,CAAgB,aAAhB;\",\n" + - "\"sources\":[\"/closure/compiler/test/hello.js\"],\n" + - "\"sourcesContent\":[\"// Copyright 2016 The Closure Rules Authors. All rights reserved.\\n//\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\");\\n// you may not use this file except in compliance with the License.\\n// You may obtain a copy of the License at\\n//\\n// http://www.apache.org/licenses/LICENSE-2.0\\n//\\n// Unless required by applicable law or agreed to in writing, software\\n// distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\\n// See the License for the specific language governing permissions and\\n// limitations under the License.\\n\\n// hello world\\n\\nconsole . log ( 'hello world' ) ;\\n\"],\n" + - "\"names\":[\"console\",\"log\"]\n" + - "}\n", - file = "hello_wrap_bin.js.map", + expected_output = "golden/sourcemap_with_wrapper_has_different_mapping_codes.js.map", + target = ":hello_wrap_bin", ) closure_js_binary( @@ -90,10 +75,10 @@ closure_js_binary( deps = [":hello_lib"], ) -file_test( +closure_js_binary_output_test( name = "strictOutputLanguage_addsUseStrict", - content = "'use strict';console.log(\"hello world\");\n", - file = "hello_es5strict_bin.js", + expected_output = "golden/strict_output_language_adds_use_strict.js", + target = ":hello_es5strict_bin", ) closure_js_library( @@ -109,10 +94,10 @@ closure_js_binary( deps = [":es6const_lib"], ) -file_test( +closure_js_binary_output_test( name = "es6WithConstKeyword_getsRemoved", - content = "var hello=\"hello world\";console.log(hello);\n", - file = "es6const_bin.js", + expected_output = "golden/es6_with_const_keyword_gets_removed.js", + target = ":es6const_bin", ) closure_js_library( @@ -128,10 +113,10 @@ closure_js_binary( deps = [":es6arrow_lib"], ) -file_test( +closure_js_binary_output_test( name = "es6WithArrowFunction_getsExpanded", - content = "var hello=function(e){return e+\" world\"};console.log(hello(\"hello\"));\n", - file = "es6arrow_bin.js", + expected_output = "golden/es6_with_arrow_function_gets_expanded.js", + target = ":es6arrow_bin", ) closure_js_library( @@ -165,10 +150,10 @@ closure_js_binary( deps = [":hello_lib"], ) -file_test( +closure_js_binary_output_test( name = "output_wrapper_dash_dash_space", - content = "-- console.log(\"hello world\");\n", - file = "hello_output_wrapper_dash_dash_space_bin.js", + expected_output = "golden/output_wrapper_dash_dash_space.js", + target = ":hello_output_wrapper_dash_dash_space_bin", ) closure_js_binary( @@ -177,10 +162,10 @@ closure_js_binary( deps = [":empty_lib"], ) -file_test( +closure_js_binary_output_test( name = "multiline_output_wrapper_test", - content = "\n//# sourceMappingURL=/app.js.map\n", - file = "multiline_output_wrapper_bin.js", + expected_output = "golden/multiline_output_wrapper_test.js", + target = ":multiline_output_wrapper_bin", ) ################################################################################ @@ -202,10 +187,10 @@ closure_js_binary( deps = [":extern_invoke_lib"], ) -file_test( +closure_js_binary_output_test( name = "externFile_namesDidntCollapse", - content = "omg.im_an_extern(\"hello\");\n", - file = "extern_bin.js", + expected_output = "golden/extern_file_names_didnt_collapse.js", + target = ":extern_bin", ) closure_js_library( diff --git a/closure/compiler/test/closure_js_deps/BUILD b/closure/compiler/test/closure_js_deps/BUILD index 91686b8a1c..703597e140 100644 --- a/closure/compiler/test/closure_js_deps/BUILD +++ b/closure/compiler/test/closure_js_deps/BUILD @@ -157,5 +157,5 @@ genrule( file_test( name = "srcsReferencingJsBinary_getsJsBinaryAndMapNotData", file = "hyperion2_bin_srcs.txt", - regexp = "^.*/closure/compiler/test/closure_js_deps/hyperion2_bin.js .*/closure/compiler/test/closure_js_deps/hyperion2_bin.js.map$", + regexp = "^.*/closure/compiler/test/closure_js_deps/hyperion2_bin.js .*/closure/compiler/test/closure_js_deps/hyperion2_bin.js.map .*/closure/compiler/test/closure_js_deps/hyperion2_bin.property_renaming_report.txt$", ) diff --git a/closure/compiler/test/exports_and_entry_points/BUILD b/closure/compiler/test/exports_and_entry_points/BUILD index f189db2598..90bb193bce 100644 --- a/closure/compiler/test/exports_and_entry_points/BUILD +++ b/closure/compiler/test/exports_and_entry_points/BUILD @@ -16,8 +16,8 @@ package(default_testonly = True) licenses(["notice"]) # Apache 2.0 -load("//closure/private:file_test.bzl", "file_test") -load("//closure:defs.bzl", "closure_js_binary", "closure_js_library") +load("//closure/private:expected_output_test.bzl", "closure_js_binary_output_test") +load("//closure:defs.bzl", "closure_js_binary", "closure_js_library", "closure_js_test") ################################################################################ # Assume we want to write a JavaScript program (not a library) that we compile @@ -39,10 +39,10 @@ closure_js_binary( deps = [":program_lib"], ) -file_test( +closure_js_binary_output_test( name = "fileWithoutNamespacesExportsOrEntryPoints_producesBinaryThatExecutesCodeInGlobalNamespace", - content = "console.log(\"hi\");\n", - file = "program_bin.js", + expected_output = "golden/file_without_namespaces_exports_or_entry_points_produces_binary_that_executes_code_in_global_namespace.js", + target = ":program_bin", ) ################################################################################ @@ -59,15 +59,19 @@ closure_js_library( srcs = ["library.js"], ) -closure_js_binary( - name = "library_bin", - deps = [":library_lib"], -) - -file_test( +closure_js_test( name = "es6_exportedFunction_willGoInBinary", - file = "library_bin.js", - regexp = "iWillGoIntoTheBinary", + srcs = [ + "es6_exported_function_will_go_in_binary_test.js", + ], + entry_points = [ + "/closure/compiler/test/exports_and_entry_points/es6_exported_function_will_go_in_binary_test.js", + "/closure/compiler/test/exports_and_entry_points/library.js", + ], + deps = [ + ":library_lib", + "//closure/library/testing:testsuite", + ], ) ################################################################################ @@ -86,16 +90,19 @@ closure_js_library( suppress = ["useOfGoogProvide"], ) -closure_js_binary( - name = "library_goog_bin", - entry_points = ["goog:io.bazel.rules.closure.iWillGoIntoTheBinary"], - deps = [":library_goog_lib"], -) - -file_test( +closure_js_test( name = "goog_exportedFunction_willGoInBinary", - file = "library_goog_bin.js", - regexp = "iWillGoIntoTheBinary", + srcs = [ + "goog_exported_function_will_go_in_binary_test.js", + ], + entry_points = [ + "/closure/compiler/test/exports_and_entry_points/goog_exported_function_will_go_in_binary_test.js", + "/closure/compiler/test/exports_and_entry_points/library_goog.js", + ], + deps = [ + ":library_goog_lib", + "//closure/library/testing:testsuite", + ], ) ################################################################################ @@ -113,10 +120,10 @@ closure_js_binary( ], ) -file_test( +closure_js_binary_output_test( name = "strictModeGlobalCodeNotListedInEntryPoints_codeGoesPoof", - content = "\n", - file = "program_strict_bin.js", + expected_output = "golden/strict_mode_global_code_not_listed_in_entry_points_code_goes_poof.js", + target = ":program_strict_bin", ) closure_js_binary( @@ -129,8 +136,8 @@ closure_js_binary( ], ) -file_test( +closure_js_binary_output_test( name = "strictModeGlobalCodeIsListedInEntryPoints_codeShowsUp", - content = "console.log(\"hi\");\n", - file = "program_strict_bin2.js", + expected_output = "golden/strict_mode_global_code_is_listed_in_entry_points_code_shows_up.js", + target = ":program_strict_bin2", ) diff --git a/closure/compiler/test/exports_and_entry_points/es6_exported_function_will_go_in_binary_test.js b/closure/compiler/test/exports_and_entry_points/es6_exported_function_will_go_in_binary_test.js new file mode 100644 index 0000000000..2271e30732 --- /dev/null +++ b/closure/compiler/test/exports_and_entry_points/es6_exported_function_will_go_in_binary_test.js @@ -0,0 +1,35 @@ +// Copyright 2020 The Closure Rules 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. + +import testSuite from 'goog:goog.testing.testSuite'; + + + +class ES6ExportedFunctionWillGoInBinaryTest { + /** @return {void} */ + test_myNameWillBeMinified() { + assertTrue(undefined === window['myNameWillBeMinified']); + } + + /** @return {void} */ + test_iWillGoIntoTheBinary() { + assertTrue("function" === typeof window['iWillGoIntoTheBinary']); + } + + /** @return {void} */ + test_iWillGetPrunedByTheCompiler() { + assertTrue(undefined === window['iWillGetPrunedByTheCompiler']); + } +} +testSuite(new ES6ExportedFunctionWillGoInBinaryTest()); diff --git a/closure/compiler/test/exports_and_entry_points/golden/file_without_namespaces_exports_or_entry_points_produces_binary_that_executes_code_in_global_namespace.js b/closure/compiler/test/exports_and_entry_points/golden/file_without_namespaces_exports_or_entry_points_produces_binary_that_executes_code_in_global_namespace.js new file mode 100644 index 0000000000..d914c6066c --- /dev/null +++ b/closure/compiler/test/exports_and_entry_points/golden/file_without_namespaces_exports_or_entry_points_produces_binary_that_executes_code_in_global_namespace.js @@ -0,0 +1 @@ +console.log("hi"); diff --git a/closure/compiler/test/exports_and_entry_points/golden/strict_mode_global_code_is_listed_in_entry_points_code_shows_up.js b/closure/compiler/test/exports_and_entry_points/golden/strict_mode_global_code_is_listed_in_entry_points_code_shows_up.js new file mode 100644 index 0000000000..d914c6066c --- /dev/null +++ b/closure/compiler/test/exports_and_entry_points/golden/strict_mode_global_code_is_listed_in_entry_points_code_shows_up.js @@ -0,0 +1 @@ +console.log("hi"); diff --git a/closure/compiler/test/exports_and_entry_points/golden/strict_mode_global_code_not_listed_in_entry_points_code_goes_poof.js b/closure/compiler/test/exports_and_entry_points/golden/strict_mode_global_code_not_listed_in_entry_points_code_goes_poof.js new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/closure/compiler/test/exports_and_entry_points/golden/strict_mode_global_code_not_listed_in_entry_points_code_goes_poof.js @@ -0,0 +1 @@ + diff --git a/closure/compiler/test/exports_and_entry_points/goog_exported_function_will_go_in_binary_test.js b/closure/compiler/test/exports_and_entry_points/goog_exported_function_will_go_in_binary_test.js new file mode 100644 index 0000000000..1ab47f7917 --- /dev/null +++ b/closure/compiler/test/exports_and_entry_points/goog_exported_function_will_go_in_binary_test.js @@ -0,0 +1,64 @@ +// Copyright 2020 The Closure Rules 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. + +import testSuite from 'goog:goog.testing.testSuite'; + + + +/** + * @param {!Object} obj + * @param {!Array} namespaces + * @return {!Object} + */ +function getNamespaceInternal(obj, namespaces) { + if (namespaces.length < 1) { + return obj; + } + + const ns = namespaces[0]; + const newObj = /** @type {undefined|!Object} */ (obj[ns]); + assertTrue(undefined !== newObj); + return getNamespaceInternal( + /** @type {!Object} */ (newObj), namespaces.slice(1)); +} + + +/** + * @return {!Object} + */ +function getNamespace() { + return getNamespaceInternal(window, ['io', 'bazel', 'rules', 'closure']); +} + + +class GoogExportedFunctionWillGoInBinaryTest { + /** @return {void} */ + test_myNameWillBeMinified() { + const namespace = getNamespace(); + assertTrue(undefined === namespace['myNameWillBeMinified']); + } + + /** @return {void} */ + test_iWillGoIntoTheBinary() { + const namespace = getNamespace(); + assertTrue("function" === typeof namespace['iWillGoIntoTheBinary']); + } + + /** @return {void} */ + test_iWillGetPrunedByTheCompiler() { + const namespace = getNamespace(); + assertTrue(undefined === namespace['iWillGetPrunedByTheCompiler']); + } +} +testSuite(new GoogExportedFunctionWillGoInBinaryTest()); diff --git a/closure/compiler/test/golden/es6_with_arrow_function_gets_expanded.js b/closure/compiler/test/golden/es6_with_arrow_function_gets_expanded.js new file mode 100644 index 0000000000..7701e4f66a --- /dev/null +++ b/closure/compiler/test/golden/es6_with_arrow_function_gets_expanded.js @@ -0,0 +1 @@ +var hello=function(e){return e+" world"};console.log(hello("hello")); diff --git a/closure/compiler/test/golden/es6_with_const_keyword_gets_removed.js b/closure/compiler/test/golden/es6_with_const_keyword_gets_removed.js new file mode 100644 index 0000000000..afc45f0928 --- /dev/null +++ b/closure/compiler/test/golden/es6_with_const_keyword_gets_removed.js @@ -0,0 +1 @@ +var hello="hello world";console.log(hello); diff --git a/closure/compiler/test/golden/extern_file_names_didnt_collapse.js b/closure/compiler/test/golden/extern_file_names_didnt_collapse.js new file mode 100644 index 0000000000..16139cf101 --- /dev/null +++ b/closure/compiler/test/golden/extern_file_names_didnt_collapse.js @@ -0,0 +1 @@ +omg.im_an_extern("hello"); diff --git a/closure/compiler/test/golden/minification.js b/closure/compiler/test/golden/minification.js new file mode 100644 index 0000000000..6b2b3db0f6 --- /dev/null +++ b/closure/compiler/test/golden/minification.js @@ -0,0 +1 @@ +console.log("hello world"); diff --git a/closure/compiler/test/golden/minification_with_wrapper.js b/closure/compiler/test/golden/minification_with_wrapper.js new file mode 100644 index 0000000000..37d76568a6 --- /dev/null +++ b/closure/compiler/test/golden/minification_with_wrapper.js @@ -0,0 +1 @@ +(function(){console.log("hello world");}).call(this); diff --git a/closure/compiler/test/golden/multiline_output_wrapper_test.js b/closure/compiler/test/golden/multiline_output_wrapper_test.js new file mode 100644 index 0000000000..97e411820c --- /dev/null +++ b/closure/compiler/test/golden/multiline_output_wrapper_test.js @@ -0,0 +1,2 @@ + +//# sourceMappingURL=/app.js.map diff --git a/closure/compiler/test/golden/output_wrapper_dash_dash_space.js b/closure/compiler/test/golden/output_wrapper_dash_dash_space.js new file mode 100644 index 0000000000..8e984feff3 --- /dev/null +++ b/closure/compiler/test/golden/output_wrapper_dash_dash_space.js @@ -0,0 +1 @@ +-- console.log("hello world"); diff --git a/closure/compiler/test/golden/sourcemap_doesn_contain_weird_bazel_directories.js.map b/closure/compiler/test/golden/sourcemap_doesn_contain_weird_bazel_directories.js.map new file mode 100644 index 0000000000..3bace9bb17 --- /dev/null +++ b/closure/compiler/test/golden/sourcemap_doesn_contain_weird_bazel_directories.js.map @@ -0,0 +1,9 @@ +{ +"version":3, +"file":"hello_bin.js", +"lineCount":1, +"mappings":"AAgBAA,OAAA,CAAUC,GAAV,CAAgB,aAAhB;", +"sources":["/closure/compiler/test/hello.js"], +"sourcesContent":["// Copyright 2016 The Closure Rules Authors. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// hello world\n\nconsole . log ( 'hello world' ) ;\n"], +"names":["console","log"] +} diff --git a/closure/compiler/test/golden/sourcemap_with_wrapper_has_different_mapping_codes.js.map b/closure/compiler/test/golden/sourcemap_with_wrapper_has_different_mapping_codes.js.map new file mode 100644 index 0000000000..b49db683ee --- /dev/null +++ b/closure/compiler/test/golden/sourcemap_with_wrapper_has_different_mapping_codes.js.map @@ -0,0 +1,9 @@ +{ +"version":3, +"file":"hello_wrap_bin.js", +"lineCount":1, +"mappings":"A,YAgBAA,OAAA,CAAUC,GAAV,CAAgB,aAAhB;", +"sources":["/closure/compiler/test/hello.js"], +"sourcesContent":["// Copyright 2016 The Closure Rules Authors. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// hello world\n\nconsole . log ( 'hello world' ) ;\n"], +"names":["console","log"] +} diff --git a/closure/compiler/test/golden/strict_output_language_adds_use_strict.js b/closure/compiler/test/golden/strict_output_language_adds_use_strict.js new file mode 100644 index 0000000000..f878f91587 --- /dev/null +++ b/closure/compiler/test/golden/strict_output_language_adds_use_strict.js @@ -0,0 +1 @@ +'use strict';console.log("hello world"); diff --git a/closure/compiler/test/js_zip/BUILD b/closure/compiler/test/js_zip/BUILD index fb9ada70df..0d76277343 100644 --- a/closure/compiler/test/js_zip/BUILD +++ b/closure/compiler/test/js_zip/BUILD @@ -16,7 +16,7 @@ package(default_testonly = True) licenses(["notice"]) # Apache 2.0 -load("//closure/private:file_test.bzl", "file_test") +load("//closure/private:expected_output_test.bzl", "closure_js_binary_output_test") load("//closure:defs.bzl", "closure_js_binary") load(":zip_file_test_library.bzl", "zip_file_test_library") @@ -30,10 +30,10 @@ closure_js_binary( deps = [":main_lib"], ) -file_test( +closure_js_binary_output_test( name = "zip_files_worksCorrectly", - content = "console.log(\"hi from zip\");\n", - file = "main_bin.js", + expected_output = "golden/zip_files_works_correctly.js", + target = ":main_bin", ) zip_file_test_library( @@ -50,8 +50,8 @@ closure_js_binary( deps = [":main_with_error_lib"], ) -file_test( +closure_js_binary_output_test( name = "zip_files_areSuppressable", - content = "iDontExist();\n", - file = "main_with_error_bin.js", + expected_output = "golden/zip_files_are_suppressable.js", + target = ":main_with_error_bin", ) diff --git a/closure/compiler/test/js_zip/golden/zip_files_are_suppressable.js b/closure/compiler/test/js_zip/golden/zip_files_are_suppressable.js new file mode 100644 index 0000000000..da6ac0953e --- /dev/null +++ b/closure/compiler/test/js_zip/golden/zip_files_are_suppressable.js @@ -0,0 +1 @@ +iDontExist(); diff --git a/closure/compiler/test/js_zip/golden/zip_files_works_correctly.js b/closure/compiler/test/js_zip/golden/zip_files_works_correctly.js new file mode 100644 index 0000000000..0688380105 --- /dev/null +++ b/closure/compiler/test/js_zip/golden/zip_files_works_correctly.js @@ -0,0 +1 @@ +console.log("hi from zip"); diff --git a/closure/compiler/test/reports/BUILD b/closure/compiler/test/reports/BUILD index 56ed44dbb3..010f71a6af 100644 --- a/closure/compiler/test/reports/BUILD +++ b/closure/compiler/test/reports/BUILD @@ -16,7 +16,7 @@ package(default_testonly = True) licenses(["notice"]) # Apache 2.0 -load("//closure/private:file_test.bzl", "file_test") +load("//closure/private:expected_output_test.bzl", "closure_js_binary_output_test", "closure_js_binary_property_renaming_report_test") load("//closure:defs.bzl", "closure_js_binary", "closure_js_library") # Property renaming reports are rarely used. But they can be used to minify @@ -33,14 +33,14 @@ closure_js_binary( deps = [":property_lib"], ) -file_test( +closure_js_binary_output_test( name = "propertyWithoutQuotes_getsRenamed", - content = "console.log({a:\"world\"});\n", - file = "property_bin.js", + expected_output = "golden/property_without_quotes_gets_renamed.js", + target = ":property_bin", ) -file_test( +closure_js_binary_property_renaming_report_test( name = "propertyRenamingReportDef_createsAdditionalOutputFile", - content = "hello:a\n", - file = "property_bin_renaming_report.txt", + expected_output = "golden/property_renaming_report.txt", + target = ":property_bin", ) diff --git a/closure/compiler/test/reports/golden/property_renaming_report.txt b/closure/compiler/test/reports/golden/property_renaming_report.txt new file mode 100644 index 0000000000..0d093b0a08 --- /dev/null +++ b/closure/compiler/test/reports/golden/property_renaming_report.txt @@ -0,0 +1 @@ +hello:a diff --git a/closure/compiler/test/reports/golden/property_without_quotes_gets_renamed.js b/closure/compiler/test/reports/golden/property_without_quotes_gets_renamed.js new file mode 100644 index 0000000000..0bff127b7d --- /dev/null +++ b/closure/compiler/test/reports/golden/property_without_quotes_gets_renamed.js @@ -0,0 +1 @@ +console.log({a:"world"}); diff --git a/closure/compiler/test/strict_dependency_checking/BUILD b/closure/compiler/test/strict_dependency_checking/BUILD index 915d448676..aff9f291b2 100644 --- a/closure/compiler/test/strict_dependency_checking/BUILD +++ b/closure/compiler/test/strict_dependency_checking/BUILD @@ -16,6 +16,7 @@ package(default_testonly = True) licenses(["notice"]) # Apache 2.0 +load("//closure/private:expected_output_test.bzl", "closure_js_binary_output_test") load("//closure/private:file_test.bzl", "file_test") load("//closure:defs.bzl", "closure_js_binary", "closure_js_library") @@ -149,7 +150,7 @@ file_test( closure_js_library( name = "setTestOnlyInLibraryWithoutTestOnly", - testonly = False, # <-- oops I forgot this line + testonly = False, srcs = ["t.js"], internal_expect_failure = True, tags = ["manual"], @@ -266,10 +267,10 @@ closure_js_binary( deps = [":es6_g2"], ) -file_test( +closure_js_binary_output_test( name = "es6ModulesWithRootPaths_compileCorrectlyWhenReferencedWithoutRootPrefix", - content = "console.log(\"hi\");\n", - file = "es6_g2_bin.js", + expected_output = "golden/es6_modules_with_root_paths_compile_correctly_when_referenced_without_root_prefix.js", + target = ":es6_g2_bin", ) closure_js_library( @@ -291,8 +292,8 @@ closure_js_binary( deps = [":es6_relative_imports_lib"], ) -file_test( +closure_js_binary_output_test( name = "es6RelativeImports_workCorrectly", - content = "console.log(\"a\");\n", - file = "es6_relative_imports_bin.js", + expected_output = "golden/es6_relative_imports_work_correctly.js", + target = ":es6_relative_imports_bin", ) diff --git a/closure/compiler/test/strict_dependency_checking/golden/es6_modules_with_root_paths_compile_correctly_when_referenced_without_root_prefix.js b/closure/compiler/test/strict_dependency_checking/golden/es6_modules_with_root_paths_compile_correctly_when_referenced_without_root_prefix.js new file mode 100644 index 0000000000..d914c6066c --- /dev/null +++ b/closure/compiler/test/strict_dependency_checking/golden/es6_modules_with_root_paths_compile_correctly_when_referenced_without_root_prefix.js @@ -0,0 +1 @@ +console.log("hi"); diff --git a/closure/compiler/test/strict_dependency_checking/golden/es6_relative_imports_work_correctly.js b/closure/compiler/test/strict_dependency_checking/golden/es6_relative_imports_work_correctly.js new file mode 100644 index 0000000000..7b2a346011 --- /dev/null +++ b/closure/compiler/test/strict_dependency_checking/golden/es6_relative_imports_work_correctly.js @@ -0,0 +1 @@ +console.log("a"); diff --git a/closure/defs.bzl b/closure/defs.bzl index 2a8e31a938..e3ffe48894 100644 --- a/closure/defs.bzl +++ b/closure/defs.bzl @@ -13,7 +13,7 @@ # limitations under the License. load("//closure/compiler:closure_js_aspect.bzl", _closure_js_aspect = "closure_js_aspect") -load("//closure/compiler:closure_js_binary.bzl", _closure_js_binary = "closure_js_binary") +load("//closure/compiler:closure_js_binary.bzl", _closure_js_binary = "closure_js_binary", _JavaScriptBinaryInfo = "JavaScriptBinaryInfo") load("//closure/compiler:closure_js_deps.bzl", _closure_js_deps = "closure_js_deps") load("//closure/compiler:closure_js_library.bzl", _closure_js_library = "closure_js_library", _create_closure_js_library = "create_closure_js_library") load("//closure/private:defs.bzl", _CLOSURE_JS_TOOLCHAIN_ATTRS = "CLOSURE_JS_TOOLCHAIN_ATTRS") @@ -31,6 +31,8 @@ load("//closure:filegroup_external.bzl", _filegroup_external = "filegroup_extern load("//closure:webfiles/web_library.bzl", _web_library = "web_library") load("//closure:webfiles/web_library_external.bzl", _web_library_external = "web_library_external") +JavaScriptBinaryInfo = _JavaScriptBinaryInfo + closure_js_aspect = _closure_js_aspect closure_js_binary = _closure_js_binary closure_js_deps = _closure_js_deps diff --git a/closure/private/expected_output_test.bzl b/closure/private/expected_output_test.bzl new file mode 100644 index 0000000000..9778c119b4 --- /dev/null +++ b/closure/private/expected_output_test.bzl @@ -0,0 +1,123 @@ +# Copyright 2020 The Closure Rules 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. + +"""Rules for testing contents of text files generated by rules.""" + +load("//closure:defs.bzl", "JavaScriptBinaryInfo") + +def _rule(implementation, providers): + return rule( + implementation = implementation, + test = True, + attrs = { + "expected_output": attr.label( + mandatory = True, + allow_single_file = True, + ), + "target": attr.label( + mandatory = True, + providers = providers, + ), + }, + ) + +def _runfiles_path(f): + if f.root.path: + return f.path[len(f.root.path) + 1:] # generated file + else: + return f.path # source file + +def _common_impl(ctx, fn): + file1 = ctx.file.expected_output + file2 = fn(ctx.attr.target) + + # Based on the implementation of `diff_test` in `bazel-skylib`, + # licensed under Apache 2.0. + test_bin = ctx.actions.declare_file(ctx.label.name + "-test.sh") + ctx.actions.write( + output = test_bin, + content = r"""#!/bin/bash +set -euo pipefail +F1="{file1}" +F2="{file2}" +[[ "$F1" =~ ^external/* ]] && F1="${{F1#external/}}" || F1="$TEST_WORKSPACE/$F1" +[[ "$F2" =~ ^external/* ]] && F2="${{F2#external/}}" || F2="$TEST_WORKSPACE/$F2" +if [[ -d "${{RUNFILES_DIR:-/dev/null}}" && "${{RUNFILES_MANIFEST_ONLY:-}}" != 1 ]]; then + RF1="$RUNFILES_DIR/$F1" + RF2="$RUNFILES_DIR/$F2" +elif [[ -f "${{RUNFILES_MANIFEST_FILE:-/dev/null}}" ]]; then + RF1="$(grep -F -m1 "$F1 " "$RUNFILES_MANIFEST_FILE" | sed 's/^[^ ]* //')" + RF2="$(grep -F -m1 "$F2 " "$RUNFILES_MANIFEST_FILE" | sed 's/^[^ ]* //')" +elif [[ -f "$TEST_SRCDIR/$F1" && -f "$TEST_SRCDIR/$F2" ]]; then + RF1="$TEST_SRCDIR/$F1" + RF2="$TEST_SRCDIR/$F2" +else + echo >&2 "ERROR: could not find \"{file1}\" and \"{file2}\"" + exit 1 +fi +if ! diff "$RF1" "$RF2"; then + echo >&2 "FAIL: files \"{file1}\" and \"{file2}\" differ" + exit 1 +fi +""".format( + file1 = _runfiles_path(file1), + file2 = _runfiles_path(file2), + ), + is_executable = True, + ) + + return DefaultInfo( + executable = test_bin, + files = depset(direct = [test_bin]), + runfiles = ctx.runfiles(files = [test_bin, file1, file2]), + ) + +def _closure_js_binary_output_test_get_expected_file(target): + return target[JavaScriptBinaryInfo].output + +def _closure_js_binary_output_test_impl(ctx): + return _common_impl(ctx, _closure_js_binary_output_test_get_expected_file) + +closure_js_binary_output_test = _rule( + implementation = _closure_js_binary_output_test_impl, + providers = [ + JavaScriptBinaryInfo, + ], +) + +def _closure_js_binary_sourcemap_test_get_expected_file(target): + return target[JavaScriptBinaryInfo].sourcemap + +def _closure_js_binary_sourcemap_test_impl(ctx): + return _common_impl(ctx, _closure_js_binary_sourcemap_test_get_expected_file) + +closure_js_binary_sourcemap_test = _rule( + implementation = _closure_js_binary_sourcemap_test_impl, + providers = [ + JavaScriptBinaryInfo, + ], +) + +def _closure_js_binary_property_renaming_report_test_get_expected_file(target): + return target[JavaScriptBinaryInfo].property_renaming_report + +def _closure_js_binary_property_renaming_report_test_impl(ctx): + return _common_impl(ctx, _closure_js_binary_property_renaming_report_test_get_expected_file) + +closure_js_binary_property_renaming_report_test = _rule( + implementation = _closure_js_binary_property_renaming_report_test_impl, + providers = [ + JavaScriptBinaryInfo, + ], +) diff --git a/closure/stylesheets/test/BUILD b/closure/stylesheets/test/BUILD index cf25638382..2b21c297f3 100644 --- a/closure/stylesheets/test/BUILD +++ b/closure/stylesheets/test/BUILD @@ -16,6 +16,7 @@ package(default_testonly = True) licenses(["notice"]) # Apache 2.0 +load("//closure/private:expected_output_test.bzl", "closure_js_binary_output_test") load("//closure/private:file_test.bzl", "file_test") load("//closure:defs.bzl", "closure_css_binary", "closure_css_library", "closure_js_binary", "closure_js_library") @@ -103,10 +104,10 @@ closure_js_binary( deps = [":rename_lib"], ) -file_test( +closure_js_binary_output_test( name = "jsBinaryReferencesCssBinary_googGetCssNameCallsGetRewritten", - content = "console.log(\"a-b\");\n", - file = "rename_bin.js", + expected_output = "golden/js_binary_references_css_binary_goog_get_css_name_calls_get_rewritten.js", + target = ":rename_bin", ) closure_css_binary( diff --git a/closure/stylesheets/test/golden/js_binary_references_css_binary_goog_get_css_name_calls_get_rewritten.js b/closure/stylesheets/test/golden/js_binary_references_css_binary_goog_get_css_name_calls_get_rewritten.js new file mode 100644 index 0000000000..36462177d8 --- /dev/null +++ b/closure/stylesheets/test/golden/js_binary_references_css_binary_goog_get_css_name_calls_get_rewritten.js @@ -0,0 +1 @@ +console.log("a-b");