02Engine JavaScript Direct Coding Feature
Overview
02Engine extends the Scratch GUI by allowing developers to write JavaScript code directly inside comments on hat blocks, bypassing the traditional block-to-JavaScript compilation process.
When the compiler detects a #code comment, it directly uses the JavaScript code inside the comment as the executable script body.
Features
- Direct JavaScript Execution: Write JS code in comments and compile/run it directly
- Full Runtime Access: Access the complete internal Scratch VM API
- Generator Function Support: Use the
yieldkeyword to pause execution between frames - Parameter Passing: Access parameters of custom procedures
- Backward Compatibility: Fully compatible with existing Scratch projects
Usage
1. Adding a Comment
Add a comment to a hat block (such as “when green flag clicked”) using the following format:
#code
// Your JavaScript code
console.log("Hello from JS!");
target.setXY(100, 50);
Or in a single line:
#code console.log("Single-line code");
You can directly use the block function to call Scratch blocks, for example:
block.looks_sayforsecs({ MESSAGE: "Hello", SECS: 2 }, { target: target });
You can quickly access variables using the vars.stage / vars.target helpers:
// Access a list
list = vars.stage("My List", "list"); // global list
list.value.push(123);
list._monitorUpToDate = false; // refresh display
// Access variables
variable = vars.stage("My Variable"); // global variable
selfvar = vars.target("Private Variable"); // local variable
variable.value++;
variable._monitorUpToDate = false;
You can use yield* wait to implement delays:
yield* wait(1000); // milliseconds
Each script must end with:
retire();
return;
2. Comment Rules
#codemust occupy an entire line or appear at the beginning of a line- All lines following
#codeare treated as JavaScript code - Multi-line JavaScript is supported
- Other comment content is allowed, but only the
#codesection is parsed
3. Writing Code
Available predefined variables:
| Name | Type | Description |
|---|---|---|
target | RenderedTarget | Sprite executing the script |
runtime | Runtime | Scratch runtime instance |
stage | RenderedTarget | Stage object |
thread | Thread | Current execution thread |
p0, p1, ... | any | Procedure parameters |
Technical Implementation
Modified Files
1. intermediate.js
/**
* Custom JavaScript code for this script, if any.
* @type {string|null}
*/
this.customCode = null;
2. irgen.js
Core logic:
- Detect lines starting with
#code - Collect subsequent lines as JavaScript
- Auto-detect
yield - Store code in
this.script.customCode
3. jsgen.js
if (this.script.customCode) {
source = this.script.customCode;
}
Compilation Flow
- Parse hat block comments
- Use
customCodedirectly if present - Execute inside the Scratch runtime
Example Code
Example 1: Simple Movement
let x = 100;
let y = 100;
let dx = 5;
let dy = 3;
while (true) {
x += dx;
y += dy;
if (x > 240 || x < -240) dx = -dx;
if (y > 180 || y < -180) dy = -dy;
target.setXY(x, y);
yield;
}
Example 2: Mouse Following
while (true) {
const mouse = runtime.ioDevices.mouse;
target.setXY(mouse._clientX - 240, 180 - mouse._clientY);
yield;
}
Example 3: Loop Output
target.setXY(0, 0);
for (let i = 0; i < 10; i++) {
block.looks_sayforsecs({ MESSAGE: i, SECS: 0.5 });
yield* wait(500);
}
retire(); return;
Notes
Security
- JavaScript executes directly; only trust safe code
- Beware of injection risks
Performance
- Always use
yieldin long loops - Avoid heavy per-frame allocations
Compatibility
- APIs depend on Scratch VM internals
- Test across versions and browsers
License
This feature is based on the Scratch open-source project and follows its license.
Please ensure compliance with Scratch’s terms of use.