diff --git a/core/blockly.js b/core/blockly.js index 1c7b37377b3..48fc78e21dc 100644 --- a/core/blockly.js +++ b/core/blockly.js @@ -184,6 +184,11 @@ goog.require('Blockly.Events.VarCreate'); */ exports.VERSION = 'uncompiled'; +/** + * @define {boolean} Overridden to true by the compiler. + */ +const COMPILED = false; + // Add a getter and setter pair for Blockly.alert, Blockly.confirm, // Blockly.mainWorkspace, Blockly.prompt and Blockly.selected for backwards // compatibility. @@ -700,7 +705,7 @@ exports.zelos = zelos; // // This is only needed in uncompiled mode (see // google/blockly-samples#902); in compiled mode the exports object is -// already the value of globalThis.Blockly. +// already the value of globalThis['Blockly']. // // Note that this code will still attempt to redefine accessors on a // previously-imported copy of the Blockly library if both are @@ -708,8 +713,8 @@ exports.zelos = zelos; // accessors are nonconfigurable (which is good, as otherwise one // accessors on one copy would call get/set functions on the other // copy!) -if (!goog.global['COMPILED'] && typeof goog.global['Blockly'] === 'object' && - goog.global['Blockly'] !== exports) { +if (!COMPILED && typeof globalThis['Blockly'] === 'object' && + globalThis['Blockly'] !== exports) { const descriptors = Object.getOwnPropertyDescriptors(exports); const accessors = {}; for (const key in descriptors) { @@ -717,5 +722,5 @@ if (!goog.global['COMPILED'] && typeof goog.global['Blockly'] === 'object' && accessors[key] = descriptors[key]; } } - Object.defineProperties(globalThis.Blockly, accessors); + Object.defineProperties(globalThis['Blockly'], accessors); } diff --git a/core/utils/xml.js b/core/utils/xml.js index f11117a2e1a..10e675f8c3c 100644 --- a/core/utils/xml.js +++ b/core/utils/xml.js @@ -36,7 +36,7 @@ exports.NAME_SPACE = NAME_SPACE; * jsdom package instead. * @type {!Document} */ -let xmlDocument = globalThis.document; +let xmlDocument = globalThis['document']; /** * Get the document object to use for XML serialization. diff --git a/externs/block-externs.js b/externs/block-externs.js deleted file mode 100644 index 20b6f51b1d3..00000000000 --- a/externs/block-externs.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview Externs for Blockly blocks. - * @externs - */ - -goog.provide('Blockly'); -goog.provide('Blockly.Blocks'); -goog.provide('Blockly.Comment'); -goog.provide('Blockly.FieldCheckbox'); -goog.provide('Blockly.FieldColour'); -goog.provide('Blockly.FieldDropdown'); -goog.provide('Blockly.FieldImage'); -goog.provide('Blockly.FieldLabel'); -goog.provide('Blockly.FieldMultilineInput'); -goog.provide('Blockly.FieldNumber'); -goog.provide('Blockly.FieldTextInput'); -goog.provide('Blockly.FieldVariable'); -goog.provide('Blockly.Mutator'); -goog.provide('Blockly.Warning'); -goog.provide('Blockly.loopMixin'); - -var Blockly; diff --git a/externs/generator-externs.js b/externs/generator-externs.js deleted file mode 100644 index 6b6d9d650a7..00000000000 --- a/externs/generator-externs.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview Externs for Blockly generators. - * @externs - */ - -goog.provide('Blockly'); -goog.provide('Blockly.Generator'); -goog.provide('Blockly.inputTypes'); -goog.provide('Blockly.loopMixin'); -goog.provide('Blockly.utils.global'); -goog.provide('Blockly.utils.object'); -goog.provide('Blockly.utils.string'); - -var Blockly; diff --git a/externs/goog-externs.js b/externs/goog-externs.js deleted file mode 100644 index dcc80965ae6..00000000000 --- a/externs/goog-externs.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview Externs for goog.* - * - * These are needed because we use goog.module, goog.require etc. to - * define our modules, but we don't actually include - * closure/goog/base.js as input to the compiler. Originally we only - * needed the extern for goog, but some time between Closure Compiler - * versions 20210601.0.0 and 20211006.0.0 we started getting - * JSC_POSSIBLE_INEXISTENT_PROPERTY errors for goog.module / - * goog.require / goog.requireType declarations involving modules - * which used goog.module.declareLegacyNamespace. - * - * @externs - */ - -/** - * @type {!Object} - */ -var goog = {}; - -/** - * @param {string} name - * @return {void} - */ -goog.module = function(name) {}; - -/** - * @return{void} - */ -goog.module.declareLegacyNamespace = function() {}; - -/** - * @param {string} name - * @return {?} - */ -goog.module.get = function(name) {}; - -/** - * @param {string} name - * @return {void} - */ -goog.provide = function(name) {}; - -/** - * @param {string} namespace - * @return {?} - */ -goog.require = function(namespace) {}; - -/** - * @param {string} namespace - * @return {?} - */ -goog.requireType = function(namespace) {}; - -/** - * @param {string=} opt_message - * @return{void} - */ -goog.setTestOnly = function(opt_message) {}; diff --git a/scripts/gulpfiles/build_tasks.js b/scripts/gulpfiles/build_tasks.js index 4b34099caf2..529b6200f6e 100644 --- a/scripts/gulpfiles/build_tasks.js +++ b/scripts/gulpfiles/build_tasks.js @@ -183,56 +183,6 @@ var JSCOMP_ERROR = [ 'visibility' ]; -/** - * Helper method for calling the Closure compiler. - * @param {*} compilerOptions - * @param {boolean=} opt_verbose Optional option for verbose logging - * @param {boolean=} opt_warnings_as_error Optional option for treating warnings - * as errors. - * @param {boolean=} opt_strict_typechecker Optional option for enabling strict - * type checking. - */ -function compile(compilerOptions, opt_verbose, opt_warnings_as_error, - opt_strict_typechecker) { - const options = {}; - options.compilation_level = 'SIMPLE_OPTIMIZATIONS'; - options.warning_level = opt_verbose ? 'VERBOSE' : 'DEFAULT'; - options.language_in = 'ECMASCRIPT6_STRICT', - options.language_out = 'ECMASCRIPT5_STRICT'; - options.rewrite_polyfills = true; - options.hide_warnings_for = 'node_modules'; - if (opt_warnings_as_error || opt_strict_typechecker) { - options.jscomp_error = JSCOMP_ERROR; - if (opt_strict_typechecker) { - options.jscomp_error.push('strictCheckTypes'); - } - } - - const platform = ['native', 'java', 'javascript']; - - return closureCompiler({...options, ...compilerOptions}, { platform }); -} - -/** - * Helper method for possibly adding the Closure library into a sources array. - * @param {Array} srcs - */ -function maybeAddClosureLibrary(srcs) { - if (argv.closureLibrary) { - // If you require Google's Closure library, you can include it in your - // build by adding the --closure-library flag. - // You will also need to include the "google-closure-library" in your list - // of devDependencies. - console.log('Including the google-closure-library in your build.'); - if (!fs.existsSync('./node_modules/google-closure-library')) { - throw Error('You must add the google-closure-library to your ' + - 'devDependencies in package.json, and run `npm install`.'); - } - srcs.push('./node_modules/google-closure-library/closure/goog/**/**/*.js'); - } - return srcs; -} - /** * This task updates tests/deps.js, used by blockly_uncompressed.js * when loading Blockly in uncompiled mode. @@ -493,6 +443,34 @@ function unflattenCorePaths(pathString) { return pathString.replace(/-slash-/g, path.sep); } +/** + * Helper method for calling the Closure compiler, establishing + * default options (that can be overridden by the caller). + * @param {*} options Caller-supplied options that will override the + * defaultOptions. + */ +function compile(options) { + const defaultOptions = { + compilation_level: 'SIMPLE_OPTIMIZATIONS', + warning_level: argv.verbose ? 'VERBOSE' : 'DEFAULT', + language_in: 'ECMASCRIPT6_STRICT', + language_out: 'ECMASCRIPT5_STRICT', + rewrite_polyfills: true, + hide_warnings_for: 'node_modules', + externs: ['./externs/svg-externs.js'], + }; + if (argv.debug || argv.strict) { + defaultOptions.jscomp_error = [...JSCOMP_ERROR]; + if (argv.strict) { + defaultOptions.jscomp_error.push('strictCheckTypes'); + } + } + // Extra options for Closure Compiler gulp plugin. + const platform = ['native', 'java', 'javascript']; + + return closureCompiler({...defaultOptions, ...options}, {platform}); +} + /** * This task compiles the core library, blocks and generators, creating * blockly_compressed.js, blocks_compressed.js, etc. @@ -505,13 +483,6 @@ function buildCompiled() { // Closure Compiler options. const packageJson = getPackageJson(); // For version number. const options = { - compilation_level: 'SIMPLE_OPTIMIZATIONS', - warning_level: argv.verbose ? 'VERBOSE' : 'DEFAULT', - language_in: 'ECMASCRIPT6_STRICT', - language_out: 'ECMASCRIPT5_STRICT', - rewrite_polyfills: true, - hide_warnings_for: 'node_modules', - externs: ['./externs/svg-externs.js'], define: 'Blockly.VERSION="' + packageJson.version + '"', chunk: chunkOptions.chunk, chunk_wrapper: chunkOptions.chunk_wrapper, @@ -519,21 +490,13 @@ function buildCompiled() { // Don't supply the list of source files in chunkOptions.js as an // option to Closure Compiler; instead feed them as input via gulp.src. }; - if (argv.debug || argv.strict) { - options.jscomp_error = [...JSCOMP_ERROR]; - if (argv.strict) { - options.jscomp_error.push('strictCheckTypes'); - } - } - // Extra options for Closure Compiler gulp plugin. - const pluginOptions = ['native', 'java', 'javascript']; // Fire up compilation pipline. return gulp.src(chunkOptions.js, {base: './'}) .pipe(stripApacheLicense()) .pipe(gulp.sourcemaps.init()) .pipe(gulp.rename(flattenCorePaths)) - .pipe(closureCompiler(options, pluginOptions)) + .pipe(compile(options)) .pipe(gulp.rename({suffix: COMPILED_SUFFIX})) .pipe(gulp.sourcemaps.mapSources(unflattenCorePaths)) .pipe( @@ -547,38 +510,24 @@ function buildCompiled() { */ function buildAdvancedCompilationTest() { const srcs = [ - 'tests/compile/main.js', 'tests/compile/test_blocks.js', 'core/**/**/*.js', - 'blocks/*.js', 'generators/**/*.js' + 'closure/goog/base_minimal.js', + 'core/**/*.js', 'blocks/**/*.js', 'generators/**/*.js', + 'tests/compile/main.js', 'tests/compile/test_blocks.js', ]; - return gulp.src(maybeAddClosureLibrary(srcs), {base: './'}) + + // Closure Compiler options. + const options = { + dependency_mode: 'PRUNE', + compilation_level: 'ADVANCED_OPTIMIZATIONS', + entry_point: './tests/compile/main.js', + js_output_file: 'main_compressed.js', + }; + return gulp.src(srcs, {base: './'}) .pipe(stripApacheLicense()) .pipe(gulp.sourcemaps.init()) - // Directories in Blockly are used to group similar files together - // but are not used to limit access with @package, instead the - // method means something is internal to Blockly and not a public - // API. - // Flatten all files so they're in the same directory, but ensure that - // files with the same name don't conflict. - .pipe(gulp.rename(function(p) { - if (p.dirname.indexOf('core') === 0) { - var dirname = p.dirname.replace( - new RegExp(path.sep.replace(/\\/, '\\\\'), "g"), "-"); - p.dirname = ""; - p.basename = dirname + "-" + p.basename; - } - })) - .pipe(compile( - { - dependency_mode: 'PRUNE', - compilation_level: 'ADVANCED_OPTIMIZATIONS', - entry_point: './tests/compile/main.js', - js_output_file: 'main_compressed.js', - externs: ['./externs/svg-externs.js', './externs/goog-externs.js'], - }, - argv.verbose, argv.strict)) - .pipe(gulp.sourcemaps.mapSources(function(sourcePath, file) { - return sourcePath.replace(/-/g, '/'); - })) + .pipe(gulp.rename(flattenCorePaths)) + .pipe(compile(options)) + .pipe(gulp.sourcemaps.mapSources(unflattenCorePaths)) .pipe(gulp.sourcemaps.write( '.', {includeContent: false, sourceRoot: '../../'})) .pipe(gulp.dest('./tests/compile/')); diff --git a/tests/compile/index.html b/tests/compile/index.html index 8ffadca8893..97fb520316f 100644 --- a/tests/compile/index.html +++ b/tests/compile/index.html @@ -22,9 +22,8 @@

Blockly: Advanced Compilation Test

-

To run this test manually, download - closure-compiler-vxxxxxxxx.jar, - place it in this directory, then run `npm run test:compile:advanced` from the command line.

+

To run this test manually, run `npm run test:compile:advanced` + from the command line, then open this file in your web browser.

Measure the size of main_compressed.js (295kb as of October 2017), then reload this page and see if Blockly works.