Skip to content

Conversation

@pufferfish101007
Copy link
Contributor

@pufferfish101007 pufferfish101007 commented Nov 9, 2025

This would resolve #8427 if finished and merged.
Related: #7475; suggestion in community server; discussion in dev server (scroll down for more technical discussion).

I don't expect that this will ever make it into the main repository, but it'd be cool if it did.

Although this is marked as a draft, feedback would be appreciated at any stage, especially in relation to the broad implementation.

Changes

This adds a new "custom reporters" addon that allows users to create custom blocks that return values. These are patched in the VM to be executed correctly, and then transpiled at serialisation to valid scratch blocks.

These blocks are not fully compatible with TurboWarp's custom reporters. I think they share the same opcodes in the internal representation, but beyond that there are very few similarities, as TurboWarp is able to integrate the expected behaviour without worrying about compatibility with vanilla scratch.

This is a proof of concept, and as such it is very rough around the edges and not at all in a state where it is usable for general purposes. I will list problems that I am aware of in a later section; it should be noted that currently the addon is marked as 'enabled by default' for my own testing purposes.

The custom block editor now looks like this:
image

There are currently two modes of transpilation; these are not necessarily good transpilation schemes but they work well in many common cases. In each transpiler mode, the VM is patched to execute the custom reporters in the way that they would be executed when transpiled to vanilla scratch, rather than being executed in the way you might naively expect (e.g. if used to TurboWarp's custom reporters).

Variable transpilation mode

This sets a variable to the return value. This works fine for non-recursive functions, or recursive functions that use the value of a recursive call at most once per stack block.

With addon enabled:
image

With addon disabled:
image
(script positions were changed manually)

List (no GC) transpilation mode

This appends the return value to a list. The list is never emptied (hence the "no GC" naming). In theory, this works fine for any sort of recursive function, provided that it is run without refresh and never triggers the warp timer (these restrictions apply to the variable transpiler mode as well). In practice, at the moment I don't think nested recursive calls will be applied correctly.

With addon enabled:
image

With addon disabled:
image

Reason for changes

The variable workaround for custom reporters seems to be well-known and well-used among more advanced scratchers. Making it easier to do this sort of thing might be nice for some people. Custom reporters seemed to be received quite well with TurboWarp, which suggests that there is an audience for this (although perhaps they'd rather use TurboWarp's better implementation of it regardless). Perhaps more importantly, it's interesting to see how much we can extend the language without breaking things too badly.

Tests

Leaving empty for now, as it is easier to list things that don't work correctly than those that do.

Known issues

  • If reporter or boolean block shape is chosen, adding a new input/label causes the very first label to not be selectable to edit until the block shape is changed to something else (and potentially changed back) - but still selectable by tabbing
  • Adding inputs once block shape is selected gives error Cannot read properties of null (reading 'FIELD_BORDER_RECT_RADIUS')
  • Clicking "edit" in the context menu of a custom reporter (call or definition) does not work (need to figure out how to patch non-exported methods)
  • When editing a custom block (whether procedure or reporter), clicking 'OK' creates a new custom block rather than editing the existing one
  • Once the custom block editor modal has been used once and closed and reopened, inputs can no longer be added
  • Reporter definition blocks don't display with the correct hat shape (using the shape_bowler_hat extension causes errors)
  • Inputs to custom reporter calls sometimes disappear. Seems to be particularly prevalent if the input is a variable
  • Nested recursive calls (i.e. of the form f (f x)) I think don't transpile as correctly using the list transpiler; if this does work, it is probably by coincidence of the order in which blocks appear in the project.json.
  • Sometimes the addon doesn't seem to recognise reporter calls correctly
  • while <>, repeat until <> and for each [i v] in () don't currently re-evaluate custom reporters each iteration (they should)

There is probably more that I am forgetting, or have yet to discover.

Future work

  • Hide the autogenerated return variables/lists from the block pallet when the addon is enabled
  • Additional transpilers using this or this or this (all discord links)
  • Perhaps automagically select the best transpiler for each block
  • Get rid of the necessity to have additional mutation properties when transpiled to vanilla
  • Perhaps recognise similar patterns (e.g. with non-autogenerated variable names; end stop block missing) to display in reporter style
  • Investigate performance and code size impact of each method of transpilation
  • Investigate compatibility with other addons that change the custom block editor modal - just "rearrange custom block inputs" and "recolour custom blocks" I think; also check compat with cat blocks
  • Ensure compatibility with new blockly

Open questions

  • What should be done about overlapping blocks when the addon is turned off? I think this issue may have been discussed before w.r.t. custom block shape, but it is probably a bit more extreme here.
  • What should be done about orphaned reporter calls? Currently they are transpiled to just the return variable access, but this loses information about the inputs. They also don't give the correct result in the little thing that pops up when you click on a reporter.
  • What should be done about return blocks that are not in a definition? Currently these cause a crash as it's not possible to identify which variable to write to.
  • What should be done about custom reporters placed inside of a hat block? e.g. when loudness > (something)?

Todo before merging (if ever)

pufferfish101007 and others added 3 commits November 12, 2025 17:07
This reverts commit 6ed9dcf to
temporarily allow testing on the spork branch of scratch-editor (which
hasn't updated the react version yet)
@pufferfish101007
Copy link
Contributor Author

pufferfish101007 commented Nov 14, 2025

I have updated the code to use the new blockly/spork. I have dropped the old code using the old blockly because they diverge enough that it would be difficult to maintain both. I had to revert #8611 to be able to test on spork; this will need to be unreverted at some point in the future. It should be noted that some things aren't quite on par with the old blockly implementation just yet.

@FlamedDogo99
Copy link
Contributor

  • Investigate compatibility with other addons that change the custom block editor modal - just "rearrange custom block inputs" and "recolour custom blocks" I think; also check compat with cat blocks

recolor custom blocks only “splices”, calls into methods like createAllInputs, so as long as you don’t completely override those methods, compatibility should be fairly easy.

rearrange custom blocks unfortunately completely overrides init and createAllInputs for the procedures declaration block when it’s enabled, so it will likely have to be reworked to behave with your changes. (This gets painful with dynamic enable/disable)

@pufferfish101007
Copy link
Contributor Author

@FlamedDogo99 thanks for the heads up - it sounds like there shouldn't be any compatibility problems with the procedures_prototype blocks as I only patch on top of existing methods for that particular block. There might be issues with addition of extra buttons but that should be solvable with a shared space or similar. I will of course do some proper testing at some point in the future.

@faretek1
Copy link

faretek1 commented Nov 20, 2025

one note, because goboscript has this issue:
Have you considered the behaviour of the repeat_until, while and for each (i) in (x) loops? Each of these (including the for block; it has weird behaviour) will re-evaluate the input on each iteration. Your reporter should be called before the first iteration and the end of every next iteration.

associated goboscript issue

@pufferfish101007
Copy link
Contributor Author

@faretek1 thank you for pointing this out - I hadn't considered this. I think at the moment it should behave as expected for addon users, but definitely won't transpile sensibly.

@pufferfish101007
Copy link
Contributor Author

Another thing to think about: what should be done about custom reporters placed inside of a hat block? e.g. when loudness > (something)? Perhaps it would be justified to outright refuse to allow custom reporter blocks to placed inside such positions, but i'm not too sure how easy that would be to do.

@mxmou
Copy link
Member

mxmou commented Nov 23, 2025

Perhaps it would be justified to outright refuse to allow custom reporter blocks to placed inside such positions, but i'm not too sure how easy that would be to do.

It might be possible to use Blockly's system of return types/connection checks to enforce this.

@Samq64 Samq64 added new addon Related to new addons to this extension. `scope: addons` should still be added. scope: addon Related to one or multiple addons labels Nov 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

new addon Related to new addons to this extension. `scope: addons` should still be added. scope: addon Related to one or multiple addons

Projects

None yet

Development

Successfully merging this pull request may close these issues.

An idea for custom reporters

5 participants