From 17d2e72ab0ec7513234567629d78e9065b89a527 Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Mon, 8 Mar 2021 16:35:11 -0500 Subject: [PATCH] Fix circular dependencies in shortcut + contextmenu registries (#4681) * Fix circular dependencies in shortcut and contextmenu registries --- blockly_uncompressed.js | 10 +++++----- core/contextmenu_items.js | 2 ++ core/contextmenu_registry.js | 14 ++++++++------ core/requires.js | 4 ++++ core/shortcut_items.js | 23 ++++++++++++++--------- core/shortcut_registry.js | 10 ++++------ tests/mocha/contextmenu_items_test.js | 1 + tests/mocha/shortcut_registry_test.js | 1 + 8 files changed, 39 insertions(+), 26 deletions(-) diff --git a/blockly_uncompressed.js b/blockly_uncompressed.js index 83da4da71..025026fdf 100644 --- a/blockly_uncompressed.js +++ b/blockly_uncompressed.js @@ -38,8 +38,8 @@ goog.addDependency('../../core/connection_db.js', ['Blockly.ConnectionDB'], ['Bl 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.Events', 'Blockly.constants', 'Blockly.inputTypes'], {'lang': 'es5'}); -goog.addDependency('../../core/contextmenu_registry.js', ['Blockly.ContextMenuRegistry'], ['Blockly.ContextMenuItems'], {'lang': 'es5'}); +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/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'], {}); @@ -159,10 +159,10 @@ goog.addDependency('../../core/renderers/zelos/measurables/row_elements.js', ['B 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.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.Themes.Classic', 'Blockly.Themes.Dark', 'Blockly.Themes.Deuteranopia', 'Blockly.Themes.HighContrast', 'Blockly.Themes.Tritanopia', 'Blockly.Toolbox', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.VerticalFlyout', 'Blockly.Warning', 'Blockly.ZoomControls', 'Blockly.geras.Renderer', 'Blockly.thrasos.Renderer', 'Blockly.zelos.Renderer'], {}); +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.Themes.Dark', 'Blockly.Themes.Deuteranopia', 'Blockly.Themes.HighContrast', 'Blockly.Themes.Tritanopia', '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.utils.KeyCodes'], {}); -goog.addDependency('../../core/shortcut_registry.js', ['Blockly.ShortcutRegistry'], ['Blockly.ShortcutItems', 'Blockly.utils.object'], {}); +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/dark.js', ['Blockly.Themes.Dark'], ['Blockly.Theme'], {}); diff --git a/core/contextmenu_items.js b/core/contextmenu_items.js index a35a5893f..4dc62dcd3 100644 --- a/core/contextmenu_items.js +++ b/core/contextmenu_items.js @@ -18,6 +18,7 @@ goog.provide('Blockly.ContextMenuItems'); /** @suppress {extraRequire} */ goog.require('Blockly.constants'); +goog.require('Blockly.ContextMenuRegistry'); goog.require('Blockly.Events'); goog.require('Blockly.inputTypes'); @@ -538,3 +539,4 @@ Blockly.ContextMenuItems.registerDefaultOptions = function() { Blockly.ContextMenuItems.registerBlockOptions_(); }; +Blockly.ContextMenuItems.registerDefaultOptions(); diff --git a/core/contextmenu_registry.js b/core/contextmenu_registry.js index 13a316405..f3f3b2205 100644 --- a/core/contextmenu_registry.js +++ b/core/contextmenu_registry.js @@ -16,15 +16,17 @@ */ goog.provide('Blockly.ContextMenuRegistry'); -goog.require('Blockly.ContextMenuItems'); +goog.requireType('Blockly.BlockSvg'); +goog.requireType('Blockly.WorkspaceSvg'); + /** - * Class for the registry of context menu items. This is intended to be a singleton. You should - * not create a new instance, and only access this class from Blockly.ContextMenuRegistry.registry. + * Class for the registry of context menu items. This is intended to be a + * singleton. You should not create a new instance, and only access this class + * from Blockly.ContextMenuRegistry.registry. * @constructor */ Blockly.ContextMenuRegistry = function() { - // Singleton instance should be registered once. Blockly.ContextMenuRegistry.registry = this; @@ -34,7 +36,6 @@ Blockly.ContextMenuRegistry = function() { * @private */ this.registry_ = {}; - Blockly.ContextMenuItems.registerDefaultOptions(); }; /** @@ -83,7 +84,8 @@ Blockly.ContextMenuRegistry.RegistryItem; Blockly.ContextMenuRegistry.ContextMenuOption; /** - * Singleton instance of this class. All interactions with this class should be done on this object. + * Singleton instance of this class. All interactions with this class should be + * done on this object. * @type {?Blockly.ContextMenuRegistry} */ Blockly.ContextMenuRegistry.registry = null; diff --git a/core/requires.js b/core/requires.js index c8aa3990b..f08286ec4 100644 --- a/core/requires.js +++ b/core/requires.js @@ -46,6 +46,10 @@ goog.require('Blockly.VariablesDynamic'); // If zoom controls aren't required, then Blockly.inject's // "zoom"/"controls" configuration must be false. goog.require('Blockly.ZoomControls'); +// This registers default keyboard shortcuts. +goog.require('Blockly.ShortcutItems'); +// This registers default contextmenu options. +goog.require('Blockly.ContextMenuItems'); // Block dependencies. diff --git a/core/shortcut_items.js b/core/shortcut_items.js index 2ffdecb91..352d829c5 100644 --- a/core/shortcut_items.js +++ b/core/shortcut_items.js @@ -16,11 +16,12 @@ */ goog.provide('Blockly.ShortcutItems'); +goog.require('Blockly.Gesture'); +goog.require('Blockly.ShortcutRegistry'); goog.require('Blockly.utils.KeyCodes'); goog.requireType('Blockly.BlockSvg'); goog.requireType('Blockly.ICopyable'); -goog.requireType('Blockly.ShortcutRegistry'); /** @@ -231,19 +232,21 @@ Blockly.ShortcutItems.registerRedo = function() { Blockly.ShortcutRegistry.registry.register(redoShortcut); var ctrlShiftZ = Blockly.ShortcutRegistry.registry.createSerializedKey( - Blockly.utils.KeyCodes.Z, [Blockly.utils.KeyCodes.SHIFT, - Blockly.utils.KeyCodes.CTRL]); - Blockly.ShortcutRegistry.registry.addKeyMapping(ctrlShiftZ, redoShortcut.name); + Blockly.utils.KeyCodes.Z, + [Blockly.utils.KeyCodes.SHIFT, Blockly.utils.KeyCodes.CTRL]); + Blockly.ShortcutRegistry.registry.addKeyMapping( + ctrlShiftZ, redoShortcut.name); var altShiftZ = Blockly.ShortcutRegistry.registry.createSerializedKey( - Blockly.utils.KeyCodes.Z, [Blockly.utils.KeyCodes.SHIFT, - Blockly.utils.KeyCodes.ALT]); + Blockly.utils.KeyCodes.Z, + [Blockly.utils.KeyCodes.SHIFT, Blockly.utils.KeyCodes.ALT]); Blockly.ShortcutRegistry.registry.addKeyMapping(altShiftZ, redoShortcut.name); var metaShiftZ = Blockly.ShortcutRegistry.registry.createSerializedKey( - Blockly.utils.KeyCodes.Z, [Blockly.utils.KeyCodes.SHIFT, - Blockly.utils.KeyCodes.META]); - Blockly.ShortcutRegistry.registry.addKeyMapping(metaShiftZ, redoShortcut.name); + Blockly.utils.KeyCodes.Z, + [Blockly.utils.KeyCodes.SHIFT, Blockly.utils.KeyCodes.META]); + Blockly.ShortcutRegistry.registry.addKeyMapping( + metaShiftZ, redoShortcut.name); // Ctrl-y is redo in Windows. Command-y is never valid on Macs. var ctrlY = Blockly.ShortcutRegistry.registry.createSerializedKey( @@ -265,3 +268,5 @@ Blockly.ShortcutItems.registerDefaultShortcuts = function() { Blockly.ShortcutItems.registerUndo(); Blockly.ShortcutItems.registerRedo(); }; + +Blockly.ShortcutItems.registerDefaultShortcuts(); diff --git a/core/shortcut_registry.js b/core/shortcut_registry.js index 5021cfcb9..3df7a0853 100644 --- a/core/shortcut_registry.js +++ b/core/shortcut_registry.js @@ -13,10 +13,9 @@ goog.provide('Blockly.ShortcutRegistry'); -goog.require('Blockly.ShortcutItems'); +goog.require('Blockly.utils.KeyCodes'); goog.require('Blockly.utils.object'); -goog.requireType('Blockly.utils.KeyCodes'); goog.requireType('Blockly.Workspace'); @@ -43,8 +42,6 @@ Blockly.ShortcutRegistry = function() { * @private */ this.keyMap_ = Object.create(null); - - Blockly.ShortcutItems.registerDefaultShortcuts(); }; /** @@ -113,8 +110,8 @@ Blockly.ShortcutRegistry.prototype.unregister = function(shortcutName) { /** * Adds a mapping between a keycode and a keyboard shortcut. - * @param {string} keyCode The key code for the keyboard shortcut. If - * registering a key code with a modifier (ex: ctrl+c) use + * @param {string|Blockly.utils.KeyCodes} keyCode The key code for the keyboard + * shortcut. If registering a key code with a modifier (ex: ctrl+c) use * Blockly.ShortcutRegistry.registry.createSerializedKey; * @param {string} shortcutName The name of the shortcut to execute when the * given keycode is pressed. @@ -125,6 +122,7 @@ Blockly.ShortcutRegistry.prototype.unregister = function(shortcutName) { */ Blockly.ShortcutRegistry.prototype.addKeyMapping = function( keyCode, shortcutName, opt_allowCollision) { + keyCode = String(keyCode); var shortcutNames = this.keyMap_[keyCode]; if (shortcutNames && !opt_allowCollision) { throw new Error( diff --git a/tests/mocha/contextmenu_items_test.js b/tests/mocha/contextmenu_items_test.js index 387e7083b..62dd6f9ea 100644 --- a/tests/mocha/contextmenu_items_test.js +++ b/tests/mocha/contextmenu_items_test.js @@ -14,6 +14,7 @@ suite('Context Menu Items', function() { // Declare a new registry to ensure default options are called. new Blockly.ContextMenuRegistry(); + Blockly.ContextMenuItems.registerDefaultOptions(); this.registry = Blockly.ContextMenuRegistry.registry; }); diff --git a/tests/mocha/shortcut_registry_test.js b/tests/mocha/shortcut_registry_test.js index b374187d4..9ca758645 100644 --- a/tests/mocha/shortcut_registry_test.js +++ b/tests/mocha/shortcut_registry_test.js @@ -8,6 +8,7 @@ suite('Keyboard Shortcut Registry Test', function() { setup(function() { sharedTestSetup.call(this); this.registry = new Blockly.ShortcutRegistry(); + Blockly.ShortcutItems.registerDefaultShortcuts(); }); teardown(function() { sharedTestTeardown.call(this);