diff --git a/.eslintignore b/.eslintignore index 03be8d360..3bcef4777 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,5 +1,4 @@ *_compressed*.js -*_uncompressed*.js gulpfile.js /msg/* /build/* diff --git a/.eslintrc.json b/.eslintrc.json index 47430bdf2..28766db11 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -2,29 +2,6 @@ "rules": { "curly": ["error"], "eol-last": ["error"], - // Blockly/Google use 2-space indents. - // Blockly/Google uses +4 space indents for line continuations. - // Ignore default rules for ternary expressions. - "indent": [ - "error", 2, - { - "SwitchCase": 1, - "MemberExpression": 2, - "ObjectExpression": 1, - "FunctionDeclaration": { - "body": 1, - "parameters": 2 - }, - "FunctionExpression": { - "body": 1, - "parameters": 2 - }, - "CallExpression": { - "arguments": 2 - }, - "ignoredNodes": ["ConditionalExpression"] - } - ], "keyword-spacing": ["error"], "linebreak-style": ["error", "unix"], "max-len": [ @@ -39,7 +16,7 @@ ], "no-trailing-spaces": ["error", { "skipBlankLines": true }], "no-unused-vars": [ - "error", + "warn", { "args": "after-used", // Ignore vars starting with an underscore. @@ -48,7 +25,6 @@ "argsIgnorePattern": "^_" } ], - "no-use-before-define": ["error"], // Blockly uses for exporting symbols. no-self-assign added in eslint 5. "no-self-assign": ["off"], // Blockly uses single quotes except for JSON blobs, which must use double quotes. @@ -75,11 +51,13 @@ }] }, "env": { + "es6": true, "browser": true }, "globals": { "Blockly": true, - "goog": true + "goog": true, + "exports": true }, "extends": [ "eslint:recommended" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a11b7ce6b..c7cdc1874 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,6 +19,13 @@ jobs: steps: - uses: actions/checkout@v2 + with: + persist-credentials: false + + - name: Reconfigure git to use HTTP authentication + run: > + git config --global url."https://github.com/".insteadOf + ssh://git@github.com/ - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 diff --git a/.github/workflows/tag_module_cleanup.yml b/.github/workflows/tag_module_cleanup.yml new file mode 100644 index 000000000..0265070af --- /dev/null +++ b/.github/workflows/tag_module_cleanup.yml @@ -0,0 +1,38 @@ +# For new pull requests against the goog_module branch, adds the 'type: cleanup' +# label and sets the milestone to q3 2021 release. + +name: Tag module cleanup + +# Trigger on pull requests against goog_module branch only +# Uses pull_request_target to get write permissions so that it can write labels. +on: + pull_request_target: + branches: + - goog_module + +jobs: + tag-module-cleanup: + + # Add the type: cleanup label + runs-on: ubuntu-latest + steps: + - uses: actions/github-script@a3e7071a34d7e1f219a8a4de9a5e0a34d1ee1293 + with: + script: | + // Note that pull requests are considered issues and "shared" + // actions for both features, like manipulating labels and + // milestones are provided within the issues API. + await github.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + // 2021 q3 release milestone. + // https://github.com/google/blockly/milestone/18 + milestone: 18 + }) + await github.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + labels: ['type: cleanup'] + }) diff --git a/blockly_uncompressed.js b/blockly_uncompressed.js index 86f6dfcb5..ff0971da3 100644 --- a/blockly_uncompressed.js +++ b/blockly_uncompressed.js @@ -1,239 +1,56 @@ -// Do not edit this file; automatically generated by gulp. +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Bootstrap code to load Blockly in uncompiled mode. + * @author cpcallen@google.com (Christopher Allen) + */ 'use strict'; -this.IS_NODE_JS = !!(typeof module !== 'undefined' && module.exports); -this.BLOCKLY_DIR = (function(root) { - if (!root.IS_NODE_JS) { +/** + * Blockly uncompiled-mode startup code. If running in a browser + * loads closure/goog/base.js and tests/deps.js, then (in any case) + * requires Blockly.requires. + */ +(function(globalThis) { + /* eslint-disable 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 = new RegExp('(.+)[\/]blockly_(.*)uncompressed\.js$'); - for (var i = 0, script; script = scripts[i]; i++) { + var re = /(.+)[\\/]blockly_(?:.*)uncompressed\.js$/; + for (var script, i = 0; (script = scripts[i]); i++) { var match = re.exec(script.src); if (match) { - return match[1]; + BLOCKLY_DIR = match[1]; + break; } } - alert('Could not detect Blockly\'s directory name.'); + 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 test/deps.js. To update + // deps.js, run `npm run build:deps`. + document.write( + ''); + // Load the rest of Blockly. + document.write(''); } - return ''; })(this); - -this.BLOCKLY_BOOT = function(root) { - // Execute after Closure has loaded. -goog.addDependency('../../core/block.js', ['Blockly.Block'], ['Blockly.ASTNode', 'Blockly.Blocks', 'Blockly.Connection', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BlockCreate', 'Blockly.Events.BlockDelete', 'Blockly.Events.BlockMove', 'Blockly.Extensions', 'Blockly.IASTNodeLocation', 'Blockly.IDeletable', 'Blockly.Input', 'Blockly.Tooltip', 'Blockly.Workspace', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.inputTypes', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.object'], {'lang': 'es5'}); -goog.addDependency('../../core/block_animations.js', ['Blockly.blockAnimations'], ['Blockly.utils.Svg', 'Blockly.utils.dom']); -goog.addDependency('../../core/block_drag_surface.js', ['Blockly.BlockDragSurfaceSvg'], ['Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom']); -goog.addDependency('../../core/block_dragger.js', ['Blockly.BlockDragger'], ['Blockly.Events', 'Blockly.Events.BlockDrag', 'Blockly.Events.BlockMove', 'Blockly.IBlockDragger', 'Blockly.InsertionMarkerManager', 'Blockly.blockAnimations', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.dom']); -goog.addDependency('../../core/block_svg.js', ['Blockly.BlockSvg'], ['Blockly.ASTNode', 'Blockly.Block', 'Blockly.ContextMenu', 'Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.Events.BlockMove', 'Blockly.Events.Selected', 'Blockly.IASTNodeLocationSvg', 'Blockly.IBoundedElement', 'Blockly.ICopyable', 'Blockly.IDraggable', 'Blockly.Msg', 'Blockly.RenderedConnection', 'Blockly.TabNavigateCursor', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Xml', 'Blockly.blockAnimations', 'Blockly.blockRendering.IPathObject', 'Blockly.browserEvents', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent']); -goog.addDependency('../../core/blockly.js', ['Blockly'], ['Blockly.ComponentManager', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.FinishedLoading', 'Blockly.Events.Ui', 'Blockly.Events.UiBase', 'Blockly.Events.VarCreate', 'Blockly.Procedures', 'Blockly.ShortcutRegistry', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Variables', 'Blockly.WidgetDiv', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.inject', 'Blockly.inputTypes', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.colour', 'Blockly.utils.deprecation', 'Blockly.utils.toolbox']); -goog.addDependency('../../core/blocks.js', ['Blockly.Blocks'], []); -goog.addDependency('../../core/browser_events.js', ['Blockly.browserEvents'], ['Blockly.Touch', 'Blockly.utils.global']); -goog.addDependency('../../core/bubble.js', ['Blockly.Bubble'], ['Blockly.IBubble', 'Blockly.Scrollbar', 'Blockly.Touch', 'Blockly.Workspace', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.userAgent']); -goog.addDependency('../../core/bubble_dragger.js', ['Blockly.BubbleDragger'], ['Blockly.Bubble', 'Blockly.ComponentManager', 'Blockly.Events', 'Blockly.Events.CommentMove', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate']); -goog.addDependency('../../core/comment.js', ['Blockly.Comment'], ['Blockly.Bubble', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.Warning', 'Blockly.browserEvents', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent']); -goog.addDependency('../../core/component_manager.js', ['Blockly.ComponentManager'], []); -goog.addDependency('../../core/connection.js', ['Blockly.Connection'], ['Blockly.Events', 'Blockly.Events.BlockMove', 'Blockly.IASTNodeLocationWithBlock', 'Blockly.Xml', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.deprecation']); -goog.addDependency('../../core/connection_checker.js', ['Blockly.ConnectionChecker'], ['Blockly.Connection', 'Blockly.IConnectionChecker', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.registry']); -goog.addDependency('../../core/connection_db.js', ['Blockly.ConnectionDB'], ['Blockly.RenderedConnection', 'Blockly.connectionTypes', 'Blockly.constants']); -goog.addDependency('../../core/connection_types.js', ['Blockly.connectionTypes'], []); -goog.addDependency('../../core/constants.js', ['Blockly.constants'], ['Blockly.connectionTypes']); -goog.addDependency('../../core/contextmenu.js', ['Blockly.ContextMenu'], ['Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Menu', 'Blockly.MenuItem', 'Blockly.Msg', 'Blockly.WidgetDiv', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.userAgent']); -goog.addDependency('../../core/contextmenu_items.js', ['Blockly.ContextMenuItems'], ['Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.constants', 'Blockly.inputTypes'], {'lang': 'es5'}); -goog.addDependency('../../core/contextmenu_registry.js', ['Blockly.ContextMenuRegistry'], [], {'lang': 'es5'}); -goog.addDependency('../../core/css.js', ['Blockly.Css'], [], {'lang': 'es5'}); -goog.addDependency('../../core/delete_area.js', ['Blockly.DeleteArea'], ['Blockly.BlockSvg', 'Blockly.DragTarget', 'Blockly.IDeleteArea']); -goog.addDependency('../../core/drag_target.js', ['Blockly.DragTarget'], ['Blockly.IDragTarget']); -goog.addDependency('../../core/dropdowndiv.js', ['Blockly.DropDownDiv'], ['Blockly.utils.Rect', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.style']); -goog.addDependency('../../core/events/block_events.js', ['Blockly.Events.BlockBase', 'Blockly.Events.BlockChange', 'Blockly.Events.BlockCreate', 'Blockly.Events.BlockDelete', 'Blockly.Events.BlockMove', 'Blockly.Events.Change', 'Blockly.Events.Create', 'Blockly.Events.Delete', 'Blockly.Events.Move'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.Xml', 'Blockly.connectionTypes', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.object', 'Blockly.utils.xml']); -goog.addDependency('../../core/events/events.js', ['Blockly.Events'], ['Blockly.registry', 'Blockly.utils']); -goog.addDependency('../../core/events/events_abstract.js', ['Blockly.Events.Abstract'], ['Blockly.Events']); -goog.addDependency('../../core/events/events_block_drag.js', ['Blockly.Events.BlockDrag'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']); -goog.addDependency('../../core/events/events_bubble_open.js', ['Blockly.Events.BubbleOpen'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']); -goog.addDependency('../../core/events/events_click.js', ['Blockly.Events.Click'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']); -goog.addDependency('../../core/events/events_marker_move.js', ['Blockly.Events.MarkerMove'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']); -goog.addDependency('../../core/events/events_selected.js', ['Blockly.Events.Selected'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']); -goog.addDependency('../../core/events/events_theme_change.js', ['Blockly.Events.ThemeChange'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']); -goog.addDependency('../../core/events/events_toolbox_item_select.js', ['Blockly.Events.ToolboxItemSelect'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']); -goog.addDependency('../../core/events/events_trashcan_open.js', ['Blockly.Events.TrashcanOpen'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']); -goog.addDependency('../../core/events/events_viewport.js', ['Blockly.Events.ViewportChange'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']); -goog.addDependency('../../core/events/ui_events.js', ['Blockly.Events.Ui', 'Blockly.Events.UiBase'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.registry', 'Blockly.utils.object']); -goog.addDependency('../../core/events/variable_events.js', ['Blockly.Events.VarBase', 'Blockly.Events.VarCreate', 'Blockly.Events.VarDelete', 'Blockly.Events.VarRename'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.registry', 'Blockly.utils.object']); -goog.addDependency('../../core/events/workspace_events.js', ['Blockly.Events.FinishedLoading'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es5'}); -goog.addDependency('../../core/events/ws_comment_events.js', ['Blockly.Events.CommentBase', 'Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.Xml', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.object', 'Blockly.utils.xml']); -goog.addDependency('../../core/extensions.js', ['Blockly.Extensions'], ['Blockly.utils']); -goog.addDependency('../../core/field.js', ['Blockly.Field'], ['Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Gesture', 'Blockly.IASTNodeLocationSvg', 'Blockly.IASTNodeLocationWithBlock', 'Blockly.IKeyboardAccessible', 'Blockly.IRegistrable', 'Blockly.MarkerManager', 'Blockly.Tooltip', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.style', 'Blockly.utils.userAgent'], {'lang': 'es5'}); -goog.addDependency('../../core/field_angle.js', ['Blockly.FieldAngle'], ['Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.FieldTextInput', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils.KeyCodes', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.object', 'Blockly.utils.userAgent']); -goog.addDependency('../../core/field_checkbox.js', ['Blockly.FieldCheckbox'], ['Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils.dom', 'Blockly.utils.object']); -goog.addDependency('../../core/field_colour.js', ['Blockly.FieldColour'], ['Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils.IdGenerator', 'Blockly.utils.KeyCodes', 'Blockly.utils.Size', 'Blockly.utils.aria', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object']); -goog.addDependency('../../core/field_dropdown.js', ['Blockly.FieldDropdown'], ['Blockly.DropDownDiv', 'Blockly.Field', 'Blockly.Menu', 'Blockly.MenuItem', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.string', 'Blockly.utils.userAgent']); -goog.addDependency('../../core/field_image.js', ['Blockly.FieldImage'], ['Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object']); -goog.addDependency('../../core/field_label.js', ['Blockly.FieldLabel'], ['Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.dom', 'Blockly.utils.object']); -goog.addDependency('../../core/field_label_serializable.js', ['Blockly.FieldLabelSerializable'], ['Blockly.FieldLabel', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.object']); -goog.addDependency('../../core/field_multilineinput.js', ['Blockly.FieldMultilineInput'], ['Blockly.Css', 'Blockly.Field', 'Blockly.FieldTextInput', 'Blockly.WidgetDiv', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.KeyCodes', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es5'}); -goog.addDependency('../../core/field_number.js', ['Blockly.FieldNumber'], ['Blockly.FieldTextInput', 'Blockly.fieldRegistry', 'Blockly.utils.aria', 'Blockly.utils.object']); -goog.addDependency('../../core/field_registry.js', ['Blockly.fieldRegistry'], ['Blockly.registry']); -goog.addDependency('../../core/field_textinput.js', ['Blockly.FieldTextInput'], ['Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.Msg', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent']); -goog.addDependency('../../core/field_variable.js', ['Blockly.FieldVariable'], ['Blockly.Events.BlockChange', 'Blockly.FieldDropdown', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Variables', 'Blockly.Xml', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.object']); -goog.addDependency('../../core/flyout_base.js', ['Blockly.Flyout'], ['Blockly.Block', 'Blockly.ComponentManager', 'Blockly.DeleteArea', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.VarCreate', 'Blockly.FlyoutMetricsManager', 'Blockly.Gesture', 'Blockly.IFlyout', 'Blockly.ScrollbarPair', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.blockRendering', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.toolbox', 'Blockly.utils.xml']); -goog.addDependency('../../core/flyout_button.js', ['Blockly.FlyoutButton'], ['Blockly.Css', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.style'], {'lang': 'es5'}); -goog.addDependency('../../core/flyout_horizontal.js', ['Blockly.HorizontalFlyout'], ['Blockly.Block', 'Blockly.DropDownDiv', 'Blockly.Flyout', 'Blockly.Scrollbar', 'Blockly.WidgetDiv', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.object', 'Blockly.utils.toolbox']); -goog.addDependency('../../core/flyout_vertical.js', ['Blockly.VerticalFlyout'], ['Blockly.Block', 'Blockly.DropDownDiv', 'Blockly.Flyout', 'Blockly.Scrollbar', 'Blockly.WidgetDiv', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.object', 'Blockly.utils.toolbox']); -goog.addDependency('../../core/generator.js', ['Blockly.Generator'], ['Blockly.Block', 'Blockly.constants', 'Blockly.utils.deprecation']); -goog.addDependency('../../core/gesture.js', ['Blockly.Gesture'], ['Blockly.BlockDragger', 'Blockly.BubbleDragger', 'Blockly.Events', 'Blockly.Events.Click', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Workspace', 'Blockly.WorkspaceDragger', 'Blockly.blockAnimations', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate']); -goog.addDependency('../../core/grid.js', ['Blockly.Grid'], ['Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.userAgent']); -goog.addDependency('../../core/icon.js', ['Blockly.Icon'], ['Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom']); -goog.addDependency('../../core/inject.js', ['Blockly.inject'], ['Blockly.BlockDragSurfaceSvg', 'Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Grid', 'Blockly.Msg', 'Blockly.Options', 'Blockly.ScrollbarPair', 'Blockly.Tooltip', 'Blockly.WidgetDiv', 'Blockly.Workspace', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.WorkspaceSvg', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.userAgent']); -goog.addDependency('../../core/input.js', ['Blockly.Input'], ['Blockly.Connection', 'Blockly.FieldLabel', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.inputTypes'], {'lang': 'es5'}); -goog.addDependency('../../core/input_types.js', ['Blockly.inputTypes'], ['Blockly.connectionTypes']); -goog.addDependency('../../core/insertion_marker_manager.js', ['Blockly.InsertionMarkerManager'], ['Blockly.ComponentManager', 'Blockly.Events', 'Blockly.blockAnimations', 'Blockly.connectionTypes', 'Blockly.constants'], {'lang': 'es5'}); -goog.addDependency('../../core/interfaces/i_accessibility.js', ['Blockly.IASTNodeLocation', 'Blockly.IASTNodeLocationSvg', 'Blockly.IASTNodeLocationWithBlock', 'Blockly.IKeyboardAccessible'], []); -goog.addDependency('../../core/interfaces/i_autohideable.js', ['Blockly.IAutoHideable'], ['Blockly.IComponent']); -goog.addDependency('../../core/interfaces/i_block_dragger.js', ['Blockly.IBlockDragger'], []); -goog.addDependency('../../core/interfaces/i_bounded_element.js', ['Blockly.IBoundedElement'], []); -goog.addDependency('../../core/interfaces/i_bubble.js', ['Blockly.IBubble'], ['Blockly.IContextMenu', 'Blockly.IDraggable']); -goog.addDependency('../../core/interfaces/i_component.js', ['Blockly.IComponent'], []); -goog.addDependency('../../core/interfaces/i_connection_checker.js', ['Blockly.IConnectionChecker'], []); -goog.addDependency('../../core/interfaces/i_contextmenu.js', ['Blockly.IContextMenu'], []); -goog.addDependency('../../core/interfaces/i_copyable.js', ['Blockly.ICopyable'], []); -goog.addDependency('../../core/interfaces/i_deletable.js', ['Blockly.IDeletable'], []); -goog.addDependency('../../core/interfaces/i_delete_area.js', ['Blockly.IDeleteArea'], ['Blockly.IDragTarget']); -goog.addDependency('../../core/interfaces/i_drag_target.js', ['Blockly.IDragTarget'], ['Blockly.IComponent']); -goog.addDependency('../../core/interfaces/i_draggable.js', ['Blockly.IDraggable'], ['Blockly.IDeletable']); -goog.addDependency('../../core/interfaces/i_flyout.js', ['Blockly.IFlyout'], []); -goog.addDependency('../../core/interfaces/i_metrics_manager.js', ['Blockly.IMetricsManager'], []); -goog.addDependency('../../core/interfaces/i_movable.js', ['Blockly.IMovable'], []); -goog.addDependency('../../core/interfaces/i_positionable.js', ['Blockly.IPositionable'], ['Blockly.IComponent']); -goog.addDependency('../../core/interfaces/i_registrable.js', ['Blockly.IRegistrable'], []); -goog.addDependency('../../core/interfaces/i_registrable_field.js', ['Blockly.IRegistrableField'], []); -goog.addDependency('../../core/interfaces/i_selectable.js', ['Blockly.ISelectable'], []); -goog.addDependency('../../core/interfaces/i_styleable.js', ['Blockly.IStyleable'], []); -goog.addDependency('../../core/interfaces/i_toolbox.js', ['Blockly.IToolbox'], []); -goog.addDependency('../../core/interfaces/i_toolbox_item.js', ['Blockly.ICollapsibleToolboxItem', 'Blockly.ISelectableToolboxItem', 'Blockly.IToolboxItem'], []); -goog.addDependency('../../core/keyboard_nav/ast_node.js', ['Blockly.ASTNode'], ['Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.Coordinate'], {'lang': 'es5'}); -goog.addDependency('../../core/keyboard_nav/basic_cursor.js', ['Blockly.BasicCursor'], ['Blockly.ASTNode', 'Blockly.Cursor', 'Blockly.registry'], {'lang': 'es5'}); -goog.addDependency('../../core/keyboard_nav/cursor.js', ['Blockly.Cursor'], ['Blockly.ASTNode', 'Blockly.Marker', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es5'}); -goog.addDependency('../../core/keyboard_nav/marker.js', ['Blockly.Marker'], ['Blockly.ASTNode']); -goog.addDependency('../../core/keyboard_nav/tab_navigate_cursor.js', ['Blockly.TabNavigateCursor'], ['Blockly.ASTNode', 'Blockly.BasicCursor', 'Blockly.utils.object']); -goog.addDependency('../../core/marker_manager.js', ['Blockly.MarkerManager'], ['Blockly.Cursor', 'Blockly.Marker']); -goog.addDependency('../../core/menu.js', ['Blockly.Menu'], ['Blockly.browserEvents', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.style']); -goog.addDependency('../../core/menuitem.js', ['Blockly.MenuItem'], ['Blockly.utils.IdGenerator', 'Blockly.utils.aria', 'Blockly.utils.dom']); -goog.addDependency('../../core/metrics_manager.js', ['Blockly.FlyoutMetricsManager', 'Blockly.MetricsManager'], ['Blockly.IMetricsManager', 'Blockly.registry', 'Blockly.utils.Size', 'Blockly.utils.toolbox'], {'lang': 'es5'}); -goog.addDependency('../../core/msg.js', ['Blockly.Msg'], ['Blockly.utils.global']); -goog.addDependency('../../core/mutator.js', ['Blockly.Mutator'], ['Blockly.Bubble', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.Options', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox', 'Blockly.utils.xml']); -goog.addDependency('../../core/names.js', ['Blockly.Names'], ['Blockly.Msg', 'Blockly.constants']); -goog.addDependency('../../core/options.js', ['Blockly.Options'], ['Blockly.Theme', 'Blockly.Themes.Classic', 'Blockly.registry', 'Blockly.utils.IdGenerator', 'Blockly.utils.Metrics', 'Blockly.utils.toolbox']); -goog.addDependency('../../core/positionable_helpers.js', ['Blockly.uiPosition'], ['Blockly.Scrollbar', 'Blockly.utils.Rect', 'Blockly.utils.toolbox']); -goog.addDependency('../../core/procedures.js', ['Blockly.Procedures'], ['Blockly.Blocks', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.Msg', 'Blockly.Names', 'Blockly.Workspace', 'Blockly.Xml', 'Blockly.constants', 'Blockly.utils.xml']); -goog.addDependency('../../core/registry.js', ['Blockly.registry'], []); -goog.addDependency('../../core/rendered_connection.js', ['Blockly.RenderedConnection'], ['Blockly.Connection', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.object']); -goog.addDependency('../../core/renderers/common/block_rendering.js', ['Blockly.blockRendering'], ['Blockly.registry']); -goog.addDependency('../../core/renderers/common/constants.js', ['Blockly.blockRendering.ConstantProvider'], ['Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.svgPaths', 'Blockly.utils.userAgent'], {'lang': 'es5'}); -goog.addDependency('../../core/renderers/common/debugger.js', ['Blockly.blockRendering.Debug'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.Types', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es5'}); -goog.addDependency('../../core/renderers/common/drawer.js', ['Blockly.blockRendering.Drawer'], ['Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.Types', 'Blockly.utils.svgPaths']); -goog.addDependency('../../core/renderers/common/i_path_object.js', ['Blockly.blockRendering.IPathObject'], []); -goog.addDependency('../../core/renderers/common/info.js', ['Blockly.blockRendering.RenderInfo'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.Field', 'Blockly.blockRendering.Hat', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.JaggedEdge', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.OutputConnection', 'Blockly.blockRendering.PreviousConnection', 'Blockly.blockRendering.RoundCorner', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.SpacerRow', 'Blockly.blockRendering.SquareCorner', 'Blockly.blockRendering.StatementInput', 'Blockly.blockRendering.TopRow', 'Blockly.blockRendering.Types', 'Blockly.constants', 'Blockly.inputTypes']); -goog.addDependency('../../core/renderers/common/marker_svg.js', ['Blockly.blockRendering.MarkerSvg'], ['Blockly.ASTNode', 'Blockly.Events', 'Blockly.Events.MarkerMove', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.Svg', 'Blockly.utils.dom']); -goog.addDependency('../../core/renderers/common/path_object.js', ['Blockly.blockRendering.PathObject'], ['Blockly.Theme', 'Blockly.blockRendering.ConstantProvider', 'Blockly.blockRendering.IPathObject', 'Blockly.utils.Svg', 'Blockly.utils.dom']); -goog.addDependency('../../core/renderers/common/renderer.js', ['Blockly.blockRendering.Renderer'], ['Blockly.IRegistrable', 'Blockly.InsertionMarkerManager', 'Blockly.blockRendering.ConstantProvider', 'Blockly.blockRendering.Debug', 'Blockly.blockRendering.Drawer', 'Blockly.blockRendering.IPathObject', 'Blockly.blockRendering.MarkerSvg', 'Blockly.blockRendering.PathObject', 'Blockly.blockRendering.RenderInfo', 'Blockly.connectionTypes', 'Blockly.constants']); -goog.addDependency('../../core/renderers/geras/constants.js', ['Blockly.geras.ConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.utils.object'], {'lang': 'es5'}); -goog.addDependency('../../core/renderers/geras/drawer.js', ['Blockly.geras.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.geras.Highlighter', 'Blockly.geras.RenderInfo', 'Blockly.utils.object', 'Blockly.utils.svgPaths']); -goog.addDependency('../../core/renderers/geras/highlight_constants.js', ['Blockly.geras.HighlightConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.utils.svgPaths'], {'lang': 'es5'}); -goog.addDependency('../../core/renderers/geras/highlighter.js', ['Blockly.geras.Highlighter'], ['Blockly.blockRendering.Types', 'Blockly.utils.svgPaths']); -goog.addDependency('../../core/renderers/geras/info.js', ['Blockly.geras', 'Blockly.geras.RenderInfo'], ['Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.constants', 'Blockly.geras.InlineInput', 'Blockly.geras.StatementInput', 'Blockly.inputTypes', 'Blockly.utils.object']); -goog.addDependency('../../core/renderers/geras/measurables/inputs.js', ['Blockly.geras.InlineInput', 'Blockly.geras.StatementInput'], ['Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.StatementInput', 'Blockly.utils.object']); -goog.addDependency('../../core/renderers/geras/path_object.js', ['Blockly.geras.PathObject'], ['Blockly.Theme', 'Blockly.blockRendering.PathObject', 'Blockly.geras.ConstantProvider', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object']); -goog.addDependency('../../core/renderers/geras/renderer.js', ['Blockly.geras.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.geras.ConstantProvider', 'Blockly.geras.Drawer', 'Blockly.geras.HighlightConstantProvider', 'Blockly.geras.PathObject', 'Blockly.geras.RenderInfo', 'Blockly.utils.object']); -goog.addDependency('../../core/renderers/measurables/base.js', ['Blockly.blockRendering.Measurable'], ['Blockly.blockRendering.Types']); -goog.addDependency('../../core/renderers/measurables/connections.js', ['Blockly.blockRendering.Connection', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.OutputConnection', 'Blockly.blockRendering.PreviousConnection'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object']); -goog.addDependency('../../core/renderers/measurables/inputs.js', ['Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.InputConnection', 'Blockly.blockRendering.StatementInput'], ['Blockly.blockRendering.Connection', 'Blockly.blockRendering.Types', 'Blockly.utils.object']); -goog.addDependency('../../core/renderers/measurables/row_elements.js', ['Blockly.blockRendering.Field', 'Blockly.blockRendering.Hat', 'Blockly.blockRendering.Icon', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.JaggedEdge', 'Blockly.blockRendering.RoundCorner', 'Blockly.blockRendering.SquareCorner'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object']); -goog.addDependency('../../core/renderers/measurables/rows.js', ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.SpacerRow', 'Blockly.blockRendering.TopRow'], ['Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.InputConnection', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.PreviousConnection', 'Blockly.blockRendering.Types', 'Blockly.utils.object']); -goog.addDependency('../../core/renderers/measurables/types.js', ['Blockly.blockRendering.Types'], []); -goog.addDependency('../../core/renderers/minimalist/constants.js', ['Blockly.minimalist.ConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.utils.object']); -goog.addDependency('../../core/renderers/minimalist/drawer.js', ['Blockly.minimalist.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.minimalist.RenderInfo', 'Blockly.utils.object']); -goog.addDependency('../../core/renderers/minimalist/info.js', ['Blockly.minimalist', 'Blockly.minimalist.RenderInfo'], ['Blockly.utils.object']); -goog.addDependency('../../core/renderers/minimalist/renderer.js', ['Blockly.minimalist.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.minimalist.ConstantProvider', 'Blockly.minimalist.Drawer', 'Blockly.minimalist.RenderInfo', 'Blockly.utils.object']); -goog.addDependency('../../core/renderers/thrasos/info.js', ['Blockly.thrasos', 'Blockly.thrasos.RenderInfo'], ['Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.utils.object']); -goog.addDependency('../../core/renderers/thrasos/renderer.js', ['Blockly.thrasos.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.thrasos.RenderInfo', 'Blockly.utils.object']); -goog.addDependency('../../core/renderers/zelos/constants.js', ['Blockly.zelos.ConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.svgPaths'], {'lang': 'es5'}); -goog.addDependency('../../core/renderers/zelos/drawer.js', ['Blockly.zelos.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.utils.object', 'Blockly.utils.svgPaths', 'Blockly.zelos.RenderInfo']); -goog.addDependency('../../core/renderers/zelos/info.js', ['Blockly.zelos', 'Blockly.zelos.RenderInfo'], ['Blockly.FieldImage', 'Blockly.FieldLabel', 'Blockly.FieldTextInput', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.constants', 'Blockly.inputTypes', 'Blockly.utils.object', 'Blockly.zelos.BottomRow', 'Blockly.zelos.RightConnectionShape', 'Blockly.zelos.TopRow']); -goog.addDependency('../../core/renderers/zelos/marker_svg.js', ['Blockly.zelos.MarkerSvg'], ['Blockly.blockRendering.MarkerSvg', 'Blockly.utils.Svg', 'Blockly.utils.dom']); -goog.addDependency('../../core/renderers/zelos/measurables/inputs.js', ['Blockly.zelos.StatementInput'], ['Blockly.blockRendering.StatementInput', 'Blockly.utils.object']); -goog.addDependency('../../core/renderers/zelos/measurables/row_elements.js', ['Blockly.zelos.RightConnectionShape'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object']); -goog.addDependency('../../core/renderers/zelos/measurables/rows.js', ['Blockly.zelos.BottomRow', 'Blockly.zelos.TopRow'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.TopRow', 'Blockly.utils.object']); -goog.addDependency('../../core/renderers/zelos/path_object.js', ['Blockly.zelos.PathObject'], ['Blockly.blockRendering.PathObject', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.zelos.ConstantProvider']); -goog.addDependency('../../core/renderers/zelos/renderer.js', ['Blockly.zelos.Renderer'], ['Blockly.InsertionMarkerManager', 'Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.object', 'Blockly.zelos.ConstantProvider', 'Blockly.zelos.Drawer', 'Blockly.zelos.MarkerSvg', 'Blockly.zelos.PathObject', 'Blockly.zelos.RenderInfo']); -goog.addDependency('../../core/requires.js', ['Blockly.requires'], ['Blockly', 'Blockly.Comment', 'Blockly.ContextMenuItems', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldLabelSerializable', 'Blockly.FieldMultilineInput', 'Blockly.FieldNumber', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.FlyoutButton', 'Blockly.Generator', 'Blockly.HorizontalFlyout', 'Blockly.Mutator', 'Blockly.ShortcutItems', 'Blockly.Themes.Classic', 'Blockly.Toolbox', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.VerticalFlyout', 'Blockly.Warning', 'Blockly.ZoomControls', 'Blockly.geras.Renderer', 'Blockly.thrasos.Renderer', 'Blockly.zelos.Renderer']); -goog.addDependency('../../core/scrollbar.js', ['Blockly.Scrollbar', 'Blockly.ScrollbarPair'], ['Blockly.Events', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Metrics', 'Blockly.utils.Svg', 'Blockly.utils.dom']); -goog.addDependency('../../core/shortcut_items.js', ['Blockly.ShortcutItems'], ['Blockly.Gesture', 'Blockly.ShortcutRegistry', 'Blockly.utils.KeyCodes']); -goog.addDependency('../../core/shortcut_registry.js', ['Blockly.ShortcutRegistry'], ['Blockly.utils.KeyCodes', 'Blockly.utils.object']); -goog.addDependency('../../core/theme.js', ['Blockly.Theme'], ['Blockly.registry', 'Blockly.utils', 'Blockly.utils.object']); -goog.addDependency('../../core/theme/classic.js', ['Blockly.Themes.Classic'], ['Blockly.Theme']); -goog.addDependency('../../core/theme/zelos.js', ['Blockly.Themes.Zelos'], ['Blockly.Theme']); -goog.addDependency('../../core/theme_manager.js', ['Blockly.ThemeManager'], ['Blockly.Theme']); -goog.addDependency('../../core/toolbox/category.js', ['Blockly.ToolboxCategory'], ['Blockly.ISelectableToolboxItem', 'Blockly.ToolboxItem', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es5'}); -goog.addDependency('../../core/toolbox/collapsible_category.js', ['Blockly.CollapsibleToolboxCategory'], ['Blockly.ICollapsibleToolboxItem', 'Blockly.ToolboxCategory', 'Blockly.ToolboxItem', 'Blockly.ToolboxSeparator', 'Blockly.registry', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox']); -goog.addDependency('../../core/toolbox/separator.js', ['Blockly.ToolboxSeparator'], ['Blockly.IToolboxItem', 'Blockly.ToolboxItem', 'Blockly.registry', 'Blockly.utils.dom'], {'lang': 'es5'}); -goog.addDependency('../../core/toolbox/toolbox.js', ['Blockly.Toolbox'], ['Blockly.BlockSvg', 'Blockly.CollapsibleToolboxCategory', 'Blockly.ComponentManager', 'Blockly.Css', 'Blockly.DeleteArea', 'Blockly.Events', 'Blockly.Events.ToolboxItemSelect', 'Blockly.IAutoHideable', 'Blockly.IKeyboardAccessible', 'Blockly.IStyleable', 'Blockly.IToolbox', 'Blockly.Options', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.toolbox'], {'lang': 'es5'}); -goog.addDependency('../../core/toolbox/toolbox_item.js', ['Blockly.ToolboxItem'], ['Blockly.IToolboxItem']); -goog.addDependency('../../core/tooltip.js', ['Blockly.Tooltip'], ['Blockly.browserEvents', 'Blockly.utils.string']); -goog.addDependency('../../core/touch.js', ['Blockly.Touch'], ['Blockly.constants', 'Blockly.utils', 'Blockly.utils.global', 'Blockly.utils.string']); -goog.addDependency('../../core/touch_gesture.js', ['Blockly.TouchGesture'], ['Blockly.Gesture', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.object']); -goog.addDependency('../../core/trashcan.js', ['Blockly.Trashcan'], ['Blockly.ComponentManager', 'Blockly.DeleteArea', 'Blockly.Events', 'Blockly.Events.TrashcanOpen', 'Blockly.IAutoHideable', 'Blockly.IPositionable', 'Blockly.Options', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.registry', 'Blockly.uiPosition', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.toolbox'], {'lang': 'es5'}); -goog.addDependency('../../core/utils.js', ['Blockly.utils'], ['Blockly.Msg', 'Blockly.constants', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.colour', 'Blockly.utils.global', 'Blockly.utils.string', 'Blockly.utils.style', 'Blockly.utils.userAgent']); -goog.addDependency('../../core/utils/aria.js', ['Blockly.utils.aria'], []); -goog.addDependency('../../core/utils/colour.js', ['Blockly.utils.colour'], []); -goog.addDependency('../../core/utils/coordinate.js', ['Blockly.utils.Coordinate'], []); -goog.addDependency('../../core/utils/deprecation.js', ['Blockly.utils.deprecation'], []); -goog.addDependency('../../core/utils/dom.js', ['Blockly.utils.dom'], ['Blockly.utils.Svg', 'Blockly.utils.userAgent']); -goog.addDependency('../../core/utils/global.js', ['Blockly.utils.global'], []); -goog.addDependency('../../core/utils/idgenerator.js', ['Blockly.utils.IdGenerator'], []); -goog.addDependency('../../core/utils/keycodes.js', ['Blockly.utils.KeyCodes'], []); -goog.addDependency('../../core/utils/math.js', ['Blockly.utils.math'], []); -goog.addDependency('../../core/utils/metrics.js', ['Blockly.utils.Metrics'], []); -goog.addDependency('../../core/utils/object.js', ['Blockly.utils.object'], []); -goog.addDependency('../../core/utils/rect.js', ['Blockly.utils.Rect'], []); -goog.addDependency('../../core/utils/size.js', ['Blockly.utils.Size'], []); -goog.addDependency('../../core/utils/string.js', ['Blockly.utils.string'], []); -goog.addDependency('../../core/utils/style.js', ['Blockly.utils.style'], ['Blockly.utils.Coordinate', 'Blockly.utils.Size']); -goog.addDependency('../../core/utils/svg.js', ['Blockly.utils.Svg'], []); -goog.addDependency('../../core/utils/svg_paths.js', ['Blockly.utils.svgPaths'], []); -goog.addDependency('../../core/utils/toolbox.js', ['Blockly.utils.toolbox'], ['Blockly.Xml', 'Blockly.constants']); -goog.addDependency('../../core/utils/useragent.js', ['Blockly.utils.userAgent'], ['Blockly.utils.global']); -goog.addDependency('../../core/utils/xml.js', ['Blockly.utils.xml'], []); -goog.addDependency('../../core/variable_map.js', ['Blockly.VariableMap'], ['Blockly.Events', 'Blockly.Events.VarDelete', 'Blockly.Events.VarRename', 'Blockly.Msg', 'Blockly.utils', 'Blockly.utils.object']); -goog.addDependency('../../core/variable_model.js', ['Blockly.VariableModel'], ['Blockly.Events', 'Blockly.Events.VarCreate', 'Blockly.utils']); -goog.addDependency('../../core/variables.js', ['Blockly.Variables'], ['Blockly.Blocks', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Xml', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.xml']); -goog.addDependency('../../core/variables_dynamic.js', ['Blockly.VariablesDynamic'], ['Blockly.Blocks', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Variables', 'Blockly.utils.xml']); -goog.addDependency('../../core/warning.js', ['Blockly.Warning'], ['Blockly.Bubble', 'Blockly.Events', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object']); -goog.addDependency('../../core/widgetdiv.js', ['Blockly.WidgetDiv'], ['Blockly.utils.dom']); -goog.addDependency('../../core/workspace.js', ['Blockly.Workspace'], ['Blockly.ConnectionChecker', 'Blockly.Events', 'Blockly.IASTNodeLocation', 'Blockly.Options', 'Blockly.VariableMap', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.math']); -goog.addDependency('../../core/workspace_audio.js', ['Blockly.WorkspaceAudio'], ['Blockly.constants', 'Blockly.utils', 'Blockly.utils.global', 'Blockly.utils.userAgent'], {'lang': 'es5'}); -goog.addDependency('../../core/workspace_comment.js', ['Blockly.WorkspaceComment'], ['Blockly.Events', 'Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.xml']); -goog.addDependency('../../core/workspace_comment_render_svg.js', ['Blockly.WorkspaceCommentSvg.render'], ['Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom']); -goog.addDependency('../../core/workspace_comment_svg.js', ['Blockly.WorkspaceCommentSvg'], ['Blockly.Css', 'Blockly.Events', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.Events.Selected', 'Blockly.WorkspaceComment', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object']); -goog.addDependency('../../core/workspace_drag_surface_svg.js', ['Blockly.WorkspaceDragSurfaceSvg'], ['Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.dom']); -goog.addDependency('../../core/workspace_dragger.js', ['Blockly.WorkspaceDragger'], ['Blockly.utils.Coordinate']); -goog.addDependency('../../core/workspace_svg.js', ['Blockly.WorkspaceSvg'], ['Blockly.BlockSvg', 'Blockly.ComponentManager', 'Blockly.ConnectionDB', 'Blockly.ContextMenu', 'Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.ThemeChange', 'Blockly.Events.ViewportChange', 'Blockly.Gesture', 'Blockly.Grid', 'Blockly.IASTNodeLocationSvg', 'Blockly.MarkerManager', 'Blockly.MetricsManager', 'Blockly.Msg', 'Blockly.Options', 'Blockly.ThemeManager', 'Blockly.Themes.Classic', 'Blockly.TouchGesture', 'Blockly.Workspace', 'Blockly.WorkspaceAudio', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.Xml', 'Blockly.blockRendering', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Metrics', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es5'}); -goog.addDependency('../../core/xml.js', ['Blockly.Xml'], ['Blockly.Events', 'Blockly.constants', 'Blockly.inputTypes', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.dom', 'Blockly.utils.xml']); -goog.addDependency('../../core/zoom_controls.js', ['Blockly.ZoomControls'], ['Blockly.ComponentManager', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.Click', 'Blockly.IPositionable', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.uiPosition', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es5'}); -goog.addDependency("base.js", [], []); - -// Load Blockly. -goog.require('Blockly.requires'); - -delete root.BLOCKLY_DIR; -delete root.BLOCKLY_BOOT; -delete root.IS_NODE_JS; -}; - -if (this.IS_NODE_JS) { - this.BLOCKLY_BOOT(this); - module.exports = Blockly; -} else { - document.write(''); - document.write(''); -} diff --git a/blocks/colour.js b/blocks/colour.js index 9ab3acb95..3e697c174 100644 --- a/blocks/colour.js +++ b/blocks/colour.js @@ -19,7 +19,6 @@ goog.provide('Blockly.Blocks.colour'); // Deprecated goog.provide('Blockly.Constants.Colour'); goog.require('Blockly'); -goog.require('Blockly.Blocks'); goog.require('Blockly.FieldColour'); goog.require('Blockly.FieldLabel'); diff --git a/blocks/lists.js b/blocks/lists.js index 7d1cc9be2..5aa43b269 100644 --- a/blocks/lists.js +++ b/blocks/lists.js @@ -18,7 +18,6 @@ goog.provide('Blockly.Constants.Lists'); goog.require('Blockly'); -goog.require('Blockly.Blocks'); goog.require('Blockly.FieldDropdown'); goog.require('Blockly.FieldLabel'); goog.require('Blockly.Mutator'); @@ -131,6 +130,7 @@ Blockly.Blocks['lists_create_with'] = { }, /** * Create XML to represent list inputs. + * Backwards compatible serialization implementation. * @return {!Element} XML storage element. * @this {Blockly.Block} */ @@ -141,6 +141,7 @@ Blockly.Blocks['lists_create_with'] = { }, /** * Parse XML to restore the list inputs. + * Backwards compatible serialization implementation. * @param {!Element} xmlElement XML storage element. * @this {Blockly.Block} */ @@ -148,6 +149,23 @@ Blockly.Blocks['lists_create_with'] = { this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); this.updateShape_(); }, + /** + * Returns the state of this block as a JSON serializable object. + * @return {{itemCount: number}} The state of this block, ie the item count. + */ + saveExtraState: function() { + return { + 'itemCount': this.itemCount_, + }; + }, + /** + * Applies the given state to this block. + * @param {*} state The state to apply to this block, ie the item count. + */ + loadExtraState: function(state) { + this.itemCount_ = state['itemCount']; + this.updateShape_(); + }, /** * Populate the mutator's dialog with this block's components. * @param {!Blockly.Workspace} workspace Mutator's workspace. @@ -424,6 +442,12 @@ Blockly.Blocks['lists_getIndex'] = { var isAt = (xmlElement.getAttribute('at') != 'false'); this.updateAt_(isAt); }, + + // This block does not need JSO serialization hooks (saveExtraState and + // loadExtraState) because the state of this object is already encoded in the + // dropdown values. + // XML hooks are kept for backwards compatibility. + /** * Switch between a value block and a statement block. * @param {boolean} newStatement True if the block should be a statement. @@ -584,6 +608,12 @@ Blockly.Blocks['lists_setIndex'] = { var isAt = (xmlElement.getAttribute('at') != 'false'); this.updateAt_(isAt); }, + + // This block does not need JSO serialization hooks (saveExtraState and + // loadExtraState) because the state of this object is already encoded in the + // dropdown values. + // XML hooks are kept for backwards compatibility. + /** * Create or delete an input for the numeric index. * @param {boolean} isAt True if the input should exist. @@ -684,6 +714,12 @@ Blockly.Blocks['lists_getSublist'] = { this.updateAt_(1, isAt1); this.updateAt_(2, isAt2); }, + + // This block does not need JSO serialization hooks (saveExtraState and + // loadExtraState) because the state of this object is already encoded in the + // dropdown values. + // XML hooks are kept for backwards compatibility. + /** * Create or delete an input for a numeric index. * This block has two such inputs, independent of each other. @@ -857,5 +893,10 @@ Blockly.Blocks['lists_split'] = { */ domToMutation: function(xmlElement) { this.updateType_(xmlElement.getAttribute('mode')); - } + }, + + // This block does not need JSO serialization hooks (saveExtraState and + // loadExtraState) because the state of this object is already encoded in the + // dropdown values. + // XML hooks are kept for backwards compatibility. }; diff --git a/blocks/logic.js b/blocks/logic.js index 7f977fdad..a00fdba0a 100644 --- a/blocks/logic.js +++ b/blocks/logic.js @@ -19,7 +19,6 @@ goog.provide('Blockly.Blocks.logic'); // Deprecated goog.provide('Blockly.Constants.Logic'); goog.require('Blockly'); -goog.require('Blockly.Blocks'); goog.require('Blockly.FieldDropdown'); goog.require('Blockly.FieldLabel'); goog.require('Blockly.Mutator'); @@ -299,6 +298,7 @@ Blockly.Constants.Logic.CONTROLS_IF_MUTATOR_MIXIN = { /** * Create XML to represent the number of else-if and else inputs. + * Backwards compatible serialization implementation. * @return {Element} XML storage element. * @this {Blockly.Block} */ @@ -317,6 +317,7 @@ Blockly.Constants.Logic.CONTROLS_IF_MUTATOR_MIXIN = { }, /** * Parse XML to restore the else-if and else inputs. + * Backwards compatible serialization implementation. * @param {!Element} xmlElement XML storage element. * @this {Blockly.Block} */ @@ -325,6 +326,34 @@ Blockly.Constants.Logic.CONTROLS_IF_MUTATOR_MIXIN = { this.elseCount_ = parseInt(xmlElement.getAttribute('else'), 10) || 0; this.rebuildShape_(); }, + /** + * Returns the state of this block as a JSON serializable object. + * @return {?{elseIfCount: (number|undefined), haseElse: (boolean|undefined)}} + * The state of this block, ie the else if count and else state. + */ + saveExtraState: function() { + if (!this.elseifCount_ && !this.elseCount_) { + return null; + } + var state = Object.create(null); + if (this.elseifCount_) { + state['elseIfCount'] = this.elseifCount_; + } + if (this.elseCount_) { + state['hasElse'] = true; + } + return state; + }, + /** + * Applies the given state to this block. + * @param {*} state The state to apply to this block, ie the else if count and + * else state. + */ + loadExtraState: function(state) { + this.elseifCount_ = state['elseIfCount'] || 0; + this.elseCount_ = state['hasElse'] ? 1 : 0; + this.updateShape_(); + }, /** * Populate the mutator's dialog with this block's components. * @param {!Blockly.Workspace} workspace Mutator's workspace. diff --git a/blocks/loops.js b/blocks/loops.js index 6e7ad1997..cbb76b59e 100644 --- a/blocks/loops.js +++ b/blocks/loops.js @@ -19,7 +19,6 @@ goog.provide('Blockly.Blocks.loops'); // Deprecated goog.provide('Blockly.Constants.Loops'); goog.require('Blockly'); -goog.require('Blockly.Blocks'); goog.require('Blockly.FieldDropdown'); goog.require('Blockly.FieldLabel'); goog.require('Blockly.FieldNumber'); diff --git a/blocks/math.js b/blocks/math.js index b6827c5b1..62eb81337 100644 --- a/blocks/math.js +++ b/blocks/math.js @@ -19,7 +19,6 @@ goog.provide('Blockly.Blocks.math'); // Deprecated goog.provide('Blockly.Constants.Math'); goog.require('Blockly'); -goog.require('Blockly.Blocks'); goog.require('Blockly.FieldDropdown'); goog.require('Blockly.FieldLabel'); goog.require('Blockly.FieldNumber'); @@ -446,6 +445,7 @@ Blockly.Extensions.register('math_op_tooltip', Blockly.Constants.Math.IS_DIVISIBLEBY_MUTATOR_MIXIN = { /** * Create XML to represent whether the 'divisorInput' should be present. + * Backwards compatible serialization implementation. * @return {!Element} XML storage element. * @this {Blockly.Block} */ @@ -457,6 +457,7 @@ Blockly.Constants.Math.IS_DIVISIBLEBY_MUTATOR_MIXIN = { }, /** * Parse XML to restore the 'divisorInput'. + * Backwards compatible serialization implementation. * @param {!Element} xmlElement XML storage element. * @this {Blockly.Block} */ @@ -464,6 +465,12 @@ Blockly.Constants.Math.IS_DIVISIBLEBY_MUTATOR_MIXIN = { var divisorInput = (xmlElement.getAttribute('divisor_input') == 'true'); this.updateShape_(divisorInput); }, + + // This block does not need JSO serialization hooks (saveExtraState and + // loadExtraState) because the state of this object is already encoded in the + // dropdown values. + // XML hooks are kept for backwards compatibility. + /** * Modify this block to have (or not have) an input for 'is divisible by'. * @param {boolean} divisorInput True if this block has a divisor input. @@ -531,6 +538,7 @@ Blockly.Constants.Math.LIST_MODES_MUTATOR_MIXIN = { }, /** * Create XML to represent the output type. + * Backwards compatible serialization implementation. * @return {!Element} XML storage element. * @this {Blockly.Block} */ @@ -541,12 +549,18 @@ Blockly.Constants.Math.LIST_MODES_MUTATOR_MIXIN = { }, /** * Parse XML to restore the output type. + * Backwards compatible serialization implementation. * @param {!Element} xmlElement XML storage element. * @this {Blockly.Block} */ domToMutation: function(xmlElement) { this.updateType_(xmlElement.getAttribute('op')); - } + }, + + // This block does not need JSO serialization hooks (saveExtraState and + // loadExtraState) because the state of this object is already encoded in the + // dropdown values. + // XML hooks are kept for backwards compatibility. }; /** diff --git a/blocks/procedures.js b/blocks/procedures.js index d6127cca0..34697ce50 100644 --- a/blocks/procedures.js +++ b/blocks/procedures.js @@ -13,7 +13,6 @@ goog.provide('Blockly.Blocks.procedures'); goog.require('Blockly'); -goog.require('Blockly.Blocks'); goog.require('Blockly.Comment'); goog.require('Blockly.FieldCheckbox'); goog.require('Blockly.FieldLabel'); @@ -95,6 +94,7 @@ Blockly.Blocks['procedures_defnoreturn'] = { }, /** * Create XML to represent the argument inputs. + * Backwards compatible serialization implementation. * @param {boolean=} opt_paramIds If true include the IDs of the parameter * quarks. Used by Blockly.Procedures.mutateCallers for reconnection. * @return {!Element} XML storage element. @@ -124,6 +124,7 @@ Blockly.Blocks['procedures_defnoreturn'] = { }, /** * Parse XML to restore the argument inputs. + * Backwards compatible serialization implementation. * @param {!Element} xmlElement XML storage element. * @this {Blockly.Block} */ @@ -150,6 +151,54 @@ Blockly.Blocks['procedures_defnoreturn'] = { // Show or hide the statement input. this.setStatements_(xmlElement.getAttribute('statements') !== 'false'); }, + /** + * Returns the state of this block as a JSON serializable object. + * @return {?{params: (!Array<{name: string, id: string}>|undefined), + * hasStatements: (boolean|undefined)}} The state of this block, eg the + * parameters and statements. + */ + saveExtraState: function() { + if (!this.argumentVarModels_.length && this.hasStatements_) { + return null; + } + var state = Object.create(null); + if (this.argumentVarModels_.length) { + state['params'] = []; + for (var i = 0; i < this.argumentVarModels_.length; i++) { + state['params'].push({ + // We don't need to serialize the name, but just in case we decide + // to separate params from variables. + 'name': this.argumentVarModels_[i].name, + 'id': this.argumentVarModels_[i].getId() + }); + } + } + if (!this.hasStatements_) { + state['hasStatements'] = false; + } + return state; + }, + /** + * Applies the given state to this block. + * @param {*} state The state to apply to this block, eg the parameters and + * statements. + */ + loadExtraState: function(state) { + this.arguments_ = []; + this.argumentVarModels_ = []; + if (state['params']) { + for (var i = 0; i < state['params'].length; i++) { + var param = state['params'][i]; + var variable = Blockly.Variables.getOrCreateVariablePackage( + this.workspace, param['id'], param['name'], ''); + this.arguments_.push(variable.name); + this.argumentVarModels_.push(variable); + } + } + this.updateParams_(); + Blockly.Procedures.mutateCallers(this); + this.setStatements_(state['hasStatements'] === false ? false : true); + }, /** * Populate the mutator's dialog with this block's components. * @param {!Blockly.Workspace} workspace Mutator's workspace. @@ -436,6 +485,8 @@ Blockly.Blocks['procedures_defreturn'] = { updateParams_: Blockly.Blocks['procedures_defnoreturn'].updateParams_, mutationToDom: Blockly.Blocks['procedures_defnoreturn'].mutationToDom, domToMutation: Blockly.Blocks['procedures_defnoreturn'].domToMutation, + saveExtraState: Blockly.Blocks['procedures_defnoreturn'].saveExtraState, + loadExtraState: Blockly.Blocks['procedures_defnoreturn'].loadExtraState, decompose: Blockly.Blocks['procedures_defnoreturn'].decompose, compose: Blockly.Blocks['procedures_defnoreturn'].compose, /** @@ -519,7 +570,7 @@ Blockly.Blocks['procedures_mutatorarg'] = { * @param {string} varName User-supplied name. * @return {?string} Valid name, or null if a name was not specified. * @private - * @this Blockly.FieldTextInput + * @this {Blockly.FieldTextInput} */ validator_: function(varName) { var sourceBlock = this.getSourceBlock(); @@ -571,7 +622,7 @@ Blockly.Blocks['procedures_mutatorarg'] = { * variable name. * @param {string} newText The new variable name. * @private - * @this Blockly.FieldTextInput + * @this {Blockly.FieldTextInput} */ deleteIntermediateVars_: function(newText) { var outerWs = Blockly.Mutator.findParentWs(this.getSourceBlock().workspace); @@ -776,6 +827,7 @@ Blockly.Blocks['procedures_callnoreturn'] = { }, /** * Create XML to represent the (non-editable) name and arguments. + * Backwards compatible serialization implementation. * @return {!Element} XML storage element. * @this {Blockly.Block} */ @@ -791,6 +843,7 @@ Blockly.Blocks['procedures_callnoreturn'] = { }, /** * Parse XML to restore the (non-editable) name and parameters. + * Backwards compatible serialization implementation. * @param {!Element} xmlElement XML storage element. * @this {Blockly.Block} */ @@ -807,6 +860,34 @@ Blockly.Blocks['procedures_callnoreturn'] = { } this.setProcedureParameters_(args, paramIds); }, + /** + * Returns the state of this block as a JSON serializable object. + * @return {{name: string, params:(!Array|undefined)}} The state of + * this block, ie the params and procedure name. + */ + saveExtraState: function() { + var state = Object.create(null); + state['name'] = this.getProcedureCall(); + if (this.arguments_.length) { + state['params'] = this.arguments_; + } + return state; + }, + /** + * Applies the given state to this block. + * @param {*} state The state to apply to this block, ie the params and + * procedure name. + */ + loadExtraState: function(state) { + this.renameProcedure(this.getProcedureCall(), state['name']); + const params = state['params']; + if (params) { + const ids = []; + ids.length = params.length; + ids.fill(null); + this.setProcedureParameters_(params, ids); + } + }, /** * Return all variables referenced by this block. * @return {!Array} List of variable names. @@ -975,6 +1056,8 @@ Blockly.Blocks['procedures_callreturn'] = { updateShape_: Blockly.Blocks['procedures_callnoreturn'].updateShape_, mutationToDom: Blockly.Blocks['procedures_callnoreturn'].mutationToDom, domToMutation: Blockly.Blocks['procedures_callnoreturn'].domToMutation, + saveExtraState: Blockly.Blocks['procedures_callnoreturn'].saveExtraState, + loadExtraState: Blockly.Blocks['procedures_callnoreturn'].loadExtraState, getVars: Blockly.Blocks['procedures_callnoreturn'].getVars, getVarModels: Blockly.Blocks['procedures_callnoreturn'].getVarModels, onchange: Blockly.Blocks['procedures_callnoreturn'].onchange, @@ -1026,6 +1109,12 @@ Blockly.Blocks['procedures_ifreturn'] = { .appendField(Blockly.Msg['PROCEDURES_DEFRETURN_RETURN']); } }, + + // This block does not need JSO serialization hooks (saveExtraState and + // loadExtraState) because the state of this block is already encoded in the + // block's position in the workspace. + // XML hooks are kept for backwards compatibility. + /** * Called whenever anything on the workspace changes. * Add warning if this flow block is not nested inside a loop. @@ -1033,7 +1122,7 @@ Blockly.Blocks['procedures_ifreturn'] = { * @this {Blockly.Block} */ onchange: function(_e) { - if (!this.workspace.isDragging || this.workspace.isDragging()) { + if (this.workspace.isDragging && this.workspace.isDragging()) { return; // Don't change state at the start of a drag. } var legal = false; diff --git a/blocks/text.js b/blocks/text.js index 9e806be92..a226752e1 100644 --- a/blocks/text.js +++ b/blocks/text.js @@ -14,7 +14,6 @@ goog.provide('Blockly.Blocks.texts'); // Deprecated goog.provide('Blockly.Constants.Text'); goog.require('Blockly'); -goog.require('Blockly.Blocks'); goog.require('Blockly.FieldDropdown'); goog.require('Blockly.FieldImage'); goog.require('Blockly.FieldMultilineInput'); @@ -261,6 +260,7 @@ Blockly.Blocks['text_getSubstring'] = { }, /** * Create XML to represent whether there are 'AT' inputs. + * Backwards compatible serialization implementation. * @return {!Element} XML storage element. * @this {Blockly.Block} */ @@ -274,6 +274,7 @@ Blockly.Blocks['text_getSubstring'] = { }, /** * Parse XML to restore the 'AT' inputs. + * Backwards compatible serialization implementation. * @param {!Element} xmlElement XML storage element. * @this {Blockly.Block} */ @@ -283,6 +284,12 @@ Blockly.Blocks['text_getSubstring'] = { this.updateAt_(1, isAt1); this.updateAt_(2, isAt2); }, + + // This block does not need JSO serialization hooks (saveExtraState and + // loadExtraState) because the state of this object is already encoded in the + // dropdown values. + // XML hooks are kept for backwards compatibility. + /** * Create or delete an input for a numeric index. * This block has two such inputs, independent of each other. @@ -441,6 +448,7 @@ Blockly.Blocks['text_prompt_ext'] = { }, /** * Create XML to represent the output type. + * Backwards compatible serialization implementation. * @return {!Element} XML storage element. * @this {Blockly.Block} */ @@ -451,12 +459,18 @@ Blockly.Blocks['text_prompt_ext'] = { }, /** * Parse XML to restore the output type. + * Backwards compatible serialization implementation. * @param {!Element} xmlElement XML storage element. * @this {Blockly.Block} */ domToMutation: function(xmlElement) { this.updateType_(xmlElement.getAttribute('type')); - } + }, + + // This block does not need JSO serialization hooks (saveExtraState and + // loadExtraState) because the state of this object is already encoded in the + // dropdown values. + // XML hooks are kept for backwards compatibility. }; Blockly.Blocks['text_prompt'] = { @@ -678,6 +692,7 @@ Blockly.Constants.Text.TEXT_QUOTES_EXTENSION = function() { Blockly.Constants.Text.TEXT_JOIN_MUTATOR_MIXIN = { /** * Create XML to represent number of text inputs. + * Backwards compatible serialization implementation. * @return {!Element} XML storage element. * @this {Blockly.Block} */ @@ -688,6 +703,7 @@ Blockly.Constants.Text.TEXT_JOIN_MUTATOR_MIXIN = { }, /** * Parse XML to restore the text inputs. + * Backwards compatible serialization implementation. * @param {!Element} xmlElement XML storage element. * @this {Blockly.Block} */ @@ -695,6 +711,23 @@ Blockly.Constants.Text.TEXT_JOIN_MUTATOR_MIXIN = { this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); this.updateShape_(); }, + /** + * Returns the state of this block as a JSON serializable object. + * @return {{itemCount: number}} The state of this block, ie the item count. + */ + saveExtraState: function() { + return { + 'itemCount': this.itemCount_, + }; + }, + /** + * Applies the given state to this block. + * @param {*} state The state to apply to this block, ie the item count. + */ + loadExtraState: function(state) { + this.itemCount_ = state['itemCount']; + this.updateShape_(); + }, /** * Populate the mutator's dialog with this block's components. * @param {!Blockly.Workspace} workspace Mutator's workspace. @@ -829,6 +862,7 @@ Blockly.Constants.Text.TEXT_INDEXOF_TOOLTIP_EXTENSION = function() { Blockly.Constants.Text.TEXT_CHARAT_MUTATOR_MIXIN = { /** * Create XML to represent whether there is an 'AT' input. + * Backwards compatible serialization implementation. * @return {!Element} XML storage element. * @this {Blockly.Block} */ @@ -839,6 +873,7 @@ Blockly.Constants.Text.TEXT_CHARAT_MUTATOR_MIXIN = { }, /** * Parse XML to restore the 'AT' input. + * Backwards compatible serialization implementation. * @param {!Element} xmlElement XML storage element. * @this {Blockly.Block} */ @@ -848,6 +883,12 @@ Blockly.Constants.Text.TEXT_CHARAT_MUTATOR_MIXIN = { var isAt = (xmlElement.getAttribute('at') != 'false'); this.updateAt_(isAt); }, + + // This block does not need JSO serialization hooks (saveExtraState and + // loadExtraState) because the state of this object is already encoded in the + // dropdown values. + // XML hooks are kept for backwards compatibility. + /** * Create or delete an input for the numeric index. * @param {boolean} isAt True if the input should exist. diff --git a/blocks/variables.js b/blocks/variables.js index 65967f921..aabc9ec51 100644 --- a/blocks/variables.js +++ b/blocks/variables.js @@ -19,7 +19,6 @@ goog.provide('Blockly.Blocks.variables'); // Deprecated. goog.provide('Blockly.Constants.Variables'); goog.require('Blockly'); -goog.require('Blockly.Blocks'); goog.require('Blockly.FieldLabel'); goog.require('Blockly.FieldVariable'); diff --git a/blocks/variables_dynamic.js b/blocks/variables_dynamic.js index de9a364fd..041d1144a 100644 --- a/blocks/variables_dynamic.js +++ b/blocks/variables_dynamic.js @@ -18,7 +18,6 @@ goog.provide('Blockly.Constants.VariablesDynamic'); goog.require('Blockly'); -goog.require('Blockly.Blocks'); goog.require('Blockly.FieldLabel'); goog.require('Blockly.FieldVariable'); diff --git a/closure/goog/base.js b/closure/goog/base.js index 52a15dbcb..310db20f7 100644 --- a/closure/goog/base.js +++ b/closure/goog/base.js @@ -1,16 +1,8 @@ -// Copyright 2006 The Closure Library 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. +/** + * @license + * Copyright The Closure Library Authors. + * SPDX-License-Identifier: Apache-2.0 + */ /** * @fileoverview Bootstrap for the Google JS Library (Closure). @@ -26,6 +18,12 @@ */ +/** + * @define {boolean} Overridden to true by the compiler. + */ +var COMPILED = false; + + /** * Base namespace for the Closure library. Checks to see goog is already * defined in the current scope before assigning to prevent clobbering if @@ -57,17 +55,65 @@ goog.global = // For in-page browser environments and workers. self; + +/** + * A hook for overriding the define values in uncompiled mode. + * + * In uncompiled mode, `CLOSURE_UNCOMPILED_DEFINES` may be defined before + * loading base.js. If a key is defined in `CLOSURE_UNCOMPILED_DEFINES`, + * `goog.define` will use the value instead of the default value. This + * allows flags to be overwritten without compilation (this is normally + * accomplished with the compiler's "define" flag). + * + * Example: + *
+ *   var CLOSURE_UNCOMPILED_DEFINES = {'goog.DEBUG': false};
+ * 
+ * + * @type {Object|undefined} + */ +goog.global.CLOSURE_UNCOMPILED_DEFINES; + + +/** + * A hook for overriding the define values in uncompiled or compiled mode, + * like CLOSURE_UNCOMPILED_DEFINES but effective in compiled code. In + * uncompiled code CLOSURE_UNCOMPILED_DEFINES takes precedence. + * + * Also unlike CLOSURE_UNCOMPILED_DEFINES the values must be number, boolean or + * string literals or the compiler will emit an error. + * + * While any @define value may be set, only those set with goog.define will be + * effective for uncompiled code. + * + * Example: + *
+ *   var CLOSURE_DEFINES = {'goog.DEBUG': false} ;
+ * 
+ * + * @type {Object|undefined} + */ +goog.global.CLOSURE_DEFINES; + + /** * Builds an object structure for the provided namespace path, ensuring that * names that already exist are not overwritten. For example: * "a.b.c" -> a = {};a.b={};a.b.c={}; * Used by goog.provide and goog.exportSymbol. - * @param {string} name name of the object that this file defines. + * @param {string} name The name of the object that this file defines. + * @param {*=} object The object to expose at the end of the path. + * @param {boolean=} overwriteImplicit If object is set and a previous call + * implicitly constructed the namespace given by name, this parameter + * controls whether object should overwrite the implicitly constructed + * namespace or be merged into it. Defaults to false. + * @param {?Object=} objectToExportTo The object to add the path to; if this + * field is not specified, its value defaults to `goog.global`. * @private */ -goog.exportPath_ = function(name) { +goog.exportPath_ = function(name, object, overwriteImplicit, objectToExportTo) { var parts = name.split('.'); - var cur = goog.global; + var cur = objectToExportTo || goog.global; // Internet Explorer exhibits strange behavior when throwing errors from // methods externed in this manner. See the testExportSymbolExceptions in @@ -77,7 +123,24 @@ goog.exportPath_ = function(name) { } for (var part; parts.length && (part = parts.shift());) { - if (cur[part] && cur[part] !== Object.prototype[part]) { + if (!parts.length && object !== undefined) { + if (!overwriteImplicit && goog.isObject(object) && + goog.isObject(cur[part])) { + // Merge properties on object (the input parameter) with the existing + // implicitly defined namespace, so as to not clobber previously + // defined child namespaces. + for (var prop in object) { + if (object.hasOwnProperty(prop)) { + cur[part][prop] = object[prop]; + } + } + } else { + // Either there is no existing implicit namespace, or overwriteImplicit + // is set to true, so directly assign object (the input parameter) to + // the namespace. + cur[part] = object; + } + } else if (cur[part] && cur[part] !== Object.prototype[part]) { cur = cur[part]; } else { cur = cur[part] = {}; @@ -85,6 +148,152 @@ goog.exportPath_ = function(name) { } }; + +/** + * Defines a named value. In uncompiled mode, the value is retrieved from + * CLOSURE_DEFINES or CLOSURE_UNCOMPILED_DEFINES if the object is defined and + * has the property specified, and otherwise used the defined defaultValue. + * When compiled the default can be overridden using the compiler options or the + * value set in the CLOSURE_DEFINES object. Returns the defined value so that it + * can be used safely in modules. Note that the value type MUST be either + * boolean, number, or string. + * + * @param {string} name The distinguished name to provide. + * @param {T} defaultValue + * @return {T} The defined value. + * @template T + */ +goog.define = function(name, defaultValue) { + var value = defaultValue; + if (!COMPILED) { + var uncompiledDefines = goog.global.CLOSURE_UNCOMPILED_DEFINES; + var defines = goog.global.CLOSURE_DEFINES; + if (uncompiledDefines && + // Anti DOM-clobbering runtime check (b/37736576). + /** @type {?} */ (uncompiledDefines).nodeType === undefined && + Object.prototype.hasOwnProperty.call(uncompiledDefines, name)) { + value = uncompiledDefines[name]; + } else if ( + defines && + // Anti DOM-clobbering runtime check (b/37736576). + /** @type {?} */ (defines).nodeType === undefined && + Object.prototype.hasOwnProperty.call(defines, name)) { + value = defines[name]; + } + } + return value; +}; + + +/** + * @define {number} Integer year indicating the set of browser features that are + * guaranteed to be present. This is defined to include exactly features that + * work correctly on all "modern" browsers that are stable on January 1 of the + * specified year. For example, + * ```js + * if (goog.FEATURESET_YEAR >= 2019) { + * // use APIs known to be available on all major stable browsers Jan 1, 2019 + * } else { + * // polyfill for older browsers + * } + * ``` + * This is intended to be the primary define for removing + * unnecessary browser compatibility code (such as ponyfills and workarounds), + * and should inform the default value for most other defines: + * ```js + * const ASSUME_NATIVE_PROMISE = + * goog.define('ASSUME_NATIVE_PROMISE', goog.FEATURESET_YEAR >= 2016); + * ``` + * + * The default assumption is that IE9 is the lowest supported browser, which was + * first available Jan 1, 2012. + * + * TODO(user): Reference more thorough documentation when it's available. + */ +goog.FEATURESET_YEAR = goog.define('goog.FEATURESET_YEAR', 2012); + + +/** + * @define {boolean} DEBUG is provided as a convenience so that debugging code + * that should not be included in a production. It can be easily stripped + * by specifying --define goog.DEBUG=false to the Closure Compiler aka + * JSCompiler. For example, most toString() methods should be declared inside an + * "if (goog.DEBUG)" conditional because they are generally used for debugging + * purposes and it is difficult for the JSCompiler to statically determine + * whether they are used. + */ +goog.DEBUG = goog.define('goog.DEBUG', true); + + +/** + * @define {string} LOCALE defines the locale being used for compilation. It is + * used to select locale specific data to be compiled in js binary. BUILD rule + * can specify this value by "--define goog.LOCALE=" as a compiler + * option. + * + * Take into account that the locale code format is important. You should use + * the canonical Unicode format with hyphen as a delimiter. Language must be + * lowercase, Language Script - Capitalized, Region - UPPERCASE. + * There are few examples: pt-BR, en, en-US, sr-Latin-BO, zh-Hans-CN. + * + * See more info about locale codes here: + * http://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers + * + * For language codes you should use values defined by ISO 693-1. See it here + * http://www.w3.org/WAI/ER/IG/ert/iso639.htm. There is only one exception from + * this rule: the Hebrew language. For legacy reasons the old code (iw) should + * be used instead of the new code (he). + * + */ +goog.LOCALE = goog.define('goog.LOCALE', 'en'); // default to en + + +/** + * This method is intended to be used for bookkeeping purposes. We would + * like to distinguish uses of goog.LOCALE used for code stripping purposes + * and uses of goog.LOCALE for other uses (such as URL parameters). + * + * This allows us to ban direct uses of goog.LOCALE and to ensure that all + * code has been transformed to our new localization build scheme. + * + * @return {string} + * + */ +goog.getLocale = function() { + return goog.LOCALE; +}; + + +/** + * @define {boolean} Whether this code is running on trusted sites. + * + * On untrusted sites, several native functions can be defined or overridden by + * external libraries like Prototype, Datejs, and JQuery and setting this flag + * to false forces closure to use its own implementations when possible. + * + * If your JavaScript can be loaded by a third party site and you are wary about + * relying on non-standard implementations, specify + * "--define goog.TRUSTED_SITE=false" to the compiler. + */ +goog.TRUSTED_SITE = goog.define('goog.TRUSTED_SITE', true); + + +/** + * @define {boolean} Whether code that calls {@link goog.setTestOnly} should + * be disallowed in the compilation unit. + */ +goog.DISALLOW_TEST_ONLY_CODE = + goog.define('goog.DISALLOW_TEST_ONLY_CODE', COMPILED && !goog.DEBUG); + + +/** + * @define {boolean} Whether to use a Chrome app CSP-compliant method for + * loading scripts via goog.require. @see appendScriptSrcNode_. + */ +goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING = + goog.define('goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING', false); + + /** * Defines a namespace in Closure. * @@ -106,27 +315,199 @@ goog.exportPath_ = function(name) { * @see goog.module * @param {string} name Namespace provided by this file in the form * "goog.package.part". + * deprecated Use goog.module (see b/159289405) */ goog.provide = function(name) { - // Ensure that the same namespace isn't provided twice. - // A goog.module/goog.provide maps a goog.require to a specific file - if (goog.isProvided_(name)) { - throw Error('Namespace "' + name + '" already declared.'); + if (goog.isInModuleLoader_()) { + throw new Error('goog.provide cannot be used within a module.'); } - - delete goog.implicitNamespaces_[name]; - - var namespace = name; - while ((namespace = namespace.substring(0, namespace.lastIndexOf('.')))) { - if (goog.getObjectByName(namespace)) { - break; + if (!COMPILED) { + // Ensure that the same namespace isn't provided twice. + // A goog.module/goog.provide maps a goog.require to a specific file + if (goog.isProvided_(name)) { + throw new Error('Namespace "' + name + '" already declared.'); } - goog.implicitNamespaces_[namespace] = true; } - goog.exportPath_(name); + goog.constructNamespace_(name); }; + +/** + * @param {string} name Namespace provided by this file in the form + * "goog.package.part". + * @param {?Object=} object The object to embed in the namespace. + * @param {boolean=} overwriteImplicit If object is set and a previous call + * implicitly constructed the namespace given by name, this parameter + * controls whether opt_obj should overwrite the implicitly constructed + * namespace or be merged into it. Defaults to false. + * @private + */ +goog.constructNamespace_ = function(name, object, overwriteImplicit) { + if (!COMPILED) { + delete goog.implicitNamespaces_[name]; + + var namespace = name; + while ((namespace = namespace.substring(0, namespace.lastIndexOf('.')))) { + if (goog.getObjectByName(namespace)) { + break; + } + goog.implicitNamespaces_[namespace] = true; + } + } + + goog.exportPath_(name, object, overwriteImplicit); +}; + + +/** + * According to the CSP3 spec a nonce must be a valid base64 string. + * @see https://www.w3.org/TR/CSP3/#grammardef-base64-value + * @private @const + */ +goog.NONCE_PATTERN_ = /^[\w+/_-]+[=]{0,2}$/; + + +/** + * Returns CSP nonce, if set for any script tag. + * @param {?Window=} opt_window The window context used to retrieve the nonce. + * Defaults to global context. + * @return {string} CSP nonce or empty string if no nonce is present. + * @private + */ +goog.getScriptNonce_ = function(opt_window) { + var doc = (opt_window || goog.global).document; + var script = doc.querySelector && doc.querySelector('script[nonce]'); + if (script) { + // Try to get the nonce from the IDL property first, because browsers that + // implement additional nonce protection features (currently only Chrome) to + // prevent nonce stealing via CSS do not expose the nonce via attributes. + // See https://github.com/whatwg/html/issues/2369 + var nonce = script['nonce'] || script.getAttribute('nonce'); + if (nonce && goog.NONCE_PATTERN_.test(nonce)) { + return nonce; + } + } + return ''; +}; + + +/** + * Module identifier validation regexp. + * Note: This is a conservative check, it is very possible to be more lenient, + * the primary exclusion here is "/" and "\" and a leading ".", these + * restrictions are intended to leave the door open for using goog.require + * with relative file paths rather than module identifiers. + * @private + */ +goog.VALID_MODULE_RE_ = /^[a-zA-Z_$][a-zA-Z0-9._$]*$/; + + +/** + * Defines a module in Closure. + * + * Marks that this file must be loaded as a module and claims the namespace. + * + * A namespace may only be defined once in a codebase. It may be defined using + * goog.provide() or goog.module(). + * + * goog.module() has three requirements: + * - goog.module may not be used in the same file as goog.provide. + * - goog.module must be the first statement in the file. + * - only one goog.module is allowed per file. + * + * When a goog.module annotated file is loaded, it is enclosed in + * a strict function closure. This means that: + * - any variables declared in a goog.module file are private to the file + * (not global), though the compiler is expected to inline the module. + * - The code must obey all the rules of "strict" JavaScript. + * - the file will be marked as "use strict" + * + * NOTE: unlike goog.provide, goog.module does not declare any symbols by + * itself. If declared symbols are desired, use + * goog.module.declareLegacyNamespace(). + * + * + * See the public goog.module proposal: http://goo.gl/Va1hin + * + * @param {string} name Namespace provided by this file in the form + * "goog.package.part", is expected but not required. + * @return {void} + */ +goog.module = function(name) { + if (typeof name !== 'string' || !name || + name.search(goog.VALID_MODULE_RE_) == -1) { + throw new Error('Invalid module identifier'); + } + if (!goog.isInGoogModuleLoader_()) { + throw new Error( + 'Module ' + name + ' has been loaded incorrectly. Note, ' + + 'modules cannot be loaded as normal scripts. They require some kind of ' + + 'pre-processing step. You\'re likely trying to load a module via a ' + + 'script tag or as a part of a concatenated bundle without rewriting the ' + + 'module. For more info see: ' + + 'https://github.com/google/closure-library/wiki/goog.module:-an-ES6-module-like-alternative-to-goog.provide.'); + } + if (goog.moduleLoaderState_.moduleName) { + throw new Error('goog.module may only be called once per module.'); + } + + // Store the module name for the loader. + goog.moduleLoaderState_.moduleName = name; + if (!COMPILED) { + // Ensure that the same namespace isn't provided twice. + // A goog.module/goog.provide maps a goog.require to a specific file + if (goog.isProvided_(name)) { + throw new Error('Namespace "' + name + '" already declared.'); + } + delete goog.implicitNamespaces_[name]; + } +}; + + +/** + * @param {string} name The module identifier. + * @return {?} The module exports for an already loaded module or null. + * + * Note: This is not an alternative to goog.require, it does not + * indicate a hard dependency, instead it is used to indicate + * an optional dependency or to access the exports of a module + * that has already been loaded. + * @suppress {missingProvide} + */ +goog.module.get = function(name) { + return goog.module.getInternal_(name); +}; + + +/** + * @param {string} name The module identifier. + * @return {?} The module exports for an already loaded module or null. + * @private + */ +goog.module.getInternal_ = function(name) { + if (!COMPILED) { + if (name in goog.loadedModules_) { + return goog.loadedModules_[name].exports; + } else if (!goog.implicitNamespaces_[name]) { + var ns = goog.getObjectByName(name); + return ns != null ? ns : null; + } + } + return null; +}; + + +/** + * Types of modules the debug loader can load. + * @enum {string} + */ +goog.ModuleType = { + ES6: 'es6', + GOOG: 'goog' +}; + + /** * @private {?{ * moduleName: (string|undefined), @@ -136,32 +517,210 @@ goog.provide = function(name) { */ goog.moduleLoaderState_ = null; + /** - * Check if the given name has been goog.provided. This will return false for - * names that are available only as implicit namespaces. - * @param {string} name name of the object to look for. - * @return {boolean} Whether the name has been provided. * @private + * @return {boolean} Whether a goog.module or an es6 module is currently being + * initialized. */ -goog.isProvided_ = function(name) { - return (!goog.implicitNamespaces_[name] && - goog.isDefAndNotNull(goog.getObjectByName(name))); +goog.isInModuleLoader_ = function() { + return goog.isInGoogModuleLoader_() || goog.isInEs6ModuleLoader_(); }; -/** - * Namespaces implicitly defined by goog.provide. For example, - * goog.provide('goog.events.Event') implicitly declares that 'goog' and - * 'goog.events' must be namespaces. - * - * @type {!Object} - * @private - */ -goog.implicitNamespaces_ = {}; -// NOTE: We add goog.module as an implicit namespace as goog.module is defined -// here and because the existing module package has not been moved yet out of -// the goog.module namespace. This satisfies both the debug loader and -// ahead-of-time dependency management. +/** + * @private + * @return {boolean} Whether a goog.module is currently being initialized. + */ +goog.isInGoogModuleLoader_ = function() { + return !!goog.moduleLoaderState_ && + goog.moduleLoaderState_.type == goog.ModuleType.GOOG; +}; + + +/** + * @private + * @return {boolean} Whether an es6 module is currently being initialized. + */ +goog.isInEs6ModuleLoader_ = function() { + var inLoader = !!goog.moduleLoaderState_ && + goog.moduleLoaderState_.type == goog.ModuleType.ES6; + + if (inLoader) { + return true; + } + + var jscomp = goog.global['$jscomp']; + + if (jscomp) { + // jscomp may not have getCurrentModulePath if this is a compiled bundle + // that has some of the runtime, but not all of it. This can happen if + // optimizations are turned on so the unused runtime is removed but renaming + // and Closure pass are off (so $jscomp is still named $jscomp and the + // goog.provide/require calls still exist). + if (typeof jscomp.getCurrentModulePath != 'function') { + return false; + } + + // Bundled ES6 module. + return !!jscomp.getCurrentModulePath(); + } + + return false; +}; + + +/** + * Provide the module's exports as a globally accessible object under the + * module's declared name. This is intended to ease migration to goog.module + * for files that have existing usages. + * @suppress {missingProvide} + */ +goog.module.declareLegacyNamespace = function() { + if (!COMPILED && !goog.isInGoogModuleLoader_()) { + throw new Error( + 'goog.module.declareLegacyNamespace must be called from ' + + 'within a goog.module'); + } + if (!COMPILED && !goog.moduleLoaderState_.moduleName) { + throw new Error( + 'goog.module must be called prior to ' + + 'goog.module.declareLegacyNamespace.'); + } + goog.moduleLoaderState_.declareLegacyNamespace = true; +}; + + +/** + * Associates an ES6 module with a Closure module ID so that is available via + * goog.require. The associated ID acts like a goog.module ID - it does not + * create any global names, it is merely available via goog.require / + * goog.module.get / goog.forwardDeclare / goog.requireType. goog.require and + * goog.module.get will return the entire module as if it was import *'d. This + * allows Closure files to reference ES6 modules for the sake of migration. + * + * @param {string} namespace + * @suppress {missingProvide} + */ +goog.declareModuleId = function(namespace) { + if (!COMPILED) { + if (!goog.isInEs6ModuleLoader_()) { + throw new Error( + 'goog.declareModuleId may only be called from ' + + 'within an ES6 module'); + } + if (goog.moduleLoaderState_ && goog.moduleLoaderState_.moduleName) { + throw new Error( + 'goog.declareModuleId may only be called once per module.'); + } + if (namespace in goog.loadedModules_) { + throw new Error( + 'Module with namespace "' + namespace + '" already exists.'); + } + } + if (goog.moduleLoaderState_) { + // Not bundled - debug loading. + goog.moduleLoaderState_.moduleName = namespace; + } else { + // Bundled - not debug loading, no module loader state. + var jscomp = goog.global['$jscomp']; + if (!jscomp || typeof jscomp.getCurrentModulePath != 'function') { + throw new Error( + 'Module with namespace "' + namespace + + '" has been loaded incorrectly.'); + } + var exports = jscomp.require(jscomp.getCurrentModulePath()); + goog.loadedModules_[namespace] = { + exports: exports, + type: goog.ModuleType.ES6, + moduleId: namespace + }; + } +}; + + +/** + * Marks that the current file should only be used for testing, and never for + * live code in production. + * + * In the case of unit tests, the message may optionally be an exact namespace + * for the test (e.g. 'goog.stringTest'). The linter will then ignore the extra + * provide (if not explicitly defined in the code). + * + * @param {string=} opt_message Optional message to add to the error that's + * raised when used in production code. + */ +goog.setTestOnly = function(opt_message) { + if (goog.DISALLOW_TEST_ONLY_CODE) { + opt_message = opt_message || ''; + throw new Error( + 'Importing test-only code into non-debug environment' + + (opt_message ? ': ' + opt_message : '.')); + } +}; + + +/** + * Forward declares a symbol. This is an indication to the compiler that the + * symbol may be used in the source yet is not required and may not be provided + * in compilation. + * + * The most common usage of forward declaration is code that takes a type as a + * function parameter but does not need to require it. By forward declaring + * instead of requiring, no hard dependency is made, and (if not required + * elsewhere) the namespace may never be required and thus, not be pulled + * into the JavaScript binary. If it is required elsewhere, it will be type + * checked as normal. + * + * Before using goog.forwardDeclare, please read the documentation at + * https://github.com/google/closure-compiler/wiki/Bad-Type-Annotation to + * understand the options and tradeoffs when working with forward declarations. + * + * @param {string} name The namespace to forward declare in the form of + * "goog.package.part". + * @deprecated See go/noforwarddeclaration, Use `goog.requireType` instead. + */ +goog.forwardDeclare = function(name) {}; + + +/** + * Forward declare type information. Used to assign types to goog.global + * referenced object that would otherwise result in unknown type references + * and thus block property disambiguation. + */ +goog.forwardDeclare('Document'); +goog.forwardDeclare('HTMLScriptElement'); +goog.forwardDeclare('XMLHttpRequest'); + + +if (!COMPILED) { + /** + * Check if the given name has been goog.provided. This will return false for + * names that are available only as implicit namespaces. + * @param {string} name name of the object to look for. + * @return {boolean} Whether the name has been provided. + * @private + */ + goog.isProvided_ = function(name) { + return (name in goog.loadedModules_) || + (!goog.implicitNamespaces_[name] && goog.getObjectByName(name) != null); + }; + + /** + * Namespaces implicitly defined by goog.provide. For example, + * goog.provide('goog.events.Event') implicitly declares that 'goog' and + * 'goog.events' must be namespaces. + * + * @type {!Object} + * @private + */ + goog.implicitNamespaces_ = {'goog.module': true}; + + // NOTE: We add goog.module as an implicit namespace as goog.module is defined + // here and because the existing module package has not been moved yet out of + // the goog.module namespace. This satisifies both the debug loader and + // ahead-of-time dependency management. +} /** @@ -180,7 +739,7 @@ goog.getObjectByName = function(name, opt_obj) { var cur = opt_obj || goog.global; for (var i = 0; i < parts.length; i++) { cur = cur[parts[i]]; - if (!goog.isDefAndNotNull(cur)) { + if (cur == null) { return null; } } @@ -195,14 +754,18 @@ goog.getObjectByName = function(name, opt_obj) { * the names of the objects this file provides. * @param {!Array} requires An array of strings with * the names of the objects this file requires. + * @param {boolean|!Object=} opt_loadFlags Parameters indicating + * how the file must be loaded. The boolean 'true' is equivalent + * to {'module': 'goog'} for backwards-compatibility. Valid properties + * and values include {'module': 'goog'} and {'lang': 'es6'}. */ -goog.addDependency = function(relPath, provides, requires) { - goog.debugLoader_.addDependency(relPath, provides, requires); +goog.addDependency = function(relPath, provides, requires, opt_loadFlags) { + if (!COMPILED && goog.DEPENDENCIES_ENABLED) { + goog.debugLoader_.addDependency(relPath, provides, requires, opt_loadFlags); + } }; - - // NOTE(nnaze): The debug DOM loader was included in base.js as an original way // to do "debug-mode" development. The dependency system can sometimes be // confusing, as can the debug DOM loader's asynchronous nature. @@ -222,6 +785,30 @@ goog.addDependency = function(relPath, provides, requires) { // for example). See bootstrap/ for more information. +/** + * @define {boolean} Whether to enable the debug loader. + * + * If enabled, a call to goog.require() will attempt to load the namespace by + * appending a script tag to the DOM (if the namespace has been registered). + * + * If disabled, goog.require() will simply assert that the namespace has been + * provided (and depend on the fact that some outside tool correctly ordered + * the script). + */ +goog.ENABLE_DEBUG_LOADER = goog.define('goog.ENABLE_DEBUG_LOADER', true); + + +/** + * @param {string} msg + * @private + */ +goog.logToConsole_ = function(msg) { + if (goog.global.console) { + goog.global.console['error'](msg); + } +}; + + /** * Implements a system for the dynamic resolution of dependencies that works in * parallel with the BUILD system. @@ -236,20 +823,32 @@ goog.addDependency = function(relPath, provides, requires) { * namespace or module otherwise null. */ goog.require = function(namespace) { - // If the object already exists we do not need to do anything. - if (!goog.isProvided_(namespace)) { - var moduleLoaderState = goog.moduleLoaderState_; - goog.moduleLoaderState_ = null; - try { - goog.debugLoader_.load_(namespace); - } finally { - goog.moduleLoaderState_ = moduleLoaderState; + if (!COMPILED) { + // Might need to lazy load on old IE. + if (goog.ENABLE_DEBUG_LOADER) { + goog.debugLoader_.requested(namespace); } - } - return null; + // If the object already exists we do not need to do anything. + if (goog.isProvided_(namespace)) { + if (goog.isInModuleLoader_()) { + return goog.module.getInternal_(namespace); + } + } else if (goog.ENABLE_DEBUG_LOADER) { + var moduleLoaderState = goog.moduleLoaderState_; + goog.moduleLoaderState_ = null; + try { + goog.debugLoader_.load_(namespace); + } finally { + goog.moduleLoaderState_ = moduleLoaderState; + } + } + + return null; + } }; + /** * Requires a symbol for its type information. This is an indication to the * compiler that the symbol may appear in type annotations, yet it is not @@ -273,12 +872,275 @@ goog.requireType = function(namespace) { return {}; }; + /** * Path for included scripts. * @type {string} */ goog.basePath = ''; + +/** + * A hook for overriding the base path. + * @type {string|undefined} + */ +goog.global.CLOSURE_BASE_PATH; + + +/** + * Whether to attempt to load Closure's deps file. By default, when uncompiled, + * deps files will attempt to be loaded. + * @type {boolean|undefined} + */ +goog.global.CLOSURE_NO_DEPS; + + +/** + * A function to import a single script. This is meant to be overridden when + * Closure is being run in non-HTML contexts, such as web workers. It's defined + * in the global scope so that it can be set before base.js is loaded, which + * allows deps.js to be imported properly. + * + * The first parameter the script source, which is a relative URI. The second, + * optional parameter is the script contents, in the event the script needed + * transformation. It should return true if the script was imported, false + * otherwise. + * @type {(function(string, string=): boolean)|undefined} + */ +goog.global.CLOSURE_IMPORT_SCRIPT; + + +/** + * Null function used for default values of callbacks, etc. + * @return {void} Nothing. + * @deprecated use '()=>{}' or 'function(){}' instead. + */ +goog.nullFunction = function() {}; + + +/** + * When defining a class Foo with an abstract method bar(), you can do: + * Foo.prototype.bar = goog.abstractMethod + * + * Now if a subclass of Foo fails to override bar(), an error will be thrown + * when bar() is invoked. + * + * @type {!Function} + * @throws {Error} when invoked to indicate the method should be overridden. + * @deprecated Use "@abstract" annotation instead of goog.abstractMethod in new + * code. See + * https://github.com/google/closure-compiler/wiki/@abstract-classes-and-methods + */ +goog.abstractMethod = function() { + throw new Error('unimplemented abstract method'); +}; + + +/** + * Adds a `getInstance` static method that always returns the same + * instance object. + * @param {!Function} ctor The constructor for the class to add the static + * method to. + * @suppress {missingProperties} 'instance_' isn't a property on 'Function' + * but we don't have a better type to use here. + */ +goog.addSingletonGetter = function(ctor) { + // instance_ is immediately set to prevent issues with sealed constructors + // such as are encountered when a constructor is returned as the export object + // of a goog.module in unoptimized code. + // Delcare type to avoid conformance violations that ctor.instance_ is unknown + /** @type {undefined|!Object} @suppress {underscore} */ + ctor.instance_ = undefined; + ctor.getInstance = function() { + if (ctor.instance_) { + return ctor.instance_; + } + if (goog.DEBUG) { + // NOTE: JSCompiler can't optimize away Array#push. + goog.instantiatedSingletons_[goog.instantiatedSingletons_.length] = ctor; + } + // Cast to avoid conformance violations that ctor.instance_ is unknown + return /** @type {!Object|undefined} */ (ctor.instance_) = new ctor; + }; +}; + + +/** + * All singleton classes that have been instantiated, for testing. Don't read + * it directly, use the `goog.testing.singleton` module. The compiler + * removes this variable if unused. + * @type {!Array} + * @private + */ +goog.instantiatedSingletons_ = []; + + +/** + * @define {boolean} Whether to load goog.modules using `eval` when using + * the debug loader. This provides a better debugging experience as the + * source is unmodified and can be edited using Chrome Workspaces or similar. + * However in some environments the use of `eval` is banned + * so we provide an alternative. + */ +goog.LOAD_MODULE_USING_EVAL = goog.define('goog.LOAD_MODULE_USING_EVAL', true); + + +/** + * @define {boolean} Whether the exports of goog.modules should be sealed when + * possible. + */ +goog.SEAL_MODULE_EXPORTS = goog.define('goog.SEAL_MODULE_EXPORTS', goog.DEBUG); + + +/** + * The registry of initialized modules: + * The module identifier or path to module exports map. + * @private @const {!Object} + */ +goog.loadedModules_ = {}; + + +/** + * True if the debug loader enabled and used. + * @const {boolean} + */ +goog.DEPENDENCIES_ENABLED = !COMPILED && goog.ENABLE_DEBUG_LOADER; + + +/** + * @define {string} How to decide whether to transpile. Valid values + * are 'always', 'never', and 'detect'. The default ('detect') is to + * use feature detection to determine which language levels need + * transpilation. + */ +// NOTE(sdh): we could expand this to accept a language level to bypass +// detection: e.g. goog.TRANSPILE == 'es5' would transpile ES6 files but +// would leave ES3 and ES5 files alone. +goog.TRANSPILE = goog.define('goog.TRANSPILE', 'detect'); + +/** + * @define {boolean} If true assume that ES modules have already been + * transpiled by the jscompiler (in the same way that transpile.js would + * transpile them - to jscomp modules). Useful only for servers that wish to use + * the debug loader and transpile server side. Thus this is only respected if + * goog.TRANSPILE is "never". + */ +goog.ASSUME_ES_MODULES_TRANSPILED = + goog.define('goog.ASSUME_ES_MODULES_TRANSPILED', false); + + +/** + * @define {string} If a file needs to be transpiled what the output language + * should be. By default this is the highest language level this file detects + * the current environment supports. Generally this flag should not be set, but + * it could be useful to override. Example: If the current environment supports + * ES6 then by default ES7+ files will be transpiled to ES6, unless this is + * overridden. + * + * Valid values include: es3, es5, es6, es7, and es8. Anything not recognized + * is treated as es3. + * + * Note that setting this value does not force transpilation. Just if + * transpilation occurs this will be the output. So this is most useful when + * goog.TRANSPILE is set to 'always' and then forcing the language level to be + * something lower than what the environment detects. + */ +goog.TRANSPILE_TO_LANGUAGE = goog.define('goog.TRANSPILE_TO_LANGUAGE', ''); + + +/** + * @define {string} Path to the transpiler. Executing the script at this + * path (relative to base.js) should define a function $jscomp.transpile. + */ +goog.TRANSPILER = goog.define('goog.TRANSPILER', 'transpile.js'); + + +/** + * @define {string} Trusted Types policy name. If non-empty then Closure will + * use Trusted Types. + */ +goog.TRUSTED_TYPES_POLICY_NAME = + goog.define('goog.TRUSTED_TYPES_POLICY_NAME', 'goog'); + + +/** + * @package {?boolean} + * Visible for testing. + */ +goog.hasBadLetScoping = null; + + +/** + * @param {function(?):?|string} moduleDef The module definition. + */ +goog.loadModule = function(moduleDef) { + // NOTE: we allow function definitions to be either in the from + // of a string to eval (which keeps the original source intact) or + // in a eval forbidden environment (CSP) we allow a function definition + // which in its body must call `goog.module`, and return the exports + // of the module. + var previousState = goog.moduleLoaderState_; + try { + goog.moduleLoaderState_ = { + moduleName: '', + declareLegacyNamespace: false, + type: goog.ModuleType.GOOG + }; + var origExports = {}; + var exports = origExports; + if (typeof moduleDef === 'function') { + exports = moduleDef.call(undefined, exports); + } else if (typeof moduleDef === 'string') { + exports = goog.loadModuleFromSource_.call(undefined, exports, moduleDef); + } else { + throw new Error('Invalid module definition'); + } + + var moduleName = goog.moduleLoaderState_.moduleName; + if (typeof moduleName === 'string' && moduleName) { + // Don't seal legacy namespaces as they may be used as a parent of + // another namespace + if (goog.moduleLoaderState_.declareLegacyNamespace) { + // Whether exports was overwritten via default export assignment. + // This is important for legacy namespaces as it dictates whether + // previously a previously loaded implicit namespace should be clobbered + // or not. + var isDefaultExport = origExports !== exports; + goog.constructNamespace_(moduleName, exports, isDefaultExport); + } else if ( + goog.SEAL_MODULE_EXPORTS && Object.seal && + typeof exports == 'object' && exports != null) { + Object.seal(exports); + } + + var data = { + exports: exports, + type: goog.ModuleType.GOOG, + moduleId: goog.moduleLoaderState_.moduleName + }; + goog.loadedModules_[moduleName] = data; + } else { + throw new Error('Invalid module name \"' + moduleName + '\"'); + } + } finally { + goog.moduleLoaderState_ = previousState; + } +}; + + +/** + * @private @const + */ +goog.loadModuleFromSource_ = + /** @type {function(!Object, string):?} */ (function(exports) { + // NOTE: we avoid declaring parameters or local variables here to avoid + // masking globals or leaking values into the module definition. + 'use strict'; + eval(goog.CLOSURE_EVAL_PREFILTER_.createScript(arguments[1])); + return exports; + }); + + /** * Normalize a file path by removing redundant ".." and extraneous "." file * path components. @@ -304,228 +1166,2717 @@ goog.normalizePath_ = function(path) { }; +/** + * Provides a hook for loading a file when using Closure's goog.require() API + * with goog.modules. In particular this hook is provided to support Node.js. + * + * @type {(function(string):string)|undefined} + */ +goog.global.CLOSURE_LOAD_FILE_SYNC; + + +/** + * Loads file by synchronous XHR. Should not be used in production environments. + * @param {string} src Source URL. + * @return {?string} File contents, or null if load failed. + * @private + */ +goog.loadFileSync_ = function(src) { + if (goog.global.CLOSURE_LOAD_FILE_SYNC) { + return goog.global.CLOSURE_LOAD_FILE_SYNC(src); + } else { + try { + /** @type {XMLHttpRequest} */ + var xhr = new goog.global['XMLHttpRequest'](); + xhr.open('get', src, false); + xhr.send(); + // NOTE: Successful http: requests have a status of 200, but successful + // file: requests may have a status of zero. Any other status, or a + // thrown exception (particularly in case of file: requests) indicates + // some sort of error, which we treat as a missing or unavailable file. + return xhr.status == 0 || xhr.status == 200 ? xhr.responseText : null; + } catch (err) { + // No need to rethrow or log, since errors should show up on their own. + return null; + } + } +}; + + +/** + * Lazily retrieves the transpiler and applies it to the source. + * @param {string} code JS code. + * @param {string} path Path to the code. + * @param {string} target Language level output. + * @return {string} The transpiled code. + * @private + */ +goog.transpile_ = function(code, path, target) { + var jscomp = goog.global['$jscomp']; + if (!jscomp) { + goog.global['$jscomp'] = jscomp = {}; + } + var transpile = jscomp.transpile; + if (!transpile) { + var transpilerPath = goog.basePath + goog.TRANSPILER; + var transpilerCode = goog.loadFileSync_(transpilerPath); + if (transpilerCode) { + // This must be executed synchronously, since by the time we know we + // need it, we're about to load and write the ES6 code synchronously, + // so a normal script-tag load will be too slow. Wrapped in a function + // so that code is eval'd in the global scope. + (function() { + (0, eval)(transpilerCode + '\n//# sourceURL=' + transpilerPath); + }).call(goog.global); + // Even though the transpiler is optional, if $gwtExport is found, it's + // a sign the transpiler was loaded and the $jscomp.transpile *should* + // be there. + if (goog.global['$gwtExport'] && goog.global['$gwtExport']['$jscomp'] && + !goog.global['$gwtExport']['$jscomp']['transpile']) { + throw new Error( + 'The transpiler did not properly export the "transpile" ' + + 'method. $gwtExport: ' + JSON.stringify(goog.global['$gwtExport'])); + } + // transpile.js only exports a single $jscomp function, transpile. We + // grab just that and add it to the existing definition of $jscomp which + // contains the polyfills. + goog.global['$jscomp'].transpile = + goog.global['$gwtExport']['$jscomp']['transpile']; + jscomp = goog.global['$jscomp']; + transpile = jscomp.transpile; + } + } + if (!transpile) { + // The transpiler is an optional component. If it's not available then + // replace it with a pass-through function that simply logs. + var suffix = ' requires transpilation but no transpiler was found.'; + transpile = jscomp.transpile = function(code, path) { + // TODO(sdh): figure out some way to get this error to show up + // in test results, noting that the failure may occur in many + // different ways, including in loadModule() before the test + // runner even comes up. + goog.logToConsole_(path + suffix); + return code; + }; + } + // Note: any transpilation errors/warnings will be logged to the console. + return transpile(code, path, target); +}; + //============================================================================== // Language Enhancements //============================================================================== /** - * Returns true if the specified value is defined and not null. - * @param {?} val Variable to test. - * @return {boolean} Whether variable is defined and not null. + * This is a "fixed" version of the typeof operator. It differs from the typeof + * operator in such a way that null returns 'null' and arrays return 'array'. + * @param {?} value The value to get the type of. + * @return {string} The name of the type. */ -goog.isDefAndNotNull = function(val) { - // Note that undefined == null. - return val != null; +goog.typeOf = function(value) { + var s = typeof value; + + if (s != 'object') { + return s; + } + + if (!value) { + return 'null'; + } + + if (Array.isArray(value)) { + return 'array'; + } + return s; }; + +/** + * Returns true if the object looks like an array. To qualify as array like + * the value needs to be either a NodeList or an object with a Number length + * property. Note that for this function neither strings nor functions are + * considered "array-like". + * + * @param {?} val Variable to test. + * @return {boolean} Whether variable is an array. + */ +goog.isArrayLike = function(val) { + var type = goog.typeOf(val); + // We do not use goog.isObject here in order to exclude function values. + return type == 'array' || type == 'object' && typeof val.length == 'number'; +}; + + +/** + * Returns true if the object looks like a Date. To qualify as Date-like the + * value needs to be an object and have a getFullYear() function. + * @param {?} val Variable to test. + * @return {boolean} Whether variable is a like a Date. + */ +goog.isDateLike = function(val) { + return goog.isObject(val) && typeof val.getFullYear == 'function'; +}; + + +/** + * Returns true if the specified value is an object. This includes arrays and + * functions. + * @param {?} val Variable to test. + * @return {boolean} Whether variable is an object. + */ +goog.isObject = function(val) { + var type = typeof val; + return type == 'object' && val != null || type == 'function'; + // return Object(val) === val also works, but is slower, especially if val is + // not an object. +}; + + +/** + * Gets a unique ID for an object. This mutates the object so that further calls + * with the same object as a parameter returns the same value. The unique ID is + * guaranteed to be unique across the current session amongst objects that are + * passed into `getUid`. There is no guarantee that the ID is unique or + * consistent across sessions. It is unsafe to generate unique ID for function + * prototypes. + * + * @param {Object} obj The object to get the unique ID for. + * @return {number} The unique ID for the object. + */ +goog.getUid = function(obj) { + // TODO(arv): Make the type stricter, do not accept null. + return Object.prototype.hasOwnProperty.call(obj, goog.UID_PROPERTY_) && + obj[goog.UID_PROPERTY_] || + (obj[goog.UID_PROPERTY_] = ++goog.uidCounter_); +}; + + +/** + * Whether the given object is already assigned a unique ID. + * + * This does not modify the object. + * + * @param {!Object} obj The object to check. + * @return {boolean} Whether there is an assigned unique id for the object. + */ +goog.hasUid = function(obj) { + return !!obj[goog.UID_PROPERTY_]; +}; + + +/** + * Removes the unique ID from an object. This is useful if the object was + * previously mutated using `goog.getUid` in which case the mutation is + * undone. + * @param {Object} obj The object to remove the unique ID field from. + */ +goog.removeUid = function(obj) { + // TODO(arv): Make the type stricter, do not accept null. + + // In IE, DOM nodes are not instances of Object and throw an exception if we + // try to delete. Instead we try to use removeAttribute. + if (obj !== null && 'removeAttribute' in obj) { + obj.removeAttribute(goog.UID_PROPERTY_); + } + + try { + delete obj[goog.UID_PROPERTY_]; + } catch (ex) { + } +}; + + +/** + * Name for unique ID property. Initialized in a way to help avoid collisions + * with other closure JavaScript on the same page. + * @type {string} + * @private + */ +goog.UID_PROPERTY_ = 'closure_uid_' + ((Math.random() * 1e9) >>> 0); + + +/** + * Counter for UID. + * @type {number} + * @private + */ +goog.uidCounter_ = 0; + + +/** + * Clones a value. The input may be an Object, Array, or basic type. Objects and + * arrays will be cloned recursively. + * + * WARNINGS: + * goog.cloneObject does not detect reference loops. Objects that + * refer to themselves will cause infinite recursion. + * + * goog.cloneObject is unaware of unique identifiers, and copies + * UIDs created by getUid into cloned results. + * + * @param {*} obj The value to clone. + * @return {*} A clone of the input value. + * @deprecated goog.cloneObject is unsafe. Prefer the goog.object methods. + */ +goog.cloneObject = function(obj) { + var type = goog.typeOf(obj); + if (type == 'object' || type == 'array') { + if (typeof obj.clone === 'function') { + return obj.clone(); + } + if (typeof Map !== 'undefined' && obj instanceof Map) { + return new Map(obj); + } else if (typeof Set !== 'undefined' && obj instanceof Set) { + return new Set(obj); + } + var clone = type == 'array' ? [] : {}; + for (var key in obj) { + clone[key] = goog.cloneObject(obj[key]); + } + return clone; + } + + return obj; +}; + + +/** + * A native implementation of goog.bind. + * @param {?function(this:T, ...)} fn A function to partially apply. + * @param {T} selfObj Specifies the object which this should point to when the + * function is run. + * @param {...*} var_args Additional arguments that are partially applied to the + * function. + * @return {!Function} A partially-applied form of the function goog.bind() was + * invoked as a method of. + * @template T + * @private + */ +goog.bindNative_ = function(fn, selfObj, var_args) { + return /** @type {!Function} */ (fn.call.apply(fn.bind, arguments)); +}; + + +/** + * A pure-JS implementation of goog.bind. + * @param {?function(this:T, ...)} fn A function to partially apply. + * @param {T} selfObj Specifies the object which this should point to when the + * function is run. + * @param {...*} var_args Additional arguments that are partially applied to the + * function. + * @return {!Function} A partially-applied form of the function goog.bind() was + * invoked as a method of. + * @template T + * @private + */ +goog.bindJs_ = function(fn, selfObj, var_args) { + if (!fn) { + throw new Error(); + } + + if (arguments.length > 2) { + var boundArgs = Array.prototype.slice.call(arguments, 2); + return function() { + // Prepend the bound arguments to the current arguments. + var newArgs = Array.prototype.slice.call(arguments); + Array.prototype.unshift.apply(newArgs, boundArgs); + return fn.apply(selfObj, newArgs); + }; + + } else { + return function() { + return fn.apply(selfObj, arguments); + }; + } +}; + + +/** + * Partially applies this function to a particular 'this object' and zero or + * more arguments. The result is a new function with some arguments of the first + * function pre-filled and the value of this 'pre-specified'. + * + * Remaining arguments specified at call-time are appended to the pre-specified + * ones. + * + * Also see: {@link #partial}. + * + * Usage: + *
var barMethBound = goog.bind(myFunction, myObj, 'arg1', 'arg2');
+ * barMethBound('arg3', 'arg4');
+ * + * @param {?function(this:T, ...)} fn A function to partially apply. + * @param {T} selfObj Specifies the object which this should point to when the + * function is run. + * @param {...*} var_args Additional arguments that are partially applied to the + * function. + * @return {!Function} A partially-applied form of the function goog.bind() was + * invoked as a method of. + * @template T + * @suppress {deprecated} See above. + * @deprecated use `=> {}` or Function.prototype.bind instead. + */ +goog.bind = function(fn, selfObj, var_args) { + // TODO(nicksantos): narrow the type signature. + if (Function.prototype.bind && + // NOTE(nicksantos): Somebody pulled base.js into the default Chrome + // extension environment. This means that for Chrome extensions, they get + // the implementation of Function.prototype.bind that calls goog.bind + // instead of the native one. Even worse, we don't want to introduce a + // circular dependency between goog.bind and Function.prototype.bind, so + // we have to hack this to make sure it works correctly. + Function.prototype.bind.toString().indexOf('native code') != -1) { + goog.bind = goog.bindNative_; + } else { + goog.bind = goog.bindJs_; + } + return goog.bind.apply(null, arguments); +}; + + +/** + * Like goog.bind(), except that a 'this object' is not required. Useful when + * the target function is already bound. + * + * Usage: + * var g = goog.partial(f, arg1, arg2); + * g(arg3, arg4); + * + * @param {Function} fn A function to partially apply. + * @param {...*} var_args Additional arguments that are partially applied to fn. + * @return {!Function} A partially-applied form of the function goog.partial() + * was invoked as a method of. + */ +goog.partial = function(fn, var_args) { + var args = Array.prototype.slice.call(arguments, 1); + return function() { + // Clone the array (with slice()) and append additional arguments + // to the existing arguments. + var newArgs = args.slice(); + newArgs.push.apply(newArgs, arguments); + return fn.apply(/** @type {?} */ (this), newArgs); + }; +}; + + +/** + * Copies all the members of a source object to a target object. This method + * does not work on all browsers for all objects that contain keys such as + * toString or hasOwnProperty. Use goog.object.extend for this purpose. + * + * NOTE: Some have advocated for the use of goog.mixin to setup classes + * with multiple inheritence (traits, mixins, etc). However, as it simply + * uses "for in", this is not compatible with ES6 classes whose methods are + * non-enumerable. Changing this, would break cases where non-enumerable + * properties are not expected. + * + * @param {Object} target Target. + * @param {Object} source Source. + * @deprecated Prefer Object.assign + */ +goog.mixin = function(target, source) { + for (var x in source) { + target[x] = source[x]; + } + + // For IE7 or lower, the for-in-loop does not contain any properties that are + // not enumerable on the prototype object (for example, isPrototypeOf from + // Object.prototype) but also it will not include 'replace' on objects that + // extend String and change 'replace' (not that it is common for anyone to + // extend anything except Object). +}; + + +/** + * @return {number} An integer value representing the number of milliseconds + * between midnight, January 1, 1970 and the current time. + * @deprecated Use Date.now + */ +goog.now = function() { + return Date.now(); +}; + + +/** + * Evals JavaScript in the global scope. + * + * Throws an exception if neither execScript or eval is defined. + * @param {string|!TrustedScript} script JavaScript string. + */ +goog.globalEval = function(script) { + (0, eval)(script); +}; + + +/** + * Optional map of CSS class names to obfuscated names used with + * goog.getCssName(). + * @private {!Object|undefined} + * @see goog.setCssNameMapping + */ +goog.cssNameMapping_; + + +/** + * Optional obfuscation style for CSS class names. Should be set to either + * 'BY_WHOLE' or 'BY_PART' if defined. + * @type {string|undefined} + * @private + * @see goog.setCssNameMapping + */ +goog.cssNameMappingStyle_; + + + +/** + * A hook for modifying the default behavior goog.getCssName. The function + * if present, will receive the standard output of the goog.getCssName as + * its input. + * + * @type {(function(string):string)|undefined} + */ +goog.global.CLOSURE_CSS_NAME_MAP_FN; + + +/** + * Handles strings that are intended to be used as CSS class names. + * + * This function works in tandem with @see goog.setCssNameMapping. + * + * Without any mapping set, the arguments are simple joined with a hyphen and + * passed through unaltered. + * + * When there is a mapping, there are two possible styles in which these + * mappings are used. In the BY_PART style, each part (i.e. in between hyphens) + * of the passed in css name is rewritten according to the map. In the BY_WHOLE + * style, the full css name is looked up in the map directly. If a rewrite is + * not specified by the map, the compiler will output a warning. + * + * When the mapping is passed to the compiler, it will replace calls to + * goog.getCssName with the strings from the mapping, e.g. + * var x = goog.getCssName('foo'); + * var y = goog.getCssName(this.baseClass, 'active'); + * becomes: + * var x = 'foo'; + * var y = this.baseClass + '-active'; + * + * If one argument is passed it will be processed, if two are passed only the + * modifier will be processed, as it is assumed the first argument was generated + * as a result of calling goog.getCssName. + * + * @param {string} className The class name. + * @param {string=} opt_modifier A modifier to be appended to the class name. + * @return {string} The class name or the concatenation of the class name and + * the modifier. + */ +goog.getCssName = function(className, opt_modifier) { + // String() is used for compatibility with compiled soy where the passed + // className can be non-string objects. + if (String(className).charAt(0) == '.') { + throw new Error( + 'className passed in goog.getCssName must not start with ".".' + + ' You passed: ' + className); + } + + var getMapping = function(cssName) { + return goog.cssNameMapping_[cssName] || cssName; + }; + + var renameByParts = function(cssName) { + // Remap all the parts individually. + var parts = cssName.split('-'); + var mapped = []; + for (var i = 0; i < parts.length; i++) { + mapped.push(getMapping(parts[i])); + } + return mapped.join('-'); + }; + + var rename; + if (goog.cssNameMapping_) { + rename = + goog.cssNameMappingStyle_ == 'BY_WHOLE' ? getMapping : renameByParts; + } else { + rename = function(a) { + return a; + }; + } + + var result = + opt_modifier ? className + '-' + rename(opt_modifier) : rename(className); + + // The special CLOSURE_CSS_NAME_MAP_FN allows users to specify further + // processing of the class name. + if (goog.global.CLOSURE_CSS_NAME_MAP_FN) { + return goog.global.CLOSURE_CSS_NAME_MAP_FN(result); + } + + return result; +}; + + +/** + * Sets the map to check when returning a value from goog.getCssName(). Example: + *
+ * goog.setCssNameMapping({
+ *   "goog": "a",
+ *   "disabled": "b",
+ * });
+ *
+ * var x = goog.getCssName('goog');
+ * // The following evaluates to: "a a-b".
+ * goog.getCssName('goog') + ' ' + goog.getCssName(x, 'disabled')
+ * 
+ * When declared as a map of string literals to string literals, the JSCompiler + * will replace all calls to goog.getCssName() using the supplied map if the + * --process_closure_primitives flag is set. + * + * @param {!Object} mapping A map of strings to strings where keys are possible + * arguments to goog.getCssName() and values are the corresponding values + * that should be returned. + * @param {string=} opt_style The style of css name mapping. There are two valid + * options: 'BY_PART', and 'BY_WHOLE'. + * @see goog.getCssName for a description. + */ +goog.setCssNameMapping = function(mapping, opt_style) { + goog.cssNameMapping_ = mapping; + goog.cssNameMappingStyle_ = opt_style; +}; + + +/** + * To use CSS renaming in compiled mode, one of the input files should have a + * call to goog.setCssNameMapping() with an object literal that the JSCompiler + * can extract and use to replace all calls to goog.getCssName(). In uncompiled + * mode, JavaScript code should be loaded before this base.js file that declares + * a global variable, CLOSURE_CSS_NAME_MAPPING, which is used below. This is + * to ensure that the mapping is loaded before any calls to goog.getCssName() + * are made in uncompiled mode. + * + * A hook for overriding the CSS name mapping. + * @type {!Object|undefined} + */ +goog.global.CLOSURE_CSS_NAME_MAPPING; + + +if (!COMPILED && goog.global.CLOSURE_CSS_NAME_MAPPING) { + // This does not call goog.setCssNameMapping() because the JSCompiler + // requires that goog.setCssNameMapping() be called with an object literal. + goog.cssNameMapping_ = goog.global.CLOSURE_CSS_NAME_MAPPING; +} + + +/** + * Gets a localized message. + * + * This function is a compiler primitive. If you give the compiler a localized + * message bundle, it will replace the string at compile-time with a localized + * version, and expand goog.getMsg call to a concatenated string. + * + * Messages must be initialized in the form: + * + * var MSG_NAME = goog.getMsg('Hello {$placeholder}', {'placeholder': 'world'}); + * + * + * This function produces a string which should be treated as plain text. Use + * {@link goog.html.SafeHtmlFormatter} in conjunction with goog.getMsg to + * produce SafeHtml. + * + * @param {string} str Translatable string, places holders in the form {$foo}. + * @param {Object=} opt_values Maps place holder name to value. + * @param {{html: (boolean|undefined), + * unescapeHtmlEntities: (boolean|undefined)}=} opt_options Options: + * html: Escape '<' in str to '<'. Used by Closure Templates where the + * generated code size and performance is critical which is why {@link + * goog.html.SafeHtmlFormatter} is not used. The value must be literal true + * or false. + * unescapeHtmlEntities: Unescape common html entities: >, <, ', + * " and &. Used for messages not in HTML context, such as with + * `textContent` property. + * @return {string} message with placeholders filled. + */ +goog.getMsg = function(str, opt_values, opt_options) { + if (opt_options && opt_options.html) { + // Note that '&' is not replaced because the translation can contain HTML + // entities. + str = str.replace(/') + .replace(/'/g, '\'') + .replace(/"/g, '"') + .replace(/&/g, '&'); + } + if (opt_values) { + str = str.replace(/\{\$([^}]+)}/g, function(match, key) { + return (opt_values != null && key in opt_values) ? opt_values[key] : + match; + }); + } + return str; +}; + + +/** + * Gets a localized message. If the message does not have a translation, gives a + * fallback message. + * + * This is useful when introducing a new message that has not yet been + * translated into all languages. + * + * This function is a compiler primitive. Must be used in the form: + * var x = goog.getMsgWithFallback(MSG_A, MSG_B); + * where MSG_A and MSG_B were initialized with goog.getMsg. + * + * @param {string} a The preferred message. + * @param {string} b The fallback message. + * @return {string} The best translated message. + */ +goog.getMsgWithFallback = function(a, b) { + return a; +}; + + +/** + * Exposes an unobfuscated global namespace path for the given object. + * Note that fields of the exported object *will* be obfuscated, unless they are + * exported in turn via this function or goog.exportProperty. + * + * Also handy for making public items that are defined in anonymous closures. + * + * ex. goog.exportSymbol('public.path.Foo', Foo); + * + * ex. goog.exportSymbol('public.path.Foo.staticFunction', Foo.staticFunction); + * public.path.Foo.staticFunction(); + * + * ex. goog.exportSymbol('public.path.Foo.prototype.myMethod', + * Foo.prototype.myMethod); + * new public.path.Foo().myMethod(); + * + * @param {string} publicPath Unobfuscated name to export. + * @param {*} object Object the name should point to. + * @param {?Object=} objectToExportTo The object to add the path to; default + * is goog.global. + */ +goog.exportSymbol = function(publicPath, object, objectToExportTo) { + goog.exportPath_( + publicPath, object, /* overwriteImplicit= */ true, objectToExportTo); +}; + + +/** + * Exports a property unobfuscated into the object's namespace. + * ex. goog.exportProperty(Foo, 'staticFunction', Foo.staticFunction); + * ex. goog.exportProperty(Foo.prototype, 'myMethod', Foo.prototype.myMethod); + * @param {Object} object Object whose static property is being exported. + * @param {string} publicName Unobfuscated name to export. + * @param {*} symbol Object the name should point to. + */ +goog.exportProperty = function(object, publicName, symbol) { + object[publicName] = symbol; +}; + + +/** + * Inherit the prototype methods from one constructor into another. + * + * Usage: + *
+ * function ParentClass(a, b) { }
+ * ParentClass.prototype.foo = function(a) { };
+ *
+ * function ChildClass(a, b, c) {
+ *   ChildClass.base(this, 'constructor', a, b);
+ * }
+ * goog.inherits(ChildClass, ParentClass);
+ *
+ * var child = new ChildClass('a', 'b', 'see');
+ * child.foo(); // This works.
+ * 
+ * + * @param {!Function} childCtor Child class. + * @param {!Function} parentCtor Parent class. + * @suppress {strictMissingProperties} superClass_ and base is not defined on + * Function. + * @deprecated Use ECMAScript class syntax instead. + */ +goog.inherits = function(childCtor, parentCtor) { + /** @constructor */ + function tempCtor() {} + tempCtor.prototype = parentCtor.prototype; + childCtor.superClass_ = parentCtor.prototype; + childCtor.prototype = new tempCtor(); + /** @override */ + childCtor.prototype.constructor = childCtor; + + /** + * Calls superclass constructor/method. + * + * This function is only available if you use goog.inherits to + * express inheritance relationships between classes. + * + * NOTE: This is a replacement for goog.base and for superClass_ + * property defined in childCtor. + * + * @param {!Object} me Should always be "this". + * @param {string} methodName The method name to call. Calling + * superclass constructor can be done with the special string + * 'constructor'. + * @param {...*} var_args The arguments to pass to superclass + * method/constructor. + * @return {*} The return value of the superclass method/constructor. + */ + childCtor.base = function(me, methodName, var_args) { + // Copying using loop to avoid deop due to passing arguments object to + // function. This is faster in many JS engines as of late 2014. + var args = new Array(arguments.length - 2); + for (var i = 2; i < arguments.length; i++) { + args[i - 2] = arguments[i]; + } + return parentCtor.prototype[methodName].apply(me, args); + }; +}; + + +/** + * Allow for aliasing within scope functions. This function exists for + * uncompiled code - in compiled code the calls will be inlined and the aliases + * applied. In uncompiled code the function is simply run since the aliases as + * written are valid JavaScript. + * + * + * @param {function()} fn Function to call. This function can contain aliases + * to namespaces (e.g. "var dom = goog.dom") or classes + * (e.g. "var Timer = goog.Timer"). + * @deprecated Use goog.module instead. + */ +goog.scope = function(fn) { + if (goog.isInModuleLoader_()) { + throw new Error('goog.scope is not supported within a module.'); + } + fn.call(goog.global); +}; + + +/* + * To support uncompiled, strict mode bundles that use eval to divide source + * like so: + * eval('someSource;//# sourceUrl sourcefile.js'); + * We need to export the globally defined symbols "goog" and "COMPILED". + * Exporting "goog" breaks the compiler optimizations, so we required that + * be defined externally. + * NOTE: We don't use goog.exportSymbol here because we don't want to trigger + * extern generation when that compiler option is enabled. + */ +if (!COMPILED) { + goog.global['COMPILED'] = COMPILED; +} + + //============================================================================== // goog.defineClass implementation //============================================================================== +/** + * Creates a restricted form of a Closure "class": + * - from the compiler's perspective, the instance returned from the + * constructor is sealed (no new properties may be added). This enables + * better checks. + * - the compiler will rewrite this definition to a form that is optimal + * for type checking and optimization (initially this will be a more + * traditional form). + * + * @param {Function} superClass The superclass, Object or null. + * @param {goog.defineClass.ClassDescriptor} def + * An object literal describing + * the class. It may have the following properties: + * "constructor": the constructor function + * "statics": an object literal containing methods to add to the constructor + * as "static" methods or a function that will receive the constructor + * function as its only parameter to which static properties can + * be added. + * all other properties are added to the prototype. + * @return {!Function} The class constructor. + * @deprecated Use ECMAScript class syntax instead. + */ +goog.defineClass = function(superClass, def) { + // TODO(johnlenz): consider making the superClass an optional parameter. + var constructor = def.constructor; + var statics = def.statics; + // Wrap the constructor prior to setting up the prototype and static methods. + if (!constructor || constructor == Object.prototype.constructor) { + constructor = function() { + throw new Error( + 'cannot instantiate an interface (no constructor defined).'); + }; + } + + var cls = goog.defineClass.createSealingConstructor_(constructor, superClass); + if (superClass) { + goog.inherits(cls, superClass); + } + + // Remove all the properties that should not be copied to the prototype. + delete def.constructor; + delete def.statics; + + goog.defineClass.applyProperties_(cls.prototype, def); + if (statics != null) { + if (statics instanceof Function) { + statics(cls); + } else { + goog.defineClass.applyProperties_(cls, statics); + } + } + + return cls; +}; + + +/** + * @typedef {{ + * constructor: (!Function|undefined), + * statics: (Object|undefined|function(Function):void) + * }} + */ +goog.defineClass.ClassDescriptor; + + +/** + * @define {boolean} Whether the instances returned by goog.defineClass should + * be sealed when possible. + * + * When sealing is disabled the constructor function will not be wrapped by + * goog.defineClass, making it incompatible with ES6 class methods. + */ +goog.defineClass.SEAL_CLASS_INSTANCES = + goog.define('goog.defineClass.SEAL_CLASS_INSTANCES', goog.DEBUG); + + +/** + * If goog.defineClass.SEAL_CLASS_INSTANCES is enabled and Object.seal is + * defined, this function will wrap the constructor in a function that seals the + * results of the provided constructor function. + * + * @param {!Function} ctr The constructor whose results maybe be sealed. + * @param {Function} superClass The superclass constructor. + * @return {!Function} The replacement constructor. + * @private + */ +goog.defineClass.createSealingConstructor_ = function(ctr, superClass) { + if (!goog.defineClass.SEAL_CLASS_INSTANCES) { + // Do now wrap the constructor when sealing is disabled. Angular code + // depends on this for injection to work properly. + return ctr; + } + + // NOTE: The sealing behavior has been removed + + /** + * @this {Object} + * @return {?} + */ + var wrappedCtr = function() { + // Don't seal an instance of a subclass when it calls the constructor of + // its super class as there is most likely still setup to do. + var instance = ctr.apply(this, arguments) || this; + instance[goog.UID_PROPERTY_] = instance[goog.UID_PROPERTY_]; + + return instance; + }; + + return wrappedCtr; +}; + + + +// TODO(johnlenz): share these values with the goog.object +/** + * The names of the fields that are defined on Object.prototype. + * @type {!Array} + * @private + * @const + */ +goog.defineClass.OBJECT_PROTOTYPE_FIELDS_ = [ + 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', + 'toLocaleString', 'toString', 'valueOf' +]; + + +// TODO(johnlenz): share this function with the goog.object +/** + * @param {!Object} target The object to add properties to. + * @param {!Object} source The object to copy properties from. + * @private + */ +goog.defineClass.applyProperties_ = function(target, source) { + // TODO(johnlenz): update this to support ES5 getters/setters + + var key; + for (key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + + // For IE the for-in-loop does not contain any properties that are not + // enumerable on the prototype object (for example isPrototypeOf from + // Object.prototype) and it will also not include 'replace' on objects that + // extend String and change 'replace' (not that it is common for anyone to + // extend anything except Object). + for (var i = 0; i < goog.defineClass.OBJECT_PROTOTYPE_FIELDS_.length; i++) { + key = goog.defineClass.OBJECT_PROTOTYPE_FIELDS_[i]; + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } +}; + +/** + * Returns the parameter. + * @param {string} s + * @return {string} + * @private + */ +goog.identity_ = function(s) { + return s; +}; + + +/** + * Creates Trusted Types policy if Trusted Types are supported by the browser. + * The policy just blesses any string as a Trusted Type. It is not visibility + * restricted because anyone can also call trustedTypes.createPolicy directly. + * However, the allowed names should be restricted by a HTTP header and the + * reference to the created policy should be visibility restricted. + * @param {string} name + * @return {?TrustedTypePolicy} + */ +goog.createTrustedTypesPolicy = function(name) { + var policy = null; + var policyFactory = goog.global.trustedTypes; + if (!policyFactory || !policyFactory.createPolicy) { + return policy; + } + // trustedTypes.createPolicy throws if called with a name that is already + // registered, even in report-only mode. Until the API changes, catch the + // error not to break the applications functionally. In such case, the code + // will fall back to using regular Safe Types. + // TODO(koto): Remove catching once createPolicy API stops throwing. + try { + policy = policyFactory.createPolicy(name, { + createHTML: goog.identity_, + createScript: goog.identity_, + createScriptURL: goog.identity_ + }); + } catch (e) { + goog.logToConsole_(e.message); + } + return policy; +}; + // There's a bug in the compiler where without collapse properties the // Closure namespace defines do not guard code correctly. To help reduce code // size also check for !COMPILED even though it redundant until this is fixed. +if (!COMPILED && goog.DEPENDENCIES_ENABLED) { -/** - * Tries to detect the base path of base.js script that bootstraps Closure. - * @private - */ -goog.findBasePath_ = function() { - /** @type {!Document} */ - var doc = goog.global.document; - // If we have a currentScript available, use it exclusively. - var currentScript = doc.currentScript; - if (currentScript) { - var scripts = [currentScript]; - } else { - var scripts = doc.getElementsByTagName('SCRIPT'); - } - // Search backwards since the current script is in almost all cases the one - // that has base.js. - for (var i = scripts.length - 1; i >= 0; --i) { - var script = /** @type {!HTMLScriptElement} */ (scripts[i]); - var src = script.src; - var qmark = src.lastIndexOf('?'); - var l = qmark == -1 ? src.length : qmark; - if (src.substr(l - 7, 7) == 'base.js') { - goog.basePath = src.substr(0, l - 7); + + /** + * Tries to detect whether the current browser is Edge, based on the user + * agent. This matches only pre-Chromium Edge. + * @see https://docs.microsoft.com/en-us/microsoft-edge/web-platform/user-agent-string + * @return {boolean} True if the current browser is Edge. + * @private + */ + goog.isEdge_ = function() { + var userAgent = goog.global.navigator && goog.global.navigator.userAgent ? + goog.global.navigator.userAgent : + ''; + var edgeRe = /Edge\/(\d+)(\.\d)*/i; + return !!userAgent.match(edgeRe); + }; + + + /** + * Tries to detect whether is in the context of an HTML document. + * @return {boolean} True if it looks like HTML document. + * @private + */ + goog.inHtmlDocument_ = function() { + /** @type {!Document} */ + var doc = goog.global.document; + return doc != null && 'write' in doc; // XULDocument misses write. + }; + + + /** + * We'd like to check for if the document readyState is 'loading'; however + * there are bugs on IE 10 and below where the readyState being anything other + * than 'complete' is not reliable. + * @return {boolean} + * @private + */ + goog.isDocumentLoading_ = function() { + // attachEvent is available on IE 6 thru 10 only, and thus can be used to + // detect those browsers. + /** @type {!HTMLDocument} */ + var doc = goog.global.document; + return doc.attachEvent ? doc.readyState != 'complete' : + doc.readyState == 'loading'; + }; + + + /** + * Tries to detect the base path of base.js script that bootstraps Closure. + * @private + */ + goog.findBasePath_ = function() { + if (goog.global.CLOSURE_BASE_PATH != undefined && + // Anti DOM-clobbering runtime check (b/37736576). + typeof goog.global.CLOSURE_BASE_PATH === 'string') { + goog.basePath = goog.global.CLOSURE_BASE_PATH; + return; + } else if (!goog.inHtmlDocument_()) { return; } - } -}; + /** @type {!Document} */ + var doc = goog.global.document; + // If we have a currentScript available, use it exclusively. + var currentScript = doc.currentScript; + if (currentScript) { + var scripts = [currentScript]; + } else { + var scripts = doc.getElementsByTagName('SCRIPT'); + } + // Search backwards since the current script is in almost all cases the one + // that has base.js. + for (var i = scripts.length - 1; i >= 0; --i) { + var script = /** @type {!HTMLScriptElement} */ (scripts[i]); + var src = script.src; + var qmark = src.lastIndexOf('?'); + var l = qmark == -1 ? src.length : qmark; + if (src.substr(l - 7, 7) == 'base.js') { + goog.basePath = src.substr(0, l - 7); + return; + } + } + }; -goog.findBasePath_(); + goog.findBasePath_(); -/** - * A debug loader is responsible for downloading and executing javascript - * files in an unbundled, uncompiled environment. - * - * @struct @constructor @final @private - */ -goog.DebugLoader_ = function() { - /** @private @const {!Object} */ - this.dependencies_ = {}; - /** @private @const {!Object} */ - this.idToPath_ = {}; - /** @private @const {!Object} */ - this.written_ = {}; - /** @private {!Array} */ - this.depsToLoad_ = []; -}; + /** @struct @constructor @final */ + goog.Transpiler = function() { + /** @private {?Object} */ + this.requiresTranspilation_ = null; + /** @private {string} */ + this.transpilationTarget_ = goog.TRANSPILE_TO_LANGUAGE; + }; + /** + * Returns a newly created map from language mode string to a boolean + * indicating whether transpilation should be done for that mode as well as + * the highest level language that this environment supports. + * + * Guaranteed invariant: + * For any two modes, l1 and l2 where l2 is a newer mode than l1, + * `map[l1] == true` implies that `map[l2] == true`. + * + * Note this method is extracted and used elsewhere, so it cannot rely on + * anything external (it should easily be able to be transformed into a + * standalone, top level function). + * + * @private + * @return {{ + * target: string, + * map: !Object + * }} + */ + goog.Transpiler.prototype.createRequiresTranspilation_ = function() { + var transpilationTarget = 'es3'; + var /** !Object */ requiresTranspilation = {'es3': false}; + var transpilationRequiredForAllLaterModes = false; + + /** + * Adds an entry to requiresTranspliation for the given language mode. + * + * IMPORTANT: Calls must be made in order from oldest to newest language + * mode. + * @param {string} modeName + * @param {function(): boolean} isSupported Returns true if the JS engine + * supports the given mode. + */ + function addNewerLanguageTranspilationCheck(modeName, isSupported) { + if (transpilationRequiredForAllLaterModes) { + requiresTranspilation[modeName] = true; + } else if (isSupported()) { + transpilationTarget = modeName; + requiresTranspilation[modeName] = false; + } else { + requiresTranspilation[modeName] = true; + transpilationRequiredForAllLaterModes = true; + } + } + + /** + * Does the given code evaluate without syntax errors and return a truthy + * result? + */ + function /** boolean */ evalCheck(/** string */ code) { + try { + return !!eval(goog.CLOSURE_EVAL_PREFILTER_.createScript(code)); + } catch (ignored) { + return false; + } + } + + // Identify ES3-only browsers by their incorrect treatment of commas. + addNewerLanguageTranspilationCheck('es5', function() { + return evalCheck('[1,].length==1'); + }); + addNewerLanguageTranspilationCheck('es6', function() { + // Edge has a non-deterministic (i.e., not reproducible) bug with ES6: + // https://github.com/Microsoft/ChakraCore/issues/1496. + if (goog.isEdge_()) { + // The Reflect.construct test below is flaky on Edge. It can sometimes + // pass or fail on 40 15.15063, so just exit early for Edge and treat + // it as ES5. Until we're on a more up to date version just always use + // ES5. See https://github.com/Microsoft/ChakraCore/issues/3217. + return false; + } + // Test es6: [FF50 (?), Edge 14 (?), Chrome 50] + // (a) default params (specifically shadowing locals), + // (b) destructuring, (c) block-scoped functions, + // (d) for-of (const), (e) new.target/Reflect.construct + var es6fullTest = + 'class X{constructor(){if(new.target!=String)throw 1;this.x=42}}' + + 'let q=Reflect.construct(X,[],String);if(q.x!=42||!(q instanceof ' + + 'String))throw 1;for(const a of[2,3]){if(a==2)continue;function ' + + 'f(z={a}){let a=0;return z.a}{function f(){return 0;}}return f()' + + '==3}'; + + return evalCheck('(()=>{"use strict";' + es6fullTest + '})()'); + }); + // ** and **= are the only new features in 'es7' + addNewerLanguageTranspilationCheck('es7', function() { + return evalCheck('2**3==8'); + }); + // async functions are the only new features in 'es8' + addNewerLanguageTranspilationCheck('es8', function() { + return evalCheck('async()=>1,1'); + }); + addNewerLanguageTranspilationCheck('es9', function() { + return evalCheck('({...rest}={}),1'); + }); + // optional catch binding, unescaped unicode paragraph separator in strings + addNewerLanguageTranspilationCheck('es_2019', function() { + return evalCheck('let r;try{r="\u2029"}catch{};r'); + }); + // optional chaining, nullish coalescing + // untested/unsupported: bigint, import meta + addNewerLanguageTranspilationCheck('es_2020', function() { + return evalCheck('null?.x??1'); + }); + addNewerLanguageTranspilationCheck('es_next', function() { + return false; // assume it always need to transpile + }); + return {target: transpilationTarget, map: requiresTranspilation}; + }; -/** - * Travserses the dependency graph and queues the given dependency, and all of - * its transitive dependencies, for loading and then starts loading if not - * paused. - * - * @param {string} namespace - * @private - */ -goog.DebugLoader_.prototype.load_ = function(namespace) { - if (!this.getPathFromDeps_(namespace)) { - throw Error('goog.require could not find: ' + namespace); - } else { - var loader = this; + /** + * Determines whether the given language needs to be transpiled. + * @param {string} lang + * @param {string|undefined} module + * @return {boolean} + */ + goog.Transpiler.prototype.needsTranspile = function(lang, module) { + if (goog.TRANSPILE == 'always') { + return true; + } else if (goog.TRANSPILE == 'never') { + return false; + } else if (!this.requiresTranspilation_) { + var obj = this.createRequiresTranspilation_(); + this.requiresTranspilation_ = obj.map; + this.transpilationTarget_ = this.transpilationTarget_ || obj.target; + } + if (lang in this.requiresTranspilation_) { + if (this.requiresTranspilation_[lang]) { + return true; + } else if ( + goog.inHtmlDocument_() && module == 'es6' && + !('noModule' in goog.global.document.createElement('script'))) { + return true; + } else { + return false; + } + } else { + throw new Error('Unknown language mode: ' + lang); + } + }; + + + /** + * Lazily retrieves the transpiler and applies it to the source. + * @param {string} code JS code. + * @param {string} path Path to the code. + * @return {string} The transpiled code. + */ + goog.Transpiler.prototype.transpile = function(code, path) { + // TODO(johnplaisted): We should delete goog.transpile_ and just have this + // function. But there's some compile error atm where goog.global is being + // stripped incorrectly without this. + return goog.transpile_(code, path, this.transpilationTarget_); + }; + + + /** @private @final {!goog.Transpiler} */ + goog.transpiler_ = new goog.Transpiler(); + + /** + * Rewrites closing script tags in input to avoid ending an enclosing script + * tag. + * + * @param {string} str + * @return {string} + * @private + */ + goog.protectScriptTag_ = function(str) { + return str.replace(/<\/(SCRIPT)/ig, '\\x3c/$1'); + }; + + + /** + * A debug loader is responsible for downloading and executing javascript + * files in an unbundled, uncompiled environment. + * + * This can be custimized via the setDependencyFactory method, or by + * CLOSURE_IMPORT_SCRIPT/CLOSURE_LOAD_FILE_SYNC. + * + * @struct @constructor @final @private + */ + goog.DebugLoader_ = function() { + /** @private @const {!Object} */ + this.dependencies_ = {}; + /** @private @const {!Object} */ + this.idToPath_ = {}; + /** @private @const {!Object} */ + this.written_ = {}; + /** @private @const {!Array} */ + this.loadingDeps_ = []; + /** @private {!Array} */ + this.depsToLoad_ = []; + /** @private {boolean} */ + this.paused_ = false; + /** @private {!goog.DependencyFactory} */ + this.factory_ = new goog.DependencyFactory(goog.transpiler_); + /** @private @const {!Object} */ + this.deferredCallbacks_ = {}; + /** @private @const {!Array} */ + this.deferredQueue_ = []; + }; + + /** + * @param {!Array} namespaces + * @param {function(): undefined} callback Function to call once all the + * namespaces have loaded. + */ + goog.DebugLoader_.prototype.bootstrap = function(namespaces, callback) { + var cb = callback; + function resolve() { + if (cb) { + goog.global.setTimeout(cb, 0); + cb = null; + } + } + + if (!namespaces.length) { + resolve(); + return; + } var deps = []; - - /** @param {string} namespace */ - var visit = function(namespace) { - var path = loader.getPathFromDeps_(namespace); - + for (var i = 0; i < namespaces.length; i++) { + var path = this.getPathFromDeps_(namespaces[i]); if (!path) { - throw Error('Bad dependency path or symbol: ' + namespace); + throw new Error('Unregonized namespace: ' + namespaces[i]); + } + deps.push(this.dependencies_[path]); + } + + var require = goog.require; + var loaded = 0; + for (var i = 0; i < namespaces.length; i++) { + require(namespaces[i]); + deps[i].onLoad(function() { + if (++loaded == namespaces.length) { + resolve(); + } + }); + } + }; + + + /** + * Loads the Closure Dependency file. + * + * Exposed a public function so CLOSURE_NO_DEPS can be set to false, base + * loaded, setDependencyFactory called, and then this called. i.e. allows + * custom loading of the deps file. + */ + goog.DebugLoader_.prototype.loadClosureDeps = function() { + // Circumvent addDependency, which would try to transpile deps.js if + // transpile is set to always. + var relPath = 'deps.js'; + this.depsToLoad_.push(this.factory_.createDependency( + goog.normalizePath_(goog.basePath + relPath), relPath, [], [], {}, + false)); + this.loadDeps_(); + }; + + + /** + * Notifies the debug loader when a dependency has been requested. + * + * @param {string} absPathOrId Path of the dependency or goog id. + * @param {boolean=} opt_force + */ + goog.DebugLoader_.prototype.requested = function(absPathOrId, opt_force) { + var path = this.getPathFromDeps_(absPathOrId); + if (path && + (opt_force || this.areDepsLoaded_(this.dependencies_[path].requires))) { + var callback = this.deferredCallbacks_[path]; + if (callback) { + delete this.deferredCallbacks_[path]; + callback(); + } + } + }; + + + /** + * Sets the dependency factory, which can be used to create custom + * goog.Dependency implementations to control how dependencies are loaded. + * + * @param {!goog.DependencyFactory} factory + */ + goog.DebugLoader_.prototype.setDependencyFactory = function(factory) { + this.factory_ = factory; + }; + + + /** + * Travserses the dependency graph and queues the given dependency, and all of + * its transitive dependencies, for loading and then starts loading if not + * paused. + * + * @param {string} namespace + * @private + */ + goog.DebugLoader_.prototype.load_ = function(namespace) { + if (!this.getPathFromDeps_(namespace)) { + var errorMessage = 'goog.require could not find: ' + namespace; + goog.logToConsole_(errorMessage); + } else { + var loader = this; + + var deps = []; + + /** @param {string} namespace */ + var visit = function(namespace) { + var path = loader.getPathFromDeps_(namespace); + + if (!path) { + throw new Error('Bad dependency path or symbol: ' + namespace); + } + + if (loader.written_[path]) { + return; + } + + loader.written_[path] = true; + + var dep = loader.dependencies_[path]; + for (var i = 0; i < dep.requires.length; i++) { + if (!goog.isProvided_(dep.requires[i])) { + visit(dep.requires[i]); + } + } + + deps.push(dep); + }; + + visit(namespace); + + var wasLoading = !!this.depsToLoad_.length; + this.depsToLoad_ = this.depsToLoad_.concat(deps); + + if (!this.paused_ && !wasLoading) { + this.loadDeps_(); + } + } + }; + + + /** + * Loads any queued dependencies until they are all loaded or paused. + * + * @private + */ + goog.DebugLoader_.prototype.loadDeps_ = function() { + var loader = this; + var paused = this.paused_; + + while (this.depsToLoad_.length && !paused) { + (function() { + var loadCallDone = false; + var dep = loader.depsToLoad_.shift(); + + var loaded = false; + loader.loading_(dep); + + var controller = { + pause: function() { + if (loadCallDone) { + throw new Error('Cannot call pause after the call to load.'); + } else { + paused = true; + } + }, + resume: function() { + if (loadCallDone) { + loader.resume_(); + } else { + // Some dep called pause and then resume in the same load call. + // Just keep running this same loop. + paused = false; + } + }, + loaded: function() { + if (loaded) { + throw new Error('Double call to loaded.'); + } + + loaded = true; + loader.loaded_(dep); + }, + pending: function() { + // Defensive copy. + var pending = []; + for (var i = 0; i < loader.loadingDeps_.length; i++) { + pending.push(loader.loadingDeps_[i]); + } + return pending; + }, + /** + * @param {goog.ModuleType} type + */ + setModuleState: function(type) { + goog.moduleLoaderState_ = { + type: type, + moduleName: '', + declareLegacyNamespace: false + }; + }, + /** @type {function(string, string, string=)} */ + registerEs6ModuleExports: function( + path, exports, opt_closureNamespace) { + if (opt_closureNamespace) { + goog.loadedModules_[opt_closureNamespace] = { + exports: exports, + type: goog.ModuleType.ES6, + moduleId: opt_closureNamespace || '' + }; + } + }, + /** @type {function(string, ?)} */ + registerGoogModuleExports: function(moduleId, exports) { + goog.loadedModules_[moduleId] = { + exports: exports, + type: goog.ModuleType.GOOG, + moduleId: moduleId + }; + }, + clearModuleState: function() { + goog.moduleLoaderState_ = null; + }, + defer: function(callback) { + if (loadCallDone) { + throw new Error( + 'Cannot register with defer after the call to load.'); + } + loader.defer_(dep, callback); + }, + areDepsLoaded: function() { + return loader.areDepsLoaded_(dep.requires); + } + }; + + try { + dep.load(controller); + } finally { + loadCallDone = true; + } + })(); + } + + if (paused) { + this.pause_(); + } + }; + + + /** @private */ + goog.DebugLoader_.prototype.pause_ = function() { + this.paused_ = true; + }; + + + /** @private */ + goog.DebugLoader_.prototype.resume_ = function() { + if (this.paused_) { + this.paused_ = false; + this.loadDeps_(); + } + }; + + + /** + * Marks the given dependency as loading (load has been called but it has not + * yet marked itself as finished). Useful for dependencies that want to know + * what else is loading. Example: goog.modules cannot eval if there are + * loading dependencies. + * + * @param {!goog.Dependency} dep + * @private + */ + goog.DebugLoader_.prototype.loading_ = function(dep) { + this.loadingDeps_.push(dep); + }; + + + /** + * Marks the given dependency as having finished loading and being available + * for require. + * + * @param {!goog.Dependency} dep + * @private + */ + goog.DebugLoader_.prototype.loaded_ = function(dep) { + for (var i = 0; i < this.loadingDeps_.length; i++) { + if (this.loadingDeps_[i] == dep) { + this.loadingDeps_.splice(i, 1); + break; + } + } + + for (var i = 0; i < this.deferredQueue_.length; i++) { + if (this.deferredQueue_[i] == dep.path) { + this.deferredQueue_.splice(i, 1); + break; + } + } + + if (this.loadingDeps_.length == this.deferredQueue_.length && + !this.depsToLoad_.length) { + // Something has asked to load these, but they may not be directly + // required again later, so load them now that we know we're done loading + // everything else. e.g. a goog module entry point. + while (this.deferredQueue_.length) { + this.requested(this.deferredQueue_.shift(), true); + } + } + + dep.loaded(); + }; + + + /** + * @param {!Array} pathsOrIds + * @return {boolean} + * @private + */ + goog.DebugLoader_.prototype.areDepsLoaded_ = function(pathsOrIds) { + for (var i = 0; i < pathsOrIds.length; i++) { + var path = this.getPathFromDeps_(pathsOrIds[i]); + if (!path || + (!(path in this.deferredCallbacks_) && + !goog.isProvided_(pathsOrIds[i]))) { + return false; + } + } + + return true; + }; + + + /** + * @param {string} absPathOrId + * @return {?string} + * @private + */ + goog.DebugLoader_.prototype.getPathFromDeps_ = function(absPathOrId) { + if (absPathOrId in this.idToPath_) { + return this.idToPath_[absPathOrId]; + } else if (absPathOrId in this.dependencies_) { + return absPathOrId; + } else { + return null; + } + }; + + + /** + * @param {!goog.Dependency} dependency + * @param {!Function} callback + * @private + */ + goog.DebugLoader_.prototype.defer_ = function(dependency, callback) { + this.deferredCallbacks_[dependency.path] = callback; + this.deferredQueue_.push(dependency.path); + }; + + + /** + * Interface for goog.Dependency implementations to have some control over + * loading of dependencies. + * + * @record + */ + goog.LoadController = function() {}; + + + /** + * Tells the controller to halt loading of more dependencies. + */ + goog.LoadController.prototype.pause = function() {}; + + + /** + * Tells the controller to resume loading of more dependencies if paused. + */ + goog.LoadController.prototype.resume = function() {}; + + + /** + * Tells the controller that this dependency has finished loading. + * + * This causes this to be removed from pending() and any load callbacks to + * fire. + */ + goog.LoadController.prototype.loaded = function() {}; + + + /** + * List of dependencies on which load has been called but which have not + * called loaded on their controller. This includes the current dependency. + * + * @return {!Array} + */ + goog.LoadController.prototype.pending = function() {}; + + + /** + * Registers an object as an ES6 module's exports so that goog.modules may + * require it by path. + * + * @param {string} path Full path of the module. + * @param {?} exports + * @param {string=} opt_closureNamespace Closure namespace to associate with + * this module. + */ + goog.LoadController.prototype.registerEs6ModuleExports = function( + path, exports, opt_closureNamespace) {}; + + + /** + * Sets the current module state. + * + * @param {goog.ModuleType} type Type of module. + */ + goog.LoadController.prototype.setModuleState = function(type) {}; + + + /** + * Clears the current module state. + */ + goog.LoadController.prototype.clearModuleState = function() {}; + + + /** + * Registers a callback to call once the dependency is actually requested + * via goog.require + all of the immediate dependencies have been loaded or + * all other files have been loaded. Allows for lazy loading until + * require'd without pausing dependency loading, which is needed on old IE. + * + * @param {!Function} callback + */ + goog.LoadController.prototype.defer = function(callback) {}; + + + /** + * @return {boolean} + */ + goog.LoadController.prototype.areDepsLoaded = function() {}; + + + /** + * Basic super class for all dependencies Closure Library can load. + * + * This default implementation is designed to load untranspiled, non-module + * scripts in a web broswer. + * + * For transpiled non-goog.module files {@see goog.TranspiledDependency}. + * For goog.modules see {@see goog.GoogModuleDependency}. + * For untranspiled ES6 modules {@see goog.Es6ModuleDependency}. + * + * @param {string} path Absolute path of this script. + * @param {string} relativePath Path of this script relative to goog.basePath. + * @param {!Array} provides goog.provided or goog.module symbols + * in this file. + * @param {!Array} requires goog symbols or relative paths to Closure + * this depends on. + * @param {!Object} loadFlags + * @struct @constructor + */ + goog.Dependency = function( + path, relativePath, provides, requires, loadFlags) { + /** @const */ + this.path = path; + /** @const */ + this.relativePath = relativePath; + /** @const */ + this.provides = provides; + /** @const */ + this.requires = requires; + /** @const */ + this.loadFlags = loadFlags; + /** @private {boolean} */ + this.loaded_ = false; + /** @private {!Array} */ + this.loadCallbacks_ = []; + }; + + + /** + * @return {string} The pathname part of this dependency's path if it is a + * URI. + */ + goog.Dependency.prototype.getPathName = function() { + var pathName = this.path; + var protocolIndex = pathName.indexOf('://'); + if (protocolIndex >= 0) { + pathName = pathName.substring(protocolIndex + 3); + var slashIndex = pathName.indexOf('/'); + if (slashIndex >= 0) { + pathName = pathName.substring(slashIndex + 1); + } + } + return pathName; + }; + + + /** + * @param {function()} callback Callback to fire as soon as this has loaded. + * @final + */ + goog.Dependency.prototype.onLoad = function(callback) { + if (this.loaded_) { + callback(); + } else { + this.loadCallbacks_.push(callback); + } + }; + + + /** + * Marks this dependency as loaded and fires any callbacks registered with + * onLoad. + * @final + */ + goog.Dependency.prototype.loaded = function() { + this.loaded_ = true; + var callbacks = this.loadCallbacks_; + this.loadCallbacks_ = []; + for (var i = 0; i < callbacks.length; i++) { + callbacks[i](); + } + }; + + + /** + * Whether or not document.written / appended script tags should be deferred. + * + * @private {boolean} + */ + goog.Dependency.defer_ = false; + + + /** + * Map of script ready / state change callbacks. Old IE cannot handle putting + * these properties on goog.global. + * + * @private @const {!Object} + */ + goog.Dependency.callbackMap_ = {}; + + + /** + * @param {function(...?):?} callback + * @return {string} + * @private + */ + goog.Dependency.registerCallback_ = function(callback) { + var key = Math.random().toString(32); + goog.Dependency.callbackMap_[key] = callback; + return key; + }; + + + /** + * @param {string} key + * @private + */ + goog.Dependency.unregisterCallback_ = function(key) { + delete goog.Dependency.callbackMap_[key]; + }; + + + /** + * @param {string} key + * @param {...?} var_args + * @private + * @suppress {unusedPrivateMembers} + */ + goog.Dependency.callback_ = function(key, var_args) { + if (key in goog.Dependency.callbackMap_) { + var callback = goog.Dependency.callbackMap_[key]; + var args = []; + for (var i = 1; i < arguments.length; i++) { + args.push(arguments[i]); + } + callback.apply(undefined, args); + } else { + var errorMessage = 'Callback key ' + key + + ' does not exist (was base.js loaded more than once?).'; + throw Error(errorMessage); + } + }; + + + /** + * Starts loading this dependency. This dependency can pause loading if it + * needs to and resume it later via the controller interface. + * + * When this is loaded it should call controller.loaded(). Note that this will + * end up calling the loaded method of this dependency; there is no need to + * call it explicitly. + * + * @param {!goog.LoadController} controller + */ + goog.Dependency.prototype.load = function(controller) { + if (goog.global.CLOSURE_IMPORT_SCRIPT) { + if (goog.global.CLOSURE_IMPORT_SCRIPT(this.path)) { + controller.loaded(); + } else { + controller.pause(); + } + return; + } + + if (!goog.inHtmlDocument_()) { + goog.logToConsole_( + 'Cannot use default debug loader outside of HTML documents.'); + if (this.relativePath == 'deps.js') { + // Some old code is relying on base.js auto loading deps.js failing with + // no error before later setting CLOSURE_IMPORT_SCRIPT. + // CLOSURE_IMPORT_SCRIPT should be set *before* base.js is loaded, or + // CLOSURE_NO_DEPS set to true. + goog.logToConsole_( + 'Consider setting CLOSURE_IMPORT_SCRIPT before loading base.js, ' + + 'or setting CLOSURE_NO_DEPS to true.'); + controller.loaded(); + } else { + controller.pause(); + } + return; + } + + /** @type {!HTMLDocument} */ + var doc = goog.global.document; + + // If the user tries to require a new symbol after document load, + // something has gone terribly wrong. Doing a document.write would + // wipe out the page. This does not apply to the CSP-compliant method + // of writing script tags. + if (doc.readyState == 'complete' && + !goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING) { + // Certain test frameworks load base.js multiple times, which tries + // to write deps.js each time. If that happens, just fail silently. + // These frameworks wipe the page between each load of base.js, so this + // is OK. + var isDeps = /\bdeps.js$/.test(this.path); + if (isDeps) { + controller.loaded(); + return; + } else { + throw Error('Cannot write "' + this.path + '" after document load'); + } + } + + var nonce = goog.getScriptNonce_(); + if (!goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING && + goog.isDocumentLoading_()) { + var key; + var callback = function(script) { + if (script.readyState && script.readyState != 'complete') { + script.onload = callback; + return; + } + goog.Dependency.unregisterCallback_(key); + controller.loaded(); + }; + key = goog.Dependency.registerCallback_(callback); + + var defer = goog.Dependency.defer_ ? ' defer' : ''; + var nonceAttr = nonce ? ' nonce="' + nonce + '"' : ''; + var script = ''); - document.write(''); -} -`; - -let deps = []; -return gulp.src(maybeAddClosureLibrary(['core/**/**/*.js'])) - .pipe(through2.obj((file, _enc, cb) => { - const result = closureDeps.parser.parseFile(file.path); - for (const dep of result.dependencies) { - deps.push(dep); - } - cb(null); - })) - .on('end', () => { - // Update the path to closure for any files that we don't know the full path - // of (parsed from a goog.addDependency call). - for (const dep of deps) { - dep.setClosurePath(closurePath); - } - - const addDependency = closureDeps.depFile - .getDepFileText(closurePath, deps) - .replace(/\\/g, '\/'); - - const requires = `goog.addDependency("base.js", [], []); - -// Load Blockly. -goog.require('Blockly.requires'); -`; - fs.writeFileSync('blockly_uncompressed.js', - header + - addDependency + - requires + - footer); - }); + const testArgs = testRoots.map(root => `--root '${root}' `).join(''); + execSync(`closure-make-deps ${testArgs} > tests/deps.mocha.js`, + {stdio: 'inherit'}); + done(); }; /** @@ -516,10 +464,10 @@ function buildAdvancedCompilationTest() { * blockly_uncompressed.js */ const buildCore = gulp.parallel( - buildCompressed, - buildBlocks, - buildUncompressed -); + buildDeps, + buildCompressed, + buildBlocks, + ); /** * This task builds all of Blockly: @@ -534,10 +482,10 @@ const buildCore = gulp.parallel( * msg/json/*.js */ const build = gulp.parallel( - buildCore, - buildGenerators, - buildLangfiles -); + buildCore, + buildGenerators, + buildLangfiles, + ); /** * This task copies built files from BUILD_DIR back to the repository @@ -565,11 +513,11 @@ function cleanBuildDir(done) { module.exports = { build: build, + deps: buildDeps, core: buildCore, blocks: buildBlocks, generateLangfiles: generateLangfiles, langfiles: buildLangfiles, - uncompressed: buildUncompressed, compressed: buildCompressed, generators: buildGenerators, checkinBuilt: checkinBuilt, diff --git a/scripts/gulpfiles/release_tasks.js b/scripts/gulpfiles/release_tasks.js index 793ce50d3..cfc2ebf8b 100644 --- a/scripts/gulpfiles/release_tasks.js +++ b/scripts/gulpfiles/release_tasks.js @@ -155,6 +155,7 @@ const rebuildAll = gulp.series( buildTasks.build, buildTasks.checkinBuilt, typings.typings, + typings.msgTypings, typings.checkinTypings, ); diff --git a/scripts/migration/renamings.js b/scripts/migration/renamings.js new file mode 100644 index 000000000..6b7553546 --- /dev/null +++ b/scripts/migration/renamings.js @@ -0,0 +1,211 @@ +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Collected information about modules and module + * exports that have been renamed between versions. + * + * For now this is a node module, not a goog.module. + */ +'use strict'; + +/** + * Map from Blockly core version number to table of renamings made + * *since* that version was released (since we don't know for sure + * what the version number of the release that will incorporate those + * renamings will be yet). + * @type {Object} + */ +const renamings = { + // Example entry: + '0.0.0': { // These renaming were made after version 0.0.0 was published. + // Each entry is keyed by the original module name. + 'module.name.Old': { + // If the module has been renamed, its new name will be listed. + module: 'module.name.new', + + // Modules which had a default export that has been turned into + // a named export the new name will be given. + export: 'defaultName', + + // For backward-compatibility reasons, we may choose to continue + // to reexport default exports in the same place in the Blockly + // tree that they were previously (or nearby). If so, the full + // path to the former default export will be listed. This path + // is only relevant to code that accesses the export via the + // namespace tree rather than by a named import. + // + // The given example implies that: + // module.name.Old === + // goog.require('module.name.new').defaultExport + // which may not be what what one expects but is very handy. + path: 'module.name.Old', + // If path is not given explicitly then it can be assumed to be + // `${module}.${export}`. + + // Modules which already had named exports can instead list + // information about exports which have been renamed or moved in + // the exports subsection, which is a map from old export name + // to object with info about the new export name. + exports: { + oldExportName: { // No need to quote this. + + // If the export has been moved to a different module, that + // module is listed. + module: 'module.name.other', + + // If the export has been given a new name, that is listed. + export: 'newExportName', + + // As with default exports, if a named export has been + // reexported on the namespace tree somewhere other than at + // `${module}.${export}` then that can specified explicitly. + path: 'module.name.Old.oldExportName', + // This given example implies that code that previously + // accessed this export via module.name.Old.oldExportName + // can continue to do so; only code using named requires + // needs to update from + // goog.require('module.name.Old').oldExportName + // to + // goog.require('module.name.new').newExportName + }, + // More individual exports in this module can be listed here. + }, + }, + // More modules with renamings can be listed here. + }, + + '4.20201217.0': { + 'Blockly': { + exports: { + // bind/unbind events functions. See PR #4642 + EventData: {module: 'Blockly.eventHandling', export: 'Data'}, + bindEvent_: {module: 'Blockly.browserEvents', export: 'bind'}, + unbindEvent_: {module: 'Blockly.browserEvents', export: 'unbind'}, + bindEventWithChecks_: { + module: 'Blockly.browserEvents', + export: 'conditionalBind', + }, + }, + }, + }, + '6.20210701.0': { + 'Blockly': { + exports: { + // Clipboard. See PR #5237. + clipboardXml_: {module: 'Blockly.clipboard', export: 'xml'}, + clipboardSource_: {module: 'Blockly.clipboard', export: 'source'}, + clipboardTypeCounts_: { + module: 'Blockly.clipboard', + export: 'typeCounts', + }, + copy: {module: 'Blockly.clipboard'}, + paste: {module: 'Blockly.clipboard'}, + duplicate: {module: 'Blockly.clipboard'}, + + // mainWorkspace. See PR #5244. + mainWorkspace: { + module: 'Blockly.common', + get: 'getMainWorkspace', + set: 'setMainWorkspace', + }, + getMainWorkspace: {module: 'Blockly.common'}, + + // parentContainer, draggingConnections. See PR #5262. + parentContainer: { + module: 'Blockly.common', + get: 'getParentContainer', + set: 'setParentContainer', + }, + setParentContainer: {module: 'Blockly.common'}, + draggingConnections: {module: 'Blockly.common'}, + // Dialogs. See PR #5457. + alert: { + module: 'Blockly.dialog', + export: 'alert', + set: 'setAlert', + }, + confirm: { + module: 'Blockly.dialog', + export: 'confirm', + set: 'setConfirm', + }, + prompt: { + module: 'Blockly.dialog', + export: 'prompt', + set: 'setPrompt', + }, + // hueToHex. See PR #5462. + hueToHex: {module: 'Blockly.utils.colour'}, + // Blockly.hideChaff() became + // Blockly.common.getMainWorkspace().hideChaff(). See PR #5460. + + // selected. See PR #5489. + selected: { + module: 'Blockly.common', + get: 'getSelected', + set: 'setSelected', + }, + }, + }, + 'Blockly.Blocks': { + module: 'Blockly.blocks', + export: 'Blocks', // Previous default export now named. + path: 'Blockly.Blocks', // But still on tree with original name. + }, + 'Blockly.ContextMenu': { + exports: { + currentBlock: {get: 'getCurrentBlock', set: 'setCurrentBlock'}, + }, + }, + 'Blockly.Events': { + exports: { + recordUndo: {get: 'getRecordUndo', set: 'setRecordUndo'}, + }, + }, + 'Blockly.Tooltip': { + exports: { + DIV: {get: 'getDiv', set: 'setDiv'}, + visible: {get: 'isVisible'}, + }, + }, + 'Blockly.WidgetDiv': { + exports: { + DIV: {get: 'getDiv'}, + }, + }, + 'Blockly.connectionTypes': { + module: 'Blockly.ConnectionType', + export: 'ConnectionType', // Previous default export now named. + path: 'Blockly.ConnectionType', // Type reexported directly. + }, + 'Blockly.utils': { + exports: { + genUid: {module: 'Blockly.utils.idGenerator'}, + getScrollDelta: {module: 'Blockly.utils.browserEvents'}, + isTargetInput: {module: 'Blockly.utils.browserEvents'}, + isRightButton: {module: 'Blockly.utils.browserEvents'}, + mouseToSvg: {module: 'Blockly.utils.browserEvents'}, + }, + }, + 'Blockly.utils.global': { + export: 'globalThis', // Previous default export now named. + path: 'Blockly.utils.global', // But still exported under original name. + }, + 'Blockly.utils.IdGenerator': { + module: 'Blockly.utils.idGenerator', + }, + 'Blockly.utils.xml': { + exports: { + // document was a function before, too - not a static property + // or get accessor. + document: {export: 'getDocument'}, + }, + }, + }, +}; + +exports.renamings = renamings; diff --git a/scripts/package/node/core.js b/scripts/package/node/core.js index 7935f0cc5..9692855d3 100644 --- a/scripts/package/node/core.js +++ b/scripts/package/node/core.js @@ -22,12 +22,12 @@ Blockly.setLocale = function (locale) { // Override textToDomDocument and provide Node.js alternatives to DOMParser and // XMLSerializer. -if (typeof Blockly.utils.global.document !== 'object') { - Blockly.utils.global.DOMParser = require('jsdom/lib/jsdom/living').DOMParser; - Blockly.utils.global.XMLSerializer = require('jsdom/lib/jsdom/living').XMLSerializer; - var doc = Blockly.utils.xml.textToDomDocument( - ''); - Blockly.utils.xml.document = function() { - return doc; - }; +const globalThis = Blockly.utils.global; +if (typeof globalThis.document !== 'object') { + const jsdom = require('jsdom/lib/jsdom/living'); + globalThis.DOMParser = jsdom.DOMParser; + globalThis.XMLSerializer = jsdom.XMLSerializer; + const xmlDocument = Blockly.utils.xml.textToDomDocument( + ``); + Blockly.utils.xml.setDocument(xmlDocument); } diff --git a/tests/deps.js b/tests/deps.js new file mode 100644 index 000000000..6d8e9e4cc --- /dev/null +++ b/tests/deps.js @@ -0,0 +1,265 @@ +goog.addDependency('../../blocks/colour.js', ['Blockly.Blocks.colour', 'Blockly.Constants.Colour'], ['Blockly', 'Blockly.FieldColour', 'Blockly.FieldLabel']); +goog.addDependency('../../blocks/lists.js', ['Blockly.Constants.Lists'], ['Blockly', 'Blockly.FieldDropdown', 'Blockly.FieldLabel', 'Blockly.Mutator'], {'lang': 'es5'}); +goog.addDependency('../../blocks/logic.js', ['Blockly.Blocks.logic', 'Blockly.Constants.Logic'], ['Blockly', 'Blockly.FieldDropdown', 'Blockly.FieldLabel', 'Blockly.Mutator']); +goog.addDependency('../../blocks/loops.js', ['Blockly.Blocks.loops', 'Blockly.Constants.Loops'], ['Blockly', 'Blockly.FieldDropdown', 'Blockly.FieldLabel', 'Blockly.FieldNumber', 'Blockly.FieldVariable', 'Blockly.Warning']); +goog.addDependency('../../blocks/math.js', ['Blockly.Blocks.math', 'Blockly.Constants.Math'], ['Blockly', 'Blockly.FieldDropdown', 'Blockly.FieldLabel', 'Blockly.FieldNumber', 'Blockly.FieldVariable'], {'lang': 'es5'}); +goog.addDependency('../../blocks/procedures.js', ['Blockly.Blocks.procedures'], ['Blockly', 'Blockly.Comment', 'Blockly.FieldCheckbox', 'Blockly.FieldLabel', 'Blockly.FieldTextInput', 'Blockly.Mutator', 'Blockly.Warning'], {'lang': 'es6'}); +goog.addDependency('../../blocks/text.js', ['Blockly.Blocks.texts', 'Blockly.Constants.Text'], ['Blockly', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldMultilineInput', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.Mutator'], {'lang': 'es5'}); +goog.addDependency('../../blocks/variables.js', ['Blockly.Blocks.variables', 'Blockly.Constants.Variables'], ['Blockly', 'Blockly.FieldLabel', 'Blockly.FieldVariable']); +goog.addDependency('../../blocks/variables_dynamic.js', ['Blockly.Constants.VariablesDynamic'], ['Blockly', 'Blockly.FieldLabel', 'Blockly.FieldVariable']); +goog.addDependency('../../core/block.js', ['Blockly.Block'], ['Blockly.ASTNode', 'Blockly.Connection', 'Blockly.ConnectionType', 'Blockly.Events.BlockChange', 'Blockly.Events.BlockCreate', 'Blockly.Events.BlockDelete', 'Blockly.Events.BlockMove', 'Blockly.Events.utils', 'Blockly.Extensions', 'Blockly.Input', 'Blockly.Tooltip', 'Blockly.blocks', 'Blockly.common', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.inputTypes', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.idGenerator', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/block_animations.js', ['Blockly.blockAnimations'], ['Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/block_drag_surface.js', ['Blockly.BlockDragSurfaceSvg'], ['Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/block_dragger.js', ['Blockly.BlockDragger'], ['Blockly.Events.BlockDrag', 'Blockly.Events.BlockMove', 'Blockly.Events.utils', 'Blockly.InsertionMarkerManager', 'Blockly.blockAnimations', 'Blockly.bumpObjects', 'Blockly.common', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/block_svg.js', ['Blockly.BlockSvg'], ['Blockly.ASTNode', 'Blockly.Block', 'Blockly.ConnectionType', 'Blockly.ContextMenu', 'Blockly.ContextMenuRegistry', 'Blockly.Events.BlockMove', 'Blockly.Events.Selected', 'Blockly.Events.utils', 'Blockly.FieldLabel', 'Blockly.MarkerManager', 'Blockly.Msg', 'Blockly.RenderedConnection', 'Blockly.TabNavigateCursor', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.blockAnimations', 'Blockly.browserEvents', 'Blockly.common', 'Blockly.constants', 'Blockly.internalConstants', 'Blockly.serialization.blocks', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/blockly.js', ['Blockly'], ['Blockly.ASTNode', 'Blockly.BasicCursor', 'Blockly.Block', 'Blockly.BlockDragSurfaceSvg', 'Blockly.BlockDragger', 'Blockly.BlockSvg', 'Blockly.BlocklyOptions', 'Blockly.Bubble', 'Blockly.BubbleDragger', 'Blockly.CollapsibleToolboxCategory', 'Blockly.Comment', 'Blockly.ComponentManager', 'Blockly.Connection', 'Blockly.ConnectionChecker', 'Blockly.ConnectionDB', 'Blockly.ConnectionType', 'Blockly.ContextMenu', 'Blockly.ContextMenuItems', 'Blockly.ContextMenuRegistry', 'Blockly.Css', 'Blockly.Cursor', 'Blockly.DeleteArea', 'Blockly.DragTarget', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.FinishedLoading', 'Blockly.Events.Ui', 'Blockly.Events.UiBase', 'Blockly.Events.VarCreate', 'Blockly.Extensions', 'Blockly.Field', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldLabel', 'Blockly.FieldLabelSerializable', 'Blockly.FieldMultilineInput', 'Blockly.FieldNumber', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.Flyout', 'Blockly.FlyoutButton', 'Blockly.FlyoutMetricsManager', 'Blockly.Generator', 'Blockly.Gesture', 'Blockly.Grid', 'Blockly.HorizontalFlyout', 'Blockly.IASTNodeLocation', 'Blockly.IASTNodeLocationSvg', 'Blockly.IASTNodeLocationWithBlock', 'Blockly.IAutoHideable', 'Blockly.IBlockDragger', 'Blockly.IBoundedElement', 'Blockly.IBubble', 'Blockly.ICollapsibleToolboxItem', 'Blockly.IComponent', 'Blockly.IConnectionChecker', 'Blockly.IContextMenu', 'Blockly.ICopyable', 'Blockly.IDeletable', 'Blockly.IDeleteArea', 'Blockly.IDragTarget', 'Blockly.IDraggable', 'Blockly.IFlyout', 'Blockly.IKeyboardAccessible', 'Blockly.IMetricsManager', 'Blockly.IMovable', 'Blockly.IPositionable', 'Blockly.IRegistrable', 'Blockly.IRegistrableField', 'Blockly.ISelectable', 'Blockly.ISelectableToolboxItem', 'Blockly.IStyleable', 'Blockly.IToolbox', 'Blockly.IToolboxItem', 'Blockly.Icon', 'Blockly.Input', 'Blockly.InsertionMarkerManager', 'Blockly.Marker', 'Blockly.MarkerManager', 'Blockly.Menu', 'Blockly.MenuItem', 'Blockly.MetricsManager', 'Blockly.Mutator', 'Blockly.Names', 'Blockly.Options', 'Blockly.Procedures', 'Blockly.Procedures', 'Blockly.RenderedConnection', 'Blockly.Scrollbar', 'Blockly.ScrollbarPair', 'Blockly.ShortcutItems', 'Blockly.ShortcutRegistry', 'Blockly.TabNavigateCursor', 'Blockly.Theme', 'Blockly.ThemeManager', 'Blockly.Themes', 'Blockly.Toolbox', 'Blockly.ToolboxCategory', 'Blockly.ToolboxItem', 'Blockly.ToolboxSeparator', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Touch', 'Blockly.TouchGesture', 'Blockly.Trashcan', 'Blockly.VariableMap', 'Blockly.VariableModel', 'Blockly.Variables', 'Blockly.Variables', 'Blockly.VariablesDynamic', 'Blockly.VerticalFlyout', 'Blockly.Warning', 'Blockly.WidgetDiv', 'Blockly.Workspace', 'Blockly.WorkspaceAudio', 'Blockly.WorkspaceComment', 'Blockly.WorkspaceCommentSvg', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.WorkspaceDragger', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.Xml', 'Blockly.ZoomControls', 'Blockly.blockAnimations', 'Blockly.blockRendering', 'Blockly.blocks', 'Blockly.browserEvents', 'Blockly.bumpObjects', 'Blockly.clipboard', 'Blockly.common', 'Blockly.constants', 'Blockly.dialog', 'Blockly.fieldRegistry', 'Blockly.geras', 'Blockly.inject', 'Blockly.inject', 'Blockly.inputTypes', 'Blockly.internalConstants', 'Blockly.minimalist', 'Blockly.registry', 'Blockly.thrasos', 'Blockly.uiPosition', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.colour', 'Blockly.utils.deprecation', 'Blockly.utils.toolbox', 'Blockly.zelos'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/blockly_options.js', ['Blockly.BlocklyOptions'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/blocks.js', ['Blockly.blocks'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/browser_events.js', ['Blockly.browserEvents'], ['Blockly.Touch', 'Blockly.internalConstants', 'Blockly.utils.global', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/bubble.js', ['Blockly.Bubble'], ['Blockly.Scrollbar', 'Blockly.Touch', 'Blockly.Workspace', 'Blockly.browserEvents', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/bubble_dragger.js', ['Blockly.BubbleDragger'], ['Blockly.Bubble', 'Blockly.ComponentManager', 'Blockly.Events.CommentMove', 'Blockly.Events.utils', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/bump_objects.js', ['Blockly.bumpObjects'], ['Blockly.Events.utils', 'Blockly.utils.math'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/clipboard.js', ['Blockly.clipboard'], ['Blockly.Events.utils'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/comment.js', ['Blockly.Comment'], ['Blockly.Bubble', 'Blockly.Css', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Events.utils', 'Blockly.Icon', 'Blockly.Warning', 'Blockly.browserEvents', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/common.js', ['Blockly.common'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/component_manager.js', ['Blockly.ComponentManager'], ['Blockly.utils'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/connection.js', ['Blockly.Connection'], ['Blockly.ConnectionType', 'Blockly.Events.BlockMove', 'Blockly.Events.utils', 'Blockly.Xml', 'Blockly.constants', 'Blockly.serialization.blocks', 'Blockly.utils.deprecation'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/connection_checker.js', ['Blockly.ConnectionChecker'], ['Blockly.Connection', 'Blockly.ConnectionType', 'Blockly.common', 'Blockly.internalConstants', 'Blockly.registry'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/connection_db.js', ['Blockly.ConnectionDB'], ['Blockly.ConnectionType', 'Blockly.constants'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/connection_type.js', ['Blockly.ConnectionType'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/constants.js', ['Blockly.constants'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/contextmenu.js', ['Blockly.ContextMenu'], ['Blockly.Events.BlockCreate', 'Blockly.Events.utils', 'Blockly.Menu', 'Blockly.MenuItem', 'Blockly.Msg', 'Blockly.WidgetDiv', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.clipboard', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.aria', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/contextmenu_items.js', ['Blockly.ContextMenuItems'], ['Blockly.ContextMenuRegistry', 'Blockly.Events.utils', 'Blockly.Msg', 'Blockly.clipboard', 'Blockly.dialog', 'Blockly.inputTypes', 'Blockly.utils.idGenerator', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/contextmenu_registry.js', ['Blockly.ContextMenuRegistry'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/css.js', ['Blockly.Css'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/delete_area.js', ['Blockly.DeleteArea'], ['Blockly.BlockSvg', 'Blockly.DragTarget', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/dialog.js', ['Blockly.dialog'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/drag_target.js', ['Blockly.DragTarget'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/dropdowndiv.js', ['Blockly.DropDownDiv'], ['Blockly.common', 'Blockly.utils.Rect', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.style'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events.js', ['Blockly.Events'], ['Blockly.Events.Abstract', 'Blockly.Events.BlockBase', 'Blockly.Events.BlockChange', 'Blockly.Events.BlockCreate', 'Blockly.Events.BlockDelete', 'Blockly.Events.BlockDrag', 'Blockly.Events.BlockMove', 'Blockly.Events.BubbleOpen', 'Blockly.Events.Click', 'Blockly.Events.CommentBase', 'Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.Events.FinishedLoading', 'Blockly.Events.MarkerMove', 'Blockly.Events.Selected', 'Blockly.Events.ThemeChange', 'Blockly.Events.ToolboxItemSelect', 'Blockly.Events.TrashcanOpen', 'Blockly.Events.Ui', 'Blockly.Events.UiBase', 'Blockly.Events.VarBase', 'Blockly.Events.VarCreate', 'Blockly.Events.VarDelete', 'Blockly.Events.VarRename', 'Blockly.Events.ViewportChange', 'Blockly.Events.utils', 'Blockly.utils.deprecation'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_abstract.js', ['Blockly.Events.Abstract'], ['Blockly.Events.utils'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_block_base.js', ['Blockly.Events.BlockBase'], ['Blockly.Events.Abstract', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_block_change.js', ['Blockly.Events.BlockChange'], ['Blockly.Events.BlockBase', 'Blockly.Events.utils', 'Blockly.Xml', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_block_create.js', ['Blockly.Events.BlockCreate'], ['Blockly.Events.BlockBase', 'Blockly.Events.utils', 'Blockly.Xml', 'Blockly.registry', 'Blockly.serialization.blocks', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_block_delete.js', ['Blockly.Events.BlockDelete'], ['Blockly.Events.BlockBase', 'Blockly.Events.utils', 'Blockly.Xml', 'Blockly.registry', 'Blockly.serialization.blocks', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_block_drag.js', ['Blockly.Events.BlockDrag'], ['Blockly.Events.UiBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_block_move.js', ['Blockly.Events.BlockMove'], ['Blockly.ConnectionType', 'Blockly.Events.BlockBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_bubble_open.js', ['Blockly.Events.BubbleOpen'], ['Blockly.Events.UiBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_click.js', ['Blockly.Events.Click'], ['Blockly.Events.UiBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_comment_base.js', ['Blockly.Events.CommentBase'], ['Blockly.Events.Abstract', 'Blockly.Events.utils', 'Blockly.Xml', 'Blockly.utils.object', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_comment_change.js', ['Blockly.Events.CommentChange'], ['Blockly.Events.CommentBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_comment_create.js', ['Blockly.Events.CommentCreate'], ['Blockly.Events.CommentBase', 'Blockly.Events.utils', 'Blockly.Xml', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_comment_delete.js', ['Blockly.Events.CommentDelete'], ['Blockly.Events.CommentBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_comment_move.js', ['Blockly.Events.CommentMove'], ['Blockly.Events.CommentBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_marker_move.js', ['Blockly.Events.MarkerMove'], ['Blockly.ASTNode', 'Blockly.Events.UiBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_selected.js', ['Blockly.Events.Selected'], ['Blockly.Events.UiBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_theme_change.js', ['Blockly.Events.ThemeChange'], ['Blockly.Events.UiBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_toolbox_item_select.js', ['Blockly.Events.ToolboxItemSelect'], ['Blockly.Events.UiBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_trashcan_open.js', ['Blockly.Events.TrashcanOpen'], ['Blockly.Events.UiBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_ui.js', ['Blockly.Events.Ui'], ['Blockly.Events.UiBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_ui_base.js', ['Blockly.Events.UiBase'], ['Blockly.Events.Abstract', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_var_base.js', ['Blockly.Events.VarBase'], ['Blockly.Events.Abstract', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_var_create.js', ['Blockly.Events.VarCreate'], ['Blockly.Events.VarBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_var_delete.js', ['Blockly.Events.VarDelete'], ['Blockly.Events.VarBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_var_rename.js', ['Blockly.Events.VarRename'], ['Blockly.Events.VarBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_viewport.js', ['Blockly.Events.ViewportChange'], ['Blockly.Events.UiBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/utils.js', ['Blockly.Events.utils'], ['Blockly.registry', 'Blockly.utils.idGenerator'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/workspace_events.js', ['Blockly.Events.FinishedLoading'], ['Blockly.Events.Abstract', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/extensions.js', ['Blockly.Extensions'], ['Blockly.utils'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field.js', ['Blockly.Field'], ['Blockly.DropDownDiv', 'Blockly.Events.BlockChange', 'Blockly.Events.utils', 'Blockly.Gesture', 'Blockly.MarkerManager', 'Blockly.Tooltip', 'Blockly.WidgetDiv', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.style', 'Blockly.utils.userAgent', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_angle.js', ['Blockly.FieldAngle'], ['Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.FieldTextInput', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils.KeyCodes', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_checkbox.js', ['Blockly.FieldCheckbox'], ['Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_colour.js', ['Blockly.FieldColour'], ['Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils.KeyCodes', 'Blockly.utils.Size', 'Blockly.utils.aria', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.idGenerator', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_dropdown.js', ['Blockly.FieldDropdown'], ['Blockly.DropDownDiv', 'Blockly.Field', 'Blockly.Menu', 'Blockly.MenuItem', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.string', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_image.js', ['Blockly.FieldImage'], ['Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_label.js', ['Blockly.FieldLabel'], ['Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_label_serializable.js', ['Blockly.FieldLabelSerializable'], ['Blockly.FieldLabel', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_multilineinput.js', ['Blockly.FieldMultilineInput'], ['Blockly.Css', 'Blockly.Field', 'Blockly.FieldTextInput', 'Blockly.WidgetDiv', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.KeyCodes', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_number.js', ['Blockly.FieldNumber'], ['Blockly.FieldTextInput', 'Blockly.fieldRegistry', 'Blockly.utils.aria', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_registry.js', ['Blockly.fieldRegistry'], ['Blockly.registry'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_textinput.js', ['Blockly.FieldTextInput'], ['Blockly.DropDownDiv', 'Blockly.Events.BlockChange', 'Blockly.Events.utils', 'Blockly.Field', 'Blockly.Msg', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.dialog', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_variable.js', ['Blockly.FieldVariable'], ['Blockly.Events.BlockChange', 'Blockly.FieldDropdown', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Variables', 'Blockly.Xml', 'Blockly.fieldRegistry', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/flyout_base.js', ['Blockly.Flyout'], ['Blockly.ComponentManager', 'Blockly.DeleteArea', 'Blockly.Events.BlockCreate', 'Blockly.Events.VarCreate', 'Blockly.Events.utils', 'Blockly.FlyoutMetricsManager', 'Blockly.Gesture', 'Blockly.ScrollbarPair', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Variables', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.blockRendering', 'Blockly.browserEvents', 'Blockly.serialization.blocks', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.idGenerator', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/flyout_button.js', ['Blockly.FlyoutButton'], ['Blockly.Css', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.style'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/flyout_horizontal.js', ['Blockly.HorizontalFlyout'], ['Blockly.DropDownDiv', 'Blockly.Flyout', 'Blockly.Scrollbar', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.registry', 'Blockly.utils.Rect', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/flyout_metrics_manager.js', ['Blockly.FlyoutMetricsManager'], ['Blockly.MetricsManager', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/flyout_vertical.js', ['Blockly.VerticalFlyout'], ['Blockly.Block', 'Blockly.DropDownDiv', 'Blockly.Flyout', 'Blockly.Scrollbar', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils.Rect', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/generator.js', ['Blockly.Generator'], ['Blockly.common', 'Blockly.internalConstants', 'Blockly.utils.deprecation'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/gesture.js', ['Blockly.Gesture'], ['Blockly.BlockDragger', 'Blockly.BubbleDragger', 'Blockly.Events.Click', 'Blockly.Events.utils', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Workspace', 'Blockly.WorkspaceDragger', 'Blockly.blockAnimations', 'Blockly.browserEvents', 'Blockly.common', 'Blockly.internalConstants', 'Blockly.registry', 'Blockly.utils.Coordinate'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/grid.js', ['Blockly.Grid'], ['Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/icon.js', ['Blockly.Icon'], ['Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/inject.js', ['Blockly.inject'], ['Blockly.BlockDragSurfaceSvg', 'Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.Grid', 'Blockly.Msg', 'Blockly.Options', 'Blockly.ScrollbarPair', 'Blockly.ShortcutRegistry', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.WidgetDiv', 'Blockly.Workspace', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.WorkspaceSvg', 'Blockly.browserEvents', 'Blockly.bumpObjects', 'Blockly.common', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/input.js', ['Blockly.Input'], ['Blockly.FieldLabel', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.inputTypes'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/input_types.js', ['Blockly.inputTypes'], ['Blockly.ConnectionType'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/insertion_marker_manager.js', ['Blockly.InsertionMarkerManager'], ['Blockly.ComponentManager', 'Blockly.ConnectionType', 'Blockly.Events.utils', 'Blockly.blockAnimations', 'Blockly.common', 'Blockly.constants', 'Blockly.internalConstants'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_ast_node_location.js', ['Blockly.IASTNodeLocation'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_ast_node_location_svg.js', ['Blockly.IASTNodeLocationSvg'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_ast_node_location_with_block.js', ['Blockly.IASTNodeLocationWithBlock'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_autohideable.js', ['Blockly.IAutoHideable'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_block_dragger.js', ['Blockly.IBlockDragger'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_bounded_element.js', ['Blockly.IBoundedElement'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_bubble.js', ['Blockly.IBubble'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_collapsible_toolbox_item.js', ['Blockly.ICollapsibleToolboxItem'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_component.js', ['Blockly.IComponent'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_connection_checker.js', ['Blockly.IConnectionChecker'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_contextmenu.js', ['Blockly.IContextMenu'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_copyable.js', ['Blockly.ICopyable'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_deletable.js', ['Blockly.IDeletable'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_delete_area.js', ['Blockly.IDeleteArea'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_drag_target.js', ['Blockly.IDragTarget'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_draggable.js', ['Blockly.IDraggable'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_flyout.js', ['Blockly.IFlyout'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_keyboard_accessible.js', ['Blockly.IKeyboardAccessible'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_metrics_manager.js', ['Blockly.IMetricsManager'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_movable.js', ['Blockly.IMovable'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_positionable.js', ['Blockly.IPositionable'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_registrable.js', ['Blockly.IRegistrable'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_registrable_field.js', ['Blockly.IRegistrableField'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_selectable.js', ['Blockly.ISelectable'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_selectable_toolbox_item.js', ['Blockly.ISelectableToolboxItem'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_serializer.js', ['Blockly.serialization.ISerializer'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_styleable.js', ['Blockly.IStyleable'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_toolbox.js', ['Blockly.IToolbox'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_toolbox_item.js', ['Blockly.IToolboxItem'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/internal_constants.js', ['Blockly.internalConstants'], ['Blockly.ConnectionType'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/keyboard_nav/ast_node.js', ['Blockly.ASTNode'], ['Blockly.ConnectionType', 'Blockly.utils.Coordinate'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/keyboard_nav/basic_cursor.js', ['Blockly.BasicCursor'], ['Blockly.ASTNode', 'Blockly.Cursor', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/keyboard_nav/cursor.js', ['Blockly.Cursor'], ['Blockly.ASTNode', 'Blockly.Marker', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/keyboard_nav/marker.js', ['Blockly.Marker'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/keyboard_nav/tab_navigate_cursor.js', ['Blockly.TabNavigateCursor'], ['Blockly.ASTNode', 'Blockly.BasicCursor', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/marker_manager.js', ['Blockly.MarkerManager'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/menu.js', ['Blockly.Menu'], ['Blockly.browserEvents', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.style'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/menuitem.js', ['Blockly.MenuItem'], ['Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.idGenerator'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/metrics_manager.js', ['Blockly.MetricsManager'], ['Blockly.registry', 'Blockly.utils.Size', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/msg.js', ['Blockly.Msg'], ['Blockly.utils.global'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/mutator.js', ['Blockly.Mutator'], ['Blockly.Bubble', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Events.utils', 'Blockly.Icon', 'Blockly.Options', 'Blockly.WorkspaceSvg', 'Blockly.internalConstants', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/names.js', ['Blockly.Names'], ['Blockly.Msg', 'Blockly.Variables', 'Blockly.internalConstants'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/options.js', ['Blockly.Options'], ['Blockly.Theme', 'Blockly.Themes.Classic', 'Blockly.registry', 'Blockly.utils.idGenerator', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/positionable_helpers.js', ['Blockly.uiPosition'], ['Blockly.Scrollbar', 'Blockly.utils.Rect', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/procedures.js', ['Blockly.Procedures'], ['Blockly.Events.BlockChange', 'Blockly.Events.utils', 'Blockly.Msg', 'Blockly.Names', 'Blockly.Variables', 'Blockly.Workspace', 'Blockly.Xml', 'Blockly.blocks', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/registry.js', ['Blockly.registry'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/rendered_connection.js', ['Blockly.RenderedConnection'], ['Blockly.Connection', 'Blockly.ConnectionType', 'Blockly.Events.utils', 'Blockly.common', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.svgPaths'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/common/block_rendering.js', ['Blockly.blockRendering'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.Connection', 'Blockly.blockRendering.ConstantProvider', 'Blockly.blockRendering.Debug', 'Blockly.blockRendering.Drawer', 'Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.Field', 'Blockly.blockRendering.Hat', 'Blockly.blockRendering.IPathObject', 'Blockly.blockRendering.Icon', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.InputConnection', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.JaggedEdge', 'Blockly.blockRendering.MarkerSvg', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.OutputConnection', 'Blockly.blockRendering.PathObject', 'Blockly.blockRendering.PreviousConnection', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Renderer', 'Blockly.blockRendering.RoundCorner', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.SpacerRow', 'Blockly.blockRendering.SquareCorner', 'Blockly.blockRendering.StatementInput', 'Blockly.blockRendering.TopRow', 'Blockly.blockRendering.Types', 'Blockly.blockRendering.debug', 'Blockly.registry', 'Blockly.utils.deprecation'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/common/constants.js', ['Blockly.blockRendering.ConstantProvider'], ['Blockly.ConnectionType', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.svgPaths', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/common/debug.js', ['Blockly.blockRendering.debug'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/common/debugger.js', ['Blockly.blockRendering.Debug'], ['Blockly.ConnectionType', 'Blockly.FieldLabel', 'Blockly.blockRendering.Types', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/common/drawer.js', ['Blockly.blockRendering.Drawer'], ['Blockly.blockRendering.Types', 'Blockly.blockRendering.debug', 'Blockly.utils.svgPaths'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/common/i_path_object.js', ['Blockly.blockRendering.IPathObject'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/common/info.js', ['Blockly.blockRendering.RenderInfo'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.Field', 'Blockly.blockRendering.Hat', 'Blockly.blockRendering.Icon', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.JaggedEdge', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.OutputConnection', 'Blockly.blockRendering.PreviousConnection', 'Blockly.blockRendering.RoundCorner', 'Blockly.blockRendering.SpacerRow', 'Blockly.blockRendering.SquareCorner', 'Blockly.blockRendering.StatementInput', 'Blockly.blockRendering.TopRow', 'Blockly.blockRendering.Types', 'Blockly.constants', 'Blockly.inputTypes'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/common/marker_svg.js', ['Blockly.blockRendering.MarkerSvg'], ['Blockly.ASTNode', 'Blockly.ConnectionType', 'Blockly.Events.MarkerMove', 'Blockly.Events.utils', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.svgPaths'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/common/path_object.js', ['Blockly.blockRendering.PathObject'], ['Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/common/renderer.js', ['Blockly.blockRendering.Renderer'], ['Blockly.Connection', 'Blockly.ConnectionType', 'Blockly.InsertionMarkerManager', 'Blockly.blockRendering.ConstantProvider', 'Blockly.blockRendering.Drawer', 'Blockly.blockRendering.MarkerSvg', 'Blockly.blockRendering.PathObject', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.debug', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/geras/constants.js', ['Blockly.geras.ConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/geras/drawer.js', ['Blockly.geras.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.blockRendering.debug', 'Blockly.geras.Highlighter', 'Blockly.utils.object', 'Blockly.utils.svgPaths'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/geras/geras.js', ['Blockly.geras'], ['Blockly.geras.ConstantProvider', 'Blockly.geras.Drawer', 'Blockly.geras.HighlightConstantProvider', 'Blockly.geras.Highlighter', 'Blockly.geras.InlineInput', 'Blockly.geras.PathObject', 'Blockly.geras.RenderInfo', 'Blockly.geras.Renderer', 'Blockly.geras.StatementInput'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/geras/highlight_constants.js', ['Blockly.geras.HighlightConstantProvider'], ['Blockly.utils.svgPaths'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/geras/highlighter.js', ['Blockly.geras.Highlighter'], ['Blockly.blockRendering.Types', 'Blockly.utils.svgPaths'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/geras/info.js', ['Blockly.geras.RenderInfo'], ['Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.geras.InlineInput', 'Blockly.geras.StatementInput', 'Blockly.inputTypes', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/geras/measurables/inline_input.js', ['Blockly.geras.InlineInput'], ['Blockly.blockRendering.InlineInput', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/geras/measurables/statement_input.js', ['Blockly.geras.StatementInput'], ['Blockly.blockRendering.StatementInput', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/geras/path_object.js', ['Blockly.geras.PathObject'], ['Blockly.blockRendering.PathObject', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/geras/renderer.js', ['Blockly.geras.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.geras.ConstantProvider', 'Blockly.geras.Drawer', 'Blockly.geras.HighlightConstantProvider', 'Blockly.geras.PathObject', 'Blockly.geras.RenderInfo', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/base.js', ['Blockly.blockRendering.Measurable'], ['Blockly.blockRendering.Types'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/bottom_row.js', ['Blockly.blockRendering.BottomRow'], ['Blockly.blockRendering.Row', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/connection.js', ['Blockly.blockRendering.Connection'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/external_value_input.js', ['Blockly.blockRendering.ExternalValueInput'], ['Blockly.blockRendering.InputConnection', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/field.js', ['Blockly.blockRendering.Field'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/hat.js', ['Blockly.blockRendering.Hat'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/icon.js', ['Blockly.blockRendering.Icon'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/in_row_spacer.js', ['Blockly.blockRendering.InRowSpacer'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/inline_input.js', ['Blockly.blockRendering.InlineInput'], ['Blockly.blockRendering.InputConnection', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/input_connection.js', ['Blockly.blockRendering.InputConnection'], ['Blockly.blockRendering.Connection', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/input_row.js', ['Blockly.blockRendering.InputRow'], ['Blockly.blockRendering.Row', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/jagged_edge.js', ['Blockly.blockRendering.JaggedEdge'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/next_connection.js', ['Blockly.blockRendering.NextConnection'], ['Blockly.blockRendering.Connection', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/output_connection.js', ['Blockly.blockRendering.OutputConnection'], ['Blockly.blockRendering.Connection', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/previous_connection.js', ['Blockly.blockRendering.PreviousConnection'], ['Blockly.blockRendering.Connection', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/round_corner.js', ['Blockly.blockRendering.RoundCorner'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/row.js', ['Blockly.blockRendering.Row'], ['Blockly.blockRendering.Types'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/spacer_row.js', ['Blockly.blockRendering.SpacerRow'], ['Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/square_corner.js', ['Blockly.blockRendering.SquareCorner'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/statement_input.js', ['Blockly.blockRendering.StatementInput'], ['Blockly.blockRendering.InputConnection', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/top_row.js', ['Blockly.blockRendering.TopRow'], ['Blockly.blockRendering.Row', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/types.js', ['Blockly.blockRendering.Types'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/minimalist/constants.js', ['Blockly.minimalist.ConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/minimalist/drawer.js', ['Blockly.minimalist.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/minimalist/info.js', ['Blockly.minimalist.RenderInfo'], ['Blockly.blockRendering.RenderInfo', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/minimalist/minimalist.js', ['Blockly.minimalist'], ['Blockly.minimalist.ConstantProvider', 'Blockly.minimalist.Drawer', 'Blockly.minimalist.RenderInfo', 'Blockly.minimalist.Renderer'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/minimalist/renderer.js', ['Blockly.minimalist.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.minimalist.ConstantProvider', 'Blockly.minimalist.Drawer', 'Blockly.minimalist.RenderInfo', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/thrasos/info.js', ['Blockly.thrasos.RenderInfo'], ['Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/thrasos/renderer.js', ['Blockly.thrasos.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.thrasos.RenderInfo', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/thrasos/thrasos.js', ['Blockly.thrasos'], ['Blockly.thrasos.RenderInfo', 'Blockly.thrasos.Renderer'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/zelos/constants.js', ['Blockly.zelos.ConstantProvider'], ['Blockly.ConnectionType', 'Blockly.blockRendering.ConstantProvider', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.svgPaths'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/zelos/drawer.js', ['Blockly.zelos.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.blockRendering.debug', 'Blockly.utils.object', 'Blockly.utils.svgPaths'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/zelos/info.js', ['Blockly.zelos.RenderInfo'], ['Blockly.FieldImage', 'Blockly.FieldLabel', 'Blockly.FieldTextInput', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.constants', 'Blockly.inputTypes', 'Blockly.utils.object', 'Blockly.zelos.BottomRow', 'Blockly.zelos.RightConnectionShape', 'Blockly.zelos.StatementInput', 'Blockly.zelos.TopRow'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/zelos/marker_svg.js', ['Blockly.zelos.MarkerSvg'], ['Blockly.blockRendering.MarkerSvg', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/zelos/measurables/bottom_row.js', ['Blockly.zelos.BottomRow'], ['Blockly.blockRendering.BottomRow', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/zelos/measurables/inputs.js', ['Blockly.zelos.StatementInput'], ['Blockly.blockRendering.StatementInput', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/zelos/measurables/row_elements.js', ['Blockly.zelos.RightConnectionShape'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/zelos/measurables/top_row.js', ['Blockly.zelos.TopRow'], ['Blockly.blockRendering.TopRow', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/zelos/path_object.js', ['Blockly.zelos.PathObject'], ['Blockly.blockRendering.PathObject', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/zelos/renderer.js', ['Blockly.zelos.Renderer'], ['Blockly.ConnectionType', 'Blockly.InsertionMarkerManager', 'Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.utils.object', 'Blockly.zelos.ConstantProvider', 'Blockly.zelos.Drawer', 'Blockly.zelos.MarkerSvg', 'Blockly.zelos.PathObject', 'Blockly.zelos.RenderInfo'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/zelos/zelos.js', ['Blockly.zelos'], ['Blockly.zelos.BottomRow', 'Blockly.zelos.ConstantProvider', 'Blockly.zelos.Drawer', 'Blockly.zelos.MarkerSvg', 'Blockly.zelos.PathObject', 'Blockly.zelos.RenderInfo', 'Blockly.zelos.Renderer', 'Blockly.zelos.RightConnectionShape', 'Blockly.zelos.StatementInput', 'Blockly.zelos.TopRow'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/requires.js', ['Blockly.requires'], ['Blockly', 'Blockly.Comment', 'Blockly.ContextMenuItems', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldLabelSerializable', 'Blockly.FieldMultilineInput', 'Blockly.FieldNumber', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.FlyoutButton', 'Blockly.Generator', 'Blockly.HorizontalFlyout', 'Blockly.Mutator', 'Blockly.ShortcutItems', 'Blockly.Themes.Classic', 'Blockly.Toolbox', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.VerticalFlyout', 'Blockly.Warning', 'Blockly.ZoomControls', 'Blockly.geras.Renderer', 'Blockly.serialization.blocks', 'Blockly.serialization.registry', 'Blockly.serialization.variables', 'Blockly.serialization.workspaces', 'Blockly.thrasos.Renderer', 'Blockly.zelos.Renderer']); +goog.addDependency('../../core/scrollbar.js', ['Blockly.Scrollbar'], ['Blockly.Touch', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/scrollbar_pair.js', ['Blockly.ScrollbarPair'], ['Blockly.Events.utils', 'Blockly.Scrollbar', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/serialization/blocks.js', ['Blockly.serialization.blocks'], ['Blockly.Events.utils', 'Blockly.Xml', 'Blockly.inputTypes', 'Blockly.serialization.ISerializer', 'Blockly.serialization.exceptions', 'Blockly.serialization.priorities', 'Blockly.serialization.registry', 'Blockly.utils.Size'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/serialization/exceptions.js', ['Blockly.serialization.exceptions'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/serialization/priorities.js', ['Blockly.serialization.priorities'], [], {'module': 'goog'}); +goog.addDependency('../../core/serialization/registry.js', ['Blockly.serialization.registry'], ['Blockly.registry'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/serialization/variables.js', ['Blockly.serialization.variables'], ['Blockly.serialization.ISerializer', 'Blockly.serialization.priorities', 'Blockly.serialization.registry'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/serialization/workspaces.js', ['Blockly.serialization.workspaces'], ['Blockly.Events.utils', 'Blockly.Workspace', 'Blockly.registry', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/shortcut_items.js', ['Blockly.ShortcutItems'], ['Blockly.Gesture', 'Blockly.ShortcutRegistry', 'Blockly.clipboard', 'Blockly.common', 'Blockly.utils.KeyCodes'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/shortcut_registry.js', ['Blockly.ShortcutRegistry'], ['Blockly.utils.KeyCodes', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/theme.js', ['Blockly.Theme'], ['Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/theme/classic.js', ['Blockly.Themes.Classic'], ['Blockly.Theme'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/theme/themes.js', ['Blockly.Themes'], ['Blockly.Themes.Classic', 'Blockly.Themes.Zelos'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/theme/zelos.js', ['Blockly.Themes.Zelos'], ['Blockly.Theme'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/theme_manager.js', ['Blockly.ThemeManager'], ['Blockly.utils', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/toolbox/category.js', ['Blockly.ToolboxCategory'], ['Blockly.Css', 'Blockly.ToolboxItem', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.aria', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/toolbox/collapsible_category.js', ['Blockly.CollapsibleToolboxCategory'], ['Blockly.ToolboxCategory', 'Blockly.ToolboxSeparator', 'Blockly.registry', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/toolbox/separator.js', ['Blockly.ToolboxSeparator'], ['Blockly.Css', 'Blockly.ToolboxItem', 'Blockly.registry', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/toolbox/toolbox.js', ['Blockly.Toolbox'], ['Blockly.BlockSvg', 'Blockly.CollapsibleToolboxCategory', 'Blockly.ComponentManager', 'Blockly.Css', 'Blockly.DeleteArea', 'Blockly.Events.ToolboxItemSelect', 'Blockly.Events.utils', 'Blockly.Options', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.common', 'Blockly.registry', 'Blockly.utils.KeyCodes', 'Blockly.utils.Rect', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/toolbox/toolbox_item.js', ['Blockly.ToolboxItem'], ['Blockly.utils.idGenerator'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/tooltip.js', ['Blockly.Tooltip'], ['Blockly.browserEvents', 'Blockly.common', 'Blockly.utils.deprecation', 'Blockly.utils.string'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/touch.js', ['Blockly.Touch'], ['Blockly.internalConstants', 'Blockly.utils.global', 'Blockly.utils.string'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/touch_gesture.js', ['Blockly.TouchGesture'], ['Blockly.Gesture', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.utils.Coordinate', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/trashcan.js', ['Blockly.Trashcan'], ['Blockly.ComponentManager', 'Blockly.DeleteArea', 'Blockly.Events.TrashcanOpen', 'Blockly.Events.utils', 'Blockly.Options', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.registry', 'Blockly.uiPosition', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils.js', ['Blockly.utils'], ['Blockly.Msg', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.Metrics', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.colour', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.global', 'Blockly.utils.idGenerator', 'Blockly.utils.math', 'Blockly.utils.object', 'Blockly.utils.string', 'Blockly.utils.style', 'Blockly.utils.svgPaths', 'Blockly.utils.toolbox', 'Blockly.utils.userAgent', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/aria.js', ['Blockly.utils.aria'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/colour.js', ['Blockly.utils.colour'], ['Blockly.internalConstants'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/coordinate.js', ['Blockly.utils.Coordinate'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/deprecation.js', ['Blockly.utils.deprecation'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/dom.js', ['Blockly.utils.dom'], ['Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/global.js', ['Blockly.utils.global'], [], {'module': 'goog'}); +goog.addDependency('../../core/utils/idgenerator.js', ['Blockly.utils.idGenerator'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/keycodes.js', ['Blockly.utils.KeyCodes'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/math.js', ['Blockly.utils.math'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/metrics.js', ['Blockly.utils.Metrics'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/object.js', ['Blockly.utils.object'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/rect.js', ['Blockly.utils.Rect'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/size.js', ['Blockly.utils.Size'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/string.js', ['Blockly.utils.string'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/style.js', ['Blockly.utils.style'], ['Blockly.utils.Coordinate', 'Blockly.utils.Size'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/svg.js', ['Blockly.utils.Svg'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/svg_paths.js', ['Blockly.utils.svgPaths'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/toolbox.js', ['Blockly.utils.toolbox'], ['Blockly.Xml', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/useragent.js', ['Blockly.utils.userAgent'], ['Blockly.utils.global'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/xml.js', ['Blockly.utils.xml'], ['Blockly.utils.global'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/variable_map.js', ['Blockly.VariableMap'], ['Blockly.Events.VarDelete', 'Blockly.Events.VarRename', 'Blockly.Events.utils', 'Blockly.Msg', 'Blockly.Names', 'Blockly.VariableModel', 'Blockly.dialog', 'Blockly.utils', 'Blockly.utils.idGenerator', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/variable_model.js', ['Blockly.VariableModel'], ['Blockly.Events.VarCreate', 'Blockly.Events.utils', 'Blockly.utils.idGenerator'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/variables.js', ['Blockly.Variables'], ['Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Xml', 'Blockly.blocks', 'Blockly.dialog', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/variables_dynamic.js', ['Blockly.VariablesDynamic'], ['Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Variables', 'Blockly.blocks', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/warning.js', ['Blockly.Warning'], ['Blockly.Bubble', 'Blockly.Events.BubbleOpen', 'Blockly.Events.utils', 'Blockly.Icon', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/widgetdiv.js', ['Blockly.WidgetDiv'], ['Blockly.common', 'Blockly.utils.deprecation', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/workspace.js', ['Blockly.Workspace'], ['Blockly.ConnectionChecker', 'Blockly.Events.utils', 'Blockly.Options', 'Blockly.VariableMap', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.idGenerator', 'Blockly.utils.math'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/workspace_audio.js', ['Blockly.WorkspaceAudio'], ['Blockly.internalConstants', 'Blockly.utils.global', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/workspace_comment.js', ['Blockly.WorkspaceComment'], ['Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.Events.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.idGenerator', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/workspace_comment_svg.js', ['Blockly.WorkspaceCommentSvg'], ['Blockly.ContextMenu', 'Blockly.Css', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.Events.Selected', 'Blockly.Events.utils', 'Blockly.Touch', 'Blockly.WorkspaceComment', 'Blockly.browserEvents', 'Blockly.common', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/workspace_drag_surface_svg.js', ['Blockly.WorkspaceDragSurfaceSvg'], ['Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/workspace_dragger.js', ['Blockly.WorkspaceDragger'], ['Blockly.common', 'Blockly.utils.Coordinate'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/workspace_svg.js', ['Blockly.WorkspaceSvg'], ['Blockly.BlockSvg', 'Blockly.ComponentManager', 'Blockly.ConnectionDB', 'Blockly.ContextMenu', 'Blockly.ContextMenuRegistry', 'Blockly.DropDownDiv', 'Blockly.Events.BlockCreate', 'Blockly.Events.ThemeChange', 'Blockly.Events.ViewportChange', 'Blockly.Events.utils', 'Blockly.Gesture', 'Blockly.Grid', 'Blockly.MarkerManager', 'Blockly.MetricsManager', 'Blockly.Msg', 'Blockly.Options', 'Blockly.ThemeManager', 'Blockly.Themes.Classic', 'Blockly.Tooltip', 'Blockly.TouchGesture', 'Blockly.WidgetDiv', 'Blockly.Workspace', 'Blockly.WorkspaceAudio', 'Blockly.Xml', 'Blockly.blockRendering', 'Blockly.browserEvents', 'Blockly.common', 'Blockly.internalConstants', 'Blockly.registry', 'Blockly.serialization.blocks', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/xml.js', ['Blockly.Xml'], ['Blockly.Events.utils', 'Blockly.inputTypes', 'Blockly.utils.Size', 'Blockly.utils.dom', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/zoom_controls.js', ['Blockly.ZoomControls'], ['Blockly.ComponentManager', 'Blockly.Css', 'Blockly.Events.Click', 'Blockly.Events.utils', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.uiPosition', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('base.js', [], []); + diff --git a/tests/deps.mocha.js b/tests/deps.mocha.js new file mode 100644 index 000000000..23ffa5d68 --- /dev/null +++ b/tests/deps.mocha.js @@ -0,0 +1,379 @@ +goog.addDependency('../../blocks/colour.js', ['Blockly.Blocks.colour', 'Blockly.Constants.Colour'], ['Blockly', 'Blockly.FieldColour', 'Blockly.FieldLabel']); +goog.addDependency('../../blocks/lists.js', ['Blockly.Constants.Lists'], ['Blockly', 'Blockly.FieldDropdown', 'Blockly.FieldLabel', 'Blockly.Mutator'], {'lang': 'es5'}); +goog.addDependency('../../blocks/logic.js', ['Blockly.Blocks.logic', 'Blockly.Constants.Logic'], ['Blockly', 'Blockly.FieldDropdown', 'Blockly.FieldLabel', 'Blockly.Mutator']); +goog.addDependency('../../blocks/loops.js', ['Blockly.Blocks.loops', 'Blockly.Constants.Loops'], ['Blockly', 'Blockly.FieldDropdown', 'Blockly.FieldLabel', 'Blockly.FieldNumber', 'Blockly.FieldVariable', 'Blockly.Warning']); +goog.addDependency('../../blocks/math.js', ['Blockly.Blocks.math', 'Blockly.Constants.Math'], ['Blockly', 'Blockly.FieldDropdown', 'Blockly.FieldLabel', 'Blockly.FieldNumber', 'Blockly.FieldVariable'], {'lang': 'es5'}); +goog.addDependency('../../blocks/procedures.js', ['Blockly.Blocks.procedures'], ['Blockly', 'Blockly.Comment', 'Blockly.FieldCheckbox', 'Blockly.FieldLabel', 'Blockly.FieldTextInput', 'Blockly.Mutator', 'Blockly.Warning'], {'lang': 'es6'}); +goog.addDependency('../../blocks/text.js', ['Blockly.Blocks.texts', 'Blockly.Constants.Text'], ['Blockly', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldMultilineInput', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.Mutator'], {'lang': 'es5'}); +goog.addDependency('../../blocks/variables.js', ['Blockly.Blocks.variables', 'Blockly.Constants.Variables'], ['Blockly', 'Blockly.FieldLabel', 'Blockly.FieldVariable']); +goog.addDependency('../../blocks/variables_dynamic.js', ['Blockly.Constants.VariablesDynamic'], ['Blockly', 'Blockly.FieldLabel', 'Blockly.FieldVariable']); +goog.addDependency('../../core/block.js', ['Blockly.Block'], ['Blockly.ASTNode', 'Blockly.Connection', 'Blockly.ConnectionType', 'Blockly.Events.BlockChange', 'Blockly.Events.BlockCreate', 'Blockly.Events.BlockDelete', 'Blockly.Events.BlockMove', 'Blockly.Events.utils', 'Blockly.Extensions', 'Blockly.Input', 'Blockly.Tooltip', 'Blockly.blocks', 'Blockly.common', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.inputTypes', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.idGenerator', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/block_animations.js', ['Blockly.blockAnimations'], ['Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/block_drag_surface.js', ['Blockly.BlockDragSurfaceSvg'], ['Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/block_dragger.js', ['Blockly.BlockDragger'], ['Blockly.Events.BlockDrag', 'Blockly.Events.BlockMove', 'Blockly.Events.utils', 'Blockly.InsertionMarkerManager', 'Blockly.blockAnimations', 'Blockly.bumpObjects', 'Blockly.common', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/block_svg.js', ['Blockly.BlockSvg'], ['Blockly.ASTNode', 'Blockly.Block', 'Blockly.ConnectionType', 'Blockly.ContextMenu', 'Blockly.ContextMenuRegistry', 'Blockly.Events.BlockMove', 'Blockly.Events.Selected', 'Blockly.Events.utils', 'Blockly.FieldLabel', 'Blockly.MarkerManager', 'Blockly.Msg', 'Blockly.RenderedConnection', 'Blockly.TabNavigateCursor', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.blockAnimations', 'Blockly.browserEvents', 'Blockly.common', 'Blockly.constants', 'Blockly.internalConstants', 'Blockly.serialization.blocks', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/blockly.js', ['Blockly'], ['Blockly.ASTNode', 'Blockly.BasicCursor', 'Blockly.Block', 'Blockly.BlockDragSurfaceSvg', 'Blockly.BlockDragger', 'Blockly.BlockSvg', 'Blockly.BlocklyOptions', 'Blockly.Bubble', 'Blockly.BubbleDragger', 'Blockly.CollapsibleToolboxCategory', 'Blockly.Comment', 'Blockly.ComponentManager', 'Blockly.Connection', 'Blockly.ConnectionChecker', 'Blockly.ConnectionDB', 'Blockly.ConnectionType', 'Blockly.ContextMenu', 'Blockly.ContextMenuItems', 'Blockly.ContextMenuRegistry', 'Blockly.Css', 'Blockly.Cursor', 'Blockly.DeleteArea', 'Blockly.DragTarget', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.FinishedLoading', 'Blockly.Events.Ui', 'Blockly.Events.UiBase', 'Blockly.Events.VarCreate', 'Blockly.Extensions', 'Blockly.Field', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldLabel', 'Blockly.FieldLabelSerializable', 'Blockly.FieldMultilineInput', 'Blockly.FieldNumber', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.Flyout', 'Blockly.FlyoutButton', 'Blockly.FlyoutMetricsManager', 'Blockly.Generator', 'Blockly.Gesture', 'Blockly.Grid', 'Blockly.HorizontalFlyout', 'Blockly.IASTNodeLocation', 'Blockly.IASTNodeLocationSvg', 'Blockly.IASTNodeLocationWithBlock', 'Blockly.IAutoHideable', 'Blockly.IBlockDragger', 'Blockly.IBoundedElement', 'Blockly.IBubble', 'Blockly.ICollapsibleToolboxItem', 'Blockly.IComponent', 'Blockly.IConnectionChecker', 'Blockly.IContextMenu', 'Blockly.ICopyable', 'Blockly.IDeletable', 'Blockly.IDeleteArea', 'Blockly.IDragTarget', 'Blockly.IDraggable', 'Blockly.IFlyout', 'Blockly.IKeyboardAccessible', 'Blockly.IMetricsManager', 'Blockly.IMovable', 'Blockly.IPositionable', 'Blockly.IRegistrable', 'Blockly.IRegistrableField', 'Blockly.ISelectable', 'Blockly.ISelectableToolboxItem', 'Blockly.IStyleable', 'Blockly.IToolbox', 'Blockly.IToolboxItem', 'Blockly.Icon', 'Blockly.Input', 'Blockly.InsertionMarkerManager', 'Blockly.Marker', 'Blockly.MarkerManager', 'Blockly.Menu', 'Blockly.MenuItem', 'Blockly.MetricsManager', 'Blockly.Mutator', 'Blockly.Names', 'Blockly.Options', 'Blockly.Procedures', 'Blockly.Procedures', 'Blockly.RenderedConnection', 'Blockly.Scrollbar', 'Blockly.ScrollbarPair', 'Blockly.ShortcutItems', 'Blockly.ShortcutRegistry', 'Blockly.TabNavigateCursor', 'Blockly.Theme', 'Blockly.ThemeManager', 'Blockly.Themes', 'Blockly.Toolbox', 'Blockly.ToolboxCategory', 'Blockly.ToolboxItem', 'Blockly.ToolboxSeparator', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Touch', 'Blockly.TouchGesture', 'Blockly.Trashcan', 'Blockly.VariableMap', 'Blockly.VariableModel', 'Blockly.Variables', 'Blockly.Variables', 'Blockly.VariablesDynamic', 'Blockly.VerticalFlyout', 'Blockly.Warning', 'Blockly.WidgetDiv', 'Blockly.Workspace', 'Blockly.WorkspaceAudio', 'Blockly.WorkspaceComment', 'Blockly.WorkspaceCommentSvg', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.WorkspaceDragger', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.Xml', 'Blockly.ZoomControls', 'Blockly.blockAnimations', 'Blockly.blockRendering', 'Blockly.blocks', 'Blockly.browserEvents', 'Blockly.bumpObjects', 'Blockly.clipboard', 'Blockly.common', 'Blockly.constants', 'Blockly.dialog', 'Blockly.fieldRegistry', 'Blockly.geras', 'Blockly.inject', 'Blockly.inject', 'Blockly.inputTypes', 'Blockly.internalConstants', 'Blockly.minimalist', 'Blockly.registry', 'Blockly.thrasos', 'Blockly.uiPosition', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.colour', 'Blockly.utils.deprecation', 'Blockly.utils.toolbox', 'Blockly.zelos'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/blockly_options.js', ['Blockly.BlocklyOptions'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/blocks.js', ['Blockly.blocks'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/browser_events.js', ['Blockly.browserEvents'], ['Blockly.Touch', 'Blockly.internalConstants', 'Blockly.utils.global', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/bubble.js', ['Blockly.Bubble'], ['Blockly.Scrollbar', 'Blockly.Touch', 'Blockly.Workspace', 'Blockly.browserEvents', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/bubble_dragger.js', ['Blockly.BubbleDragger'], ['Blockly.Bubble', 'Blockly.ComponentManager', 'Blockly.Events.CommentMove', 'Blockly.Events.utils', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/bump_objects.js', ['Blockly.bumpObjects'], ['Blockly.Events.utils', 'Blockly.utils.math'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/clipboard.js', ['Blockly.clipboard'], ['Blockly.Events.utils'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/comment.js', ['Blockly.Comment'], ['Blockly.Bubble', 'Blockly.Css', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Events.utils', 'Blockly.Icon', 'Blockly.Warning', 'Blockly.browserEvents', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/common.js', ['Blockly.common'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/component_manager.js', ['Blockly.ComponentManager'], ['Blockly.utils'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/connection.js', ['Blockly.Connection'], ['Blockly.ConnectionType', 'Blockly.Events.BlockMove', 'Blockly.Events.utils', 'Blockly.Xml', 'Blockly.constants', 'Blockly.serialization.blocks', 'Blockly.utils.deprecation'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/connection_checker.js', ['Blockly.ConnectionChecker'], ['Blockly.Connection', 'Blockly.ConnectionType', 'Blockly.common', 'Blockly.internalConstants', 'Blockly.registry'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/connection_db.js', ['Blockly.ConnectionDB'], ['Blockly.ConnectionType', 'Blockly.constants'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/connection_type.js', ['Blockly.ConnectionType'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/constants.js', ['Blockly.constants'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/contextmenu.js', ['Blockly.ContextMenu'], ['Blockly.Events.BlockCreate', 'Blockly.Events.utils', 'Blockly.Menu', 'Blockly.MenuItem', 'Blockly.Msg', 'Blockly.WidgetDiv', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.clipboard', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.aria', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/contextmenu_items.js', ['Blockly.ContextMenuItems'], ['Blockly.ContextMenuRegistry', 'Blockly.Events.utils', 'Blockly.Msg', 'Blockly.clipboard', 'Blockly.dialog', 'Blockly.inputTypes', 'Blockly.utils.idGenerator', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/contextmenu_registry.js', ['Blockly.ContextMenuRegistry'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/css.js', ['Blockly.Css'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/delete_area.js', ['Blockly.DeleteArea'], ['Blockly.BlockSvg', 'Blockly.DragTarget', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/dialog.js', ['Blockly.dialog'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/drag_target.js', ['Blockly.DragTarget'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/dropdowndiv.js', ['Blockly.DropDownDiv'], ['Blockly.common', 'Blockly.utils.Rect', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.style'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events.js', ['Blockly.Events'], ['Blockly.Events.Abstract', 'Blockly.Events.BlockBase', 'Blockly.Events.BlockChange', 'Blockly.Events.BlockCreate', 'Blockly.Events.BlockDelete', 'Blockly.Events.BlockDrag', 'Blockly.Events.BlockMove', 'Blockly.Events.BubbleOpen', 'Blockly.Events.Click', 'Blockly.Events.CommentBase', 'Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.Events.FinishedLoading', 'Blockly.Events.MarkerMove', 'Blockly.Events.Selected', 'Blockly.Events.ThemeChange', 'Blockly.Events.ToolboxItemSelect', 'Blockly.Events.TrashcanOpen', 'Blockly.Events.Ui', 'Blockly.Events.UiBase', 'Blockly.Events.VarBase', 'Blockly.Events.VarCreate', 'Blockly.Events.VarDelete', 'Blockly.Events.VarRename', 'Blockly.Events.ViewportChange', 'Blockly.Events.utils', 'Blockly.utils.deprecation'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_abstract.js', ['Blockly.Events.Abstract'], ['Blockly.Events.utils'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_block_base.js', ['Blockly.Events.BlockBase'], ['Blockly.Events.Abstract', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_block_change.js', ['Blockly.Events.BlockChange'], ['Blockly.Events.BlockBase', 'Blockly.Events.utils', 'Blockly.Xml', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_block_create.js', ['Blockly.Events.BlockCreate'], ['Blockly.Events.BlockBase', 'Blockly.Events.utils', 'Blockly.Xml', 'Blockly.registry', 'Blockly.serialization.blocks', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_block_delete.js', ['Blockly.Events.BlockDelete'], ['Blockly.Events.BlockBase', 'Blockly.Events.utils', 'Blockly.Xml', 'Blockly.registry', 'Blockly.serialization.blocks', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_block_drag.js', ['Blockly.Events.BlockDrag'], ['Blockly.Events.UiBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_block_move.js', ['Blockly.Events.BlockMove'], ['Blockly.ConnectionType', 'Blockly.Events.BlockBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_bubble_open.js', ['Blockly.Events.BubbleOpen'], ['Blockly.Events.UiBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_click.js', ['Blockly.Events.Click'], ['Blockly.Events.UiBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_comment_base.js', ['Blockly.Events.CommentBase'], ['Blockly.Events.Abstract', 'Blockly.Events.utils', 'Blockly.Xml', 'Blockly.utils.object', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_comment_change.js', ['Blockly.Events.CommentChange'], ['Blockly.Events.CommentBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_comment_create.js', ['Blockly.Events.CommentCreate'], ['Blockly.Events.CommentBase', 'Blockly.Events.utils', 'Blockly.Xml', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_comment_delete.js', ['Blockly.Events.CommentDelete'], ['Blockly.Events.CommentBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_comment_move.js', ['Blockly.Events.CommentMove'], ['Blockly.Events.CommentBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_marker_move.js', ['Blockly.Events.MarkerMove'], ['Blockly.ASTNode', 'Blockly.Events.UiBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_selected.js', ['Blockly.Events.Selected'], ['Blockly.Events.UiBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_theme_change.js', ['Blockly.Events.ThemeChange'], ['Blockly.Events.UiBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_toolbox_item_select.js', ['Blockly.Events.ToolboxItemSelect'], ['Blockly.Events.UiBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_trashcan_open.js', ['Blockly.Events.TrashcanOpen'], ['Blockly.Events.UiBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_ui.js', ['Blockly.Events.Ui'], ['Blockly.Events.UiBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_ui_base.js', ['Blockly.Events.UiBase'], ['Blockly.Events.Abstract', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_var_base.js', ['Blockly.Events.VarBase'], ['Blockly.Events.Abstract', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_var_create.js', ['Blockly.Events.VarCreate'], ['Blockly.Events.VarBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_var_delete.js', ['Blockly.Events.VarDelete'], ['Blockly.Events.VarBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_var_rename.js', ['Blockly.Events.VarRename'], ['Blockly.Events.VarBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/events_viewport.js', ['Blockly.Events.ViewportChange'], ['Blockly.Events.UiBase', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/utils.js', ['Blockly.Events.utils'], ['Blockly.registry', 'Blockly.utils.idGenerator'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/events/workspace_events.js', ['Blockly.Events.FinishedLoading'], ['Blockly.Events.Abstract', 'Blockly.Events.utils', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/extensions.js', ['Blockly.Extensions'], ['Blockly.utils'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field.js', ['Blockly.Field'], ['Blockly.DropDownDiv', 'Blockly.Events.BlockChange', 'Blockly.Events.utils', 'Blockly.Gesture', 'Blockly.MarkerManager', 'Blockly.Tooltip', 'Blockly.WidgetDiv', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.style', 'Blockly.utils.userAgent', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_angle.js', ['Blockly.FieldAngle'], ['Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.FieldTextInput', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils.KeyCodes', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_checkbox.js', ['Blockly.FieldCheckbox'], ['Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_colour.js', ['Blockly.FieldColour'], ['Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils.KeyCodes', 'Blockly.utils.Size', 'Blockly.utils.aria', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.idGenerator', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_dropdown.js', ['Blockly.FieldDropdown'], ['Blockly.DropDownDiv', 'Blockly.Field', 'Blockly.Menu', 'Blockly.MenuItem', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.string', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_image.js', ['Blockly.FieldImage'], ['Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_label.js', ['Blockly.FieldLabel'], ['Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_label_serializable.js', ['Blockly.FieldLabelSerializable'], ['Blockly.FieldLabel', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_multilineinput.js', ['Blockly.FieldMultilineInput'], ['Blockly.Css', 'Blockly.Field', 'Blockly.FieldTextInput', 'Blockly.WidgetDiv', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.KeyCodes', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_number.js', ['Blockly.FieldNumber'], ['Blockly.FieldTextInput', 'Blockly.fieldRegistry', 'Blockly.utils.aria', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_registry.js', ['Blockly.fieldRegistry'], ['Blockly.registry'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_textinput.js', ['Blockly.FieldTextInput'], ['Blockly.DropDownDiv', 'Blockly.Events.BlockChange', 'Blockly.Events.utils', 'Blockly.Field', 'Blockly.Msg', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.dialog', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field_variable.js', ['Blockly.FieldVariable'], ['Blockly.Events.BlockChange', 'Blockly.FieldDropdown', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Variables', 'Blockly.Xml', 'Blockly.fieldRegistry', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/flyout_base.js', ['Blockly.Flyout'], ['Blockly.ComponentManager', 'Blockly.DeleteArea', 'Blockly.Events.BlockCreate', 'Blockly.Events.VarCreate', 'Blockly.Events.utils', 'Blockly.FlyoutMetricsManager', 'Blockly.Gesture', 'Blockly.ScrollbarPair', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Variables', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.blockRendering', 'Blockly.browserEvents', 'Blockly.serialization.blocks', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.idGenerator', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/flyout_button.js', ['Blockly.FlyoutButton'], ['Blockly.Css', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.style'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/flyout_horizontal.js', ['Blockly.HorizontalFlyout'], ['Blockly.DropDownDiv', 'Blockly.Flyout', 'Blockly.Scrollbar', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.registry', 'Blockly.utils.Rect', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/flyout_metrics_manager.js', ['Blockly.FlyoutMetricsManager'], ['Blockly.MetricsManager', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/flyout_vertical.js', ['Blockly.VerticalFlyout'], ['Blockly.Block', 'Blockly.DropDownDiv', 'Blockly.Flyout', 'Blockly.Scrollbar', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils.Rect', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/generator.js', ['Blockly.Generator'], ['Blockly.common', 'Blockly.internalConstants', 'Blockly.utils.deprecation'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/gesture.js', ['Blockly.Gesture'], ['Blockly.BlockDragger', 'Blockly.BubbleDragger', 'Blockly.Events.Click', 'Blockly.Events.utils', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Workspace', 'Blockly.WorkspaceDragger', 'Blockly.blockAnimations', 'Blockly.browserEvents', 'Blockly.common', 'Blockly.internalConstants', 'Blockly.registry', 'Blockly.utils.Coordinate'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/grid.js', ['Blockly.Grid'], ['Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/icon.js', ['Blockly.Icon'], ['Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/inject.js', ['Blockly.inject'], ['Blockly.BlockDragSurfaceSvg', 'Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.Grid', 'Blockly.Msg', 'Blockly.Options', 'Blockly.ScrollbarPair', 'Blockly.ShortcutRegistry', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.WidgetDiv', 'Blockly.Workspace', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.WorkspaceSvg', 'Blockly.browserEvents', 'Blockly.bumpObjects', 'Blockly.common', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/input.js', ['Blockly.Input'], ['Blockly.FieldLabel', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.inputTypes'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/input_types.js', ['Blockly.inputTypes'], ['Blockly.ConnectionType'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/insertion_marker_manager.js', ['Blockly.InsertionMarkerManager'], ['Blockly.ComponentManager', 'Blockly.ConnectionType', 'Blockly.Events.utils', 'Blockly.blockAnimations', 'Blockly.common', 'Blockly.constants', 'Blockly.internalConstants'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_ast_node_location.js', ['Blockly.IASTNodeLocation'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_ast_node_location_svg.js', ['Blockly.IASTNodeLocationSvg'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_ast_node_location_with_block.js', ['Blockly.IASTNodeLocationWithBlock'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_autohideable.js', ['Blockly.IAutoHideable'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_block_dragger.js', ['Blockly.IBlockDragger'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_bounded_element.js', ['Blockly.IBoundedElement'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_bubble.js', ['Blockly.IBubble'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_collapsible_toolbox_item.js', ['Blockly.ICollapsibleToolboxItem'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_component.js', ['Blockly.IComponent'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_connection_checker.js', ['Blockly.IConnectionChecker'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_contextmenu.js', ['Blockly.IContextMenu'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_copyable.js', ['Blockly.ICopyable'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_deletable.js', ['Blockly.IDeletable'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_delete_area.js', ['Blockly.IDeleteArea'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_drag_target.js', ['Blockly.IDragTarget'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_draggable.js', ['Blockly.IDraggable'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_flyout.js', ['Blockly.IFlyout'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_keyboard_accessible.js', ['Blockly.IKeyboardAccessible'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_metrics_manager.js', ['Blockly.IMetricsManager'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_movable.js', ['Blockly.IMovable'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_positionable.js', ['Blockly.IPositionable'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_registrable.js', ['Blockly.IRegistrable'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_registrable_field.js', ['Blockly.IRegistrableField'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_selectable.js', ['Blockly.ISelectable'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_selectable_toolbox_item.js', ['Blockly.ISelectableToolboxItem'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_serializer.js', ['Blockly.serialization.ISerializer'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_styleable.js', ['Blockly.IStyleable'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_toolbox.js', ['Blockly.IToolbox'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_toolbox_item.js', ['Blockly.IToolboxItem'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/internal_constants.js', ['Blockly.internalConstants'], ['Blockly.ConnectionType'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/keyboard_nav/ast_node.js', ['Blockly.ASTNode'], ['Blockly.ConnectionType', 'Blockly.utils.Coordinate'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/keyboard_nav/basic_cursor.js', ['Blockly.BasicCursor'], ['Blockly.ASTNode', 'Blockly.Cursor', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/keyboard_nav/cursor.js', ['Blockly.Cursor'], ['Blockly.ASTNode', 'Blockly.Marker', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/keyboard_nav/marker.js', ['Blockly.Marker'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/keyboard_nav/tab_navigate_cursor.js', ['Blockly.TabNavigateCursor'], ['Blockly.ASTNode', 'Blockly.BasicCursor', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/marker_manager.js', ['Blockly.MarkerManager'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/menu.js', ['Blockly.Menu'], ['Blockly.browserEvents', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.style'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/menuitem.js', ['Blockly.MenuItem'], ['Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.idGenerator'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/metrics_manager.js', ['Blockly.MetricsManager'], ['Blockly.registry', 'Blockly.utils.Size', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/msg.js', ['Blockly.Msg'], ['Blockly.utils.global'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/mutator.js', ['Blockly.Mutator'], ['Blockly.Bubble', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Events.utils', 'Blockly.Icon', 'Blockly.Options', 'Blockly.WorkspaceSvg', 'Blockly.internalConstants', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/names.js', ['Blockly.Names'], ['Blockly.Msg', 'Blockly.Variables', 'Blockly.internalConstants'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/options.js', ['Blockly.Options'], ['Blockly.Theme', 'Blockly.Themes.Classic', 'Blockly.registry', 'Blockly.utils.idGenerator', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/positionable_helpers.js', ['Blockly.uiPosition'], ['Blockly.Scrollbar', 'Blockly.utils.Rect', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/procedures.js', ['Blockly.Procedures'], ['Blockly.Events.BlockChange', 'Blockly.Events.utils', 'Blockly.Msg', 'Blockly.Names', 'Blockly.Variables', 'Blockly.Workspace', 'Blockly.Xml', 'Blockly.blocks', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/registry.js', ['Blockly.registry'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/rendered_connection.js', ['Blockly.RenderedConnection'], ['Blockly.Connection', 'Blockly.ConnectionType', 'Blockly.Events.utils', 'Blockly.common', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.svgPaths'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/common/block_rendering.js', ['Blockly.blockRendering'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.Connection', 'Blockly.blockRendering.ConstantProvider', 'Blockly.blockRendering.Debug', 'Blockly.blockRendering.Drawer', 'Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.Field', 'Blockly.blockRendering.Hat', 'Blockly.blockRendering.IPathObject', 'Blockly.blockRendering.Icon', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.InputConnection', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.JaggedEdge', 'Blockly.blockRendering.MarkerSvg', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.OutputConnection', 'Blockly.blockRendering.PathObject', 'Blockly.blockRendering.PreviousConnection', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Renderer', 'Blockly.blockRendering.RoundCorner', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.SpacerRow', 'Blockly.blockRendering.SquareCorner', 'Blockly.blockRendering.StatementInput', 'Blockly.blockRendering.TopRow', 'Blockly.blockRendering.Types', 'Blockly.blockRendering.debug', 'Blockly.registry', 'Blockly.utils.deprecation'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/common/constants.js', ['Blockly.blockRendering.ConstantProvider'], ['Blockly.ConnectionType', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.svgPaths', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/common/debug.js', ['Blockly.blockRendering.debug'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/common/debugger.js', ['Blockly.blockRendering.Debug'], ['Blockly.ConnectionType', 'Blockly.FieldLabel', 'Blockly.blockRendering.Types', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/common/drawer.js', ['Blockly.blockRendering.Drawer'], ['Blockly.blockRendering.Types', 'Blockly.blockRendering.debug', 'Blockly.utils.svgPaths'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/common/i_path_object.js', ['Blockly.blockRendering.IPathObject'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/common/info.js', ['Blockly.blockRendering.RenderInfo'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.Field', 'Blockly.blockRendering.Hat', 'Blockly.blockRendering.Icon', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.JaggedEdge', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.OutputConnection', 'Blockly.blockRendering.PreviousConnection', 'Blockly.blockRendering.RoundCorner', 'Blockly.blockRendering.SpacerRow', 'Blockly.blockRendering.SquareCorner', 'Blockly.blockRendering.StatementInput', 'Blockly.blockRendering.TopRow', 'Blockly.blockRendering.Types', 'Blockly.constants', 'Blockly.inputTypes'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/common/marker_svg.js', ['Blockly.blockRendering.MarkerSvg'], ['Blockly.ASTNode', 'Blockly.ConnectionType', 'Blockly.Events.MarkerMove', 'Blockly.Events.utils', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.svgPaths'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/common/path_object.js', ['Blockly.blockRendering.PathObject'], ['Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/common/renderer.js', ['Blockly.blockRendering.Renderer'], ['Blockly.Connection', 'Blockly.ConnectionType', 'Blockly.InsertionMarkerManager', 'Blockly.blockRendering.ConstantProvider', 'Blockly.blockRendering.Drawer', 'Blockly.blockRendering.MarkerSvg', 'Blockly.blockRendering.PathObject', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.debug', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/geras/constants.js', ['Blockly.geras.ConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/geras/drawer.js', ['Blockly.geras.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.blockRendering.debug', 'Blockly.geras.Highlighter', 'Blockly.utils.object', 'Blockly.utils.svgPaths'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/geras/geras.js', ['Blockly.geras'], ['Blockly.geras.ConstantProvider', 'Blockly.geras.Drawer', 'Blockly.geras.HighlightConstantProvider', 'Blockly.geras.Highlighter', 'Blockly.geras.InlineInput', 'Blockly.geras.PathObject', 'Blockly.geras.RenderInfo', 'Blockly.geras.Renderer', 'Blockly.geras.StatementInput'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/geras/highlight_constants.js', ['Blockly.geras.HighlightConstantProvider'], ['Blockly.utils.svgPaths'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/geras/highlighter.js', ['Blockly.geras.Highlighter'], ['Blockly.blockRendering.Types', 'Blockly.utils.svgPaths'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/geras/info.js', ['Blockly.geras.RenderInfo'], ['Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.geras.InlineInput', 'Blockly.geras.StatementInput', 'Blockly.inputTypes', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/geras/measurables/inline_input.js', ['Blockly.geras.InlineInput'], ['Blockly.blockRendering.InlineInput', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/geras/measurables/statement_input.js', ['Blockly.geras.StatementInput'], ['Blockly.blockRendering.StatementInput', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/geras/path_object.js', ['Blockly.geras.PathObject'], ['Blockly.blockRendering.PathObject', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/geras/renderer.js', ['Blockly.geras.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.geras.ConstantProvider', 'Blockly.geras.Drawer', 'Blockly.geras.HighlightConstantProvider', 'Blockly.geras.PathObject', 'Blockly.geras.RenderInfo', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/base.js', ['Blockly.blockRendering.Measurable'], ['Blockly.blockRendering.Types'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/bottom_row.js', ['Blockly.blockRendering.BottomRow'], ['Blockly.blockRendering.Row', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/connection.js', ['Blockly.blockRendering.Connection'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/external_value_input.js', ['Blockly.blockRendering.ExternalValueInput'], ['Blockly.blockRendering.InputConnection', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/field.js', ['Blockly.blockRendering.Field'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/hat.js', ['Blockly.blockRendering.Hat'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/icon.js', ['Blockly.blockRendering.Icon'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/in_row_spacer.js', ['Blockly.blockRendering.InRowSpacer'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/inline_input.js', ['Blockly.blockRendering.InlineInput'], ['Blockly.blockRendering.InputConnection', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/input_connection.js', ['Blockly.blockRendering.InputConnection'], ['Blockly.blockRendering.Connection', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/input_row.js', ['Blockly.blockRendering.InputRow'], ['Blockly.blockRendering.Row', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/jagged_edge.js', ['Blockly.blockRendering.JaggedEdge'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/next_connection.js', ['Blockly.blockRendering.NextConnection'], ['Blockly.blockRendering.Connection', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/output_connection.js', ['Blockly.blockRendering.OutputConnection'], ['Blockly.blockRendering.Connection', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/previous_connection.js', ['Blockly.blockRendering.PreviousConnection'], ['Blockly.blockRendering.Connection', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/round_corner.js', ['Blockly.blockRendering.RoundCorner'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/row.js', ['Blockly.blockRendering.Row'], ['Blockly.blockRendering.Types'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/spacer_row.js', ['Blockly.blockRendering.SpacerRow'], ['Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/square_corner.js', ['Blockly.blockRendering.SquareCorner'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/statement_input.js', ['Blockly.blockRendering.StatementInput'], ['Blockly.blockRendering.InputConnection', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/top_row.js', ['Blockly.blockRendering.TopRow'], ['Blockly.blockRendering.Row', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/measurables/types.js', ['Blockly.blockRendering.Types'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/minimalist/constants.js', ['Blockly.minimalist.ConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/minimalist/drawer.js', ['Blockly.minimalist.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/minimalist/info.js', ['Blockly.minimalist.RenderInfo'], ['Blockly.blockRendering.RenderInfo', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/minimalist/minimalist.js', ['Blockly.minimalist'], ['Blockly.minimalist.ConstantProvider', 'Blockly.minimalist.Drawer', 'Blockly.minimalist.RenderInfo', 'Blockly.minimalist.Renderer'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/minimalist/renderer.js', ['Blockly.minimalist.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.minimalist.ConstantProvider', 'Blockly.minimalist.Drawer', 'Blockly.minimalist.RenderInfo', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/thrasos/info.js', ['Blockly.thrasos.RenderInfo'], ['Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/thrasos/renderer.js', ['Blockly.thrasos.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.thrasos.RenderInfo', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/thrasos/thrasos.js', ['Blockly.thrasos'], ['Blockly.thrasos.RenderInfo', 'Blockly.thrasos.Renderer'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/zelos/constants.js', ['Blockly.zelos.ConstantProvider'], ['Blockly.ConnectionType', 'Blockly.blockRendering.ConstantProvider', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.svgPaths'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/zelos/drawer.js', ['Blockly.zelos.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.blockRendering.debug', 'Blockly.utils.object', 'Blockly.utils.svgPaths'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/zelos/info.js', ['Blockly.zelos.RenderInfo'], ['Blockly.FieldImage', 'Blockly.FieldLabel', 'Blockly.FieldTextInput', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.constants', 'Blockly.inputTypes', 'Blockly.utils.object', 'Blockly.zelos.BottomRow', 'Blockly.zelos.RightConnectionShape', 'Blockly.zelos.StatementInput', 'Blockly.zelos.TopRow'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/zelos/marker_svg.js', ['Blockly.zelos.MarkerSvg'], ['Blockly.blockRendering.MarkerSvg', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/zelos/measurables/bottom_row.js', ['Blockly.zelos.BottomRow'], ['Blockly.blockRendering.BottomRow', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/zelos/measurables/inputs.js', ['Blockly.zelos.StatementInput'], ['Blockly.blockRendering.StatementInput', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/zelos/measurables/row_elements.js', ['Blockly.zelos.RightConnectionShape'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/zelos/measurables/top_row.js', ['Blockly.zelos.TopRow'], ['Blockly.blockRendering.TopRow', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/zelos/path_object.js', ['Blockly.zelos.PathObject'], ['Blockly.blockRendering.PathObject', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/zelos/renderer.js', ['Blockly.zelos.Renderer'], ['Blockly.ConnectionType', 'Blockly.InsertionMarkerManager', 'Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.utils.object', 'Blockly.zelos.ConstantProvider', 'Blockly.zelos.Drawer', 'Blockly.zelos.MarkerSvg', 'Blockly.zelos.PathObject', 'Blockly.zelos.RenderInfo'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/zelos/zelos.js', ['Blockly.zelos'], ['Blockly.zelos.BottomRow', 'Blockly.zelos.ConstantProvider', 'Blockly.zelos.Drawer', 'Blockly.zelos.MarkerSvg', 'Blockly.zelos.PathObject', 'Blockly.zelos.RenderInfo', 'Blockly.zelos.Renderer', 'Blockly.zelos.RightConnectionShape', 'Blockly.zelos.StatementInput', 'Blockly.zelos.TopRow'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/requires.js', ['Blockly.requires'], ['Blockly', 'Blockly.Comment', 'Blockly.ContextMenuItems', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldLabelSerializable', 'Blockly.FieldMultilineInput', 'Blockly.FieldNumber', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.FlyoutButton', 'Blockly.Generator', 'Blockly.HorizontalFlyout', 'Blockly.Mutator', 'Blockly.ShortcutItems', 'Blockly.Themes.Classic', 'Blockly.Toolbox', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.VerticalFlyout', 'Blockly.Warning', 'Blockly.ZoomControls', 'Blockly.geras.Renderer', 'Blockly.serialization.blocks', 'Blockly.serialization.registry', 'Blockly.serialization.variables', 'Blockly.serialization.workspaces', 'Blockly.thrasos.Renderer', 'Blockly.zelos.Renderer']); +goog.addDependency('../../core/scrollbar.js', ['Blockly.Scrollbar'], ['Blockly.Touch', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/scrollbar_pair.js', ['Blockly.ScrollbarPair'], ['Blockly.Events.utils', 'Blockly.Scrollbar', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/serialization/blocks.js', ['Blockly.serialization.blocks'], ['Blockly.Events.utils', 'Blockly.Xml', 'Blockly.inputTypes', 'Blockly.serialization.ISerializer', 'Blockly.serialization.exceptions', 'Blockly.serialization.priorities', 'Blockly.serialization.registry', 'Blockly.utils.Size'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/serialization/exceptions.js', ['Blockly.serialization.exceptions'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/serialization/priorities.js', ['Blockly.serialization.priorities'], [], {'module': 'goog'}); +goog.addDependency('../../core/serialization/registry.js', ['Blockly.serialization.registry'], ['Blockly.registry'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/serialization/variables.js', ['Blockly.serialization.variables'], ['Blockly.serialization.ISerializer', 'Blockly.serialization.priorities', 'Blockly.serialization.registry'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/serialization/workspaces.js', ['Blockly.serialization.workspaces'], ['Blockly.Events.utils', 'Blockly.Workspace', 'Blockly.registry', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/shortcut_items.js', ['Blockly.ShortcutItems'], ['Blockly.Gesture', 'Blockly.ShortcutRegistry', 'Blockly.clipboard', 'Blockly.common', 'Blockly.utils.KeyCodes'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/shortcut_registry.js', ['Blockly.ShortcutRegistry'], ['Blockly.utils.KeyCodes', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/theme.js', ['Blockly.Theme'], ['Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/theme/classic.js', ['Blockly.Themes.Classic'], ['Blockly.Theme'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/theme/themes.js', ['Blockly.Themes'], ['Blockly.Themes.Classic', 'Blockly.Themes.Zelos'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/theme/zelos.js', ['Blockly.Themes.Zelos'], ['Blockly.Theme'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/theme_manager.js', ['Blockly.ThemeManager'], ['Blockly.utils', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/toolbox/category.js', ['Blockly.ToolboxCategory'], ['Blockly.Css', 'Blockly.ToolboxItem', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.aria', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/toolbox/collapsible_category.js', ['Blockly.CollapsibleToolboxCategory'], ['Blockly.ToolboxCategory', 'Blockly.ToolboxSeparator', 'Blockly.registry', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/toolbox/separator.js', ['Blockly.ToolboxSeparator'], ['Blockly.Css', 'Blockly.ToolboxItem', 'Blockly.registry', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/toolbox/toolbox.js', ['Blockly.Toolbox'], ['Blockly.BlockSvg', 'Blockly.CollapsibleToolboxCategory', 'Blockly.ComponentManager', 'Blockly.Css', 'Blockly.DeleteArea', 'Blockly.Events.ToolboxItemSelect', 'Blockly.Events.utils', 'Blockly.Options', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.common', 'Blockly.registry', 'Blockly.utils.KeyCodes', 'Blockly.utils.Rect', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/toolbox/toolbox_item.js', ['Blockly.ToolboxItem'], ['Blockly.utils.idGenerator'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/tooltip.js', ['Blockly.Tooltip'], ['Blockly.browserEvents', 'Blockly.common', 'Blockly.utils.deprecation', 'Blockly.utils.string'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/touch.js', ['Blockly.Touch'], ['Blockly.internalConstants', 'Blockly.utils.global', 'Blockly.utils.string'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/touch_gesture.js', ['Blockly.TouchGesture'], ['Blockly.Gesture', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.utils.Coordinate', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/trashcan.js', ['Blockly.Trashcan'], ['Blockly.ComponentManager', 'Blockly.DeleteArea', 'Blockly.Events.TrashcanOpen', 'Blockly.Events.utils', 'Blockly.Options', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.registry', 'Blockly.uiPosition', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils.js', ['Blockly.utils'], ['Blockly.Msg', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.Metrics', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.colour', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.global', 'Blockly.utils.idGenerator', 'Blockly.utils.math', 'Blockly.utils.object', 'Blockly.utils.string', 'Blockly.utils.style', 'Blockly.utils.svgPaths', 'Blockly.utils.toolbox', 'Blockly.utils.userAgent', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/aria.js', ['Blockly.utils.aria'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/colour.js', ['Blockly.utils.colour'], ['Blockly.internalConstants'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/coordinate.js', ['Blockly.utils.Coordinate'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/deprecation.js', ['Blockly.utils.deprecation'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/dom.js', ['Blockly.utils.dom'], ['Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/global.js', ['Blockly.utils.global'], [], {'module': 'goog'}); +goog.addDependency('../../core/utils/idgenerator.js', ['Blockly.utils.idGenerator'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/keycodes.js', ['Blockly.utils.KeyCodes'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/math.js', ['Blockly.utils.math'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/metrics.js', ['Blockly.utils.Metrics'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/object.js', ['Blockly.utils.object'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/rect.js', ['Blockly.utils.Rect'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/size.js', ['Blockly.utils.Size'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/string.js', ['Blockly.utils.string'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/style.js', ['Blockly.utils.style'], ['Blockly.utils.Coordinate', 'Blockly.utils.Size'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/svg.js', ['Blockly.utils.Svg'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/svg_paths.js', ['Blockly.utils.svgPaths'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/toolbox.js', ['Blockly.utils.toolbox'], ['Blockly.Xml', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/useragent.js', ['Blockly.utils.userAgent'], ['Blockly.utils.global'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/xml.js', ['Blockly.utils.xml'], ['Blockly.utils.global'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/variable_map.js', ['Blockly.VariableMap'], ['Blockly.Events.VarDelete', 'Blockly.Events.VarRename', 'Blockly.Events.utils', 'Blockly.Msg', 'Blockly.Names', 'Blockly.VariableModel', 'Blockly.dialog', 'Blockly.utils', 'Blockly.utils.idGenerator', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/variable_model.js', ['Blockly.VariableModel'], ['Blockly.Events.VarCreate', 'Blockly.Events.utils', 'Blockly.utils.idGenerator'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/variables.js', ['Blockly.Variables'], ['Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Xml', 'Blockly.blocks', 'Blockly.dialog', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/variables_dynamic.js', ['Blockly.VariablesDynamic'], ['Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Variables', 'Blockly.blocks', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/warning.js', ['Blockly.Warning'], ['Blockly.Bubble', 'Blockly.Events.BubbleOpen', 'Blockly.Events.utils', 'Blockly.Icon', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/widgetdiv.js', ['Blockly.WidgetDiv'], ['Blockly.common', 'Blockly.utils.deprecation', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/workspace.js', ['Blockly.Workspace'], ['Blockly.ConnectionChecker', 'Blockly.Events.utils', 'Blockly.Options', 'Blockly.VariableMap', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.idGenerator', 'Blockly.utils.math'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/workspace_audio.js', ['Blockly.WorkspaceAudio'], ['Blockly.internalConstants', 'Blockly.utils.global', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/workspace_comment.js', ['Blockly.WorkspaceComment'], ['Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.Events.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.idGenerator', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/workspace_comment_svg.js', ['Blockly.WorkspaceCommentSvg'], ['Blockly.ContextMenu', 'Blockly.Css', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.Events.Selected', 'Blockly.Events.utils', 'Blockly.Touch', 'Blockly.WorkspaceComment', 'Blockly.browserEvents', 'Blockly.common', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/workspace_drag_surface_svg.js', ['Blockly.WorkspaceDragSurfaceSvg'], ['Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/workspace_dragger.js', ['Blockly.WorkspaceDragger'], ['Blockly.common', 'Blockly.utils.Coordinate'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/workspace_svg.js', ['Blockly.WorkspaceSvg'], ['Blockly.BlockSvg', 'Blockly.ComponentManager', 'Blockly.ConnectionDB', 'Blockly.ContextMenu', 'Blockly.ContextMenuRegistry', 'Blockly.DropDownDiv', 'Blockly.Events.BlockCreate', 'Blockly.Events.ThemeChange', 'Blockly.Events.ViewportChange', 'Blockly.Events.utils', 'Blockly.Gesture', 'Blockly.Grid', 'Blockly.MarkerManager', 'Blockly.MetricsManager', 'Blockly.Msg', 'Blockly.Options', 'Blockly.ThemeManager', 'Blockly.Themes.Classic', 'Blockly.Tooltip', 'Blockly.TouchGesture', 'Blockly.WidgetDiv', 'Blockly.Workspace', 'Blockly.WorkspaceAudio', 'Blockly.Xml', 'Blockly.blockRendering', 'Blockly.browserEvents', 'Blockly.common', 'Blockly.internalConstants', 'Blockly.registry', 'Blockly.serialization.blocks', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/xml.js', ['Blockly.Xml'], ['Blockly.Events.utils', 'Blockly.inputTypes', 'Blockly.utils.Size', 'Blockly.utils.dom', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/zoom_controls.js', ['Blockly.ZoomControls'], ['Blockly.ComponentManager', 'Blockly.Css', 'Blockly.Events.Click', 'Blockly.Events.utils', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.uiPosition', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../generators/dart.js', ['Blockly.Dart'], ['Blockly.Generator', 'Blockly.inputTypes', 'Blockly.utils.string']); +goog.addDependency('../../generators/dart/colour.js', ['Blockly.Dart.colour'], ['Blockly.Dart']); +goog.addDependency('../../generators/dart/lists.js', ['Blockly.Dart.lists'], ['Blockly.Dart']); +goog.addDependency('../../generators/dart/logic.js', ['Blockly.Dart.logic'], ['Blockly.Dart']); +goog.addDependency('../../generators/dart/loops.js', ['Blockly.Dart.loops'], ['Blockly.Dart']); +goog.addDependency('../../generators/dart/math.js', ['Blockly.Dart.math'], ['Blockly.Dart']); +goog.addDependency('../../generators/dart/procedures.js', ['Blockly.Dart.procedures'], ['Blockly.Dart']); +goog.addDependency('../../generators/dart/text.js', ['Blockly.Dart.texts'], ['Blockly.Dart']); +goog.addDependency('../../generators/dart/variables.js', ['Blockly.Dart.variables'], ['Blockly.Dart']); +goog.addDependency('../../generators/dart/variables_dynamic.js', ['Blockly.Dart.variablesDynamic'], ['Blockly.Dart', 'Blockly.Dart.variables']); +goog.addDependency('../../generators/javascript.js', ['Blockly.JavaScript'], ['Blockly.Generator', 'Blockly.inputTypes', 'Blockly.utils.global', 'Blockly.utils.object', 'Blockly.utils.string']); +goog.addDependency('../../generators/javascript/colour.js', ['Blockly.JavaScript.colour'], ['Blockly.JavaScript']); +goog.addDependency('../../generators/javascript/lists.js', ['Blockly.JavaScript.lists'], ['Blockly.JavaScript']); +goog.addDependency('../../generators/javascript/logic.js', ['Blockly.JavaScript.logic'], ['Blockly.JavaScript']); +goog.addDependency('../../generators/javascript/loops.js', ['Blockly.JavaScript.loops'], ['Blockly.JavaScript']); +goog.addDependency('../../generators/javascript/math.js', ['Blockly.JavaScript.math'], ['Blockly.JavaScript']); +goog.addDependency('../../generators/javascript/procedures.js', ['Blockly.JavaScript.procedures'], ['Blockly.JavaScript']); +goog.addDependency('../../generators/javascript/text.js', ['Blockly.JavaScript.texts'], ['Blockly.JavaScript']); +goog.addDependency('../../generators/javascript/variables.js', ['Blockly.JavaScript.variables'], ['Blockly.JavaScript']); +goog.addDependency('../../generators/javascript/variables_dynamic.js', ['Blockly.JavaScript.variablesDynamic'], ['Blockly.JavaScript', 'Blockly.JavaScript.variables']); +goog.addDependency('../../generators/lua.js', ['Blockly.Lua'], ['Blockly.Generator', 'Blockly.inputTypes', 'Blockly.utils.object', 'Blockly.utils.string']); +goog.addDependency('../../generators/lua/colour.js', ['Blockly.Lua.colour'], ['Blockly.Lua']); +goog.addDependency('../../generators/lua/lists.js', ['Blockly.Lua.lists'], ['Blockly.Lua']); +goog.addDependency('../../generators/lua/logic.js', ['Blockly.Lua.logic'], ['Blockly.Lua']); +goog.addDependency('../../generators/lua/loops.js', ['Blockly.Lua.loops'], ['Blockly.Lua']); +goog.addDependency('../../generators/lua/math.js', ['Blockly.Lua.math'], ['Blockly.Lua']); +goog.addDependency('../../generators/lua/procedures.js', ['Blockly.Lua.procedures'], ['Blockly.Lua']); +goog.addDependency('../../generators/lua/text.js', ['Blockly.Lua.texts'], ['Blockly.Lua'], {'lang': 'es5'}); +goog.addDependency('../../generators/lua/variables.js', ['Blockly.Lua.variables'], ['Blockly.Lua']); +goog.addDependency('../../generators/lua/variables_dynamic.js', ['Blockly.Lua.variablesDynamic'], ['Blockly.Lua', 'Blockly.Lua.variables']); +goog.addDependency('../../generators/php.js', ['Blockly.PHP'], ['Blockly.Generator', 'Blockly.inputTypes', 'Blockly.utils.object', 'Blockly.utils.string']); +goog.addDependency('../../generators/php/colour.js', ['Blockly.PHP.colour'], ['Blockly.PHP']); +goog.addDependency('../../generators/php/lists.js', ['Blockly.PHP.lists'], ['Blockly.PHP']); +goog.addDependency('../../generators/php/logic.js', ['Blockly.PHP.logic'], ['Blockly.PHP']); +goog.addDependency('../../generators/php/loops.js', ['Blockly.PHP.loops'], ['Blockly.PHP']); +goog.addDependency('../../generators/php/math.js', ['Blockly.PHP.math'], ['Blockly.PHP']); +goog.addDependency('../../generators/php/procedures.js', ['Blockly.PHP.procedures'], ['Blockly.PHP']); +goog.addDependency('../../generators/php/text.js', ['Blockly.PHP.texts'], ['Blockly.PHP']); +goog.addDependency('../../generators/php/variables.js', ['Blockly.PHP.variables'], ['Blockly.PHP']); +goog.addDependency('../../generators/php/variables_dynamic.js', ['Blockly.PHP.variablesDynamic'], ['Blockly.PHP', 'Blockly.PHP.variables']); +goog.addDependency('../../generators/python.js', ['Blockly.Python'], ['Blockly.Generator', 'Blockly.inputTypes', 'Blockly.utils.string']); +goog.addDependency('../../generators/python/colour.js', ['Blockly.Python.colour'], ['Blockly.Python']); +goog.addDependency('../../generators/python/lists.js', ['Blockly.Python.lists'], ['Blockly.Python']); +goog.addDependency('../../generators/python/logic.js', ['Blockly.Python.logic'], ['Blockly.Python']); +goog.addDependency('../../generators/python/loops.js', ['Blockly.Python.loops'], ['Blockly.Python']); +goog.addDependency('../../generators/python/math.js', ['Blockly.Python.math'], ['Blockly.Python']); +goog.addDependency('../../generators/python/procedures.js', ['Blockly.Python.procedures'], ['Blockly.Python']); +goog.addDependency('../../generators/python/text.js', ['Blockly.Python.texts'], ['Blockly.Python']); +goog.addDependency('../../generators/python/variables.js', ['Blockly.Python.variables'], ['Blockly.Python']); +goog.addDependency('../../generators/python/variables_dynamic.js', ['Blockly.Python.variablesDynamic'], ['Blockly.Python', 'Blockly.Python.variables']); +goog.addDependency('../../tests/mocha/.mocharc.js', [], []); +goog.addDependency('../../tests/mocha/astnode_test.js', ['Blockly.test.astNode'], ['Blockly.ASTNode', 'Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/block_change_event_test.js', ['Blockly.test.blockChangeEvent'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/block_create_event_test.js', ['Blockly.test.blockCreateEvent'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/block_json_test.js', ['Blockly.test.blockJson'], [], {'lang': 'es5', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/block_test.js', ['Blockly.test.blocks'], ['Blockly.Events.utils', 'Blockly.blocks', 'Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/comment_test.js', ['Blockly.test.comments'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/connection_checker_test.js', ['Blockly.test.connectionChecker'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/connection_db_test.js', ['Blockly.test.connectionDb'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/connection_test.js', ['Blockly.test.connection'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/contextmenu_items_test.js', ['Blockly.test.contextMenuItem'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/cursor_test.js', ['Blockly.test.cursor'], ['Blockly.ASTNode', 'Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/dropdowndiv_test.js', ['Blockly.test.dropdown'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/event_test.js', ['Blockly.test.event'], ['Blockly.ASTNode', 'Blockly.Events.utils', 'Blockly.WorkspaceComment', 'Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/extensions_test.js', ['Blockly.test.extensions'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/field_angle_test.js', ['Blockly.test.fieldAngle'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/field_checkbox_test.js', ['Blockly.test.fieldCheckbox'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/field_colour_test.js', ['Blockly.test.fieldColour'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/field_dropdown_test.js', ['Blockly.test.fieldDropdown'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/field_image_test.js', ['Blockly.test.fieldImage'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/field_label_serializable_test.js', ['Blockly.test.fieldLabelSerialization'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/field_label_test.js', ['Blockly.test.fieldLabel'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/field_multilineinput_test.js', ['Blockly.test.fieldMultiline'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/field_number_test.js', ['Blockly.test.fieldNumber'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/field_registry_test.js', ['Blockly.test.fieldRegistry'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/field_test.js', ['Blockly.test.fieldTest'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/field_textinput_test.js', ['Blockly.test.fieldTextInput'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/field_variable_test.js', ['Blockly.test.fieldVariable'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/flyout_test.js', ['Blockly.test.flyout'], ['Blockly.test.helpers', 'Blockly.test.toolboxHelpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/generator_test.js', ['Blockly.test.generator'], ['Blockly.Dart', 'Blockly.JavaScript', 'Blockly.Lua', 'Blockly.PHP', 'Blockly.Python', 'Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/gesture_test.js', ['Blockly.test.gesture'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/input_test.js', ['Blockly.test.input'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/insertion_marker_test.js', ['Blockly.test.insertionMarker'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/jso_deserialization_test.js', ['Blockly.test.jsoDeserialization'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/jso_serialization_test.js', ['Blockly.test.jsoSerialization'], ['Blockly.test.helpers'], {'lang': 'es8', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/json_test.js', ['Blockly.test.json'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/keydown_test.js', ['Blockly.test.keydown'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/logic_ternary_test.js', ['Blockly.test.logicTernary'], ['Blockly.Events.utils', 'Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/metrics_test.js', ['Blockly.test.metrics'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/mutator_test.js', ['Blockly.test.mutator'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/names_test.js', ['Blockly.test.names'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/procedures_test.js', ['Blockly.test.procedures'], ['Blockly', 'Blockly.Msg', 'Blockly.test.helpers', 'Blockly.test.procedureHelpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/procedures_test_helpers.js', ['Blockly.test.procedureHelpers'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/registry_test.js', ['Blockly.test.registry'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/run_mocha_tests_in_browser.js', [], [], {'lang': 'es8'}); +goog.addDependency('../../tests/mocha/serializer_test.js', ['Blockly.test.serialization'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/shortcut_registry_test.js', ['Blockly.test.shortcutRegistry'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/test_helpers.js', ['Blockly.test.helpers'], ['Blockly.Events.utils', 'Blockly.blocks', 'Blockly.utils.KeyCodes'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/theme_test.js', ['Blockly.test.theme'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/toolbox_helper.js', ['Blockly.test.toolboxHelpers'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/toolbox_test.js', ['Blockly.test.toolbox'], ['Blockly.test.helpers', 'Blockly.test.toolboxHelpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/tooltip_test.js', ['Blockly.test.tooltip'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/trashcan_test.js', ['Blockly.test.trashcan'], ['Blockly.Events.utils', 'Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/utils_test.js', ['Blockly.test.utils'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/variable_map_test.js', ['Blockly.test.variableMap'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/variable_model_test.js', ['Blockly.test.variableModel'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/variables_test.js', ['Blockly.test.variables'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/widget_div_test.js', ['Blockly.test.widgetDiv'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/workspace_comment_test.js', ['Blockly.test.workspaceComment'], ['Blockly.WorkspaceComment', 'Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/workspace_helpers.js', ['Blockly.test.workspaceHelpers'], ['Blockly.Events.utils', 'Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/workspace_svg_test.js', ['Blockly.test.workspaceSvg'], ['Blockly.test.helpers', 'Blockly.test.workspaceHelpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/workspace_test.js', ['Blockly.test.workspace'], ['Blockly.test.helpers', 'Blockly.test.workspaceHelpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/xml_test.js', ['Blockly.test.xml'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../tests/mocha/zoom_controls_test.js', ['Blockly.test.zoomControls'], ['Blockly.test.helpers'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('base.js', [], []); + diff --git a/tests/generators/run_generators_in_browser.js b/tests/generators/run_generators_in_browser.js index 2ab48ee2e..97dcf9727 100644 --- a/tests/generators/run_generators_in_browser.js +++ b/tests/generators/run_generators_in_browser.js @@ -51,8 +51,11 @@ async function runGeneratorsInBrowser() { args: ['--headless', '--no-sandbox', '--disable-dev-shm-usage', '--allow-file-access-from-files'] }; } else { + // --disable-gpu is needed to prevent Chrome from hanging on Linux with + // NVIDIA drivers older than v295.20. See + // https://github.com/google/blockly/issues/5345 for details. options.capabilities['goog:chromeOptions'] = { - args: ['--allow-file-access-from-files'] + args: ['--allow-file-access-from-files', '--disable-gpu'] }; } diff --git a/tests/mocha/.eslintrc.json b/tests/mocha/.eslintrc.json index 47ffaefb5..0aa6e5b1e 100644 --- a/tests/mocha/.eslintrc.json +++ b/tests/mocha/.eslintrc.json @@ -7,48 +7,7 @@ "globals": { "chai": false, "sinon": false, - "addBlockTypeToCleanup": true, - "addMessageToCleanup": true, - "assertArrayEquals": true, - "assertCallBlockStructure": true, - "assertDefBlockStructure": true, - "assertDeprecationWarningCall": true, - "assertEventEquals": true, - "assertEventFired": true, - "assertEventNotFired": true, - "assertNthCallEventArgEquals": true, - "assertSingleDeprecationWarningCall": true, - "assertVariableValues": true, - "assertNoWarnings": true, - "assertWarnings": true, - "captureWarnings": false, - "createDeprecationWarningStub": true, - "createKeyDownEvent": true, - "createRenderedBlock": true, - "createTestBlock": true, - "defineBasicBlockWithField": true, - "defineRowBlock": true, - "defineStackBlock": true, - "defineStatementBlock": true, - "dispatchPointerEvent": true, - "createFireChangeListenerSpy": true, - "createGenUidStubWithReturns": true, - "getBasicToolbox": true, - "getCategoryJSON": true, - "getChildItem": true, - "getCollapsibleItem": true, - "getDeeplyNestedJSON": true, - "getInjectedToolbox": true, - "getNonCollapsibleItem": true, - "getSeparator": true, - "getSimpleJSON": true, - "getXmlArray": true, - "sharedTestSetup": true, - "sharedTestTeardown": true, - "simulateClick": true, - "testAWorkspace": true, - "testHelpers": true, - "workspaceTeardown": true + "testHelpers": true }, "rules": { "no-unused-vars": ["off"], diff --git a/tests/mocha/astnode_test.js b/tests/mocha/astnode_test.js index c5169936e..ea713b4c0 100644 --- a/tests/mocha/astnode_test.js +++ b/tests/mocha/astnode_test.js @@ -4,6 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.astNode'); + +const {ASTNode} = goog.require('Blockly.ASTNode'); +const {sharedTestSetup, sharedTestTeardown, workspaceTeardown} = goog.require('Blockly.test.helpers'); + + suite('ASTNode', function() { setup(function() { sharedTestSetup.call(this); @@ -98,7 +104,7 @@ suite('ASTNode', function() { var input = this.blocks.statementInput1.inputList[0]; var input2 = this.blocks.statementInput1.inputList[1]; var connection = input.connection; - var node = Blockly.ASTNode.createConnectionNode(connection); + var node = ASTNode.createConnectionNode(connection); var newASTNode = node.findNextForInput_(input); chai.assert.equal(newASTNode.getLocation(), input2.connection); }); @@ -107,7 +113,7 @@ suite('ASTNode', function() { var input = this.blocks.statementInput1.inputList[0]; var input2 = this.blocks.statementInput1.inputList[1]; var connection = input2.connection; - var node = Blockly.ASTNode.createConnectionNode(connection); + var node = ASTNode.createConnectionNode(connection); var newASTNode = node.findPrevForInput_(input2); chai.assert.equal(newASTNode.getLocation(), input.connection); }); @@ -115,7 +121,7 @@ suite('ASTNode', function() { test('findNextForField_', function() { var field = this.blocks.statementInput1.inputList[0].fieldRow[0]; var field2 = this.blocks.statementInput1.inputList[0].fieldRow[1]; - var node = Blockly.ASTNode.createFieldNode(field); + var node = ASTNode.createFieldNode(field); var newASTNode = node.findNextForField_(field); chai.assert.equal(newASTNode.getLocation(), field2); }); @@ -123,39 +129,39 @@ suite('ASTNode', function() { test('findPrevForField_', function() { var field = this.blocks.statementInput1.inputList[0].fieldRow[0]; var field2 = this.blocks.statementInput1.inputList[0].fieldRow[1]; - var node = Blockly.ASTNode.createFieldNode(field2); + var node = ASTNode.createFieldNode(field2); var newASTNode = node.findPrevForField_(field2); chai.assert.equal(newASTNode.getLocation(), field); }); test('navigateBetweenStacks_Forward', function() { - var node = new Blockly.ASTNode( - Blockly.ASTNode.types.NEXT, this.blocks.statementInput1.nextConnection); + var node = new ASTNode( + ASTNode.types.NEXT, this.blocks.statementInput1.nextConnection); var newASTNode = node.navigateBetweenStacks_(true); chai.assert.equal(newASTNode.getLocation(), this.blocks.statementInput4); }); test('navigateBetweenStacks_Backward', function() { - var node = new Blockly.ASTNode( - Blockly.ASTNode.types.BLOCK, this.blocks.statementInput4); + var node = new ASTNode( + ASTNode.types.BLOCK, this.blocks.statementInput4); var newASTNode = node.navigateBetweenStacks_(false); chai.assert.equal(newASTNode.getLocation(), this.blocks.statementInput1); }); test('getOutAstNodeForBlock_', function() { - var node = new Blockly.ASTNode( - Blockly.ASTNode.types.BLOCK, this.blocks.statementInput2); + var node = new ASTNode( + ASTNode.types.BLOCK, this.blocks.statementInput2); var newASTNode = node.getOutAstNodeForBlock_(this.blocks.statementInput2); chai.assert.equal(newASTNode.getLocation(), this.blocks.statementInput1); }); test('getOutAstNodeForBlock_OneBlock', function() { - var node = new Blockly.ASTNode( - Blockly.ASTNode.types.BLOCK, this.blocks.statementInput4); + var node = new ASTNode( + ASTNode.types.BLOCK, this.blocks.statementInput4); var newASTNode = node.getOutAstNodeForBlock_(this.blocks.statementInput4); chai.assert.equal(newASTNode.getLocation(), this.blocks.statementInput4); }); test('findFirstFieldOrInput_', function() { - var node = new Blockly.ASTNode( - Blockly.ASTNode.types.BLOCK, this.blocks.statementInput4); + var node = new ASTNode( + ASTNode.types.BLOCK, this.blocks.statementInput4); var field = this.blocks.statementInput4.inputList[0].fieldRow[0]; var newASTNode = node.findFirstFieldOrInput_(this.blocks.statementInput4); chai.assert.equal(newASTNode.getLocation(), field); @@ -316,95 +322,95 @@ suite('ASTNode', function() { test('fromPreviousToBlock', function() { var prevConnection = this.blocks.statementInput1.previousConnection; - var node = Blockly.ASTNode.createConnectionNode(prevConnection); + var node = ASTNode.createConnectionNode(prevConnection); var nextNode = node.next(); chai.assert.equal(nextNode.getLocation(), this.blocks.statementInput1); }); test('fromBlockToNext', function() { var nextConnection = this.blocks.statementInput1.nextConnection; - var node = Blockly.ASTNode.createBlockNode(this.blocks.statementInput1); + var node = ASTNode.createBlockNode(this.blocks.statementInput1); var nextNode = node.next(); chai.assert.equal(nextNode.getLocation(), nextConnection); }); test('fromBlockToNull', function() { - var node = Blockly.ASTNode.createBlockNode(this.blocks.noNextConnection); + var node = ASTNode.createBlockNode(this.blocks.noNextConnection); var nextNode = node.next(); chai.assert.isNull(nextNode); }); test('fromNextToPrevious', function() { var nextConnection = this.blocks.statementInput1.nextConnection; var prevConnection = this.blocks.statementInput2.previousConnection; - var node = Blockly.ASTNode.createConnectionNode(nextConnection); + var node = ASTNode.createConnectionNode(nextConnection); var nextNode = node.next(); chai.assert.equal(nextNode.getLocation(), prevConnection); }); test('fromNextToNull', function() { var nextConnection = this.blocks.statementInput2.nextConnection; - var node = Blockly.ASTNode.createConnectionNode(nextConnection); + var node = ASTNode.createConnectionNode(nextConnection); var nextNode = node.next(); chai.assert.isNull(nextNode); }); test('fromInputToInput', function() { var input = this.blocks.statementInput1.inputList[0]; var inputConnection = this.blocks.statementInput1.inputList[1].connection; - var node = Blockly.ASTNode.createInputNode(input); + var node = ASTNode.createInputNode(input); var nextNode = node.next(); chai.assert.equal(nextNode.getLocation(), inputConnection); }); test('fromInputToStatementInput', function() { var input = this.blocks.fieldAndInputs2.inputList[1]; var inputConnection = this.blocks.fieldAndInputs2.inputList[2].connection; - var node = Blockly.ASTNode.createInputNode(input); + var node = ASTNode.createInputNode(input); var nextNode = node.next(); chai.assert.equal(nextNode.getLocation(), inputConnection); }); test('fromInputToField', function() { var input = this.blocks.fieldAndInputs2.inputList[0]; var field = this.blocks.fieldAndInputs2.inputList[1].fieldRow[0]; - var node = Blockly.ASTNode.createInputNode(input); + var node = ASTNode.createInputNode(input); var nextNode = node.next(); chai.assert.equal(nextNode.getLocation(), field); }); test('fromInputToNull', function() { var input = this.blocks.fieldAndInputs2.inputList[2]; - var node = Blockly.ASTNode.createInputNode(input); + var node = ASTNode.createInputNode(input); var nextNode = node.next(); chai.assert.isNull(nextNode); }); test('fromOutputToBlock', function() { var output = this.blocks.fieldWithOutput.outputConnection; - var node = Blockly.ASTNode.createConnectionNode(output); + var node = ASTNode.createConnectionNode(output); var nextNode = node.next(); chai.assert.equal(nextNode.getLocation(), this.blocks.fieldWithOutput); }); test('fromFieldToInput', function() { var field = this.blocks.statementInput1.inputList[0].fieldRow[1]; var inputConnection = this.blocks.statementInput1.inputList[0].connection; - var node = Blockly.ASTNode.createFieldNode(field); + var node = ASTNode.createFieldNode(field); var nextNode = node.next(); chai.assert.equal(nextNode.getLocation(), inputConnection); }); test('fromFieldToField', function() { var field = this.blocks.fieldAndInputs.inputList[0].fieldRow[0]; - var node = Blockly.ASTNode.createFieldNode(field); + var node = ASTNode.createFieldNode(field); var field2 = this.blocks.fieldAndInputs.inputList[1].fieldRow[0]; var nextNode = node.next(); chai.assert.equal(nextNode.getLocation(), field2); }); test('fromFieldToNull', function() { var field = this.blocks.twoFields.inputList[0].fieldRow[0]; - var node = Blockly.ASTNode.createFieldNode(field); + var node = ASTNode.createFieldNode(field); var nextNode = node.next(); chai.assert.isNull(nextNode); }); test('fromStackToStack', function() { - var node = Blockly.ASTNode.createStackNode(this.blocks.statementInput1); + var node = ASTNode.createStackNode(this.blocks.statementInput1); var nextNode = node.next(); chai.assert.equal(nextNode.getLocation(), this.blocks.statementInput4); - chai.assert.equal(nextNode.getType(), Blockly.ASTNode.types.STACK); + chai.assert.equal(nextNode.getType(), ASTNode.types.STACK); }); test('fromStackToNull', function() { - var node = Blockly.ASTNode.createStackNode(this.blocks.singleBlock); + var node = ASTNode.createStackNode(this.blocks.singleBlock); var nextNode = node.next(); chai.assert.isNull(nextNode); }); @@ -413,96 +419,96 @@ suite('ASTNode', function() { suite('Previous', function() { test('fromPreviousToNull', function() { var prevConnection = this.blocks.statementInput1.previousConnection; - var node = Blockly.ASTNode.createConnectionNode(prevConnection); + var node = ASTNode.createConnectionNode(prevConnection); var prevNode = node.prev(); chai.assert.isNull(prevNode); }); test('fromPreviousToNext', function() { var prevConnection = this.blocks.statementInput2.previousConnection; - var node = Blockly.ASTNode.createConnectionNode(prevConnection); + var node = ASTNode.createConnectionNode(prevConnection); var prevNode = node.prev(); var nextConnection = this.blocks.statementInput1.nextConnection; chai.assert.equal(prevNode.getLocation(), nextConnection); }); test('fromPreviousToInput', function() { var prevConnection = this.blocks.statementInput3.previousConnection; - var node = Blockly.ASTNode.createConnectionNode(prevConnection); + var node = ASTNode.createConnectionNode(prevConnection); var prevNode = node.prev(); chai.assert.isNull(prevNode); }); test('fromBlockToPrevious', function() { - var node = Blockly.ASTNode.createBlockNode(this.blocks.statementInput1); + var node = ASTNode.createBlockNode(this.blocks.statementInput1); var prevNode = node.prev(); var prevConnection = this.blocks.statementInput1.previousConnection; chai.assert.equal(prevNode.getLocation(), prevConnection); }); test('fromBlockToNull', function() { - var node = Blockly.ASTNode.createBlockNode(this.blocks.noPrevConnection); + var node = ASTNode.createBlockNode(this.blocks.noPrevConnection); var prevNode = node.prev(); chai.assert.isNull(prevNode); }); test('fromBlockToOutput', function() { - var node = Blockly.ASTNode.createBlockNode(this.blocks.fieldWithOutput); + var node = ASTNode.createBlockNode(this.blocks.fieldWithOutput); var prevNode = node.prev(); var outputConnection = this.blocks.fieldWithOutput.outputConnection; chai.assert.equal(prevNode.getLocation(), outputConnection); }); test('fromNextToBlock', function() { var nextConnection = this.blocks.statementInput1.nextConnection; - var node = Blockly.ASTNode.createConnectionNode(nextConnection); + var node = ASTNode.createConnectionNode(nextConnection); var prevNode = node.prev(); chai.assert.equal(prevNode.getLocation(), this.blocks.statementInput1); }); test('fromInputToField', function() { var input = this.blocks.statementInput1.inputList[0]; - var node = Blockly.ASTNode.createInputNode(input); + var node = ASTNode.createInputNode(input); var prevNode = node.prev(); chai.assert.equal(prevNode.getLocation(), input.fieldRow[1]); }); test('fromInputToNull', function() { var input = this.blocks.fieldAndInputs2.inputList[0]; - var node = Blockly.ASTNode.createInputNode(input); + var node = ASTNode.createInputNode(input); var prevNode = node.prev(); chai.assert.isNull(prevNode); }); test('fromInputToInput', function() { var input = this.blocks.fieldAndInputs2.inputList[2]; var inputConnection = this.blocks.fieldAndInputs2.inputList[1].connection; - var node = Blockly.ASTNode.createInputNode(input); + var node = ASTNode.createInputNode(input); var prevNode = node.prev(); chai.assert.equal(prevNode.getLocation(), inputConnection); }); test('fromOutputToNull', function() { var output = this.blocks.fieldWithOutput.outputConnection; - var node = Blockly.ASTNode.createConnectionNode(output); + var node = ASTNode.createConnectionNode(output); var prevNode = node.prev(); chai.assert.isNull(prevNode); }); test('fromFieldToNull', function() { var field = this.blocks.statementInput1.inputList[0].fieldRow[0]; - var node = Blockly.ASTNode.createFieldNode(field); + var node = ASTNode.createFieldNode(field); var prevNode = node.prev(); chai.assert.isNull(prevNode); }); test('fromFieldToInput', function() { var field = this.blocks.fieldAndInputs2.inputList[1].fieldRow[0]; var inputConnection = this.blocks.fieldAndInputs2.inputList[0].connection; - var node = Blockly.ASTNode.createFieldNode(field); + var node = ASTNode.createFieldNode(field); var prevNode = node.prev(); chai.assert.equal(prevNode.getLocation(), inputConnection); }); test('fromFieldToField', function() { var field = this.blocks.fieldAndInputs.inputList[1].fieldRow[0]; var field2 = this.blocks.fieldAndInputs.inputList[0].fieldRow[0]; - var node = Blockly.ASTNode.createFieldNode(field); + var node = ASTNode.createFieldNode(field); var prevNode = node.prev(); chai.assert.equal(prevNode.getLocation(), field2); }); test('fromStackToStack', function() { - var node = Blockly.ASTNode.createStackNode(this.blocks.statementInput4); + var node = ASTNode.createStackNode(this.blocks.statementInput4); var prevNode = node.prev(); chai.assert.equal(prevNode.getLocation(), this.blocks.statementInput1); - chai.assert.equal(prevNode.getType(), Blockly.ASTNode.types.STACK); + chai.assert.equal(prevNode.getType(), ASTNode.types.STACK); }); }); @@ -516,99 +522,99 @@ suite('ASTNode', function() { test('fromInputToOutput', function() { var input = this.blocks.statementInput1.inputList[0]; - var node = Blockly.ASTNode.createInputNode(input); + var node = ASTNode.createInputNode(input); var inNode = node.in(); var outputConnection = this.blocks.fieldWithOutput.outputConnection; chai.assert.equal(inNode.getLocation(), outputConnection); }); test('fromInputToNull', function() { var input = this.blocks.statementInput2.inputList[0]; - var node = Blockly.ASTNode.createInputNode(input); + var node = ASTNode.createInputNode(input); var inNode = node.in(); chai.assert.isNull(inNode); }); test('fromInputToPrevious', function() { var input = this.blocks.statementInput2.inputList[1]; var previousConnection = this.blocks.statementInput3.previousConnection; - var node = Blockly.ASTNode.createInputNode(input); + var node = ASTNode.createInputNode(input); var inNode = node.in(); chai.assert.equal(inNode.getLocation(), previousConnection); }); test('fromBlockToInput', function() { var input = this.blocks.valueInput.inputList[0]; - var node = Blockly.ASTNode.createBlockNode(this.blocks.valueInput); + var node = ASTNode.createBlockNode(this.blocks.valueInput); var inNode = node.in(); chai.assert.equal(inNode.getLocation(), input.connection); }); test('fromBlockToField', function() { - var node = Blockly.ASTNode.createBlockNode(this.blocks.statementInput1); + var node = ASTNode.createBlockNode(this.blocks.statementInput1); var inNode = node.in(); var field = this.blocks.statementInput1.inputList[0].fieldRow[0]; chai.assert.equal(inNode.getLocation(), field); }); test('fromBlockToPrevious', function() { var prevConnection = this.blocks.statementInput4.previousConnection; - var node = Blockly.ASTNode.createStackNode(this.blocks.statementInput4); + var node = ASTNode.createStackNode(this.blocks.statementInput4); var inNode = node.in(); chai.assert.equal(inNode.getLocation(), prevConnection); - chai.assert.equal(inNode.getType(), Blockly.ASTNode.types.PREVIOUS); + chai.assert.equal(inNode.getType(), ASTNode.types.PREVIOUS); }); test('fromBlockToNull_DummyInput', function() { - var node = Blockly.ASTNode.createBlockNode(this.blocks.dummyInput); + var node = ASTNode.createBlockNode(this.blocks.dummyInput); var inNode = node.in(); chai.assert.isNull(inNode); }); test('fromBlockToInput_DummyInputValue', function() { - var node = Blockly.ASTNode.createBlockNode(this.blocks.dummyInputValue); + var node = ASTNode.createBlockNode(this.blocks.dummyInputValue); var inputConnection = this.blocks.dummyInputValue.inputList[1].connection; var inNode = node.in(); chai.assert.equal(inNode.getLocation(), inputConnection); }); test('fromOuputToNull', function() { var output = this.blocks.fieldWithOutput.outputConnection; - var node = Blockly.ASTNode.createConnectionNode(output); + var node = ASTNode.createConnectionNode(output); var inNode = node.in(); chai.assert.isNull(inNode); }); test('fromFieldToNull', function() { var field = this.blocks.statementInput1.inputList[0].fieldRow[0]; - var node = Blockly.ASTNode.createFieldNode(field); + var node = ASTNode.createFieldNode(field); var inNode = node.in(); chai.assert.isNull(inNode); }); test('fromWorkspaceToStack', function() { var coordinate = new Blockly.utils.Coordinate(100, 100); - var node = Blockly.ASTNode.createWorkspaceNode(this.workspace, coordinate); + var node = ASTNode.createWorkspaceNode(this.workspace, coordinate); var inNode = node.in(); chai.assert.equal(inNode.getLocation(), this.workspace.getTopBlocks()[0]); - chai.assert.equal(inNode.getType(), Blockly.ASTNode.types.STACK); + chai.assert.equal(inNode.getType(), ASTNode.types.STACK); }); test('fromWorkspaceToNull', function() { var coordinate = new Blockly.utils.Coordinate(100, 100); - var node = Blockly.ASTNode.createWorkspaceNode( + var node = ASTNode.createWorkspaceNode( this.emptyWorkspace, coordinate); var inNode = node.in(); chai.assert.isNull(inNode); }); test('fromStackToPrevious', function() { - var node = Blockly.ASTNode.createStackNode(this.blocks.statementInput1); + var node = ASTNode.createStackNode(this.blocks.statementInput1); var previous = this.blocks.statementInput1.previousConnection; var inNode = node.in(); chai.assert.equal(inNode.getLocation(), previous); - chai.assert.equal(inNode.getType(), Blockly.ASTNode.types.PREVIOUS); + chai.assert.equal(inNode.getType(), ASTNode.types.PREVIOUS); }); test('fromStackToOutput', function() { - var node = Blockly.ASTNode.createStackNode(this.blocks.fieldWithOutput2); + var node = ASTNode.createStackNode(this.blocks.fieldWithOutput2); var output = this.blocks.fieldWithOutput2.outputConnection; var inNode = node.in(); chai.assert.equal(inNode.getLocation(), output); - chai.assert.equal(inNode.getType(), Blockly.ASTNode.types.OUTPUT); + chai.assert.equal(inNode.getType(), ASTNode.types.OUTPUT); }); test('fromStackToBlock', function() { - var node = Blockly.ASTNode.createStackNode(this.blocks.dummyInput); + var node = ASTNode.createStackNode(this.blocks.dummyInput); var inNode = node.in(); chai.assert.equal(inNode.getLocation(), this.blocks.dummyInput); - chai.assert.equal(inNode.getType(), Blockly.ASTNode.types.BLOCK); + chai.assert.equal(inNode.getType(), ASTNode.types.BLOCK); }); }); @@ -623,39 +629,39 @@ suite('ASTNode', function() { test('fromInputToBlock', function() { var input = this.blocks.statementInput1.inputList[0]; - var node = Blockly.ASTNode.createInputNode(input); + var node = ASTNode.createInputNode(input); var outNode = node.out(); - chai.assert.equal(outNode.getType(), Blockly.ASTNode.types.BLOCK); + chai.assert.equal(outNode.getType(), ASTNode.types.BLOCK); chai.assert.equal(outNode.getLocation(), this.blocks.statementInput1); }); test('fromOutputToInput', function() { var output = this.blocks.fieldWithOutput.outputConnection; - var node = Blockly.ASTNode.createConnectionNode(output); + var node = ASTNode.createConnectionNode(output); var outNode = node.out(); - chai.assert.equal(outNode.getType(), Blockly.ASTNode.types.INPUT); + chai.assert.equal(outNode.getType(), ASTNode.types.INPUT); chai.assert.equal(outNode.getLocation(), this.blocks.statementInput1.inputList[0].connection); }); test('fromOutputToStack', function() { var output = this.blocks.fieldWithOutput2.outputConnection; - var node = Blockly.ASTNode.createConnectionNode(output); + var node = ASTNode.createConnectionNode(output); var outNode = node.out(); - chai.assert.equal(outNode.getType(), Blockly.ASTNode.types.STACK); + chai.assert.equal(outNode.getType(), ASTNode.types.STACK); chai.assert.equal(outNode.getLocation(), this.blocks.fieldWithOutput2); }); test('fromFieldToBlock', function() { var field = this.blocks.statementInput1.inputList[0].fieldRow[0]; - var node = Blockly.ASTNode.createFieldNode(field); + var node = ASTNode.createFieldNode(field); var outNode = node.out(); - chai.assert.equal(outNode.getType(), Blockly.ASTNode.types.BLOCK); + chai.assert.equal(outNode.getType(), ASTNode.types.BLOCK); chai.assert.equal(outNode.getLocation(), this.blocks.statementInput1); }); test('fromStackToWorkspace', function() { var stub = sinon.stub(this.blocks.statementInput4, "getRelativeToSurfaceXY").returns({x: 10, y:10}); - var node = Blockly.ASTNode.createStackNode(this.blocks.statementInput4); + var node = ASTNode.createStackNode(this.blocks.statementInput4); var outNode = node.out(); - chai.assert.equal(outNode.getType(), Blockly.ASTNode.types.WORKSPACE); + chai.assert.equal(outNode.getType(), ASTNode.types.WORKSPACE); chai.assert.equal(outNode.wsCoordinate_.x, 10); chai.assert.equal(outNode.wsCoordinate_.y, -10); stub.restore(); @@ -663,38 +669,38 @@ suite('ASTNode', function() { test('fromPreviousToInput', function() { var previous = this.blocks.statementInput3.previousConnection; var inputConnection = this.blocks.statementInput2.inputList[1].connection; - var node = Blockly.ASTNode.createConnectionNode(previous); + var node = ASTNode.createConnectionNode(previous); var outNode = node.out(); - chai.assert.equal(outNode.getType(), Blockly.ASTNode.types.INPUT); + chai.assert.equal(outNode.getType(), ASTNode.types.INPUT); chai.assert.equal(outNode.getLocation(), inputConnection); }); test('fromPreviousToStack', function() { var previous = this.blocks.statementInput2.previousConnection; - var node = Blockly.ASTNode.createConnectionNode(previous); + var node = ASTNode.createConnectionNode(previous); var outNode = node.out(); - chai.assert.equal(outNode.getType(), Blockly.ASTNode.types.STACK); + chai.assert.equal(outNode.getType(), ASTNode.types.STACK); chai.assert.equal(outNode.getLocation(), this.blocks.statementInput1); }); test('fromNextToInput', function() { var next = this.blocks.statementInput3.nextConnection; var inputConnection = this.blocks.statementInput2.inputList[1].connection; - var node = Blockly.ASTNode.createConnectionNode(next); + var node = ASTNode.createConnectionNode(next); var outNode = node.out(); - chai.assert.equal(outNode.getType(), Blockly.ASTNode.types.INPUT); + chai.assert.equal(outNode.getType(), ASTNode.types.INPUT); chai.assert.equal(outNode.getLocation(), inputConnection); }); test('fromNextToStack', function() { var next = this.blocks.statementInput2.nextConnection; - var node = Blockly.ASTNode.createConnectionNode(next); + var node = ASTNode.createConnectionNode(next); var outNode = node.out(); - chai.assert.equal(outNode.getType(), Blockly.ASTNode.types.STACK); + chai.assert.equal(outNode.getType(), ASTNode.types.STACK); chai.assert.equal(outNode.getLocation(), this.blocks.statementInput1); }); test('fromNextToStack_NoPreviousConnection', function() { var next = this.blocks.secondBlock.nextConnection; - var node = Blockly.ASTNode.createConnectionNode(next); + var node = ASTNode.createConnectionNode(next); var outNode = node.out(); - chai.assert.equal(outNode.getType(), Blockly.ASTNode.types.STACK); + chai.assert.equal(outNode.getType(), ASTNode.types.STACK); chai.assert.equal(outNode.getLocation(), this.blocks.noPrevConnection); }); /** @@ -703,42 +709,42 @@ suite('ASTNode', function() { */ test('fromNextToInput_OutputAndPreviousConnection', function() { var next = this.blocks.outputNextBlock.nextConnection; - var node = Blockly.ASTNode.createConnectionNode(next); + var node = ASTNode.createConnectionNode(next); var outNode = node.out(); - chai.assert.equal(outNode.getType(), Blockly.ASTNode.types.INPUT); + chai.assert.equal(outNode.getType(), ASTNode.types.INPUT); chai.assert.equal(outNode.getLocation(), this.blocks.secondBlock.inputList[0].connection); }); test('fromBlockToStack', function() { - var node = Blockly.ASTNode.createBlockNode(this.blocks.statementInput2); + var node = ASTNode.createBlockNode(this.blocks.statementInput2); var outNode = node.out(); - chai.assert.equal(outNode.getType(), Blockly.ASTNode.types.STACK); + chai.assert.equal(outNode.getType(), ASTNode.types.STACK); chai.assert.equal(outNode.getLocation(), this.blocks.statementInput1); }); test('fromBlockToInput', function() { var input = this.blocks.statementInput2.inputList[1].connection; - var node = Blockly.ASTNode.createBlockNode(this.blocks.statementInput3); + var node = ASTNode.createBlockNode(this.blocks.statementInput3); var outNode = node.out(); - chai.assert.equal(outNode.getType(), Blockly.ASTNode.types.INPUT); + chai.assert.equal(outNode.getType(), ASTNode.types.INPUT); chai.assert.equal(outNode.getLocation(), input); }); test('fromTopBlockToStack', function() { - var node = Blockly.ASTNode.createBlockNode(this.blocks.statementInput1); + var node = ASTNode.createBlockNode(this.blocks.statementInput1); var outNode = node.out(); - chai.assert.equal(outNode.getType(), Blockly.ASTNode.types.STACK); + chai.assert.equal(outNode.getType(), ASTNode.types.STACK); chai.assert.equal(outNode.getLocation(), this.blocks.statementInput1); }); test('fromBlockToStack_OutputConnection', function() { - var node = Blockly.ASTNode.createBlockNode(this.blocks.fieldWithOutput2); + var node = ASTNode.createBlockNode(this.blocks.fieldWithOutput2); var outNode = node.out(); - chai.assert.equal(outNode.getType(), Blockly.ASTNode.types.STACK); + chai.assert.equal(outNode.getType(), ASTNode.types.STACK); chai.assert.equal(outNode.getLocation(), this.blocks.fieldWithOutput2); }); test('fromBlockToInput_OutputConnection', function() { - var node = Blockly.ASTNode.createBlockNode(this.blocks.outputNextBlock); + var node = ASTNode.createBlockNode(this.blocks.outputNextBlock); var inputConnection = this.blocks.secondBlock.inputList[0].connection; var outNode = node.out(); - chai.assert.equal(outNode.getType(), Blockly.ASTNode.types.INPUT); + chai.assert.equal(outNode.getType(), ASTNode.types.INPUT); chai.assert.equal(outNode.getLocation(), inputConnection); }); }); @@ -746,55 +752,55 @@ suite('ASTNode', function() { suite('createFunctions', function() { test('createFieldNode', function() { var field = this.blocks.statementInput1.inputList[0].fieldRow[0]; - var node = Blockly.ASTNode.createFieldNode(field); + var node = ASTNode.createFieldNode(field); chai.assert.equal(node.getLocation(), field); - chai.assert.equal(node.getType(), Blockly.ASTNode.types.FIELD); + chai.assert.equal(node.getType(), ASTNode.types.FIELD); chai.assert.isFalse(node.isConnection()); }); test('createConnectionNode', function() { var prevConnection = this.blocks.statementInput4.previousConnection; - var node = Blockly.ASTNode.createConnectionNode(prevConnection); + var node = ASTNode.createConnectionNode(prevConnection); chai.assert.equal(node.getLocation(), prevConnection); - chai.assert.equal(node.getType(), Blockly.ASTNode.types.PREVIOUS); + chai.assert.equal(node.getType(), ASTNode.types.PREVIOUS); chai.assert.isTrue(node.isConnection()); }); test('createInputNode', function() { var input = this.blocks.statementInput1.inputList[0]; - var node = Blockly.ASTNode.createInputNode(input); + var node = ASTNode.createInputNode(input); chai.assert.equal(node.getLocation(), input.connection); - chai.assert.equal(node.getType(), Blockly.ASTNode.types.INPUT); + chai.assert.equal(node.getType(), ASTNode.types.INPUT); chai.assert.isTrue(node.isConnection()); }); test('createWorkspaceNode', function() { var coordinate = new Blockly.utils.Coordinate(100, 100); - var node = Blockly.ASTNode + var node = ASTNode .createWorkspaceNode(this.workspace, coordinate); chai.assert.equal(node.getLocation(), this.workspace); - chai.assert.equal(node.getType(), Blockly.ASTNode.types.WORKSPACE); + chai.assert.equal(node.getType(), ASTNode.types.WORKSPACE); chai.assert.equal(node.getWsCoordinate(), coordinate); chai.assert.isFalse(node.isConnection()); }); test('createStatementConnectionNode', function() { var nextConnection = this.blocks.statementInput1.inputList[1].connection; var inputConnection = this.blocks.statementInput1.inputList[1].connection; - var node = Blockly.ASTNode.createConnectionNode(nextConnection); + var node = ASTNode.createConnectionNode(nextConnection); chai.assert.equal(node.getLocation(), inputConnection); - chai.assert.equal(node.getType(), Blockly.ASTNode.types.INPUT); + chai.assert.equal(node.getType(), ASTNode.types.INPUT); chai.assert.isTrue(node.isConnection()); }); test('createTopNode-previous', function() { var block = this.blocks.statementInput1; - var topNode = Blockly.ASTNode.createTopNode(block); + var topNode = ASTNode.createTopNode(block); chai.assert.equal(topNode.getLocation(), block.previousConnection); }); test('createTopNode-block', function() { var block = this.blocks.noPrevConnection; - var topNode = Blockly.ASTNode.createTopNode(block); + var topNode = ASTNode.createTopNode(block); chai.assert.equal(topNode.getLocation(), block); }); test('createTopNode-output', function() { var block = this.blocks.outputNextBlock; - var topNode = Blockly.ASTNode.createTopNode(block); + var topNode = ASTNode.createTopNode(block); chai.assert.equal(topNode.getLocation(), block.outputConnection); }); }); diff --git a/tests/mocha/block_change_event_test.js b/tests/mocha/block_change_event_test.js new file mode 100644 index 000000000..e4e3f49cf --- /dev/null +++ b/tests/mocha/block_change_event_test.js @@ -0,0 +1,73 @@ +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +goog.module('Blockly.test.blockChangeEvent'); + +const {defineMutatorBlocks, sharedTestSetup, sharedTestTeardown} = goog.require('Blockly.test.helpers'); + + +suite('Block Change Event', function() { + setup(function() { + sharedTestSetup.call(this); + this.workspace = new Blockly.Workspace(); + }); + + teardown(function() { + sharedTestTeardown.call(this); + }); + + suite('Undo and Redo', function() { + suite('Mutation', function() { + setup(function() { + defineMutatorBlocks(); + }); + + teardown(function() { + Blockly.Extensions.unregister('xml_mutator'); + Blockly.Extensions.unregister('jso_mutator'); + }); + + suite('XML', function() { + test('Undo', function() { + const block = this.workspace.newBlock('xml_block', 'block_id'); + block.domToMutation( + Blockly.Xml.textToDom('')); + const blockChange = new Blockly.Events.BlockChange( + block, 'mutation', null, '', ''); + blockChange.run(false); + chai.assert.isFalse(block.hasInput); + }); + + test('Redo', function() { + const block = this.workspace.newBlock('xml_block', 'block_id'); + const blockChange = new Blockly.Events.BlockChange( + block, 'mutation', null, '', ''); + blockChange.run(true); + chai.assert.isTrue(block.hasInput); + }); + }); + + suite('JSO', function() { + test('Undo', function() { + const block = this.workspace.newBlock('jso_block', 'block_id'); + block.loadExtraState({hasInput: true}); + const blockChange = new Blockly.Events.BlockChange( + block, 'mutation', null, '', '{"hasInput":true}'); + blockChange.run(false); + chai.assert.isFalse(block.hasInput); + }); + + test('Redo', function() { + const block = this.workspace.newBlock('jso_block', 'block_id'); + const blockChange = new Blockly.Events.BlockChange( + block, 'mutation', null, '', '{"hasInput":true}'); + blockChange.run(true); + chai.assert.isTrue(block.hasInput); + }); + }); + }); + }); +}); diff --git a/tests/mocha/block_create_event_test.js b/tests/mocha/block_create_event_test.js new file mode 100644 index 000000000..b1a07e7dd --- /dev/null +++ b/tests/mocha/block_create_event_test.js @@ -0,0 +1,58 @@ +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +goog.module('Blockly.test.blockCreateEvent'); + +const {assertEventFired, sharedTestSetup, sharedTestTeardown} = goog.require('Blockly.test.helpers'); + + +suite('Block Create Event', function() { + setup(function() { + sharedTestSetup.call(this); + this.workspace = new Blockly.Workspace(); + }); + + teardown(function() { + sharedTestTeardown.call(this); + }); + + test('Create shadow on disconnect', function() { + Blockly.Events.disable(); + const block = Blockly.serialization.blocks.append( + { + "type": "text_print", + "inputs": { + "TEXT": { + "shadow": { + "type": "text", + "id": "shadowId", + "fields": { + "TEXT": "abc" + } + }, + "block": { + "type": "text", + "fields": { + "TEXT": "" + } + } + } + } + }, + this.workspace); + Blockly.Events.enable(); + block.getInput('TEXT').connection.disconnect(); + assertEventFired( + this.eventsFireStub, + Blockly.Events.BlockCreate, + {'recordUndo': false}, + this.workspace.id, + 'shadowId'); + const calls = this.eventsFireStub.getCalls(); + const event = calls[calls.length - 1].args[0]; + chai.assert.equal(event.xml.tagName, 'shadow'); + }); +}); diff --git a/tests/mocha/block_json_test.js b/tests/mocha/block_json_test.js index 5ed3a04b8..d067784d8 100644 --- a/tests/mocha/block_json_test.js +++ b/tests/mocha/block_json_test.js @@ -4,6 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.blockJson'); + + suite('Block JSON initialization', function() { suite('validateTokens_', function() { setup(function() { diff --git a/tests/mocha/block_test.js b/tests/mocha/block_test.js index 7c841a134..04c205e9d 100644 --- a/tests/mocha/block_test.js +++ b/tests/mocha/block_test.js @@ -4,6 +4,13 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.blocks'); + +const eventUtils = goog.require('Blockly.Events.utils'); +const {Blocks} = goog.require('Blockly.blocks'); +const {createDeprecationWarningStub, createRenderedBlock, sharedTestSetup, sharedTestTeardown, workspaceTeardown} = goog.require('Blockly.test.helpers'); + + suite('Blocks', function() { setup(function() { sharedTestSetup.call(this, {fireEventsNow: false}); @@ -1076,7 +1083,7 @@ suite('Blocks', function() { function assertCommentEvent(eventSpy, oldValue, newValue) { var calls = eventSpy.getCalls(); var event = calls[calls.length - 1].args[0]; - chai.assert.equal(event.type, Blockly.Events.BLOCK_CHANGE); + chai.assert.equal(event.type, eventUtils.BLOCK_CHANGE); chai.assert.equal(event.element, 'comment'); chai.assert.equal(event.oldValue, oldValue); chai.assert.equal(event.newValue, newValue); @@ -1084,10 +1091,10 @@ suite('Blocks', function() { function assertNoCommentEvent(eventSpy) { var calls = eventSpy.getCalls(); var event = calls[calls.length - 1].args[0]; - chai.assert.notEqual(event.type, Blockly.Events.BLOCK_CHANGE); + chai.assert.notEqual(event.type, eventUtils.BLOCK_CHANGE); } setup(function() { - this.eventsFireSpy = sinon.spy(Blockly.Events, 'fire'); + this.eventsFireSpy = sinon.spy(eventUtils, 'fire'); }); teardown(function() { this.eventsFireSpy.restore(); @@ -1171,10 +1178,7 @@ suite('Blocks', function() { // Restored up by call to sinon.restore() in sharedTestTeardown() sinon.stub(this.block, 'isEditable').returns(false); var icon = this.block.getCommentIcon(); - // TODO(#4186): Remove stubbing of deprecation warning after fixing. - var deprecationWarnStub = createDeprecationWarningStub(); icon.setVisible(true); - deprecationWarnStub.restore(); this.block.setCommentText('test2'); chai.assert.equal(this.block.getCommentText(), 'test2'); @@ -1361,7 +1365,7 @@ suite('Blocks', function() { } setup(function() { - Blockly.Events.disable(); + eventUtils.disable(); // We need a visible workspace. this.workspace = Blockly.inject('blocklyDiv', {}); Blockly.defineBlocksWithJsonArray([ @@ -1379,7 +1383,7 @@ suite('Blocks', function() { ]); }); teardown(function() { - Blockly.Events.enable(); + eventUtils.enable(); workspaceTeardown.call(this, this.workspace); }); suite('Connecting and Disconnecting', function() { @@ -1825,7 +1829,7 @@ suite('Blocks', function() { teardown(function() { workspaceTeardown.call(this, this.workspace); // Clear all registered themes. - Blockly.registry.typeMap_['theme'] = {}; + Blockly.registry.TEST_ONLY.typeMap['theme'] = {}; }); test('Set colour hue', function() { this.block.setColour('20'); @@ -1983,9 +1987,9 @@ suite('Blocks', function() { // so we assert init was called to be safe. var initCalled = false; var recordUndoDuringInit; - Blockly.Blocks['init_test_block'].init = function() { + Blocks['init_test_block'].init = function() { initCalled = true; - recordUndoDuringInit = Blockly.Events.recordUndo; + recordUndoDuringInit = eventUtils.getRecordUndo(); throw new Error(); }; chai.assert.throws(function() { @@ -1993,7 +1997,7 @@ suite('Blocks', function() { }.bind(this)); chai.assert.isFalse(recordUndoDuringInit, 'recordUndo should be false during block init function'); - chai.assert.isTrue(Blockly.Events.recordUndo, + chai.assert.isTrue(eventUtils.getRecordUndo(), 'recordUndo should be reset to true after init'); chai.assert.isTrue(initCalled, 'expected init function to be called'); }); diff --git a/tests/mocha/comment_test.js b/tests/mocha/comment_test.js index 5cedf6709..32f7c6b89 100644 --- a/tests/mocha/comment_test.js +++ b/tests/mocha/comment_test.js @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.comments'); + +const {assertEventFired, sharedTestSetup, sharedTestTeardown} = goog.require('Blockly.test.helpers'); + + suite('Comments', function() { setup(function() { sharedTestSetup.call(this); @@ -55,10 +60,7 @@ suite('Comments', function() { test('Not Editable', function() { sinon.stub(this.block, 'isEditable').returns(false); - // TODO(#4186): Remove stubbing of deprecation warning after fixing. - var deprecationWarnStub = createDeprecationWarningStub(); this.comment.setVisible(true); - deprecationWarnStub.restore(); chai.assert.isTrue(this.comment.isVisible()); assertNotEditable(this.comment); @@ -71,10 +73,7 @@ suite('Comments', function() { this.comment.setVisible(true); sinon.stub(this.block, 'isEditable').returns(false); - // TODO(#4186): Remove stubbing of deprecation warning after fixing. - var deprecationWarnStub = createDeprecationWarningStub(); this.comment.updateEditable(); - deprecationWarnStub.restore(); chai.assert.isTrue(this.comment.isVisible()); assertNotEditable(this.comment); @@ -86,10 +85,7 @@ suite('Comments', function() { test('Not Editable -> Editable', function() { var editableStub = sinon.stub(this.block, 'isEditable').returns(false); - // TODO(#4186): Remove stubbing of deprecation warning after fixing. - var deprecationWarnStub = createDeprecationWarningStub(); this.comment.setVisible(true); - deprecationWarnStub.restore(); editableStub.returns(true); diff --git a/tests/mocha/connection_checker_test.js b/tests/mocha/connection_checker_test.js index cb6b126db..ab2281198 100644 --- a/tests/mocha/connection_checker_test.js +++ b/tests/mocha/connection_checker_test.js @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.connectionChecker'); + +const {sharedTestSetup, sharedTestTeardown} = goog.require('Blockly.test.helpers'); + + suite('Connection checker', function() { setup(function() { sharedTestSetup.call(this); diff --git a/tests/mocha/connection_db_test.js b/tests/mocha/connection_db_test.js index d05c7ba98..91df4e819 100644 --- a/tests/mocha/connection_db_test.js +++ b/tests/mocha/connection_db_test.js @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.connectionDb'); + +const {sharedTestSetup, sharedTestTeardown} = goog.require('Blockly.test.helpers'); + + suite('Connection Database', function() { setup(function() { sharedTestSetup.call(this); diff --git a/tests/mocha/connection_test.js b/tests/mocha/connection_test.js index 67f2c75e2..f10338540 100644 --- a/tests/mocha/connection_test.js +++ b/tests/mocha/connection_test.js @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.connection'); + +const {assertSingleDeprecationWarningCall, createDeprecationWarningStub, createGenUidStubWithReturns, defineRowBlock, defineStatementBlock, defineStackBlock, sharedTestSetup, sharedTestTeardown, workspaceTeardown} = goog.require('Blockly.test.helpers'); + + suite('Connection', function() { setup(function() { sharedTestSetup.call(this); @@ -25,8 +30,8 @@ suite('Connection', function() { test('Deprecated - canConnectWithReason passes', function() { var deprecateWarnSpy = createDeprecationWarningStub(); - var conn1 = this.createConnection(Blockly.PREVIOUS_STATEMENT); - var conn2 = this.createConnection(Blockly.NEXT_STATEMENT); + var conn1 = this.createConnection(Blockly.PREVIOUS_NAME); + var conn2 = this.createConnection(Blockly.NEXT_NAME); chai.assert.equal(conn1.canConnectWithReason(conn2), Blockly.Connection.CAN_CONNECT); assertSingleDeprecationWarningCall(deprecateWarnSpy, @@ -35,7 +40,7 @@ suite('Connection', function() { test('Deprecated - canConnectWithReason fails', function() { var deprecateWarnSpy = createDeprecationWarningStub(); - var conn1 = this.createConnection(Blockly.PREVIOUS_STATEMENT); + var conn1 = this.createConnection(Blockly.PREVIOUS_NAME); var conn2 = this.createConnection(Blockly.OUTPUT_VALUE); chai.assert.equal(conn1.canConnectWithReason(conn2), Blockly.Connection.REASON_WRONG_TYPE); @@ -45,8 +50,8 @@ suite('Connection', function() { test('Deprecated - checkConnection passes', function() { var deprecateWarnSpy = createDeprecationWarningStub(); - var conn1 = this.createConnection(Blockly.PREVIOUS_STATEMENT); - var conn2 = this.createConnection(Blockly.NEXT_STATEMENT); + var conn1 = this.createConnection(Blockly.PREVIOUS_NAME); + var conn2 = this.createConnection(Blockly.NEXT_NAME); chai.assert.doesNotThrow(function() { conn1.checkConnection(conn2); }); @@ -56,7 +61,7 @@ suite('Connection', function() { test('Deprecated - checkConnection fails', function() { var deprecateWarnSpy = createDeprecationWarningStub(); - var conn1 = this.createConnection(Blockly.PREVIOUS_STATEMENT); + var conn1 = this.createConnection(Blockly.PREVIOUS_NAME); var conn2 = this.createConnection(Blockly.OUTPUT_VALUE); chai.assert.throws(function() { conn1.checkConnection(conn2); @@ -65,7 +70,7 @@ suite('Connection', function() { 'Connection.prototype.checkConnection'); }); - suite('Set Shadow Dom', function() { + suite('Set Shadow', function() { function assertBlockMatches(block, isShadow, opt_id) { chai.assert.equal(block.isShadow(), isShadow, @@ -100,6 +105,14 @@ suite('Connection', function() { chai.assert.notExists(block, `expected block ${block && block.id} to not be attached to next connection`); } + + function assertSerialization(block, jso, xmlText) { + const actualJso = Blockly.serialization.blocks + .save(block, {addNextBlocks: true}); + const actualXml = Blockly.Xml.domToText(Blockly.Xml.blockToDom(block)); + chai.assert.deepEqual(actualJso, jso); + chai.assert.equal(actualXml, xmlText); + } var testSuites = [ { @@ -122,660 +135,2482 @@ suite('Connection', function() { setup(function() { this.workspace = testSuite.createWorkspace(); - Blockly.defineBlocksWithJsonArray([ - { - "type": "stack_block", - "message0": "", - "previousStatement": null, - "nextStatement": null - }, - { - "type": "row_block", - "message0": "%1", - "args0": [ - { - "type": "input_value", - "name": "INPUT" - } - ], - "output": null - }, - { - "type": "statement_block", - "message0": "%1", - "args0": [ - { - "type": "input_statement", - "name": "STATEMENT" - } - ], - "previousStatement": null, - "nextStatement": null - }]); + defineRowBlock(); + defineStatementBlock(); + defineStackBlock(); + + createGenUidStubWithReturns( + new Array(30).fill().map((_, i) => 'id' + i)); }); teardown(function() { workspaceTeardown.call(this, this.workspace); }); - suite('Add - No Block Connected', function() { - // These are defined separately in each suite. - function createRowBlock(workspace) { - var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( - '' - ), workspace); - return block; - } - - function createStatementBlock(workspace) { - var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( - '' - ), workspace); - return block; - } - - function createStackBlock(workspace) { - var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( - '' - ), workspace); - return block; - } - - test('Value', function() { - var parent = createRowBlock(this.workspace); - var xml = Blockly.Xml.textToDom( - '' - ); - parent.getInput('INPUT').connection.setShadowDom(xml); - assertInputHasBlock(parent, 'INPUT', true); + suite('setShadowDom', function() { + suite('Add - No Block Connected', function() { + // These are defined separately in each suite. + function createRowBlock(workspace) { + var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( + '' + ), workspace); + return block; + } + + function createStatementBlock(workspace) { + var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( + '' + ), workspace); + return block; + } + + function createStackBlock(workspace) { + var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( + '' + ), workspace); + return block; + } + + test('Value', function() { + var parent = createRowBlock(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + ); + parent.getInput('INPUT').connection.setShadowDom(xml); + assertInputHasBlock(parent, 'INPUT', true); + assertSerialization( + parent, + { + 'type': 'row_block', + 'id': 'id0', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': 'id1', + } + } + } + }, + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Multiple Value', function() { + var parent = createRowBlock(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + '' + ); + parent.getInput('INPUT').connection.setShadowDom(xml); + assertInputHasBlock(parent, 'INPUT', true); + assertInputHasBlock( + parent.getInputTargetBlock('INPUT'), 'INPUT', true); + assertSerialization( + parent, + { + 'type': 'row_block', + 'id': 'id0', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': 'id1', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': 'id2', + } + } + } + } + } + } + }, + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Statement', function() { + var parent = createStatementBlock(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + ); + parent.getInput('NAME').connection.setShadowDom(xml); + assertInputHasBlock(parent, 'NAME', true); + assertSerialization( + parent, + { + 'type': 'statement_block', + 'id': 'id0', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': 'id1', + } + } + } + }, + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Multiple Statement', function() { + var parent = createStatementBlock(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + '' + ); + parent.getInput('NAME').connection.setShadowDom(xml); + assertInputHasBlock(parent, 'NAME', true); + assertInputHasBlock( + parent.getInputTargetBlock('NAME'), 'NAME', true); + assertSerialization( + parent, + { + 'type': 'statement_block', + 'id': 'id0', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': 'id1', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': 'id2', + } + } + } + } + } + } + }, + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Next', function() { + var parent = createStackBlock(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + ); + parent.nextConnection.setShadowDom(xml); + assertNextHasBlock(parent, true); + assertSerialization( + parent, + { + 'type': 'stack_block', + 'id': 'id0', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': 'id1', + } + } + }, + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Multiple Next', function() { + var parent = createStackBlock(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + '' + ); + parent.nextConnection.setShadowDom(xml); + assertNextHasBlock(parent, true); + assertNextHasBlock(parent.getNextBlock(), true); + assertSerialization( + parent, + { + 'type': 'stack_block', + 'id': 'id0', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': 'id1', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': 'id2', + } + } + } + } + }, + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + ); + }); + }); + + suite('Add - With Block Connected', function() { + // These are defined separately in each suite. + function createRowBlocks(workspace) { + var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + '' + ), workspace); + return block; + } + + function createStatementBlocks(workspace) { + var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + '' + ), workspace); + return block; + } + + function createStackBlocks(workspace) { + var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + '' + ), workspace); + return block; + } + + test('Value', function() { + var parent = createRowBlocks(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + ); + parent.getInput('INPUT').connection.setShadowDom(xml); + assertInputHasBlock(parent, 'INPUT', false); + parent.getInput('INPUT').connection.disconnect(); + assertInputHasBlock(parent, 'INPUT', true); + assertSerialization( + parent, + { + 'type': 'row_block', + 'id': 'id0', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': 'id1', + } + } + } + }, + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Multiple Value', function() { + var parent = createRowBlocks(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + '' + ); + parent.getInput('INPUT').connection.setShadowDom(xml); + assertInputHasBlock(parent, 'INPUT', false); + assertInputNotHasBlock(parent.getInputTargetBlock('INPUT'), 'INPUT'); + parent.getInput('INPUT').connection.disconnect(); + assertInputHasBlock(parent, 'INPUT', true); + assertInputHasBlock( + parent.getInputTargetBlock('INPUT'), 'INPUT', true); + assertSerialization( + parent, + { + 'type': 'row_block', + 'id': 'id0', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': 'id1', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': 'id2', + } + } + } + } + } + } + }, + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Statement', function() { + var parent = createStatementBlocks(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + ); + parent.getInput('NAME').connection.setShadowDom(xml); + assertInputHasBlock(parent, 'NAME', false); + parent.getInput('NAME').connection.disconnect(); + assertInputHasBlock(parent, 'NAME', true); + assertSerialization( + parent, + { + 'type': 'statement_block', + 'id': 'id0', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': 'id1', + } + } + } + }, + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Multiple Statement', function() { + var parent = createStatementBlocks(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + '' + ); + parent.getInput('NAME').connection.setShadowDom(xml); + assertInputHasBlock(parent, 'NAME', false); + assertInputNotHasBlock( + parent.getInputTargetBlock('NAME'), 'NAME'); + parent.getInput('NAME').connection.disconnect(); + assertInputHasBlock(parent, 'NAME', true); + assertInputHasBlock( + parent.getInputTargetBlock('NAME'), 'NAME', true); + assertSerialization( + parent, + { + 'type': 'statement_block', + 'id': 'id0', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': 'id1', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': 'id2', + } + } + } + } + } + } + }, + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Next', function() { + var parent = createStackBlocks(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + ); + parent.nextConnection.setShadowDom(xml); + assertNextHasBlock(parent, false); + parent.nextConnection.disconnect(); + assertNextHasBlock(parent, true); + assertSerialization( + parent, + { + 'type': 'stack_block', + 'id': 'id0', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': 'id1', + } + } + }, + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Multiple Next', function() { + var parent = createStackBlocks(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + '' + ); + parent.nextConnection.setShadowDom(xml); + assertNextHasBlock(parent, false); + assertNextNotHasBlock(parent.getNextBlock()); + parent.nextConnection.disconnect(); + assertNextHasBlock(parent, true); + assertNextHasBlock(parent.getNextBlock(), true); + assertSerialization( + parent, + { + 'type': 'stack_block', + 'id': 'id0', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': 'id1', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': 'id2', + } + } + } + } + }, + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + ); + }); + }); + + suite('Add - With Shadow Connected', function() { + // These are defined separately in each suite. + function createRowBlock(workspace) { + var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( + '' + ), workspace); + return block; + } + + function createStatementBlock(workspace) { + var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( + '' + ), workspace); + return block; + } + + function createStackBlock(workspace) { + var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( + '' + ), workspace); + return block; + } + + test('Value', function() { + var parent = createRowBlock(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + ); + parent.getInput('INPUT').connection.setShadowDom(xml); + assertInputHasBlock(parent, 'INPUT', true, '1'); + var xml = Blockly.Xml.textToDom( + '' + ); + parent.getInput('INPUT').connection.setShadowDom(xml); + assertInputHasBlock(parent, 'INPUT', true, '2'); + assertSerialization( + parent, + { + 'type': 'row_block', + 'id': 'id0', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': '2', + } + } + } + }, + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Multiple Value', function() { + var parent = createRowBlock(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + '' + ); + parent.getInput('INPUT').connection.setShadowDom(xml); + assertInputHasBlock(parent, 'INPUT', true, '1'); + assertInputHasBlock( + parent.getInputTargetBlock('INPUT'), 'INPUT', true, 'a'); + var xml = Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + '' + ); + parent.getInput('INPUT').connection.setShadowDom(xml); + assertInputHasBlock(parent, 'INPUT', true, '2'); + assertInputHasBlock( + parent.getInputTargetBlock('INPUT'), 'INPUT', true, 'b'); + assertSerialization( + parent, + { + 'type': 'row_block', + 'id': 'id0', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': '2', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': 'b', + } + } + } + } + } + } + }, + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Statement', function() { + var parent = createStatementBlock(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + ); + parent.getInput('NAME').connection.setShadowDom(xml); + assertInputHasBlock(parent, 'NAME', true, '1'); + var xml = Blockly.Xml.textToDom( + '' + ); + parent.getInput('NAME').connection.setShadowDom(xml); + assertInputHasBlock(parent, 'NAME', true, '2'); + assertSerialization( + parent, + { + 'type': 'statement_block', + 'id': 'id0', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': '2', + } + } + } + }, + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Multiple Statement', function() { + var parent = createStatementBlock(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + '' + ); + parent.getInput('NAME').connection.setShadowDom(xml); + assertInputHasBlock(parent, 'NAME', true, '1'); + assertInputHasBlock( + parent.getInputTargetBlock('NAME'), 'NAME', true, 'a'); + var xml = Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + '' + ); + parent.getInput('NAME').connection.setShadowDom(xml); + assertInputHasBlock(parent, 'NAME', true, '2'); + assertInputHasBlock( + parent.getInputTargetBlock('NAME'), 'NAME', true, 'b'); + assertSerialization( + parent, + { + 'type': 'statement_block', + 'id': 'id0', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': '2', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': 'b', + } + } + } + } + } + } + }, + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Next', function() { + var parent = createStackBlock(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + ); + parent.nextConnection.setShadowDom(xml); + assertNextHasBlock(parent, true, '1'); + var xml = Blockly.Xml.textToDom( + '' + ); + parent.nextConnection.setShadowDom(xml); + assertNextHasBlock(parent, true, '2'); + assertSerialization( + parent, + { + 'type': 'stack_block', + 'id': 'id0', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': '2', + } + } + }, + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Multiple Next', function() { + var parent = createStackBlock(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + '' + ); + parent.nextConnection.setShadowDom(xml); + assertNextHasBlock(parent, true, '1'); + assertNextHasBlock(parent.getNextBlock(), true, 'a'); + var xml = Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + '' + ); + parent.nextConnection.setShadowDom(xml); + assertNextHasBlock(parent, true, '2'); + assertNextHasBlock(parent.getNextBlock(), true, 'b'); + assertSerialization( + parent, + { + 'type': 'stack_block', + 'id': 'id0', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': '2', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': 'b', + } + } + } + } + }, + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + ); + }); + }); + + suite('Remove - No Block Connected', function() { + // These are defined separately in each suite. + function createRowBlock(workspace) { + var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + '' + ), workspace); + return block; + } + + function createStatementBlock(workspace) { + var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + '' + ), workspace); + return block; + } + + function createStackBlock(workspace) { + var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + '' + ), workspace); + return block; + } + + test('Value', function() { + var parent = createRowBlock(this.workspace); + parent.getInput('INPUT').connection.setShadowDom(null); + assertInputNotHasBlock(parent, 'INPUT'); + assertSerialization( + parent, + { + 'type': 'row_block', + 'id': 'id0', + }, + '' + + '' + ); + }); + + test('Statement', function() { + var parent = createStatementBlock(this.workspace); + parent.getInput('NAME').connection.setShadowDom(null); + assertInputNotHasBlock(parent, 'STATEMENT'); + assertSerialization( + parent, + { + 'type': 'statement_block', + 'id': 'id0', + }, + '' + + '' + ); + }); + + test('Next', function() { + var parent = createStackBlock(this.workspace); + parent.nextConnection.setShadowDom(null); + assertNextNotHasBlock(parent); + assertSerialization( + parent, + { + 'type': 'stack_block', + 'id': 'id0', + }, + '' + + '' + ); + }); + }); + + suite('Remove - Block Connected', function() { + // These are defined separately in each suite. + function createRowBlock(workspace) { + var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + ' ' + + '' + ), workspace); + return block; + } + + function createStatementBlock(workspace) { + var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + ' ' + + '' + ), workspace); + return block; + } + + function createStackBlock(workspace) { + var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + ' ' + + '' + ), workspace); + return block; + } + + test('Value', function() { + var parent = createRowBlock(this.workspace); + parent.getInput('INPUT').connection.setShadowDom(null); + assertInputHasBlock(parent, 'INPUT', false); + parent.getInput('INPUT').connection.disconnect(); + assertInputNotHasBlock(parent, 'INPUT'); + assertSerialization( + parent, + { + 'type': 'row_block', + 'id': 'id0', + }, + '' + + '' + ); + }); + + test('Statement', function() { + var parent = createStatementBlock(this.workspace); + parent.getInput('NAME').connection.setShadowDom(null); + assertInputHasBlock(parent, 'NAME', false); + parent.getInput('NAME').connection.disconnect(); + assertInputNotHasBlock(parent, 'NAME'); + assertSerialization( + parent, + { + 'type': 'statement_block', + 'id': 'id0', + }, + '' + + '' + ); + }); + + test('Next', function() { + var parent = createStackBlock(this.workspace); + parent.nextConnection.setShadowDom(null); + assertNextHasBlock(parent, false); + parent.nextConnection.disconnect(); + assertNextNotHasBlock(parent); + assertSerialization( + parent, + { + 'type': 'stack_block', + 'id': 'id0', + }, + '' + + '' + ); + }); + }); + + suite('Add - Connect & Disconnect - Remove', function() { + // These are defined separately in each suite. + function createRowBlock(workspace) { + var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( + '' + ), workspace); + return block; + } + + function createStatementBlock(workspace) { + var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( + '' + ), workspace); + return block; + } + + function createStackBlock(workspace) { + var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( + '' + ), workspace); + return block; + } + + test('Value', function() { + var parent = createRowBlock(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + ); + parent.getInput('INPUT').connection.setShadowDom(xml); + assertInputHasBlock(parent, 'INPUT', true); + var child = createRowBlock(this.workspace); + parent.getInput('INPUT').connection.connect(child.outputConnection); + assertInputHasBlock(parent, 'INPUT', false); + parent.getInput('INPUT').connection.disconnect(); + assertInputHasBlock(parent, 'INPUT', true); + parent.getInput('INPUT').connection.setShadowDom(null); + assertInputNotHasBlock(parent, 'INPUT'); + }); + + test('Multiple Value', function() { + var parent = createRowBlock(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + '' + ); + parent.getInput('INPUT').connection.setShadowDom(xml); + assertInputHasBlock(parent, 'INPUT', true); + assertInputHasBlock( + parent.getInputTargetBlock('INPUT'), 'INPUT', true); + var child = createRowBlock(this.workspace); + parent.getInput('INPUT').connection.connect(child.outputConnection); + assertInputHasBlock(parent, 'INPUT', false); + parent.getInput('INPUT').connection.disconnect(); + assertInputHasBlock(parent, 'INPUT', true); + assertInputHasBlock( + parent.getInputTargetBlock('INPUT'), 'INPUT', true); + parent.getInput('INPUT').connection.setShadowDom(null); + assertInputNotHasBlock(parent, 'INPUT'); + }); + + test('Statement', function() { + var parent = createStatementBlock(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + ); + parent.getInput('NAME').connection.setShadowDom(xml); + assertInputHasBlock(parent, 'NAME', true); + var child = createStatementBlock(this.workspace); + parent.getInput('NAME').connection + .connect(child.previousConnection); + assertInputHasBlock(parent, 'NAME', false); + parent.getInput('NAME').connection.disconnect(); + assertInputHasBlock(parent, 'NAME', true); + parent.getInput('NAME').connection.setShadowDom(null); + assertInputNotHasBlock(parent, 'NAME'); + }); + + test('Multiple Statement', function() { + var parent = createStatementBlock(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + '' + ); + parent.getInput('NAME').connection.setShadowDom(xml); + assertInputHasBlock(parent, 'NAME', true); + assertInputHasBlock( + parent.getInputTargetBlock('NAME'), 'NAME', true); + var child = createStatementBlock(this.workspace); + parent.getInput('NAME').connection + .connect(child.previousConnection); + assertInputHasBlock(parent, 'NAME', false); + parent.getInput('NAME').connection.disconnect(); + assertInputHasBlock(parent, 'NAME', true); + assertInputHasBlock( + parent.getInputTargetBlock('NAME'), 'NAME', true); + parent.getInput('NAME').connection.setShadowDom(null); + assertInputNotHasBlock(parent, 'NAME'); + }); + + test('Next', function() { + var parent = createStackBlock(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + ); + parent.nextConnection.setShadowDom(xml); + assertNextHasBlock(parent, true); + var child = createStatementBlock(this.workspace); + parent.nextConnection.connect(child.previousConnection); + assertNextHasBlock(parent, false); + parent.nextConnection.disconnect(); + assertNextHasBlock(parent, true); + parent.nextConnection.setShadowDom(null); + assertNextNotHasBlock(parent); + }); + + test('Multiple Next', function() { + var parent = createStackBlock(this.workspace); + var xml = Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + '' + ); + parent.nextConnection.setShadowDom(xml); + assertNextHasBlock(parent, true); + assertNextHasBlock(parent.getNextBlock(), true); + var child = createStatementBlock(this.workspace); + parent.nextConnection.connect(child.previousConnection); + assertNextHasBlock(parent, false); + parent.nextConnection.disconnect(); + assertNextHasBlock(parent, true); + assertNextHasBlock(parent.getNextBlock(), true); + parent.nextConnection.setShadowDom(null); + assertNextNotHasBlock(parent); + }); }); - test('Multiple Value', function() { - var parent = createRowBlock(this.workspace); - var xml = Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - '' - ); - parent.getInput('INPUT').connection.setShadowDom(xml); - assertInputHasBlock(parent, 'INPUT', true); - assertInputHasBlock( - parent.getInputTargetBlock('INPUT'), 'INPUT', true); - }); + suite('Invalid', function() { + test('Attach to output', function() { + const block = this.workspace.newBlock('row_block'); + chai.assert.throws(() => + block.outputConnection.setShadowDom(Blockly.Xml.textToDom( + ''))); + }); - test('Statement', function() { - var parent = createStatementBlock(this.workspace); - var xml = Blockly.Xml.textToDom( - '' - ); - parent.getInput('STATEMENT').connection.setShadowDom(xml); - assertInputHasBlock(parent, 'STATEMENT', true); - }); + test('Attach to previous', function() { + const block = this.workspace.newBlock('stack_block'); + chai.assert.throws(() => + block.previousConnection.setShadowDom(Blockly.Xml.textToDom( + ''))); + }); - test('Multiple Statement', function() { - var parent = createStatementBlock(this.workspace); - var xml = Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - '' - ); - parent.getInput('STATEMENT').connection.setShadowDom(xml); - assertInputHasBlock(parent, 'STATEMENT', true); - assertInputHasBlock( - parent.getInputTargetBlock('STATEMENT'), 'STATEMENT', true); - }); + test('Missing output', function() { + const block = this.workspace.newBlock('row_block'); + chai.assert.throws(() => + block.outputConnection.setShadowDom(Blockly.Xml.textToDom( + ''))); + }); - test('Next', function() { - var parent = createStackBlock(this.workspace); - var xml = Blockly.Xml.textToDom( - '' - ); - parent.nextConnection.setShadowDom(xml); - assertNextHasBlock(parent, true); - }); + test('Missing previous', function() { + const block = this.workspace.newBlock('stack_block'); + chai.assert.throws(() => + block.previousConnection.setShadowDom(Blockly.Xml.textToDom( + ''))); + }); - test('Multiple Next', function() { - var parent = createStackBlock(this.workspace); - var xml = Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - '' - ); - parent.nextConnection.setShadowDom(xml); - assertNextHasBlock(parent, true); - assertNextHasBlock(parent.getNextBlock(), true); + test('Invalid connection checks, output', function() { + const block = this.workspace.newBlock('logic_operation'); + chai.assert.throws(() => + block.getInput('A').connection.setShadowDom( + Blockly.Xml.textToDom(''))); + }); + + test('Invalid connection checks, previous', function() { + Blockly.defineBlocksWithJsonArray([{ + "type": "stack_checks_block", + "message0": "", + "previousStatement": "check 1", + "nextStatement": "check 2" + }]); + const block = this.workspace.newBlock('stack_checks_block'); + chai.assert.throws(() => + block.nextConnection.setShadowDom(Blockly.Xml.textToDom( + ''))); + }); }); }); - suite('Add - With Block Connected', function() { - // These are defined separately in each suite. - function createRowBlocks(workspace) { - var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - '' - ), workspace); - return block; - } + suite('setShadowState', function() { + suite('Add - No Block Connected', function() { + // These are defined separately in each suite. + function createRowBlock(workspace) { + return Blockly.serialization.blocks.append( + {'type': 'row_block', 'id': 'id0'}, workspace); + } + + function createStatementBlock(workspace) { + return Blockly.serialization.blocks.append( + {'type': 'statement_block', 'id': 'id0'}, workspace); + } + + function createStackBlock(workspace) { + return Blockly.serialization.blocks.append( + {'type': 'stack_block', 'id': 'id0'}, workspace); + } - function createStatementBlocks(workspace) { - var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - '' - ), workspace); - return block; - } + test('Value', function() { + var parent = createRowBlock(this.workspace); + parent.getInput('INPUT').connection + .setShadowState({'type': 'row_block', 'id': 'id1'}); + assertInputHasBlock(parent, 'INPUT', true); + assertSerialization( + parent, + { + 'type': 'row_block', + 'id': 'id0', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': 'id1', + } + } + } + }, + '' + + '' + + '' + + '' + + '' + ); + }); - function createStackBlocks(workspace) { - var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - '' - ), workspace); - return block; - } + test('Multiple Value', function() { + var parent = createRowBlock(this.workspace); + parent.getInput('INPUT').connection.setShadowState({ + 'type': 'row_block', + 'id': 'id1', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': 'id2' + } + } + } + }); + assertInputHasBlock(parent, 'INPUT', true); + assertInputHasBlock( + parent.getInputTargetBlock('INPUT'), 'INPUT', true); + assertSerialization( + parent, + { + 'type': 'row_block', + 'id': 'id0', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': 'id1', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': 'id2', + } + } + } + } + } + } + }, + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + ); + }); - test('Value', function() { - var parent = createRowBlocks(this.workspace); - var xml = Blockly.Xml.textToDom( - '' - ); - parent.getInput('INPUT').connection.setShadowDom(xml); - assertInputHasBlock(parent, 'INPUT', false); - parent.getInput('INPUT').connection.disconnect(); - assertInputHasBlock(parent, 'INPUT', true); + test('Statement', function() { + var parent = createStatementBlock(this.workspace); + parent.getInput('NAME').connection + .setShadowState({'type': 'statement_block', 'id': 'id1'}); + assertInputHasBlock(parent, 'NAME', true); + assertSerialization( + parent, + { + 'type': 'statement_block', + 'id': 'id0', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': 'id1', + } + } + } + }, + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Multiple Statment', function() { + var parent = createStatementBlock(this.workspace); + parent.getInput('NAME').connection.setShadowState({ + 'type': 'statement_block', + 'id': 'id1', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': 'id2', + } + } + } + }); + assertInputHasBlock(parent, 'NAME', true); + assertInputHasBlock( + parent.getInputTargetBlock('NAME'), 'NAME', true); + assertSerialization( + parent, + { + 'type': 'statement_block', + 'id': 'id0', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': 'id1', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': 'id2', + } + } + } + } + } + } + }, + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Next', function() { + var parent = createStackBlock(this.workspace); + parent.nextConnection + .setShadowState({'type': 'stack_block', 'id': 'id1'}); + assertNextHasBlock(parent, true); + assertSerialization( + parent, + { + 'type': 'stack_block', + 'id': 'id0', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': 'id1', + } + } + }, + '' + + '' + + '' + + '' + + '' + ); + }); + test('Multiple Next', function() { + var parent = createStackBlock(this.workspace); + parent.nextConnection.setShadowState({ + 'type': 'stack_block', + 'id': 'id1', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': 'id2', + } + } + }); + assertNextHasBlock(parent, true); + assertNextHasBlock(parent.getNextBlock(), true); + assertSerialization( + parent, + { + 'type': 'stack_block', + 'id': 'id0', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': 'id1', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': 'id2', + } + } + } + } + }, + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + ); + }); }); - test('Multiple Value', function() { - var parent = createRowBlocks(this.workspace); - var xml = Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - '' - ); - parent.getInput('INPUT').connection.setShadowDom(xml); - assertInputHasBlock(parent, 'INPUT', false); - assertInputNotHasBlock(parent.getInputTargetBlock('INPUT'), 'INPUT'); - parent.getInput('INPUT').connection.disconnect(); - assertInputHasBlock(parent, 'INPUT', true); - assertInputHasBlock( - parent.getInputTargetBlock('INPUT'), 'INPUT', true); + suite('Add - With Block Connected', function() { + // These are defined separately in each suite. + function createRowBlocks(workspace) { + return Blockly.serialization.blocks.append( + { + 'type': 'row_block', + 'id': 'id0', + 'inputs': { + 'INPUT': { + 'block': { + 'type': 'row_block', + 'id': 'idA' + } + } + } + }, + workspace); + } + + function createStatementBlocks(workspace) { + return Blockly.serialization.blocks.append( + { + 'type': 'statement_block', + 'id': 'id0', + 'inputs': { + 'NAME': { + 'block': { + 'type': 'statement_block', + 'id': 'idA' + } + } + } + }, + workspace); + } + + function createStackBlocks(workspace) { + return Blockly.serialization.blocks.append( + { + 'type': 'stack_block', + 'id': 'id0', + 'next': { + 'block': { + 'type': 'stack_block', + 'id': 'idA' + } + } + }, + workspace); + } + + test('Value', function() { + var parent = createRowBlocks(this.workspace); + parent.getInput('INPUT').connection + .setShadowState({'type': 'row_block', 'id': 'id1'}); + assertInputHasBlock(parent, 'INPUT', false); + parent.getInput('INPUT').connection.disconnect(); + assertInputHasBlock(parent, 'INPUT', true); + assertSerialization( + parent, + { + 'type': 'row_block', + 'id': 'id0', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': 'id1', + } + } + } + }, + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Multiple Value', function() { + var parent = createRowBlocks(this.workspace); + parent.getInput('INPUT').connection.setShadowState( + { + 'type': 'row_block', + 'id': 'id1', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': 'id2', + } + } + } + } + ); + assertInputHasBlock(parent, 'INPUT', false); + assertInputNotHasBlock(parent.getInputTargetBlock('INPUT'), 'INPUT'); + parent.getInput('INPUT').connection.disconnect(); + assertInputHasBlock(parent, 'INPUT', true); + assertInputHasBlock( + parent.getInputTargetBlock('INPUT'), 'INPUT', true); + assertSerialization( + parent, + { + 'type': 'row_block', + 'id': 'id0', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': 'id1', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': 'id2', + } + } + } + } + } + } + }, + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Statement', function() { + var parent = createStatementBlocks(this.workspace); + parent.getInput('NAME').connection + .setShadowState({'type': 'statement_block', 'id': 'id1'}); + assertInputHasBlock(parent, 'NAME', false); + parent.getInput('NAME').connection.disconnect(); + assertInputHasBlock(parent, 'NAME', true); + assertSerialization( + parent, + { + 'type': 'statement_block', + 'id': 'id0', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': 'id1', + } + } + } + }, + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Multiple Statement', function() { + var parent = createStatementBlocks(this.workspace); + parent.getInput('NAME').connection.setShadowState( + { + 'type': 'statement_block', + 'id': 'id1', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': 'id2', + } + } + } + } + ); + assertInputHasBlock(parent, 'NAME', false); + assertInputNotHasBlock( + parent.getInputTargetBlock('NAME'), 'NAME'); + parent.getInput('NAME').connection.disconnect(); + assertInputHasBlock(parent, 'NAME', true); + assertInputHasBlock( + parent.getInputTargetBlock('NAME'), 'NAME', true); + assertSerialization( + parent, + { + 'type': 'statement_block', + 'id': 'id0', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': 'id1', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': 'id2', + } + } + } + } + } + } + }, + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Next', function() { + var parent = createStackBlocks(this.workspace); + parent.nextConnection + .setShadowState({'type': 'stack_block', 'id': 'id1'}); + assertNextHasBlock(parent, false); + parent.nextConnection.disconnect(); + assertNextHasBlock(parent, true); + assertSerialization( + parent, + { + 'type': 'stack_block', + 'id': 'id0', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': 'id1', + } + } + }, + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Multiple Next', function() { + var parent = createStackBlocks(this.workspace); + parent.nextConnection.setShadowState( + { + 'type': 'stack_block', + 'id': 'id1', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': 'id2', + } + } + } + ); + assertNextHasBlock(parent, false); + assertNextNotHasBlock(parent.getNextBlock()); + parent.nextConnection.disconnect(); + assertNextHasBlock(parent, true); + assertNextHasBlock(parent.getNextBlock(), true); + assertSerialization( + parent, + { + 'type': 'stack_block', + 'id': 'id0', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': 'id1', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': 'id2', + } + } + } + } + }, + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + ); + }); + }); + + suite('Add - With Shadow Connected', function() { + // These are defined separately in each suite. + function createRowBlock(workspace) { + return Blockly.serialization.blocks.append( + {'type': 'row_block', 'id': 'id0'}, workspace); + } + + function createStatementBlock(workspace) { + return Blockly.serialization.blocks.append( + {'type': 'statement_block', 'id': 'id0'}, workspace); + } + + function createStackBlock(workspace) { + return Blockly.serialization.blocks.append( + {'type': 'stack_block', 'id': 'id0'}, workspace); + } + + test('Value', function() { + var parent = createRowBlock(this.workspace); + parent.getInput('INPUT').connection + .setShadowState({'type': 'row_block', 'id': '1'}); + assertInputHasBlock(parent, 'INPUT', true, '1'); + parent.getInput('INPUT').connection + .setShadowState({'type': 'row_block', 'id': '2'}); + assertInputHasBlock(parent, 'INPUT', true, '2'); + assertSerialization( + parent, + { + 'type': 'row_block', + 'id': 'id0', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': '2', + } + } + } + }, + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Multiple Value', function() { + var parent = createRowBlock(this.workspace); + parent.getInput('INPUT').connection.setShadowState( + { + 'type': 'row_block', + 'id': '1', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': 'a', + } + } + } + } + ); + assertInputHasBlock(parent, 'INPUT', true, '1'); + assertInputHasBlock( + parent.getInputTargetBlock('INPUT'), 'INPUT', true, 'a'); + parent.getInput('INPUT').connection.setShadowState( + { + 'type': 'row_block', + 'id': '2', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': 'b', + } + } + } + } + ); + assertInputHasBlock(parent, 'INPUT', true, '2'); + assertInputHasBlock( + parent.getInputTargetBlock('INPUT'), 'INPUT', true, 'b'); + assertSerialization( + parent, + { + 'type': 'row_block', + 'id': 'id0', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': '2', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': 'b', + } + } + } + } + } + } + }, + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Statement', function() { + var parent = createStatementBlock(this.workspace); + parent.getInput('NAME').connection + .setShadowState({'type': 'statement_block', 'id': '1'}); + assertInputHasBlock(parent, 'NAME', true, '1'); + parent.getInput('NAME').connection + .setShadowState({'type': 'statement_block', 'id': '2'}); + assertInputHasBlock(parent, 'NAME', true, '2'); + assertSerialization( + parent, + { + 'type': 'statement_block', + 'id': 'id0', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': '2', + } + } + } + }, + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Multiple Statement', function() { + var parent = createStatementBlock(this.workspace); + parent.getInput('NAME').connection.setShadowState( + { + 'type': 'statement_block', + 'id': '1', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': 'a', + } + } + } + } + ); + assertInputHasBlock(parent, 'NAME', true, '1'); + assertInputHasBlock( + parent.getInputTargetBlock('NAME'), 'NAME', true, 'a'); + parent.getInput('NAME').connection.setShadowState( + { + 'type': 'statement_block', + 'id': '2', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': 'b', + } + } + } + } + ); + assertInputHasBlock(parent, 'NAME', true, '2'); + assertInputHasBlock( + parent.getInputTargetBlock('NAME'), 'NAME', true, 'b'); + assertSerialization( + parent, + { + 'type': 'statement_block', + 'id': 'id0', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': '2', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': 'b', + } + } + } + } + } + } + }, + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Next', function() { + var parent = createStackBlock(this.workspace); + parent.nextConnection + .setShadowState({'type': 'stack_block', 'id': '1'}); + assertNextHasBlock(parent, true, '1'); + parent.nextConnection + .setShadowState({'type': 'stack_block', 'id': '2'}); + assertNextHasBlock(parent, true, '2'); + assertSerialization( + parent, + { + 'type': 'stack_block', + 'id': 'id0', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': '2', + } + } + }, + '' + + '' + + '' + + '' + + '' + ); + }); + + test('Multiple Next', function() { + var parent = createStackBlock(this.workspace); + parent.nextConnection.setShadowState( + { + 'type': 'stack_block', + 'id': '1', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': 'a', + } + } + } + ); + assertNextHasBlock(parent, true, '1'); + assertNextHasBlock(parent.getNextBlock(), true, 'a'); + parent.nextConnection.setShadowState( + { + 'type': 'stack_block', + 'id': '2', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': 'b', + } + } + } + ); + assertNextHasBlock(parent, true, '2'); + assertNextHasBlock(parent.getNextBlock(), true, 'b'); + assertSerialization( + parent, + { + 'type': 'stack_block', + 'id': 'id0', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': '2', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': 'b', + } + } + } + } + }, + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + ); + }); + }); + + suite('Remove - No Block Connected', function() { + // These are defined separately in each suite. + function createRowBlocks(workspace) { + return Blockly.serialization.blocks.append( + { + 'type': 'row_block', + 'id': 'id0', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': 'id1', + } + } + } + }, + workspace); + } + + function createStatementBlocks(workspace) { + return Blockly.serialization.blocks.append( + { + 'type': 'statement_block', + 'id': 'id0', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': 'id1', + } + } + } + }, + workspace); + } + + function createStackBlocks(workspace) { + return Blockly.serialization.blocks.append( + { + 'type': 'stack_block', + 'id': 'id0', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': 'id1', + } + } + }, + workspace); + } + + test('Value', function() { + var parent = createRowBlocks(this.workspace); + parent.getInput('INPUT').connection.setShadowState(null); + assertInputNotHasBlock(parent, 'INPUT'); + assertSerialization( + parent, + { + 'type': 'row_block', + 'id': 'id0', + }, + '' + + '' + ); + }); + + test('Statement', function() { + var parent = createStatementBlocks(this.workspace); + parent.getInput('NAME').connection.setShadowState(null); + assertInputNotHasBlock(parent, 'NAME'); + assertSerialization( + parent, + { + 'type': 'statement_block', + 'id': 'id0', + }, + '' + + '' + ); + }); + + test('Next', function() { + var parent = createStackBlocks(this.workspace); + parent.nextConnection.setShadowState(null); + assertNextNotHasBlock(parent); + assertSerialization( + parent, + { + 'type': 'stack_block', + 'id': 'id0', + }, + '' + + '' + ); + }); + }); + + suite('Remove - Block Connected', function() { + // These are defined separately in each suite. + function createRowBlocks(workspace) { + return Blockly.serialization.blocks.append( + { + 'type': 'row_block', + 'id': 'id0', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + 'id': 'id1', + }, + 'block': { + 'type': 'row_block', + 'id': 'id2', + } + } + } + }, + workspace); + } + + function createStatementBlocks(workspace) { + return Blockly.serialization.blocks.append( + { + 'type': 'statement_block', + 'id': 'id0', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + 'id': 'id1', + }, + 'block': { + 'type': 'statement_block', + 'id': 'id2', + } + } + } + }, + workspace); + } + + function createStackBlocks(workspace) { + return Blockly.serialization.blocks.append( + { + 'type': 'stack_block', + 'id': 'id0', + 'next': { + 'shadow': { + 'type': 'stack_block', + 'id': 'id1', + }, + 'block': { + 'type': 'stack_block', + 'id': 'id2', + } + } + }, + workspace); + } + + test('Value', function() { + var parent = createRowBlocks(this.workspace); + parent.getInput('INPUT').connection.setShadowState(null); + assertInputHasBlock(parent, 'INPUT', false); + parent.getInput('INPUT').connection.disconnect(); + assertInputNotHasBlock(parent, 'INPUT'); + assertSerialization( + parent, + { + 'type': 'row_block', + 'id': 'id0', + }, + '' + + '' + ); + }); + + test('Statement', function() { + var parent = createStatementBlocks(this.workspace); + parent.getInput('NAME').connection.setShadowState(null); + assertInputHasBlock(parent, 'NAME', false); + parent.getInput('NAME').connection.disconnect(); + assertInputNotHasBlock(parent, 'NAME'); + assertSerialization( + parent, + { + 'type': 'statement_block', + 'id': 'id0', + }, + '' + + '' + ); + }); + + test('Next', function() { + var parent = createStackBlocks(this.workspace); + parent.nextConnection.setShadowState(null); + assertNextHasBlock(parent, false); + parent.nextConnection.disconnect(); + assertNextNotHasBlock(parent); + assertSerialization( + parent, + { + 'type': 'stack_block', + 'id': 'id0', + }, + '' + + '' + ); + }); + }); + + suite('Add - Connect & Disconnect - Remove', function() { + // These are defined separately in each suite. + function createRowBlock(workspace) { + return Blockly.serialization.blocks.append( + {'type': 'row_block'}, workspace); + } + + function createStatementBlock(workspace) { + return Blockly.serialization.blocks.append( + {'type': 'statement_block'}, workspace); + } + + function createStackBlock(workspace) { + return Blockly.serialization.blocks.append( + {'type': 'stack_block'}, workspace); + } + + test('Value', function() { + var parent = createRowBlock(this.workspace); + parent.getInput('INPUT').connection + .setShadowState({'type': 'row_block'}); + assertInputHasBlock(parent, 'INPUT', true); + var child = createRowBlock(this.workspace); + parent.getInput('INPUT').connection.connect(child.outputConnection); + assertInputHasBlock(parent, 'INPUT', false); + parent.getInput('INPUT').connection.disconnect(); + assertInputHasBlock(parent, 'INPUT', true); + parent.getInput('INPUT').connection.setShadowState(null); + assertInputNotHasBlock(parent, 'INPUT'); + }); + + test('Multiple Value', function() { + var parent = createRowBlock(this.workspace); + parent.getInput('INPUT').connection.setShadowState({ + 'type': 'row_block', + 'inputs': { + 'INPUT': { + 'shadow': { + 'type': 'row_block', + } + } + } + }); + assertInputHasBlock(parent, 'INPUT', true); + assertInputHasBlock( + parent.getInputTargetBlock('INPUT'), 'INPUT', true); + var child = createRowBlock(this.workspace); + parent.getInput('INPUT').connection.connect(child.outputConnection); + assertInputHasBlock(parent, 'INPUT', false); + parent.getInput('INPUT').connection.disconnect(); + assertInputHasBlock(parent, 'INPUT', true); + assertInputHasBlock( + parent.getInputTargetBlock('INPUT'), 'INPUT', true); + parent.getInput('INPUT').connection.setShadowState(null); + assertInputNotHasBlock(parent, 'INPUT'); + }); + + test('Statement', function() { + var parent = createStatementBlock(this.workspace); + parent.getInput('NAME').connection + .setShadowState({'type': 'statement_block'}); + assertInputHasBlock(parent, 'NAME', true); + var child = createStatementBlock(this.workspace); + parent.getInput('NAME').connection + .connect(child.previousConnection); + assertInputHasBlock(parent, 'NAME', false); + parent.getInput('NAME').connection.disconnect(); + assertInputHasBlock(parent, 'NAME', true); + parent.getInput('NAME').connection.setShadowState(null); + assertInputNotHasBlock(parent, 'NAME'); + }); + + test('Multiple Statement', function() { + var parent = createStatementBlock(this.workspace); + parent.getInput('NAME').connection.setShadowState({ + 'type': 'statement_block', + 'inputs': { + 'NAME': { + 'shadow': { + 'type': 'statement_block', + } + } + } + }); + assertInputHasBlock(parent, 'NAME', true); + assertInputHasBlock( + parent.getInputTargetBlock('NAME'), 'NAME', true); + var child = createStatementBlock(this.workspace); + parent.getInput('NAME').connection + .connect(child.previousConnection); + assertInputHasBlock(parent, 'NAME', false); + parent.getInput('NAME').connection.disconnect(); + assertInputHasBlock(parent, 'NAME', true); + assertInputHasBlock( + parent.getInputTargetBlock('NAME'), 'NAME', true); + parent.getInput('NAME').connection.setShadowState(null); + assertInputNotHasBlock(parent, 'NAME'); + }); + + test('Next', function() { + var parent = createStackBlock(this.workspace); + parent.nextConnection.setShadowState({'type': 'stack_block'}); + var child = createStatementBlock(this.workspace); + parent.nextConnection.connect(child.previousConnection); + assertNextHasBlock(parent, false); + parent.nextConnection.disconnect(); + assertNextHasBlock(parent, true); + parent.nextConnection.setShadowState(null); + assertNextNotHasBlock(parent); + }); + + test('Multiple Next', function() { + var parent = createStackBlock(this.workspace); + parent.nextConnection.setShadowState({ + 'type': 'stack_block', + 'next': { + 'shadow': { + 'type': 'stack_block' + } + } + }); + assertNextHasBlock(parent, true); + assertNextHasBlock(parent.getNextBlock(), true); + var child = createStatementBlock(this.workspace); + parent.nextConnection.connect(child.previousConnection); + assertNextHasBlock(parent, false); + parent.nextConnection.disconnect(); + assertNextHasBlock(parent, true); + assertNextHasBlock(parent.getNextBlock(), true); + parent.nextConnection.setShadowState(null); + assertNextNotHasBlock(parent); + }); }); - test('Statement', function() { - var parent = createStatementBlocks(this.workspace); - var xml = Blockly.Xml.textToDom( - '' - ); - parent.getInput('STATEMENT').connection.setShadowDom(xml); - assertInputHasBlock(parent, 'STATEMENT', false); - parent.getInput('STATEMENT').connection.disconnect(); - assertInputHasBlock(parent, 'STATEMENT', true); - }); + suite('Invalid', function() { + test('Attach to output', function() { + const block = this.workspace.newBlock('row_block'); + chai.assert.throws(() => + block.outputConnection.setShadowState({'type': 'row_block'})); + }); - test('Multiple Statement', function() { - var parent = createStatementBlocks(this.workspace); - var xml = Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - '' - ); - parent.getInput('STATEMENT').connection.setShadowDom(xml); - assertInputHasBlock(parent, 'STATEMENT', false); - assertInputNotHasBlock( - parent.getInputTargetBlock('STATEMENT'), 'STATEMENT'); - parent.getInput('STATEMENT').connection.disconnect(); - assertInputHasBlock(parent, 'STATEMENT', true); - assertInputHasBlock( - parent.getInputTargetBlock('STATEMENT'), 'STATEMENT', true); - }); + test('Attach to previous', function() { + const block = this.workspace.newBlock('stack_block'); + chai.assert.throws(() => + block.previousConnection.setShadowState( + {'type': 'stack_block'})); + }); - test('Next', function() { - var parent = createStackBlocks(this.workspace); - var xml = Blockly.Xml.textToDom( - '' - ); - parent.nextConnection.setShadowDom(xml); - assertNextHasBlock(parent, false); - parent.nextConnection.disconnect(); - assertNextHasBlock(parent, true); - }); + test('Missing output', function() { + const block = this.workspace.newBlock('row_block'); + chai.assert.throws(() => + block.outputConnection.setShadowState({'type': 'stack_block'})); + }); - test('Multiple Next', function() { - var parent = createStackBlocks(this.workspace); - var xml = Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - '' - ); - parent.nextConnection.setShadowDom(xml); - assertNextHasBlock(parent, false); - assertNextNotHasBlock(parent.getNextBlock()); - parent.nextConnection.disconnect(); - assertNextHasBlock(parent, true); - assertNextHasBlock(parent.getNextBlock(), true); - }); - }); + test('Missing previous', function() { + const block = this.workspace.newBlock('stack_block'); + chai.assert.throws(() => + block.previousConnection.setShadowState({'type': 'row_block'})); + }); - suite('Add - With Shadow Connected', function() { - // These are defined separately in each suite. - function createRowBlock(workspace) { - var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( - '' - ), workspace); - return block; - } + test('Invalid connection checks, output', function() { + const block = this.workspace.newBlock('logic_operation'); + chai.assert.throws(() => + block.getInput('A').connection.setShadowState( + {'type': 'math_number'})); + }); - function createStatementBlock(workspace) { - var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( - '' - ), workspace); - return block; - } - - function createStackBlock(workspace) { - var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( - '' - ), workspace); - return block; - } - - test('Value', function() { - var parent = createRowBlock(this.workspace); - var xml = Blockly.Xml.textToDom( - '' - ); - parent.getInput('INPUT').connection.setShadowDom(xml); - assertInputHasBlock(parent, 'INPUT', true, '1'); - var xml = Blockly.Xml.textToDom( - '' - ); - parent.getInput('INPUT').connection.setShadowDom(xml); - assertInputHasBlock(parent, 'INPUT', true, '2'); - }); - - test('Multiple Value', function() { - var parent = createRowBlock(this.workspace); - var xml = Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - '' - ); - parent.getInput('INPUT').connection.setShadowDom(xml); - assertInputHasBlock(parent, 'INPUT', true, '1'); - assertInputHasBlock( - parent.getInputTargetBlock('INPUT'), 'INPUT', true, 'a'); - var xml = Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - '' - ); - parent.getInput('INPUT').connection.setShadowDom(xml); - assertInputHasBlock(parent, 'INPUT', true, '2'); - assertInputHasBlock( - parent.getInputTargetBlock('INPUT'), 'INPUT', true, 'b'); - }); - - test('Statement', function() { - var parent = createStatementBlock(this.workspace); - var xml = Blockly.Xml.textToDom( - '' - ); - parent.getInput('STATEMENT').connection.setShadowDom(xml); - assertInputHasBlock(parent, 'STATEMENT', true, '1'); - var xml = Blockly.Xml.textToDom( - '' - ); - parent.getInput('STATEMENT').connection.setShadowDom(xml); - assertInputHasBlock(parent, 'STATEMENT', true, '2'); - }); - - test('Multiple Statement', function() { - var parent = createStatementBlock(this.workspace); - var xml = Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - '' - ); - parent.getInput('STATEMENT').connection.setShadowDom(xml); - assertInputHasBlock(parent, 'STATEMENT', true, '1'); - assertInputHasBlock( - parent.getInputTargetBlock('STATEMENT'), 'STATEMENT', true, 'a'); - var xml = Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - '' - ); - parent.getInput('STATEMENT').connection.setShadowDom(xml); - assertInputHasBlock(parent, 'STATEMENT', true, '2'); - assertInputHasBlock( - parent.getInputTargetBlock('STATEMENT'), 'STATEMENT', true, 'b'); - }); - - test('Next', function() { - var parent = createStackBlock(this.workspace); - var xml = Blockly.Xml.textToDom( - '' - ); - parent.nextConnection.setShadowDom(xml); - assertNextHasBlock(parent, true, '1'); - var xml = Blockly.Xml.textToDom( - '' - ); - parent.nextConnection.setShadowDom(xml); - assertNextHasBlock(parent, true, '2'); - }); - - test('Multiple Next', function() { - var parent = createStackBlock(this.workspace); - var xml = Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - '' - ); - parent.nextConnection.setShadowDom(xml); - assertNextHasBlock(parent, true, '1'); - assertNextHasBlock(parent.getNextBlock(), true, 'a'); - var xml = Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - '' - ); - parent.nextConnection.setShadowDom(xml); - assertNextHasBlock(parent, true, '2'); - assertNextHasBlock(parent.getNextBlock(), true, 'b'); - }); - }); - - suite('Remove - No Block Connected', function() { - // These are defined separately in each suite. - function createRowBlock(workspace) { - var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - '' - ), workspace); - return block; - } - - function createStatementBlock(workspace) { - var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - '' - ), workspace); - return block; - } - - function createStackBlock(workspace) { - var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - '' - ), workspace); - return block; - } - - test('Value', function() { - var parent = createRowBlock(this.workspace); - parent.getInput('INPUT').connection.setShadowDom(null); - assertInputNotHasBlock(parent, 'INPUT'); - }); - - test('Statement', function() { - var parent = createStatementBlock(this.workspace); - parent.getInput('STATEMENT').connection.setShadowDom(null); - assertInputNotHasBlock(parent, 'STATMENT'); - }); - - test('Next', function() { - var parent = createStackBlock(this.workspace); - parent.nextConnection.setShadowDom(null); - assertNextNotHasBlock(parent); - }); - }); - - suite('Remove - Block Connected', function() { - // These are defined separately in each suite. - function createRowBlock(workspace) { - var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - ' ' + - '' - ), workspace); - return block; - } - - function createStatementBlock(workspace) { - var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - ' ' + - '' - ), workspace); - return block; - } - - function createStackBlock(workspace) { - var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - ' ' + - '' - ), workspace); - return block; - } - - test('Value', function() { - var parent = createRowBlock(this.workspace); - parent.getInput('INPUT').connection.setShadowDom(null); - assertInputHasBlock(parent, 'INPUT', false); - parent.getInput('INPUT').connection.disconnect(); - assertInputNotHasBlock(parent, 'INPUT'); - }); - - test('Statement', function() { - var parent = createStatementBlock(this.workspace); - parent.getInput('STATEMENT').connection.setShadowDom(null); - assertInputHasBlock(parent, 'STATEMENT', false); - parent.getInput('STATEMENT').connection.disconnect(); - assertInputNotHasBlock(parent, 'STATEMENT'); - }); - - test('Next', function() { - var parent = createStackBlock(this.workspace); - parent.nextConnection.setShadowDom(null); - assertNextHasBlock(parent, false); - parent.nextConnection.disconnect(); - assertNextNotHasBlock(parent); - }); - }); - - suite('Add - Connect & Disconnect - Remove', function() { - // These are defined separately in each suite. - function createRowBlock(workspace) { - var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( - '' - ), workspace); - return block; - } - - function createStatementBlock(workspace) { - var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( - '' - ), workspace); - return block; - } - - function createStackBlock(workspace) { - var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( - '' - ), workspace); - return block; - } - - test('Value', function() { - var parent = createRowBlock(this.workspace); - var xml = Blockly.Xml.textToDom( - '' - ); - parent.getInput('INPUT').connection.setShadowDom(xml); - assertInputHasBlock(parent, 'INPUT', true); - var child = createRowBlock(this.workspace); - parent.getInput('INPUT').connection.connect(child.outputConnection); - assertInputHasBlock(parent, 'INPUT', false); - parent.getInput('INPUT').connection.disconnect(); - assertInputHasBlock(parent, 'INPUT', true); - parent.getInput('INPUT').connection.setShadowDom(null); - assertInputNotHasBlock(parent, 'INPUT'); - }); - - test('Multiple Value', function() { - var parent = createRowBlock(this.workspace); - var xml = Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - '' - ); - parent.getInput('INPUT').connection.setShadowDom(xml); - assertInputHasBlock(parent, 'INPUT', true); - assertInputHasBlock( - parent.getInputTargetBlock('INPUT'), 'INPUT', true); - var child = createRowBlock(this.workspace); - parent.getInput('INPUT').connection.connect(child.outputConnection); - assertInputHasBlock(parent, 'INPUT', false); - parent.getInput('INPUT').connection.disconnect(); - assertInputHasBlock(parent, 'INPUT', true); - assertInputHasBlock( - parent.getInputTargetBlock('INPUT'), 'INPUT', true); - parent.getInput('INPUT').connection.setShadowDom(null); - assertInputNotHasBlock(parent, 'INPUT'); - }); - - test('Statement', function() { - var parent = createStatementBlock(this.workspace); - var xml = Blockly.Xml.textToDom( - '' - ); - parent.getInput('STATEMENT').connection.setShadowDom(xml); - assertInputHasBlock(parent, 'STATEMENT', true); - var child = createStatementBlock(this.workspace); - parent.getInput('STATEMENT').connection - .connect(child.previousConnection); - assertInputHasBlock(parent, 'STATEMENT', false); - parent.getInput('STATEMENT').connection.disconnect(); - assertInputHasBlock(parent, 'STATEMENT', true); - parent.getInput('STATEMENT').connection.setShadowDom(null); - assertInputNotHasBlock(parent, 'STATEMENT'); - }); - - test('Multiple Statement', function() { - var parent = createStatementBlock(this.workspace); - var xml = Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - '' - ); - parent.getInput('STATEMENT').connection.setShadowDom(xml); - assertInputHasBlock(parent, 'STATEMENT', true); - assertInputHasBlock( - parent.getInputTargetBlock('STATEMENT'), 'STATEMENT', true); - var child = createStatementBlock(this.workspace); - parent.getInput('STATEMENT').connection - .connect(child.previousConnection); - assertInputHasBlock(parent, 'STATEMENT', false); - parent.getInput('STATEMENT').connection.disconnect(); - assertInputHasBlock(parent, 'STATEMENT', true); - assertInputHasBlock( - parent.getInputTargetBlock('STATEMENT'), 'STATEMENT', true); - parent.getInput('STATEMENT').connection.setShadowDom(null); - assertInputNotHasBlock(parent, 'STATEMENT'); - }); - - test('Next', function() { - var parent = createStackBlock(this.workspace); - var xml = Blockly.Xml.textToDom( - '' - ); - parent.nextConnection.setShadowDom(xml); - assertNextHasBlock(parent, true); - var child = createStatementBlock(this.workspace); - parent.nextConnection.connect(child.previousConnection); - assertNextHasBlock(parent, false); - parent.nextConnection.disconnect(); - assertNextHasBlock(parent, true); - parent.nextConnection.setShadowDom(null); - assertNextNotHasBlock(parent); - }); - - test('Multiple Next', function() { - var parent = createStackBlock(this.workspace); - var xml = Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - '' - ); - parent.nextConnection.setShadowDom(xml); - assertNextHasBlock(parent, true); - assertNextHasBlock(parent.getNextBlock(), true); - var child = createStatementBlock(this.workspace); - parent.nextConnection.connect(child.previousConnection); - assertNextHasBlock(parent, false); - parent.nextConnection.disconnect(); - assertNextHasBlock(parent, true); - assertNextHasBlock(parent.getNextBlock(), true); - parent.nextConnection.setShadowDom(null); - assertNextNotHasBlock(parent); + test('Invalid connection checks, previous', function() { + Blockly.defineBlocksWithJsonArray([{ + "type": "stack_checks_block", + "message0": "", + "previousStatement": "check 1", + "nextStatement": "check 2" + }]); + const block = this.workspace.newBlock('stack_checks_block'); + chai.assert.throws(() => + block.nextConnection.setShadowState( + {'type': 'stack_checks_block'})); + }); }); }); }); @@ -907,7 +2742,7 @@ suite('Connection', function() { }, { "type": "input_statement", - "name": "STATEMENT", + "name": "NAME", "check": 'check1' } ], @@ -920,7 +2755,7 @@ suite('Connection', function() { "args0": [ { "type": "input_statement", - "name": "STATEMENT", + "name": "NAME", "check": 'check1' } ], @@ -933,7 +2768,7 @@ suite('Connection', function() { "args0": [ { "type": "input_statement", - "name": "STATEMENT", + "name": "NAME", "check": 'check2' } ], @@ -946,7 +2781,7 @@ suite('Connection', function() { "args0": [ { "type": "input_statement", - "name": "STATEMENT", + "name": "NAME", "check": 'check1' } ], @@ -979,13 +2814,13 @@ suite('Connection', function() { var newParent = this.workspace.newBlock('statement_block'); var child = this.workspace.newBlock('stack_block'); - oldParent.getInput('STATEMENT').connection + oldParent.getInput('NAME').connection .connect(child.previousConnection); - newParent.getInput('STATEMENT').connection + newParent.getInput('NAME').connection .connect(child.previousConnection); chai.assert.isFalse( - oldParent.getInput('STATEMENT').connection.isConnected()); + oldParent.getInput('NAME').connection.isConnected()); this.assertBlockCount(3); }); @@ -1024,15 +2859,15 @@ suite('Connection', function() { var xml = Blockly.Xml.textToDom( '' ); - newParent.getInput('STATEMENT').connection.setShadowDom(xml); + newParent.getInput('NAME').connection.setShadowDom(xml); chai.assert.isTrue( - newParent.getInputTargetBlock('STATEMENT').isShadow()); + newParent.getInputTargetBlock('NAME').isShadow()); - newParent.getInput('STATEMENT').connection + newParent.getInput('NAME').connection .connect(child.previousConnection); chai.assert.isFalse( - newParent.getInputTargetBlock('STATEMENT').isShadow()); + newParent.getInputTargetBlock('NAME').isShadow()); this.assertBlockCount(2); }); @@ -1077,15 +2912,15 @@ suite('Connection', function() { var xml = Blockly.Xml.textToDom( '' ); - newParent.getInput('STATEMENT').connection.setShadowDom(xml); - newParent.getInputTargetBlock('STATEMENT') + newParent.getInput('NAME').connection.setShadowDom(xml); + newParent.getInputTargetBlock('NAME') .setFieldValue('new', 'FIELD'); - newParent.getInput('STATEMENT').connection + newParent.getInput('NAME').connection .connect(child.previousConnection); - newParent.getInput('STATEMENT').connection.disconnect(); + newParent.getInput('NAME').connection.disconnect(); - const target = newParent.getInputTargetBlock('STATEMENT'); + const target = newParent.getInputTargetBlock('NAME'); chai.assert.isTrue(target.isShadow()); chai.assert.equal(target.getFieldValue('FIELD'), 'new'); this.assertBlockCount(3); @@ -1403,16 +3238,16 @@ suite('Connection', function() { var parent = this.workspace.newBlock('statement_block'); var oldChild = this.workspace.newBlock('stack_block'); var newChild = this.workspace.newBlock('stack_block'); - parent.getInput('STATEMENT').connection + parent.getInput('NAME').connection .connect(oldChild.previousConnection); - parent.getInput('STATEMENT').connection + parent.getInput('NAME').connection .connect(newChild.previousConnection); chai.assert.isTrue( - parent.getInput('STATEMENT').connection.isConnected()); + parent.getInput('NAME').connection.isConnected()); chai.assert.equal( - parent.getInputTargetBlock('STATEMENT'), newChild); + parent.getInputTargetBlock('NAME'), newChild); chai.assert.isTrue(newChild.nextConnection.isConnected()); chai.assert.equal(newChild.getNextBlock(), oldChild); this.assertBlockCount(3); @@ -1423,17 +3258,17 @@ suite('Connection', function() { var oldChild = this.workspace.newBlock('stack_block'); var newChild1 = this.workspace.newBlock('stack_block_1to2'); var newChild2 = this.workspace.newBlock('stack_block_2to1'); - parent.getInput('STATEMENT').connection + parent.getInput('NAME').connection .connect(oldChild.previousConnection); newChild1.nextConnection.connect(newChild2.previousConnection); - parent.getInput('STATEMENT').connection + parent.getInput('NAME').connection .connect(newChild1.previousConnection); chai.assert.isTrue( - parent.getInput('STATEMENT').connection.isConnected()); + parent.getInput('NAME').connection.isConnected()); chai.assert.equal( - parent.getInputTargetBlock('STATEMENT'), newChild1); + parent.getInputTargetBlock('NAME'), newChild1); chai.assert.isTrue(newChild2.nextConnection.isConnected()); chai.assert.equal(newChild2.getNextBlock(), oldChild); this.assertBlockCount(4); @@ -1443,17 +3278,17 @@ suite('Connection', function() { var parent = this.workspace.newBlock('statement_block'); var oldChild = this.workspace.newBlock('stack_block'); var newChild = this.workspace.newBlock('stack_block_1to2'); - parent.getInput('STATEMENT').connection + parent.getInput('NAME').connection .connect(oldChild.previousConnection); var spy = sinon.spy(oldChild.previousConnection, 'onFailedConnect'); - parent.getInput('STATEMENT').connection + parent.getInput('NAME').connection .connect(newChild.previousConnection); chai.assert.isTrue( - parent.getInput('STATEMENT').connection.isConnected()); + parent.getInput('NAME').connection.isConnected()); chai.assert.equal( - parent.getInputTargetBlock('STATEMENT'), newChild); + parent.getInputTargetBlock('NAME'), newChild); chai.assert.isFalse(newChild.nextConnection.isConnected()); chai.assert.isTrue(spy.calledOnce); this.assertBlockCount(3); @@ -1463,17 +3298,17 @@ suite('Connection', function() { var parent = this.workspace.newBlock('statement_block'); var oldChild = this.workspace.newBlock('stack_block'); var newChild = this.workspace.newBlock('stack_block_noend'); - parent.getInput('STATEMENT').connection + parent.getInput('NAME').connection .connect(oldChild.previousConnection); var spy = sinon.spy(oldChild.previousConnection, 'onFailedConnect'); - parent.getInput('STATEMENT').connection + parent.getInput('NAME').connection .connect(newChild.previousConnection); chai.assert.isTrue( - parent.getInput('STATEMENT').connection.isConnected()); + parent.getInput('NAME').connection.isConnected()); chai.assert.equal( - parent.getInputTargetBlock('STATEMENT'), newChild); + parent.getInputTargetBlock('NAME'), newChild); chai.assert.isTrue(spy.calledOnce); this.assertBlockCount(3); }); @@ -1484,20 +3319,20 @@ suite('Connection', function() { var parent = this.workspace.newBlock('statement_block'); var oldChild = this.workspace.newBlock('stack_block'); var newChild = this.workspace.newBlock('stack_block'); - parent.getInput('STATEMENT').connection + parent.getInput('NAME').connection .connect(oldChild.previousConnection); var xml = Blockly.Xml.textToDom( '' ); newChild.nextConnection.setShadowDom(xml); - parent.getInput('STATEMENT').connection + parent.getInput('NAME').connection .connect(newChild.previousConnection); chai.assert.isTrue( - parent.getInput('STATEMENT').connection.isConnected()); + parent.getInput('NAME').connection.isConnected()); chai.assert.equal( - parent.getInputTargetBlock('STATEMENT'), newChild); + parent.getInputTargetBlock('NAME'), newChild); chai.assert.isTrue(newChild.nextConnection.isConnected()); chai.assert.equal(newChild.getNextBlock(), oldChild); this.assertBlockCount(3); @@ -1508,7 +3343,7 @@ suite('Connection', function() { var oldChild = this.workspace.newBlock('stack_block'); var newChild1 = this.workspace.newBlock('stack_block_1to2'); var newChild2 = this.workspace.newBlock('stack_block_2to1'); - parent.getInput('STATEMENT').connection + parent.getInput('NAME').connection .connect(oldChild.previousConnection); newChild1.nextConnection.connect(newChild2.previousConnection); var xml = Blockly.Xml.textToDom( @@ -1516,13 +3351,13 @@ suite('Connection', function() { ); newChild2.nextConnection.setShadowDom(xml); - parent.getInput('STATEMENT').connection + parent.getInput('NAME').connection .connect(newChild1.previousConnection); chai.assert.isTrue( - parent.getInput('STATEMENT').connection.isConnected()); + parent.getInput('NAME').connection.isConnected()); chai.assert.equal( - parent.getInputTargetBlock('STATEMENT'), newChild1); + parent.getInputTargetBlock('NAME'), newChild1); chai.assert.isTrue(newChild2.nextConnection.isConnected()); chai.assert.equal(newChild2.getNextBlock(), oldChild); this.assertBlockCount(4); @@ -1532,7 +3367,7 @@ suite('Connection', function() { var parent = this.workspace.newBlock('statement_block'); var oldChild = this.workspace.newBlock('stack_block'); var newChild = this.workspace.newBlock('stack_block_1to2'); - parent.getInput('STATEMENT').connection + parent.getInput('NAME').connection .connect(oldChild.previousConnection); var xml = Blockly.Xml.textToDom( '' @@ -1540,13 +3375,13 @@ suite('Connection', function() { newChild.nextConnection.setShadowDom(xml); var spy = sinon.spy(oldChild.previousConnection, 'onFailedConnect'); - parent.getInput('STATEMENT').connection + parent.getInput('NAME').connection .connect(newChild.previousConnection); chai.assert.isTrue( - parent.getInput('STATEMENT').connection.isConnected()); + parent.getInput('NAME').connection.isConnected()); chai.assert.equal( - parent.getInputTargetBlock('STATEMENT'), newChild); + parent.getInputTargetBlock('NAME'), newChild); chai.assert.isTrue(newChild.nextConnection.isConnected()); chai.assert.isTrue(newChild.getNextBlock().isShadow()); chai.assert.isTrue(spy.calledOnce); diff --git a/tests/mocha/contextmenu_items_test.js b/tests/mocha/contextmenu_items_test.js index 62dd6f9ea..fd4a39d90 100644 --- a/tests/mocha/contextmenu_items_test.js +++ b/tests/mocha/contextmenu_items_test.js @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.contextMenuItem'); + +const {sharedTestSetup, sharedTestTeardown, workspaceTeardown} = goog.require('Blockly.test.helpers'); + + suite('Context Menu Items', function() { setup(function() { sharedTestSetup.call(this); @@ -17,11 +22,11 @@ suite('Context Menu Items', function() { Blockly.ContextMenuItems.registerDefaultOptions(); this.registry = Blockly.ContextMenuRegistry.registry; }); - + teardown(function() { sharedTestTeardown.call(this); }); - + suite('Workspace Items', function() { setup(function() { this.scope = {workspace: this.workspace}; @@ -255,7 +260,8 @@ suite('Context Menu Items', function() { test('Deletes all blocks after confirming', function() { // Mocks the confirmation dialog and calls the callback with 'true' simulating ok. - var confirmStub = sinon.stub(Blockly, 'confirm').callsArgWith(1, true); + var confirmStub = sinon.stub( + Blockly.dialog, 'confirm').callsArgWith(1, true); this.workspace.newBlock('text'); this.workspace.newBlock('text'); @@ -267,7 +273,8 @@ suite('Context Menu Items', function() { test('Does not delete blocks if not confirmed', function() { // Mocks the confirmation dialog and calls the callback with 'false' simulating cancel. - var confirmStub = sinon.stub(Blockly, 'confirm').callsArgWith(1, false); + var confirmStub = sinon.stub( + Blockly.dialog, 'confirm').callsArgWith(1, false); this.workspace.newBlock('text'); this.workspace.newBlock('text'); @@ -278,7 +285,7 @@ suite('Context Menu Items', function() { }); test('No dialog for single block', function() { - var confirmStub = sinon.stub(Blockly, 'confirm'); + var confirmStub = sinon.stub(Blockly.dialog, 'confirm'); this.workspace.newBlock('text'); this.deleteOption.callback(this.scope); this.clock.runAll(); @@ -328,12 +335,12 @@ suite('Context Menu Items', function() { }); test('Calls duplicate', function() { - var stub = sinon.stub(Blockly, 'duplicate'); + var spy = sinon.spy(Blockly.clipboard, 'duplicate'); this.duplicateOption.callback(this.scope); - sinon.assert.calledOnce(stub); - sinon.assert.calledWith(stub, this.block); + sinon.assert.calledOnce(spy); + sinon.assert.calledWith(spy, this.block); }); test('Has correct label', function() { diff --git a/tests/mocha/cursor_test.js b/tests/mocha/cursor_test.js index f689526f2..fe6273163 100644 --- a/tests/mocha/cursor_test.js +++ b/tests/mocha/cursor_test.js @@ -4,6 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.cursor'); + +const {sharedTestSetup, sharedTestTeardown} = goog.require('Blockly.test.helpers'); +const {ASTNode} = goog.require('Blockly.ASTNode'); + + suite('Cursor', function() { setup(function() { sharedTestSetup.call(this); @@ -77,14 +83,14 @@ suite('Cursor', function() { }); test('Next - From a Previous skip over next connection and block', function() { - var prevNode = Blockly.ASTNode.createConnectionNode(this.blocks.A.previousConnection); + var prevNode = ASTNode.createConnectionNode(this.blocks.A.previousConnection); this.cursor.setCurNode(prevNode); this.cursor.next(); var curNode = this.cursor.getCurNode(); chai.assert.equal(curNode.getLocation(), this.blocks.B.previousConnection); }); test('Next - From last block in a stack go to next connection', function() { - var prevNode = Blockly.ASTNode.createConnectionNode(this.blocks.B.previousConnection); + var prevNode = ASTNode.createConnectionNode(this.blocks.B.previousConnection); this.cursor.setCurNode(prevNode); this.cursor.next(); var curNode = this.cursor.getCurNode(); @@ -93,7 +99,7 @@ suite('Cursor', function() { test('In - From output connection', function() { var fieldBlock = this.blocks.E; - var outputNode = Blockly.ASTNode.createConnectionNode(fieldBlock.outputConnection); + var outputNode = ASTNode.createConnectionNode(fieldBlock.outputConnection); this.cursor.setCurNode(outputNode); this.cursor.in(); var curNode = this.cursor.getCurNode(); @@ -102,7 +108,7 @@ suite('Cursor', function() { test('Prev - From previous connection skip over next connection', function() { var prevConnection = this.blocks.B.previousConnection; - var prevConnectionNode = Blockly.ASTNode.createConnectionNode(prevConnection); + var prevConnectionNode = ASTNode.createConnectionNode(prevConnection); this.cursor.setCurNode(prevConnectionNode); this.cursor.prev(); var curNode = this.cursor.getCurNode(); @@ -111,7 +117,7 @@ suite('Cursor', function() { test('Out - From field skip over block node', function() { var field = this.blocks.E.inputList[0].fieldRow[0]; - var fieldNode = Blockly.ASTNode.createFieldNode(field); + var fieldNode = ASTNode.createFieldNode(field); this.cursor.setCurNode(fieldNode); this.cursor.out(); var curNode = this.cursor.getCurNode(); diff --git a/tests/mocha/dropdowndiv_test.js b/tests/mocha/dropdowndiv_test.js index c51c83dea..75027a82b 100644 --- a/tests/mocha/dropdowndiv_test.js +++ b/tests/mocha/dropdowndiv_test.js @@ -4,11 +4,16 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.dropdown'); + +const {sharedTestSetup, sharedTestTeardown} = goog.require('Blockly.test.helpers'); + + suite('DropDownDiv', function() { suite('Positioning', function() { setup(function() { sharedTestSetup.call(this); - this.boundsStub = sinon.stub(Blockly.DropDownDiv, 'getBoundsInfo_') + this.boundsStub = sinon.stub(Blockly.DropDownDiv.TEST_ONLY, 'getBoundsInfo') .returns({ left: 0, right: 100, @@ -31,7 +36,7 @@ suite('DropDownDiv', function() { sharedTestTeardown.call(this); }); test('Below, in Bounds', function() { - var metrics = Blockly.DropDownDiv.getPositionMetrics_(50, 0, 50, -10); + var metrics = Blockly.DropDownDiv.TEST_ONLY.getPositionMetrics(50, 0, 50, -10); // "Above" in value actually means below in render. chai.assert.isAtLeast(metrics.initialY, 0); chai.assert.isAbove(metrics.finalY, 0); @@ -39,7 +44,7 @@ suite('DropDownDiv', function() { chai.assert.isTrue(metrics.arrowAtTop); }); test('Above, in Bounds', function() { - var metrics = Blockly.DropDownDiv.getPositionMetrics_(50, 100, 50, 90); + var metrics = Blockly.DropDownDiv.TEST_ONLY.getPositionMetrics(50, 100, 50, 90); // "Below" in value actually means above in render. chai.assert.isAtMost(metrics.initialY, 100); chai.assert.isBelow(metrics.finalY, 100); @@ -47,7 +52,7 @@ suite('DropDownDiv', function() { chai.assert.isFalse(metrics.arrowAtTop); }); test('Below, out of Bounds', function() { - var metrics = Blockly.DropDownDiv.getPositionMetrics_(50, 60, 50, 50); + var metrics = Blockly.DropDownDiv.TEST_ONLY.getPositionMetrics(50, 60, 50, 50); // "Above" in value actually means below in render. chai.assert.isAtLeast(metrics.initialY, 60); chai.assert.isAbove(metrics.finalY, 60); @@ -55,7 +60,7 @@ suite('DropDownDiv', function() { chai.assert.isTrue(metrics.arrowAtTop); }); test('Above, in Bounds', function() { - var metrics = Blockly.DropDownDiv.getPositionMetrics_(50, 100, 50, 90); + var metrics = Blockly.DropDownDiv.TEST_ONLY.getPositionMetrics(50, 100, 50, 90); // "Below" in value actually means above in render. chai.assert.isAtMost(metrics.initialY, 100); chai.assert.isBelow(metrics.finalY, 100); @@ -64,7 +69,7 @@ suite('DropDownDiv', function() { }); test('No Solution, Render At Top', function() { this.clientHeightStub.get(function() { return 100; }); - var metrics = Blockly.DropDownDiv.getPositionMetrics_(50, 60, 50, 50); + var metrics = Blockly.DropDownDiv.TEST_ONLY.getPositionMetrics(50, 60, 50, 50); // "Above" in value actually means below in render. chai.assert.equal(metrics.initialY, 0); chai.assert.equal(metrics.finalY, 0); diff --git a/tests/mocha/event_test.js b/tests/mocha/event_test.js index 81ab69519..26f1f29f0 100644 --- a/tests/mocha/event_test.js +++ b/tests/mocha/event_test.js @@ -4,12 +4,18 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.event'); + +const eventUtils = goog.require('Blockly.Events.utils'); +const {assertEventEquals, assertNthCallEventArgEquals, assertVariableValues, createFireChangeListenerSpy, createGenUidStubWithReturns, sharedTestSetup, sharedTestTeardown, workspaceTeardown} = goog.require('Blockly.test.helpers'); +const {ASTNode} = goog.require('Blockly.ASTNode'); goog.require('Blockly.WorkspaceComment'); + suite('Events', function() { setup(function() { sharedTestSetup.call(this, {fireEventsNow: false}); - this.eventsFireSpy = sinon.spy(Blockly.Events, 'fire'); + this.eventsFireSpy = sinon.spy(eventUtils, 'fire'); this.workspace = new Blockly.Workspace(); Blockly.defineBlocksWithJsonArray([{ 'type': 'field_variable_test_block', @@ -36,15 +42,15 @@ suite('Events', function() { // Disable events while constructing the block: this is a test of the // Blockly.Event constructors, not the block constructors. // Set the group id to avoid an extra call to genUid. - Blockly.Events.disable(); + eventUtils.disable(); try { - Blockly.Events.setGroup('unused'); + eventUtils.setGroup('unused'); var block = new Blockly.Block( workspace, 'simple_test_block'); } finally { - Blockly.Events.setGroup(false); + eventUtils.setGroup(false); } - Blockly.Events.enable(); + eventUtils.enable(); return block; } @@ -76,7 +82,7 @@ suite('Events', function() { test('Old UI event without block', function() { var TEST_GROUP_ID = 'testGroup'; - Blockly.Events.setGroup(TEST_GROUP_ID); + eventUtils.setGroup(TEST_GROUP_ID); var event = new Blockly.Events.Ui(null, 'foo', 'bar', 'baz'); assertEventEquals(event, Blockly.Events.UI, '', null, { 'element': 'foo', @@ -109,32 +115,10 @@ suite('Events', function() { }); }); - test('Create', function() { - var event = new Blockly.Events.Create(this.block); - sinon.assert.calledOnce(this.genUidStub); - assertEventEquals(event, Blockly.Events.CREATE, - this.workspace.id, this.TEST_BLOCK_ID, - { - 'recordUndo': true, - 'group': '', - }); - }); - test('Block create', function() { var event = new Blockly.Events.BlockCreate(this.block); sinon.assert.calledOnce(this.genUidStub); - assertEventEquals(event, Blockly.Events.CREATE, - this.workspace.id, this.TEST_BLOCK_ID, - { - 'recordUndo': true, - 'group': '', - }); - }); - - test('Delete', function() { - var event = new Blockly.Events.Delete(this.block); - sinon.assert.calledOnce(this.genUidStub); - assertEventEquals(event, Blockly.Events.DELETE, + assertEventEquals(event, Blockly.Events.BLOCK_CREATE, this.workspace.id, this.TEST_BLOCK_ID, { 'recordUndo': true, @@ -145,7 +129,7 @@ suite('Events', function() { test('Block delete', function() { var event = new Blockly.Events.BlockDelete(this.block); sinon.assert.calledOnce(this.genUidStub); - assertEventEquals(event, Blockly.Events.DELETE, + assertEventEquals(event, Blockly.Events.BLOCK_DELETE, this.workspace.id, this.TEST_BLOCK_ID, { 'recordUndo': true, @@ -155,7 +139,7 @@ suite('Events', function() { test('Old UI event with block', function() { var TEST_GROUP_ID = 'testGroup'; - Blockly.Events.setGroup(TEST_GROUP_ID); + eventUtils.setGroup(TEST_GROUP_ID); var event = new Blockly.Events.Ui(this.block, 'foo', 'bar', 'baz'); sinon.assert.calledOnce(this.genUidStub); assertEventEquals(event, Blockly.Events.UI, this.workspace.id, @@ -171,7 +155,7 @@ suite('Events', function() { test('Click with block', function() { var TEST_GROUP_ID = 'testGroup'; - Blockly.Events.setGroup(TEST_GROUP_ID); + eventUtils.setGroup(TEST_GROUP_ID); var event = new Blockly.Events.Click(this.block, null, 'block'); assertEventEquals(event, Blockly.Events.CLICK, this.workspace.id, this.TEST_BLOCK_ID, { @@ -181,30 +165,14 @@ suite('Events', function() { }, true); }); - suite('Move', function() { - test('Move by coordinate', function() { - var coordinate = new Blockly.utils.Coordinate(3, 4); - this.block.xy_ = coordinate; - - var event = new Blockly.Events.Move(this.block); - sinon.assert.calledOnce(this.genUidStub); - assertEventEquals(event, Blockly.Events.MOVE, this.workspace.id, - this.TEST_BLOCK_ID, { - 'oldParentId': undefined, - 'oldInputName': undefined, - 'oldCoordinate': coordinate, - 'recordUndo': true, - 'group': '' - }); - }); - - test('Block move by coordinate', function() { + suite('Block Move', function() { + test('by coordinate', function() { var coordinate = new Blockly.utils.Coordinate(3, 4); this.block.xy_ = coordinate; var event = new Blockly.Events.BlockMove(this.block); sinon.assert.calledOnce(this.genUidStub); - assertEventEquals(event, Blockly.Events.MOVE, this.workspace.id, + assertEventEquals(event, Blockly.Events.BLOCK_MOVE, this.workspace.id, this.TEST_BLOCK_ID, { 'oldParentId': undefined, 'oldInputName': undefined, @@ -214,22 +182,14 @@ suite('Events', function() { }); }); - suite('Move by parent', function() { - setup(function() { + test('by parent', function() { + try { this.parentBlock = createSimpleTestBlock(this.workspace); - this.block.parentBlock_ = this.parentBlock; this.block.xy_ = new Blockly.utils.Coordinate(3, 4); - }); - teardown(function() { - // This needs to be cleared, otherwise workspace.dispose will fail. - this.block.parentBlock_ = null; - }); - - test('Move by parent', function() { - var event = new Blockly.Events.Move(this.block); + var event = new Blockly.Events.BlockMove(this.block); sinon.assert.calledTwice(this.genUidStub); - assertEventEquals(event, Blockly.Events.MOVE, this.workspace.id, + assertEventEquals(event, Blockly.Events.BLOCK_MOVE, this.workspace.id, this.TEST_BLOCK_ID, { 'oldParentId': this.TEST_PARENT_ID, 'oldInputName': undefined, @@ -237,21 +197,10 @@ suite('Events', function() { 'recordUndo': true, 'group': '' }); - }); - - test('Block move by parent', function() { - var event = new Blockly.Events.BlockMove(this.block); - sinon.assert.calledTwice(this.genUidStub); - assertEventEquals(event, Blockly.Events.MOVE, this.workspace.id, - this.TEST_BLOCK_ID, - { - 'oldParentId': this.TEST_PARENT_ID, - 'oldInputName': undefined, - 'oldCoordinate': undefined, - 'recordUndo': true, - 'group': '' - }); - }); + } finally { + // This needs to be cleared, otherwise workspace.dispose will fail. + this.block.parentBlock_ = null; + } }); }); }); @@ -279,28 +228,11 @@ suite('Events', function() { }); }); - test('Change', function() { - var event = new Blockly.Events.Change( - this.block, 'field', 'FIELD_NAME', 'old', 'new'); - sinon.assert.calledOnce(this.genUidStub); - assertEventEquals(event, Blockly.Events.CHANGE, - this.workspace.id, this.TEST_BLOCK_ID, - { - 'varId': undefined, - 'element': 'field', - 'name': 'FIELD_NAME', - 'oldValue': 'old', - 'newValue': 'new', - 'recordUndo': true, - 'group': '', - }); - }); - test('Block change', function() { var event = new Blockly.Events.BlockChange( this.block, 'field', 'FIELD_NAME', 'old', 'new'); sinon.assert.calledOnce(this.genUidStub); - assertEventEquals(event, Blockly.Events.CHANGE, + assertEventEquals(event, Blockly.Events.BLOCK_CHANGE, this.workspace.id, this.TEST_BLOCK_ID, { 'varId': undefined, @@ -313,32 +245,10 @@ suite('Events', function() { }); }); - test('Create', function() { - var event = new Blockly.Events.Create(this.block); - sinon.assert.calledOnce(this.genUidStub); - assertEventEquals(event, Blockly.Events.CREATE, - this.workspace.id, this.TEST_BLOCK_ID, - { - 'recordUndo': false, - 'group': '', - }); - }); - test('Block create', function() { var event = new Blockly.Events.BlockCreate(this.block); sinon.assert.calledOnce(this.genUidStub); - assertEventEquals(event, Blockly.Events.CREATE, - this.workspace.id, this.TEST_BLOCK_ID, - { - 'recordUndo': false, - 'group': '', - }); - }); - - test('Delete', function() { - var event = new Blockly.Events.Delete(this.block); - sinon.assert.calledOnce(this.genUidStub); - assertEventEquals(event, Blockly.Events.DELETE, + assertEventEquals(event, Blockly.Events.BLOCK_CREATE, this.workspace.id, this.TEST_BLOCK_ID, { 'recordUndo': false, @@ -349,7 +259,7 @@ suite('Events', function() { test('Block delete', function() { var event = new Blockly.Events.BlockDelete(this.block); sinon.assert.calledOnce(this.genUidStub); - assertEventEquals(event, Blockly.Events.DELETE, + assertEventEquals(event, Blockly.Events.BLOCK_DELETE, this.workspace.id, this.TEST_BLOCK_ID, { 'recordUndo': false, @@ -357,35 +267,14 @@ suite('Events', function() { }); }); - suite('Move', function() { - setup(function() { + test('Block move', function() { + try { this.parentBlock = createSimpleTestBlock(this.workspace); this.block.parentBlock_ = this.parentBlock; this.block.xy_ = new Blockly.utils.Coordinate(3, 4); - }); - - teardown(function() { - // This needs to be cleared, otherwise workspace.dispose will fail. - this.block.parentBlock_ = null; - }); - - test('Move', function() { - var event = new Blockly.Events.Move(this.block); - sinon.assert.calledTwice(this.genUidStub); - assertEventEquals(event, Blockly.Events.MOVE, this.workspace.id, - this.TEST_BLOCK_ID, { - 'oldParentId': this.TEST_PARENT_ID, - 'oldInputName': undefined, - 'oldCoordinate': undefined, - 'recordUndo': false, - 'group': '' - }); - }); - - test('Block move', function() { var event = new Blockly.Events.BlockMove(this.block); sinon.assert.calledTwice(this.genUidStub); - assertEventEquals(event, Blockly.Events.MOVE, this.workspace.id, + assertEventEquals(event, Blockly.Events.BLOCK_MOVE, this.workspace.id, this.TEST_BLOCK_ID, { 'oldParentId': this.TEST_PARENT_ID, @@ -394,7 +283,10 @@ suite('Events', function() { 'recordUndo': false, 'group': '' }); - }); + } finally { + // This needs to be cleared, otherwise workspace.dispose will fail. + this.block.parentBlock_ = null; + } }); }); @@ -408,25 +300,10 @@ suite('Events', function() { this.workspace, 'field_variable_test_block'); }); - test('Change', function() { - var event = new Blockly.Events.Change( - this.block, 'field', 'VAR', 'id1', 'id2'); - assertEventEquals(event, Blockly.Events.CHANGE, this.workspace.id, - this.TEST_BLOCK_ID, - { - 'element': 'field', - 'name': 'VAR', - 'oldValue': 'id1', - 'newValue': 'id2', - 'recordUndo': true, - 'group': '' - }); - }); - test('Block change', function() { var event = new Blockly.Events.BlockChange( this.block, 'field', 'VAR', 'id1', 'id2'); - assertEventEquals(event, Blockly.Events.CHANGE, this.workspace.id, + assertEventEquals(event, Blockly.Events.BLOCK_CHANGE, this.workspace.id, this.TEST_BLOCK_ID, { 'element': 'field', @@ -492,36 +369,36 @@ suite('Events', function() { isStart: false, blockId: thisObj.block.id, blocks: [thisObj.block]})}, {title: 'null to Block Marker move', class: Blockly.Events.MarkerMove, getArgs: (thisObj) => [thisObj.block, true, null, - new Blockly.ASTNode(Blockly.ASTNode.types.BLOCK, thisObj.block)], + new ASTNode(ASTNode.types.BLOCK, thisObj.block)], getExpectedJson: (thisObj) => ({type: 'marker_move', isCursor: true, blockId: thisObj.block.id, oldNode: null, - newNode: new Blockly.ASTNode(Blockly.ASTNode.types.BLOCK, + newNode: new ASTNode(ASTNode.types.BLOCK, thisObj.block)})}, {title: 'null to Workspace Marker move', class: Blockly.Events.MarkerMove, getArgs: (thisObj) => [null, true, null, - Blockly.ASTNode.createWorkspaceNode(thisObj.workspace, + ASTNode.createWorkspaceNode(thisObj.workspace, new Blockly.utils.Coordinate(0, 0))], getExpectedJson: (thisObj) => ({type: 'marker_move', isCursor: true, blockId: null, oldNode: null, - newNode: Blockly.ASTNode.createWorkspaceNode(thisObj.workspace, + newNode: ASTNode.createWorkspaceNode(thisObj.workspace, new Blockly.utils.Coordinate(0, 0))})}, {title: 'Workspace to Block Marker move', class: Blockly.Events.MarkerMove, getArgs: (thisObj) => [thisObj.block, true, - Blockly.ASTNode.createWorkspaceNode(thisObj.workspace, + ASTNode.createWorkspaceNode(thisObj.workspace, new Blockly.utils.Coordinate(0, 0)), - new Blockly.ASTNode(Blockly.ASTNode.types.BLOCK, thisObj.block)], + new ASTNode(ASTNode.types.BLOCK, thisObj.block)], getExpectedJson: (thisObj) => ({type: 'marker_move', isCursor: true, blockId: thisObj.block.id, - oldNode: Blockly.ASTNode.createWorkspaceNode(thisObj.workspace, + oldNode: ASTNode.createWorkspaceNode(thisObj.workspace, new Blockly.utils.Coordinate(0, 0)), - newNode: new Blockly.ASTNode(Blockly.ASTNode.types.BLOCK, + newNode: new ASTNode(ASTNode.types.BLOCK, thisObj.block)})}, {title: 'Block to Workspace Marker move', class: Blockly.Events.MarkerMove, getArgs: (thisObj) => [null, true, - new Blockly.ASTNode(Blockly.ASTNode.types.BLOCK, thisObj.block), - Blockly.ASTNode.createWorkspaceNode(thisObj.workspace, + new ASTNode(ASTNode.types.BLOCK, thisObj.block), + ASTNode.createWorkspaceNode(thisObj.workspace, new Blockly.utils.Coordinate(0, 0))]}, {title: 'Selected', class: Blockly.Events.Selected, getArgs: (thisObj) => [null, thisObj.block.id, thisObj.workspace.id], @@ -562,48 +439,118 @@ suite('Events', function() { viewLeft: 0, scale: 1.2, oldScale: 1})}, ]; var blockEventTestCases = [ - {title: 'Block change', class: Blockly.Events.BlockChange, + { + title: 'Block change', + class: Blockly.Events.BlockChange, getArgs: (thisObj) => [thisObj.block, 'collapsed', null, false, true], - getExpectedJson: (thisObj) => ({type: 'change', - blockId: thisObj.block.id, element: 'collapsed', oldValue: false, - newValue: true})}, - {title: 'Block create', class: Blockly.Events.BlockCreate, + getExpectedJson: (thisObj) => ({ + type: 'change', + blockId: thisObj.block.id, + element: 'collapsed', + oldValue: false, + newValue: true + }) + }, + { + title: 'Block create', + class: Blockly.Events.BlockCreate, getArgs: (thisObj) => [thisObj.block], - getExpectedJson: (thisObj) => ({type: 'create', + getExpectedJson: (thisObj) => ({ + type: 'create', blockId: thisObj.block.id, xml: '', - ids: [thisObj.block.id]})}, - {title: 'Block create (shadow)', class: Blockly.Events.BlockCreate, + ' type="simple_test_block" id="testBlockId1" x="0" y="0">' + + '', + ids: [thisObj.block.id], + json: { + 'type': 'simple_test_block', + 'id': 'testBlockId1', + 'x': 0, + 'y': 0, + }, + }) + }, + { + title: 'Block create (shadow)', + class: Blockly.Events.BlockCreate, getArgs: (thisObj) => [thisObj.shadowBlock], - getExpectedJson: (thisObj) => ({type: 'create', + getExpectedJson: (thisObj) => ({ + type: 'create', blockId: thisObj.shadowBlock.id, xml: '', - ids: [thisObj.shadowBlock.id], recordUndo: false})}, - {title: 'Block delete', class: Blockly.Events.BlockDelete, + ' type="simple_test_block" id="testBlockId2" x="0" y="0">' + + '', + ids: [thisObj.shadowBlock.id], + json: { + 'type': 'simple_test_block', + 'id': 'testBlockId2', + 'x': 0, + 'y': 0, + }, + recordUndo: false + }) + }, + { + title: 'Block delete', + class: Blockly.Events.BlockDelete, getArgs: (thisObj) => [thisObj.block], - getExpectedJson: (thisObj) => ({type: 'delete', + getExpectedJson: (thisObj) => ({ + type: 'delete', blockId: thisObj.block.id, oldXml: '', - ids: [thisObj.block.id]})}, - {title: 'Block delete (shadow)', class: Blockly.Events.BlockDelete, + ' type="simple_test_block" id="testBlockId1" x="0" y="0">' + + '', + ids: [thisObj.block.id], + wasShadow: false, + oldJson: { + 'type': 'simple_test_block', + 'id': 'testBlockId1', + 'x': 0, + 'y': 0, + }, + }) + }, + { + title: 'Block delete (shadow)', + class: Blockly.Events.BlockDelete, getArgs: (thisObj) => [thisObj.shadowBlock], - getExpectedJson: (thisObj) => ({type: 'delete', + getExpectedJson: (thisObj) => ({ + type: 'delete', blockId: thisObj.shadowBlock.id, oldXml: '', - ids: [thisObj.shadowBlock.id], recordUndo: false})}, + ' type="simple_test_block" id="testBlockId2" x="0" y="0">' + + '', + ids: [thisObj.shadowBlock.id], + wasShadow: true, + oldJson: { + 'type': 'simple_test_block', + 'id': 'testBlockId2', + 'x': 0, + 'y': 0, + }, + recordUndo: false + }) + }, // TODO(#4577) Test serialization of move event coordinate properties. - {title: 'Block move', class: Blockly.Events.BlockMove, + { + title: 'Block move', + class: Blockly.Events.BlockMove, getArgs: (thisObj) => [thisObj.block], - getExpectedJson: (thisObj) => ({type: 'move', - blockId: thisObj.block.id})}, - {title: 'Block move (shadow)', class: Blockly.Events.BlockMove, + getExpectedJson: (thisObj) => ({ + type: 'move', + blockId: thisObj.block.id + }) + }, + { + title: 'Block move (shadow)', + class: Blockly.Events.BlockMove, getArgs: (thisObj) => [thisObj.shadowBlock], - getExpectedJson: (thisObj) => ({type: 'move', - blockId: thisObj.shadowBlock.id, recordUndo: false})}, + getExpectedJson: (thisObj) => ({ + type: 'move', + blockId: thisObj.shadowBlock.id, + recordUndo: false + }) + }, ]; var workspaceEventTestCases = [ {title: 'Finished Loading', class: Blockly.Events.FinishedLoading, @@ -770,7 +717,7 @@ suite('Events', function() { test('Var create', function() { var json = {type: "var_create", varId: "id2", varType: "type2", varName: "name2"}; - var event = Blockly.Events.fromJson(json, this.workspace); + var event = eventUtils.fromJson(json, this.workspace); var x = this.workspace.getVariableById('id2'); chai.assert.isNull(x); event.run(true); @@ -801,7 +748,7 @@ suite('Events', function() { test('Var delete', function() { var json = {type: "var_delete", varId: "id2", varType: "type2", varName: "name2"}; - var event = Blockly.Events.fromJson(json, this.workspace); + var event = eventUtils.fromJson(json, this.workspace); chai.assert.isNull(this.workspace.getVariableById('id2')); event.run(false); assertVariableValues(this.workspace, 'name2', 'type2', 'id2'); @@ -837,7 +784,7 @@ suite('Events', function() { new Blockly.Events.BlockChange(block, 'field', 'VAR', 'id1', 'id2'), new Blockly.Events.Click(block) ]; - var filteredEvents = Blockly.Events.filter(events, true); + var filteredEvents = eventUtils.filter(events, true); chai.assert.equal(filteredEvents.length, 4); // no event should have been removed. // test that the order hasn't changed chai.assert.isTrue(filteredEvents[0] instanceof Blockly.Events.BlockCreate); @@ -855,7 +802,7 @@ suite('Events', function() { new Blockly.Events.BlockCreate(block2), new Blockly.Events.BlockMove(block2) ]; - var filteredEvents = Blockly.Events.filter(events, true); + var filteredEvents = eventUtils.filter(events, true); chai.assert.equal(filteredEvents.length, 4); // no event should have been removed. }); @@ -865,7 +812,7 @@ suite('Events', function() { addMoveEvent(events, block, 1, 1); addMoveEvent(events, block, 2, 2); addMoveEvent(events, block, 3, 3); - var filteredEvents = Blockly.Events.filter(events, true); + var filteredEvents = eventUtils.filter(events, true); chai.assert.equal(filteredEvents.length, 2); // duplicate moves should have been removed. // test that the order hasn't changed chai.assert.isTrue(filteredEvents[0] instanceof Blockly.Events.BlockCreate); @@ -880,7 +827,7 @@ suite('Events', function() { addMoveEvent(events, block, 1, 1); addMoveEvent(events, block, 2, 2); addMoveEvent(events, block, 3, 3); - var filteredEvents = Blockly.Events.filter(events, false); + var filteredEvents = eventUtils.filter(events, false); chai.assert.equal(filteredEvents.length, 2); // duplicate event should have been removed. // test that the order hasn't changed chai.assert.isTrue(filteredEvents[0] instanceof Blockly.Events.BlockCreate); @@ -889,24 +836,24 @@ suite('Events', function() { chai.assert.equal(filteredEvents[1].newCoordinate.y, 1); }); - test('Merge move events', function() { + test('Merge block move events', function() { var block = this.workspace.newBlock('field_variable_test_block', '1'); var events = []; addMoveEvent(events, block, 0, 0); addMoveEvent(events, block, 1, 1); - var filteredEvents = Blockly.Events.filter(events, true); + var filteredEvents = eventUtils.filter(events, true); chai.assert.equal(filteredEvents.length, 1); // second move event merged into first chai.assert.equal(filteredEvents[0].newCoordinate.x, 1); chai.assert.equal(filteredEvents[0].newCoordinate.y, 1); }); - test('Merge change events', function() { + test('Merge block change events', function() { var block1 = this.workspace.newBlock('field_variable_test_block', '1'); var events = [ - new Blockly.Events.Change(block1, 'field', 'VAR', 'item', 'item1'), - new Blockly.Events.Change(block1, 'field', 'VAR', 'item1', 'item2') + new Blockly.Events.BlockChange(block1, 'field', 'VAR', 'item', 'item1'), + new Blockly.Events.BlockChange(block1, 'field', 'VAR', 'item1', 'item2') ]; - var filteredEvents = Blockly.Events.filter(events, true); + var filteredEvents = eventUtils.filter(events, true); chai.assert.equal(filteredEvents.length, 1); // second change event merged into first chai.assert.equal(filteredEvents[0].oldValue, 'item'); chai.assert.equal(filteredEvents[0].newValue, 'item2'); @@ -917,7 +864,7 @@ suite('Events', function() { new Blockly.Events.ViewportChange(1, 2, 3, this.workspace, 4), new Blockly.Events.ViewportChange(5, 6, 7, this.workspace, 8) ]; - var filteredEvents = Blockly.Events.filter(events, true); + var filteredEvents = eventUtils.filter(events, true); chai.assert.equal(filteredEvents.length, 1); // second change event merged into first chai.assert.equal(filteredEvents[0].viewTop, 5); chai.assert.equal(filteredEvents[0].viewLeft, 6); @@ -937,7 +884,7 @@ suite('Events', function() { new Blockly.Events.BubbleOpen(block3, true, 'warning'), new Blockly.Events.Click(block3) ]; - var filteredEvents = Blockly.Events.filter(events, true); + var filteredEvents = eventUtils.filter(events, true); // click event merged into corresponding *Open event chai.assert.equal(filteredEvents.length, 3); chai.assert.isTrue(filteredEvents[0] instanceof Blockly.Events.BubbleOpen); @@ -956,7 +903,7 @@ suite('Events', function() { new Blockly.Events.Click(block), new Blockly.Events.Ui(block, 'stackclick', undefined, undefined) ]; - var filteredEvents = Blockly.Events.filter(events, true); + var filteredEvents = eventUtils.filter(events, true); // click and stackclick should both exist chai.assert.equal(filteredEvents.length, 2); chai.assert.isTrue(filteredEvents[0] instanceof Blockly.Events.Click); @@ -976,7 +923,7 @@ suite('Events', function() { var events = []; addMoveEventParent(events, block, null); addMoveEventParent(events, block, null); - var filteredEvents = Blockly.Events.filter(events, true); + var filteredEvents = eventUtils.filter(events, true); // The two events should be merged, but because nothing has changed // they will be filtered out. chai.assert.equal(filteredEvents.length, 0); @@ -997,7 +944,7 @@ suite('Events', function() { events.push(new Blockly.Events.BlockDelete(block2)); addMoveEvent(events, block1, 2, 2); - var filteredEvents = Blockly.Events.filter(events, true); + var filteredEvents = eventUtils.filter(events, true); // Nothing should have merged. chai.assert.equal(filteredEvents.length, 4); // test that the order hasn't changed @@ -1042,11 +989,11 @@ suite('Events', function() { sinon.assert.calledTwice(genUidStub); assertNthCallEventArgEquals( - this.eventsFireSpy, 0, Blockly.Events.Delete, + this.eventsFireSpy, 0, Blockly.Events.BlockDelete, {oldXml: expectedOldXml, group: ''}, workspaceSvg.id, expectedId); assertNthCallEventArgEquals( - changeListenerSpy, 0, Blockly.Events.Delete, + changeListenerSpy, 0, Blockly.Events.BlockDelete, {oldXml: expectedOldXml, group: ''}, workspaceSvg.id, expectedId); @@ -1086,7 +1033,7 @@ suite('Events', function() { {group: TEST_GROUP_ID, varId: TEST_VAR_ID, varName: TEST_VAR_NAME}, this.workspace.id, undefined); assertNthCallEventArgEquals( - this.changeListenerSpy, 1, Blockly.Events.Create, + this.changeListenerSpy, 1, Blockly.Events.BlockCreate, {group: TEST_GROUP_ID}, this.workspace.id, TEST_BLOCK_ID); // Expect the workspace to have a variable with ID 'test_var_id'. @@ -1131,7 +1078,7 @@ suite('Events', function() { {group: TEST_GROUP_ID, varId: TEST_VAR_ID, varName: TEST_VAR_NAME}, this.workspace.id, undefined); assertNthCallEventArgEquals( - this.changeListenerSpy, 1, Blockly.Events.Create, + this.changeListenerSpy, 1, Blockly.Events.BlockCreate, {group: TEST_GROUP_ID}, this.workspace.id, TEST_BLOCK_ID); // Finished loading event should not be part of event group. @@ -1153,7 +1100,7 @@ suite('Events', function() { workspaceTeardown.call(this, this.workspace); }); test('Created orphan block is disabled', function() { - this.workspace.addChangeListener(Blockly.Events.disableOrphans); + this.workspace.addChangeListener(eventUtils.disableOrphans); var block = this.workspace.newBlock('controls_for'); block.initSvg(); block.render(); @@ -1165,7 +1112,7 @@ suite('Events', function() { 'Expected orphan block to be disabled after creation'); }); test('Created procedure block is enabled', function() { - this.workspace.addChangeListener(Blockly.Events.disableOrphans); + this.workspace.addChangeListener(eventUtils.disableOrphans); // Procedure block is never an orphan var functionBlock = this.workspace.newBlock('procedures_defnoreturn'); @@ -1179,7 +1126,7 @@ suite('Events', function() { 'Expected top-level procedure block to be enabled'); }); test('Moving a block to top-level disables it', function() { - this.workspace.addChangeListener(Blockly.Events.disableOrphans); + this.workspace.addChangeListener(eventUtils.disableOrphans); var functionBlock = this.workspace.newBlock('procedures_defnoreturn'); functionBlock.initSvg(); functionBlock.render(); @@ -1201,7 +1148,7 @@ suite('Events', function() { 'Expected disconnected block to be disabled'); }); test('Giving block a parent enables it', function() { - this.workspace.addChangeListener(Blockly.Events.disableOrphans); + this.workspace.addChangeListener(eventUtils.disableOrphans); var functionBlock = this.workspace.newBlock('procedures_defnoreturn'); functionBlock.initSvg(); functionBlock.render(); @@ -1220,7 +1167,7 @@ suite('Events', function() { 'Expected block to be enabled after connecting to parent'); }); test('disableOrphans events are not undoable', function() { - this.workspace.addChangeListener(Blockly.Events.disableOrphans); + this.workspace.addChangeListener(eventUtils.disableOrphans); var functionBlock = this.workspace.newBlock('procedures_defnoreturn'); functionBlock.initSvg(); functionBlock.render(); diff --git a/tests/mocha/extensions_test.js b/tests/mocha/extensions_test.js index 5c5cc23f5..07ff865f5 100644 --- a/tests/mocha/extensions_test.js +++ b/tests/mocha/extensions_test.js @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.extensions'); + +const {sharedTestSetup, sharedTestTeardown} = goog.require('Blockly.test.helpers'); + + suite('Extensions', function() { setup(function() { sharedTestSetup.call(this); @@ -14,7 +19,7 @@ suite('Extensions', function() { sharedTestTeardown.call(this); for (let i = 0; i < this.extensionsCleanup_.length; i++) { var extension = this.extensionsCleanup_[i]; - delete Blockly.Extensions.ALL_[extension]; + delete Blockly.Extensions.TEST_ONLY.allExtensions[extension]; } }); @@ -22,7 +27,8 @@ suite('Extensions', function() { this.extensionsCleanup_.push('extensions_test_before'); this.extensionsCleanup_.push('extensions_test_after'); - chai.assert.isUndefined(Blockly.Extensions.ALL_['extensions_test_before']); + chai.assert.isUndefined( + Blockly.Extensions.TEST_ONLY.allExtensions['extensions_test_before']); var beforeCallback = sinon.spy(); // Extension defined before the block type is defined. Blockly.Extensions.register('extensions_test_before', beforeCallback); @@ -33,13 +39,18 @@ suite('Extensions', function() { "extensions": ["extensions_test_before", "extensions_test_after"] }]); - chai.assert.isUndefined(Blockly.Extensions.ALL_['extensions_test_after']); + chai.assert.isUndefined( + Blockly.Extensions.TEST_ONLY.allExtensions['extensions_test_after']); var afterCallback = sinon.spy(); // Extension defined after the block type (but before instantiation). Blockly.Extensions.register('extensions_test_after', afterCallback); - chai.assert.typeOf(Blockly.Extensions.ALL_['extensions_test_before'], 'function'); - chai.assert.typeOf(Blockly.Extensions.ALL_['extensions_test_after'], 'function'); + chai.assert.typeOf( + Blockly.Extensions.TEST_ONLY.allExtensions['extensions_test_before'], + 'function'); + chai.assert.typeOf( + Blockly.Extensions.TEST_ONLY.allExtensions['extensions_test_after'], + 'function'); sinon.assert.notCalled(beforeCallback); sinon.assert.notCalled(afterCallback); @@ -113,11 +124,13 @@ suite('Extensions', function() { } }; - chai.assert.isUndefined(Blockly.Extensions.ALL_['mixin_test']); + chai.assert.isUndefined( + Blockly.Extensions.TEST_ONLY.allExtensions['mixin_test']); // Extension defined before the block type is defined. Blockly.Extensions.registerMixin('mixin_test', testMixin); - chai.assert.typeOf(Blockly.Extensions.ALL_['mixin_test'], 'function'); + chai.assert.typeOf( + Blockly.Extensions.TEST_ONLY.allExtensions['mixin_test'], 'function'); Blockly.defineBlocksWithJsonArray([{ @@ -182,7 +195,8 @@ suite('Extensions', function() { // Events code calls mutationToDom and expects it to give back a // meaningful value. Blockly.Events.disable(); - chai.assert.isUndefined(Blockly.Extensions.ALL_['extensions_test']); + chai.assert.isUndefined( + Blockly.Extensions.TEST_ONLY.allExtensions['extensions_test']); var helperFunctionSpy = sinon.spy(); Blockly.Extensions.registerMutator('extensions_test', { @@ -213,7 +227,8 @@ suite('Extensions', function() { // Events code calls mutationToDom and expects it to give back a // meaningful value. Blockly.Events.disable(); - chai.assert.isUndefined(Blockly.Extensions.ALL_['mutator_test']); + chai.assert.isUndefined( + Blockly.Extensions.TEST_ONLY.allExtensions['mutator_test']); Blockly.Extensions.registerMutator('mutator_test', { domToMutation: function() { @@ -243,7 +258,8 @@ suite('Extensions', function() { "extensions": ["missing_extension"] }]); - chai.assert.isUndefined(Blockly.Extensions.ALL_['missing_extension']); + chai.assert.isUndefined( + Blockly.Extensions.TEST_ONLY.allExtensions['missing_extension']); var workspace = this.workspace; chai.assert.throws(function() { var _ = new Blockly.Block(workspace, 'missing_extension_block'); @@ -257,10 +273,14 @@ suite('Extensions', function() { inputList: 'bad inputList' // Defined in constructor }; - chai.assert.isUndefined(Blockly.Extensions.ALL_['mixin_bad_inputList']); + chai.assert.isUndefined( + Blockly.Extensions.TEST_ONLY.allExtensions['mixin_bad_inputList']); // Extension defined before the block type is defined. - Blockly.Extensions.registerMixin('mixin_bad_inputList', TEST_MIXIN_BAD_INPUTLIST); - chai.assert.typeOf(Blockly.Extensions.ALL_['mixin_bad_inputList'], 'function'); + Blockly.Extensions.registerMixin( + 'mixin_bad_inputList', TEST_MIXIN_BAD_INPUTLIST); + chai.assert.typeOf( + Blockly.Extensions.TEST_ONLY.allExtensions['mixin_bad_inputList'], + 'function'); Blockly.defineBlocksWithJsonArray([{ "type": "test_block_bad_inputList", @@ -281,10 +301,14 @@ suite('Extensions', function() { colour_: 'bad colour_' // Defined on prototype }; - chai.assert.isUndefined(Blockly.Extensions.ALL_['mixin_bad_colour_']); + chai.assert.isUndefined( + Blockly.Extensions.TEST_ONLY.allExtensions['mixin_bad_colour_']); // Extension defined before the block type is defined. - Blockly.Extensions.registerMixin('mixin_bad_colour_', TEST_MIXIN_BAD_COLOUR); - chai.assert.typeOf(Blockly.Extensions.ALL_['mixin_bad_colour_'], 'function'); + Blockly.Extensions.registerMixin( + 'mixin_bad_colour_', TEST_MIXIN_BAD_COLOUR); + chai.assert.typeOf( + Blockly.Extensions.TEST_ONLY.allExtensions['mixin_bad_colour_'], + 'function'); Blockly.defineBlocksWithJsonArray([{ "type": "test_block_bad_colour", @@ -310,7 +334,8 @@ suite('Extensions', function() { // Events code calls mutationToDom and expects it to give back a // meaningful value. Blockly.Events.disable(); - chai.assert.isUndefined(Blockly.Extensions.ALL_['mutator_test']); + chai.assert.isUndefined( + Blockly.Extensions.TEST_ONLY.allExtensions['mutator_test']); Blockly.Extensions.registerMutator('mutator_test', { domToMutation: function() { @@ -326,7 +351,8 @@ suite('Extensions', function() { var _ = new Blockly.Block(workspace, 'mutator_test_block'); }); // Should have failed on apply, not on register. - chai.assert.isNotNull(Blockly.Extensions.ALL_['mutator_test']); + chai.assert.isNotNull( + Blockly.Extensions.TEST_ONLY.allExtensions['mutator_test']); }); test('Use mutator mixin as extension', function() { @@ -341,7 +367,8 @@ suite('Extensions', function() { // Events code calls mutationToDom and expects it to give back a // meaningful value. Blockly.Events.disable(); - chai.assert.isUndefined(Blockly.Extensions.ALL_['mutator_test']); + chai.assert.isUndefined( + Blockly.Extensions.TEST_ONLY.allExtensions['mutator_test']); Blockly.Extensions.registerMixin('mutator_test', { domToMutation: function() { @@ -357,7 +384,8 @@ suite('Extensions', function() { var _ = new Blockly.Block(workspace, 'mutator_test_block'); }); // Should have failed on apply, not on register. - chai.assert.isNotNull(Blockly.Extensions.ALL_['mutator_test']); + chai.assert.isNotNull( + Blockly.Extensions.TEST_ONLY.allExtensions['mutator_test']); }); test('Use extension as mutator', function() { @@ -372,7 +400,8 @@ suite('Extensions', function() { // Events code calls mutationToDom and expects it to give back a // meaningful value. Blockly.Events.disable(); - chai.assert.isUndefined(Blockly.Extensions.ALL_['extensions_test']); + chai.assert.isUndefined( + Blockly.Extensions.TEST_ONLY.allExtensions['extensions_test']); Blockly.Extensions.register('extensions_test', function() { return 'extensions_test_fn'; }); @@ -382,13 +411,15 @@ suite('Extensions', function() { var _ = new Blockly.Block(workspace, 'mutator_test_block'); }); // Should have failed on apply, not on register. - chai.assert.isNotNull(Blockly.Extensions.ALL_['extensions_test']); + chai.assert.isNotNull( + Blockly.Extensions.TEST_ONLY.allExtensions['extensions_test']); }); suite('register', function() { test('Just a string', function() { this.extensionsCleanup_.push('extension_just_a_string'); - chai.assert.isUndefined(Blockly.Extensions.ALL_['extension_just_a_string']); + chai.assert.isUndefined(Blockly.Extensions.TEST_ONLY + .allExtensions['extension_just_a_string']); chai.assert.throws(function() { Blockly.Extensions.register('extension_just_a_string', null); }); @@ -396,7 +427,8 @@ suite('Extensions', function() { test('Null', function() { this.extensionsCleanup_.push('extension_is_null'); - chai.assert.isUndefined(Blockly.Extensions.ALL_['extension_is_null']); + chai.assert.isUndefined( + Blockly.Extensions.TEST_ONLY.allExtensions['extension_is_null']); chai.assert.throws(function() { Blockly.Extensions.register('extension_is_null', null); }); @@ -404,7 +436,8 @@ suite('Extensions', function() { test('Undefined', function() { this.extensionsCleanup_.push('extension_is_undefined'); - chai.assert.isUndefined(Blockly.Extensions.ALL_['extension_is_undefined']); + chai.assert.isUndefined(Blockly.Extensions.TEST_ONLY + .allExtensions['extension_is_undefined']); chai.assert.throws(function() { Blockly.Extensions.register('extension_is_undefined', null); }); @@ -448,6 +481,57 @@ suite('Extensions', function() { }, /mutationToDom/); }); + test('No saveExtraState', function() { + this.extensionsCleanup_.push('mutator_test'); + chai.assert.throws(function() { + Blockly.Extensions.registerMutator('mutator_test', + { + loadExtraState: function() { + return 'loadExtraState'; + }, + compose: function() { + return 'composeFn'; + }, + decompose: function() { + return 'decomposeFn'; + } + }); + }, /saveExtraState/); + }); + + test('No loadExtraState', function() { + this.extensionsCleanup_.push('mutator_test'); + chai.assert.throws(function() { + Blockly.Extensions.registerMutator('mutator_test', + { + saveExtraState: function() { + return 'saveExtraState'; + }, + compose: function() { + return 'composeFn'; + }, + decompose: function() { + return 'decomposeFn'; + } + }); + }, /loadExtraState/); + }); + + test('No serialization hooks', function() { + this.extensionsCleanup_.push('mutator_test'); + chai.assert.throws(function() { + Blockly.Extensions.registerMutator('mutator_test', + { + compose: function() { + return 'composeFn'; + }, + decompose: function() { + return 'decomposeFn'; + } + }); + }, 'Mutations must contain either XML hooks, or JSON hooks, or both'); + }); + test('Has decompose but no compose', function() { this.extensionsCleanup_.push('mutator_test'); chai.assert.throws(function() { diff --git a/tests/mocha/field_angle_test.js b/tests/mocha/field_angle_test.js index 7a1eb928c..7ec50fade 100644 --- a/tests/mocha/field_angle_test.js +++ b/tests/mocha/field_angle_test.js @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.fieldAngle'); + +const {createTestBlock, defineRowBlock, sharedTestSetup, sharedTestTeardown, workspaceTeardown} = goog.require('Blockly.test.helpers'); + + suite('Angle Fields', function() { setup(function() { sharedTestSetup.call(this); @@ -310,4 +315,35 @@ suite('Angle Fields', function() { }); }); }); + + suite('Serialization', function() { + setup(function() { + this.workspace = new Blockly.Workspace(); + defineRowBlock(); + + this.assertValue = (value) => { + const block = this.workspace.newBlock('row_block'); + const field = new Blockly.FieldAngle(value); + block.getInput('INPUT').appendField(field, 'ANGLE'); + const jso = Blockly.serialization.blocks.save(block); + chai.assert.deepEqual(jso['fields'], {'ANGLE': value}); + }; + }); + + teardown(function() { + workspaceTeardown.call(this, this.workspace); + }); + + test('Simple', function() { + this.assertValue(90); + }); + + test('Max precision', function() { + this.assertValue(1.000000000000001); + }); + + test('Smallest number', function() { + this.assertValue(5e-324); + }); + }); }); diff --git a/tests/mocha/field_checkbox_test.js b/tests/mocha/field_checkbox_test.js index 5a10ef57f..379c9e389 100644 --- a/tests/mocha/field_checkbox_test.js +++ b/tests/mocha/field_checkbox_test.js @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.fieldCheckbox'); + +const {defineRowBlock, sharedTestSetup, sharedTestTeardown, workspaceTeardown} = goog.require('Blockly.test.helpers'); + + suite('Checkbox Fields', function() { setup(function() { sharedTestSetup.call(this); @@ -204,4 +209,31 @@ suite('Checkbox Fields', function() { }); }); }); + + suite('Serialization', function() { + setup(function() { + this.workspace = new Blockly.Workspace(); + defineRowBlock(); + + this.assertValue = (value) => { + const block = this.workspace.newBlock('row_block'); + const field = new Blockly.FieldCheckbox(value); + block.getInput('INPUT').appendField(field, 'CHECK'); + const jso = Blockly.serialization.blocks.save(block); + chai.assert.deepEqual(jso['fields'], {'CHECK': value}); + }; + }); + + teardown(function() { + workspaceTeardown.call(this, this.workspace); + }); + + test('True', function() { + this.assertValue(true); + }); + + test('False', function() { + this.assertValue(false); + }); + }); }); diff --git a/tests/mocha/field_colour_test.js b/tests/mocha/field_colour_test.js index e779bf831..016d96185 100644 --- a/tests/mocha/field_colour_test.js +++ b/tests/mocha/field_colour_test.js @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.fieldColour'); + +const {createTestBlock, defineRowBlock, sharedTestSetup, sharedTestTeardown, workspaceTeardown} = goog.require('Blockly.test.helpers'); + + suite('Colour Fields', function() { setup(function() { sharedTestSetup.call(this); @@ -277,4 +282,31 @@ suite('Colour Fields', function() { }); }); }); + + suite('Serialization', function() { + setup(function() { + this.workspace = new Blockly.Workspace(); + defineRowBlock(); + + this.assertValue = (value) => { + const block = this.workspace.newBlock('row_block'); + const field = new Blockly.FieldColour(value); + block.getInput('INPUT').appendField(field, 'COLOUR'); + const jso = Blockly.serialization.blocks.save(block); + chai.assert.deepEqual(jso['fields'], {'COLOUR': value}); + }; + }); + + teardown(function() { + workspaceTeardown.call(this, this.workspace); + }); + + test('Three char', function() { + this.assertValue('#001122'); + }); + + test('Six char', function() { + this.assertValue('#012345'); + }); + }); }); diff --git a/tests/mocha/field_dropdown_test.js b/tests/mocha/field_dropdown_test.js index 95ad8eacf..2f3e782bb 100644 --- a/tests/mocha/field_dropdown_test.js +++ b/tests/mocha/field_dropdown_test.js @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.fieldDropdown'); + +const {createTestBlock, defineRowBlock, sharedTestSetup, sharedTestTeardown, workspaceTeardown} = goog.require('Blockly.test.helpers'); + + suite('Dropdown Fields', function() { setup(function() { sharedTestSetup.call(this); @@ -152,4 +157,36 @@ suite('Dropdown Fields', function() { }); }); }); + + suite('Serialization', function() { + setup(function() { + this.workspace = new Blockly.Workspace(); + defineRowBlock(); + + + this.assertValue = (value, field) => { + const block = this.workspace.newBlock('row_block'); + field.setValue(value); + block.getInput('INPUT').appendField(field, 'DROPDOWN'); + const jso = Blockly.serialization.blocks.save(block); + chai.assert.deepEqual(jso['fields'], {'DROPDOWN': value}); + }; + }); + + teardown(function() { + workspaceTeardown.call(this, this.workspace); + }); + + test('Simple', function() { + const field = new Blockly.FieldDropdown( + [['apple', 'A'], ['ball', 'B'], ['carrot', 'C']]); + this.assertValue('C', field); + }); + + test('Dynamic', function() { + const field = new Blockly.FieldDropdown( + () => [['apple', 'A'], ['ball', 'B'], ['carrot', 'C']]); + this.assertValue('C', field); + }); + }); }); diff --git a/tests/mocha/field_image_test.js b/tests/mocha/field_image_test.js index 2bbd06664..48d8b3e5f 100644 --- a/tests/mocha/field_image_test.js +++ b/tests/mocha/field_image_test.js @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.fieldImage'); + +const {sharedTestSetup, sharedTestTeardown} = goog.require('Blockly.test.helpers'); + + suite('Image Fields', function() { setup(function() { sharedTestSetup.call(this); diff --git a/tests/mocha/field_label_serializable_test.js b/tests/mocha/field_label_serializable_test.js index 330241503..0dc769f41 100644 --- a/tests/mocha/field_label_serializable_test.js +++ b/tests/mocha/field_label_serializable_test.js @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.fieldLabelSerialization'); + +const {createTestBlock, defineRowBlock, sharedTestSetup, sharedTestTeardown, workspaceTeardown} = goog.require('Blockly.test.helpers'); + + suite('Label Serializable Fields', function() { setup(function() { sharedTestSetup.call(this); @@ -181,4 +186,27 @@ suite('Label Serializable Fields', function() { }); }); }); + + suite('Serialization', function() { + setup(function() { + this.workspace = new Blockly.Workspace(); + defineRowBlock(); + + this.assertValue = (value) => { + const block = this.workspace.newBlock('row_block'); + const field = new Blockly.FieldLabelSerializable(value); + block.getInput('INPUT').appendField(field, 'LABEL'); + const jso = Blockly.serialization.blocks.save(block); + chai.assert.deepEqual(jso['fields'], {'LABEL': value}); + }; + }); + + teardown(function() { + workspaceTeardown.call(this, this.workspace); + }); + + test('Simple', function() { + this.assertValue('test label'); + }); + }); }); diff --git a/tests/mocha/field_label_test.js b/tests/mocha/field_label_test.js index b0b7162a0..d7e381ac8 100644 --- a/tests/mocha/field_label_test.js +++ b/tests/mocha/field_label_test.js @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.fieldLabel'); + +const {createTestBlock, sharedTestSetup, sharedTestTeardown} = goog.require('Blockly.test.helpers'); + + suite('Label Fields', function() { setup(function() { sharedTestSetup.call(this); diff --git a/tests/mocha/field_multilineinput_test.js b/tests/mocha/field_multilineinput_test.js index 844593f86..51426c694 100644 --- a/tests/mocha/field_multilineinput_test.js +++ b/tests/mocha/field_multilineinput_test.js @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.fieldMultiline'); + +const {createTestBlock, defineRowBlock, sharedTestSetup, sharedTestTeardown, workspaceTeardown} = goog.require('Blockly.test.helpers'); + + suite('Multiline Input Fields', function() { setup(function() { sharedTestSetup.call(this); @@ -153,4 +158,31 @@ suite('Multiline Input Fields', function() { ]; testHelpers.runCodeGenerationTestSuites(testSuites); }); + + suite('Serialization', function() { + setup(function() { + this.workspace = new Blockly.Workspace(); + defineRowBlock(); + + this.assertValue = (value) => { + const block = this.workspace.newBlock('row_block'); + const field = new Blockly.FieldMultilineInput(value); + block.getInput('INPUT').appendField(field, 'MULTILINE'); + const jso = Blockly.serialization.blocks.save(block); + chai.assert.deepEqual(jso['fields'], {'MULTILINE': value}); + }; + }); + + teardown(function() { + workspaceTeardown.call(this, this.workspace); + }); + + test('Single line', function() { + this.assertValue('this is a single line'); + }); + + test('Multiple lines', function() { + this.assertValue('this\nis\n multiple\n lines'); + }); + }); }); diff --git a/tests/mocha/field_number_test.js b/tests/mocha/field_number_test.js index 338aa4ad0..598e482ca 100644 --- a/tests/mocha/field_number_test.js +++ b/tests/mocha/field_number_test.js @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.fieldNumber'); + +const {defineRowBlock, sharedTestSetup, sharedTestTeardown, workspaceTeardown} = goog.require('Blockly.test.helpers'); + + suite('Number Fields', function() { setup(function() { sharedTestSetup.call(this); @@ -332,4 +337,43 @@ suite('Number Fields', function() { }); }); }); + + suite('Serialization', function() { + setup(function() { + this.workspace = new Blockly.Workspace(); + defineRowBlock(); + + this.assertValue = (value) => { + const block = this.workspace.newBlock('row_block'); + const field = new Blockly.FieldNumber(value); + block.getInput('INPUT').appendField(field, 'NUMBER'); + const jso = Blockly.serialization.blocks.save(block); + chai.assert.deepEqual(jso['fields'], {'NUMBER': value}); + }; + }); + + teardown(function() { + workspaceTeardown.call(this, this.workspace); + }); + + test('Simple', function() { + this.assertValue(10); + }); + + test('Max precision small', function() { + this.assertValue(1.000000000000001); + }); + + test('Max precision large', function() { + this.assertValue(1000000000000001); + }); + + test('Smallest', function() { + this.assertValue(5e-324); + }); + + test('Largest', function() { + this.assertValue(1.7976931348623157e+308); + }); + }); }); diff --git a/tests/mocha/field_registry_test.js b/tests/mocha/field_registry_test.js index 29338d533..bddb3fc64 100644 --- a/tests/mocha/field_registry_test.js +++ b/tests/mocha/field_registry_test.js @@ -4,11 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -/** - * @fileoverview Tests for Blockly.fieldRegistry - * @author bekawestberg@gmail.com (Beka Westberg) - */ -'use strict'; +goog.module('Blockly.test.fieldRegistry'); + +const {createDeprecationWarningStub, sharedTestSetup, sharedTestTeardown} = goog.require('Blockly.test.helpers'); + suite('Field Registry', function() { function CustomFieldType(value) { @@ -24,8 +23,8 @@ suite('Field Registry', function() { }); teardown(function() { sharedTestTeardown.call(this); - if (Blockly.registry.typeMap_['field']['field_custom_test']) { - delete Blockly.registry.typeMap_['field']['field_custom_test']; + if (Blockly.registry.TEST_ONLY.typeMap['field']['field_custom_test']) { + delete Blockly.registry.TEST_ONLY.typeMap['field']['field_custom_test']; } }); @@ -64,10 +63,7 @@ suite('Field Registry', function() { value: 'ok' }; - // TODO(#4197): Remove stubbing of deprecation warning after fixing. - var deprecationWarnStub = createDeprecationWarningStub(); var field = Blockly.fieldRegistry.fromJson(json); - deprecationWarnStub.restore(); chai.assert.isNotNull(field); chai.assert.equal(field.getValue(), 'ok'); @@ -92,10 +88,7 @@ suite('Field Registry', function() { value: 'ok' }; - // TODO(#4197): Remove stubbing of deprecation warning after fixing. - var deprecationWarnStub = createDeprecationWarningStub(); var field = Blockly.fieldRegistry.fromJson(json); - deprecationWarnStub.restore(); chai.assert.isNotNull(field); chai.assert.equal(field.getValue(), 'ok'); diff --git a/tests/mocha/field_test.js b/tests/mocha/field_test.js index f89193d4b..dca8bb153 100644 --- a/tests/mocha/field_test.js +++ b/tests/mocha/field_test.js @@ -4,17 +4,20 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.fieldTest'); + +const {addBlockTypeToCleanup, addMessageToCleanup, createDeprecationWarningStub, sharedTestSetup, sharedTestTeardown, workspaceTeardown} = goog.require('Blockly.test.helpers'); + + suite('Abstract Fields', function() { setup(function() { sharedTestSetup.call(this); - // TODO(#4197): Remove stubbing of deprecation warning after fixing. - // field.setValue calls trigger a deprecation warning, capture to prevent - // console logs. - createDeprecationWarningStub(); }); + teardown(function() { sharedTestTeardown.call(this); }); + suite('Is Serializable', function() { // Both EDITABLE and SERIALIZABLE are default. function FieldDefault() { @@ -68,6 +71,269 @@ suite('Abstract Fields', function() { chai.assert.isTrue(field.isSerializable()); }); }); + + suite('Serialization', function() { + class DefaultSerializationField extends Blockly.Field { + constructor(value, validator = undefined, config = undefined) { + super(value, validator, config); + this.SERIALIZABLE = true; + } + } + + class CustomXmlField extends Blockly.Field { + constructor(value, validator = undefined, config = undefined) { + super(value, validator, config); + this.SERIALIZABLE = true; + } + + toXml(fieldElement) { + fieldElement.textContent = 'custom value'; + return fieldElement; + } + + fromXml(fieldElement) { + this.someProperty = fieldElement.textContent; + } + } + + class CustomXmlCallSuperField extends Blockly.Field { + constructor(value, validator = undefined, config = undefined) { + super(value, validator, config); + this.SERIALIZABLE = true; + } + + toXml(fieldElement) { + super.toXml(fieldElement); + fieldElement.setAttribute('attribute', 'custom value'); + return fieldElement; + } + + fromXml(fieldElement) { + super.fromXml(fieldElement); + this.someProperty = fieldElement.getAttribute('attribute'); + } + } + + class CustomJsoField extends Blockly.Field { + constructor(value, validator = undefined, config = undefined) { + super(value, validator, config); + this.SERIALIZABLE = true; + } + + saveState() { + return 'custom value'; + } + + loadState(state) { + this.someProperty = state; + } + } + + class CustomJsoCallSuperField extends Blockly.Field { + constructor(value, validator = undefined, config = undefined) { + super(value, validator, config); + this.SERIALIZABLE = true; + } + + saveState() { + return { + default: super.saveState(), + val: 'custom value' + }; + } + + loadState(state) { + super.loadState(state.default); + this.someProperty = state.val; + } + } + + class CustomXmlAndJsoField extends Blockly.Field { + constructor(value, validator = undefined, config = undefined) { + super(value, validator, config); + this.SERIALIZABLE = true; + } + + toXml(fieldElement) { + fieldElement.textContent = 'custom value'; + return fieldElement; + } + + fromXml(fieldElement) { + this.someProperty = fieldElement.textContent; + } + + saveState() { + return 'custom value'; + } + + loadState(state) { + this.someProperty = state; + } + } + + suite('Save', function() { + suite('JSO', function() { + test('No implementations', function() { + const field = new DefaultSerializationField('test value'); + const value = field.saveState(); + chai.assert.equal(value, 'test value'); + }); + + test('Xml implementations', function() { + const field = new CustomXmlField('test value'); + const value = field.saveState(); + chai.assert.equal(value, 'custom value'); + }); + + test('Xml super implementation', function() { + const field = new CustomXmlCallSuperField('test value'); + const value = field.saveState(); + chai.assert.equal( + value, + 'test value'); + }); + + test('JSO implementations', function() { + const field = new CustomJsoField('test value'); + const value = field.saveState(); + chai.assert.equal(value, 'custom value'); + }); + + test('JSO super implementations', function() { + const field = new CustomJsoCallSuperField('test value'); + const value = field.saveState(); + chai.assert.deepEqual( + value, {default: 'test value', val: 'custom value'}); + }); + + test('Xml and JSO implementations', function() { + const field = new CustomXmlAndJsoField('test value'); + const value = field.saveState(); + chai.assert.equal(value, 'custom value'); + }); + }); + + suite('Xml', function() { + test('No implementations', function() { + const field = new DefaultSerializationField('test value'); + const element = document.createElement('field'); + const value = Blockly.Xml.domToText(field.toXml(element)); + chai.assert.equal( + value, + 'test value'); + }); + + test('Xml implementations', function() { + const field = new CustomXmlField('test value'); + const element = document.createElement('field'); + const value = Blockly.Xml.domToText(field.toXml(element)); + chai.assert.equal( + value, + 'custom value' + ); + }); + + test('Xml super implementation', function() { + const field = new CustomXmlCallSuperField('test value'); + const element = document.createElement('field'); + const value = Blockly.Xml.domToText(field.toXml(element)); + chai.assert.equal( + value, + 'test value'); + }); + + test('Xml and JSO implementations', function() { + const field = new CustomXmlAndJsoField('test value'); + const element = document.createElement('field'); + const value = Blockly.Xml.domToText(field.toXml(element)); + chai.assert.equal( + value, + 'custom value' + ); + }); + }); + }); + + suite('Load', function() { + suite('JSO', function() { + test('No implementations', function() { + const field = new DefaultSerializationField(''); + field.loadState('test value'); + chai.assert.equal(field.getValue(), 'test value'); + }); + + test('Xml implementations', function() { + const field = new CustomXmlField(''); + field.loadState('custom value'); + chai.assert.equal(field.someProperty, 'custom value'); + }); + + test('Xml super implementation', function() { + const field = new CustomXmlCallSuperField(''); + field.loadState( + 'test value'); + chai.assert.equal(field.getValue(), 'test value'); + chai.assert.equal(field.someProperty, 'custom value'); + }); + + test('JSO implementations', function() { + const field = new CustomJsoField(''); + field.loadState('custom value'); + chai.assert.equal(field.someProperty, 'custom value'); + }); + + test('JSO super implementations', function() { + const field = new CustomJsoCallSuperField(''); + field.loadState({default: 'test value', val: 'custom value'}); + chai.assert.equal(field.getValue(), 'test value'); + chai.assert.equal(field.someProperty, 'custom value'); + }); + + test('Xml and JSO implementations', function() { + const field = new CustomXmlAndJsoField(''); + field.loadState('custom value'); + chai.assert.equal(field.someProperty, 'custom value'); + }); + }); + + suite('Xml', function() { + test('No implementations', function() { + const field = new DefaultSerializationField(''); + field.fromXml( + Blockly.Xml.textToDom('test value')); + chai.assert.equal(field.getValue(), 'test value'); + }); + + test('Xml implementations', function() { + const field = new CustomXmlField(''); + field.fromXml( + Blockly.Xml.textToDom('custom value')); + chai.assert.equal(field.someProperty, 'custom value'); + }); + + test('Xml super implementation', function() { + const field = new CustomXmlCallSuperField(''); + field.fromXml( + Blockly.Xml.textToDom( + 'test value' + ) + ); + chai.assert.equal(field.getValue(), 'test value'); + chai.assert.equal(field.someProperty, 'custom value'); + }); + + test('XML andd JSO implementations', function() { + const field = new CustomXmlAndJsoField(''); + field.fromXml( + Blockly.Xml.textToDom('custom value')); + chai.assert.equal(field.someProperty, 'custom value'); + }); + }); + }); + }); + suite('setValue', function() { function addSpies(field, excludeSpies = []) { if (!excludeSpies.includes('doValueInvalid_')) { @@ -316,6 +582,7 @@ suite('Abstract Fields', function() { sinon.assert.calledOnce(this.field.doValueUpdate_); }); }); + suite('Customization', function() { // All this field does is wrap the abstract field. function CustomField(opt_config) { diff --git a/tests/mocha/field_textinput_test.js b/tests/mocha/field_textinput_test.js index 1a1c1ed2a..496f1ce6f 100644 --- a/tests/mocha/field_textinput_test.js +++ b/tests/mocha/field_textinput_test.js @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.fieldTextInput'); + +const {createTestBlock, defineRowBlock, sharedTestSetup, sharedTestTeardown, workspaceTeardown} = goog.require('Blockly.test.helpers'); + + suite('Text Input Fields', function() { setup(function() { sharedTestSetup.call(this); @@ -167,8 +172,8 @@ suite('Text Input Fields', function() { FIELD_TEXT_FONTFAMILY: 'sans-serif' }; field.clickTarget_ = document.createElement('div'); - Blockly.mainWorkspace = workspace; - Blockly.WidgetDiv.DIV = document.createElement('div'); + Blockly.common.setMainWorkspace(workspace); + Blockly.WidgetDiv.createDom(); this.stub = sinon.stub(field, 'resizeEditor_'); }; @@ -215,4 +220,27 @@ suite('Text Input Fields', function() { }); }); }); + + suite('Serialization', function() { + setup(function() { + this.workspace = new Blockly.Workspace(); + defineRowBlock(); + + this.assertValue = (value) => { + const block = this.workspace.newBlock('row_block'); + const field = new Blockly.FieldTextInput(value); + block.getInput('INPUT').appendField(field, 'TEXT'); + const jso = Blockly.serialization.blocks.save(block); + chai.assert.deepEqual(jso['fields'], {'TEXT': value}); + }; + }); + + teardown(function() { + workspaceTeardown.call(this, this.workspace); + }); + + test('Simple', function() { + this.assertValue('test text'); + }); + }); }); diff --git a/tests/mocha/field_variable_test.js b/tests/mocha/field_variable_test.js index 0048b8e09..b28781baa 100644 --- a/tests/mocha/field_variable_test.js +++ b/tests/mocha/field_variable_test.js @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.fieldVariable'); + +const {createGenUidStubWithReturns, createTestBlock, defineRowBlock, sharedTestSetup, sharedTestTeardown, workspaceTeardown} = goog.require('Blockly.test.helpers'); + + suite('Variable Fields', function() { var FAKE_VARIABLE_NAME = 'default_name'; var FAKE_ID = 'id1'; @@ -11,8 +16,8 @@ suite('Variable Fields', function() { sharedTestSetup.call(this); this.workspace = new Blockly.Workspace(); // Stub for default variable name. - sinon.stub(Blockly.Variables, 'generateUniqueName') - .returns(FAKE_VARIABLE_NAME); + sinon.stub(Blockly.Variables, 'generateUniqueName').returns( + FAKE_VARIABLE_NAME); }); teardown(function() { sharedTestTeardown.call(this); @@ -377,4 +382,124 @@ suite('Variable Fields', function() { chai.assert.equal(this.variableField.getValue(), 'id2'); }); }); + + suite('Serialization', function() { + setup(function() { + this.workspace = new Blockly.Workspace(); + defineRowBlock(); + createGenUidStubWithReturns(new Array(10).fill().map((_, i) => 'id' + i)); + }); + + teardown(function() { + workspaceTeardown.call(this, this.workspace); + }); + + suite('Full', function() { + test('Untyped', function() { + const block = this.workspace.newBlock('row_block'); + const field = new Blockly.FieldVariable('x'); + block.getInput('INPUT').appendField(field, 'VAR'); + const jso = Blockly.serialization.blocks.save(block); + chai.assert.deepEqual( + jso['fields'], {'VAR': {'id': 'id2', 'name': 'x', 'type': ''}}); + }); + + test('Typed', function() { + const block = this.workspace.newBlock('row_block'); + const field = + new Blockly.FieldVariable('x', undefined, undefined, 'String'); + block.getInput('INPUT').appendField(field, 'VAR'); + const jso = Blockly.serialization.blocks.save(block); + chai.assert.deepEqual( + jso['fields'], {'VAR': {'id': 'id2', 'name': 'x', 'type': 'String'}}); + }); + }); + + suite('Not full', function() { + test('Untyped', function() { + const block = this.workspace.newBlock('row_block'); + const field = new Blockly.FieldVariable('x'); + block.getInput('INPUT').appendField(field, 'VAR'); + const jso = Blockly.serialization.blocks.save( + block, {doFullSerialization: false}); + chai.assert.deepEqual(jso['fields'], {'VAR': {'id': 'id2'}}); + chai.assert.isUndefined(jso['fields']['VAR']['name']); + chai.assert.isUndefined(jso['fields']['VAR']['type']); + }); + + test('Typed', function() { + const block = this.workspace.newBlock('row_block'); + const field = + new Blockly.FieldVariable('x', undefined, undefined, 'String'); + block.getInput('INPUT').appendField(field, 'VAR'); + const jso = Blockly.serialization.blocks.save( + block, {doFullSerialization: false}); + chai.assert.deepEqual(jso['fields'], {'VAR': {'id': 'id2'}}); + chai.assert.isUndefined(jso['fields']['VAR']['name']); + chai.assert.isUndefined(jso['fields']['VAR']['type']); + }); + }); + }); + + suite('Deserialization', function() { + setup(function() { + this.workspace = new Blockly.Workspace(); + defineRowBlock(); + createGenUidStubWithReturns(new Array(10).fill().map((_, i) => 'id' + i)); + }); + + teardown(function() { + workspaceTeardown.call(this, this.workspace); + }); + + test('ID', function() { + this.workspace.createVariable('test', '', 'id1'); + var block = Blockly.serialization.blocks.append({ + 'type': 'variables_get', + 'fields': { + 'VAR': { + 'id': 'id1' + } + } + }, + this.workspace); + var variable = block.getField('VAR').getVariable(); + chai.assert.equal(variable.name, 'test'); + chai.assert.equal(variable.type, ''); + chai.assert.equal(variable.getId(), 'id1'); + }); + + test('Name, untyped', function() { + var block = Blockly.serialization.blocks.append({ + 'type': 'variables_get', + 'fields': { + 'VAR': { + 'name': 'test', + } + } + }, + this.workspace); + var variable = block.getField('VAR').getVariable(); + chai.assert.equal(variable.name, 'test'); + chai.assert.equal(variable.type, ''); + chai.assert.equal(variable.getId(), 'id2'); + }); + + test('Name, typed', function() { + var block = Blockly.serialization.blocks.append({ + 'type': 'variables_get', + 'fields': { + 'VAR': { + 'name': 'test', + 'type': 'string', + } + } + }, + this.workspace); + var variable = block.getField('VAR').getVariable(); + chai.assert.equal(variable.name, 'test'); + chai.assert.equal(variable.type, 'string'); + chai.assert.equal(variable.getId(), 'id2'); + }); + }); }); diff --git a/tests/mocha/flyout_test.js b/tests/mocha/flyout_test.js index 6ccd08d90..5faf8bf84 100644 --- a/tests/mocha/flyout_test.js +++ b/tests/mocha/flyout_test.js @@ -4,6 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.flyout'); + +const {defineStackBlock, sharedTestSetup, sharedTestTeardown, workspaceTeardown} = goog.require('Blockly.test.helpers'); +const {getBasicToolbox, getChildItem, getCollapsibleItem, getDeeplyNestedJSON, getInjectedToolbox, getNonCollapsibleItem, getProperSimpleJson, getSeparator, getSimpleJson, getXmlArray} = goog.require('Blockly.test.toolboxHelpers'); + + suite('Flyout', function() { setup(function() { sharedTestSetup.call(this); @@ -236,74 +242,345 @@ suite('Flyout', function() { suite('createFlyoutInfo_', function() { setup(function() { - this.simpleToolboxJSON = getSimpleJSON(); this.flyout = this.workspace.getFlyout(); this.createFlyoutSpy = sinon.spy(this.flyout, 'createFlyoutInfo_'); - }); - function checkLayoutContents(actual, expected, opt_message) { - chai.assert.equal(actual.length, expected.length, opt_message); - for (var i = 0; i < actual.length; i++) { - chai.assert.equal(actual[i].type, expected[i].type, opt_message); - if (actual[i].type == 'BLOCK') { - chai.assert.typeOf(actual[i]['block'], 'Blockly.Block'); - } else if (actual[i].type == 'BUTTON' || actual[i].type == 'LABEL') { - chai.assert.typeOf(actual[i]['block'], 'Blockly.FlyoutButton'); - } - } - } - function checkFlyoutInfo(flyoutSpy) { - var expectedContents = [ - {type: "block"}, - {type: "button"}, - {type: "button"} - ]; - var expectedGaps = [20, 24, 24]; var flyoutInfo = flyoutSpy.returnValues[0]; var contents = flyoutInfo.contents; var gaps = flyoutInfo.gaps; + + var expectedGaps = [20, 24, 24]; chai.assert.deepEqual(gaps, expectedGaps); - checkLayoutContents(contents, expectedContents, 'Contents'); + + chai.assert.equal(contents.length, 3, 'Contents'); + + chai.assert.equal(contents[0].type, 'block', 'Contents'); + var block = contents[0]['block']; + chai.assert.instanceOf(block, Blockly.BlockSvg); + chai.assert.equal(block.getFieldValue('OP'), 'NEQ'); + var childA = block.getInputTargetBlock('A'); + var childB = block.getInputTargetBlock('B'); + chai.assert.isTrue(childA.isShadow()); + chai.assert.isFalse(childB.isShadow()); + chai.assert.equal(childA.getFieldValue('NUM'), 1); + chai.assert.equal(childB.getFieldValue('NUM'), 2); + + chai.assert.equal(contents[1].type, 'button', 'Contents'); + chai.assert.instanceOf(contents[1]['button'], Blockly.FlyoutButton); + + chai.assert.equal(contents[2].type, 'button', 'Contents'); + chai.assert.instanceOf(contents[2]['button'], Blockly.FlyoutButton); } - test('Node', function() { - this.flyout.show(this.toolboxXml); - checkFlyoutInfo(this.createFlyoutSpy); + suite('Direct show', function() { + test('Node', function() { + this.flyout.show(this.toolboxXml); + checkFlyoutInfo(this.createFlyoutSpy); + }); + + test('NodeList', function() { + var nodeList = document.getElementById('toolbox-simple').childNodes; + this.flyout.show(nodeList); + checkFlyoutInfo(this.createFlyoutSpy); + }); + + test('Array of JSON', function() { + this.flyout.show(getSimpleJson()); + checkFlyoutInfo(this.createFlyoutSpy); + }); + + test('Array of Proper JSON', function() { + this.flyout.show(getProperSimpleJson()); + checkFlyoutInfo(this.createFlyoutSpy); + }); + + test('Array of XML', function() { + this.flyout.show(getXmlArray()); + checkFlyoutInfo(this.createFlyoutSpy); + }); }); - test('NodeList', function() { - var nodeList = document.getElementById('toolbox-simple').childNodes; - this.flyout.show(nodeList); - checkFlyoutInfo(this.createFlyoutSpy); + + suite('Dynamic category', function() { + setup(function() { + this.stubAndAssert = function(val) { + sinon.stub( + this.flyout.workspace_.targetWorkspace, + 'getToolboxCategoryCallback') + .returns(function() { return val; }); + this.flyout.show('someString'); + checkFlyoutInfo(this.createFlyoutSpy); + }; + }); + + test('No category available', function() { + chai.assert.throws( + function() { + this.flyout.show('someString'); + }.bind(this), + 'Couldn\'t find a callback function when opening ' + + 'a toolbox category.'); + }); + + test('Node', function() { + this.stubAndAssert(this.toolboxXml); + }); + + test('NodeList', function() { + this.stubAndAssert( + document.getElementById('toolbox-simple').childNodes); + }); + + test('Array of JSON', function() { + this.stubAndAssert(getSimpleJson()); + }); + + test('Array of Proper JSON', function() { + this.stubAndAssert(getProperSimpleJson()); + }); + + test('Array of XML', function() { + this.stubAndAssert(getXmlArray()); + }); }); - test('Array of JSON', function() { - this.flyout.show(this.simpleToolboxJSON); - checkFlyoutInfo(this.createFlyoutSpy); + }); + + suite('Creating blocks', function() { + suite('Enabled/Disabled', function() { + setup(function() { + this.flyout = this.workspace.getFlyout(); + + this.assertDisabled = function(disabled) { + var block = this.flyout.getWorkspace().getTopBlocks(false)[0]; + chai.assert.equal(!block.isEnabled(), disabled); + }; + }); + + suite('XML', function() { + test('True string', function() { + var xml = Blockly.Xml.textToDom( + '' + + '' + + '' + ); + this.flyout.show(xml); + this.assertDisabled(true); + }); + + test('False string', function() { + var xml = Blockly.Xml.textToDom( + '' + + '' + + '' + ); + this.flyout.show(xml); + this.assertDisabled(false); + }); + + test('Disabled string', function() { + // The XML system supports this for some reason!? + var xml = Blockly.Xml.textToDom( + '' + + '' + + '' + ); + this.flyout.show(xml); + this.assertDisabled(true); + }); + + test('Different string', function() { + var xml = Blockly.Xml.textToDom( + '' + + '' + + '' + ); + this.flyout.show(xml); + this.assertDisabled(false); + }); + }); + + suite('JSON', function() { + test('All undefined', function() { + var json = [ + { + 'kind': 'block', + 'type': 'text_print', + } + ]; + this.flyout.show(json); + this.assertDisabled(false); + }); + + test('Enabled true', function() { + var json = [ + { + 'kind': 'block', + 'type': 'text_print', + 'enabled': true, + } + ]; + this.flyout.show(json); + this.assertDisabled(false); + }); + + test('Enabled false', function() { + var json = [ + { + 'kind': 'block', + 'type': 'text_print', + 'enabled': false, + } + ]; + this.flyout.show(json); + this.assertDisabled(true); + }); + + test('Disabled true string', function() { + var json = [ + { + 'kind': 'block', + 'type': 'text_print', + 'disabled': 'true' + } + ]; + this.flyout.show(json); + this.assertDisabled(true); + }); + + test('Disabled false string', function() { + var json = [ + { + 'kind': 'block', + 'type': 'text_print', + 'disabled': 'false' + } + ]; + this.flyout.show(json); + this.assertDisabled(false); + }); + + test('Disabled string', function() { + var json = [ + { + 'kind': 'block', + 'type': 'text_print', + 'disabled': 'disabled' // This is not respected by the JSON! + } + ]; + this.flyout.show(json); + this.assertDisabled(false); + }); + + test('Disabled true value', function() { + var json = [ + { + 'kind': 'block', + 'type': 'text_print', + 'disabled': true + } + ]; + this.flyout.show(json); + this.assertDisabled(true); + }); + + test('Disabled false value', function() { + var json = [ + { + 'kind': 'block', + 'type': 'text_print', + 'disabled': false + } + ]; + this.flyout.show(json); + this.assertDisabled(false); + }); + + test('Disabled different string', function() { + var json = [ + { + 'kind': 'block', + 'type': 'text_print', + 'disabled': 'random' + } + ]; + this.flyout.show(json); + this.assertDisabled(false); + }); + + test('Disabled empty string', function() { + var json = [ + { + 'kind': 'block', + 'type': 'text_print', + 'disabled': '' + } + ]; + this.flyout.show(json); + this.assertDisabled(false); + }); + }); }); - test('Array of xml', function() { - this.flyout.show(getXmlArray()); - checkFlyoutInfo(this.createFlyoutSpy); + }); + + suite('Recycling', function() { + setup(function() { + this.flyout = this.workspace.getFlyout(); }); - test('Custom Toolbox: No Category Available', function() { - chai.assert.throws(function() { - this.flyout.show('someString'); - }.bind(this), 'Couldn\'t find a callback function when opening' + - ' a toolbox category.'); + + test('Recycling disabled', function() { + this.flyout.show({ + 'contents': [ + { + 'kind': 'BLOCK', + 'type': 'math_number', + 'fields': { + 'NUM': 123 + } + } + ] + }); + this.flyout.show({ + 'contents': [ + { + 'kind': 'BLOCK', + 'type': 'math_number', + 'fields': { + 'NUM': 321 + } + } + ] + }); + const block = this.flyout.workspace_.getAllBlocks()[0]; + chai.assert.equal(block.getFieldValue('NUM'), 321); }); - test('Custom Toolbox: Function does not return array', function() { - sinon.stub(this.flyout.workspace_.targetWorkspace, - 'getToolboxCategoryCallback').returns(function(){return null;}); - chai.assert.throws(function() { - this.flyout.show('someString'); - }.bind(this), 'Result of toolbox category callback must be an array.'); - }); - test('Custom Toolbox: Returns Array', function() { - sinon.stub(this.flyout.workspace_.targetWorkspace, - 'getToolboxCategoryCallback').returns(function(){return getXmlArray();}); - chai.assert.doesNotThrow(function() { - this.flyout.show('someString'); - }.bind(this)); + + test('Recycling enabled', function() { + this.flyout.blockIsRecyclable_ = function() { return true; }; + this.flyout.show({ + 'contents': [ + { + 'kind': 'BLOCK', + 'type': 'math_number', + 'fields': { + 'NUM': 123 + } + } + ] + }); + this.flyout.show({ + 'contents': [ + { + 'kind': 'BLOCK', + 'type': 'math_number', + 'fields': { + 'NUM': 321 + } + } + ] + }); + const block = this.flyout.workspace_.getAllBlocks()[0]; + chai.assert.equal(block.getFieldValue('NUM'), 123); }); }); }); diff --git a/tests/mocha/generator_test.js b/tests/mocha/generator_test.js index 9250557ab..8cc5d7901 100644 --- a/tests/mocha/generator_test.js +++ b/tests/mocha/generator_test.js @@ -4,11 +4,15 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.module('Blockly.test.generator'); + goog.require('Blockly.Dart'); goog.require('Blockly.JavaScript'); goog.require('Blockly.Lua'); goog.require('Blockly.PHP'); goog.require('Blockly.Python'); +const {sharedTestSetup, sharedTestTeardown} = goog.require('Blockly.test.helpers'); + suite('Generator', function() { setup(function() { @@ -90,6 +94,7 @@ suite('Generator', function() { var generator = testCase[0]; var name = testCase[1]; test(name, function() { + generator.init(this.workspace); this.blockToCodeTest(generator, false, true, 'row_block'); this.blockToCodeTest( generator, false, false, 'row_blockstack_block', 'thisOnly=false'); diff --git a/tests/mocha/gesture_test.js b/tests/mocha/gesture_test.js index ba77a27d1..9311112f9 100644 --- a/tests/mocha/gesture_test.js +++ b/tests/mocha/gesture_test.js @@ -4,11 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -/** - * @fileoverview Tests for gesture. - * @author marisaleung@google.com (Marisa Leung) - */ -'use strict'; +goog.module('Blockly.test.gesture'); + +const {assertEventFired, assertEventNotFired, defineBasicBlockWithField, dispatchPointerEvent, sharedTestSetup, sharedTestTeardown} = goog.require('Blockly.test.helpers'); + suite('Gesture', function() { function testGestureIsFieldClick(block, isFieldClick, eventsFireStub){ diff --git a/tests/mocha/index.html b/tests/mocha/index.html index 71b7de6b4..ec5f778fd 100644 --- a/tests/mocha/index.html +++ b/tests/mocha/index.html @@ -4,8 +4,9 @@ Mocha Tests for Blockly - + + @@ -25,6 +26,8 @@ + +