diff --git a/blockly_uncompressed.js b/blockly_uncompressed.js deleted file mode 100644 index 804f97f0b..000000000 --- a/blockly_uncompressed.js +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview Bootstrap code to load Blockly in uncompiled mode. - */ -'use strict'; - - -/* eslint-disable no-var */ - -/** - * Blockly uncompiled-mode startup code. If running in a browser - * loads closure/goog/base.js and build/deps.js, then (in any case) - * requires Blockly.requires. - */ -(function(globalThis) { - /* eslint-disable-next-line no-undef */ - var IS_NODE_JS = !!(typeof module !== 'undefined' && module.exports); - - if (IS_NODE_JS) { - // Load Blockly. - goog.require('Blockly.requires'); - /* eslint-disable no-undef */ - module.exports = Blockly; - } else { - var BLOCKLY_DIR = ''; - // Find name of current directory. - var scripts = document.getElementsByTagName('script'); - var re = /(.+)[\\/]blockly_(?:.*)uncompressed\.js$/; - for (var script, i = 0; (script = scripts[i]); i++) { - var match = re.exec(script.src); - if (match) { - BLOCKLY_DIR = match[1]; - break; - } - } - if (!BLOCKLY_DIR) { - alert('Could not detect Blockly\'s directory name.'); - } - // Disable loading of closure/goog/deps.js (which doesn't exist). - globalThis.CLOSURE_NO_DEPS = true; - // Load Closure Library base.js (the only part of the libary we use, - // mainly for goog.require / goog.provide / goog.module). - document.write( - ''); - // Load dependency graph info from build/deps.js. To update - // deps.js, run `npm run build:deps`. - document.write( - ''); - // Load the rest of Blockly. - document.write(''); - } - /* eslint-disable-next-line no-invalid-this */ -})(this); diff --git a/scripts/gulpfiles/build_tasks.js b/scripts/gulpfiles/build_tasks.js index 9b6114bc5..1da8c3325 100644 --- a/scripts/gulpfiles/build_tasks.js +++ b/scripts/gulpfiles/build_tasks.js @@ -262,7 +262,7 @@ function buildJavaScript(done) { /** * This task updates DEPS_FILE (deps.js), used by - * blockly_uncompressed.js when loading Blockly in uncompiled mode. + * bootstrap.js when loading Blockly in uncompiled mode. * * Also updates TEST_DEPS_FILE (deps.mocha.js), used by the mocha test * suite. @@ -673,7 +673,6 @@ function buildAdvancedCompilationTest() { * php_compressed.js * lua_compressed.js * dart_compressed.js - * blockly_uncompressed.js * msg/json/*.js * test/deps*.js */ diff --git a/scripts/gulpfiles/config.js b/scripts/gulpfiles/config.js index 9080866fa..02df80291 100644 --- a/scripts/gulpfiles/config.js +++ b/scripts/gulpfiles/config.js @@ -19,17 +19,16 @@ var path = require('path'); // - tests/scripts/compile_typings.sh // - tests/scripts/check_metadata.sh // - tests/scripts/update_metadata.sh -// - blockly_uncompressed.js (for location of deps.js) -// - tests/playgrounds/prepare.js (for location of deps.js) +// - tests/bootstrap.js (for location of deps.js) // - tests/mocha/index.html (for location of deps.mocha.js) // Directory to write compiled output to. exports.BUILD_DIR = 'build'; -// Dependencies file (for blockly_uncompressed.js): +// Dependencies file (used by bootstrap.js in uncompiled mode): exports.DEPS_FILE = path.join(exports.BUILD_DIR, 'deps.js'); -// Dependencies file (for blockly_uncompressed.js): +// Mocha test dependencies file (used by tests/mocha/index.html): exports.TEST_DEPS_FILE = path.join(exports.BUILD_DIR, 'deps.mocha.js'); // Directory to write typings output to. diff --git a/tests/bootstrap.js b/tests/bootstrap.js new file mode 100644 index 000000000..45f64bb19 --- /dev/null +++ b/tests/bootstrap.js @@ -0,0 +1,246 @@ +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Bootstrap code to load Blockly, typically in + * uncompressed mode. + * + * Load this file in a '); + + // Prevent spurious transpilation warnings. + document.write(''); + + // Load dependency graph info from the specified deps files - + // typically just build/deps.js. To update deps after changing + // any module's goog.requires / imports, run `npm run build:deps`. + for (let i = 0; i < options.depsFiles.length; i++) { + document.write( + ''); + } + + // Record require targets for bootstrap_helper.js. + window.bootstrapInfo.requires = options.requires; + + // Assemble a list of module targets to bootstrap. + // + // The first group of targets are those listed in + // options.requires. + // + // The next target is a fake one that will load + // bootstrap_helper.js. We generate a call to goog.addDependency + // to tell the debug module loader that it can be loaded via a + // fake module name, and that it depends on all the targets in the + // first group (and indeed bootstrap_helper.js will make a call to + // goog.require for each one). + // + // We then create another target for each of + // options.additionalScripts, again generating calls to + // goog.addDependency for each one making it dependent on the + // previous one. + let requires = options.requires.slice(); + const scripts = + ['tests/bootstrap_helper.js'].concat(options.additionalScripts); + const scriptDeps = []; + for (let script, i = 0; script = scripts[i]; i++) { + const fakeModuleName = 'script.' + script.replace(/[./]/g, "-"); + scriptDeps.push(' goog.addDependency(' + + quote('../../' + script) + ', [' + quote(fakeModuleName) + + '], [' + requires.map(quote).join() + "], {'lang': 'es6'});\n"); + requires = [fakeModuleName]; + } + + // Finally, write out a script containing the generated + // goog.addDependency calls and a call to goog.bootstrap + // requesting the loading of the final target, which will cause + // all the previous ones to be loaded recursively. Wrap this in a + // promise and save it so it can be awaited in bootstrap_done.mjs. + document.write( + '\n'); + } else { + // We need to load Blockly in compressed mode. Load + // blockly_compressed.js et al. using '); + } + } + + return; // All done. Only helper functions after this point. + + /** + * Convert a string into a string literal. Strictly speaking we + * only need to escape backslash, \r, \n, \u2028 (line separator), + * \u2029 (paragraph separator) and whichever quote character we're + * using, but for simplicity we escape all the control characters. + * + * Based on https://github.com/google/CodeCity/blob/master/server/code.js + * + * @param {string} str The string to convert. + * @return {string} The value s as a eval-able string literal. + */ + function quote(str) { + /* eslint-disable no-control-regex, no-multi-spaces */ + /** Regexp for characters to be escaped in a single-quoted string. */ + const singleRE = /[\x00-\x1f\\\u2028\u2029']/g; + + /** Map of control character replacements. */ + const replacements = { + '\x00': '\\0', '\x01': '\\x01', '\x02': '\\x02', '\x03': '\\x03', + '\x04': '\\x04', '\x05': '\\x05', '\x06': '\\x06', '\x07': '\\x07', + '\x08': '\\b', '\x09': '\\t', '\x0a': '\\n', '\x0b': '\\v', + '\x0c': '\\f', '\x0d': '\\r', '\x0e': '\\x0e', '\x0f': '\\x0f', + '"': '\\"', "'": "\\'", '\\': '\\\\', + '\u2028': '\\u2028', '\u2029': '\\u2029', + }; + /* eslint-enable no-control-regex, no-multi-spaces */ + + /** + * Replacer function. + * @param {string} c Single UTF-16 code unit ("character") string to + * be replaced. + * @return {string} Multi-character string containing escaped + * representation of c. + */ + function replace(c) { + return replacements[c]; + } + + return "'" + str.replace(singleRE, replace) + "'"; + } +})(); diff --git a/tests/playgrounds/blockly.mjs b/tests/bootstrap_done.mjs similarity index 57% rename from tests/playgrounds/blockly.mjs rename to tests/bootstrap_done.mjs index cb836f539..d6d0c9b31 100644 --- a/tests/playgrounds/blockly.mjs +++ b/tests/bootstrap_done.mjs @@ -20,20 +20,20 @@ * * See tests/playground.html for example usage. */ - -let Blockly; - -if (window.BlocklyLoader) { - // Uncompiled mode. Use top-level await - // (https://v8.dev/features/top-level-await) to block loading of - // this module until goog.bootstrap()ping of Blockly is finished. - await window.BlocklyLoader; - Blockly = globalThis.Blockly; -} else if (window.Blockly) { - // Compiled mode. Retrieve the pre-installed Blockly global. - Blockly = globalThis.Blockly; -} else { - throw new Error('neither window.Blockly nor window.BlocklyLoader found'); +if (!window.bootstrapInfo) { + throw new Error('window.bootstrapInfo not found. ' + + 'Make sure to load bootstrap.js before importing bootstrap_done.mjs.'); } -export default Blockly; +if (window.bootstrapInfo.compressed) { + // Compiled mode. Nothing more to do. +} else { + // Uncompressed mode. Use top-level await + // (https://v8.dev/features/top-level-await) to block loading of + // this module until goog.bootstrap()ping of Blockly is finished. + await window.bootstrapInfo.done; + // Note that this module previously did an export default of the + // value returned by the bootstrapInfo.done promise. This was + // changed in PR #5995 because library blocks and generators cannot + // be accessed via that the core/blockly.js exports object. +} diff --git a/tests/bootstrap_helper.js b/tests/bootstrap_helper.js new file mode 100644 index 000000000..ba61ff2ea --- /dev/null +++ b/tests/bootstrap_helper.js @@ -0,0 +1,20 @@ +/** + * @license + * Copyright 2022 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Helper script for bootstrap.js + * + * This is loaded, via goog.bootstrap(), after the other top-level + * Blockly modules. It simply calls goog.require() for each of them, + * to force the debug module loader to finish loading them before any + * non-module scripts (like msg/messages.js) that might have + * undeclared dependencies on them. + */ + +/* eslint-disable-next-line no-undef */ +for (const require of window.bootstrapInfo.requires) { + goog.require(require); +} diff --git a/tests/generators/index.html b/tests/generators/index.html index 9e37f05b6..69badeed1 100644 --- a/tests/generators/index.html +++ b/tests/generators/index.html @@ -3,41 +3,36 @@ Blockly Generator Tests - - - - - - - - - + + - +
diff --git a/tests/mocha/.mocharc.js b/tests/mocha/.mocharc.js index 3c156db3e..0928b25d2 100644 --- a/tests/mocha/.mocharc.js +++ b/tests/mocha/.mocharc.js @@ -2,6 +2,5 @@ module.exports = { ui: 'tdd', - file: '../blockly_uncompressed.js', reporter: 'landing' }; diff --git a/tests/mocha/index.html b/tests/mocha/index.html index c3caf1469..10fe5ed45 100644 --- a/tests/mocha/index.html +++ b/tests/mocha/index.html @@ -5,9 +5,6 @@ Mocha Tests for Blockly - - - - +

Blockly Multi Playground

diff --git a/tests/playground.html b/tests/playground.html index 7a555392f..142eef3fb 100644 --- a/tests/playground.html +++ b/tests/playground.html @@ -4,15 +4,23 @@ Blockly Playground - - - - + + + diff --git a/tests/playgrounds/advanced_playground.html b/tests/playgrounds/advanced_playground.html index 1510555b7..0103b6961 100644 --- a/tests/playgrounds/advanced_playground.html +++ b/tests/playgrounds/advanced_playground.html @@ -3,15 +3,23 @@ Advanced Blockly Playground - - - - - + + + `); - document.write(``); - document.write(``); - document.write( - ``); - document.write(``); -} else { - document.write( - ``); - document.write(``); - document.write(``); - document.write(``); - document.write(``); - document.write(``); - document.write(``); - document.write(``); -} -})(); diff --git a/tests/playgrounds/prepare.js b/tests/playgrounds/prepare.js deleted file mode 100644 index 5f17a97f7..000000000 --- a/tests/playgrounds/prepare.js +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview Load this file in a '); - // Load dependency graph info from build/deps.js. To update - // deps.js, run `npm run build:deps`. - document.write(''); - - // Msg loading kludge. This should go away once #5409 and/or - // #1895 are fixed. - - // Load messages into a temporary Blockly.Msg object, deleting it - // afterwards (after saving the messages!) - window.Blockly = {Msg: Object.create(null)}; - document.write(''); - document.write(` - `); - - document.write(` - `); - } else { - // The below code is necessary for a few reasons: - // - We need an absolute path instead of relative path because the - // advanced_playground the and regular playground are in different folders. - // - We need to get the root directory for blockly because it is - // different for github.io, appspot and local. - const files = [ - 'blockly_compressed.js', - 'msg/messages.js', - 'blocks_compressed.js', - 'dart_compressed.js', - 'javascript_compressed.js', - 'lua_compressed.js', - 'php_compressed.js', - 'python_compressed.js', - ]; - - // We need to load Blockly in compiled mode. - const hostName = window.location.host.replaceAll('.', '\\.'); - const matches = new RegExp(hostName + '\\/(.*)tests').exec(window.location.href); - const root = matches && matches[1] ? matches[1] : ''; - - // Load blockly_compressed.js et al. using '); - } - } -})();