Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
b770245
:truck: chore(vm): migrate block.js, including logic fixes
SimonShiki May 12, 2026
6c5a790
:truck: chore(vm): migrate execute.js
SimonShiki May 12, 2026
a61bc88
:truck: chore(vm): migrate serialize-assets.js
SimonShiki May 12, 2026
5c2e09f
:truck: chore(vm): migrate sb2_specmap.ts
SimonShiki May 12, 2026
b649d9f
:truck: chore(vm): migrate target.js
SimonShiki May 12, 2026
7efe120
:truck: chore(vm): migrate rendered-target.js
SimonShiki May 12, 2026
7a9f4a0
:wrench: chore(vm): more neat ts usage
SimonShiki May 12, 2026
5a1d40b
:truck: chore(vm,render,storage): migrate left io/*.js and load-costu…
SimonShiki May 12, 2026
8486a47
:wrench: chore(vm): copied json block definitions from blockly
SimonShiki May 12, 2026
99c1169
:truck: chore(vm,audio): migrate load-sound.js
SimonShiki May 12, 2026
4bfff1e
:wrench: chore(vm): update import
SimonShiki May 12, 2026
5bc6341
:wrench: chore(vm): some cleanup
SimonShiki May 12, 2026
c10865a
:truck: chore(vm,audio): migrate runtime.js
SimonShiki May 13, 2026
1b9b66e
:bug: fix(vm,gui): add missing global declaration for gui & remove us…
SimonShiki May 13, 2026
47e4f46
:bug: fix(vm): tests
SimonShiki May 13, 2026
15a2b22
:truck: chore(vm,storage): migrate virtual-machine.js
SimonShiki May 13, 2026
10f5806
:bug: fix: build
SimonShiki May 13, 2026
1b4d1f8
:wrench: chore(vm): add event map to virtual machine
SimonShiki May 14, 2026
d432d37
:truck: chore(vm,storage): migrate extension-manager.js
SimonShiki May 14, 2026
8f90ea4
:truck: chore(vm): refine types
SimonShiki May 14, 2026
9a2b18a
:wrench: chore(vm): add missing runtime events
SimonShiki May 14, 2026
9aea110
:wrench: chore(vm): cleanup
SimonShiki May 14, 2026
e8182f6
:bug: fix(vm): fix wrong updateBitmapSkin usage
SimonShiki May 14, 2026
b0a6658
:wrench: chore: inline const enums as soon as possible
SimonShiki May 14, 2026
300d53a
:wrench: chore(vm): make Mouse accept zero for x/y
SimonShiki May 14, 2026
646fbd0
:truck: chore(vm,storage): migrate deserialize-assets.js
SimonShiki May 15, 2026
0b57dd3
:truck: chore(vm): migrate pen extension
SimonShiki May 16, 2026
607743e
:wrench: chore(vm): refine types
SimonShiki May 16, 2026
2aef46f
:bug: chore(vm): fix test & refine types
SimonShiki May 16, 2026
ac8f708
:wrench: chore(vm): migrate more extensions & refine types
SimonShiki May 17, 2026
13fc3fe
:truck: chore: migrate music extension
SimonShiki May 18, 2026
661b978
:wrench: chore: add node types for audio
SimonShiki May 18, 2026
7f5ff8a
:bug: fix(vm): wrong import
SimonShiki May 18, 2026
390a90e
:fire: chore(block): remove unused index.ts
SimonShiki May 18, 2026
bf7ef3a
:wrench: chore(vm): export necessary types
SimonShiki May 22, 2026
678c6eb
:wrench: chore(vm): refine types
SimonShiki May 28, 2026
3f44f77
:wrench: chore(vm): refine types
SimonShiki May 28, 2026
e155269
:art: chore(vm): remove unexpected empty line
SimonShiki May 28, 2026
05d8fc8
:wrench: chore(lint-config): don't require return jsdoc should have t…
SimonShiki May 28, 2026
033a8d1
:wrench: chore(vm): migrate extension-worker.js
SimonShiki May 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/audio/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"@babel/core": "7.29.0",
"@babel/eslint-parser": "7.28.6",
"@babel/preset-env": "7.29.2",
"@types/node": "^25.5.2",
"babel-eslint": "10.0.3",
"babel-loader": "^10.1.1",
"eslint": "^9.39.2",
Expand Down
6 changes: 3 additions & 3 deletions packages/audio/src/AudioEngine.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ class AudioEngine {
* Decode a sound, decompressing it into audio samples.
* @param {object} sound - an object containing audio data and metadata for
* a sound
* @param {Buffer} sound.data - sound data loaded from scratch-storage
* @param {{buffer: ArrayBuffer}} sound.data - sound data loaded from scratch-storage
* @returns {?Promise} - a promise which will resolve to the sound id and
* buffer if decoded
*/
Expand Down Expand Up @@ -217,8 +217,8 @@ class AudioEngine {
*
* @param {object} sound - an object containing audio data and metadata for
* a sound
* @param {Buffer} sound.data - sound data loaded from scratch-storage
* @returns {?Promise} - a promise which will resolve to the buffer
* @param {{buffer: ArrayBuffer}} sound.data - sound data loaded from scratch-storage
* @returns - a promise which will resolve to the buffer
*/
decodeSoundPlayer (sound) {
return this._decodeSound(sound)
Expand Down
2 changes: 1 addition & 1 deletion packages/audio/src/SoundPlayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class SoundPlayer extends EventEmitter {

/**
* Output audio node.
* @type {AudioNode}
* @type {AudioBufferSourceNode}
*/
this.outputNode = null;

Expand Down
8 changes: 4 additions & 4 deletions packages/block/src/blocks/control.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Blockly.Blocks['control_forever'] = {
message0: Blockly.Msg.CONTROL_FOREVER,
message1: '%1', // Statement
message2: '%1', // Icon
lastDummyAlign2: 'RIGHT',
implicitAlign2: 'RIGHT',
args1: [
{
type: 'input_statement',
Expand Down Expand Up @@ -69,7 +69,7 @@ Blockly.Blocks['control_repeat'] = {
message0: Blockly.Msg.CONTROL_REPEAT,
message1: '%1', // Statement
message2: '%1', // Icon
lastDummyAlign2: 'RIGHT',
implicitAlign2: 'RIGHT',
args0: [
{
type: 'input_value',
Expand Down Expand Up @@ -263,7 +263,7 @@ Blockly.Blocks['control_repeat_until'] = {
message0: Blockly.Msg.CONTROL_REPEATUNTIL,
message1: '%1',
message2: '%1',
lastDummyAlign2: 'RIGHT',
implicitAlign2: 'RIGHT',
args0: [
{
type: 'input_value',
Expand Down Expand Up @@ -302,7 +302,7 @@ Blockly.Blocks['control_while'] = {
message0: Blockly.Msg.CONTROL_WHILE,
message1: '%1',
message2: '%1',
lastDummyAlign2: 'RIGHT',
implicitAlign2: 'RIGHT',
args0: [
{
type: 'input_value',
Expand Down
4 changes: 2 additions & 2 deletions packages/block/src/blocks/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Blockly.Blocks['data_variable'] = {
init: function(this: Blockly.Block) {
this.jsonInit({
message0: '%1',
lastDummyAlign0: 'CENTRE',
implicitAlign0: 'CENTRE',
args0: [
{
type: 'field_variable_getter',
Expand Down Expand Up @@ -142,7 +142,7 @@ Blockly.Blocks['data_listcontents'] = {
init: function(this: Blockly.Block) {
this.jsonInit({
message0: '%1',
lastDummyAlign0: 'CENTRE',
implicitAlign0: 'CENTRE',
args0: [
{
type: 'field_variable_getter',
Expand Down
2 changes: 1 addition & 1 deletion packages/block/src/events/block_comment_collapse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export class BlockCommentCollapse extends BlockCommentBase {
override type = 'block_comment_collapse';

/** Whether the comment is collpased. */
protected newCollapsed?: boolean;
newCollapsed?: boolean;

/**
* @param icon The comment icon this event corresponds to.
Expand Down
4 changes: 2 additions & 2 deletions packages/block/src/events/func_change.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ export class FuncChange extends FuncBase {
override type = FuncChange.TYPE;

/** The previous extra state of the procedure. */
protected oldExtraState?: ProcedureExtraState;
oldExtraState?: ProcedureExtraState;

/** The new extra state of the procedure. */
protected newExtraState?: ProcedureExtraState;
newExtraState?: ProcedureExtraState;

/**
* @param procedure The procedure model.
Expand Down
13 changes: 13 additions & 0 deletions packages/block/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,21 @@ export type * as variableModel from './variable_model';
export {reportValue} from './report_value';
export {Colours} from './theme';
export {BlockDragEnd} from './events/block_drag_end';
export {BlockDragOutside} from './events/block_drag_outside';
export {FuncChange} from './events/func_change';
export {FuncCreate} from './events/func_create';
export {FuncDelete} from './events/func_delete';
export {BlockCommentCreate} from './events/block_comment_create';
export {BlockCommentDelete} from './events/block_comment_delete';
export {BlockCommentMove} from './events/block_comment_move';
export {BlockCommentResize} from './events/block_comment_resize';
export {BlockCommentCollapse} from './events/block_comment_collapse';
export {BlockChange} from './events/block_change';
export {VarCreate} from './events/var_create';
export {VarDelete} from './events/var_delete';
export * as Theme from './theme';
export {glowStack} from './glow';
export type {BlockCommentState} from './block_comment_icon';

export {
FieldAngle,
Expand Down
2 changes: 1 addition & 1 deletion packages/gui/.babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
"presets": [
["@babel/preset-env", {"targets": {"browsers": ["last 3 versions", "Safari >= 8", "iOS >= 8"]}}],
"@babel/preset-react",
"@babel/preset-typescript"
["@babel/preset-typescript", {"optimizeConstEnums": true}]
]
}
13 changes: 13 additions & 0 deletions packages/gui/src/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type ScratchLinkWebSocket from '../../vm/src/util/scratch-link-websocket';

type ScratchLinkSafariSocket = (new (type: 'BLE' | 'BT') => ScratchLinkWebSocket) & {
isSafariHelperCompatible: () => boolean;
};

declare global {
interface Window {
Scratch?: {
ScratchLinkSafariSocket?: ScratchLinkSafariSocket;
}
}
}
3 changes: 2 additions & 1 deletion packages/gui/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"include": [
"./src/**/*",
"./test/**/*"
"./test/**/*",
"types/**/*.d.ts"
],
"compilerOptions": {
/* Visit https://aka.ms/tsconfig to read more about this file */
Expand Down
1 change: 1 addition & 0 deletions packages/lint-config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ module.exports = [
rules: {
// Most packaages uses JSDoc to generate declaration files, which has lots of undefined types.
'jsdoc/no-undefined-types': 'warn',
'jsdoc/require-returns-type': 'off', /** tsc can infer return types */
'jsdoc/reject-function-type': 'warn',
'jsdoc/check-param-names': 'error',
'jsdoc/check-tag-names': 'error',
Expand Down
2 changes: 1 addition & 1 deletion packages/lint-config/ts.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ module.exports = [
// Disable JSDoc type requirements for TypeScript (it has its own types)
'jsdoc/require-jsdoc': 'off',
'jsdoc/require-param-type': 'off',
'jsdoc/require-returns-type': 'off',
'jsdoc/require-property-type': 'off',
'func-style': 'off',

// Disable rules that conflict with TypeScript's type system
Expand Down
13 changes: 7 additions & 6 deletions packages/render/src/RenderWebGL.js
Original file line number Diff line number Diff line change
Expand Up @@ -381,8 +381,8 @@ class RenderWebGL extends EventEmitter {
/**
* Create a new SVG skin.
* @param {!string} svgData - new SVG to use.
* @param {?Array<number>} rotationCenter Optional: rotation center of the skin. If not supplied, the center of the
* skin will be used
* @param {?Array<number>} [rotationCenter] Optional: rotation center of the skin. If not supplied,
* the center of the skin will be used
* @returns {!int} the ID for the new skin.
*/
createSVGSkin (svgData, rotationCenter) {
Expand Down Expand Up @@ -443,7 +443,8 @@ class RenderWebGL extends EventEmitter {
* @param {!int} skinId the ID for the skin to change.
* @param {!ImageData|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} imgData - new contents for this skin.
* @param {!number} bitmapResolution - the resolution scale for a bitmap costume.
* @param {?Array<number>} rotationCenter Optional: rotation center of the skin. If not supplied, the center of the
* @param {?Array<number>} [rotationCenter] Optional:
* rotation center of the skin. If not supplied, the center of the
* skin will be used
*/
updateBitmapSkin (skinId, imgData, bitmapResolution, rotationCenter) {
Expand Down Expand Up @@ -508,7 +509,7 @@ class RenderWebGL extends EventEmitter {
/**
* Create a new Drawable and add it to the scene.
* @param {string} group Layer group to add the drawable to
* @returns {int | void} The ID of the new Drawable.
* @returns The ID of the new Drawable.
*/
createDrawable (group) {
if (!group || !Object.prototype.hasOwnProperty.call(this._layerGroups, group)) {
Expand Down Expand Up @@ -800,7 +801,7 @@ class RenderWebGL extends EventEmitter {
/**
* Get the size of a skin by ID.
* @param {int} skinID The ID of the Skin to measure.
* @returns {Array<number>} Skin size, width and height.
* @returns {[number, number]} Skin size, width and height.
*/
getSkinSize (skinID) {
const skin = this._allSkins[skinID];
Expand All @@ -810,7 +811,7 @@ class RenderWebGL extends EventEmitter {
/**
* Get the rotation center of a skin by ID.
* @param {int} skinID The ID of the Skin
* @returns {Array<number>} The rotationCenterX and rotationCenterY
* @returns {[number, number]} The rotationCenterX and rotationCenterY
*/
getSkinRotationCenter (skinID) {
const skin = this._allSkins[skinID];
Expand Down
4 changes: 2 additions & 2 deletions packages/render/src/Skin.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class Skin extends EventEmitter {

/**
* @abstract
* @returns {Array<number>} the "native" size, in texels, of this skin.
* @returns {[number, number]} the "native" size, in texels, of this skin.
*/
get size () {
return [0, 0];
Expand All @@ -106,7 +106,7 @@ class Skin extends EventEmitter {

/**
* Get the center of the current bounding box
* @returns {Array<number>} the center of the current bounding box
* @returns {[number, number]} the center of the current bounding box
*/
calculateRotationCenter () {
return [this.size[0] / 2, this.size[1] / 2];
Expand Down
2 changes: 1 addition & 1 deletion packages/storage/src/Asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export default class Asset {
*/
constructor (
public assetType: IAssetType,
public assetId?: AssetId,
public assetId?: AssetId |null,
dataFormat?: DataFormat,
data?: AssetData,
generateId?: boolean
Expand Down
8 changes: 4 additions & 4 deletions packages/storage/src/ScratchStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export class ScratchStorage {
* @param assetId - The id of the asset to fetch.
* @returns The asset, if it exists.
*/
get (assetId: string): Asset | null {
get (assetId: AssetId): Asset | null {
return this.builtinHelper.get(assetId);
}

Expand Down Expand Up @@ -134,8 +134,8 @@ export class ScratchStorage {
assetType: IAssetType,
dataFormat: DataFormat,
data: AssetData,
id: AssetId,
generateId: boolean
id?: AssetId | null,
generateId?: boolean
): Asset {
if (!dataFormat) throw new Error('Tried to create asset without a dataFormat');
return new Asset(assetType, id, dataFormat, data, generateId);
Expand Down Expand Up @@ -202,7 +202,7 @@ export class ScratchStorage {
* If the promise is rejected, there was an error on at least one asset source. HTTP 404 does not count as an
* error here, but (for example) HTTP 403 does.
*/
load (assetType: IAssetType, assetId: AssetId, dataFormat: DataFormat): Promise<Asset | null> {
load (assetType: IAssetType, assetId: AssetId, dataFormat?: DataFormat): Promise<Asset | null> {
const helpers = this._helpers.map(x => x.helper);
const errors: unknown[] = [];
dataFormat = dataFormat || assetType.runtimeFormat;
Expand Down
10 changes: 0 additions & 10 deletions packages/vm/.babelrc

This file was deleted.

20 changes: 20 additions & 0 deletions packages/vm/.babelrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const TESTING = process.env.NODE_ENV === 'test';

const config = {
presets: [
['@babel/preset-env', {
targets: {
browsers: ['last 3 versions', 'Safari >= 8', 'iOS >= 8']
}
}],
['@babel/preset-typescript', {optimizeConstEnums: true}]
]
};

if (TESTING) {
config.plugins = [
['babel-plugin-transform-import-meta']
];
}

module.exports = config;
2 changes: 1 addition & 1 deletion packages/vm/docs/extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ const TargetType = require('../../extension-support/target-type');
const formatMessage = require('format-message');

// Core, Team, and Official extension classes should be registered statically with the Extension Manager.
// See: scratch-vm/src/extension-support/extension-manager.js
// See: scratch-vm/src/extension-support/extension-manager.ts
class SomeBlocks {
constructor (runtime) {
/**
Expand Down
4 changes: 2 additions & 2 deletions packages/vm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"url": "https://github.com/Clipteam/clipcc.git"
},
"exports": {
"types": "./dist/types/index.d.ts",
"types": "./dist/types/src/index.d.ts",
"webpack": "./src/index.ts",
"node": "./dist/node/scratch-vm.js",
"browser": "./dist/web/scratch-vm.min.js",
Expand Down Expand Up @@ -66,14 +66,14 @@
"babel-eslint": "10.1.0",
"babel-jest": "23.6.0",
"babel-loader": "^10.1.1",
"babel-plugin-transform-import-meta": "^2.3.3",
"callsite": "1.0.0",
"clipcc-audio": "workspace:~",
"clipcc-block": "workspace:~",
"clipcc-l10n": "workspace:~",
"clipcc-render": "workspace:~",
"clipcc-storage": "workspace:~",
"clipcc-svg-renderer": "workspace:~",
"codingclip-worker-loader": "^3.0.10",
"copy-webpack-plugin": "^14.0.0",
"domhandler": "^5.0.3",
"eslint": "^9.39.2",
Expand Down
3 changes: 3 additions & 0 deletions packages/vm/src/blocks/category_prototype.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import type BlockUtility from '../engine/block-utility';
import type {HatMetadata, MonitorBlockInfo} from '../engine/runtime';
import type Runtime from '../engine/runtime';

export type BlockArgs = {
[argName: string]: any;
Expand All @@ -19,3 +20,5 @@ export interface CategoryPrototype {
getMonitored?(): Record<string, MonitorBlockInfo>;
getOrders?(): Record<string, (string | {execute: string})[]>;
}

export type CategoryPrototypeConstructor = new (runtime: Runtime) => CategoryPrototype;
Loading
Loading