@neocompose/cli 0.84.3 → 0.84.4
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 +17 -0
- package/dist/neo-runtime.mjs +388 -189
- package/dist/test-worker.mjs +171 -51
- package/package.json +1 -1
- package/skills/neocompose-cli/SKILL.md +1 -1
- package/skills/neocompose-cli/references/cli-development.md +1 -1
- package/skills/neocompose-cli/references/commands-and-sync.md +3 -0
- package/skills/neocompose-cli/references/declarations-and-construction.md +4 -0
- package/skills/neocompose-cli/references/neoscript.md +14 -3
- package/skills/neocompose-cli/references/values-identities-and-references.md +16 -0
package/dist/test-worker.mjs
CHANGED
|
@@ -3302,14 +3302,14 @@ function isNSFunctionContains(value) {
|
|
|
3302
3302
|
if (v?.type !== "contains" /* contains */) return false;
|
|
3303
3303
|
const info = v.info;
|
|
3304
3304
|
if (typeof info !== "object" || info === null) return false;
|
|
3305
|
-
return isNSPointer(info.collectionPointer) && isNSPointer(info.valuePointer) && isReferenceFlag(info.reference);
|
|
3305
|
+
return isNSPointer(info.collectionPointer) && isNSPointer(info.valuePointer) && isReferenceFlag(info.reference) && (info.float === void 0 || info.float === true) && (info.decimal === void 0 || info.decimal === true);
|
|
3306
3306
|
}
|
|
3307
3307
|
function isNSFunctionIndexOf(value) {
|
|
3308
3308
|
const v = value;
|
|
3309
3309
|
if (v?.type !== "indexOf" /* indexOf */) return false;
|
|
3310
3310
|
const info = v.info;
|
|
3311
3311
|
if (typeof info !== "object" || info === null) return false;
|
|
3312
|
-
return isNSPointer(info.collectionPointer) && isNSPointer(info.valuePointer) && isReferenceFlag(info.reference);
|
|
3312
|
+
return isNSPointer(info.collectionPointer) && isNSPointer(info.valuePointer) && isReferenceFlag(info.reference) && (info.float === void 0 || info.float === true) && (info.decimal === void 0 || info.decimal === true);
|
|
3313
3313
|
}
|
|
3314
3314
|
var NS_STRING_OPS = [
|
|
3315
3315
|
"toLower",
|
|
@@ -3483,7 +3483,7 @@ function isNSFunctionCollectionQuery(value) {
|
|
|
3483
3483
|
case "Reverse":
|
|
3484
3484
|
return true;
|
|
3485
3485
|
case "ToSet":
|
|
3486
|
-
return info.reference === void 0 || info.reference === true;
|
|
3486
|
+
return (info.reference === void 0 || info.reference === true) && (info.decimalEntries === void 0 || info.decimalEntries === true);
|
|
3487
3487
|
default:
|
|
3488
3488
|
return false;
|
|
3489
3489
|
}
|
|
@@ -17029,16 +17029,18 @@ var UncompiledInitializerRuntimeError = class extends NSGetterRuntimeError {
|
|
|
17029
17029
|
|
|
17030
17030
|
// ../packages/neoscript-runtime/src/neoscript/runtime-set.ts
|
|
17031
17031
|
var RuntimeSet = class {
|
|
17032
|
-
constructor(source, reference, enumEntries, slotReferences = null) {
|
|
17032
|
+
constructor(source, reference, enumEntries, slotReferences = null, decimalEntries = false) {
|
|
17033
17033
|
this.source = source;
|
|
17034
17034
|
this.reference = reference;
|
|
17035
17035
|
this.enumEntries = enumEntries;
|
|
17036
17036
|
this.slotReferences = slotReferences;
|
|
17037
|
+
this.decimalEntries = decimalEntries;
|
|
17037
17038
|
}
|
|
17038
17039
|
source;
|
|
17039
17040
|
reference;
|
|
17040
17041
|
enumEntries;
|
|
17041
17042
|
slotReferences;
|
|
17043
|
+
decimalEntries;
|
|
17042
17044
|
entries = /* @__PURE__ */ new Map();
|
|
17043
17045
|
validations = /* @__PURE__ */ new Map();
|
|
17044
17046
|
snapshot;
|
|
@@ -17048,6 +17050,9 @@ var RuntimeSet = class {
|
|
|
17048
17050
|
has(key) {
|
|
17049
17051
|
return this.entries.has(key);
|
|
17050
17052
|
}
|
|
17053
|
+
*values() {
|
|
17054
|
+
for (const entry of this.entries.values()) yield entry.raw;
|
|
17055
|
+
}
|
|
17051
17056
|
add(key, raw, reference) {
|
|
17052
17057
|
if (this.entries.has(key)) return;
|
|
17053
17058
|
this.entries.set(key, { raw, reference });
|
|
@@ -21440,7 +21445,14 @@ function evaluateNSGetterWithEffects(getter, ctx, argumentValues = [], options =
|
|
|
21440
21445
|
for (let index = 0; index < argumentValues.length; index += 1) {
|
|
21441
21446
|
const parameter3 = parameters[index];
|
|
21442
21447
|
if (parameter3 === void 0) continue;
|
|
21443
|
-
scope.setLocal(
|
|
21448
|
+
scope.setLocal(
|
|
21449
|
+
parameter3.id,
|
|
21450
|
+
coerceAssignmentValue(
|
|
21451
|
+
argumentValues[index],
|
|
21452
|
+
parameter3.typeInfo,
|
|
21453
|
+
"getter argument"
|
|
21454
|
+
)
|
|
21455
|
+
);
|
|
21444
21456
|
}
|
|
21445
21457
|
try {
|
|
21446
21458
|
const result = evalBody(
|
|
@@ -21450,9 +21462,11 @@ function evaluateNSGetterWithEffects(getter, ctx, argumentValues = [], options =
|
|
|
21450
21462
|
evaluationOptions(runtimeCtx, false)
|
|
21451
21463
|
);
|
|
21452
21464
|
if (result.kind === "return") {
|
|
21453
|
-
|
|
21454
|
-
result.value
|
|
21455
|
-
|
|
21465
|
+
result.value = coerceAssignmentValue(
|
|
21466
|
+
result.value,
|
|
21467
|
+
getter.typeInfo,
|
|
21468
|
+
"return"
|
|
21469
|
+
);
|
|
21456
21470
|
if (ownsInvocationState) {
|
|
21457
21471
|
flushRuntimeSets(runtimeCtx);
|
|
21458
21472
|
result.value = exportRuntimeSetValue(result.value, runtimeCtx);
|
|
@@ -22324,7 +22338,11 @@ function executeCompiledFunction(action, ctx, args, allowFallthroughReturn, runt
|
|
|
22324
22338
|
const parameter3 = action.parameters[index + 2];
|
|
22325
22339
|
const runtimeTypeInfo = runtimeArgumentTypes[index];
|
|
22326
22340
|
const value2 = asDeclaredRuntimeSet(
|
|
22327
|
-
|
|
22341
|
+
coerceAssignmentValue(
|
|
22342
|
+
restoreExportedReferences(filledArgs[index], runtimeTypeInfo, ctx),
|
|
22343
|
+
runtimeTypeInfo,
|
|
22344
|
+
"function argument"
|
|
22345
|
+
),
|
|
22328
22346
|
runtimeTypeInfo,
|
|
22329
22347
|
ctx
|
|
22330
22348
|
);
|
|
@@ -22358,9 +22376,7 @@ function executeCompiledFunction(action, ctx, args, allowFallthroughReturn, runt
|
|
|
22358
22376
|
}
|
|
22359
22377
|
return null;
|
|
22360
22378
|
}
|
|
22361
|
-
|
|
22362
|
-
value = coerceDecimalOperand(value, "function return");
|
|
22363
|
-
}
|
|
22379
|
+
value = coerceAssignmentValue(value, runtimeReturnType, "function return");
|
|
22364
22380
|
if (!runtimeValueMatchesType(value, runtimeReturnType, ctx)) {
|
|
22365
22381
|
throw new NSGetterRuntimeError(
|
|
22366
22382
|
"NSFunction returned a value that does not match its compiled return type."
|
|
@@ -22702,9 +22718,11 @@ function evalInstructions(instructions, scope, ctx, options) {
|
|
|
22702
22718
|
}
|
|
22703
22719
|
case "variable" /* variable */: {
|
|
22704
22720
|
let value = evalPointer(ins.variable.pointer, scope, ctx);
|
|
22705
|
-
|
|
22706
|
-
value
|
|
22707
|
-
|
|
22721
|
+
value = coerceAssignmentValue(
|
|
22722
|
+
value,
|
|
22723
|
+
ins.variable.typeInfo,
|
|
22724
|
+
"variable initialization"
|
|
22725
|
+
);
|
|
22708
22726
|
value = asDeclaredRuntimeSet(value, ins.variable.typeInfo, ctx);
|
|
22709
22727
|
scope.setLocal(ins.variable.id, value);
|
|
22710
22728
|
break;
|
|
@@ -22740,9 +22758,11 @@ function evalInstructions(instructions, scope, ctx, options) {
|
|
|
22740
22758
|
}
|
|
22741
22759
|
case "assign" /* assign */: {
|
|
22742
22760
|
let value = evalPointer(ins.pointer, scope, ctx);
|
|
22743
|
-
|
|
22744
|
-
value
|
|
22745
|
-
|
|
22761
|
+
value = coerceAssignmentValue(
|
|
22762
|
+
value,
|
|
22763
|
+
ins.target.typeInfo,
|
|
22764
|
+
"assignment"
|
|
22765
|
+
);
|
|
22746
22766
|
if (ins.target.pointer.type === "variable" /* variable */) {
|
|
22747
22767
|
assertVariableBindingWritable(scope, ins.target.pointer.variableId);
|
|
22748
22768
|
scope.setLocal(ins.target.pointer.variableId, value);
|
|
@@ -24524,6 +24544,21 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
|
|
|
24524
24544
|
);
|
|
24525
24545
|
}
|
|
24526
24546
|
const args = ins.args.map((arg) => evalPointer(arg, scope, ctx));
|
|
24547
|
+
const decimalEntries = "entryTypeInfo" in ins.target.typeInfo && ins.target.typeInfo.entryTypeInfo.type === 20 /* Decimal */;
|
|
24548
|
+
let entryArgumentIndex = null;
|
|
24549
|
+
const dictionary = ins.target.typeInfo.type === 5 /* Dictionary */;
|
|
24550
|
+
if (ins.mutation === "Add" /* Add */)
|
|
24551
|
+
entryArgumentIndex = dictionary ? 1 : 0;
|
|
24552
|
+
if (ins.mutation === "Insert" /* Insert */) entryArgumentIndex = 1;
|
|
24553
|
+
if (ins.mutation === "Remove" /* Remove */ && !dictionary)
|
|
24554
|
+
entryArgumentIndex = 0;
|
|
24555
|
+
if (entryArgumentIndex !== null && "entryTypeInfo" in ins.target.typeInfo) {
|
|
24556
|
+
args[entryArgumentIndex] = coerceAssignmentValue(
|
|
24557
|
+
args[entryArgumentIndex],
|
|
24558
|
+
ins.target.typeInfo.entryTypeInfo,
|
|
24559
|
+
"collection mutation entry"
|
|
24560
|
+
);
|
|
24561
|
+
}
|
|
24527
24562
|
const setEntryMember = mutatesLocalVariable ? null : storedSetEntryMember(targetValue, ctx);
|
|
24528
24563
|
const isLookupSet = setEntryMember === null && ins.target.typeInfo.type === 9 /* Lookup */;
|
|
24529
24564
|
if (isLookupSet && Array.isArray(targetValue)) {
|
|
@@ -24531,7 +24566,8 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
|
|
|
24531
24566
|
targetValue,
|
|
24532
24567
|
ins.reference === true,
|
|
24533
24568
|
ins.target.typeInfo.type === 9 /* Lookup */ && (ins.target.typeInfo.entryTypeInfo.type === 8 /* Enum */ || ins.target.typeInfo.entryTypeInfo.type === 18 /* DialogueLookup */),
|
|
24534
|
-
ctx
|
|
24569
|
+
ctx,
|
|
24570
|
+
decimalEntries
|
|
24535
24571
|
);
|
|
24536
24572
|
}
|
|
24537
24573
|
const setMatch = setEntryMember !== null && Array.isArray(targetValue) && (ins.mutation === "Add" /* Add */ || ins.mutation === "Remove" /* Remove */) ? findStoredSetEntry(targetValue, args[0], setEntryMember, ctx) : null;
|
|
@@ -24550,7 +24586,8 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
|
|
|
24550
24586
|
ctx,
|
|
24551
24587
|
isLookupSet,
|
|
24552
24588
|
false,
|
|
24553
|
-
ins.reference === true
|
|
24589
|
+
ins.reference === true,
|
|
24590
|
+
decimalEntries
|
|
24554
24591
|
);
|
|
24555
24592
|
updateCollectionReferenceProvenance(
|
|
24556
24593
|
targetValue,
|
|
@@ -24628,7 +24665,8 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
|
|
|
24628
24665
|
ctx,
|
|
24629
24666
|
isLookupSet,
|
|
24630
24667
|
ins.reference !== true && ins.mutation === "Remove" /* Remove */ && isArrayCollection(targetValue) && setEntryMember === null && !isLookupSet && findKnownRowIdByValueReference(args[0], ctx) === null,
|
|
24631
|
-
ins.reference === true
|
|
24668
|
+
ins.reference === true,
|
|
24669
|
+
setEntryMember === null && decimalEntries
|
|
24632
24670
|
);
|
|
24633
24671
|
updateCollectionReferenceProvenance(
|
|
24634
24672
|
targetValue,
|
|
@@ -24904,21 +24942,28 @@ function asDeclaredRuntimeSet(value, type, ctx) {
|
|
|
24904
24942
|
value,
|
|
24905
24943
|
entry === 7 /* Class */ || entry === 22 /* Interface */ || entry === 6 /* List */ || entry === 5 /* Dictionary */ || entry === 9 /* Lookup */,
|
|
24906
24944
|
entry === 8 /* Enum */ || entry === 18 /* DialogueLookup */,
|
|
24907
|
-
ctx
|
|
24945
|
+
ctx,
|
|
24946
|
+
entry === 20 /* Decimal */
|
|
24908
24947
|
);
|
|
24909
24948
|
}
|
|
24910
24949
|
function runtimeSetKey(value, set, ctx) {
|
|
24911
24950
|
if (set.slotReferences !== null) return slotReferenceKey(value);
|
|
24912
24951
|
if (set.enumEntries && Array.isArray(value) && value.length === 1)
|
|
24913
24952
|
value = value[0];
|
|
24914
|
-
return toSetEntryKey(value, null, set.reference, ctx);
|
|
24953
|
+
return toSetEntryKey(value, null, set.reference, ctx, set.decimalEntries);
|
|
24915
24954
|
}
|
|
24916
|
-
function runtimeSet(array2, reference, enumEntries, ctx) {
|
|
24955
|
+
function runtimeSet(array2, reference, enumEntries, ctx, decimalEntries = false) {
|
|
24917
24956
|
const sets = ctx.__runtimeSets ??= /* @__PURE__ */ new WeakMap();
|
|
24918
24957
|
ctx.__dirtyRuntimeSets ??= /* @__PURE__ */ new Set();
|
|
24919
24958
|
const existing = sets.get(array2);
|
|
24920
24959
|
if (existing !== void 0) return existing;
|
|
24921
|
-
const set = new RuntimeSet(
|
|
24960
|
+
const set = new RuntimeSet(
|
|
24961
|
+
array2,
|
|
24962
|
+
reference,
|
|
24963
|
+
enumEntries,
|
|
24964
|
+
null,
|
|
24965
|
+
decimalEntries
|
|
24966
|
+
);
|
|
24922
24967
|
const references = collectionReferences(array2, ctx);
|
|
24923
24968
|
for (let index = 0; index < array2.length; index++) {
|
|
24924
24969
|
const raw = array2[index];
|
|
@@ -25037,7 +25082,7 @@ function removableEntryRowIds(targetValue, mutation, args, ctx) {
|
|
|
25037
25082
|
}
|
|
25038
25083
|
return rowIds;
|
|
25039
25084
|
}
|
|
25040
|
-
function applyLocalCollectionMutation(targetValue, mutation, args, ctx, unique = false, resolveRemovalEntries = false, reference = false) {
|
|
25085
|
+
function applyLocalCollectionMutation(targetValue, mutation, args, ctx, unique = false, resolveRemovalEntries = false, reference = false, decimal = false) {
|
|
25041
25086
|
if (targetValue instanceof RuntimeSet) {
|
|
25042
25087
|
(ctx.__dirtyRuntimeSets ??= /* @__PURE__ */ new Set()).add(targetValue);
|
|
25043
25088
|
switch (mutation) {
|
|
@@ -25089,6 +25134,7 @@ function applyLocalCollectionMutation(targetValue, mutation, args, ctx, unique =
|
|
|
25089
25134
|
case "Remove" /* Remove */:
|
|
25090
25135
|
if (Array.isArray(targetValue)) {
|
|
25091
25136
|
const references = resolveRemovalEntries ? collectionReferences(targetValue, ctx) : recordedReferenceEntries(targetValue, ctx) ?? 1 /* Values */;
|
|
25137
|
+
const targetKey = decimal ? decimalCollectionKey(args[0]) : args[0];
|
|
25092
25138
|
let index = -1;
|
|
25093
25139
|
for (let candidate = 0; candidate < targetValue.length; candidate += 1) {
|
|
25094
25140
|
const entry = targetValue[candidate];
|
|
@@ -25099,10 +25145,8 @@ function applyLocalCollectionMutation(targetValue, mutation, args, ctx, unique =
|
|
|
25099
25145
|
}
|
|
25100
25146
|
continue;
|
|
25101
25147
|
}
|
|
25102
|
-
|
|
25103
|
-
|
|
25104
|
-
args[0]
|
|
25105
|
-
)) {
|
|
25148
|
+
const value = typeof entry === "string" && isReferenceEntry(references, candidate) ? resolveValueIfId(entry, ctx) : entry;
|
|
25149
|
+
if (jsEqual(decimal ? decimalCollectionKey(value) : value, targetKey)) {
|
|
25106
25150
|
index = candidate;
|
|
25107
25151
|
break;
|
|
25108
25152
|
}
|
|
@@ -25589,12 +25633,22 @@ function evalPointerCore(pointer, scope, ctx, resultUsage = "value") {
|
|
|
25589
25633
|
case "function" /* function */:
|
|
25590
25634
|
return evalFunction(pointer.function, scope, ctx);
|
|
25591
25635
|
case "listLiteral" /* listLiteral */:
|
|
25592
|
-
return pointer.entries.map(
|
|
25636
|
+
return pointer.entries.map(
|
|
25637
|
+
(entry) => coerceAssignmentValue(
|
|
25638
|
+
evalPointer(entry, scope, ctx),
|
|
25639
|
+
pointer.typeInfo.entryTypeInfo,
|
|
25640
|
+
"list entry"
|
|
25641
|
+
)
|
|
25642
|
+
);
|
|
25593
25643
|
case "dictLiteral" /* dictLiteral */: {
|
|
25594
25644
|
const out = {};
|
|
25595
25645
|
for (const e of pointer.entries) {
|
|
25596
25646
|
const k = evalPointer(e.key, scope, ctx);
|
|
25597
|
-
out[String(k)] =
|
|
25647
|
+
out[String(k)] = coerceAssignmentValue(
|
|
25648
|
+
evalPointer(e.value, scope, ctx),
|
|
25649
|
+
pointer.typeInfo.entryTypeInfo,
|
|
25650
|
+
"dictionary entry"
|
|
25651
|
+
);
|
|
25598
25652
|
}
|
|
25599
25653
|
return out;
|
|
25600
25654
|
}
|
|
@@ -27257,9 +27311,9 @@ function readRecordKey(receiver, k, memberId, ctx) {
|
|
|
27257
27311
|
if (receiver === ctx.thisValue && typeof ctx.thisValueRowId === "string") {
|
|
27258
27312
|
return ctx.thisValueRowId;
|
|
27259
27313
|
}
|
|
27260
|
-
const
|
|
27261
|
-
if (
|
|
27262
|
-
|
|
27314
|
+
const row = trackedRowForValueReference(receiver, ctx);
|
|
27315
|
+
if (row !== null && classIdForValueRow(row, ctx) !== void 0)
|
|
27316
|
+
return row.id;
|
|
27263
27317
|
}
|
|
27264
27318
|
const assetMember = resolveAssetRuntimeMember(receiver, k, ctx);
|
|
27265
27319
|
if (assetMember.kind === "ok") return assetMember.value;
|
|
@@ -28690,7 +28744,11 @@ function evalDecimalMathOp(info, fn, scope, ctx) {
|
|
|
28690
28744
|
}
|
|
28691
28745
|
}
|
|
28692
28746
|
function evalListRepeat(info, scope, ctx) {
|
|
28693
|
-
const value =
|
|
28747
|
+
const value = coerceAssignmentValue(
|
|
28748
|
+
evalPointer(info.valuePointer, scope, ctx),
|
|
28749
|
+
info.entryTypeInfo,
|
|
28750
|
+
"List.Repeat entry"
|
|
28751
|
+
);
|
|
28694
28752
|
const count = numberArg(
|
|
28695
28753
|
evalPointer(info.countPointer, scope, ctx),
|
|
28696
28754
|
"List.Repeat count"
|
|
@@ -28778,13 +28836,18 @@ function jsEqual(a, b) {
|
|
|
28778
28836
|
return a instanceof NSSlotReference && b instanceof NSSlotReference && a.targetId === b.targetId;
|
|
28779
28837
|
}
|
|
28780
28838
|
if (a === b) return true;
|
|
28781
|
-
if (Array.isArray(a)
|
|
28782
|
-
if (
|
|
28783
|
-
|
|
28784
|
-
|
|
28839
|
+
if (Array.isArray(a) || a instanceof RuntimeSet) {
|
|
28840
|
+
if (!Array.isArray(b) && !(b instanceof RuntimeSet)) return false;
|
|
28841
|
+
const aSize = a instanceof RuntimeSet ? a.size : a.length;
|
|
28842
|
+
const bSize = b instanceof RuntimeSet ? b.size : b.length;
|
|
28843
|
+
if (aSize !== bSize) return false;
|
|
28844
|
+
const other = b.values();
|
|
28845
|
+
for (const entry of a.values()) {
|
|
28846
|
+
if (!jsEqual(entry, other.next().value)) return false;
|
|
28785
28847
|
}
|
|
28786
28848
|
return true;
|
|
28787
28849
|
}
|
|
28850
|
+
if (b instanceof RuntimeSet) return false;
|
|
28788
28851
|
if (typeof a === "object" && typeof b === "object" && a !== null && b !== null && !Array.isArray(a) && !Array.isArray(b)) {
|
|
28789
28852
|
const aKeys = Object.keys(a);
|
|
28790
28853
|
const bKeys = Object.keys(b);
|
|
@@ -29220,7 +29283,8 @@ function evalCollectionQuery(info, scope, ctx) {
|
|
|
29220
29283
|
output,
|
|
29221
29284
|
info.reference === true,
|
|
29222
29285
|
info.enumEntries === true,
|
|
29223
|
-
ctx
|
|
29286
|
+
ctx,
|
|
29287
|
+
info.decimalEntries === true
|
|
29224
29288
|
) : output;
|
|
29225
29289
|
};
|
|
29226
29290
|
if (info.op === "OrderBy" || info.op === "OrderByDescending") {
|
|
@@ -29272,7 +29336,8 @@ function evalCollectionQuery(info, scope, ctx) {
|
|
|
29272
29336
|
entry,
|
|
29273
29337
|
valueId,
|
|
29274
29338
|
info.reference === true,
|
|
29275
|
-
ctx
|
|
29339
|
+
ctx,
|
|
29340
|
+
info.decimalEntries === true
|
|
29276
29341
|
);
|
|
29277
29342
|
if (seenSetKeys.has(setKey)) return 0 /* Continue */;
|
|
29278
29343
|
seenSetKeys.add(setKey);
|
|
@@ -29327,10 +29392,15 @@ function evalCollectionQuery(info, scope, ctx) {
|
|
|
29327
29392
|
}
|
|
29328
29393
|
return finish();
|
|
29329
29394
|
}
|
|
29330
|
-
function toSetEntryKey(entry, valueId, reference, ctx) {
|
|
29395
|
+
function toSetEntryKey(entry, valueId, reference, ctx, decimal = false) {
|
|
29331
29396
|
if (reference) return valueId ?? referenceIdOf(entry, ctx) ?? entry;
|
|
29397
|
+
if (decimal) return decimalCollectionKey(entry);
|
|
29332
29398
|
return typeof entry === "object" && entry !== null ? canonicalJsonStringify(entry) : entry;
|
|
29333
29399
|
}
|
|
29400
|
+
function decimalCollectionKey(value) {
|
|
29401
|
+
if (value === null) return null;
|
|
29402
|
+
return decimalKey(coerceDecimalOperand(value, "decimal collection entry"));
|
|
29403
|
+
}
|
|
29334
29404
|
function compareCollectionKeys(left, right, keyType) {
|
|
29335
29405
|
if (left === null) return right === null ? 0 : -1;
|
|
29336
29406
|
if (right === null) return 1;
|
|
@@ -29448,7 +29518,11 @@ function evalFunction(fn, scope, ctx) {
|
|
|
29448
29518
|
}
|
|
29449
29519
|
case "contains" /* contains */: {
|
|
29450
29520
|
let c = evalPointer(fn.info.collectionPointer, scope, ctx);
|
|
29451
|
-
|
|
29521
|
+
let target = evalPointer(fn.info.valuePointer, scope, ctx);
|
|
29522
|
+
if (fn.info.float === true && typeof target === "number")
|
|
29523
|
+
target = Math.fround(target);
|
|
29524
|
+
if (fn.info.decimal === true && target !== null)
|
|
29525
|
+
target = coerceDecimalOperand(target, "collection search");
|
|
29452
29526
|
if (typeof c === "string") {
|
|
29453
29527
|
if (typeof target !== "string") {
|
|
29454
29528
|
throw new NSGetterRuntimeError(
|
|
@@ -29481,9 +29555,13 @@ function evalFunction(fn, scope, ctx) {
|
|
|
29481
29555
|
return referenceIndexOf(c, target, ctx) !== null;
|
|
29482
29556
|
}
|
|
29483
29557
|
const targetReferenceId = typeof target === "string" ? null : findKnownRowIdByValueReference(target, ctx);
|
|
29558
|
+
const targetKey = fn.info.decimal ? decimalCollectionKey(target) : target;
|
|
29484
29559
|
let containsResolvedEntry = false;
|
|
29485
29560
|
iterateCollection(c, ctx, (entry, _key, valueId) => {
|
|
29486
|
-
if (valueId !== null && valueId === targetReferenceId || jsEqual(
|
|
29561
|
+
if (valueId !== null && valueId === targetReferenceId || jsEqual(
|
|
29562
|
+
fn.info.decimal ? decimalCollectionKey(entry) : entry,
|
|
29563
|
+
targetKey
|
|
29564
|
+
)) {
|
|
29487
29565
|
containsResolvedEntry = true;
|
|
29488
29566
|
return 1 /* Break */;
|
|
29489
29567
|
}
|
|
@@ -29496,15 +29574,21 @@ function evalFunction(fn, scope, ctx) {
|
|
|
29496
29574
|
evalPointer(fn.info.collectionPointer, scope, ctx),
|
|
29497
29575
|
"IndexOf receiver"
|
|
29498
29576
|
);
|
|
29499
|
-
|
|
29577
|
+
let target = evalPointer(fn.info.valuePointer, scope, ctx);
|
|
29578
|
+
if (fn.info.float === true && typeof target === "number")
|
|
29579
|
+
target = Math.fround(target);
|
|
29500
29580
|
if (fn.info.reference === true) {
|
|
29501
29581
|
const index = referenceIndexOf(collection, target, ctx);
|
|
29502
29582
|
return index === null ? -1 : numberArg(index, "IndexOf index");
|
|
29503
29583
|
}
|
|
29504
29584
|
const targetReferenceId = typeof target === "string" ? null : findKnownRowIdByValueReference(target, ctx);
|
|
29585
|
+
const targetKey = fn.info.decimal ? decimalCollectionKey(target) : target;
|
|
29505
29586
|
let found = -1;
|
|
29506
29587
|
iterateCollection(collection, ctx, (entry, key, valueId) => {
|
|
29507
|
-
if (valueId !== null && valueId === targetReferenceId || jsEqual(
|
|
29588
|
+
if (valueId !== null && valueId === targetReferenceId || jsEqual(
|
|
29589
|
+
fn.info.decimal ? decimalCollectionKey(entry) : entry,
|
|
29590
|
+
targetKey
|
|
29591
|
+
)) {
|
|
29508
29592
|
found = numberArg(key, "IndexOf index");
|
|
29509
29593
|
return 1 /* Break */;
|
|
29510
29594
|
}
|
|
@@ -29712,7 +29796,19 @@ function evalFunction(fn, scope, ctx) {
|
|
|
29712
29796
|
);
|
|
29713
29797
|
iterateCollection(c, ctx, callback);
|
|
29714
29798
|
}
|
|
29715
|
-
if (found !== sentinel)
|
|
29799
|
+
if (found !== sentinel) {
|
|
29800
|
+
if (typeof found === "string") {
|
|
29801
|
+
if (c instanceof RuntimeSet) {
|
|
29802
|
+
if (c.enumEntries) return [found];
|
|
29803
|
+
} else {
|
|
29804
|
+
const row = trackedRowForValueReference(c, ctx);
|
|
29805
|
+
const member = row === null ? null : memberForValueRow(row, ctx);
|
|
29806
|
+
if (member?.kind === 8 /* Enum */ || member?.kind === 18 /* DialogueLookup */)
|
|
29807
|
+
return [found];
|
|
29808
|
+
}
|
|
29809
|
+
}
|
|
29810
|
+
return found;
|
|
29811
|
+
}
|
|
29716
29812
|
if (fn.type === "first" /* first */) {
|
|
29717
29813
|
throw new NSGetterRuntimeError(
|
|
29718
29814
|
innerFn ? "First() found no matching entry. Use FirstOrDefault() and handle null if no match is expected." : "First() called on an empty collection. Check that it has entries, or use FirstOrDefault() and handle null."
|
|
@@ -30926,10 +31022,19 @@ function constructionInitEvaluator(ctx, createdValues, argumentScopes, construct
|
|
|
30926
31022
|
}
|
|
30927
31023
|
return null;
|
|
30928
31024
|
};
|
|
31025
|
+
const defaultScopeMemberId = (memberId) => walkExtendsMemberChain(
|
|
31026
|
+
memberId,
|
|
31027
|
+
ctx.vm.members,
|
|
31028
|
+
(declaration) => declaration.defaultValue === void 0 ? void 0 : declaration.id,
|
|
31029
|
+
{
|
|
31030
|
+
memberById: (id) => indexes4.schemaIndex.member(id) ?? null,
|
|
31031
|
+
maxHops: ctx.vm.members.length
|
|
31032
|
+
}
|
|
31033
|
+
);
|
|
30929
31034
|
return (member, init, sourceValueId, genericEnv = instanceEnv) => {
|
|
30930
31035
|
const memberId = Reflect.get(member, "id");
|
|
30931
31036
|
const effectiveMemberId = typeof memberId === "string" ? memberId : null;
|
|
30932
|
-
const scopeMemberId = indexes4.initializerScopeMemberIds.get(init) ?? (typeof sourceValueId !== "string" ? void 0 : indexes4.initializerScopeMemberIdsByValueId.get(sourceValueId)) ?? effectiveMemberId;
|
|
31037
|
+
const scopeMemberId = indexes4.initializerScopeMemberIds.get(init) ?? (typeof sourceValueId !== "string" ? void 0 : indexes4.initializerScopeMemberIdsByValueId.get(sourceValueId)) ?? (sourceValueId === void 0 && effectiveMemberId !== null ? defaultScopeMemberId(effectiveMemberId) : void 0) ?? effectiveMemberId;
|
|
30933
31038
|
const compiled = ensureInitializerCompiled({
|
|
30934
31039
|
init,
|
|
30935
31040
|
member,
|
|
@@ -50069,7 +50174,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
50069
50174
|
scope
|
|
50070
50175
|
)
|
|
50071
50176
|
);
|
|
50072
|
-
const schemaClassInfo =
|
|
50177
|
+
const schemaClassInfo = this.constructorWireType(targetType, expression);
|
|
50073
50178
|
if (schemaClassInfo.type !== 7 /* Class */) {
|
|
50074
50179
|
throw new Error(
|
|
50075
50180
|
`NeoScript constructor ${className} has non-Class return type ${this.describe(signature.returnType)}.`
|
|
@@ -50087,6 +50192,16 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
50087
50192
|
writability: "session" /* Session */
|
|
50088
50193
|
};
|
|
50089
50194
|
}
|
|
50195
|
+
/** Constructor storage arguments stay distinct from their expression read types. */
|
|
50196
|
+
constructorWireType(target, expression) {
|
|
50197
|
+
const typeArguments = expression.typeArguments?.map(
|
|
50198
|
+
(argument2) => resolveStoredReferenceTarget(argument2, this.context, this.project)
|
|
50199
|
+
);
|
|
50200
|
+
return toWireType(
|
|
50201
|
+
typeArguments === void 0 ? target : { ...target, typeArguments },
|
|
50202
|
+
this.project
|
|
50203
|
+
);
|
|
50204
|
+
}
|
|
50090
50205
|
constructorTargetType(schemaClass2, expression, expected) {
|
|
50091
50206
|
const typeArguments = expression.typeArguments?.map(
|
|
50092
50207
|
(argument2) => this.resolveType(argument2)
|
|
@@ -50217,7 +50332,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
50217
50332
|
scope
|
|
50218
50333
|
);
|
|
50219
50334
|
const classType = targetType;
|
|
50220
|
-
const schemaClassInfo =
|
|
50335
|
+
const schemaClassInfo = this.constructorWireType(classType, expression);
|
|
50221
50336
|
if (schemaClassInfo.type !== 7 /* Class */) {
|
|
50222
50337
|
throw new Error(
|
|
50223
50338
|
`NeoScript declared constructor ${className} projected a non-Class wire type.`
|
|
@@ -51080,6 +51195,8 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
51080
51195
|
{
|
|
51081
51196
|
collectionPointer: receiver.pointer,
|
|
51082
51197
|
valuePointer: value.pointer,
|
|
51198
|
+
...isPrimitive(expectedValueType, "float") ? { float: true } : {},
|
|
51199
|
+
...isPrimitive(expectedValueType, "decimal") ? { decimal: true } : {},
|
|
51083
51200
|
...hasReferenceEquality(collection.valueType, this.project) ? { reference: true } : {}
|
|
51084
51201
|
},
|
|
51085
51202
|
{ kind: "primitive", name: "int" }
|
|
@@ -51109,6 +51226,8 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
51109
51226
|
{
|
|
51110
51227
|
collectionPointer: receiver.pointer,
|
|
51111
51228
|
valuePointer: value.pointer,
|
|
51229
|
+
...isPrimitive(expectedValueType, "float") ? { float: true } : {},
|
|
51230
|
+
...isPrimitive(expectedValueType, "decimal") ? { decimal: true } : {},
|
|
51112
51231
|
...hasReferenceEquality(collection.valueType, this.project) ? { reference: true } : {}
|
|
51113
51232
|
},
|
|
51114
51233
|
{ kind: "primitive", name: "bool" }
|
|
@@ -51341,6 +51460,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
51341
51460
|
info = {
|
|
51342
51461
|
...base,
|
|
51343
51462
|
op: name,
|
|
51463
|
+
...isPrimitive(collection.valueType, "decimal") ? { decimalEntries: true } : {},
|
|
51344
51464
|
...hasReferenceEquality(collection.valueType, this.project) ? { reference: true } : {}
|
|
51345
51465
|
};
|
|
51346
51466
|
resultType = {
|
package/package.json
CHANGED
|
@@ -129,7 +129,7 @@ wrappers.
|
|
|
129
129
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
130
130
|
|
|
131
131
|
```html
|
|
132
|
-
<!-- reviewed-through-cli: 0.84.
|
|
132
|
+
<!-- reviewed-through-cli: 0.84.4 -->
|
|
133
133
|
```
|
|
134
134
|
|
|
135
135
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -335,6 +335,9 @@ Generated animation clip targets and reference lookup factories retain construct
|
|
|
335
335
|
generic arguments, including supported forwarded bindings. Clip getters use the
|
|
336
336
|
declared target type when the owner is a derived class. Export reports an error
|
|
337
337
|
when a clip target does not match the owner or one of its constructed base types.
|
|
338
|
+
Inherited collection interface getters preserve supported detached temporaries.
|
|
339
|
+
Constructed entries such as `Frame<T>` use the interface's generic argument
|
|
340
|
+
family for both their collection type and value converters.
|
|
338
341
|
New instances that reuse existing member-localized text retain its shared ID
|
|
339
342
|
and translations in the export.
|
|
340
343
|
|
|
@@ -425,6 +425,10 @@ value-level target metadata.
|
|
|
425
425
|
|
|
426
426
|
## Computed initializers and declared constructors
|
|
427
427
|
|
|
428
|
+
Inherited member initializers read parameters from the constructor that declared
|
|
429
|
+
them, including when export materialization clones their bodies. A storage-only
|
|
430
|
+
override keeps that original constructor scope.
|
|
431
|
+
|
|
428
432
|
Use an expression initializer when a member default must be evaluated during
|
|
429
433
|
construction rather than stored as a closed literal. It is replayed for omitted
|
|
430
434
|
members in push, web, and SDK contexts. A stored override remains pinned until
|
|
@@ -224,7 +224,8 @@ unconstrained generic `T` compares by value.
|
|
|
224
224
|
Calling `Equals(other)` on a non-null generic value dynamically uses the
|
|
225
225
|
runtime Class's one-argument `Equals` Function or NSFunction when it returns
|
|
226
226
|
`bool`, including the effective override. Values without that member fall back
|
|
227
|
-
to value equality.
|
|
227
|
+
to value equality. For local sets, that fallback compares their current entries
|
|
228
|
+
in insertion order, regardless of prior reads or mutations.
|
|
228
229
|
|
|
229
230
|
Object initializers are available in method bodies and `.spec.neo` tests:
|
|
230
231
|
|
|
@@ -387,6 +388,11 @@ may be null. The receiver stays unchanged.
|
|
|
387
388
|
return "banana".Replace("a", "o"); // "bonono"
|
|
388
389
|
```
|
|
389
390
|
|
|
391
|
+
Integer inputs assigned to `float` round to float32. This also applies to
|
|
392
|
+
function arguments and returns, collection entries, and `List.Repeat` with a
|
|
393
|
+
float entry type. `Contains` and `IndexOf` on float collections also convert
|
|
394
|
+
integer search arguments. Nullable assignments preserve `null`.
|
|
395
|
+
|
|
390
396
|
## Collection builtins
|
|
391
397
|
|
|
392
398
|
Lists expose their size as either `items.Count` or `items.Count()`. Use
|
|
@@ -399,8 +405,9 @@ Use `Any()` or `Any((item) => predicate)` to check for a match, and
|
|
|
399
405
|
`All((item) => predicate)` to check every entry. Both short-circuit; an empty
|
|
400
406
|
collection has `Any() == false` and `All(...) == true`.
|
|
401
407
|
|
|
402
|
-
`Last`, `LastOrDefault`, `Single`, and `SingleOrDefault` accept zero arguments
|
|
403
|
-
or one predicate. `Last`
|
|
408
|
+
`First`, `FirstOrDefault`, `Last`, `LastOrDefault`, `Single`, and `SingleOrDefault` accept zero arguments
|
|
409
|
+
or one predicate. `First` and `Last` throw when no entry matches. Enum sets
|
|
410
|
+
return enum values, including when a predicate selects the entry. `Single` throws unless
|
|
404
411
|
exactly one matches; `SingleOrDefault` still throws for multiple matches.
|
|
405
412
|
The `OrDefault` forms return nullable entries and use `null` for no match.
|
|
406
413
|
|
|
@@ -711,3 +718,7 @@ and may appear in any order. Use the existing nested positional override for a
|
|
|
711
718
|
virtual owner; changing its listeners alone must not add a value override.
|
|
712
719
|
Omitting a field inherits its listeners. An empty array suppresses inherited
|
|
713
720
|
listeners and disappears when there is no inherited wiring to suppress.
|
|
721
|
+
|
|
722
|
+
Decimal collection membership compares numeric values: `1.0` and `1.00` are
|
|
723
|
+
equal for `ToSet`, `Contains`, `IndexOf`, `Add`, and `Remove`. Decimal scale
|
|
724
|
+
is retained for display; string entries such as `"1.0"` and `"1.00"` stay distinct.
|
|
@@ -190,6 +190,13 @@ EligibleIngredients = root.Assets.Crafting.FurnaceRecipes
|
|
|
190
190
|
.ToSet()
|
|
191
191
|
```
|
|
192
192
|
|
|
193
|
+
`Box<Reference<Item>>` keeps its reference storage type through push and pull,
|
|
194
|
+
including explicit `new Box<Reference<Item>>()` calls. Its `Item` targets stay
|
|
195
|
+
shared; reading a class reference still produces the class value. A derived
|
|
196
|
+
construction in a base-typed slot retains reference bindings forwarded through
|
|
197
|
+
the inheritance chain, such as `Base<Reference<Item>>` holding
|
|
198
|
+
`new Derived<Reference<Item>>()`.
|
|
199
|
+
|
|
193
200
|
Writing `Reference(recipe.Ingredient)` inside the callback is also valid.
|
|
194
201
|
`Reference(value)` preserves an evaluated class value and its identity; it does
|
|
195
202
|
not clone it or turn it into a separate wrapper object. An optional generic
|
|
@@ -276,6 +283,10 @@ that instance. Leaving the emitted construction unchanged creates no redundant
|
|
|
276
283
|
value rows. A nullable member with no default remains bare; an explicit null
|
|
277
284
|
default emits `= null`.
|
|
278
285
|
|
|
286
|
+
Changing a construction to another overload or shared argument rebuilds the
|
|
287
|
+
instance even when the argument values compare equal. Owned inline arguments
|
|
288
|
+
still compare by contents; unchanged shared arguments keep their identities.
|
|
289
|
+
|
|
279
290
|
Spelling an unchanged child default, such as `FPS = 8`, stays a no-op after
|
|
280
291
|
push even when sibling fields own stored rows. Adding a different child default
|
|
281
292
|
preserves those siblings' row identities; it does not transfer their ownership.
|
|
@@ -399,3 +410,8 @@ is an error; remove the declaration to request deletion.
|
|
|
399
410
|
New schema getters referenced by NeoFlow interpolation need no `@id`. Export and
|
|
400
411
|
`neo dev` assign the same identity to the declaration and its references, including
|
|
401
412
|
inherited getters. Repeated exports and the next push reuse the export identity ledger.
|
|
413
|
+
|
|
414
|
+
Dictionary string keys are data. An entry named `"Id"` reads its value through
|
|
415
|
+
`dictionary["Id"]`; class `.Id` continues to return the class instance identity.
|
|
416
|
+
|
|
417
|
+
You can remove a constructor and replace every call to it in the same edit. Push prepares the new calls together with the schema change and removes argument rows owned by the old constructions.
|