-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Illegal program state occurs due to belated enforcement by onchange
methods
#8467
Comments
@cpcallen can you explain the issue briefly? |
Survey of existing
|
Invalid program state
One of Blockly's principles is that any connected group of blocks is a valid program. Not necessarily a correct program, but one which could compiled to syntactically valid code in a supported language and then run. This is leveraged by a number of Blockly projects, which generate and run code on every workspace update.
In the process of investigating #7950, it came to light that when a
procedures_ifreturn
block is inserted into aprocedures_defnoreturn
this principle is momentarily violated, because theifreturn
block'sVALUE
input is only removed afterwards, by itsonchange
handler. A quick investigation of otheronchange
handlers suggested that many of them also contained code smells for invalid program state.In addition to potential code-generation-correctness issues, the invalid state prevents undo from working correctly—in this case because undo attempts to reattach a return value to the
ifreturn
block before it removes theifreturn
block from thedefnoreturn
block.Proposal 1: Reaffirm that Blockly does not permit invalid program state
We should reaffirm the principle that Blockly does not allow invalid program states, and clarify that this means even momentarily:
Proposal 2: Provide a synchronous mechanism for ensuring program validity invariants are maintained
This would replace the use of
onchange
handlers with some other, more specific and synchronous mechanism, akin to field validators. Ideally this mechanism should be:onchange
handlers.(For LambdaMOO programmers: the check vs. update distinction is akin to
:acceptable
vs.:accept
in LambdaCore: either can allow or reject a move, but only the latter should have any side effects.)In the case of the
procedures_ifreturn
block, this would mean that theifreturn
block could remove itsVALUE
(return value) input (and thereby detach any child blocks from it) before its pending connected to aprocedures_defnoreturn
block is effected.Scope
While it is desirable that this machinery call the minimum number of validator functions when considering / making a connection, it is not sufficient for only the immediately-involved blocks to be validated.
controls_flow_statements
(break/continue) enable or disable themselves depending on whether they are enclosed in a loop block or not, orprocedures_ifreturn
to add/remove itsVALUE
input.onchange
handler currently allows but in a more timely way—or even all proposed changes.Proposal 3: Deprecate block
onchange
methodsWe can and probably should continue to support the
onchange
mechanism indefinitely for backwards compatibility with developer's custom blocks, we should stop usingonchange
methods in the library blocks and we should discourage their use by developers.onchange
methods are used to enforce program validity invariants (see survey in separate comment below), but they can only ever do so belatedly. It seems very likely that anyonchange
methods not used to enforce program validity could also be converted to use a proposed synchronous validation mechanism instead (just as we currently use field validators for block mutation).onchange
handlers are very powerful, because they can react to any change on the workspace, but also very inefficient, because a separate change listener is registered for every such block on the workspace; this means that a change listener is called for every such block on the workspace for every change, regardless of whether the change affects the block in question, and a workspace with N copies of a particular block will call the block definition'sonchange
method N times for every event, with onlythis
differing between calls. If fully-general event listening is useful will in many cases be better for developers to register a single change listener at the workspace level that will handle updates for all relevant blocks.See also:
procedures_ifreturn
detaches child block, but undoing doesn't reattach it. #7950The text was updated successfully, but these errors were encountered: