@neocompose/cli 0.55.0 → 0.56.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.56.1] - 2026-09-23
|
|
4
|
+
|
|
5
|
+
- Changing a member that a variant's `initialize` or `apply` closure uses, such as its storage, recompiles the closure. The closure used to keep the code compiled against the old member, so after a member changed from `.Session` to `.Writable`, a variant that writes it failed in the game with "Member '…' is not Session-owned." To repair closures an earlier push left stale, add `--force-recompile` to your next push.
|
|
6
|
+
|
|
7
|
+
## [0.56.0] - 2026-09-23
|
|
8
|
+
|
|
9
|
+
- `@storage(allowed: .Writable)` declares a member that is always writable at runtime and persists wherever its owner persists: Save under a Save parent, Session otherwise. NeoScript can write it through any receiver, including one read from Assets, and animation clips can target it. `neo pull` writes it back in the same form. Earlier CLIs fail on a project that uses it, so upgrade before pulling.
|
|
10
|
+
- `@storage(allowed: .Writable)` on a class requires every placement of the class to resolve to Save or Session.
|
|
11
|
+
- An override below a `.Writable` member may narrow it to `.Save` or `.Session`. Declaring `.Immutable` or `.Inherit` on it fails at the member's position and names the `.Writable` ancestor. `.Writable` on a static member also fails at its position. A `readonly` member under or declaring `.Writable` fails with the existing "Read-only field … requires resolved @storage(allowed: .Immutable)" error.
|
|
12
|
+
|
|
3
13
|
## [0.55.0] - 2026-09-23
|
|
4
14
|
|
|
5
15
|
- `@settings` before a `List` element or `Dictionary` value type configures the collection's entries, such as `List<@settings(format: .Plain) string>` or `Dictionary<string, @settings(min: 0) int>`. `neo pull` writes entry settings in this form. Switching entries between Localized and Plain converts every entry's text exactly as the same change on a string member does. Annotations on a Dictionary key, another generic's type argument, or an override's element type are reported at their position. Run `neo pull` before your first push so entry settings set in the web app appear in source.
|
package/dist/neo.mjs
CHANGED
|
@@ -18769,13 +18769,15 @@ var init_project_schema_contract_generated = __esm({
|
|
|
18769
18769
|
"Inherit",
|
|
18770
18770
|
"Immutable",
|
|
18771
18771
|
"Save",
|
|
18772
|
-
"Session"
|
|
18772
|
+
"Session",
|
|
18773
|
+
"Writable"
|
|
18773
18774
|
],
|
|
18774
18775
|
"NeoAllowedStorage": [
|
|
18775
18776
|
"Any",
|
|
18776
18777
|
"Immutable",
|
|
18777
18778
|
"Save",
|
|
18778
|
-
"Session"
|
|
18779
|
+
"Session",
|
|
18780
|
+
"Writable"
|
|
18779
18781
|
],
|
|
18780
18782
|
"NeoListKind": [
|
|
18781
18783
|
"Ordered",
|
|
@@ -32457,10 +32459,22 @@ function resolvedAllowedStorage(classId, environment) {
|
|
|
32457
32459
|
}
|
|
32458
32460
|
return null;
|
|
32459
32461
|
}
|
|
32460
|
-
function
|
|
32461
|
-
const allowed = resolvedAllowedStorage(classId, environment);
|
|
32462
|
+
function constraintDefaultWritability(allowed) {
|
|
32462
32463
|
return allowed === "immutable" || allowed === "save" || allowed === "session" ? allowed : "session";
|
|
32463
32464
|
}
|
|
32465
|
+
function declaredStorageWritability(storage, staticOwnerClassId, environment) {
|
|
32466
|
+
if (storage === "immutable" || storage === "save" || storage === "session") {
|
|
32467
|
+
return storage;
|
|
32468
|
+
}
|
|
32469
|
+
if (storage === "writable") return "runtime";
|
|
32470
|
+
if (!staticOwnerClassId) return void 0;
|
|
32471
|
+
return staticDefaultWritability(staticOwnerClassId, environment);
|
|
32472
|
+
}
|
|
32473
|
+
function staticDefaultWritability(classId, environment) {
|
|
32474
|
+
return constraintDefaultWritability(
|
|
32475
|
+
resolvedAllowedStorage(classId, environment)
|
|
32476
|
+
);
|
|
32477
|
+
}
|
|
32464
32478
|
function createRootType(ids, environment) {
|
|
32465
32479
|
const definitions = [
|
|
32466
32480
|
["Assets", ids.assets, false],
|
|
@@ -32522,7 +32536,7 @@ function effectiveMemberWritability(members, classes, roots) {
|
|
|
32522
32536
|
seen.add(memberId);
|
|
32523
32537
|
const member = memberById2.get(memberId);
|
|
32524
32538
|
if (!member) return null;
|
|
32525
|
-
if (member.storage === "immutable" || member.storage === "save" || member.storage === "session") {
|
|
32539
|
+
if (member.storage === "immutable" || member.storage === "save" || member.storage === "session" || member.storage === "writable") {
|
|
32526
32540
|
return member.storage;
|
|
32527
32541
|
}
|
|
32528
32542
|
return typeof member.overrideOf === "string" ? declaredStorage(member.overrideOf, seen) : null;
|
|
@@ -32545,8 +32559,8 @@ function effectiveMemberWritability(members, classes, roots) {
|
|
|
32545
32559
|
seen.add(currentId);
|
|
32546
32560
|
const current = classById.get(currentId);
|
|
32547
32561
|
if (!current) break;
|
|
32548
|
-
if (
|
|
32549
|
-
return current.allowedStorage;
|
|
32562
|
+
if (typeof current.allowedStorage === "string") {
|
|
32563
|
+
return constraintDefaultWritability(current.allowedStorage);
|
|
32550
32564
|
}
|
|
32551
32565
|
currentId = typeof current.extendsClassId === "string" ? current.extendsClassId : null;
|
|
32552
32566
|
}
|
|
@@ -32581,6 +32595,7 @@ function effectiveMemberWritability(members, classes, roots) {
|
|
|
32581
32595
|
}
|
|
32582
32596
|
const effective = /* @__PURE__ */ new Map();
|
|
32583
32597
|
const anchored = /* @__PURE__ */ new Set();
|
|
32598
|
+
const writable = /* @__PURE__ */ new Set();
|
|
32584
32599
|
const rootStorage = /* @__PURE__ */ new Map();
|
|
32585
32600
|
if (typeof roots.assets === "string") {
|
|
32586
32601
|
rootStorage.set(roots.assets, "immutable");
|
|
@@ -32590,16 +32605,19 @@ function effectiveMemberWritability(members, classes, roots) {
|
|
|
32590
32605
|
rootStorage.set(roots.session, "session");
|
|
32591
32606
|
}
|
|
32592
32607
|
for (const [memberId, member] of memberById2) {
|
|
32593
|
-
const
|
|
32594
|
-
|
|
32595
|
-
|
|
32596
|
-
|
|
32608
|
+
const declared = rootStorage.get(memberId) ?? declaredStorage(memberId);
|
|
32609
|
+
if (declared === "writable") {
|
|
32610
|
+
writable.add(memberId);
|
|
32611
|
+
continue;
|
|
32612
|
+
}
|
|
32613
|
+
let storage = declared;
|
|
32614
|
+
if (storage === null) {
|
|
32597
32615
|
const owner = optionalRecord(member.owner);
|
|
32598
32616
|
if (member.modifier === "static" && owner?.kind === "classMember" && typeof owner.classId === "string") {
|
|
32599
32617
|
storage = staticDefault(owner.classId);
|
|
32600
32618
|
}
|
|
32601
32619
|
}
|
|
32602
|
-
if (storage ===
|
|
32620
|
+
if (storage === null) continue;
|
|
32603
32621
|
effective.set(memberId, /* @__PURE__ */ new Set([storage]));
|
|
32604
32622
|
anchored.add(memberId);
|
|
32605
32623
|
}
|
|
@@ -32609,8 +32627,11 @@ function effectiveMemberWritability(members, classes, roots) {
|
|
|
32609
32627
|
for (const memberId of memberById2.keys()) {
|
|
32610
32628
|
if (anchored.has(memberId)) continue;
|
|
32611
32629
|
const next = new Set(effective.get(memberId) ?? []);
|
|
32630
|
+
const isWritable = writable.has(memberId);
|
|
32612
32631
|
for (const parentId of parents.get(memberId) ?? []) {
|
|
32613
|
-
for (const storage of effective.get(parentId) ?? [])
|
|
32632
|
+
for (const storage of effective.get(parentId) ?? []) {
|
|
32633
|
+
next.add(isWritable && storage === "immutable" ? "session" : storage);
|
|
32634
|
+
}
|
|
32614
32635
|
}
|
|
32615
32636
|
const current = effective.get(memberId);
|
|
32616
32637
|
if (current?.size === next.size || next.size === 0) continue;
|
|
@@ -32741,7 +32762,16 @@ function memberSymbol(member, schemaKey, environment, field) {
|
|
|
32741
32762
|
}
|
|
32742
32763
|
const writable = isReadOnly ? false : kind === "computed" ? computedHasSetter(member, field) : true;
|
|
32743
32764
|
const storage = typeof member.storage === "string" ? member.storage : void 0;
|
|
32744
|
-
|
|
32765
|
+
let writability;
|
|
32766
|
+
if (!writable) writability = "readOnly";
|
|
32767
|
+
else if (kind === "computed") writability = "setter";
|
|
32768
|
+
else {
|
|
32769
|
+
writability = declaredStorageWritability(
|
|
32770
|
+
storage,
|
|
32771
|
+
isStatic ? ownerClassId : void 0,
|
|
32772
|
+
environment
|
|
32773
|
+
);
|
|
32774
|
+
}
|
|
32745
32775
|
const lookupCollectionMemberId = kind === "lookup" ? string2(member.collectionMemberId, `${field}.collectionMemberId`) : null;
|
|
32746
32776
|
const lookupCollectionWritability = lookupCollectionMemberId === null ? void 0 : environment.effectiveWritabilityByMemberId.get(
|
|
32747
32777
|
lookupCollectionMemberId
|
|
@@ -40103,7 +40133,13 @@ var init_codecs = __esm({
|
|
|
40103
40133
|
};
|
|
40104
40134
|
MEMBER_MODIFIERS = ["virtual", "sealed", "abstract", "static"];
|
|
40105
40135
|
MEMBER_ACCESS = ["public", "protected", "private"];
|
|
40106
|
-
MEMBER_STORAGE = [
|
|
40136
|
+
MEMBER_STORAGE = [
|
|
40137
|
+
"inherit",
|
|
40138
|
+
"immutable",
|
|
40139
|
+
"save",
|
|
40140
|
+
"session",
|
|
40141
|
+
"writable"
|
|
40142
|
+
];
|
|
40107
40143
|
MEMBER_DISTRIBUTION = ["sparse", "packed"];
|
|
40108
40144
|
STRING_FORMAT = ["localized", "plain"];
|
|
40109
40145
|
MEMBER_SEARCH_BY = ["none", "memberKey"];
|
|
@@ -40823,7 +40859,7 @@ function schemaClassToDocument(schemaClass2) {
|
|
|
40823
40859
|
uiVisibility: schemaClass2.hiddenInMemberSelector ? 1 : void 0,
|
|
40824
40860
|
modifier: schemaClass2.declarationModifier === "abstract" ? 1 : schemaClass2.declarationModifier === "sealed" ? 2 : void 0,
|
|
40825
40861
|
system: systemToDocument(schemaClass2.system),
|
|
40826
|
-
allowedStorage: schemaClass2.allowedStorage === null ? void 0 :
|
|
40862
|
+
allowedStorage: schemaClass2.allowedStorage === null ? void 0 : CLASS_ALLOWED_STORAGE.indexOf(schemaClass2.allowedStorage),
|
|
40827
40863
|
allowedStorageKeys: schemaClass2.allowedStorageKeys,
|
|
40828
40864
|
// An unconstrained param is stored with no `constraint` key. The manifest
|
|
40829
40865
|
// spells that absence `null` for a uniform in-memory shape, so emitting
|
|
@@ -40846,7 +40882,7 @@ function schemaClassToDocument(schemaClass2) {
|
|
|
40846
40882
|
function allowedStorageFromDocument(value, record6) {
|
|
40847
40883
|
const storage = ordinalValue(
|
|
40848
40884
|
value ?? 0,
|
|
40849
|
-
|
|
40885
|
+
CLASS_ALLOWED_STORAGE,
|
|
40850
40886
|
record6,
|
|
40851
40887
|
"allowedStorage"
|
|
40852
40888
|
);
|
|
@@ -40893,12 +40929,19 @@ function optionalDocsTextProperty(value, record6) {
|
|
|
40893
40929
|
const docsText = optionalDocsText(value, record6, "docsText");
|
|
40894
40930
|
return docsText === void 0 ? {} : { docsText };
|
|
40895
40931
|
}
|
|
40896
|
-
var CLASS_SCHEMA_RECORD_ADAPTER;
|
|
40932
|
+
var CLASS_ALLOWED_STORAGE, CLASS_SCHEMA_RECORD_ADAPTER;
|
|
40897
40933
|
var init_class = __esm({
|
|
40898
40934
|
"src/project-manifest/record-adapters/class.ts"() {
|
|
40899
40935
|
"use strict";
|
|
40900
40936
|
init_contracts();
|
|
40901
40937
|
init_codecs();
|
|
40938
|
+
CLASS_ALLOWED_STORAGE = [
|
|
40939
|
+
"any",
|
|
40940
|
+
"immutable",
|
|
40941
|
+
"save",
|
|
40942
|
+
"session",
|
|
40943
|
+
"writable"
|
|
40944
|
+
];
|
|
40902
40945
|
CLASS_SCHEMA_RECORD_ADAPTER = {
|
|
40903
40946
|
recordKind: "class",
|
|
40904
40947
|
manifestCollection: "classes",
|
|
@@ -42999,7 +43042,7 @@ var init_schema_member = __esm({
|
|
|
42999
43042
|
defaultValue: nullable(schemaDefaultValueSchema),
|
|
43000
43043
|
overrideOf: nullableId2,
|
|
43001
43044
|
system: nullable(schemaSystemMetadataSchema),
|
|
43002
|
-
storage: nullable(picklist(["immutable", "save", "session"])),
|
|
43045
|
+
storage: nullable(picklist(["immutable", "save", "session", "writable"])),
|
|
43003
43046
|
distribution: nullable(picklist(["sparse", "packed"])),
|
|
43004
43047
|
storageKey: nullableId2
|
|
43005
43048
|
};
|
|
@@ -44665,7 +44708,7 @@ function booleanAt(value, path) {
|
|
|
44665
44708
|
}
|
|
44666
44709
|
function nullableStorage(value, path) {
|
|
44667
44710
|
if (value === null) return;
|
|
44668
|
-
stringIn(value, /* @__PURE__ */ new Set(["immutable", "save", "session"]), path);
|
|
44711
|
+
stringIn(value, /* @__PURE__ */ new Set(["immutable", "save", "session", "writable"]), path);
|
|
44669
44712
|
}
|
|
44670
44713
|
function stringIn(value, allowed, path) {
|
|
44671
44714
|
const result = stringAt(value, path);
|
|
@@ -45434,15 +45477,59 @@ var init_class_generics = __esm({
|
|
|
45434
45477
|
|
|
45435
45478
|
// ../src/models/members/member-storage.ts
|
|
45436
45479
|
function isMemberStorageKind(value) {
|
|
45437
|
-
return value === 0 /* Inherit */ || value === 1 /* Immutable */ || value === 2 /* Save */ || value === 3 /* Session */;
|
|
45480
|
+
return value === 0 /* Inherit */ || value === 1 /* Immutable */ || value === 2 /* Save */ || value === 3 /* Session */ || value === 4 /* Writable */;
|
|
45438
45481
|
}
|
|
45439
45482
|
function isEffectiveMemberStorage(value) {
|
|
45483
|
+
return value === 1 /* Immutable */ || value === 2 /* Save */ || value === 3 /* Session */;
|
|
45484
|
+
}
|
|
45485
|
+
function isClassAllowedStorage(value) {
|
|
45440
45486
|
if (!isMemberStorageKind(value)) return false;
|
|
45441
45487
|
return value !== 0 /* Inherit */;
|
|
45442
45488
|
}
|
|
45489
|
+
function childEffectiveStorage(declared, parent) {
|
|
45490
|
+
switch (declared) {
|
|
45491
|
+
case 0 /* Inherit */:
|
|
45492
|
+
return parent;
|
|
45493
|
+
case 4 /* Writable */:
|
|
45494
|
+
return parent === 2 /* Save */ ? 2 /* Save */ : 3 /* Session */;
|
|
45495
|
+
default:
|
|
45496
|
+
return declared;
|
|
45497
|
+
}
|
|
45498
|
+
}
|
|
45499
|
+
function constraintDefaultStorage(constraint) {
|
|
45500
|
+
if (constraint === null) return 3 /* Session */;
|
|
45501
|
+
if (constraint === 4 /* Writable */) {
|
|
45502
|
+
return 3 /* Session */;
|
|
45503
|
+
}
|
|
45504
|
+
return constraint;
|
|
45505
|
+
}
|
|
45506
|
+
function createWritableAncestorLookup(memberById2) {
|
|
45507
|
+
const memo = /* @__PURE__ */ new Map();
|
|
45508
|
+
const lookup = (member) => {
|
|
45509
|
+
const cached = memo.get(member.id);
|
|
45510
|
+
if (cached !== void 0) return cached;
|
|
45511
|
+
memo.set(member.id, null);
|
|
45512
|
+
const baseId = member.extendsMemberId;
|
|
45513
|
+
const base = baseId === void 0 ? void 0 : memberById2(baseId);
|
|
45514
|
+
if (base === void 0) return null;
|
|
45515
|
+
const result = base.storage === 4 /* Writable */ ? base : lookup(base);
|
|
45516
|
+
memo.set(member.id, result);
|
|
45517
|
+
return result;
|
|
45518
|
+
};
|
|
45519
|
+
return lookup;
|
|
45520
|
+
}
|
|
45521
|
+
var MemberStorageKind;
|
|
45443
45522
|
var init_member_storage = __esm({
|
|
45444
45523
|
"../src/models/members/member-storage.ts"() {
|
|
45445
45524
|
"use strict";
|
|
45525
|
+
MemberStorageKind = /* @__PURE__ */ ((MemberStorageKind3) => {
|
|
45526
|
+
MemberStorageKind3[MemberStorageKind3["Inherit"] = 0] = "Inherit";
|
|
45527
|
+
MemberStorageKind3[MemberStorageKind3["Immutable"] = 1] = "Immutable";
|
|
45528
|
+
MemberStorageKind3[MemberStorageKind3["Save"] = 2] = "Save";
|
|
45529
|
+
MemberStorageKind3[MemberStorageKind3["Session"] = 3] = "Session";
|
|
45530
|
+
MemberStorageKind3[MemberStorageKind3["Writable"] = 4] = "Writable";
|
|
45531
|
+
return MemberStorageKind3;
|
|
45532
|
+
})(MemberStorageKind || {});
|
|
45446
45533
|
}
|
|
45447
45534
|
});
|
|
45448
45535
|
|
|
@@ -47419,7 +47506,7 @@ function isNeoSchemaClassBase(value) {
|
|
|
47419
47506
|
const v = value;
|
|
47420
47507
|
return typeof v?.name === "string" && isValidDocsText(v.docsText) && isClassSchema(v?.schema) && isOptionalSchemaKeyOrder(v?.schemaKeyOrder) && (v.implementsInterfaceIds === void 0 || Array.isArray(v.implementsInterfaceIds) && v.implementsInterfaceIds.every(
|
|
47421
47508
|
(interfaceId) => typeof interfaceId === "string" && interfaceId.length > 0
|
|
47422
|
-
)) && (v.uiVisibility === void 0 || v.uiVisibility === 0 /* Visible */ || v.uiVisibility === 1 /* Hidden */) && (v.modifier === void 0 || v.modifier === 0 /* Open */ || v.modifier === 1 /* Abstract */ || v.modifier === 2 /* Sealed */) && (v.allowedStorage === void 0 ||
|
|
47509
|
+
)) && (v.uiVisibility === void 0 || v.uiVisibility === 0 /* Visible */ || v.uiVisibility === 1 /* Hidden */) && (v.modifier === void 0 || v.modifier === 0 /* Open */ || v.modifier === 1 /* Abstract */ || v.modifier === 2 /* Sealed */) && (v.allowedStorage === void 0 || isClassAllowedStorage(v.allowedStorage)) && (v.allowedStorageKeys === void 0 || Array.isArray(v.allowedStorageKeys) && v.allowedStorageKeys.every((key) => typeof key === "string")) && (v.genericParams === void 0 || Array.isArray(v.genericParams) && v.genericParams.every(isGenericParamDeclaration)) && (v.extendsGenericBindings === void 0 || isGenericBindingsRecord(v.extendsGenericBindings)) && (v.constructorIds === void 0 || Array.isArray(v.constructorIds) && v.constructorIds.every(
|
|
47423
47510
|
(constructorId) => typeof constructorId === "string" && constructorId.length > 0
|
|
47424
47511
|
) && new Set(v.constructorIds).size === v.constructorIds.length) && (v.requiredConstructorId === void 0 || typeof v.requiredConstructorId === "string" && v.requiredConstructorId.length > 0 && (v.constructorIds ?? []).length === 0) && (v.targetMemberId === void 0 || typeof v.targetMemberId === "string" && v.targetMemberId.length > 0) && (v.system === void 0 || isSystemMetadata(v.system));
|
|
47425
47512
|
}
|
|
@@ -53020,7 +53107,7 @@ function assertOwnedSchemaIsImmutable(args) {
|
|
|
53020
53107
|
const bindingKey = `${args.memberId}\0${genericEnvironmentKey(args.genericEnv)}`;
|
|
53021
53108
|
if (args.visitedBindings.has(bindingKey)) return;
|
|
53022
53109
|
args.visitedBindings.add(bindingKey);
|
|
53023
|
-
if (resolved.storage === 2 /* Save */ || resolved.storage === 3 /* Session */) {
|
|
53110
|
+
if (resolved.storage === 2 /* Save */ || resolved.storage === 3 /* Session */ || resolved.storage === 4 /* Writable */) {
|
|
53024
53111
|
throw new Error(
|
|
53025
53112
|
`Read-only member "${args.label}" has a non-Immutable owned default child "${resolved.name}"; ${args.ownerContext}.`
|
|
53026
53113
|
);
|
|
@@ -56911,6 +56998,9 @@ var init_effective_storage = __esm({
|
|
|
56911
56998
|
schemaIndex;
|
|
56912
56999
|
parentIdsByMemberId = /* @__PURE__ */ new Map();
|
|
56913
57000
|
effectiveByMemberId = /* @__PURE__ */ new Map();
|
|
57001
|
+
writableAncestor = createWritableAncestorLookup(
|
|
57002
|
+
(id2) => this.schemaIndex.member(id2)
|
|
57003
|
+
);
|
|
56914
57004
|
resolving = /* @__PURE__ */ new Set();
|
|
56915
57005
|
/** Declared storage of `memberId`, resolved through the extends chain. */
|
|
56916
57006
|
declaredStorage(memberId) {
|
|
@@ -56919,6 +57009,15 @@ var init_effective_storage = __esm({
|
|
|
56919
57009
|
this.schemaIndex.membersById
|
|
56920
57010
|
);
|
|
56921
57011
|
}
|
|
57012
|
+
/**
|
|
57013
|
+
* Nearest member in `memberId`'s `extendsMemberId` chain, excluding itself,
|
|
57014
|
+
* whose own record declares `Writable` (P93 §1.4), or null.
|
|
57015
|
+
*/
|
|
57016
|
+
writableAncestorId(memberId) {
|
|
57017
|
+
const member = this.schemaIndex.member(memberId);
|
|
57018
|
+
if (member === void 0) return null;
|
|
57019
|
+
return this.writableAncestor(member)?.id ?? null;
|
|
57020
|
+
}
|
|
56922
57021
|
/** Placement-parent member ids of `memberId` (empty for roots). */
|
|
56923
57022
|
parentMemberIds(memberId) {
|
|
56924
57023
|
if (this.ctx.rootStorage.has(memberId)) return [];
|
|
@@ -56942,21 +57041,21 @@ var init_effective_storage = __esm({
|
|
|
56942
57041
|
result.add(rootStorage);
|
|
56943
57042
|
} else {
|
|
56944
57043
|
const declared = this.declaredStorage(memberId);
|
|
56945
|
-
|
|
56946
|
-
if (isStaticMember(member) === true) {
|
|
56947
|
-
if (declared !== 0 /* Inherit */) {
|
|
56948
|
-
result.add(declared);
|
|
56949
|
-
} else {
|
|
56950
|
-
const declaringClassId = this.schemaIndex.firstSchemaPlacement(memberId)?.ownerClass.id;
|
|
56951
|
-
const inherited = declaringClassId === void 0 ? null : resolveAllowedStorage(declaringClassId, this.ctx.classes);
|
|
56952
|
-
result.add(inherited ?? 3 /* Session */);
|
|
56953
|
-
}
|
|
56954
|
-
} else if (declared !== 0 /* Inherit */) {
|
|
57044
|
+
if (isEffectiveMemberStorage(declared)) {
|
|
56955
57045
|
result.add(declared);
|
|
57046
|
+
} else if (isStaticMember(this.schemaIndex.member(memberId))) {
|
|
57047
|
+
const declaringClassId = this.schemaIndex.firstSchemaPlacement(memberId)?.ownerClass.id;
|
|
57048
|
+
const constraint = declaringClassId === void 0 ? null : resolveAllowedStorage(declaringClassId, this.ctx.classes);
|
|
57049
|
+
result.add(
|
|
57050
|
+
childEffectiveStorage(
|
|
57051
|
+
declared,
|
|
57052
|
+
constraintDefaultStorage(constraint)
|
|
57053
|
+
)
|
|
57054
|
+
);
|
|
56956
57055
|
} else {
|
|
56957
57056
|
for (const parentId of this.parentMemberIds(memberId)) {
|
|
56958
57057
|
for (const storage of this.effectiveStorages(parentId)) {
|
|
56959
|
-
result.add(storage);
|
|
57058
|
+
result.add(childEffectiveStorage(declared, storage));
|
|
56960
57059
|
}
|
|
56961
57060
|
}
|
|
56962
57061
|
}
|
|
@@ -56971,26 +57070,44 @@ var init_effective_storage = __esm({
|
|
|
56971
57070
|
* Effective storage for one concrete placement chain, ordered root-first
|
|
56972
57071
|
* (the project root at index 0, the target member last). Used when the
|
|
56973
57072
|
* caller knows the exact path (NeoScript member walks, value trees).
|
|
57073
|
+
* Anchors at the root, the nearest concrete declaration, or a single-storage
|
|
57074
|
+
* static head, then folds the members below through `childEffectiveStorage`.
|
|
56974
57075
|
*/
|
|
56975
57076
|
effectiveStorageForPath(memberIdsRootToLeaf) {
|
|
56976
|
-
|
|
56977
|
-
|
|
56978
|
-
|
|
56979
|
-
|
|
57077
|
+
let anchorIndex = memberIdsRootToLeaf.length - 1;
|
|
57078
|
+
let storage;
|
|
57079
|
+
for (; anchorIndex >= 0; anchorIndex--) {
|
|
57080
|
+
const memberId = memberIdsRootToLeaf[anchorIndex];
|
|
57081
|
+
if (anchorIndex === 0) storage = this.ctx.rootStorage.get(memberId);
|
|
57082
|
+
if (storage !== void 0) break;
|
|
56980
57083
|
const declared = this.declaredStorage(memberId);
|
|
56981
|
-
if (declared
|
|
57084
|
+
if (isEffectiveMemberStorage(declared)) {
|
|
57085
|
+
storage = declared;
|
|
57086
|
+
break;
|
|
57087
|
+
}
|
|
57088
|
+
}
|
|
57089
|
+
if (storage === void 0) {
|
|
57090
|
+
anchorIndex = 0;
|
|
57091
|
+
storage = this.staticRootStorage(memberIdsRootToLeaf[0]);
|
|
56982
57092
|
}
|
|
56983
|
-
|
|
56984
|
-
|
|
56985
|
-
|
|
57093
|
+
for (let i = anchorIndex + 1; i < memberIdsRootToLeaf.length; i++) {
|
|
57094
|
+
storage = childEffectiveStorage(
|
|
57095
|
+
this.declaredStorage(memberIdsRootToLeaf[i]),
|
|
57096
|
+
storage
|
|
57097
|
+
);
|
|
57098
|
+
}
|
|
57099
|
+
return storage;
|
|
57100
|
+
}
|
|
57101
|
+
/** A static chain head's storage when it resolves to exactly one. */
|
|
57102
|
+
staticRootStorage(rootId) {
|
|
56986
57103
|
if (rootId !== void 0 && isStaticMember(this.schemaIndex.member(rootId))) {
|
|
56987
57104
|
const staticStorages = this.effectiveStorages(rootId);
|
|
56988
57105
|
if (staticStorages.size === 1) {
|
|
56989
|
-
|
|
57106
|
+
for (const storage of staticStorages) return storage;
|
|
56990
57107
|
}
|
|
56991
57108
|
}
|
|
56992
57109
|
throw new Error(
|
|
56993
|
-
`Storage path did not resolve: no member in the chain declares
|
|
57110
|
+
`Storage path did not resolve: no member in the chain declares an Immutable, Save, or Session storage class and the chain head "${rootId ?? "(empty)"}" is not a stamped project root.`
|
|
56994
57111
|
);
|
|
56995
57112
|
}
|
|
56996
57113
|
/** Class's merged (inheritance-resolved) schema. */
|
|
@@ -64211,6 +64328,14 @@ function buildRootStorageMap(project) {
|
|
|
64211
64328
|
}
|
|
64212
64329
|
return map;
|
|
64213
64330
|
}
|
|
64331
|
+
function writtenRootStorage(project, memberIds) {
|
|
64332
|
+
const map = /* @__PURE__ */ new Map();
|
|
64333
|
+
for (const root of PROJECT_ROOTS) {
|
|
64334
|
+
const memberId = project[root.projectField];
|
|
64335
|
+
if (memberIds.has(memberId)) map.set(memberId, root.storage);
|
|
64336
|
+
}
|
|
64337
|
+
return map;
|
|
64338
|
+
}
|
|
64214
64339
|
function isProjectRootMember(project, memberId) {
|
|
64215
64340
|
return PROJECT_ROOTS.some((root) => project[root.projectField] === memberId);
|
|
64216
64341
|
}
|
|
@@ -64802,7 +64927,9 @@ function symbolWritability(memberId, context, staticOwnerClassId) {
|
|
|
64802
64927
|
if (storage === 0 /* Inherit */ && staticOwnerClassId === null) {
|
|
64803
64928
|
return {};
|
|
64804
64929
|
}
|
|
64805
|
-
const effectiveStorage = storage === 0 /* Inherit */ ?
|
|
64930
|
+
const effectiveStorage = storage === 0 /* Inherit */ ? constraintDefaultStorage(
|
|
64931
|
+
resolveAllowedStorage(staticOwnerClassId, context.vm.classes)
|
|
64932
|
+
) : storage;
|
|
64806
64933
|
switch (effectiveStorage) {
|
|
64807
64934
|
case 1 /* Immutable */:
|
|
64808
64935
|
return { writability: "immutable" };
|
|
@@ -64810,6 +64937,8 @@ function symbolWritability(memberId, context, staticOwnerClassId) {
|
|
|
64810
64937
|
return { writability: "save" };
|
|
64811
64938
|
case 3 /* Session */:
|
|
64812
64939
|
return { writability: "session" };
|
|
64940
|
+
case 4 /* Writable */:
|
|
64941
|
+
return { writability: "runtime" };
|
|
64813
64942
|
}
|
|
64814
64943
|
}
|
|
64815
64944
|
function uniqueEffectiveWritability(memberId, context) {
|
|
@@ -94947,6 +95076,121 @@ var init_member_access_modifier_validation = __esm({
|
|
|
94947
95076
|
}
|
|
94948
95077
|
});
|
|
94949
95078
|
|
|
95079
|
+
// ../src/database/project-version-write-changes.ts
|
|
95080
|
+
function applyProjectVersionWriteChanges(document, changes) {
|
|
95081
|
+
return projectVersionDocumentWithChanges(document, changes, false);
|
|
95082
|
+
}
|
|
95083
|
+
function projectVersionDocumentWithChanges(document, changes, reuseUnchangedBuckets) {
|
|
95084
|
+
const projectRows = (rows, kind) => {
|
|
95085
|
+
const relevant = changes.filter((change) => change.recordKind === kind);
|
|
95086
|
+
if (reuseUnchangedBuckets && relevant.length === 0) return rows;
|
|
95087
|
+
return applyArrayChanges(rows, relevant);
|
|
95088
|
+
};
|
|
95089
|
+
const hasGranularDialogueRecords = document.dialogueRecords !== void 0 || changes.some((change) => change.recordKind === "dialogue");
|
|
95090
|
+
const hasGranularDialogueNodes = document.dialogueNodes !== void 0 || changes.some((change) => change.recordKind === "dialogue-node");
|
|
95091
|
+
const dialogueRecords = hasGranularDialogueRecords ? projectRows(document.dialogueRecords ?? [], "dialogue") : void 0;
|
|
95092
|
+
const dialogueNodes = hasGranularDialogueNodes ? projectRows(document.dialogueNodes ?? [], "dialogue-node") : void 0;
|
|
95093
|
+
const projected = {
|
|
95094
|
+
localizedTexts: projectRows(
|
|
95095
|
+
document.localizedTexts ?? [],
|
|
95096
|
+
"localized-text"
|
|
95097
|
+
),
|
|
95098
|
+
localizationConfig: applySingletonChange(
|
|
95099
|
+
document.localizationConfig,
|
|
95100
|
+
changes,
|
|
95101
|
+
"localization-config"
|
|
95102
|
+
),
|
|
95103
|
+
project: applySingletonChange(document.project, changes, "project"),
|
|
95104
|
+
members: projectRows(document.members, "member"),
|
|
95105
|
+
classes: projectRows(document.classes, "class"),
|
|
95106
|
+
// P43 §6. Declared constructors participate in the post-transaction
|
|
95107
|
+
// document so the whole-graph validator and every body compile see the
|
|
95108
|
+
// same constructor surface the transaction is about to persist.
|
|
95109
|
+
constructors: projectRows(document.constructors ?? [], "constructor"),
|
|
95110
|
+
// P67 §2.1. Same reason as constructors: without these buckets the
|
|
95111
|
+
// whole-graph validator, the variant ownership roots, and every body
|
|
95112
|
+
// compile would grade the transaction against the pre-transaction
|
|
95113
|
+
// variant set — so a newly pushed variant's closures would compile
|
|
95114
|
+
// against a document that does not contain it.
|
|
95115
|
+
variants: projectRows(document.variants ?? [], "variant"),
|
|
95116
|
+
variantFolders: projectRows(
|
|
95117
|
+
document.variantFolders ?? [],
|
|
95118
|
+
"variant-folder"
|
|
95119
|
+
),
|
|
95120
|
+
values: projectRows(document.values ?? [], "value"),
|
|
95121
|
+
// Project-file staging finalizes pending uploads before schema
|
|
95122
|
+
// preparation. Defaults and authored instance graphs may reference a file
|
|
95123
|
+
// created by the same source transaction, so every construction pass must
|
|
95124
|
+
// see that finalized row in its post-write document.
|
|
95125
|
+
projectFiles: projectRows(document.projectFiles ?? [], "project-file"),
|
|
95126
|
+
// Import-setting templates are part of the same file graph. A new file
|
|
95127
|
+
// may select a new template in one source transaction, and default-value
|
|
95128
|
+
// materialization validates that relationship immediately against this
|
|
95129
|
+
// post-write document.
|
|
95130
|
+
textureTemplates: projectRows(
|
|
95131
|
+
document.textureTemplates ?? [],
|
|
95132
|
+
"unity-texture-template"
|
|
95133
|
+
),
|
|
95134
|
+
audioClipTemplates: projectRows(
|
|
95135
|
+
document.audioClipTemplates ?? [],
|
|
95136
|
+
"unity-audio-clip-template"
|
|
95137
|
+
),
|
|
95138
|
+
internalRecordRelations: projectRows(
|
|
95139
|
+
document.internalRecordRelations ?? [],
|
|
95140
|
+
"internal-record-relation"
|
|
95141
|
+
),
|
|
95142
|
+
enums: projectRows(document.enums, "enum"),
|
|
95143
|
+
interfaces: projectRows(document.interfaces, "interface"),
|
|
95144
|
+
dialogues: dialogueRecords === void 0 || dialogueNodes === void 0 || dialogueRecords === document.dialogueRecords && dialogueNodes === document.dialogueNodes ? document.dialogues : materializeDialogues(
|
|
95145
|
+
dialogueRecords,
|
|
95146
|
+
dialogueNodes
|
|
95147
|
+
),
|
|
95148
|
+
dialogueGroups: projectRows(
|
|
95149
|
+
document.dialogueGroups ?? [],
|
|
95150
|
+
"dialogue-group"
|
|
95151
|
+
),
|
|
95152
|
+
migrations: projectRows(document.migrations ?? [], "migration")
|
|
95153
|
+
};
|
|
95154
|
+
return {
|
|
95155
|
+
...document,
|
|
95156
|
+
...projected,
|
|
95157
|
+
...dialogueRecords === void 0 ? {} : { dialogueRecords },
|
|
95158
|
+
...dialogueNodes === void 0 ? {} : { dialogueNodes }
|
|
95159
|
+
// The document spread above carries every bucket the caller's view declares
|
|
95160
|
+
// beyond the projected ones, so the result is the same view; TypeScript
|
|
95161
|
+
// cannot prove that of an object literal built over a type parameter.
|
|
95162
|
+
};
|
|
95163
|
+
}
|
|
95164
|
+
function applySingletonChange(current, changes, recordKind) {
|
|
95165
|
+
const change = changes.find(
|
|
95166
|
+
(candidate) => candidate.recordKind === recordKind
|
|
95167
|
+
);
|
|
95168
|
+
if (change === void 0) return current;
|
|
95169
|
+
if (change.operation === "delete" || change.nextData === void 0) {
|
|
95170
|
+
throw new Error(`Schema commit cannot delete the ${recordKind} record.`);
|
|
95171
|
+
}
|
|
95172
|
+
return change.nextData;
|
|
95173
|
+
}
|
|
95174
|
+
function applyArrayChanges(current, changes) {
|
|
95175
|
+
const byId = new Map(current.map((record6) => [record6.id, record6]));
|
|
95176
|
+
for (const change of changes) {
|
|
95177
|
+
if (change.operation === "delete") {
|
|
95178
|
+
byId.delete(change.recordId);
|
|
95179
|
+
continue;
|
|
95180
|
+
}
|
|
95181
|
+
if (change.nextData !== void 0) {
|
|
95182
|
+
byId.set(change.recordId, change.nextData);
|
|
95183
|
+
}
|
|
95184
|
+
}
|
|
95185
|
+
return [...byId.values()];
|
|
95186
|
+
}
|
|
95187
|
+
var init_project_version_write_changes = __esm({
|
|
95188
|
+
"../src/database/project-version-write-changes.ts"() {
|
|
95189
|
+
"use strict";
|
|
95190
|
+
init_projectDocumentDialogueMaterialization();
|
|
95191
|
+
}
|
|
95192
|
+
});
|
|
95193
|
+
|
|
94950
95194
|
// ../src/database/member-localization-normalization.ts
|
|
94951
95195
|
function planMemberLocalizationNormalization(input, now = 0) {
|
|
94952
95196
|
const before = expandPackedDocumentValues(input);
|
|
@@ -95237,7 +95481,7 @@ var init_member_localization_normalization = __esm({
|
|
|
95237
95481
|
init_constructor_argument_ownership();
|
|
95238
95482
|
init_variant_value_graph();
|
|
95239
95483
|
init_packed_value_write_fold();
|
|
95240
|
-
|
|
95484
|
+
init_project_version_write_changes();
|
|
95241
95485
|
init_packed_value_encoding();
|
|
95242
95486
|
init_inheritance();
|
|
95243
95487
|
init_members();
|
|
@@ -100461,16 +100705,38 @@ function prepareServerOwnedValueInitializerBodies(args) {
|
|
|
100461
100705
|
}
|
|
100462
100706
|
}
|
|
100463
100707
|
function collectDelegateSweepRows(args) {
|
|
100464
|
-
|
|
100708
|
+
const closureRows = [];
|
|
100709
|
+
const inlineRows = [];
|
|
100710
|
+
if (args.targetIds.size === 0) return { closureRows, inlineRows };
|
|
100465
100711
|
const preparedValueIds = indexChangesByRecordId(args.prepared, "value");
|
|
100466
|
-
const sweepRows = [];
|
|
100467
100712
|
for (const value of args.postDocument.values) {
|
|
100468
100713
|
if (!args.targetIds.has(value.id)) continue;
|
|
100469
100714
|
if (preparedValueIds.has(value.id)) continue;
|
|
100470
100715
|
const row = delegateValueRow(value);
|
|
100471
|
-
if (row !== null)
|
|
100716
|
+
if (row !== null) {
|
|
100717
|
+
closureRows.push(row);
|
|
100718
|
+
continue;
|
|
100719
|
+
}
|
|
100720
|
+
const inlineRow = inlineDelegateSweepRow(value);
|
|
100721
|
+
if (inlineRow !== null) inlineRows.push(inlineRow);
|
|
100472
100722
|
}
|
|
100473
|
-
return
|
|
100723
|
+
return { closureRows, inlineRows };
|
|
100724
|
+
}
|
|
100725
|
+
function inlineDelegateSweepRow(value) {
|
|
100726
|
+
if (!isMemberValue(value) || !isLiteralValueContent(value)) return null;
|
|
100727
|
+
const constructorArgs = asRecord4(
|
|
100728
|
+
value.constructorArgs
|
|
100729
|
+
);
|
|
100730
|
+
if (constructorArgs === null) return null;
|
|
100731
|
+
let sourceArgs = null;
|
|
100732
|
+
for (const [key, argument2] of Object.entries(constructorArgs)) {
|
|
100733
|
+
const closure = asRecord4(argument2);
|
|
100734
|
+
if (typeof closure?.code !== "string") continue;
|
|
100735
|
+
if (!("action" in closure)) continue;
|
|
100736
|
+
sourceArgs ??= { ...constructorArgs };
|
|
100737
|
+
sourceArgs[key] = { code: closure.code };
|
|
100738
|
+
}
|
|
100739
|
+
return sourceArgs === null ? null : { ...value, constructorArgs: sourceArgs };
|
|
100474
100740
|
}
|
|
100475
100741
|
function delegateValueRow(value) {
|
|
100476
100742
|
if (!isMemberValue(value) || !isLiteralValueContent(value)) return null;
|
|
@@ -100617,8 +100883,8 @@ function prepareServerOwnedDelegateValueBodies(args) {
|
|
|
100617
100883
|
const withInlineArgs = inlineDelegateArgumentRow(change.nextData);
|
|
100618
100884
|
if (withInlineArgs !== null) inlineArgumentRows.set(index, withInlineArgs);
|
|
100619
100885
|
}
|
|
100620
|
-
const sweepRows = collectDelegateSweepRows(args);
|
|
100621
|
-
if (explicitRows.size === 0 && sweepRows.length === 0 && inlineArgumentRows.size === 0) {
|
|
100886
|
+
const { closureRows: sweepRows, inlineRows: inlineSweepRows } = collectDelegateSweepRows(args);
|
|
100887
|
+
if (explicitRows.size === 0 && sweepRows.length === 0 && inlineArgumentRows.size === 0 && inlineSweepRows.length === 0) {
|
|
100622
100888
|
return;
|
|
100623
100889
|
}
|
|
100624
100890
|
const committedDocument = applyProjectVersionWriteChanges(
|
|
@@ -100627,7 +100893,7 @@ function prepareServerOwnedDelegateValueBodies(args) {
|
|
|
100627
100893
|
);
|
|
100628
100894
|
const targetIds = valueIdsFromRows(
|
|
100629
100895
|
[...explicitRows.values(), ...inlineArgumentRows.values()],
|
|
100630
|
-
sweepRows
|
|
100896
|
+
[...sweepRows, ...inlineSweepRows]
|
|
100631
100897
|
);
|
|
100632
100898
|
const rootOwnerByValueId = /* @__PURE__ */ new Map();
|
|
100633
100899
|
const delegateScope = withVariantOwnershipRoots(
|
|
@@ -100702,7 +100968,7 @@ function prepareServerOwnedDelegateValueBodies(args) {
|
|
|
100702
100968
|
};
|
|
100703
100969
|
}
|
|
100704
100970
|
}
|
|
100705
|
-
if (sweepRows.length === 0) return;
|
|
100971
|
+
if (sweepRows.length === 0 && inlineSweepRows.length === 0) return;
|
|
100706
100972
|
const currentById = new Map(
|
|
100707
100973
|
args.document.values.map((value) => [value.id, value])
|
|
100708
100974
|
);
|
|
@@ -100712,40 +100978,65 @@ function prepareServerOwnedDelegateValueBodies(args) {
|
|
|
100712
100978
|
prepared: args.prepared,
|
|
100713
100979
|
contentHashHeads: args.contentHashHeads
|
|
100714
100980
|
});
|
|
100981
|
+
const refresh = (id2, compiled) => {
|
|
100982
|
+
const current = currentById.get(id2);
|
|
100983
|
+
if (current === void 0 || canonicallyEqual2(current, compiled)) return;
|
|
100984
|
+
const contentHash = baseHashFor(id2);
|
|
100985
|
+
if (contentHash === void 0) {
|
|
100986
|
+
throw new Error(
|
|
100987
|
+
`Cannot safely refresh the compiled NeoDelegate closure for value "${id2}": its current content hash is unavailable.`
|
|
100988
|
+
);
|
|
100989
|
+
}
|
|
100990
|
+
args.prepared.push({
|
|
100991
|
+
recordKind: "value",
|
|
100992
|
+
recordId: id2,
|
|
100993
|
+
operation: "update",
|
|
100994
|
+
nextData: compiled,
|
|
100995
|
+
intent: createProjectVersionIntent("value.update", {
|
|
100996
|
+
source: "server-neoscript-recompile"
|
|
100997
|
+
}),
|
|
100998
|
+
...contentHash === null ? {} : { expectedBaseContentHash: contentHash }
|
|
100999
|
+
});
|
|
101000
|
+
};
|
|
100715
101001
|
for (const row of sweepRows) {
|
|
100716
101002
|
const compiled = { ...row, value: { ...row.value } };
|
|
100717
101003
|
try {
|
|
100718
101004
|
compileOne(delegateScope.document, compiled);
|
|
100719
101005
|
} catch (postWriteError) {
|
|
100720
|
-
const
|
|
101006
|
+
const current = delegateValueRow(
|
|
100721
101007
|
structuredClone(currentById.get(row.id))
|
|
100722
101008
|
);
|
|
100723
|
-
if (
|
|
101009
|
+
if (current === null) throw postWriteError;
|
|
100724
101010
|
try {
|
|
100725
|
-
compileOne(args.document,
|
|
101011
|
+
compileOne(args.document, current);
|
|
100726
101012
|
} catch (preWriteError) {
|
|
100727
101013
|
if (sameCompileFailure(preWriteError, postWriteError)) continue;
|
|
100728
101014
|
}
|
|
100729
101015
|
throw postWriteError;
|
|
100730
101016
|
}
|
|
100731
|
-
|
|
100732
|
-
|
|
100733
|
-
|
|
100734
|
-
|
|
100735
|
-
|
|
100736
|
-
|
|
100737
|
-
|
|
101017
|
+
refresh(row.id, compiled);
|
|
101018
|
+
}
|
|
101019
|
+
const compileInlineOne = (document, row) => compileInlineDelegateConstructorArguments({
|
|
101020
|
+
document,
|
|
101021
|
+
row,
|
|
101022
|
+
ownerMember: ownerByValueId.get(row.id),
|
|
101023
|
+
rootOwner: rootOwnerByValueId.get(row.id) ?? null
|
|
101024
|
+
});
|
|
101025
|
+
for (const row of inlineSweepRows) {
|
|
101026
|
+
let compiledArgs;
|
|
101027
|
+
try {
|
|
101028
|
+
compiledArgs = compileInlineOne(delegateScope.document, row);
|
|
101029
|
+
} catch (postWriteError) {
|
|
101030
|
+
const current = inlineDelegateSweepRow(currentById.get(row.id));
|
|
101031
|
+
if (current === null) throw postWriteError;
|
|
101032
|
+
try {
|
|
101033
|
+
compileInlineOne(args.document, current);
|
|
101034
|
+
} catch (preWriteError) {
|
|
101035
|
+
if (sameCompileFailure(preWriteError, postWriteError)) continue;
|
|
101036
|
+
}
|
|
101037
|
+
throw postWriteError;
|
|
100738
101038
|
}
|
|
100739
|
-
|
|
100740
|
-
recordKind: "value",
|
|
100741
|
-
recordId: row.id,
|
|
100742
|
-
operation: "update",
|
|
100743
|
-
nextData: compiled,
|
|
100744
|
-
intent: createProjectVersionIntent("value.update", {
|
|
100745
|
-
source: "server-neoscript-recompile"
|
|
100746
|
-
}),
|
|
100747
|
-
...contentHash === null ? {} : { expectedBaseContentHash: contentHash }
|
|
100748
|
-
});
|
|
101039
|
+
refresh(row.id, { ...row, constructorArgs: compiledArgs });
|
|
100749
101040
|
}
|
|
100750
101041
|
}
|
|
100751
101042
|
function prepareServerOwnedConstructorBodies(args) {
|
|
@@ -101000,113 +101291,6 @@ function assertUniqueChanges(changes) {
|
|
|
101000
101291
|
}
|
|
101001
101292
|
}
|
|
101002
101293
|
}
|
|
101003
|
-
function applyProjectVersionWriteChanges(document, changes) {
|
|
101004
|
-
return projectVersionDocumentWithChanges(document, changes, false);
|
|
101005
|
-
}
|
|
101006
|
-
function projectVersionDocumentWithChanges(document, changes, reuseUnchangedBuckets) {
|
|
101007
|
-
const projectRows = (rows, kind) => {
|
|
101008
|
-
const relevant = changes.filter((change) => change.recordKind === kind);
|
|
101009
|
-
if (reuseUnchangedBuckets && relevant.length === 0) return rows;
|
|
101010
|
-
return applyArrayChanges(rows, relevant);
|
|
101011
|
-
};
|
|
101012
|
-
const hasGranularDialogueRecords = document.dialogueRecords !== void 0 || changes.some((change) => change.recordKind === "dialogue");
|
|
101013
|
-
const hasGranularDialogueNodes = document.dialogueNodes !== void 0 || changes.some((change) => change.recordKind === "dialogue-node");
|
|
101014
|
-
const dialogueRecords = hasGranularDialogueRecords ? projectRows(document.dialogueRecords ?? [], "dialogue") : void 0;
|
|
101015
|
-
const dialogueNodes = hasGranularDialogueNodes ? projectRows(document.dialogueNodes ?? [], "dialogue-node") : void 0;
|
|
101016
|
-
const projected = {
|
|
101017
|
-
localizedTexts: projectRows(
|
|
101018
|
-
document.localizedTexts ?? [],
|
|
101019
|
-
"localized-text"
|
|
101020
|
-
),
|
|
101021
|
-
localizationConfig: applySingletonChange(
|
|
101022
|
-
document.localizationConfig,
|
|
101023
|
-
changes,
|
|
101024
|
-
"localization-config"
|
|
101025
|
-
),
|
|
101026
|
-
project: applySingletonChange(document.project, changes, "project"),
|
|
101027
|
-
members: projectRows(document.members, "member"),
|
|
101028
|
-
classes: projectRows(document.classes, "class"),
|
|
101029
|
-
// P43 §6. Declared constructors participate in the post-transaction
|
|
101030
|
-
// document so the whole-graph validator and every body compile see the
|
|
101031
|
-
// same constructor surface the transaction is about to persist.
|
|
101032
|
-
constructors: projectRows(document.constructors ?? [], "constructor"),
|
|
101033
|
-
// P67 §2.1. Same reason as constructors: without these buckets the
|
|
101034
|
-
// whole-graph validator, the variant ownership roots, and every body
|
|
101035
|
-
// compile would grade the transaction against the pre-transaction
|
|
101036
|
-
// variant set — so a newly pushed variant's closures would compile
|
|
101037
|
-
// against a document that does not contain it.
|
|
101038
|
-
variants: projectRows(document.variants ?? [], "variant"),
|
|
101039
|
-
variantFolders: projectRows(
|
|
101040
|
-
document.variantFolders ?? [],
|
|
101041
|
-
"variant-folder"
|
|
101042
|
-
),
|
|
101043
|
-
values: projectRows(document.values ?? [], "value"),
|
|
101044
|
-
// Project-file staging finalizes pending uploads before schema
|
|
101045
|
-
// preparation. Defaults and authored instance graphs may reference a file
|
|
101046
|
-
// created by the same source transaction, so every construction pass must
|
|
101047
|
-
// see that finalized row in its post-write document.
|
|
101048
|
-
projectFiles: projectRows(document.projectFiles ?? [], "project-file"),
|
|
101049
|
-
// Import-setting templates are part of the same file graph. A new file
|
|
101050
|
-
// may select a new template in one source transaction, and default-value
|
|
101051
|
-
// materialization validates that relationship immediately against this
|
|
101052
|
-
// post-write document.
|
|
101053
|
-
textureTemplates: projectRows(
|
|
101054
|
-
document.textureTemplates ?? [],
|
|
101055
|
-
"unity-texture-template"
|
|
101056
|
-
),
|
|
101057
|
-
audioClipTemplates: projectRows(
|
|
101058
|
-
document.audioClipTemplates ?? [],
|
|
101059
|
-
"unity-audio-clip-template"
|
|
101060
|
-
),
|
|
101061
|
-
internalRecordRelations: projectRows(
|
|
101062
|
-
document.internalRecordRelations ?? [],
|
|
101063
|
-
"internal-record-relation"
|
|
101064
|
-
),
|
|
101065
|
-
enums: projectRows(document.enums, "enum"),
|
|
101066
|
-
interfaces: projectRows(document.interfaces, "interface"),
|
|
101067
|
-
dialogues: dialogueRecords === void 0 || dialogueNodes === void 0 || dialogueRecords === document.dialogueRecords && dialogueNodes === document.dialogueNodes ? document.dialogues : materializeDialogues(
|
|
101068
|
-
dialogueRecords,
|
|
101069
|
-
dialogueNodes
|
|
101070
|
-
),
|
|
101071
|
-
dialogueGroups: projectRows(
|
|
101072
|
-
document.dialogueGroups ?? [],
|
|
101073
|
-
"dialogue-group"
|
|
101074
|
-
),
|
|
101075
|
-
migrations: projectRows(document.migrations ?? [], "migration")
|
|
101076
|
-
};
|
|
101077
|
-
return {
|
|
101078
|
-
...document,
|
|
101079
|
-
...projected,
|
|
101080
|
-
...dialogueRecords === void 0 ? {} : { dialogueRecords },
|
|
101081
|
-
...dialogueNodes === void 0 ? {} : { dialogueNodes }
|
|
101082
|
-
// The document spread above carries every bucket the caller's view declares
|
|
101083
|
-
// beyond the projected ones, so the result is the same view; TypeScript
|
|
101084
|
-
// cannot prove that of an object literal built over a type parameter.
|
|
101085
|
-
};
|
|
101086
|
-
}
|
|
101087
|
-
function applySingletonChange(current, changes, recordKind) {
|
|
101088
|
-
const change = changes.find(
|
|
101089
|
-
(candidate) => candidate.recordKind === recordKind
|
|
101090
|
-
);
|
|
101091
|
-
if (change === void 0) return current;
|
|
101092
|
-
if (change.operation === "delete" || change.nextData === void 0) {
|
|
101093
|
-
throw new Error(`Schema commit cannot delete the ${recordKind} record.`);
|
|
101094
|
-
}
|
|
101095
|
-
return change.nextData;
|
|
101096
|
-
}
|
|
101097
|
-
function applyArrayChanges(current, changes) {
|
|
101098
|
-
const byId = new Map(current.map((record6) => [record6.id, record6]));
|
|
101099
|
-
for (const change of changes) {
|
|
101100
|
-
if (change.operation === "delete") {
|
|
101101
|
-
byId.delete(change.recordId);
|
|
101102
|
-
continue;
|
|
101103
|
-
}
|
|
101104
|
-
if (change.nextData !== void 0) {
|
|
101105
|
-
byId.set(change.recordId, change.nextData);
|
|
101106
|
-
}
|
|
101107
|
-
}
|
|
101108
|
-
return [...byId.values()];
|
|
101109
|
-
}
|
|
101110
101294
|
function asRecord4(value) {
|
|
101111
101295
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
101112
101296
|
return null;
|
|
@@ -101301,7 +101485,6 @@ var init_project_version_schema_commit = __esm({
|
|
|
101301
101485
|
init_evaluateInitializer();
|
|
101302
101486
|
init_virtual_instance_graph();
|
|
101303
101487
|
init_virtual_instance_values();
|
|
101304
|
-
init_projectDocumentDialogueMaterialization();
|
|
101305
101488
|
init_valueHeadPlacementGraph();
|
|
101306
101489
|
init_canonical_json();
|
|
101307
101490
|
init_compile_ns_property();
|
|
@@ -101326,6 +101509,7 @@ var init_project_version_schema_commit = __esm({
|
|
|
101326
101509
|
init_project_version_relation_sweep_trigger();
|
|
101327
101510
|
init_project_version_static_value_writes();
|
|
101328
101511
|
init_project_version_transaction_planning();
|
|
101512
|
+
init_project_version_write_changes();
|
|
101329
101513
|
init_value_row_owner_members();
|
|
101330
101514
|
init_variant_value_graph();
|
|
101331
101515
|
SERVER_COMPILATION_PROJECT_CACHE_LIMIT = 4;
|
|
@@ -101375,10 +101559,6 @@ var init_unity_static_members = __esm({
|
|
|
101375
101559
|
});
|
|
101376
101560
|
|
|
101377
101561
|
// ../src/models/animation/animation-clips.ts
|
|
101378
|
-
function isWorldAnimationStructuralMember(memberId, members) {
|
|
101379
|
-
const membersById = new Map(members.map((member) => [member.id, member]));
|
|
101380
|
-
return isWorldAnimationStructuralMemberFromIndex(memberId, membersById);
|
|
101381
|
-
}
|
|
101382
101562
|
function isWorldAnimationStructuralMemberFromIndex(memberId, membersById) {
|
|
101383
101563
|
const visited = /* @__PURE__ */ new Set();
|
|
101384
101564
|
let currentId = memberId;
|
|
@@ -101389,6 +101569,35 @@ function isWorldAnimationStructuralMemberFromIndex(memberId, membersById) {
|
|
|
101389
101569
|
}
|
|
101390
101570
|
return false;
|
|
101391
101571
|
}
|
|
101572
|
+
function worldOverridePathIsStructurallyEligible(memberIdsRootToLeaf, membersById) {
|
|
101573
|
+
for (const memberId of memberIdsRootToLeaf) {
|
|
101574
|
+
if (isWorldAnimationStructuralMemberFromIndex(memberId, membersById)) {
|
|
101575
|
+
return false;
|
|
101576
|
+
}
|
|
101577
|
+
const member = membersById.get(memberId);
|
|
101578
|
+
if (member === void 0) return false;
|
|
101579
|
+
const resolved = resolveMemberFromIndex(member, membersById);
|
|
101580
|
+
if (isStaticMember(resolved) || isReadOnlyMember(resolved)) return false;
|
|
101581
|
+
if (resolved.kind === 13 /* Function */ || resolved.kind === 23 /* NSFunction */ || resolved.kind === 10 /* NSProperty */ || resolved.kind === 6 /* List */ || resolved.kind === 5 /* Dictionary */) {
|
|
101582
|
+
return false;
|
|
101583
|
+
}
|
|
101584
|
+
}
|
|
101585
|
+
return true;
|
|
101586
|
+
}
|
|
101587
|
+
function animationTrackStorage(memberIdsRootToLeaf, membersById, childrenPrefix = []) {
|
|
101588
|
+
if (!worldOverridePathIsStructurallyEligible(memberIdsRootToLeaf, membersById)) {
|
|
101589
|
+
return null;
|
|
101590
|
+
}
|
|
101591
|
+
const path = [...childrenPrefix, ...memberIdsRootToLeaf];
|
|
101592
|
+
for (let index = path.length - 1; index >= 0; index -= 1) {
|
|
101593
|
+
const memberId = path[index];
|
|
101594
|
+
if (memberId === void 0) continue;
|
|
101595
|
+
const storage = declaredMemberStorageFromIndex(memberId, membersById);
|
|
101596
|
+
if (storage === 0 /* Inherit */) continue;
|
|
101597
|
+
return storage === 1 /* Immutable */ ? null : storage;
|
|
101598
|
+
}
|
|
101599
|
+
return null;
|
|
101600
|
+
}
|
|
101392
101601
|
function assertAnimationClipDocumentValid(document, scope) {
|
|
101393
101602
|
const context = new AnimationValidationContext(document);
|
|
101394
101603
|
context.validateSegments(scope);
|
|
@@ -101416,7 +101625,6 @@ var init_animation_clips = __esm({
|
|
|
101416
101625
|
init_member_storage();
|
|
101417
101626
|
init_neoscript_types();
|
|
101418
101627
|
init_neoscript_guards();
|
|
101419
|
-
init_project_root_members();
|
|
101420
101628
|
init_members();
|
|
101421
101629
|
WORLD_ANIMATION_STRUCTURAL_MEMBER_ROOT_IDS = /* @__PURE__ */ new Set([
|
|
101422
101630
|
WORLD_GRID_CHILDREN_MEMBER_ID,
|
|
@@ -101442,17 +101650,11 @@ var init_animation_clips = __esm({
|
|
|
101442
101650
|
document.members.map((value) => [value.id, value])
|
|
101443
101651
|
);
|
|
101444
101652
|
this.valueById = new Map(document.values.map((value) => [value.id, value]));
|
|
101445
|
-
this.storage = new EffectiveStorageResolver({
|
|
101446
|
-
classes: document.classes,
|
|
101447
|
-
members: document.members,
|
|
101448
|
-
rootStorage: buildRootStorageMap(document.project)
|
|
101449
|
-
});
|
|
101450
101653
|
}
|
|
101451
101654
|
document;
|
|
101452
101655
|
classById;
|
|
101453
101656
|
memberById;
|
|
101454
101657
|
valueById;
|
|
101455
|
-
storage;
|
|
101456
101658
|
classHasWorldKind(classId, worldKind) {
|
|
101457
101659
|
const visited = /* @__PURE__ */ new Set();
|
|
101458
101660
|
let current = this.classById.get(classId);
|
|
@@ -101528,6 +101730,7 @@ var init_animation_clips = __esm({
|
|
|
101528
101730
|
definitionNode: targetDefinition,
|
|
101529
101731
|
memberPath: [],
|
|
101530
101732
|
storagePath: [],
|
|
101733
|
+
childrenPrefix: [],
|
|
101531
101734
|
visited: /* @__PURE__ */ new Set()
|
|
101532
101735
|
});
|
|
101533
101736
|
}
|
|
@@ -101612,7 +101815,8 @@ var init_animation_clips = __esm({
|
|
|
101612
101815
|
overrideNode: overrides,
|
|
101613
101816
|
definitionNode: child,
|
|
101614
101817
|
memberPath: [`child:${childId}`],
|
|
101615
|
-
storagePath: [
|
|
101818
|
+
storagePath: [],
|
|
101819
|
+
childrenPrefix: args.childStoragePath,
|
|
101616
101820
|
visited: /* @__PURE__ */ new Set()
|
|
101617
101821
|
});
|
|
101618
101822
|
}
|
|
@@ -101955,12 +102159,13 @@ var init_animation_clips = __esm({
|
|
|
101955
102159
|
`${args.label} targets "${boundChildName}.${targetEntry.schemaKey}" of kind ${MemberKind[targetMember.kind]}, but its segment plays ${MemberKind[valueBindingMember.kind]} values.`
|
|
101956
102160
|
);
|
|
101957
102161
|
}
|
|
101958
|
-
if (!this.overrideLeafEligible(
|
|
101959
|
-
|
|
101960
|
-
targetMember.id
|
|
101961
|
-
|
|
102162
|
+
if (!this.overrideLeafEligible(
|
|
102163
|
+
targetMember,
|
|
102164
|
+
[targetMember.id],
|
|
102165
|
+
args.childStoragePath
|
|
102166
|
+
)) {
|
|
101962
102167
|
throw new Error(
|
|
101963
|
-
`${args.label} targets "${boundChildName}.${targetEntry.schemaKey}", which is not a writable Save
|
|
102168
|
+
`${args.label} targets "${boundChildName}.${targetEntry.schemaKey}", which is not a writable Save, Session, or Writable override leaf.`
|
|
101964
102169
|
);
|
|
101965
102170
|
}
|
|
101966
102171
|
}
|
|
@@ -102130,7 +102335,8 @@ var init_animation_clips = __esm({
|
|
|
102130
102335
|
partial: overrideChild.value,
|
|
102131
102336
|
path,
|
|
102132
102337
|
schemaKey,
|
|
102133
|
-
storagePath: args.storagePath
|
|
102338
|
+
storagePath: args.storagePath,
|
|
102339
|
+
childrenPrefix: args.childrenPrefix
|
|
102134
102340
|
});
|
|
102135
102341
|
continue;
|
|
102136
102342
|
}
|
|
@@ -102161,9 +102367,13 @@ var init_animation_clips = __esm({
|
|
|
102161
102367
|
});
|
|
102162
102368
|
continue;
|
|
102163
102369
|
}
|
|
102164
|
-
if (!this.overrideLeafEligible(
|
|
102370
|
+
if (!this.overrideLeafEligible(
|
|
102371
|
+
member,
|
|
102372
|
+
[...args.storagePath, member.id],
|
|
102373
|
+
args.childrenPrefix
|
|
102374
|
+
)) {
|
|
102165
102375
|
throw new Error(
|
|
102166
|
-
`Animation clip "${args.clipName}" frame ${args.frameIndex} member "${path.join(".")}" is not a writable Save
|
|
102376
|
+
`Animation clip "${args.clipName}" frame ${args.frameIndex} member "${path.join(".")}" is not a writable Save, Session, or Writable override leaf.`
|
|
102167
102377
|
);
|
|
102168
102378
|
}
|
|
102169
102379
|
}
|
|
@@ -102198,12 +102408,13 @@ var init_animation_clips = __esm({
|
|
|
102198
102408
|
);
|
|
102199
102409
|
}
|
|
102200
102410
|
const kindLabel = MemberKind[kind];
|
|
102201
|
-
if (!this.overrideLeafEligible(
|
|
102202
|
-
|
|
102203
|
-
args.member.id
|
|
102204
|
-
|
|
102411
|
+
if (!this.overrideLeafEligible(
|
|
102412
|
+
args.member,
|
|
102413
|
+
[...args.storagePath, args.member.id],
|
|
102414
|
+
args.childrenPrefix
|
|
102415
|
+
)) {
|
|
102205
102416
|
throw new Error(
|
|
102206
|
-
`${prefix} ${kindLabel} member "${memberPath3}" cannot take a "${STRUCTURED_LEAF_PARTIAL_KEY}" field override; member "${args.member.name}" is not a writable Save
|
|
102417
|
+
`${prefix} ${kindLabel} member "${memberPath3}" cannot take a "${STRUCTURED_LEAF_PARTIAL_KEY}" field override; member "${args.member.name}" is not a writable Save, Session, or Writable override leaf.`
|
|
102207
102418
|
);
|
|
102208
102419
|
}
|
|
102209
102420
|
const violation = structuredLeafPartialViolation(
|
|
@@ -102244,24 +102455,9 @@ var init_animation_clips = __esm({
|
|
|
102244
102455
|
throw new Error(`${descent}; its value is not a ${kindLabel} record.`);
|
|
102245
102456
|
}
|
|
102246
102457
|
}
|
|
102247
|
-
overrideLeafEligible(member, storagePath) {
|
|
102248
|
-
if (
|
|
102249
|
-
|
|
102250
|
-
if (isWorldAnimationStructuralMember(member.id, this.document.members)) {
|
|
102251
|
-
return false;
|
|
102252
|
-
}
|
|
102253
|
-
if (member.kind === 13 /* Function */ || member.kind === 23 /* NSFunction */ || member.kind === 10 /* NSProperty */ || member.kind === 7 /* Class */ || member.kind === 6 /* List */ || member.kind === 5 /* Dictionary */) {
|
|
102254
|
-
return false;
|
|
102255
|
-
}
|
|
102256
|
-
try {
|
|
102257
|
-
const storage = this.storage.effectiveStorageForPath(storagePath);
|
|
102258
|
-
return storage === 2 /* Save */ || storage === 3 /* Session */;
|
|
102259
|
-
} catch {
|
|
102260
|
-
const storages = this.storage.effectiveStorages(member.id);
|
|
102261
|
-
return storages.size > 0 && [...storages].every(
|
|
102262
|
-
(storage) => storage === 2 /* Save */ || storage === 3 /* Session */
|
|
102263
|
-
);
|
|
102264
|
-
}
|
|
102458
|
+
overrideLeafEligible(member, storagePath, childrenPrefix) {
|
|
102459
|
+
if (member.kind === 7 /* Class */) return false;
|
|
102460
|
+
return animationTrackStorage(storagePath, this.memberById, childrenPrefix) !== null;
|
|
102265
102461
|
}
|
|
102266
102462
|
authoredChildren(targetClassId, definitionNode) {
|
|
102267
102463
|
const childEntry = mergeStoredInstanceSchema(
|
|
@@ -102285,9 +102481,8 @@ var init_animation_clips = __esm({
|
|
|
102285
102481
|
(value) => typeof value === "string"
|
|
102286
102482
|
) : []
|
|
102287
102483
|
),
|
|
102288
|
-
//
|
|
102289
|
-
// owner's resolved Children member
|
|
102290
|
-
// storage path instead of treating a shared child-class leaf as a root.
|
|
102484
|
+
// P93 §5: a child track's declaration walk continues through the
|
|
102485
|
+
// owner's resolved Children member, as the authoring pane's does.
|
|
102291
102486
|
storagePath: [childEntry.memberId]
|
|
102292
102487
|
};
|
|
102293
102488
|
}
|
|
@@ -103250,7 +103445,7 @@ function readClass(value) {
|
|
|
103250
103445
|
CLASS_VISIBILITY_KINDS,
|
|
103251
103446
|
`${label} uiVisibility`
|
|
103252
103447
|
);
|
|
103253
|
-
if (value.allowedStorage != null && !
|
|
103448
|
+
if (value.allowedStorage != null && !isClassAllowedStorage(value.allowedStorage)) {
|
|
103254
103449
|
throw new Error(`${label} allowedStorage is invalid.`);
|
|
103255
103450
|
}
|
|
103256
103451
|
if (value.genericParams !== void 0 && value.genericParams !== null) {
|
|
@@ -103632,6 +103827,14 @@ function assertProjectInterfaceDocumentValid(view, options = {}) {
|
|
|
103632
103827
|
const classes = view.classes.map(readClass);
|
|
103633
103828
|
const interfaces = view.interfaces.map(readInterface);
|
|
103634
103829
|
const membersById = new Map(members.map((member) => [member.id, member]));
|
|
103830
|
+
for (const [rootId, stamped] of view.rootStorage ?? []) {
|
|
103831
|
+
const root = membersById.get(rootId);
|
|
103832
|
+
if (root === void 0 || root.storage === stamped) continue;
|
|
103833
|
+
const declared = root.storage === void 0 ? "none" : MemberStorageKind[root.storage];
|
|
103834
|
+
throw new Error(
|
|
103835
|
+
`Project root member "${root.name}" (${rootId}) must declare ${MemberStorageKind[stamped]} storage but declares ${declared}.`
|
|
103836
|
+
);
|
|
103837
|
+
}
|
|
103635
103838
|
const classesById = new Map(
|
|
103636
103839
|
classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
|
|
103637
103840
|
);
|
|
@@ -103751,6 +103954,11 @@ function assertProjectInterfaceDocumentValid(view, options = {}) {
|
|
|
103751
103954
|
`Static member "${member.name}" (${member.id}) must be a plain non-override member.`
|
|
103752
103955
|
);
|
|
103753
103956
|
}
|
|
103957
|
+
if (member.storage === 4 /* Writable */) {
|
|
103958
|
+
throw new Error(
|
|
103959
|
+
`Static member "${member.name}" (${member.id}) cannot declare Writable storage; a static member has no placement parent to resolve it against.`
|
|
103960
|
+
);
|
|
103961
|
+
}
|
|
103754
103962
|
if (member.kind === 21) {
|
|
103755
103963
|
throw new Error(
|
|
103756
103964
|
`Generic placeholder member "${member.name}" (${member.id}) cannot be static.`
|
|
@@ -104055,6 +104263,19 @@ function assertProjectInterfaceDocumentValid(view, options = {}) {
|
|
|
104055
104263
|
if (member.mutability === void 0) delete resolved.mutability;
|
|
104056
104264
|
return resolved;
|
|
104057
104265
|
};
|
|
104266
|
+
const writableAncestor2 = createWritableAncestorLookup(
|
|
104267
|
+
(id2) => membersById.get(id2)
|
|
104268
|
+
);
|
|
104269
|
+
for (const member of members) {
|
|
104270
|
+
if (member.storage !== 1 /* Immutable */ && member.storage !== 0 /* Inherit */) {
|
|
104271
|
+
continue;
|
|
104272
|
+
}
|
|
104273
|
+
const ancestor = writableAncestor2(member);
|
|
104274
|
+
if (ancestor === null) continue;
|
|
104275
|
+
throw new Error(
|
|
104276
|
+
`Member "${member.name}" (${member.id}) declares ${MemberStorageKind[member.storage]} storage but overrides Writable member "${ancestor.name}" (${ancestor.id}); an override of a Writable member may declare Writable, Save, or Session, or omit storage.`
|
|
104277
|
+
);
|
|
104278
|
+
}
|
|
104058
104279
|
const rootAndEntryMemberIds = /* @__PURE__ */ new Set();
|
|
104059
104280
|
for (const owner of members) {
|
|
104060
104281
|
if (typeof owner.entryMemberId === "string") {
|
|
@@ -104196,7 +104417,7 @@ function assertProjectInterfaceDocumentValid(view, options = {}) {
|
|
|
104196
104417
|
}
|
|
104197
104418
|
}
|
|
104198
104419
|
if (rawOwned.id === member.id && isAbstractMember(member)) return;
|
|
104199
|
-
if (owned.storage === 2 /* Save */ || owned.storage === 3 /* Session */) {
|
|
104420
|
+
if (owned.storage === 2 /* Save */ || owned.storage === 3 /* Session */ || owned.storage === 4 /* Writable */) {
|
|
104200
104421
|
throw new Error(
|
|
104201
104422
|
`Read-only member "${member.name}" has a non-Immutable owned default child "${owned.name}"; ${ownerLabel}.`
|
|
104202
104423
|
);
|
|
@@ -104727,7 +104948,7 @@ function assertProjectInterfaceDocumentValid(view, options = {}) {
|
|
|
104727
104948
|
return resolved.setterCode === void 0 ? "NSProperty has no setter implementation." : null;
|
|
104728
104949
|
}
|
|
104729
104950
|
const storage = resolved.storage;
|
|
104730
|
-
if (storage === 2 /* Save */ || storage === 3 /* Session */) {
|
|
104951
|
+
if (storage === 2 /* Save */ || storage === 3 /* Session */ || storage === 4 /* Writable */) {
|
|
104731
104952
|
return null;
|
|
104732
104953
|
}
|
|
104733
104954
|
if (storage === 1 /* Immutable */) {
|
|
@@ -106765,6 +106986,14 @@ function assertStagedProjectInterfaceValid(projected, changes) {
|
|
|
106765
106986
|
variants: projected.variants ?? [],
|
|
106766
106987
|
variantFolders: projected.variantFolders ?? [],
|
|
106767
106988
|
interfaces: projected.interfaces,
|
|
106989
|
+
rootStorage: writtenRootStorage(
|
|
106990
|
+
projected.project,
|
|
106991
|
+
new Set(
|
|
106992
|
+
changes.flatMap(
|
|
106993
|
+
(change) => change.recordKind === "member" ? [change.recordId] : []
|
|
106994
|
+
)
|
|
106995
|
+
)
|
|
106996
|
+
),
|
|
106768
106997
|
values: projected.values
|
|
106769
106998
|
},
|
|
106770
106999
|
{
|
|
@@ -107360,9 +107589,10 @@ var init_project_version_whole_graph_validation = __esm({
|
|
|
107360
107589
|
init_core();
|
|
107361
107590
|
init_animation_clips();
|
|
107362
107591
|
init_projectInterfaceValidation();
|
|
107592
|
+
init_project_root_members();
|
|
107363
107593
|
init_project_schema_identifier_validation();
|
|
107364
107594
|
init_packed_value_write_fold();
|
|
107365
|
-
|
|
107595
|
+
init_project_version_write_changes();
|
|
107366
107596
|
init_project_version_system_protection_writes();
|
|
107367
107597
|
init_reserved_record_id_validation();
|
|
107368
107598
|
init_members();
|
|
@@ -109487,6 +109717,7 @@ function memberCommon(context, ownerClass, declaration, id2, owner, base) {
|
|
|
109487
109717
|
const storage = annotation(declaration.annotations, "storage");
|
|
109488
109718
|
const distribution = annotation(declaration.annotations, "distribution");
|
|
109489
109719
|
const inheritedId = declaration.modifiers.includes("override") || declaration.modifiers.includes("sealed") ? inheritedMemberId(context, ownerClass, declaration.name) : null;
|
|
109720
|
+
assertWritableStorageRules(context, ownerClass, declaration, inheritedId);
|
|
109490
109721
|
return {
|
|
109491
109722
|
id: id2,
|
|
109492
109723
|
source: sourceIdentity2(declaration, "member", declaration.name),
|
|
@@ -111523,7 +111754,74 @@ function numberArgument(value, name) {
|
|
|
111523
111754
|
}
|
|
111524
111755
|
function storageValue(value, name) {
|
|
111525
111756
|
const enumValue2 = contextualEnumArgument(value, name)?.toLowerCase();
|
|
111526
|
-
return enumValue2 === "immutable" || enumValue2 === "save" || enumValue2 === "session" ? enumValue2 : null;
|
|
111757
|
+
return enumValue2 === "immutable" || enumValue2 === "save" || enumValue2 === "session" || enumValue2 === "writable" ? enumValue2 : null;
|
|
111758
|
+
}
|
|
111759
|
+
function assertWritableStorageRules(context, ownerClass, declaration, inheritedId) {
|
|
111760
|
+
const site = `${ownerClass.name}.${declaration.name}`;
|
|
111761
|
+
const storage = annotation(declaration.annotations, "storage");
|
|
111762
|
+
const declared = storage ? contextualEnumArgument(storage, "allowed")?.toLowerCase() : void 0;
|
|
111763
|
+
if (declared === "writable" && declaration.modifiers.includes("static")) {
|
|
111764
|
+
throw new Error(
|
|
111765
|
+
`Static member ${site} cannot declare Writable storage: a static member has no parent to resolve it against. Declare Save or Session.`
|
|
111766
|
+
);
|
|
111767
|
+
}
|
|
111768
|
+
if (inheritedId === null) return;
|
|
111769
|
+
const ancestor = writableAncestor(context, inheritedId);
|
|
111770
|
+
if (ancestor === null) return;
|
|
111771
|
+
if (declared === "immutable") {
|
|
111772
|
+
throw new Error(
|
|
111773
|
+
`${site} cannot declare Immutable storage because it overrides ${ancestor}, which declares Writable. Declare Writable, Save, or Session, or omit @storage.`
|
|
111774
|
+
);
|
|
111775
|
+
}
|
|
111776
|
+
if (declared === "inherit") {
|
|
111777
|
+
throw new Error(
|
|
111778
|
+
`${site} cannot declare Inherit storage because it overrides ${ancestor}, which declares Writable. Declare Writable, Save, or Session, or omit @storage.`
|
|
111779
|
+
);
|
|
111780
|
+
}
|
|
111781
|
+
}
|
|
111782
|
+
function writableAncestor(context, memberId) {
|
|
111783
|
+
const memo = context.writableAncestors;
|
|
111784
|
+
const chain = /* @__PURE__ */ new Set();
|
|
111785
|
+
let currentId = memberId;
|
|
111786
|
+
let found = null;
|
|
111787
|
+
while (currentId !== null) {
|
|
111788
|
+
const known = memo.get(currentId);
|
|
111789
|
+
if (known !== void 0) {
|
|
111790
|
+
found = known;
|
|
111791
|
+
break;
|
|
111792
|
+
}
|
|
111793
|
+
if (chain.has(currentId)) break;
|
|
111794
|
+
chain.add(currentId);
|
|
111795
|
+
const step = storageChainStep(context, currentId);
|
|
111796
|
+
if (step === null) break;
|
|
111797
|
+
if (step.storage === "writable") {
|
|
111798
|
+
found = step.label;
|
|
111799
|
+
break;
|
|
111800
|
+
}
|
|
111801
|
+
currentId = step.overrideOf;
|
|
111802
|
+
}
|
|
111803
|
+
for (const id2 of chain) memo.set(id2, found);
|
|
111804
|
+
return found;
|
|
111805
|
+
}
|
|
111806
|
+
function storageChainStep(context, memberId) {
|
|
111807
|
+
const sourcePlacement = context.sourceMembersById.get(memberId);
|
|
111808
|
+
if (sourcePlacement !== void 0) {
|
|
111809
|
+
const { ownerClass, member } = sourcePlacement;
|
|
111810
|
+
const storage = annotation(member.annotations, "storage");
|
|
111811
|
+
return {
|
|
111812
|
+
label: `${ownerClass.name}.${member.name}`,
|
|
111813
|
+
storage: storage ? storageValue(storage, "allowed") : null,
|
|
111814
|
+
overrideOf: member.modifiers.includes("override") || member.modifiers.includes("sealed") ? inheritedMemberId(context, ownerClass, member.name) : null
|
|
111815
|
+
};
|
|
111816
|
+
}
|
|
111817
|
+
const persisted = context.baseMembers.get(memberId);
|
|
111818
|
+
if (persisted === void 0) return null;
|
|
111819
|
+
const ownerName = persisted.owner.kind === "classMember" ? context.baseClasses.get(persisted.owner.classId)?.name : void 0;
|
|
111820
|
+
return {
|
|
111821
|
+
label: ownerName === void 0 ? persisted.name : `${ownerName}.${persisted.name}`,
|
|
111822
|
+
storage: persisted.storage,
|
|
111823
|
+
overrideOf: persisted.overrideOf
|
|
111824
|
+
};
|
|
111527
111825
|
}
|
|
111528
111826
|
function referenceIdArgument(value, name) {
|
|
111529
111827
|
const raw = argument(value, name);
|
|
@@ -112503,6 +112801,7 @@ function lowerProjectSchemaV4(base, analysis, options = {}) {
|
|
|
112503
112801
|
enumOptionsByName,
|
|
112504
112802
|
loweredMembers: /* @__PURE__ */ new Map(),
|
|
112505
112803
|
entryTypesByEntryId: /* @__PURE__ */ new Map(),
|
|
112804
|
+
writableAncestors: /* @__PURE__ */ new Map(),
|
|
112506
112805
|
placements: /* @__PURE__ */ new Map(),
|
|
112507
112806
|
staticValueIdsBySymbol: staticValueIdsBySymbol3,
|
|
112508
112807
|
settleInitializerReferences: createSchemaInitializerReferenceSettlerV4({
|
|
@@ -139241,7 +139540,7 @@ var init_registry2 = __esm({
|
|
|
139241
139540
|
"schema-contract/registry.mjs"() {
|
|
139242
139541
|
"use strict";
|
|
139243
139542
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
139244
|
-
cliVersion: "0.
|
|
139543
|
+
cliVersion: "0.56.1",
|
|
139245
139544
|
projectFileUploadBatchSize: 32,
|
|
139246
139545
|
documentRecords: {
|
|
139247
139546
|
member: {
|
|
@@ -139583,8 +139882,8 @@ var init_registry2 = __esm({
|
|
|
139583
139882
|
sdkDeclarations: {
|
|
139584
139883
|
attributes: {
|
|
139585
139884
|
enums: {
|
|
139586
|
-
NeoStorage: ["Inherit", "Immutable", "Save", "Session"],
|
|
139587
|
-
NeoAllowedStorage: ["Any", "Immutable", "Save", "Session"],
|
|
139885
|
+
NeoStorage: ["Inherit", "Immutable", "Save", "Session", "Writable"],
|
|
139886
|
+
NeoAllowedStorage: ["Any", "Immutable", "Save", "Session", "Writable"],
|
|
139588
139887
|
NeoListKind: ["Ordered", "Unordered"],
|
|
139589
139888
|
NeoDictionaryKeyKind: ["String", "Enum"],
|
|
139590
139889
|
NeoClassVisibility: ["Visible", "Hidden"],
|
|
@@ -147062,7 +147361,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
|
|
|
147062
147361
|
async function main() {
|
|
147063
147362
|
const args = parseArgs(process.argv.slice(2));
|
|
147064
147363
|
if (args.command === "--version") {
|
|
147065
|
-
console.log("0.
|
|
147364
|
+
console.log("0.56.1");
|
|
147066
147365
|
return;
|
|
147067
147366
|
}
|
|
147068
147367
|
if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
|
package/package.json
CHANGED
|
@@ -97,7 +97,7 @@ wrappers.
|
|
|
97
97
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
98
98
|
|
|
99
99
|
```html
|
|
100
|
-
<!-- reviewed-through-cli: 0.
|
|
100
|
+
<!-- reviewed-through-cli: 0.56.1 -->
|
|
101
101
|
```
|
|
102
102
|
|
|
103
103
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -103,6 +103,39 @@ Use context-aware typed annotations:
|
|
|
103
103
|
Use numeric literals for numeric limits. Keep annotations separate instead of
|
|
104
104
|
inventing a generic metadata bag.
|
|
105
105
|
|
|
106
|
+
### Storage
|
|
107
|
+
|
|
108
|
+
A member's `@storage(allowed: ...)` is `.Immutable`, `.Save`, `.Session`, or
|
|
109
|
+
`.Writable`. Omit it to inherit the placement parent's storage. `.Writable` is
|
|
110
|
+
always writable at runtime and resolves from where the value is placed: Save
|
|
111
|
+
under a Save parent, Session under a Session or Immutable parent. Use it for a
|
|
112
|
+
member that NeoScript or an animation clip writes and whose value should persist
|
|
113
|
+
exactly when its owner persists. Animation clips can target `.Writable` members.
|
|
114
|
+
|
|
115
|
+
```neo
|
|
116
|
+
class AnimationSpriteObject(SpriteInfo sprite) : NeoSpriteObject {
|
|
117
|
+
@id("69905c25-8c05-4d18-90fd-069f1526a38a")
|
|
118
|
+
@storage(allowed: .Writable)
|
|
119
|
+
public override Vector3 Size = new(1, 1, 0);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
abstract class BodyLayerSprite(CharacterCosmeticConfig config, SpriteInfo sprite, int nearOrder, int farOrder) : AnimationSpriteObject(sprite: sprite) {
|
|
123
|
+
@id("e81dcef4-9ea8-4bbc-a83b-565b7cf3feff")
|
|
124
|
+
@storage(allowed: .Session)
|
|
125
|
+
public override Vector3 Size = new(2, 2, 0);
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
An override below a `.Writable` member, directly or through other overrides,
|
|
130
|
+
may declare `.Writable`, `.Save`, or `.Session`, or omit `@storage`. It may not
|
|
131
|
+
declare `.Immutable` or `.Inherit`, and it may not be `readonly`. Static
|
|
132
|
+
members, `readonly` members, and project roots cannot declare `.Writable`.
|
|
133
|
+
Lowering reports each violation at the member's position.
|
|
134
|
+
|
|
135
|
+
On a class, `@storage(allowed: .Writable)` means every placement must resolve
|
|
136
|
+
to Save or Session. A subclass may narrow it to `.Save` or `.Session`. An
|
|
137
|
+
undeclared static member of such a class is Session.
|
|
138
|
+
|
|
106
139
|
`@index(member: Field, kind: .Unique)` and
|
|
107
140
|
`@column(member: Field, width: ..., visibility: ..., pin: ..., overflow: ...)`
|
|
108
141
|
are repeatable List annotations. `member:` is a bare field name on the entry
|