@jsprismarine/mcfunction 0.0.0 → 0.16.0-unstable-20261029132853

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.
Files changed (44) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/LICENSE +373 -0
  3. package/README.md +182 -0
  4. package/dist/compile.cjs.cjs +166 -0
  5. package/dist/compile.d.ts +91 -0
  6. package/dist/compile.d.ts.map +1 -0
  7. package/dist/compile.es.js +162 -0
  8. package/dist/diagnostics.cjs.cjs +19 -0
  9. package/dist/diagnostics.d.ts +62 -0
  10. package/dist/diagnostics.d.ts.map +1 -0
  11. package/dist/diagnostics.es.js +17 -0
  12. package/dist/executor.cjs.cjs +302 -0
  13. package/dist/executor.d.ts +140 -0
  14. package/dist/executor.d.ts.map +1 -0
  15. package/dist/executor.es.js +298 -0
  16. package/dist/identifiers.cjs.cjs +79 -0
  17. package/dist/identifiers.d.ts +44 -0
  18. package/dist/identifiers.d.ts.map +1 -0
  19. package/dist/identifiers.es.js +72 -0
  20. package/dist/index.cjs.cjs +36 -0
  21. package/dist/index.d.ts +10 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.es.js +10 -0
  24. package/dist/macro.cjs.cjs +119 -0
  25. package/dist/macro.d.ts +59 -0
  26. package/dist/macro.d.ts.map +1 -0
  27. package/dist/macro.es.js +115 -0
  28. package/dist/parse.cjs.cjs +107 -0
  29. package/dist/parse.d.ts +40 -0
  30. package/dist/parse.d.ts.map +1 -0
  31. package/dist/parse.es.js +104 -0
  32. package/dist/registry.cjs.cjs +135 -0
  33. package/dist/registry.d.ts +53 -0
  34. package/dist/registry.d.ts.map +1 -0
  35. package/dist/registry.es.js +132 -0
  36. package/dist/runner.cjs.cjs +42 -0
  37. package/dist/runner.d.ts +83 -0
  38. package/dist/runner.d.ts.map +1 -0
  39. package/dist/runner.es.js +40 -0
  40. package/dist/tags.cjs.cjs +113 -0
  41. package/dist/tags.d.ts +70 -0
  42. package/dist/tags.d.ts.map +1 -0
  43. package/dist/tags.es.js +108 -0
  44. package/package.json +61 -5
@@ -0,0 +1,302 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const require_identifiers = require("./identifiers.cjs.cjs");
4
+ const require_tags = require("./tags.cjs.cjs");
5
+ // src/executor.ts
6
+ /**
7
+ * The limits a run uses when the caller sets none.
8
+ *
9
+ * Both default to 65536. Mojang has never published either default: the
10
+ * figure has two independent secondary confirmations (minecraft.wiki's
11
+ * gamerule page and Pumpkin's extraction from the 26.3 server jar) and the
12
+ * `GameRules` class holds 65536 in its constant pool, but no Mojang document
13
+ * attributes the value to either rule. Treat it as a well-corroborated
14
+ * default rather than a confirmed one, and configure it when a world says
15
+ * otherwise.
16
+ */
17
+ var DEFAULT_EXECUTION_LIMITS = {
18
+ maxCommandSequenceLength: 65536,
19
+ maxCommandForks: 65536
20
+ };
21
+ /**
22
+ * What Bedrock caps a single `/function` call at, from Mojang's creator
23
+ * documentation. This runtime runs Java functions and does not apply it; a
24
+ * server that wants Bedrock's ceiling passes it as `maxCommandSequenceLength`.
25
+ */
26
+ var BEDROCK_MAX_COMMANDS_PER_FUNCTION = 1e4;
27
+ var CALL_PATTERN = /^function[ \t]+(\S+)[ \t]*([\s\S]*)$/;
28
+ /** Reads a JSON object as an argument compound; anything else is rejected. */
29
+ var parseJsonArguments = (text) => {
30
+ let parsed;
31
+ try {
32
+ parsed = JSON.parse(text);
33
+ } catch {
34
+ return;
35
+ }
36
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return void 0;
37
+ return { ...parsed };
38
+ };
39
+ /**
40
+ * Runs functions against a command runner.
41
+ *
42
+ * One executor is reusable: it holds no run state, so a server builds it once
43
+ * at load and calls {@link FunctionExecutor.runTick} every tick.
44
+ *
45
+ * `function <id>` and `function #tag` are the only lines the executor reads
46
+ * itself, because a call is control flow rather than a command: handling it
47
+ * here is what keeps nesting on the queue instead of on the JavaScript stack.
48
+ * Every other line goes to the runner untouched.
49
+ *
50
+ * `/return` is the other half of that split. It is a command, so the runner
51
+ * implements it, but only the executor can act on it: a runner that reports
52
+ * {@link CommandOutcome.returned} ends the function the line came from and
53
+ * the loop carries on with its caller.
54
+ */
55
+ var FunctionExecutor = class {
56
+ options;
57
+ limits;
58
+ parseArguments;
59
+ constructor(options) {
60
+ this.options = options;
61
+ this.limits = {
62
+ ...DEFAULT_EXECUTION_LIMITS,
63
+ ...options.limits
64
+ };
65
+ this.parseArguments = options.parseArguments ?? parseJsonArguments;
66
+ }
67
+ /** Runs `minecraft:load`, which a server does once after its packs load. */
68
+ runLoad(options) {
69
+ return this.run(`#${require_tags.LOAD_FUNCTION_TAG}`, options);
70
+ }
71
+ /** Runs `minecraft:tick`, which a server does once per server tick. */
72
+ runTick(options) {
73
+ return this.run(`#${require_tags.TICK_FUNCTION_TAG}`, options);
74
+ }
75
+ /**
76
+ * Runs one function or every function in one tag.
77
+ *
78
+ * Everything a call reaches shares one budget, so the report covers the
79
+ * whole tree below the entry point. A limit stops the run and is reported
80
+ * as a diagnostic; nothing here throws, and a command that throws is
81
+ * reported and skipped.
82
+ *
83
+ * @param reference - A function id, or a tag id written `#namespace:tag`.
84
+ */
85
+ run(reference, options) {
86
+ const diagnostics = [];
87
+ const state = {
88
+ operations: 0,
89
+ forks: 0,
90
+ commands: 0,
91
+ invocations: 0,
92
+ maxDepth: 0
93
+ };
94
+ const stack = [];
95
+ const returnValues = [];
96
+ const parsed = require_identifiers.parseFunctionReference(reference);
97
+ if (!parsed) {
98
+ diagnostics.push({
99
+ severity: "error",
100
+ code: "call.unknown-function",
101
+ message: `'${reference}' is not a valid function reference`
102
+ });
103
+ return {
104
+ ...state,
105
+ returnValues,
106
+ diagnostics
107
+ };
108
+ }
109
+ let stopped;
110
+ /** Charges one operation, reporting and stopping the run at the limit. */
111
+ const charge = (functionId, line) => {
112
+ state.operations += 1;
113
+ if (state.operations <= this.limits.maxCommandSequenceLength) return true;
114
+ stopped = "max-command-sequence-length";
115
+ diagnostics.push({
116
+ severity: "error",
117
+ code: "limit.command-sequence-length",
118
+ functionId,
119
+ line,
120
+ message: `the run reached maxCommandSequenceLength (${this.limits.maxCommandSequenceLength}) and stopped`
121
+ });
122
+ return false;
123
+ };
124
+ /** Instantiates one call and pushes its frame, or reports why it could not. */
125
+ const invoke = (id, args, from, root = false) => {
126
+ const compiled = this.options.functions.get(id);
127
+ if (!compiled) {
128
+ diagnostics.push({
129
+ severity: "error",
130
+ code: "call.unknown-function",
131
+ functionId: from.functionId,
132
+ line: from.line,
133
+ message: `the function ${id} does not exist`
134
+ });
135
+ return true;
136
+ }
137
+ if (!charge(from.functionId, from.line)) return false;
138
+ state.invocations += 1;
139
+ const instantiated = compiled.instantiate(args);
140
+ if (!instantiated.ok) {
141
+ diagnostics.push({
142
+ severity: "error",
143
+ code: "macro.missing-arguments",
144
+ functionId: id,
145
+ line: instantiated.line,
146
+ message: instantiated.message
147
+ });
148
+ return true;
149
+ }
150
+ const top = stack.at(-1);
151
+ const replaced = top && top.index >= top.commands.length ? stack.pop() : void 0;
152
+ stack.push({
153
+ functionId: id,
154
+ commands: instantiated.commands,
155
+ index: 0,
156
+ root: replaced?.root ?? root
157
+ });
158
+ state.maxDepth = Math.max(state.maxDepth, stack.length);
159
+ return true;
160
+ };
161
+ const entries = parsed.kind === "function" ? [parsed.id] : this.resolveTag(parsed.id, reference, diagnostics);
162
+ for (const id of [...entries].reverse()) if (!invoke(id, options.arguments, { functionId: reference }, true)) break;
163
+ while (stopped === void 0 && stack.length > 0) {
164
+ const frame = stack.at(-1);
165
+ if (!frame) break;
166
+ if (frame.index >= frame.commands.length) {
167
+ stack.pop();
168
+ continue;
169
+ }
170
+ const entry = frame.commands[frame.index];
171
+ frame.index += 1;
172
+ if (!entry) continue;
173
+ if (!charge(frame.functionId, entry.line)) break;
174
+ const call = CALL_PATTERN.exec(entry.command);
175
+ if (call) {
176
+ this.handleCall(call, frame, entry, invoke, diagnostics);
177
+ continue;
178
+ }
179
+ state.commands += 1;
180
+ let forks = 0;
181
+ let returned;
182
+ try {
183
+ const outcome = this.options.runner.run(entry.command, {
184
+ source: options.source,
185
+ functionId: frame.functionId,
186
+ line: entry.line
187
+ });
188
+ forks = outcome.forks ?? 0;
189
+ returned = outcome.returned;
190
+ } catch (error) {
191
+ diagnostics.push({
192
+ severity: "error",
193
+ code: "command.failed",
194
+ functionId: frame.functionId,
195
+ line: entry.line,
196
+ message: error instanceof Error ? error.message : String(error)
197
+ });
198
+ }
199
+ if (returned !== void 0) {
200
+ if (frame.root && returned.value !== void 0) returnValues.push(returned.value);
201
+ if (stack.at(-1) === frame) stack.pop();
202
+ }
203
+ state.forks += forks;
204
+ if (state.forks > this.limits.maxCommandForks) {
205
+ stopped = "max-command-forks";
206
+ diagnostics.push({
207
+ severity: "error",
208
+ code: "limit.command-forks",
209
+ functionId: frame.functionId,
210
+ line: entry.line,
211
+ message: `the run reached maxCommandForks (${this.limits.maxCommandForks}) and stopped`
212
+ });
213
+ break;
214
+ }
215
+ }
216
+ return {
217
+ ...state,
218
+ returnValues,
219
+ ...stopped ? { stopped } : {},
220
+ diagnostics
221
+ };
222
+ }
223
+ /** Expands a tag reference, reporting a tag no pack declared. */
224
+ resolveTag(id, reference, diagnostics) {
225
+ if (!this.options.tags) {
226
+ diagnostics.push({
227
+ severity: "error",
228
+ code: "call.unknown-tag",
229
+ message: `${reference} is a tag reference, and this executor has no tag lookup`
230
+ });
231
+ return [];
232
+ }
233
+ const resolved = require_tags.resolveFunctionTag(this.options.tags, id);
234
+ diagnostics.push(...resolved.diagnostics);
235
+ return resolved.functions;
236
+ }
237
+ /** Runs one `function` line: resolves what it names and pushes the frames it invokes. */
238
+ handleCall(call, frame, entry, invoke, diagnostics) {
239
+ const from = {
240
+ functionId: frame.functionId,
241
+ line: entry.line
242
+ };
243
+ const target = require_identifiers.parseFunctionReference(call[1] ?? "");
244
+ if (!target) {
245
+ diagnostics.push({
246
+ severity: "error",
247
+ code: "call.unknown-function",
248
+ ...from,
249
+ message: `'${call[1] ?? ""}' is not a valid function reference`
250
+ });
251
+ return;
252
+ }
253
+ const argumentText = (call[2] ?? "").trim();
254
+ let args;
255
+ if (argumentText.length > 0) {
256
+ args = this.parseArguments(argumentText);
257
+ if (args === void 0) {
258
+ diagnostics.push({
259
+ severity: "error",
260
+ code: "call.invalid-arguments",
261
+ ...from,
262
+ message: `the arguments of '${entry.command}' are not a compound this runtime can read`
263
+ });
264
+ return;
265
+ }
266
+ }
267
+ if (target.kind === "function") {
268
+ invoke(target.id, args, from);
269
+ return;
270
+ }
271
+ const tags = this.options.tags;
272
+ if (!tags) {
273
+ diagnostics.push({
274
+ severity: "error",
275
+ code: "call.unknown-tag",
276
+ ...from,
277
+ message: `#${target.id} cannot be resolved, because this executor has no tag lookup`
278
+ });
279
+ return;
280
+ }
281
+ const resolved = require_tags.resolveFunctionTag(tags, target.id);
282
+ diagnostics.push(...resolved.diagnostics.map((diagnostic) => ({
283
+ ...diagnostic,
284
+ ...from
285
+ })));
286
+ if (!resolved.exists) {
287
+ diagnostics.push({
288
+ severity: "error",
289
+ code: "call.unknown-tag",
290
+ ...from,
291
+ message: `the function tag #${target.id} does not exist`
292
+ });
293
+ return;
294
+ }
295
+ for (const id of [...resolved.functions].reverse()) if (!invoke(id, args, from)) break;
296
+ }
297
+ };
298
+ exports.BEDROCK_MAX_COMMANDS_PER_FUNCTION = BEDROCK_MAX_COMMANDS_PER_FUNCTION;
299
+ exports.DEFAULT_EXECUTION_LIMITS = DEFAULT_EXECUTION_LIMITS;
300
+ exports.FunctionExecutor = FunctionExecutor;
301
+
302
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhlY3V0b3IuY2pzLmNqcyIsIm5hbWVzIjpbIkxPQURfRlVOQ1RJT05fVEFHIiwiVElDS19GVU5DVElPTl9UQUciLCJwYXJzZUZ1bmN0aW9uUmVmZXJlbmNlIiwicmVzb2x2ZUZ1bmN0aW9uVGFnIl0sInNvdXJjZXMiOlsiLi4vc3JjL2V4ZWN1dG9yLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVGhlIGV4ZWN1dG9yLiBKYXZhIHJld3JvdGUgZnVuY3Rpb24gZXhlY3V0aW9uIGluIDIzdzQxYSBmcm9tIGEgcmVjdXJzaXZlXG4gKiBjYWxsIHBhdGggaW50byBhbiBleHBsaWNpdCBxdWV1ZSBvZiBmcmFtZXMgb24gdGhlIGhlYXAsIHdoaWNoIGlzIHdoYXQgbGV0c1xuICogaXQgYm91bmQgd29yayB3aXRoIGEgY291bnRlciBhbmQgc3RvcHMgYSB0YWlsLXJlY3Vyc2l2ZSBwYWNrIGZyb21cbiAqIGV4aGF1c3RpbmcgdGhlIGhvc3Qgc3RhY2suIFRoaXMgaXMgdGhlIHNhbWUgc2hhcGU6IGEgc3RhY2sgb2YgZnJhbWVzIGluIGFuXG4gKiBhcnJheSwgb25lIGxvb3AsIGFuZCBhIGNvdW50ZXIgY2hhcmdlZCBwZXIgb3BlcmF0aW9uLlxuICovXG5cbmltcG9ydCB0eXBlIHsgQ29tcGlsZWRGdW5jdGlvbiwgSW5zdGFudGlhdGVkQ29tbWFuZCB9IGZyb20gJy4vY29tcGlsZSc7XG5pbXBvcnQgdHlwZSB7IERpYWdub3N0aWMgfSBmcm9tICcuL2RpYWdub3N0aWNzJztcbmltcG9ydCB0eXBlIHsgRnVuY3Rpb25SZWZlcmVuY2UgfSBmcm9tICcuL2lkZW50aWZpZXJzJztcbmltcG9ydCB7IHBhcnNlRnVuY3Rpb25SZWZlcmVuY2UgfSBmcm9tICcuL2lkZW50aWZpZXJzJztcbmltcG9ydCB0eXBlIHsgTWFjcm9Bcmd1bWVudHMgfSBmcm9tICcuL21hY3JvJztcbmltcG9ydCB0eXBlIHsgQ29tbWFuZE91dGNvbWUsIENvbW1hbmRSdW5uZXIgfSBmcm9tICcuL3J1bm5lcic7XG5pbXBvcnQgdHlwZSB7IEZ1bmN0aW9uVGFnTG9va3VwIH0gZnJvbSAnLi90YWdzJztcbmltcG9ydCB7IExPQURfRlVOQ1RJT05fVEFHLCBUSUNLX0ZVTkNUSU9OX1RBRywgcmVzb2x2ZUZ1bmN0aW9uVGFnIH0gZnJvbSAnLi90YWdzJztcblxuLyoqXG4gKiBUaGUgdHdvIGdhbWVydWxlcyB0aGF0IGJvdW5kIGEgcnVuLiBUaGV5IHdlcmUgcmVuYW1lZCBpbiAxLjIxLjExIGZyb21cbiAqIGBtYXhDb21tYW5kQ2hhaW5MZW5ndGhgIGFuZCBgbWF4Q29tbWFuZEZvcmtDb3VudGA7IGFueXRoaW5nIHdyaXR0ZW4gYWdhaW5zdFxuICogdGhlIGNhbWVsQ2FzZSBuYW1lcyBpcyBzdGFsZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFeGVjdXRpb25MaW1pdHMge1xuICAgIC8qKiBgbWluZWNyYWZ0Om1heF9jb21tYW5kX3NlcXVlbmNlX2xlbmd0aGA6IGhvdyBtYW55IG9wZXJhdGlvbnMgb25lIGVudHJ5IHBvaW50IG1heSBydW4uICovXG4gICAgbWF4Q29tbWFuZFNlcXVlbmNlTGVuZ3RoOiBudW1iZXI7XG4gICAgLyoqIGBtaW5lY3JhZnQ6bWF4X2NvbW1hbmRfZm9ya3NgOiBob3cgbWFueSBjb250ZXh0cyBvbmUgZW50cnkgcG9pbnQgbWF5IGNyZWF0ZS4gKi9cbiAgICBtYXhDb21tYW5kRm9ya3M6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBUaGUgbGltaXRzIGEgcnVuIHVzZXMgd2hlbiB0aGUgY2FsbGVyIHNldHMgbm9uZS5cbiAqXG4gKiBCb3RoIGRlZmF1bHQgdG8gNjU1MzYuIE1vamFuZyBoYXMgbmV2ZXIgcHVibGlzaGVkIGVpdGhlciBkZWZhdWx0OiB0aGVcbiAqIGZpZ3VyZSBoYXMgdHdvIGluZGVwZW5kZW50IHNlY29uZGFyeSBjb25maXJtYXRpb25zIChtaW5lY3JhZnQud2lraSdzXG4gKiBnYW1lcnVsZSBwYWdlIGFuZCBQdW1wa2luJ3MgZXh0cmFjdGlvbiBmcm9tIHRoZSAyNi4zIHNlcnZlciBqYXIpIGFuZCB0aGVcbiAqIGBHYW1lUnVsZXNgIGNsYXNzIGhvbGRzIDY1NTM2IGluIGl0cyBjb25zdGFudCBwb29sLCBidXQgbm8gTW9qYW5nIGRvY3VtZW50XG4gKiBhdHRyaWJ1dGVzIHRoZSB2YWx1ZSB0byBlaXRoZXIgcnVsZS4gVHJlYXQgaXQgYXMgYSB3ZWxsLWNvcnJvYm9yYXRlZFxuICogZGVmYXVsdCByYXRoZXIgdGhhbiBhIGNvbmZpcm1lZCBvbmUsIGFuZCBjb25maWd1cmUgaXQgd2hlbiBhIHdvcmxkIHNheXNcbiAqIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfRVhFQ1VUSU9OX0xJTUlUUzogRXhlY3V0aW9uTGltaXRzID0ge1xuICAgIG1heENvbW1hbmRTZXF1ZW5jZUxlbmd0aDogNjVfNTM2LFxuICAgIG1heENvbW1hbmRGb3JrczogNjVfNTM2XG59O1xuXG4vKipcbiAqIFdoYXQgQmVkcm9jayBjYXBzIGEgc2luZ2xlIGAvZnVuY3Rpb25gIGNhbGwgYXQsIGZyb20gTW9qYW5nJ3MgY3JlYXRvclxuICogZG9jdW1lbnRhdGlvbi4gVGhpcyBydW50aW1lIHJ1bnMgSmF2YSBmdW5jdGlvbnMgYW5kIGRvZXMgbm90IGFwcGx5IGl0OyBhXG4gKiBzZXJ2ZXIgdGhhdCB3YW50cyBCZWRyb2NrJ3MgY2VpbGluZyBwYXNzZXMgaXQgYXMgYG1heENvbW1hbmRTZXF1ZW5jZUxlbmd0aGAuXG4gKi9cbmV4cG9ydCBjb25zdCBCRURST0NLX01BWF9DT01NQU5EU19QRVJfRlVOQ1RJT04gPSAxMF8wMDA7XG5cbi8qKiBXaGVyZSB0aGUgZXhlY3V0b3IgcmVhZHMgY29tcGlsZWQgZnVuY3Rpb25zIGZyb20uICovXG5leHBvcnQgaW50ZXJmYWNlIEZ1bmN0aW9uTG9va3VwIHtcbiAgICAvKiogUmV0dXJucyB0aGUgZnVuY3Rpb24gcmVnaXN0ZXJlZCB1bmRlciBhIG5hbWVzcGFjZWQgaWQuICovXG4gICAgZ2V0KGlkOiBzdHJpbmcpOiBDb21waWxlZEZ1bmN0aW9uIHwgdW5kZWZpbmVkO1xufVxuXG4vKiogSG93IHRvIGJ1aWxkIGEge0BsaW5rIEZ1bmN0aW9uRXhlY3V0b3J9LiAqL1xuZXhwb3J0IGludGVyZmFjZSBGdW5jdGlvbkV4ZWN1dG9yT3B0aW9uczxUU291cmNlID0gdW5rbm93bj4ge1xuICAgIGZ1bmN0aW9uczogRnVuY3Rpb25Mb29rdXA7XG4gICAgcnVubmVyOiBDb21tYW5kUnVubmVyPFRTb3VyY2U+O1xuICAgIC8qKiBSZXNvbHZlcyBgI25hbWVzcGFjZTp0YWdgIHJlZmVyZW5jZXMuIFdpdGhvdXQgaXQsIGEgdGFnIHJlZmVyZW5jZSBpcyByZXBvcnRlZCBhcyB1bmtub3duLiAqL1xuICAgIHRhZ3M/OiBGdW5jdGlvblRhZ0xvb2t1cDtcbiAgICAvKiogT3ZlcnJpZGVzIGVpdGhlciBsaW1pdDsgYW55dGhpbmcgbGVmdCBvdXQga2VlcHMgaXRzIHtAbGluayBERUZBVUxUX0VYRUNVVElPTl9MSU1JVFN9IHZhbHVlLiAqL1xuICAgIGxpbWl0cz86IFBhcnRpYWw8RXhlY3V0aW9uTGltaXRzPjtcbiAgICAvKipcbiAgICAgKiBSZWFkcyB0aGUgYXJndW1lbnQgY29tcG91bmQgb2YgYSBgZnVuY3Rpb24gPGlkPiA8YXJndW1lbnRzPmAgbGluZS4gVGhlXG4gICAgICogZGVmYXVsdCBhY2NlcHRzIEpTT04sIGJlY2F1c2UgU05CVCBuZWVkcyBhIHBhcnNlciB0aGlzIHBhY2thZ2UgZG9lcyBub3RcbiAgICAgKiBvd247IGEgc2VydmVyIHdpdGggb25lIHBhc3NlcyBpdCBoZXJlLlxuICAgICAqL1xuICAgIHBhcnNlQXJndW1lbnRzPzogKHRleHQ6IHN0cmluZykgPT4gTWFjcm9Bcmd1bWVudHMgfCB1bmRlZmluZWQ7XG59XG5cbi8qKiBXaGF0IG9uZSBjYWxsIG5lZWRzIGJleW9uZCB0aGUgZnVuY3Rpb24gdG8gcnVuLiAqL1xuZXhwb3J0IGludGVyZmFjZSBFeGVjdXRpb25PcHRpb25zPFRTb3VyY2UgPSB1bmtub3duPiB7XG4gICAgLyoqIFRoZSBjb21tYW5kIHNvdXJjZSBldmVyeSBjb21tYW5kIGluIHRoZSBydW4gaXMgZ2l2ZW4uICovXG4gICAgc291cmNlOiBUU291cmNlO1xuICAgIC8qKiBUaGUgY29tcG91bmQgYSBtYWNybyBmdW5jdGlvbiBzdWJzdGl0dXRlcyBmcm9tLiBJZ25vcmVkIGJ5IGEgcGxhaW4gZnVuY3Rpb24uICovXG4gICAgYXJndW1lbnRzPzogTWFjcm9Bcmd1bWVudHM7XG59XG5cbi8qKiBXaHkgYSBydW4gc3RvcHBlZCBiZWZvcmUgaXQgZmluaXNoZWQuICovXG5leHBvcnQgdHlwZSBFeGVjdXRpb25TdG9wID0gJ21heC1jb21tYW5kLXNlcXVlbmNlLWxlbmd0aCcgfCAnbWF4LWNvbW1hbmQtZm9ya3MnO1xuXG4vKiogV2hhdCBvbmUgcnVuIGRpZC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRXhlY3V0aW9uUmVwb3J0IHtcbiAgICAvKiogT3BlcmF0aW9ucyBjaGFyZ2VkIGFnYWluc3QgYG1heENvbW1hbmRTZXF1ZW5jZUxlbmd0aGAuICovXG4gICAgb3BlcmF0aW9uczogbnVtYmVyO1xuICAgIC8qKiBDb250ZXh0cyBjaGFyZ2VkIGFnYWluc3QgYG1heENvbW1hbmRGb3Jrc2AuICovXG4gICAgZm9ya3M6IG51bWJlcjtcbiAgICAvKiogSG93IG1hbnkgY29tbWFuZCBsaW5lcyByZWFjaGVkIHRoZSBydW5uZXIuICovXG4gICAgY29tbWFuZHM6IG51bWJlcjtcbiAgICAvKiogSG93IG1hbnkgZnVuY3Rpb25zIHRoZSBydW4gaW52b2tlZCwgaW5jbHVkaW5nIHRoZSBlbnRyeSBwb2ludC4gKi9cbiAgICBpbnZvY2F0aW9uczogbnVtYmVyO1xuICAgIC8qKiBUaGUgZGVlcGVzdCB0aGUgZnJhbWUgc3RhY2sgZ290LiBBIHRhaWwgY2FsbCBkb2VzIG5vdCBkZWVwZW4gaXQuICovXG4gICAgbWF4RGVwdGg6IG51bWJlcjtcbiAgICAvKipcbiAgICAgKiBUaGUgdmFsdWVzIGAvcmV0dXJuYCBwcm9kdWNlZCwgb25lIHBlciBmdW5jdGlvbiB0aGUgZW50cnkgcG9pbnRcbiAgICAgKiBpbnZva2VkIGRpcmVjdGx5IHRoYXQgcmVhY2hlZCBvbmUuXG4gICAgICpcbiAgICAgKiBFbXB0eSB3aGVuIGV2ZXJ5IGZ1bmN0aW9uIHJhbiB0byBpdHMgbGFzdCBsaW5lLCB3aGljaCBpcyB0aGUgY2FzZSBKYXZhXG4gICAgICogY2FsbHMgXCJyZXR1cm5lZCBubyB2YWx1ZVwiLiBBIHRhZyBjb250cmlidXRlcyBvbmUgZW50cnkgcGVyIG1lbWJlciB0aGF0XG4gICAgICogcmV0dXJuZWQsIGJlY2F1c2UgYGV4ZWN1dGUgaWYgZnVuY3Rpb24gI3RhZ2AgbWF0Y2hlcyB3aGVuIGFueSBtZW1iZXJcbiAgICAgKiBkaWQuIEEgYC9yZXR1cm5gIGRlZXBlciBpbiB0aGUgY2FsbCB0cmVlIGVuZHMgaXRzIG93biBmdW5jdGlvbiBhbmRcbiAgICAgKiBsZWF2ZXMgbm90aGluZyBoZXJlLCB0aGUgd2F5IEphdmEgcmV0dXJucyBmcm9tIG9uZSBmdW5jdGlvbiByYXRoZXJcbiAgICAgKiB0aGFuIGZyb20gaXRzIGNhbGxlci5cbiAgICAgKi9cbiAgICByZXR1cm5WYWx1ZXM6IHJlYWRvbmx5IG51bWJlcltdO1xuICAgIC8qKiBTZXQgd2hlbiBhIGxpbWl0IHN0b3BwZWQgdGhlIHJ1bjsgdGhlIG1hdGNoaW5nIGRpYWdub3N0aWMgY2FycmllcyB0aGUgZGV0YWlsLiAqL1xuICAgIHN0b3BwZWQ/OiBFeGVjdXRpb25TdG9wO1xuICAgIGRpYWdub3N0aWNzOiByZWFkb25seSBEaWFnbm9zdGljW107XG59XG5cbi8qKiBPbmUgZnVuY3Rpb24gaW4gcHJvZ3Jlc3M6IGl0cyByZW1haW5pbmcgY29tbWFuZHMgYW5kIHdoZXJlIGl0IGlzIGluIHRoZW0uICovXG5pbnRlcmZhY2UgRnJhbWUge1xuICAgIGZ1bmN0aW9uSWQ6IHN0cmluZztcbiAgICBjb21tYW5kczogcmVhZG9ubHkgSW5zdGFudGlhdGVkQ29tbWFuZFtdO1xuICAgIGluZGV4OiBudW1iZXI7XG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgZW50cnkgcG9pbnQgaW52b2tlZCB0aGlzIGZ1bmN0aW9uIGl0c2VsZiwgd2hpY2ggaXMgd2hhdFxuICAgICAqIGRlY2lkZXMgd2hvc2UgYC9yZXR1cm5gIHRoZSBydW4gcmVwb3J0cy4gQSB0YWlsIGNhbGwgaW5oZXJpdHMgaXQ6IHRoZVxuICAgICAqIHJlcGxhY2VtZW50IHJ1bnMgaW4gdGhlIGZyYW1lIGl0IHJlcGxhY2VkLCBzbyBpdHMgcmV0dXJuIGlzIHRoYXRcbiAgICAgKiBmdW5jdGlvbidzIGxhc3QgYWN0LlxuICAgICAqL1xuICAgIHJvb3Q6IGJvb2xlYW47XG59XG5cbmNvbnN0IENBTExfUEFUVEVSTiA9IC9eZnVuY3Rpb25bIFxcdF0rKFxcUyspWyBcXHRdKihbXFxzXFxTXSopJC87XG5cbi8qKiBSZWFkcyBhIEpTT04gb2JqZWN0IGFzIGFuIGFyZ3VtZW50IGNvbXBvdW5kOyBhbnl0aGluZyBlbHNlIGlzIHJlamVjdGVkLiAqL1xuY29uc3QgcGFyc2VKc29uQXJndW1lbnRzID0gKHRleHQ6IHN0cmluZyk6IE1hY3JvQXJndW1lbnRzIHwgdW5kZWZpbmVkID0+IHtcbiAgICBsZXQgcGFyc2VkOiB1bmtub3duO1xuICAgIHRyeSB7XG4gICAgICAgIHBhcnNlZCA9IEpTT04ucGFyc2UodGV4dCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIC8vIEpTT04ucGFyc2UgaXMgYSBwYXJzZWQtaW5wdXQgYm91bmRhcnksIHNvIG5hcnJvdyByYXRoZXIgdGhhbiBhc3NlcnQuXG4gICAgaWYgKHR5cGVvZiBwYXJzZWQgIT09ICdvYmplY3QnIHx8IHBhcnNlZCA9PT0gbnVsbCB8fCBBcnJheS5pc0FycmF5KHBhcnNlZCkpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIHsgLi4ucGFyc2VkIH07XG59O1xuXG4vKipcbiAqIFJ1bnMgZnVuY3Rpb25zIGFnYWluc3QgYSBjb21tYW5kIHJ1bm5lci5cbiAqXG4gKiBPbmUgZXhlY3V0b3IgaXMgcmV1c2FibGU6IGl0IGhvbGRzIG5vIHJ1biBzdGF0ZSwgc28gYSBzZXJ2ZXIgYnVpbGRzIGl0IG9uY2VcbiAqIGF0IGxvYWQgYW5kIGNhbGxzIHtAbGluayBGdW5jdGlvbkV4ZWN1dG9yLnJ1blRpY2t9IGV2ZXJ5IHRpY2suXG4gKlxuICogYGZ1bmN0aW9uIDxpZD5gIGFuZCBgZnVuY3Rpb24gI3RhZ2AgYXJlIHRoZSBvbmx5IGxpbmVzIHRoZSBleGVjdXRvciByZWFkc1xuICogaXRzZWxmLCBiZWNhdXNlIGEgY2FsbCBpcyBjb250cm9sIGZsb3cgcmF0aGVyIHRoYW4gYSBjb21tYW5kOiBoYW5kbGluZyBpdFxuICogaGVyZSBpcyB3aGF0IGtlZXBzIG5lc3Rpbmcgb24gdGhlIHF1ZXVlIGluc3RlYWQgb2Ygb24gdGhlIEphdmFTY3JpcHQgc3RhY2suXG4gKiBFdmVyeSBvdGhlciBsaW5lIGdvZXMgdG8gdGhlIHJ1bm5lciB1bnRvdWNoZWQuXG4gKlxuICogYC9yZXR1cm5gIGlzIHRoZSBvdGhlciBoYWxmIG9mIHRoYXQgc3BsaXQuIEl0IGlzIGEgY29tbWFuZCwgc28gdGhlIHJ1bm5lclxuICogaW1wbGVtZW50cyBpdCwgYnV0IG9ubHkgdGhlIGV4ZWN1dG9yIGNhbiBhY3Qgb24gaXQ6IGEgcnVubmVyIHRoYXQgcmVwb3J0c1xuICoge0BsaW5rIENvbW1hbmRPdXRjb21lLnJldHVybmVkfSBlbmRzIHRoZSBmdW5jdGlvbiB0aGUgbGluZSBjYW1lIGZyb20gYW5kXG4gKiB0aGUgbG9vcCBjYXJyaWVzIG9uIHdpdGggaXRzIGNhbGxlci5cbiAqL1xuZXhwb3J0IGNsYXNzIEZ1bmN0aW9uRXhlY3V0b3I8VFNvdXJjZSA9IHVua25vd24+IHtcbiAgICBwcml2YXRlIHJlYWRvbmx5IGxpbWl0czogRXhlY3V0aW9uTGltaXRzO1xuXG4gICAgcHJpdmF0ZSByZWFkb25seSBwYXJzZUFyZ3VtZW50czogKHRleHQ6IHN0cmluZykgPT4gTWFjcm9Bcmd1bWVudHMgfCB1bmRlZmluZWQ7XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBvcHRpb25zOiBGdW5jdGlvbkV4ZWN1dG9yT3B0aW9uczxUU291cmNlPikge1xuICAgICAgICB0aGlzLmxpbWl0cyA9IHsgLi4uREVGQVVMVF9FWEVDVVRJT05fTElNSVRTLCAuLi5vcHRpb25zLmxpbWl0cyB9O1xuICAgICAgICB0aGlzLnBhcnNlQXJndW1lbnRzID0gb3B0aW9ucy5wYXJzZUFyZ3VtZW50cyA/PyBwYXJzZUpzb25Bcmd1bWVudHM7XG4gICAgfVxuXG4gICAgLyoqIFJ1bnMgYG1pbmVjcmFmdDpsb2FkYCwgd2hpY2ggYSBzZXJ2ZXIgZG9lcyBvbmNlIGFmdGVyIGl0cyBwYWNrcyBsb2FkLiAqL1xuICAgIHB1YmxpYyBydW5Mb2FkKG9wdGlvbnM6IEV4ZWN1dGlvbk9wdGlvbnM8VFNvdXJjZT4pOiBFeGVjdXRpb25SZXBvcnQge1xuICAgICAgICByZXR1cm4gdGhpcy5ydW4oYCMke0xPQURfRlVOQ1RJT05fVEFHfWAsIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIC8qKiBSdW5zIGBtaW5lY3JhZnQ6dGlja2AsIHdoaWNoIGEgc2VydmVyIGRvZXMgb25jZSBwZXIgc2VydmVyIHRpY2suICovXG4gICAgcHVibGljIHJ1blRpY2sob3B0aW9uczogRXhlY3V0aW9uT3B0aW9uczxUU291cmNlPik6IEV4ZWN1dGlvblJlcG9ydCB7XG4gICAgICAgIHJldHVybiB0aGlzLnJ1bihgIyR7VElDS19GVU5DVElPTl9UQUd9YCwgb3B0aW9ucyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUnVucyBvbmUgZnVuY3Rpb24gb3IgZXZlcnkgZnVuY3Rpb24gaW4gb25lIHRhZy5cbiAgICAgKlxuICAgICAqIEV2ZXJ5dGhpbmcgYSBjYWxsIHJlYWNoZXMgc2hhcmVzIG9uZSBidWRnZXQsIHNvIHRoZSByZXBvcnQgY292ZXJzIHRoZVxuICAgICAqIHdob2xlIHRyZWUgYmVsb3cgdGhlIGVudHJ5IHBvaW50LiBBIGxpbWl0IHN0b3BzIHRoZSBydW4gYW5kIGlzIHJlcG9ydGVkXG4gICAgICogYXMgYSBkaWFnbm9zdGljOyBub3RoaW5nIGhlcmUgdGhyb3dzLCBhbmQgYSBjb21tYW5kIHRoYXQgdGhyb3dzIGlzXG4gICAgICogcmVwb3J0ZWQgYW5kIHNraXBwZWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcmVmZXJlbmNlIC0gQSBmdW5jdGlvbiBpZCwgb3IgYSB0YWcgaWQgd3JpdHRlbiBgI25hbWVzcGFjZTp0YWdgLlxuICAgICAqL1xuICAgIHB1YmxpYyBydW4ocmVmZXJlbmNlOiBzdHJpbmcsIG9wdGlvbnM6IEV4ZWN1dGlvbk9wdGlvbnM8VFNvdXJjZT4pOiBFeGVjdXRpb25SZXBvcnQge1xuICAgICAgICBjb25zdCBkaWFnbm9zdGljczogRGlhZ25vc3RpY1tdID0gW107XG4gICAgICAgIGNvbnN0IHN0YXRlID0geyBvcGVyYXRpb25zOiAwLCBmb3JrczogMCwgY29tbWFuZHM6IDAsIGludm9jYXRpb25zOiAwLCBtYXhEZXB0aDogMCB9O1xuICAgICAgICBjb25zdCBzdGFjazogRnJhbWVbXSA9IFtdO1xuICAgICAgICBjb25zdCByZXR1cm5WYWx1ZXM6IG51bWJlcltdID0gW107XG5cbiAgICAgICAgY29uc3QgcGFyc2VkID0gcGFyc2VGdW5jdGlvblJlZmVyZW5jZShyZWZlcmVuY2UpO1xuICAgICAgICBpZiAoIXBhcnNlZCkge1xuICAgICAgICAgICAgZGlhZ25vc3RpY3MucHVzaCh7XG4gICAgICAgICAgICAgICAgc2V2ZXJpdHk6ICdlcnJvcicsXG4gICAgICAgICAgICAgICAgY29kZTogJ2NhbGwudW5rbm93bi1mdW5jdGlvbicsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogYCcke3JlZmVyZW5jZX0nIGlzIG5vdCBhIHZhbGlkIGZ1bmN0aW9uIHJlZmVyZW5jZWBcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIHsgLi4uc3RhdGUsIHJldHVyblZhbHVlcywgZGlhZ25vc3RpY3MgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBzdG9wcGVkOiBFeGVjdXRpb25TdG9wIHwgdW5kZWZpbmVkO1xuXG4gICAgICAgIC8qKiBDaGFyZ2VzIG9uZSBvcGVyYXRpb24sIHJlcG9ydGluZyBhbmQgc3RvcHBpbmcgdGhlIHJ1biBhdCB0aGUgbGltaXQuICovXG4gICAgICAgIGNvbnN0IGNoYXJnZSA9IChmdW5jdGlvbklkOiBzdHJpbmcsIGxpbmU/OiBudW1iZXIpOiBib29sZWFuID0+IHtcbiAgICAgICAgICAgIHN0YXRlLm9wZXJhdGlvbnMgKz0gMTtcbiAgICAgICAgICAgIGlmIChzdGF0ZS5vcGVyYXRpb25zIDw9IHRoaXMubGltaXRzLm1heENvbW1hbmRTZXF1ZW5jZUxlbmd0aCkgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICBzdG9wcGVkID0gJ21heC1jb21tYW5kLXNlcXVlbmNlLWxlbmd0aCc7XG4gICAgICAgICAgICBkaWFnbm9zdGljcy5wdXNoKHtcbiAgICAgICAgICAgICAgICBzZXZlcml0eTogJ2Vycm9yJyxcbiAgICAgICAgICAgICAgICBjb2RlOiAnbGltaXQuY29tbWFuZC1zZXF1ZW5jZS1sZW5ndGgnLFxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uSWQsXG4gICAgICAgICAgICAgICAgbGluZSxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBgdGhlIHJ1biByZWFjaGVkIG1heENvbW1hbmRTZXF1ZW5jZUxlbmd0aCAoJHt0aGlzLmxpbWl0cy5tYXhDb21tYW5kU2VxdWVuY2VMZW5ndGh9KSBhbmQgc3RvcHBlZGBcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKiBJbnN0YW50aWF0ZXMgb25lIGNhbGwgYW5kIHB1c2hlcyBpdHMgZnJhbWUsIG9yIHJlcG9ydHMgd2h5IGl0IGNvdWxkIG5vdC4gKi9cbiAgICAgICAgY29uc3QgaW52b2tlID0gKFxuICAgICAgICAgICAgaWQ6IHN0cmluZyxcbiAgICAgICAgICAgIGFyZ3M6IE1hY3JvQXJndW1lbnRzIHwgdW5kZWZpbmVkLFxuICAgICAgICAgICAgZnJvbTogeyBmdW5jdGlvbklkOiBzdHJpbmc7IGxpbmU/OiBudW1iZXIgfSxcbiAgICAgICAgICAgIHJvb3QgPSBmYWxzZVxuICAgICAgICApOiBib29sZWFuID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNvbXBpbGVkID0gdGhpcy5vcHRpb25zLmZ1bmN0aW9ucy5nZXQoaWQpO1xuICAgICAgICAgICAgaWYgKCFjb21waWxlZCkge1xuICAgICAgICAgICAgICAgIGRpYWdub3N0aWNzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBzZXZlcml0eTogJ2Vycm9yJyxcbiAgICAgICAgICAgICAgICAgICAgY29kZTogJ2NhbGwudW5rbm93bi1mdW5jdGlvbicsXG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uSWQ6IGZyb20uZnVuY3Rpb25JZCxcbiAgICAgICAgICAgICAgICAgICAgbGluZTogZnJvbS5saW5lLFxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBgdGhlIGZ1bmN0aW9uICR7aWR9IGRvZXMgbm90IGV4aXN0YFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWNoYXJnZShmcm9tLmZ1bmN0aW9uSWQsIGZyb20ubGluZSkpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIHN0YXRlLmludm9jYXRpb25zICs9IDE7XG5cbiAgICAgICAgICAgIGNvbnN0IGluc3RhbnRpYXRlZCA9IGNvbXBpbGVkLmluc3RhbnRpYXRlKGFyZ3MpO1xuICAgICAgICAgICAgaWYgKCFpbnN0YW50aWF0ZWQub2spIHtcbiAgICAgICAgICAgICAgICBkaWFnbm9zdGljcy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgc2V2ZXJpdHk6ICdlcnJvcicsXG4gICAgICAgICAgICAgICAgICAgIGNvZGU6ICdtYWNyby5taXNzaW5nLWFyZ3VtZW50cycsXG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uSWQ6IGlkLFxuICAgICAgICAgICAgICAgICAgICBsaW5lOiBpbnN0YW50aWF0ZWQubGluZSxcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogaW5zdGFudGlhdGVkLm1lc3NhZ2VcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQSBjYWxsIG1hZGUgZnJvbSB0aGUgbGFzdCBsaW5lIG9mIGEgZnJhbWUgcmVwbGFjZXMgdGhhdCBmcmFtZVxuICAgICAgICAgICAgLy8gaW5zdGVhZCBvZiBzdGFja2luZyBvbiBpdCwgc28gYSB0YWlsLXJlY3Vyc2l2ZSBmdW5jdGlvbiBydW5zIGluXG4gICAgICAgICAgICAvLyBjb25zdGFudCBkZXB0aCwgYXMgSmF2YSdzIHJld3JpdGUgbWFkZSBpdCBpbiAyM3c0NGEuXG4gICAgICAgICAgICBjb25zdCB0b3AgPSBzdGFjay5hdCgtMSk7XG4gICAgICAgICAgICBjb25zdCByZXBsYWNlZCA9IHRvcCAmJiB0b3AuaW5kZXggPj0gdG9wLmNvbW1hbmRzLmxlbmd0aCA/IHN0YWNrLnBvcCgpIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICBzdGFjay5wdXNoKHtcbiAgICAgICAgICAgICAgICBmdW5jdGlvbklkOiBpZCxcbiAgICAgICAgICAgICAgICBjb21tYW5kczogaW5zdGFudGlhdGVkLmNvbW1hbmRzLFxuICAgICAgICAgICAgICAgIGluZGV4OiAwLFxuICAgICAgICAgICAgICAgIHJvb3Q6IHJlcGxhY2VkPy5yb290ID8/IHJvb3RcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc3RhdGUubWF4RGVwdGggPSBNYXRoLm1heChzdGF0ZS5tYXhEZXB0aCwgc3RhY2subGVuZ3RoKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IGVudHJpZXMgPSBwYXJzZWQua2luZCA9PT0gJ2Z1bmN0aW9uJyA/IFtwYXJzZWQuaWRdIDogdGhpcy5yZXNvbHZlVGFnKHBhcnNlZC5pZCwgcmVmZXJlbmNlLCBkaWFnbm9zdGljcyk7XG5cbiAgICAgICAgLy8gRnJhbWVzIHJ1biBmcm9tIHRoZSB0b3Agb2YgdGhlIHN0YWNrLCBzbyB0aGUgZmlyc3QgZnVuY3Rpb24gb2YgYSB0YWdcbiAgICAgICAgLy8gaXMgcHVzaGVkIGxhc3QuXG4gICAgICAgIGZvciAoY29uc3QgaWQgb2YgWy4uLmVudHJpZXNdLnJldmVyc2UoKSkge1xuICAgICAgICAgICAgaWYgKCFpbnZva2UoaWQsIG9wdGlvbnMuYXJndW1lbnRzLCB7IGZ1bmN0aW9uSWQ6IHJlZmVyZW5jZSB9LCB0cnVlKSkgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICB3aGlsZSAoc3RvcHBlZCA9PT0gdW5kZWZpbmVkICYmIHN0YWNrLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGNvbnN0IGZyYW1lID0gc3RhY2suYXQoLTEpO1xuICAgICAgICAgICAgaWYgKCFmcmFtZSkgYnJlYWs7XG4gICAgICAgICAgICBpZiAoZnJhbWUuaW5kZXggPj0gZnJhbWUuY29tbWFuZHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgc3RhY2sucG9wKCk7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGVudHJ5ID0gZnJhbWUuY29tbWFuZHNbZnJhbWUuaW5kZXhdO1xuICAgICAgICAgICAgZnJhbWUuaW5kZXggKz0gMTtcbiAgICAgICAgICAgIGlmICghZW50cnkpIGNvbnRpbnVlO1xuICAgICAgICAgICAgaWYgKCFjaGFyZ2UoZnJhbWUuZnVuY3Rpb25JZCwgZW50cnkubGluZSkpIGJyZWFrO1xuXG4gICAgICAgICAgICBjb25zdCBjYWxsID0gQ0FMTF9QQVRURVJOLmV4ZWMoZW50cnkuY29tbWFuZCk7XG4gICAgICAgICAgICBpZiAoY2FsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGFuZGxlQ2FsbChjYWxsLCBmcmFtZSwgZW50cnksIGludm9rZSwgZGlhZ25vc3RpY3MpO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzdGF0ZS5jb21tYW5kcyArPSAxO1xuICAgICAgICAgICAgbGV0IGZvcmtzID0gMDtcbiAgICAgICAgICAgIGxldCByZXR1cm5lZDogQ29tbWFuZE91dGNvbWVbJ3JldHVybmVkJ107XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGNvbnN0IG91dGNvbWUgPSB0aGlzLm9wdGlvbnMucnVubmVyLnJ1bihlbnRyeS5jb21tYW5kLCB7XG4gICAgICAgICAgICAgICAgICAgIHNvdXJjZTogb3B0aW9ucy5zb3VyY2UsXG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uSWQ6IGZyYW1lLmZ1bmN0aW9uSWQsXG4gICAgICAgICAgICAgICAgICAgIGxpbmU6IGVudHJ5LmxpbmVcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBmb3JrcyA9IG91dGNvbWUuZm9ya3MgPz8gMDtcbiAgICAgICAgICAgICAgICByZXR1cm5lZCA9IG91dGNvbWUucmV0dXJuZWQ7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGRpYWdub3N0aWNzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBzZXZlcml0eTogJ2Vycm9yJyxcbiAgICAgICAgICAgICAgICAgICAgY29kZTogJ2NvbW1hbmQuZmFpbGVkJyxcbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb25JZDogZnJhbWUuZnVuY3Rpb25JZCxcbiAgICAgICAgICAgICAgICAgICAgbGluZTogZW50cnkubGluZSxcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChyZXR1cm5lZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgLy8gYC9yZXR1cm5gIGVuZHMgdGhpcyBmdW5jdGlvbiBhbmQgbm8gb3RoZXI6IGl0cyBjYWxsZXInc1xuICAgICAgICAgICAgICAgIC8vIGZyYW1lIGlzIHN0aWxsIGJlbG93IGFuZCBydW5zIG9uIGZyb20gd2hlcmUgaXQgY2FsbGVkLlxuICAgICAgICAgICAgICAgIGlmIChmcmFtZS5yb290ICYmIHJldHVybmVkLnZhbHVlICE9PSB1bmRlZmluZWQpIHJldHVyblZhbHVlcy5wdXNoKHJldHVybmVkLnZhbHVlKTtcbiAgICAgICAgICAgICAgICBpZiAoc3RhY2suYXQoLTEpID09PSBmcmFtZSkgc3RhY2sucG9wKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHN0YXRlLmZvcmtzICs9IGZvcmtzO1xuICAgICAgICAgICAgaWYgKHN0YXRlLmZvcmtzID4gdGhpcy5saW1pdHMubWF4Q29tbWFuZEZvcmtzKSB7XG4gICAgICAgICAgICAgICAgc3RvcHBlZCA9ICdtYXgtY29tbWFuZC1mb3Jrcyc7XG4gICAgICAgICAgICAgICAgZGlhZ25vc3RpY3MucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIHNldmVyaXR5OiAnZXJyb3InLFxuICAgICAgICAgICAgICAgICAgICBjb2RlOiAnbGltaXQuY29tbWFuZC1mb3JrcycsXG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uSWQ6IGZyYW1lLmZ1bmN0aW9uSWQsXG4gICAgICAgICAgICAgICAgICAgIGxpbmU6IGVudHJ5LmxpbmUsXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGB0aGUgcnVuIHJlYWNoZWQgbWF4Q29tbWFuZEZvcmtzICgke3RoaXMubGltaXRzLm1heENvbW1hbmRGb3Jrc30pIGFuZCBzdG9wcGVkYFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHsgLi4uc3RhdGUsIHJldHVyblZhbHVlcywgLi4uKHN0b3BwZWQgPyB7IHN0b3BwZWQgfSA6IHt9KSwgZGlhZ25vc3RpY3MgfTtcbiAgICB9XG5cbiAgICAvKiogRXhwYW5kcyBhIHRhZyByZWZlcmVuY2UsIHJlcG9ydGluZyBhIHRhZyBubyBwYWNrIGRlY2xhcmVkLiAqL1xuICAgIHByaXZhdGUgcmVzb2x2ZVRhZyhpZDogc3RyaW5nLCByZWZlcmVuY2U6IHN0cmluZywgZGlhZ25vc3RpY3M6IERpYWdub3N0aWNbXSk6IHJlYWRvbmx5IHN0cmluZ1tdIHtcbiAgICAgICAgaWYgKCF0aGlzLm9wdGlvbnMudGFncykge1xuICAgICAgICAgICAgZGlhZ25vc3RpY3MucHVzaCh7XG4gICAgICAgICAgICAgICAgc2V2ZXJpdHk6ICdlcnJvcicsXG4gICAgICAgICAgICAgICAgY29kZTogJ2NhbGwudW5rbm93bi10YWcnLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGAke3JlZmVyZW5jZX0gaXMgYSB0YWcgcmVmZXJlbmNlLCBhbmQgdGhpcyBleGVjdXRvciBoYXMgbm8gdGFnIGxvb2t1cGBcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVzb2x2ZWQgPSByZXNvbHZlRnVuY3Rpb25UYWcodGhpcy5vcHRpb25zLnRhZ3MsIGlkKTtcbiAgICAgICAgZGlhZ25vc3RpY3MucHVzaCguLi5yZXNvbHZlZC5kaWFnbm9zdGljcyk7XG4gICAgICAgIHJldHVybiByZXNvbHZlZC5mdW5jdGlvbnM7XG4gICAgfVxuXG4gICAgLyoqIFJ1bnMgb25lIGBmdW5jdGlvbmAgbGluZTogcmVzb2x2ZXMgd2hhdCBpdCBuYW1lcyBhbmQgcHVzaGVzIHRoZSBmcmFtZXMgaXQgaW52b2tlcy4gKi9cbiAgICBwcml2YXRlIGhhbmRsZUNhbGwoXG4gICAgICAgIGNhbGw6IFJlZ0V4cEV4ZWNBcnJheSxcbiAgICAgICAgZnJhbWU6IEZyYW1lLFxuICAgICAgICBlbnRyeTogSW5zdGFudGlhdGVkQ29tbWFuZCxcbiAgICAgICAgaW52b2tlOiAoaWQ6IHN0cmluZywgYXJnczogTWFjcm9Bcmd1bWVudHMgfCB1bmRlZmluZWQsIGZyb206IHsgZnVuY3Rpb25JZDogc3RyaW5nOyBsaW5lPzogbnVtYmVyIH0pID0+IGJvb2xlYW4sXG4gICAgICAgIGRpYWdub3N0aWNzOiBEaWFnbm9zdGljW11cbiAgICApOiB2b2lkIHtcbiAgICAgICAgY29uc3QgZnJvbSA9IHsgZnVuY3Rpb25JZDogZnJhbWUuZnVuY3Rpb25JZCwgbGluZTogZW50cnkubGluZSB9O1xuICAgICAgICBjb25zdCB0YXJnZXQ6IEZ1bmN0aW9uUmVmZXJlbmNlIHwgdW5kZWZpbmVkID0gcGFyc2VGdW5jdGlvblJlZmVyZW5jZShjYWxsWzFdID8/ICcnKTtcbiAgICAgICAgaWYgKCF0YXJnZXQpIHtcbiAgICAgICAgICAgIGRpYWdub3N0aWNzLnB1c2goe1xuICAgICAgICAgICAgICAgIHNldmVyaXR5OiAnZXJyb3InLFxuICAgICAgICAgICAgICAgIGNvZGU6ICdjYWxsLnVua25vd24tZnVuY3Rpb24nLFxuICAgICAgICAgICAgICAgIC4uLmZyb20sXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogYCcke2NhbGxbMV0gPz8gJyd9JyBpcyBub3QgYSB2YWxpZCBmdW5jdGlvbiByZWZlcmVuY2VgXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGFyZ3VtZW50VGV4dCA9IChjYWxsWzJdID8/ICcnKS50cmltKCk7XG4gICAgICAgIGxldCBhcmdzOiBNYWNyb0FyZ3VtZW50cyB8IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKGFyZ3VtZW50VGV4dC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBhcmdzID0gdGhpcy5wYXJzZUFyZ3VtZW50cyhhcmd1bWVudFRleHQpO1xuICAgICAgICAgICAgaWYgKGFyZ3MgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGRpYWdub3N0aWNzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBzZXZlcml0eTogJ2Vycm9yJyxcbiAgICAgICAgICAgICAgICAgICAgY29kZTogJ2NhbGwuaW52YWxpZC1hcmd1bWVudHMnLFxuICAgICAgICAgICAgICAgICAgICAuLi5mcm9tLFxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBgdGhlIGFyZ3VtZW50cyBvZiAnJHtlbnRyeS5jb21tYW5kfScgYXJlIG5vdCBhIGNvbXBvdW5kIHRoaXMgcnVudGltZSBjYW4gcmVhZGBcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGFyZ2V0LmtpbmQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGludm9rZSh0YXJnZXQuaWQsIGFyZ3MsIGZyb20pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdGFncyA9IHRoaXMub3B0aW9ucy50YWdzO1xuICAgICAgICBpZiAoIXRhZ3MpIHtcbiAgICAgICAgICAgIGRpYWdub3N0aWNzLnB1c2goe1xuICAgICAgICAgICAgICAgIHNldmVyaXR5OiAnZXJyb3InLFxuICAgICAgICAgICAgICAgIGNvZGU6ICdjYWxsLnVua25vd24tdGFnJyxcbiAgICAgICAgICAgICAgICAuLi5mcm9tLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGAjJHt0YXJnZXQuaWR9IGNhbm5vdCBiZSByZXNvbHZlZCwgYmVjYXVzZSB0aGlzIGV4ZWN1dG9yIGhhcyBubyB0YWcgbG9va3VwYFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXNvbHZlZCA9IHJlc29sdmVGdW5jdGlvblRhZyh0YWdzLCB0YXJnZXQuaWQpO1xuICAgICAgICBkaWFnbm9zdGljcy5wdXNoKC4uLnJlc29sdmVkLmRpYWdub3N0aWNzLm1hcCgoZGlhZ25vc3RpYykgPT4gKHsgLi4uZGlhZ25vc3RpYywgLi4uZnJvbSB9KSkpO1xuICAgICAgICBpZiAoIXJlc29sdmVkLmV4aXN0cykge1xuICAgICAgICAgICAgZGlhZ25vc3RpY3MucHVzaCh7XG4gICAgICAgICAgICAgICAgc2V2ZXJpdHk6ICdlcnJvcicsXG4gICAgICAgICAgICAgICAgY29kZTogJ2NhbGwudW5rbm93bi10YWcnLFxuICAgICAgICAgICAgICAgIC4uLmZyb20sXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogYHRoZSBmdW5jdGlvbiB0YWcgIyR7dGFyZ2V0LmlkfSBkb2VzIG5vdCBleGlzdGBcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChjb25zdCBpZCBvZiBbLi4ucmVzb2x2ZWQuZnVuY3Rpb25zXS5yZXZlcnNlKCkpIHtcbiAgICAgICAgICAgIGlmICghaW52b2tlKGlkLCBhcmdzLCBmcm9tKSkgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7QUF3Q0EsSUFBYSwyQkFBNEM7Q0FDckQsMEJBQTBCO0NBQzFCLGlCQUFpQjtBQUNyQjs7Ozs7O0FBT0EsSUFBYSxvQ0FBb0M7QUE4RWpELElBQU0sZUFBZTs7QUFHckIsSUFBTSxzQkFBc0IsU0FBNkM7Q0FDckUsSUFBSTtDQUNKLElBQUk7RUFDQSxTQUFTLEtBQUssTUFBTSxJQUFJO0NBQzVCLFFBQVE7RUFDSjtDQUNKO0NBRUEsSUFBSSxPQUFPLFdBQVcsWUFBWSxXQUFXLFFBQVEsTUFBTSxRQUFRLE1BQU0sR0FBRyxPQUFPLEtB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
@@ -0,0 +1,140 @@
1
+ /**
2
+ * The executor. Java rewrote function execution in 23w41a from a recursive
3
+ * call path into an explicit queue of frames on the heap, which is what lets
4
+ * it bound work with a counter and stops a tail-recursive pack from
5
+ * exhausting the host stack. This is the same shape: a stack of frames in an
6
+ * array, one loop, and a counter charged per operation.
7
+ */
8
+ import type { CompiledFunction } from './compile';
9
+ import type { Diagnostic } from './diagnostics';
10
+ import type { MacroArguments } from './macro';
11
+ import type { CommandRunner } from './runner';
12
+ import type { FunctionTagLookup } from './tags';
13
+ /**
14
+ * The two gamerules that bound a run. They were renamed in 1.21.11 from
15
+ * `maxCommandChainLength` and `maxCommandForkCount`; anything written against
16
+ * the camelCase names is stale.
17
+ */
18
+ export interface ExecutionLimits {
19
+ /** `minecraft:max_command_sequence_length`: how many operations one entry point may run. */
20
+ maxCommandSequenceLength: number;
21
+ /** `minecraft:max_command_forks`: how many contexts one entry point may create. */
22
+ maxCommandForks: number;
23
+ }
24
+ /**
25
+ * The limits a run uses when the caller sets none.
26
+ *
27
+ * Both default to 65536. Mojang has never published either default: the
28
+ * figure has two independent secondary confirmations (minecraft.wiki's
29
+ * gamerule page and Pumpkin's extraction from the 26.3 server jar) and the
30
+ * `GameRules` class holds 65536 in its constant pool, but no Mojang document
31
+ * attributes the value to either rule. Treat it as a well-corroborated
32
+ * default rather than a confirmed one, and configure it when a world says
33
+ * otherwise.
34
+ */
35
+ export declare const DEFAULT_EXECUTION_LIMITS: ExecutionLimits;
36
+ /**
37
+ * What Bedrock caps a single `/function` call at, from Mojang's creator
38
+ * documentation. This runtime runs Java functions and does not apply it; a
39
+ * server that wants Bedrock's ceiling passes it as `maxCommandSequenceLength`.
40
+ */
41
+ export declare const BEDROCK_MAX_COMMANDS_PER_FUNCTION = 10000;
42
+ /** Where the executor reads compiled functions from. */
43
+ export interface FunctionLookup {
44
+ /** Returns the function registered under a namespaced id. */
45
+ get(id: string): CompiledFunction | undefined;
46
+ }
47
+ /** How to build a {@link FunctionExecutor}. */
48
+ export interface FunctionExecutorOptions<TSource = unknown> {
49
+ functions: FunctionLookup;
50
+ runner: CommandRunner<TSource>;
51
+ /** Resolves `#namespace:tag` references. Without it, a tag reference is reported as unknown. */
52
+ tags?: FunctionTagLookup;
53
+ /** Overrides either limit; anything left out keeps its {@link DEFAULT_EXECUTION_LIMITS} value. */
54
+ limits?: Partial<ExecutionLimits>;
55
+ /**
56
+ * Reads the argument compound of a `function <id> <arguments>` line. The
57
+ * default accepts JSON, because SNBT needs a parser this package does not
58
+ * own; a server with one passes it here.
59
+ */
60
+ parseArguments?: (text: string) => MacroArguments | undefined;
61
+ }
62
+ /** What one call needs beyond the function to run. */
63
+ export interface ExecutionOptions<TSource = unknown> {
64
+ /** The command source every command in the run is given. */
65
+ source: TSource;
66
+ /** The compound a macro function substitutes from. Ignored by a plain function. */
67
+ arguments?: MacroArguments;
68
+ }
69
+ /** Why a run stopped before it finished. */
70
+ export type ExecutionStop = 'max-command-sequence-length' | 'max-command-forks';
71
+ /** What one run did. */
72
+ export interface ExecutionReport {
73
+ /** Operations charged against `maxCommandSequenceLength`. */
74
+ operations: number;
75
+ /** Contexts charged against `maxCommandForks`. */
76
+ forks: number;
77
+ /** How many command lines reached the runner. */
78
+ commands: number;
79
+ /** How many functions the run invoked, including the entry point. */
80
+ invocations: number;
81
+ /** The deepest the frame stack got. A tail call does not deepen it. */
82
+ maxDepth: number;
83
+ /**
84
+ * The values `/return` produced, one per function the entry point
85
+ * invoked directly that reached one.
86
+ *
87
+ * Empty when every function ran to its last line, which is the case Java
88
+ * calls "returned no value". A tag contributes one entry per member that
89
+ * returned, because `execute if function #tag` matches when any member
90
+ * did. A `/return` deeper in the call tree ends its own function and
91
+ * leaves nothing here, the way Java returns from one function rather
92
+ * than from its caller.
93
+ */
94
+ returnValues: readonly number[];
95
+ /** Set when a limit stopped the run; the matching diagnostic carries the detail. */
96
+ stopped?: ExecutionStop;
97
+ diagnostics: readonly Diagnostic[];
98
+ }
99
+ /**
100
+ * Runs functions against a command runner.
101
+ *
102
+ * One executor is reusable: it holds no run state, so a server builds it once
103
+ * at load and calls {@link FunctionExecutor.runTick} every tick.
104
+ *
105
+ * `function <id>` and `function #tag` are the only lines the executor reads
106
+ * itself, because a call is control flow rather than a command: handling it
107
+ * here is what keeps nesting on the queue instead of on the JavaScript stack.
108
+ * Every other line goes to the runner untouched.
109
+ *
110
+ * `/return` is the other half of that split. It is a command, so the runner
111
+ * implements it, but only the executor can act on it: a runner that reports
112
+ * {@link CommandOutcome.returned} ends the function the line came from and
113
+ * the loop carries on with its caller.
114
+ */
115
+ export declare class FunctionExecutor<TSource = unknown> {
116
+ private readonly options;
117
+ private readonly limits;
118
+ private readonly parseArguments;
119
+ constructor(options: FunctionExecutorOptions<TSource>);
120
+ /** Runs `minecraft:load`, which a server does once after its packs load. */
121
+ runLoad(options: ExecutionOptions<TSource>): ExecutionReport;
122
+ /** Runs `minecraft:tick`, which a server does once per server tick. */
123
+ runTick(options: ExecutionOptions<TSource>): ExecutionReport;
124
+ /**
125
+ * Runs one function or every function in one tag.
126
+ *
127
+ * Everything a call reaches shares one budget, so the report covers the
128
+ * whole tree below the entry point. A limit stops the run and is reported
129
+ * as a diagnostic; nothing here throws, and a command that throws is
130
+ * reported and skipped.
131
+ *
132
+ * @param reference - A function id, or a tag id written `#namespace:tag`.
133
+ */
134
+ run(reference: string, options: ExecutionOptions<TSource>): ExecutionReport;
135
+ /** Expands a tag reference, reporting a tag no pack declared. */
136
+ private resolveTag;
137
+ /** Runs one `function` line: resolves what it names and pushes the frames it invokes. */
138
+ private handleCall;
139
+ }
140
+ //# sourceMappingURL=executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"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"}