Modifying or Patching existing blocks with javascript.

69 views
Skip to first unread message

Brandan (Builderb)

unread,
Mar 15, 2024, 7:24:27 PM3/15/24
to Blockly
Hi is there a way to modify/patch existing blocks such as changing the default input connection checks list or adding extensions to them.
This would be nice so people don't have to monkey patch the default blocks and break something in a later release.

Christopher Allen

unread,
Mar 15, 2024, 7:44:34 PM3/15/24
to blo...@googlegroups.com
Hi Brandan,

Hi is there a way to modify/patch existing blocks such as changing the default input connection checks list or adding extensions to them.
This would be nice so people don't have to monkey patch the default blocks and break something in a later release.

Broadly speaking probably the safest way to modify one of the provided library blocks is to copy it and make the changes you want.  It is true that this will mean you don't get future updates, but the library block definitions change fairly rarely.

The only ways to modify or patch those definitions all look _more_ like monkey patching, not _less_, but certainly it is possible.

Ultimately no matter how you define a block (JS or JSON) it ultimately ends up as a mixin object that includes an init method, where the init method does most of the work setting up the blocks fields/inputs/etc.

So if you wanted to modify the definition of some_block you can always do so:

// Save original init method for later use:
origInit = Blockly.Blocks['some_block'].init;
// Optionally override the init method
Blockly.Blocks['some_block'].init = function() {
  // Optionally do some setup before calling the original init method.
  // Optionally call the original init method:
  origInit.call(this);
  // Optionally do some more setup after calling the original init method.
};
// Add an extra method to the block definition:
Blockly.Blocks['some_block'].newMethod = function(/* args */) { /* implementation */ };

But in general this will likely be a bit frustrating as all the interesting stuff happens in init and there's no real way to modify what it does, only call it or not call it.  We don't even export the JSON definitions for blocks so defined, so you can't even take a copy of the JSON, modify  it, and define a block type using the modified copy.

We discussed exporting JSON when we recently started work to move some of the library blocks into plugins but ultimately decided against doing so.

I have also mooted a proposal to change the way we create block definitions for the library blocks (though not change the mixin-object-with-init-method format that Blockly ingests).  If we do update our block definitions to use this more class-based system, it might be possible to extend a block definition by subclassing, though this would not be as straight-forward as it sounds and in any case this proposal is unlikely to be implemented in the near future.


Thanks for raising this interesting topic, though.


Christopher





Brandan (Builderb)

unread,
Mar 17, 2024, 6:37:40 PM3/17/24
to Blockly
Thanks that works perfectly, as a suggestion this could be something added to the base blockly where you can set a Blockly.Blocks['some_block'].afterInit = function() that will be called after init() has been run.
Reply all
Reply to author
Forward
0 new messages