@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.
- package/CHANGELOG.md +48 -0
- package/LICENSE +373 -0
- package/README.md +182 -0
- package/dist/compile.cjs.cjs +166 -0
- package/dist/compile.d.ts +91 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.es.js +162 -0
- package/dist/diagnostics.cjs.cjs +19 -0
- package/dist/diagnostics.d.ts +62 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.es.js +17 -0
- package/dist/executor.cjs.cjs +302 -0
- package/dist/executor.d.ts +140 -0
- package/dist/executor.d.ts.map +1 -0
- package/dist/executor.es.js +298 -0
- package/dist/identifiers.cjs.cjs +79 -0
- package/dist/identifiers.d.ts +44 -0
- package/dist/identifiers.d.ts.map +1 -0
- package/dist/identifiers.es.js +72 -0
- package/dist/index.cjs.cjs +36 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.es.js +10 -0
- package/dist/macro.cjs.cjs +119 -0
- package/dist/macro.d.ts +59 -0
- package/dist/macro.d.ts.map +1 -0
- package/dist/macro.es.js +115 -0
- package/dist/parse.cjs.cjs +107 -0
- package/dist/parse.d.ts +40 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.es.js +104 -0
- package/dist/registry.cjs.cjs +135 -0
- package/dist/registry.d.ts +53 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.es.js +132 -0
- package/dist/runner.cjs.cjs +42 -0
- package/dist/runner.d.ts +83 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.es.js +40 -0
- package/dist/tags.cjs.cjs +113 -0
- package/dist/tags.d.ts +70 -0
- package/dist/tags.d.ts.map +1 -0
- package/dist/tags.es.js +108 -0
- 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":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAuB,MAAM,WAAW,CAAC;AACvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGhD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,KAAK,EAAkB,aAAa,EAAE,MAAM,UAAU,CAAC;AAC9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAGhD;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC5B,4FAA4F;IAC5F,wBAAwB,EAAE,MAAM,CAAC;IACjC,mFAAmF;IACnF,eAAe,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,wBAAwB,EAAE,eAGtC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iCAAiC,QAAS,CAAC;AAExD,wDAAwD;AACxD,MAAM,WAAW,cAAc;IAC3B,6DAA6D;IAC7D,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAAC;CACjD;AAED,+CAA+C;AAC/C,MAAM,WAAW,uBAAuB,CAAC,OAAO,GAAG,OAAO;IACtD,SAAS,EAAE,cAAc,CAAC;IAC1B,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAC/B,gGAAgG;IAChG,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,kGAAkG;IAClG,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAClC;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,cAAc,GAAG,SAAS,CAAC;CACjE;AAED,sDAAsD;AACtD,MAAM,WAAW,gBAAgB,CAAC,OAAO,GAAG,OAAO;IAC/C,4DAA4D;IAC5D,MAAM,EAAE,OAAO,CAAC;IAChB,mFAAmF;IACnF,SAAS,CAAC,EAAE,cAAc,CAAC;CAC9B;AAED,4CAA4C;AAC5C,MAAM,MAAM,aAAa,GAAG,6BAA6B,GAAG,mBAAmB,CAAC;AAEhF,wBAAwB;AACxB,MAAM,WAAW,eAAe;IAC5B,6DAA6D;IAC7D,UAAU,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,iDAAiD;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,WAAW,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;OAUG;IACH,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,oFAAoF;IACpF,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,WAAW,EAAE,SAAS,UAAU,EAAE,CAAC;CACtC;AA+BD;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,gBAAgB,CAAC,OAAO,GAAG,OAAO;IAKxB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJ3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IAEzC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA+C;IAE9E,YAAoC,OAAO,EAAE,uBAAuB,CAAC,OAAO,CAAC,EAG5E;IAED,4EAA4E;IACrE,OAAO,CAAC,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,GAAG,eAAe,CAElE;IAED,uEAAuE;IAChE,OAAO,CAAC,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,GAAG,eAAe,CAElE;IAED;;;;;;;;;OASG;IACI,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,GAAG,eAAe,CAyJjF;IAED,iEAAiE;IACjE,OAAO,CAAC,UAAU;IAelB,yFAAyF;IACzF,OAAO,CAAC,UAAU;CAkErB"}
|