@kubohiroya/turbowarp-extension-data-editor 0.8.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.ja.md CHANGED
@@ -153,7 +153,7 @@ npm install --save-exact @kubohiroya/turbowarp-extension-data-editor@0.2.2
153
153
 
154
154
  ## Optional editing examples
155
155
 
156
- Repository examples are opt-in teaching code, not template blocks or additional package exports. See [the JSON/YAML document example](examples/document-properties.mjs) and [its guide](examples/README.ja.md). Each extension owns its actual data contract.
156
+ Repository examples are opt-in teaching code, not template blocks or additional package exports. See [the JSON/YAML document example](examples/document-properties.ts) and [its guide](examples/README.ja.md). Each extension owns its actual data contract.
157
157
 
158
158
  Prepared source editing is an optional host capability. See [the source/form contract](docs/source-forms.ja.md) for fixed-schema bindings, atomic saves, compatibility, and rollback.
159
159
 
package/README.md CHANGED
@@ -151,7 +151,7 @@ The cross-repository validation record collected when introducing the existing S
151
151
 
152
152
  ## Optional editing examples
153
153
 
154
- Repository examples are opt-in teaching code, not template blocks or additional package exports. See [the JSON/YAML document example](examples/document-properties.mjs) and [its guide (Japanese)](examples/README.ja.md). Each extension owns its actual data contract.
154
+ Repository examples are opt-in teaching code, not template blocks or additional package exports. See [the JSON/YAML document example](examples/document-properties.ts) and [its guide (Japanese)](examples/README.ja.md). Each extension owns its actual data contract.
155
155
 
156
156
  Prepared source editing is an optional host capability. See [the source/form contract (Japanese)](docs/source-forms.ja.md) for fixed-schema bindings, atomic saves, compatibility, and rollback.
157
157
 
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@kubohiroya/turbowarp-extension-data-editor",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "repository": "https://github.com/kubohiroya/turbowarp-extension-data-editor",
5
- "revision": "5b8c653c6536518cf87c8b1273f73ff9eb47e1ca",
5
+ "revision": "74d367a8de1980343240d4ded4de0f1ec37ed8e1",
6
6
  "sourceState": "commit",
7
- "sourceSha256": "03d7dca0e78358e05dc242f769d71a4e90c0c49fdb7fa6b6f7196dd4281dcca2",
7
+ "sourceSha256": "194e2b4516115bd108da3a367228e037aa1405a8a24e0325d46af2eaa51f326d",
8
8
  "capabilities": {
9
9
  "preparedSource": 1
10
10
  }
@@ -1,7 +1,8 @@
1
- export default readBlockEditorAppearance;
2
- declare function readBlockEditorAppearance(block: any, ScratchBlocks: any, editableArguments: any): {
3
- name: any;
4
- colour: string;
5
- tint: string;
6
- iconURI: string;
1
+ import type { NativeBlock, NativeScratchBlocks } from './native-types.js';
2
+ declare const readBlockEditorAppearance: (block: NativeBlock | null, ScratchBlocks: NativeScratchBlocks, editableArguments?: readonly string[]) => {
3
+ name?: string;
4
+ colour?: string;
5
+ tint?: string;
6
+ iconURI?: string;
7
7
  };
8
+ export default readBlockEditorAppearance;
@@ -1,22 +1,17 @@
1
- export default createBlockEditorBridge;
2
- declare function createBlockEditorBridge({ ScratchBlocks, workspace, vm, service, label, canOpen, onOpen, onError, descendants, fixedInputs }: {
3
- ScratchBlocks: any;
4
- workspace: any;
5
- vm: any;
6
- service: any;
7
- label: any;
8
- canOpen: any;
9
- onOpen: any;
10
- onError: any;
11
- descendants?: boolean | undefined;
12
- fixedInputs?: boolean | undefined;
13
- }): {
1
+ import type { TurboWarpBlockEditorOptions } from '../turbowarp.js';
2
+ import type { BlockEditorHost, BlockReference } from '../types.js';
3
+ import type { EditorRegistry } from '../registry.js';
4
+ declare const openBlockEditorSession: ({ registry, reference, host, descendants }: {
5
+ registry: EditorRegistry;
6
+ reference: BlockReference;
7
+ host: BlockEditorHost;
8
+ descendants: boolean;
9
+ }) => import("../descendants.js").DescendantSession | import("../session.js").EditorSession | undefined;
10
+ declare const createBlockEditorBridge: ({ ScratchBlocks: nativeBlocks, workspace: nativeWorkspace, vm: nativeVM, service, label, canOpen, onOpen, onError, descendants, fixedInputs }: TurboWarpBlockEditorOptions & {
11
+ onError(error: unknown): void;
12
+ }) => {
14
13
  refresh: () => void;
15
14
  dispose: () => void;
16
15
  };
17
- export function openBlockEditorSession({ registry, reference, host, descendants }: {
18
- registry: any;
19
- reference: any;
20
- host: any;
21
- descendants: any;
22
- }): any;
16
+ export default createBlockEditorBridge;
17
+ export { openBlockEditorSession };
@@ -17,7 +17,10 @@ const openBlockEditorSession = ({ registry, reference, host, descendants }) => {
17
17
  return descendants && supportsDescendantEditing(host) ?
18
18
  registry.openDescendants(reference, host) : registry.open(reference, host);
19
19
  };
20
- const createBlockEditorBridge = ({ ScratchBlocks, workspace, vm, service, label, canOpen, onOpen, onError, descendants = false, fixedInputs = false }) => {
20
+ const createBlockEditorBridge = ({ ScratchBlocks: nativeBlocks, workspace: nativeWorkspace, vm: nativeVM, service, label, canOpen, onOpen, onError, descendants = false, fixedInputs = false }) => {
21
+ const ScratchBlocks = nativeBlocks;
22
+ const workspace = nativeWorkspace;
23
+ const vm = nativeVM;
21
24
  const host = createBlockEditorHost({ ScratchBlocks,
22
25
  workspace,
23
26
  vm,
@@ -40,7 +43,7 @@ const createBlockEditorBridge = ({ ScratchBlocks, workspace, vm, service, label,
40
43
  }
41
44
  };
42
45
  let disposed = false;
43
- let timer = null;
46
+ let timer;
44
47
  let activeSession = null;
45
48
  let openingSnapshot = null;
46
49
  let openingFixedDeclaration = null;
@@ -49,7 +52,7 @@ const createBlockEditorBridge = ({ ScratchBlocks, workspace, vm, service, label,
49
52
  const session = activeSession;
50
53
  if (!session)
51
54
  return;
52
- if (typeof session.invalidate === 'function') {
55
+ if ('invalidate' in session && typeof session.invalidate === 'function') {
53
56
  session.invalidate();
54
57
  return;
55
58
  }
@@ -61,42 +64,43 @@ const createBlockEditorBridge = ({ ScratchBlocks, workspace, vm, service, label,
61
64
  stopWaiting = session.subscribe(() => {
62
65
  if (session.getState().status === 'saving')
63
66
  return;
64
- stopWaiting();
67
+ stopWaiting === null || stopWaiting === void 0 ? void 0 : stopWaiting();
65
68
  stopWaiting = null;
66
69
  session.dispose();
67
70
  });
68
71
  }
69
72
  };
70
73
  const checkSession = () => {
71
- var _a;
74
+ var _a, _b;
72
75
  // The host owns rollback. Its synchronous transaction must retain the draft on failure.
73
76
  if (host.isCommitting())
74
77
  return;
75
78
  if (!activeSession || !openingSnapshot ||
76
79
  !['editing', 'saving'].includes(activeSession.getState().status))
77
80
  return;
78
- const current = typeof activeSession.getNodes === 'function' ?
81
+ const current = 'getNodes' in activeSession ?
79
82
  host.descendants.readSubtree(activeSession.reference) : host.readBlock(activeSession.reference);
80
83
  if (openingFixedDeclaration) {
81
84
  // Same-target external edits conflict at save while the session retains its draft.
82
85
  // Project/target/registration replacement ends the session and drops that draft.
83
- if (!current || ((_a = current.fixedContext) === null || _a === void 0 ? void 0 : _a.generation) !== openingSnapshot.fixedContext.generation ||
84
- fixedDeclaration(service.registry, current) !== openingFixedDeclaration)
86
+ if (!current || (!('fixedContext' in current) || !('fixedContext' in openingSnapshot) ||
87
+ ((_a = current.fixedContext) === null || _a === void 0 ? void 0 : _a.generation) !== ((_b = openingSnapshot.fixedContext) === null || _b === void 0 ? void 0 : _b.generation)) ||
88
+ fixedDeclaration(service.registry, 'opcode' in current ? current : null) !== openingFixedDeclaration)
85
89
  endSession();
86
90
  return;
87
91
  }
88
92
  if (!current || JSON.stringify(current) !== JSON.stringify(openingSnapshot))
89
93
  endSession();
90
94
  };
91
- const available = block => {
95
+ const available = (block) => {
92
96
  if (disposed || !vm.editingTarget || !canOpen() || !service.registry.resolve(block.type))
93
97
  return false;
94
98
  const snapshot = host.readBlock({ targetId: vm.editingTarget.id, blockId: block.id });
95
99
  if (fixedDeclaration(service.registry, snapshot))
96
100
  return supportsFixedInputEditing(host);
97
- return snapshot && Object.values(snapshot.arguments).every(slot => slot.kind === 'literal');
101
+ return snapshot !== null && Object.values(snapshot.arguments).every(slot => slot.kind === 'literal');
98
102
  };
99
- const open = block => {
103
+ const open = (block) => {
100
104
  var _a, _b;
101
105
  clearHover();
102
106
  if (activeSession && ['editing', 'saving'].includes(activeSession.getState().status))
@@ -109,15 +113,15 @@ const createBlockEditorBridge = ({ ScratchBlocks, workspace, vm, service, label,
109
113
  if (session) {
110
114
  ScratchBlocks.hideChaff();
111
115
  activeSession = session;
112
- openingSnapshot = typeof session.getNodes === 'function' ?
116
+ openingSnapshot = 'getNodes' in session ?
113
117
  host.descendants.readSubtree(session.reference) : host.readBlock(session.reference);
114
- openingFixedDeclaration = fixedDeclaration(service.registry, openingSnapshot) || null;
118
+ openingFixedDeclaration = fixedDeclaration(service.registry, openingSnapshot && 'opcode' in openingSnapshot ? openingSnapshot : null) || null;
115
119
  const labels = {};
116
120
  const appearances = Object.create(null);
117
121
  const rootAppearance = readBlockEditorAppearance(block, ScratchBlocks, (_a = service.registry.resolve(block.type)) === null || _a === void 0 ? void 0 : _a.editableArguments);
118
122
  appearances[reference.blockId] = rootAppearance;
119
123
  labels[reference.blockId] = rootAppearance.name || block.type;
120
- if (typeof session.getNodes === 'function') {
124
+ if ('getNodes' in session) {
121
125
  for (const node of session.getNodes()) {
122
126
  const source = workspace.getBlockById(node.reference.blockId);
123
127
  const appearance = readBlockEditorAppearance(source, ScratchBlocks, (_b = service.registry.resolve(node.opcode)) === null || _b === void 0 ? void 0 : _b.editableArguments);
@@ -205,12 +209,13 @@ const createBlockEditorBridge = ({ ScratchBlocks, workspace, vm, service, label,
205
209
  const unregister = service.subscribe(() => {
206
210
  // Aggregate sessions observe relevant registry changes themselves.
207
211
  if (openingFixedDeclaration && activeSession) {
208
- if (service.registry.resolveFixed(openingSnapshot.opcode) !== openingFixedDeclaration) {
212
+ if (openingSnapshot && 'opcode' in openingSnapshot &&
213
+ service.registry.resolveFixed(openingSnapshot.opcode) !== openingFixedDeclaration) {
209
214
  host.invalidate();
210
215
  endSession();
211
216
  }
212
217
  }
213
- else if (!activeSession || typeof activeSession.getNodes !== 'function') {
218
+ else if (!activeSession || !('getNodes' in activeSession)) {
214
219
  host.invalidate();
215
220
  endSession();
216
221
  }
@@ -1,18 +1,4 @@
1
+ import type { BlockReference } from '../types.js';
2
+ import type { BlockEditorFailureSession } from '../turbowarp.js';
3
+ declare const createBlockEditorErrorSession: (reference: BlockReference, error: unknown) => BlockEditorFailureSession;
1
4
  export default createBlockEditorErrorSession;
2
- declare function createBlockEditorErrorSession(reference: any, error: any): Readonly<{
3
- reference: any;
4
- getState: () => {
5
- status: string;
6
- canSave: boolean;
7
- issues: never[];
8
- error: any;
9
- };
10
- subscribe: (listener: any) => () => boolean;
11
- mount: () => () => void;
12
- save: () => Promise<{
13
- status: string;
14
- error: any;
15
- }>;
16
- cancel: () => boolean;
17
- dispose: () => true;
18
- }>;
@@ -2,7 +2,7 @@
2
2
  const createBlockEditorErrorSession = (reference, error) => {
3
3
  let status = 'editing';
4
4
  const listeners = new Set();
5
- const finish = next => {
5
+ const finish = (next) => {
6
6
  if (status !== 'editing')
7
7
  return false;
8
8
  status = next;
@@ -14,7 +14,7 @@ const createBlockEditorErrorSession = (reference, error) => {
14
14
  return Object.freeze({
15
15
  reference,
16
16
  getState: () => ({ status, canSave: false, issues: [], error }),
17
- subscribe: listener => {
17
+ subscribe: (listener) => {
18
18
  listeners.add(listener);
19
19
  return () => listeners.delete(listener);
20
20
  },
@@ -1,82 +1,67 @@
1
+ import type { FixedInputMetadata } from '../fixed-input-types.js';
2
+ import type { ArgumentSlot } from '../types.js';
3
+ import type { Identify, NativeBlock, NativeField, NativeFieldClass, NativeScratchBlocks, NativeTarget, VMBlock } from './native-types.js';
4
+ export interface FieldBinding {
5
+ block: NativeBlock;
6
+ field: NativeField;
7
+ fieldName: string;
8
+ value: string;
9
+ vmBlock: VMBlock;
10
+ kind: 'text' | 'number' | 'menu' | 'color';
11
+ Class: NativeFieldClass;
12
+ prototype: object;
13
+ allowedValues: readonly string[] | null | undefined;
14
+ restoreValue: NativeField['setValue'];
15
+ rawState: PropertyState[];
16
+ restoreHandles(): void;
17
+ restoreDom(): void;
18
+ restoreState?: ReturnType<typeof colorState>;
19
+ }
20
+ interface Inspection {
21
+ slot: ArgumentSlot;
22
+ metadata: FixedInputMetadata;
23
+ signatureParts: unknown[];
24
+ binding?: FieldBinding;
25
+ }
26
+ type PropertyState = [name: string, descriptor: PropertyDescriptor | undefined];
1
27
  /** Freeze native method identities once when the host attaches, before opening editors. */
2
- export function initializeFixedFields(ScratchBlocks: any): void;
28
+ export declare function initializeFixedFields(ScratchBlocks: NativeScratchBlocks): void;
29
+ declare const colorState: (block: NativeBlock, field: NativeField) => {
30
+ colors: unknown[];
31
+ hsv: unknown[][];
32
+ blockProperties: PropertyState[];
33
+ };
3
34
  /** Native objects stay local; only primitive metadata is returned in snapshots. */
4
- export function inspectFixedArgument({ ScratchBlocks, block, vmBlock, target, argument, role, identify, extensionId }: {
5
- ScratchBlocks: any;
6
- block: any;
7
- vmBlock: any;
8
- target: any;
9
- argument: any;
10
- role: any;
11
- identify: any;
12
- extensionId: any;
13
- }): {
14
- slot: {
15
- kind: string;
16
- value: string | number | boolean;
17
- } | {
18
- kind: string;
19
- value?: never;
20
- };
21
- metadata: {
22
- role: any;
23
- source: any;
24
- identity: string;
25
- reason: any;
26
- };
27
- signatureParts: any[];
28
- } | {
29
- slot: {
30
- kind: string;
31
- value?: never;
32
- };
33
- metadata: {
34
- role: any;
35
- source: string;
36
- identity: string;
37
- field?: never;
38
- };
39
- signatureParts: any[];
40
- } | {
41
- signatureParts: any[];
42
- binding?: {
43
- restoreState?: {
44
- colors: any[];
45
- hsv: any[][];
46
- blockProperties: any;
47
- };
48
- block: any;
49
- field: any;
50
- fieldName: any;
51
- value: string;
52
- vmBlock: any;
53
- kind: string;
54
- Class: any;
55
- prototype: any;
56
- allowedValues: readonly string[] | null | undefined;
57
- restoreValue: any;
58
- rawState: any;
59
- restoreHandles: any;
60
- restoreDom: any;
61
- };
62
- slot: {
63
- kind: string;
64
- value: string | number;
65
- };
66
- metadata: {
67
- role: any;
68
- source: string;
69
- identity: string;
70
- field: {
71
- blockId: any;
72
- name: any;
73
- type: string | undefined;
74
- };
75
- };
76
- } | null;
35
+ export declare function inspectFixedArgument({ ScratchBlocks, block, vmBlock, target, argument, role, identify, extensionId }: {
36
+ ScratchBlocks: NativeScratchBlocks;
37
+ block: NativeBlock;
38
+ vmBlock: VMBlock;
39
+ target: NativeTarget;
40
+ argument: string;
41
+ role: FixedInputMetadata['role'];
42
+ identify: Identify;
43
+ extensionId: string;
44
+ }): Inspection | null;
77
45
  /** Validate the exact saved primitive; native setters must not silently normalize it. */
78
- export function prepareFixedChange(binding: any, value: any): any;
46
+ export declare function prepareFixedChange(binding: FieldBinding, value: unknown): {
47
+ next: string;
48
+ block: NativeBlock;
49
+ field: NativeField;
50
+ fieldName: string;
51
+ value: string;
52
+ vmBlock: VMBlock;
53
+ kind: "text" | "number" | "menu" | "color";
54
+ Class: NativeFieldClass;
55
+ prototype: object;
56
+ allowedValues: readonly string[] | null | undefined;
57
+ restoreValue: NativeField["setValue"];
58
+ rawState: PropertyState[];
59
+ restoreHandles(): void;
60
+ restoreDom(): void;
61
+ restoreState?: ReturnType<typeof colorState>;
62
+ };
79
63
  /** Capture a later external value without invoking replacement field methods. */
80
- export function captureFixedFieldState(binding: any): any;
64
+ export declare function captureFixedFieldState(binding: FieldBinding): FieldBinding;
81
65
  /** Restore raw text and the standard color field's additional block/UI state. */
82
- export function restoreFixedField(binding: any): void;
66
+ export declare function restoreFixedField(binding: FieldBinding): void;
67
+ export {};
@@ -3,7 +3,7 @@ const own = (object, key) => {
3
3
  const descriptor = object && Object.getOwnPropertyDescriptor(object, key);
4
4
  return descriptor && 'value' in descriptor ? descriptor.value : undefined;
5
5
  };
6
- const primitive = value => typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean';
6
+ const primitive = (value) => typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean';
7
7
  const token = /^-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?$/u;
8
8
  // Inspect data properties without invoking custom field accessors or menu providers.
9
9
  const inherited = (object, name) => {
@@ -41,7 +41,7 @@ const safeField = (field, Class) => {
41
41
  if (currentPrototype !== entry.prototype)
42
42
  return false;
43
43
  for (const [name, expected] of entry.own) {
44
- const actual = Object.getOwnPropertyDescriptor(currentPrototype, name);
44
+ const actual = Object.getOwnPropertyDescriptor(entry.prototype, name);
45
45
  if (Boolean(actual) !== Boolean(expected) ||
46
46
  (actual && (!('value' in actual) || !expected || !('value' in expected) || actual.value !== expected.value)))
47
47
  return false;
@@ -71,7 +71,7 @@ const safeField = (field, Class) => {
71
71
  }
72
72
  return false;
73
73
  };
74
- const arrayData = value => {
74
+ const arrayData = (value) => {
75
75
  if (!Array.isArray(value) || Object.getPrototypeOf(value) !== Array.prototype)
76
76
  return null;
77
77
  const result = [];
@@ -83,7 +83,7 @@ const arrayData = value => {
83
83
  }
84
84
  return result;
85
85
  };
86
- const staticValues = field => {
86
+ const staticValues = (field) => {
87
87
  const items = arrayData(own(field, 'menuGenerator_'));
88
88
  if (!items || items.length === 0)
89
89
  return null;
@@ -156,7 +156,7 @@ export function inspectFixedArgument({ ScratchBlocks, block, vmBlock, target, ar
156
156
  return { slot: { kind: 'reporter' }, metadata: { role, source: 'reporter', identity: JSON.stringify(sourceIdentity) },
157
157
  signatureParts: sourceIdentity };
158
158
  }
159
- let owner = direct ? block : connected;
159
+ const owner = direct ? block : connected;
160
160
  if (!owner) {
161
161
  if (vmBlock.fields && owns(vmBlock.fields, argument))
162
162
  return null;
@@ -204,7 +204,7 @@ export function inspectFixedArgument({ ScratchBlocks, block, vmBlock, target, ar
204
204
  }
205
205
  if (names.length !== 1)
206
206
  return unavailable('unsupported', 'The menu shadow does not have one standard field.');
207
- [name] = names;
207
+ name = names[0];
208
208
  }
209
209
  else
210
210
  return unavailable('unsupported', 'The shadow field family is unsupported.');
@@ -1,18 +1,23 @@
1
- export default function createFixedInputPort({ ScratchBlocks, workspace, vm, registry, identify, getState, begin, markEvent, finish, onError, subscribeScope }: {
2
- ScratchBlocks: any;
3
- workspace: any;
4
- vm: any;
5
- registry: any;
6
- identify: any;
7
- getState: any;
8
- begin: any;
9
- markEvent: any;
10
- finish: any;
11
- onError: any;
12
- subscribeScope: any;
13
- }): Readonly<{
14
- capability: "fixed-inputs-v1";
15
- readBlock: (reference: any, declaration: any) => import("../fixed-input-types.js").FixedBlockSnapshot | null;
16
- commit: (request: any) => void;
17
- subscribeInvalidation: (reference: any, declaration: any, listener: any) => () => void;
18
- }>;
1
+ import type { FixedInputEditorHost } from '../fixed-input-types.js';
2
+ import type { EditorRegistry } from '../registry.js';
3
+ import type { Identify, NativeChange, NativeScratchBlocks, NativeVM, NativeWorkspace } from './native-types.js';
4
+ interface FixedPortOptions {
5
+ ScratchBlocks: NativeScratchBlocks;
6
+ workspace: NativeWorkspace;
7
+ vm: NativeVM;
8
+ registry: EditorRegistry;
9
+ identify: Identify;
10
+ getState(): {
11
+ disposed: boolean;
12
+ revision: number;
13
+ generation: number;
14
+ externalRevision: number;
15
+ };
16
+ begin(): void;
17
+ markEvent(event: NativeChange): void;
18
+ finish(succeeded: boolean): void;
19
+ onError(error: unknown): void;
20
+ subscribeScope(listener: () => void): () => void;
21
+ }
22
+ export default function createFixedInputPort({ ScratchBlocks, workspace, vm, registry, identify, getState, begin, markEvent, finish, onError, subscribeScope }: FixedPortOptions): FixedInputEditorHost;
23
+ export {};
@@ -4,7 +4,7 @@ import { initializeFixedFields, inspectFixedArgument, prepareFixedChange, restor
4
4
  import { snapshotJson } from '../schema-json.js';
5
5
  import { validateFixedBranchChanges } from '../fixed-input-branches.js';
6
6
  const own = (object, name) => {
7
- const descriptor = object && Object.getOwnPropertyDescriptor(object, name);
7
+ const descriptor = object ? Object.getOwnPropertyDescriptor(object, name) : undefined;
8
8
  if (!descriptor || !Object.prototype.hasOwnProperty.call(descriptor, 'value')) {
9
9
  throw new TypeError('Expected an own data property.');
10
10
  }
@@ -21,9 +21,10 @@ const inheritedData = (object, key) => {
21
21
  }
22
22
  return undefined;
23
23
  };
24
- const ensureNativeHistory = stack => {
24
+ const ensureNativeHistory = (stack) => {
25
+ var _a;
25
26
  if (!Array.isArray(stack) || !Object.isExtensible(stack) ||
26
- Object.getOwnPropertySymbols(stack).length || !Object.getOwnPropertyDescriptor(stack, 'length').writable) {
27
+ Object.getOwnPropertySymbols(stack).length || !((_a = Object.getOwnPropertyDescriptor(stack, 'length')) === null || _a === void 0 ? void 0 : _a.writable)) {
27
28
  throw new TypeError('Unsupported undo history.');
28
29
  }
29
30
  if (Object.getOwnPropertyNames(stack).length !== stack.length + 1)
@@ -35,7 +36,7 @@ const ensureNativeHistory = stack => {
35
36
  }
36
37
  }
37
38
  };
38
- const copyHistory = stack => {
39
+ const copyHistory = (stack) => {
39
40
  const copy = [];
40
41
  for (let index = 0; index < stack.length; index++)
41
42
  copy.push(own(stack, String(index)));
@@ -46,11 +47,11 @@ const replaceHistory = (stack, values) => {
46
47
  for (const value of values)
47
48
  Array.prototype.push.call(stack, value);
48
49
  };
49
- const conflict = () => { throw new BlockEditorConflictError(); };
50
+ function conflict() { throw new BlockEditorConflictError(); }
50
51
  const aborted = Object.getOwnPropertyDescriptor(AbortSignal.prototype, 'aborted').get;
51
- const isAborted = signal => aborted.call(signal);
52
+ const isAborted = (signal) => aborted.call(signal);
52
53
  const optionalOwn = (object, name) => {
53
- const descriptor = object && Object.getOwnPropertyDescriptor(object, name);
54
+ const descriptor = object ? Object.getOwnPropertyDescriptor(object, name) : undefined;
54
55
  if (descriptor && !Object.prototype.hasOwnProperty.call(descriptor, 'value')) {
55
56
  throw new TypeError('VM state must contain data properties.');
56
57
  }
@@ -79,7 +80,7 @@ const untouchedState = (block, vmBlock, target, bindings, identify) => {
79
80
  }
80
81
  const seen = new Set();
81
82
  const records = [];
82
- const capture = item => {
83
+ const capture = (item) => {
83
84
  if (!item || seen.has(item))
84
85
  return;
85
86
  seen.add(item);
@@ -112,8 +113,7 @@ const untouchedState = (block, vmBlock, target, bindings, identify) => {
112
113
  });
113
114
  return JSON.stringify([records, connections, statementConnections]);
114
115
  };
115
- const sameDeclaration = (left, right) => JSON.stringify(captureFixedInputDeclaration(left)) ===
116
- JSON.stringify(captureFixedInputDeclaration(right));
116
+ const sameDeclaration = (left, right) => JSON.stringify(captureFixedInputDeclaration(left)) === JSON.stringify(captureFixedInputDeclaration(right));
117
117
  // Fixed inputs deliberately use a separate transaction from the legacy TEXT adapter.
118
118
  export default function createFixedInputPort({ ScratchBlocks, workspace, vm, registry, identify, getState, begin, markEvent, finish, onError, subscribeScope }) {
119
119
  initializeFixedFields(ScratchBlocks);
@@ -162,7 +162,7 @@ export default function createFixedInputPort({ ScratchBlocks, workspace, vm, reg
162
162
  } }, reference, declaration);
163
163
  return { snapshot, bindings, declaration, target, block, vmBlock, state, untouched, runtime: vm.runtime };
164
164
  };
165
- const commit = request => {
165
+ const commit = (request) => {
166
166
  var _a;
167
167
  const expectedInput = own(request, 'expected');
168
168
  const changesInput = own(request, 'changes');
@@ -238,7 +238,7 @@ export default function createFixedInputPort({ ScratchBlocks, workspace, vm, reg
238
238
  ensureNativeHistory(redoStack);
239
239
  const configuredMaxUndo = inheritedData(workspace, 'MAX_UNDO');
240
240
  const maxUndo = configuredMaxUndo === undefined ? Infinity : configuredMaxUndo;
241
- if (maxUndo !== Infinity && (!Number.isSafeInteger(maxUndo) || maxUndo < 0)) {
241
+ if (typeof maxUndo !== 'number' || (maxUndo !== Infinity && (!Number.isSafeInteger(maxUndo) || maxUndo < 0))) {
242
242
  throw new TypeError('Unsupported undo configuration.');
243
243
  }
244
244
  const undo = copyHistory(undoStack);
@@ -290,7 +290,7 @@ export default function createFixedInputPort({ ScratchBlocks, workspace, vm, reg
290
290
  const fields = edited.vmBlock.fields;
291
291
  const field = fields && fields[edited.fieldName];
292
292
  externalWrites.set(edited.field, { binding: captureFixedFieldState(edited),
293
- fields, field, descriptors: field && Object.getOwnPropertyDescriptors(field) });
293
+ field, descriptors: field && Object.getOwnPropertyDescriptors(field) });
294
294
  }
295
295
  activeEvent = previous;
296
296
  }
@@ -1,19 +1,3 @@
1
+ import type { TurboWarpHostOptions, TurboWarpBlockEditorHost } from '../turbowarp.js';
2
+ declare const createBlockEditorHost: ({ ScratchBlocks: nativeBlocks, workspace: nativeWorkspace, vm: nativeVM, registry, enableDescendants, enableFixedInputs, onError }: TurboWarpHostOptions) => TurboWarpBlockEditorHost;
1
3
  export default createBlockEditorHost;
2
- declare function createBlockEditorHost({ ScratchBlocks, workspace, vm, registry, enableDescendants, enableFixedInputs, onError }: {
3
- ScratchBlocks: any;
4
- workspace: any;
5
- vm: any;
6
- registry: any;
7
- enableDescendants?: boolean | undefined;
8
- enableFixedInputs?: boolean | undefined;
9
- onError?: ((...data: any[]) => void) | undefined;
10
- }): {
11
- isCommitting: () => boolean;
12
- readBlock: (reference: any) => any;
13
- commit: ({ expected, changes }: {
14
- expected: any;
15
- changes: any;
16
- }) => void;
17
- invalidate: () => void;
18
- dispose: () => void;
19
- };
@@ -3,7 +3,10 @@ import collectBlockEditorSubtree from './subtree.js';
3
3
  import createFixedInputPort from './fixed-transaction.js';
4
4
  const owns = (object, key) => Object.prototype.hasOwnProperty.call(object, key);
5
5
  // Adapt only standard, unvalidated text shadows; never evaluate connected reporters.
6
- const createBlockEditorHost = ({ ScratchBlocks, workspace, vm, registry, enableDescendants = false, enableFixedInputs = false, onError = console.error }) => {
6
+ const createBlockEditorHost = ({ ScratchBlocks: nativeBlocks, workspace: nativeWorkspace, vm: nativeVM, registry, enableDescendants = false, enableFixedInputs = false, onError = console.error }) => {
7
+ const ScratchBlocks = nativeBlocks;
8
+ const workspace = nativeWorkspace;
9
+ const vm = nativeVM;
7
10
  let disposed = false;
8
11
  let committing = false;
9
12
  let revision = 0;
@@ -30,12 +33,12 @@ const createBlockEditorHost = ({ ScratchBlocks, workspace, vm, registry, enableD
30
33
  };
31
34
  let notifyInvalidations = () => { };
32
35
  const identities = new WeakMap();
33
- const identify = object => {
36
+ const identify = (object) => {
34
37
  if (!identities.has(object))
35
38
  identities.set(object, ++identity);
36
39
  return identities.get(object);
37
40
  };
38
- const invalidate = event => {
41
+ const invalidate = (event) => {
39
42
  if (event && event.isUiEvent)
40
43
  return;
41
44
  revision++;
@@ -163,7 +166,7 @@ const createBlockEditorHost = ({ ScratchBlocks, workspace, vm, registry, enableD
163
166
  vmBlock
164
167
  };
165
168
  };
166
- const collect = reference => collectBlockEditorSubtree({ ScratchBlocks, reference, inspect, generation });
169
+ const collect = (reference) => collectBlockEditorSubtree({ ScratchBlocks, reference, inspect, generation });
167
170
  notifyInvalidations = () => {
168
171
  if (committing)
169
172
  return;
@@ -171,7 +174,7 @@ const createBlockEditorHost = ({ ScratchBlocks, workspace, vm, registry, enableD
171
174
  let matches = false;
172
175
  try {
173
176
  const current = collect(item.reference);
174
- matches = current && JSON.stringify(current.snapshot) === JSON.stringify(item.snapshot);
177
+ matches = current !== null && JSON.stringify(current.snapshot) === JSON.stringify(item.snapshot);
175
178
  }
176
179
  catch (error) {
177
180
  // A malformed replacement graph invalidates an already open session too.
@@ -201,7 +204,7 @@ const createBlockEditorHost = ({ ScratchBlocks, workspace, vm, registry, enableD
201
204
  Events.disable();
202
205
  committing = true;
203
206
  try {
204
- if (signal && signal.aborted)
207
+ if (!target || (signal && signal.aborted))
205
208
  throw new BlockEditorConflictError();
206
209
  for (const item of prepared) {
207
210
  item.field.setValue(item.next);