optipack 1.0.0 → 1.0.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.
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Permissive stub of @minecraft/server-graphics@1.0.0 for the differential harness.
3
+ * Generated from the module's real index.d.ts (see test/update-mock-stubs.mjs).
4
+ * Every runtime export is a permissive value: callable, constructable, and
5
+ * chainable; calls and constructions record harness effects so differential
6
+ * equivalence holds. NOT a behavioral model of the engine module.
7
+ */
8
+ import { permissive } from '../permissive.mjs';
9
+
10
+ export const BiomeAtmospherics = permissive('server-graphics.BiomeAtmospherics');
11
+ export const BiomeColorGrading = permissive('server-graphics.BiomeColorGrading');
12
+ export const BiomeLighting = permissive('server-graphics.BiomeLighting');
13
+ export const BiomeWater = permissive('server-graphics.BiomeWater');
14
+ export const getBiomeAtmospherics = permissive('server-graphics.getBiomeAtmospherics');
15
+ export const getBiomeColorGrading = permissive('server-graphics.getBiomeColorGrading');
16
+ export const getBiomeLighting = permissive('server-graphics.getBiomeLighting');
17
+ export const getBiomeWater = permissive('server-graphics.getBiomeWater');
18
+ export const getPlayerAtmospherics = permissive('server-graphics.getPlayerAtmospherics');
19
+ export const getPlayerColorGrading = permissive('server-graphics.getPlayerColorGrading');
20
+ export const getPlayerLighting = permissive('server-graphics.getPlayerLighting');
21
+ export const getPlayerWater = permissive('server-graphics.getPlayerWater');
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Permissive stub of @minecraft/server-net@1.0.0-beta.11940b24 for the differential harness.
3
+ * Generated from the module's real index.d.ts (see test/update-mock-stubs.mjs).
4
+ * Every runtime export is a permissive value: callable, constructable, and
5
+ * chainable; calls and constructions record harness effects so differential
6
+ * equivalence holds. NOT a behavioral model of the engine module.
7
+ */
8
+ import { permissive } from '../permissive.mjs';
9
+
10
+ export const HttpClient = permissive('server-net.HttpClient');
11
+ export const HttpHeader = permissive('server-net.HttpHeader');
12
+ export const HttpRequest = permissive('server-net.HttpRequest');
13
+ export const HttpRequestMethod = permissive('server-net.HttpRequestMethod');
14
+ export const HttpResponse = permissive('server-net.HttpResponse');
15
+ export const http = permissive('server-net.http');
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Functional mock of @minecraft/server-ui for the differential harness.
3
+ *
4
+ * Models the widely used form surface accurately: ActionFormData,
5
+ * MessageFormData, ModalFormData (chainable builders), uiManager.showPlayer,
6
+ * and the response types. `.show()`/`showPlayer()` record a harness effect
7
+ * carrying the form's kind and title, then resolve with a scripted response
8
+ * from the recorder (key: `uiResponse:<entityId>`, default: a non-canceled
9
+ * selection). Names present in the real 2.2.0 module but not modeled in depth
10
+ * (CustomForm, MessageBox, observables, error classes) are bound to permissive
11
+ * stubs so any fixture using them still links and runs.
12
+ */
13
+ import { permissive } from '../permissive.mjs';
14
+
15
+ const rec = () => globalThis.__opkRecorder;
16
+
17
+ function scriptedResponse(player) {
18
+ const r = rec();
19
+ const key = 'uiResponse:' + (player && player.id !== undefined ? player.id : 'unknown');
20
+ const base = r ? r.scriptedRead(key, undefined) : undefined;
21
+ if (base) return base;
22
+ return { selection: 0, formValues: [0], canceled: false, cancelationReason: undefined };
23
+ }
24
+
25
+ class FormBase {
26
+ constructor(kind) {
27
+ this.__kind = kind;
28
+ this.__data = { title: undefined, body: undefined, buttons: [], fields: [] };
29
+ }
30
+ __chain(mutator) {
31
+ mutator();
32
+ return this;
33
+ }
34
+ title(text) { return this.__chain(() => { this.__data.title = String(text); }); }
35
+ body(text) { return this.__chain(() => { this.__data.body = String(text); }); }
36
+ __show(player) {
37
+ const r = rec();
38
+ if (r) r.effect('ui.show', { kind: this.__kind, title: this.__data.title, player: player && player.id !== undefined ? player.id : null });
39
+ const response = scriptedResponse(player);
40
+ return Promise.resolve(response);
41
+ }
42
+ }
43
+
44
+ export class ActionFormData extends FormBase {
45
+ constructor() { super('ActionFormData'); }
46
+ button(text, iconPath) { return this.__chain(() => { this.__data.buttons.push({ text: String(text), iconPath }); }); }
47
+ divider() { return this.__chain(() => { this.__data.buttons.push({ divider: true }); }); }
48
+ header(text) { return this.__chain(() => { this.__data.header = String(text); }); }
49
+ label(text) { return this.__chain(() => { this.__data.fields.push({ type: 'label', text: String(text) }); }); }
50
+ show(player) { return this.__show(player); }
51
+ }
52
+
53
+ export class MessageFormData extends FormBase {
54
+ constructor() { super('MessageFormData'); }
55
+ button1(text) { return this.__chain(() => { this.__data.buttons[0] = { text: String(text) }; }); }
56
+ button2(text) { return this.__chain(() => { this.__data.buttons[1] = { text: String(text) }; }); }
57
+ show(player) { return this.__show(player); }
58
+ }
59
+
60
+ export class ModalFormData extends FormBase {
61
+ constructor() { super('ModalFormData'); }
62
+ textField(label, placeholder, options) { return this.__chain(() => { this.__data.fields.push({ type: 'textField', label: String(label), placeholder, options }); }); }
63
+ slider(label, min, max, step, deflt) { return this.__chain(() => { this.__data.fields.push({ type: 'slider', label: String(label), min, max, step, default: deflt }); }); }
64
+ toggle(label, deflt) { return this.__chain(() => { this.__data.fields.push({ type: 'toggle', label: String(label), default: deflt }); }); }
65
+ dropdown(label, options, deflt) { return this.__chain(() => { this.__data.fields.push({ type: 'dropdown', label: String(label), options, default: deflt }); }); }
66
+ divider() { return this.__chain(() => { this.__data.fields.push({ type: 'divider' }); }); }
67
+ header(text) { return this.__chain(() => { this.__data.header = String(text); }); }
68
+ label(text) { return this.__chain(() => { this.__data.fields.push({ type: 'label', text: String(text) }); }); }
69
+ submitButton(text) { return this.__chain(() => { this.__data.submitButtonText = String(text); }); }
70
+ show(player) { return this.__show(player); }
71
+ }
72
+
73
+ class UIManagerImpl {
74
+ showPlayer(player, form) {
75
+ const r = rec();
76
+ if (r) r.effect('ui.showPlayer', { kind: form && form.__kind, title: form && form.__data && form.__data.title, player: player && player.id !== undefined ? player.id : null });
77
+ const response = scriptedResponse(player);
78
+ return Promise.resolve(response);
79
+ }
80
+ close(player) {
81
+ const r = rec();
82
+ if (r) r.effect('ui.close', { player: player && player.id !== undefined ? player.id : null });
83
+ }
84
+ }
85
+
86
+ export const uiManager = new UIManagerImpl();
87
+
88
+ // Response constructors: usable with `new`, mirror the scripted/plain shape.
89
+ export class FormResponse {
90
+ constructor(init = {}) { Object.assign(this, { canceled: false, cancelationReason: undefined }, init); }
91
+ }
92
+ export class ActionFormResponse extends FormResponse {
93
+ constructor(init = {}) { super({ selection: 0, ...init }); }
94
+ }
95
+ export class MessageFormResponse extends FormResponse {
96
+ constructor(init = {}) { super({ selection: 0, ...init }); }
97
+ }
98
+ export class ModalFormResponse extends FormResponse {
99
+ constructor(init = {}) { super({ formValues: [], ...init }); }
100
+ }
101
+
102
+ export const FormCancelationReason = Object.freeze({
103
+ UserBusy: 'UserBusy',
104
+ UserClosed: 'UserClosed',
105
+ ServerCrashed: 'ServerCrashed',
106
+ });
107
+
108
+ // Present in the real module but not modeled in depth: permissive stubs so
109
+ // named imports link and recorded effects stay identical on both sides.
110
+ export const CustomForm = permissive('server-ui.CustomForm');
111
+ export const MessageBox = permissive('server-ui.MessageBox');
112
+ export const ObservableBoolean = permissive('server-ui.ObservableBoolean');
113
+ export const ObservableNumber = permissive('server-ui.ObservableNumber');
114
+ export const ObservableString = permissive('server-ui.ObservableString');
115
+ export const ObservableUIRawMessage = permissive('server-ui.ObservableUIRawMessage');
116
+ export const DataDrivenScreenClosedReason = permissive('server-ui.DataDrivenScreenClosedReason');
117
+ export const FormRejectError = permissive('server-ui.FormRejectError');
118
+ export const FormRejectReason = permissive('server-ui.FormRejectReason');
119
+ export const FormVisibilityError = permissive('server-ui.FormVisibilityError');
120
+ export const FormVisibilityErrorReason = permissive('server-ui.FormVisibilityErrorReason');
121
+ export const InvalidFormError = permissive('server-ui.InvalidFormError');
122
+ export const InvalidFormModificationError = permissive('server-ui.InvalidFormModificationError');
123
+ export const InvalidObservableError = permissive('server-ui.InvalidObservableError');
124
+ export const PlayerLeftError = permissive('server-ui.PlayerLeftError');
125
+ export const TextFilteringError = permissive('server-ui.TextFilteringError');
@@ -1,13 +1,21 @@
1
1
  /**
2
- * Mock @minecraft/server for differential testing.
2
+ * Mock @minecraft/server for the differential harness and `optipack bench`.
3
3
  *
4
4
  * Effect-recorder contract: only MUTATING calls and registrations are recorded
5
5
  * as effects. Pure reads return scripted sequences and are intentionally not
6
6
  * recorded — transforms may legitimately eliminate reads, that is the point.
7
7
  *
8
- * The active recorder is read from globalThis.__opkRecorder at call time, so a
9
- * single mock module instance serves both the original and the optimized
10
- * variant of a script.
8
+ * Boundary counters: the optipack-relevant metric — host-boundary crossings
9
+ * (location reads, getComponent, getDynamicProperty, ...) — is counted on the
10
+ * recorder (`r.counters`). Location reads return a FRESH object per read, like
11
+ * the engine (each read allocates a new Vector3), so allocation pressure is
12
+ * visible in the counter too.
13
+ *
14
+ * Tolerance: arbitrary real-world scripts use wider API surface than any mock
15
+ * can enumerate. world/Dimension/Entity instances are wrapped so unknown
16
+ * members resolve to permissive values that record `stub.*` effects (identical
17
+ * on both sides of a comparison), and event collections accept ANY event name.
18
+ * Known hot-path members keep real implementations with counters.
11
19
  */
12
20
 
13
21
  const rec = () => globalThis.__opkRecorder;
@@ -23,6 +31,11 @@ function effect(call, args) {
23
31
  if (r) r.effect(call, args === undefined ? null : args);
24
32
  }
25
33
 
34
+ function count(kind) {
35
+ const r = rec();
36
+ if (r) r.count(kind);
37
+ }
38
+
26
39
  function serialize(v) {
27
40
  if (v === null) return null;
28
41
  const t = typeof v;
@@ -38,18 +51,87 @@ function serialize(v) {
38
51
  return String(v);
39
52
  }
40
53
 
54
+ /** Permissive fallback for unknown members on wrapped host objects. */
55
+ function unknownMember(label) {
56
+ const asPrimitive = (hint) => (hint === 'number' ? 0 : label);
57
+ const fn = function (...args) {
58
+ effect('stub.call', { target: label, args: serialize(args) });
59
+ return unknownMember(label + '()');
60
+ };
61
+ fn.toString = () => label;
62
+ fn.valueOf = () => label;
63
+ return new Proxy(fn, {
64
+ get(target, prop, receiver) {
65
+ if (prop === Symbol.toPrimitive) return asPrimitive;
66
+ if (typeof prop === 'symbol') return undefined;
67
+ if (prop === 'then' || prop === 'catch' || prop === 'finally' || prop === 'toJSON') return undefined;
68
+ if (prop === 'toString' || prop === 'valueOf') return Reflect.get(target, prop, receiver);
69
+ return unknownMember(label + '.' + String(prop));
70
+ },
71
+ construct(target, args) {
72
+ effect('stub.new', { target: label, args: serialize(args) });
73
+ return unknownMember('new ' + label);
74
+ },
75
+ apply(target, thisArg, args) {
76
+ effect('stub.call', { target: label, args: serialize(args) });
77
+ return unknownMember(label + '()');
78
+ },
79
+ has() { return true; },
80
+ });
81
+ }
82
+
83
+ class Block {
84
+ constructor(location, dimensionId) {
85
+ this.location = location;
86
+ this.__dim = dimensionId;
87
+ this.typeId = scriptedRead(`blockType:${this.__dim}`, 'minecraft:stone');
88
+ }
89
+ get permutation() {
90
+ count('boundary.block.permutation');
91
+ return scriptedRead(`blockPerm:${this.__dim}`, { type: this.typeId });
92
+ }
93
+ setPermutation(permutation) {
94
+ effect('block.setPermutation', { dimension: this.__dim, location: serialize(this.location), permutation: serialize(permutation) });
95
+ }
96
+ setType(blockType) {
97
+ effect('block.setType', { dimension: this.__dim, location: serialize(this.location), type: serialize(blockType) });
98
+ }
99
+ getComponent(name) {
100
+ count('boundary.getComponent');
101
+ return scriptedRead(`component:block:${name}`, undefined);
102
+ }
103
+ }
104
+
105
+ function wrapHost(instance, label) {
106
+ return new Proxy(instance, {
107
+ get(target, prop, receiver) {
108
+ if (typeof prop === 'symbol' || prop === 'then' || prop === 'catch' || prop === 'finally') {
109
+ return typeof prop === 'symbol' ? undefined : Reflect.get(target, prop, receiver);
110
+ }
111
+ if (prop in target) return Reflect.get(target, prop, receiver);
112
+ return unknownMember(label + '.' + String(prop));
113
+ },
114
+ });
115
+ }
116
+
41
117
  class Dimension {
42
118
  constructor(id) {
43
119
  this.id = id;
44
120
  }
45
121
  getEntities(options) {
122
+ count('boundary.getEntities');
46
123
  effect('dimension.getEntities', { dimension: this.id, options: serialize(options) });
47
124
  return scriptedRead(`entities:${this.id}`, []);
48
125
  }
49
126
  getPlayers() {
127
+ count('boundary.getPlayers');
50
128
  effect('dimension.getPlayers', { dimension: this.id });
51
129
  return scriptedRead(`players:${this.id}`, []);
52
130
  }
131
+ get players() {
132
+ count('boundary.players');
133
+ return scriptedRead(`players:${this.id}`, []);
134
+ }
53
135
  spawnEntity(type, location) {
54
136
  effect('dimension.spawnEntity', { dimension: this.id, type, location: serialize(location) });
55
137
  return scriptedRead(`spawn:${this.id}:${type}`, null);
@@ -60,6 +142,19 @@ class Dimension {
60
142
  runCommand(commandString) {
61
143
  effect('dimension.runCommand', { dimension: this.id, command: commandString });
62
144
  }
145
+ getBlock(location) {
146
+ count('boundary.getBlock');
147
+ return new Block({ x: location.x, y: location.y, z: location.z }, this.id);
148
+ }
149
+ getEntitiesAtBlockLocation(location) {
150
+ count('boundary.getEntitiesAtBlockLocation');
151
+ effect('dimension.getEntitiesAtBlockLocation', { dimension: this.id, location: serialize(location) });
152
+ return scriptedRead(`entitiesAt:${this.id}`, []);
153
+ }
154
+ }
155
+
156
+ function wrapDimension(dim) {
157
+ return wrapHost(dim, 'dimension.' + dim.id);
63
158
  }
64
159
 
65
160
  class Entity {
@@ -67,6 +162,7 @@ class Entity {
67
162
  this._id = id;
68
163
  this.typeId = typeId;
69
164
  this._dimension = dimension;
165
+ return wrapHost(this, 'entity.' + id);
70
166
  }
71
167
  get id() {
72
168
  return this._id;
@@ -75,19 +171,30 @@ class Entity {
75
171
  return scriptedRead(`name:${this._id}`, 'player' + this._id);
76
172
  }
77
173
  get location() {
78
- return scriptedRead(`location:${this._id}`, { x: 0, y: 0, z: 0 });
174
+ count('boundary.location');
175
+ const v = scriptedRead(`location:${this._id}`, { x: 0, y: 0, z: 0 });
176
+ // The engine allocates a fresh Vector3 on every read; mirror that.
177
+ return { x: v.x, y: v.y, z: v.z };
79
178
  }
80
179
  get dimension() {
180
+ count('boundary.dimension');
81
181
  return this._dimension;
82
182
  }
83
183
  getComponent(componentId) {
84
- return scriptedRead(`component:${this._id}:${componentId}`, undefined);
184
+ count('boundary.getComponent');
185
+ const v = scriptedRead(`component:${this._id}:${componentId}`, undefined);
186
+ // Real-world scripts assume queried components exist; default to a
187
+ // chainable permissive component instead of undefined (identical on both
188
+ // sides of a comparison).
189
+ return v === undefined ? unknownMember('entity.' + this._id + '.component.' + componentId) : v;
85
190
  }
86
191
  getComponents() {
192
+ count('boundary.getComponents');
87
193
  effect('entity.getComponents', { entity: this._id });
88
194
  return [];
89
195
  }
90
196
  getDynamicProperty(identifier) {
197
+ count('boundary.getDynamicProperty');
91
198
  return scriptedRead(`dp:${this._id}:${identifier}`, undefined);
92
199
  }
93
200
  setDynamicProperty(identifier, value) {
@@ -106,6 +213,12 @@ class Entity {
106
213
  effect('entity.applyDamage', { entity: this._id, amount, options: serialize(options) });
107
214
  return scriptedRead(`damage:${this._id}`, true);
108
215
  }
216
+ applyKnockback(direction, horizontalStrength, verticalStrength) {
217
+ effect('entity.applyKnockback', { entity: this._id, direction: serialize(direction), horizontalStrength, verticalStrength });
218
+ }
219
+ applyImpulse(impulse) {
220
+ effect('entity.applyImpulse', { entity: this._id, impulse: serialize(impulse) });
221
+ }
109
222
  kill() {
110
223
  effect('entity.kill', { entity: this._id });
111
224
  }
@@ -127,9 +240,11 @@ class Entity {
127
240
  effect('entity.triggerEvent', { entity: this._id, eventName });
128
241
  }
129
242
  getRotation() {
243
+ count('boundary.getRotation');
130
244
  return scriptedRead(`rotation:${this._id}`, { x: 0, y: 0 });
131
245
  }
132
246
  getVelocity() {
247
+ count('boundary.getVelocity');
133
248
  return scriptedRead(`velocity:${this._id}`, { x: 0, y: 0, z: 0 });
134
249
  }
135
250
  }
@@ -149,60 +264,63 @@ function makeEvent(fullName) {
149
264
  };
150
265
  }
151
266
 
152
- const worldAfterEvents = {
153
- worldLoad: makeEvent('world.afterEvents.worldLoad'),
154
- worldInitialize: makeEvent('world.afterEvents.worldInitialize'),
155
- playerSpawn: makeEvent('world.afterEvents.playerSpawn'),
156
- playerJoin: makeEvent('world.afterEvents.playerJoin'),
157
- playerLeave: makeEvent('world.afterEvents.playerLeave'),
158
- entityDie: makeEvent('world.afterEvents.entityDie'),
159
- entityHurt: makeEvent('world.afterEvents.entityHurt'),
160
- itemUse: makeEvent('world.afterEvents.itemUse'),
161
- chatSend: makeEvent('world.afterEvents.chatSend'),
162
- };
163
- const worldBeforeEvents = {
164
- worldLoad: makeEvent('world.beforeEvents.worldLoad'),
165
- playerInteractWithBlock: makeEvent('world.beforeEvents.playerInteractWithBlock'),
166
- playerInteractWithEntity: makeEvent('world.beforeEvents.playerInteractWithEntity'),
167
- itemUse: makeEvent('world.beforeEvents.itemUse'),
168
- chatSend: makeEvent('world.beforeEvents.chatSend'),
169
- };
267
+ // Event collections accept ANY event name (real-world scripts use the full
268
+ // API surface; unknown names record the same effect shape).
269
+ function eventCollection(prefix) {
270
+ return new Proxy({}, {
271
+ get(target, prop) {
272
+ if (typeof prop === 'symbol' || prop === 'then') return undefined;
273
+ if (prop in target) return target[prop];
274
+ const ev = makeEvent(`${prefix}.${String(prop)}`);
275
+ target[prop] = ev;
276
+ return ev;
277
+ },
278
+ });
279
+ }
170
280
 
171
281
  function currentPlayers() {
172
282
  const r = rec();
173
283
  if (!r) return [];
174
- ensurePlayers(r);
284
+ if (!r._players) {
285
+ const specs = (r.state && r.state.players) || [];
286
+ r._players = specs.map((s) => new Entity(s.id, s.typeId || 'minecraft:player', wrapDimension(new Dimension(s.dimension || 'minecraft:overworld'))));
287
+ }
175
288
  return r._players;
176
289
  }
177
290
 
178
291
  function ensurePlayers(r) {
179
292
  if (r._players) return r._players;
180
293
  const specs = (r.state && r.state.players) || [];
181
- r._players = specs.map((s) => new Entity(s.id, s.typeId || 'minecraft:player', new Dimension(s.dimension || 'minecraft:overworld')));
294
+ r._players = specs.map((s) => new Entity(s.id, s.typeId || 'minecraft:player', wrapDimension(new Dimension(s.dimension || 'minecraft:overworld'))));
182
295
  return r._players;
183
296
  }
184
297
 
185
- // The differential driver hydrates event payloads via this hook.
298
+ // The differential driver hydrates event payloads via these hooks.
186
299
  if (typeof globalThis !== 'undefined') {
187
300
  globalThis.__opkEnsurePlayers = ensurePlayers;
301
+ globalThis.__opkMakeDimension = (id) => wrapDimension(new Dimension(id));
302
+ globalThis.__opkMakeBlock = (location, dimensionId) => new Block(location, dimensionId || 'minecraft:overworld');
188
303
  }
189
304
 
190
- export const world = {
305
+ const worldImpl = {
191
306
  get afterEvents() {
192
- return worldAfterEvents;
307
+ return eventCollection('world.afterEvents');
193
308
  },
194
309
  get beforeEvents() {
195
- return worldBeforeEvents;
310
+ return eventCollection('world.beforeEvents');
196
311
  },
197
312
  getAllPlayers() {
313
+ count('boundary.getAllPlayers');
198
314
  effect('world.getAllPlayers', null);
199
315
  return currentPlayers();
200
316
  },
201
317
  getPlayers() {
318
+ count('boundary.getPlayers');
202
319
  effect('world.getPlayers', null);
203
320
  return currentPlayers();
204
321
  },
205
322
  getDynamicProperty(identifier) {
323
+ count('boundary.getDynamicProperty');
206
324
  return scriptedRead(`world.dp:${identifier}`, undefined);
207
325
  },
208
326
  setDynamicProperty(identifier, value) {
@@ -217,21 +335,17 @@ export const world = {
217
335
  },
218
336
  getDimension(dimensionId) {
219
337
  effect('world.getDimension', { id: dimensionId });
220
- return new Dimension(dimensionId);
338
+ return wrapDimension(new Dimension(dimensionId));
221
339
  },
222
340
  playSound(soundId, options) {
223
341
  effect('world.playSound', { soundId, options: serialize(options) });
224
342
  },
225
343
  };
226
344
 
227
- const systemBeforeEvents = {
228
- tick: makeEvent('system.beforeEvents.tick'),
229
- watchdogTerminate: makeEvent('system.beforeEvents.watchdogTerminate'),
230
- };
231
- const systemAfterEvents = {
232
- tick: makeEvent('system.afterEvents.tick'),
233
- watchdogTerminate: makeEvent('system.afterEvents.watchdogTerminate'),
234
- };
345
+ export const world = wrapHost(worldImpl, 'world');
346
+
347
+ const systemBeforeEvents = eventCollection('system.beforeEvents');
348
+ const systemAfterEvents = eventCollection('system.afterEvents');
235
349
 
236
350
  export const system = {
237
351
  get beforeEvents() {
@@ -268,7 +382,13 @@ export const system = {
268
382
  },
269
383
  };
270
384
 
271
- export { Entity, Dimension };
385
+ export { Entity, Dimension, Block };
272
386
  export const TicksPerSecond = 20;
273
387
  export const GameMode = { survival: 'survival', creative: 'creative', adventure: 'adventure' };
388
+
389
+ // Full API surface: every other runtime export of the real module is a
390
+ // permissive value (generated from the real index.d.ts) so real-world
391
+ // scripts' named imports link under the harness.
392
+ export * from './server-extras.mjs';
393
+
274
394
  export default { world, system, Entity, Dimension, TicksPerSecond, GameMode };
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Permissive stub factory for @minecraft/* runtime modules that optipack's
3
+ * differential harness does not model in depth.
4
+ *
5
+ * Every exported name from a module's real index.d.ts is bound to a permissive
6
+ * value: callable, constructable, and property-accessible indefinitely. Calls
7
+ * and constructions are recorded as harness effects (identically on the
8
+ * original and optimized sides), so differential equivalence still holds while
9
+ * scripts exercise these modules. Property GETS are silent — only calls and
10
+ * `new` produce effects — so chained accessors do not spam the trace.
11
+ *
12
+ * Not a behavioral model: it exists so fixtures importing these modules link
13
+ * and run. Behavior differences between stub and engine are identical on both
14
+ * sides of a differential comparison, which is the only claim it supports.
15
+ */
16
+ const rec = () => globalThis.__opkRecorder;
17
+
18
+ function record(call, args) {
19
+ const r = rec();
20
+ if (r) r.effect(call, args);
21
+ }
22
+
23
+ function shallow(v, depth = 0) {
24
+ if (v === null) return null;
25
+ const t = typeof v;
26
+ if (t === 'string' || t === 'number' || t === 'boolean' || t === 'undefined') return v;
27
+ if (depth > 2) return String(t);
28
+ if (Array.isArray(v)) return v.map((x) => shallow(x, depth + 1));
29
+ if (t === 'object') {
30
+ const out = {};
31
+ for (const k of Object.keys(v)) out[k] = shallow(v[k], depth + 1);
32
+ return out;
33
+ }
34
+ return String(t);
35
+ }
36
+
37
+ const NON_VALUE_SYMBOLS = new Set([
38
+ 'then', 'catch', 'finally', 'toJSON', 'inspect', 'constructor',
39
+ Symbol.toPrimitive, Symbol.toStringTag, Symbol.iterator,
40
+ 'nodejs.util.inspect.custom', 'asymmetricMatcher',
41
+ ]);
42
+
43
+ export function permissive(label) {
44
+ const asPrimitive = (hint) => (hint === 'number' ? 0 : label);
45
+ const fn = function (...args) {
46
+ record('stub.call', { target: label, args: shallow(args) });
47
+ return permissive(label + '()');
48
+ };
49
+ fn.toString = () => label;
50
+ fn.valueOf = () => label;
51
+ return new Proxy(fn, {
52
+ get(target, prop, receiver) {
53
+ if (prop === Symbol.toPrimitive) return asPrimitive;
54
+ if (typeof prop === 'symbol') return undefined;
55
+ if (prop === 'then' || prop === 'catch' || prop === 'finally' || prop === 'toJSON') return undefined;
56
+ if (prop === 'toString' || prop === 'valueOf') return Reflect.get(target, prop, receiver);
57
+ return permissive(label + '.' + String(prop));
58
+ },
59
+ construct(target, args) {
60
+ record('stub.new', { target: label, args: shallow(args) });
61
+ return permissive('new ' + label);
62
+ },
63
+ apply(target, thisArg, args) {
64
+ record('stub.call', { target: label, args: shallow(args) });
65
+ return permissive(label + '()');
66
+ },
67
+ has() {
68
+ return true;
69
+ },
70
+ });
71
+ }
package/src/pragma.js CHANGED
@@ -75,7 +75,7 @@ export class PragmaInfo {
75
75
  * start line only; callers walk ancestors.
76
76
  */
77
77
  disabledAt(node) {
78
- if (!node.loc) return null;
78
+ if (!node || !node.loc) return null;
79
79
  const start = node.loc.start.line;
80
80
  const direct = this.info.disableByLine.get(start);
81
81
  if (direct) return direct;
@@ -1,4 +1,4 @@
1
- /**
1
+ /**
2
2
  * Bespoke differential scenarios.
3
3
  *
4
4
  * Every scenario loads the original and optimized entry with the mock
@@ -8,7 +8,7 @@
8
8
  */
9
9
  import test from 'node:test';
10
10
  import assert from 'node:assert/strict';
11
- import { differentialCheck, runVariant, pathToUrl, buildVariantPack } from './harness/setup.js';
11
+ import { differentialCheck, runVariant, pathToUrl, buildVariantPack } from '../src/harness/driver.js';
12
12
 
13
13
  const PLAYER_READS = {
14
14
  'location:p1': [{ x: 1, y: 64, z: 2 }, { x: 2, y: 65, z: 3 }],
@@ -1,4 +1,4 @@
1
- /**
1
+ /**
2
2
  * Example pack end-to-end: run the CLI over example/, verify parse validity,
3
3
  * manifest fidelity, effects-equivalence across the whole script graph, report
4
4
  * snapshot, and determinism.
@@ -57,7 +57,7 @@ test('example: effects-equivalence across the whole script graph', async () => {
57
57
  const res = spawnSync(process.execPath, [CLI, EXAMPLE, out], { encoding: 'utf8' });
58
58
  assert.equal(res.status, 0, res.stderr);
59
59
 
60
- const { runVariant, assertSameEffects, pathToUrl } = await import('./harness/setup.js');
60
+ const { runVariant, assertSameEffects, pathToUrl } = await import('../src/harness/driver.js');
61
61
  const scenario = {
62
62
  reads: {
63
63
  'location:p1': [{ x: 10, y: 64, z: 20 }, { x: 12, y: 65, z: 22 }],
@@ -100,7 +100,7 @@ test('example: report snapshot is stable', () => {
100
100
  assert.deepEqual(got, expected, 'report matches snapshot');
101
101
  });
102
102
 
103
- test('example: deterministic output — two runs are byte-identical', () => {
103
+ test('example: deterministic output — two runs are byte-identical', () => {
104
104
  const out1 = mkOut('optipack-det1-');
105
105
  const out2 = mkOut('optipack-det2-');
106
106
  spawnSync(process.execPath, [CLI, EXAMPLE, out1], { encoding: 'utf8' });