@neocompose/cli 0.55.0 → 0.56.0
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,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.56.0] - 2026-09-23
|
|
4
|
+
|
|
5
|
+
- `@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.
|
|
6
|
+
- `@storage(allowed: .Writable)` on a class requires every placement of the class to resolve to Save or Session.
|
|
7
|
+
- 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.
|
|
8
|
+
|
|
3
9
|
## [0.55.0] - 2026-09-23
|
|
4
10
|
|
|
5
11
|
- `@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]);
|
|
57092
|
+
}
|
|
57093
|
+
for (let i = anchorIndex + 1; i < memberIdsRootToLeaf.length; i++) {
|
|
57094
|
+
storage = childEffectiveStorage(
|
|
57095
|
+
this.declaredStorage(memberIdsRootToLeaf[i]),
|
|
57096
|
+
storage
|
|
57097
|
+
);
|
|
56982
57098
|
}
|
|
56983
|
-
|
|
56984
|
-
|
|
56985
|
-
|
|
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) {
|
|
@@ -101375,10 +101504,6 @@ var init_unity_static_members = __esm({
|
|
|
101375
101504
|
});
|
|
101376
101505
|
|
|
101377
101506
|
// ../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
101507
|
function isWorldAnimationStructuralMemberFromIndex(memberId, membersById) {
|
|
101383
101508
|
const visited = /* @__PURE__ */ new Set();
|
|
101384
101509
|
let currentId = memberId;
|
|
@@ -101389,6 +101514,35 @@ function isWorldAnimationStructuralMemberFromIndex(memberId, membersById) {
|
|
|
101389
101514
|
}
|
|
101390
101515
|
return false;
|
|
101391
101516
|
}
|
|
101517
|
+
function worldOverridePathIsStructurallyEligible(memberIdsRootToLeaf, membersById) {
|
|
101518
|
+
for (const memberId of memberIdsRootToLeaf) {
|
|
101519
|
+
if (isWorldAnimationStructuralMemberFromIndex(memberId, membersById)) {
|
|
101520
|
+
return false;
|
|
101521
|
+
}
|
|
101522
|
+
const member = membersById.get(memberId);
|
|
101523
|
+
if (member === void 0) return false;
|
|
101524
|
+
const resolved = resolveMemberFromIndex(member, membersById);
|
|
101525
|
+
if (isStaticMember(resolved) || isReadOnlyMember(resolved)) return false;
|
|
101526
|
+
if (resolved.kind === 13 /* Function */ || resolved.kind === 23 /* NSFunction */ || resolved.kind === 10 /* NSProperty */ || resolved.kind === 6 /* List */ || resolved.kind === 5 /* Dictionary */) {
|
|
101527
|
+
return false;
|
|
101528
|
+
}
|
|
101529
|
+
}
|
|
101530
|
+
return true;
|
|
101531
|
+
}
|
|
101532
|
+
function animationTrackStorage(memberIdsRootToLeaf, membersById, childrenPrefix = []) {
|
|
101533
|
+
if (!worldOverridePathIsStructurallyEligible(memberIdsRootToLeaf, membersById)) {
|
|
101534
|
+
return null;
|
|
101535
|
+
}
|
|
101536
|
+
const path = [...childrenPrefix, ...memberIdsRootToLeaf];
|
|
101537
|
+
for (let index = path.length - 1; index >= 0; index -= 1) {
|
|
101538
|
+
const memberId = path[index];
|
|
101539
|
+
if (memberId === void 0) continue;
|
|
101540
|
+
const storage = declaredMemberStorageFromIndex(memberId, membersById);
|
|
101541
|
+
if (storage === 0 /* Inherit */) continue;
|
|
101542
|
+
return storage === 1 /* Immutable */ ? null : storage;
|
|
101543
|
+
}
|
|
101544
|
+
return null;
|
|
101545
|
+
}
|
|
101392
101546
|
function assertAnimationClipDocumentValid(document, scope) {
|
|
101393
101547
|
const context = new AnimationValidationContext(document);
|
|
101394
101548
|
context.validateSegments(scope);
|
|
@@ -101416,7 +101570,6 @@ var init_animation_clips = __esm({
|
|
|
101416
101570
|
init_member_storage();
|
|
101417
101571
|
init_neoscript_types();
|
|
101418
101572
|
init_neoscript_guards();
|
|
101419
|
-
init_project_root_members();
|
|
101420
101573
|
init_members();
|
|
101421
101574
|
WORLD_ANIMATION_STRUCTURAL_MEMBER_ROOT_IDS = /* @__PURE__ */ new Set([
|
|
101422
101575
|
WORLD_GRID_CHILDREN_MEMBER_ID,
|
|
@@ -101442,17 +101595,11 @@ var init_animation_clips = __esm({
|
|
|
101442
101595
|
document.members.map((value) => [value.id, value])
|
|
101443
101596
|
);
|
|
101444
101597
|
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
101598
|
}
|
|
101451
101599
|
document;
|
|
101452
101600
|
classById;
|
|
101453
101601
|
memberById;
|
|
101454
101602
|
valueById;
|
|
101455
|
-
storage;
|
|
101456
101603
|
classHasWorldKind(classId, worldKind) {
|
|
101457
101604
|
const visited = /* @__PURE__ */ new Set();
|
|
101458
101605
|
let current = this.classById.get(classId);
|
|
@@ -101528,6 +101675,7 @@ var init_animation_clips = __esm({
|
|
|
101528
101675
|
definitionNode: targetDefinition,
|
|
101529
101676
|
memberPath: [],
|
|
101530
101677
|
storagePath: [],
|
|
101678
|
+
childrenPrefix: [],
|
|
101531
101679
|
visited: /* @__PURE__ */ new Set()
|
|
101532
101680
|
});
|
|
101533
101681
|
}
|
|
@@ -101612,7 +101760,8 @@ var init_animation_clips = __esm({
|
|
|
101612
101760
|
overrideNode: overrides,
|
|
101613
101761
|
definitionNode: child,
|
|
101614
101762
|
memberPath: [`child:${childId}`],
|
|
101615
|
-
storagePath: [
|
|
101763
|
+
storagePath: [],
|
|
101764
|
+
childrenPrefix: args.childStoragePath,
|
|
101616
101765
|
visited: /* @__PURE__ */ new Set()
|
|
101617
101766
|
});
|
|
101618
101767
|
}
|
|
@@ -101955,12 +102104,13 @@ var init_animation_clips = __esm({
|
|
|
101955
102104
|
`${args.label} targets "${boundChildName}.${targetEntry.schemaKey}" of kind ${MemberKind[targetMember.kind]}, but its segment plays ${MemberKind[valueBindingMember.kind]} values.`
|
|
101956
102105
|
);
|
|
101957
102106
|
}
|
|
101958
|
-
if (!this.overrideLeafEligible(
|
|
101959
|
-
|
|
101960
|
-
targetMember.id
|
|
101961
|
-
|
|
102107
|
+
if (!this.overrideLeafEligible(
|
|
102108
|
+
targetMember,
|
|
102109
|
+
[targetMember.id],
|
|
102110
|
+
args.childStoragePath
|
|
102111
|
+
)) {
|
|
101962
102112
|
throw new Error(
|
|
101963
|
-
`${args.label} targets "${boundChildName}.${targetEntry.schemaKey}", which is not a writable Save
|
|
102113
|
+
`${args.label} targets "${boundChildName}.${targetEntry.schemaKey}", which is not a writable Save, Session, or Writable override leaf.`
|
|
101964
102114
|
);
|
|
101965
102115
|
}
|
|
101966
102116
|
}
|
|
@@ -102130,7 +102280,8 @@ var init_animation_clips = __esm({
|
|
|
102130
102280
|
partial: overrideChild.value,
|
|
102131
102281
|
path,
|
|
102132
102282
|
schemaKey,
|
|
102133
|
-
storagePath: args.storagePath
|
|
102283
|
+
storagePath: args.storagePath,
|
|
102284
|
+
childrenPrefix: args.childrenPrefix
|
|
102134
102285
|
});
|
|
102135
102286
|
continue;
|
|
102136
102287
|
}
|
|
@@ -102161,9 +102312,13 @@ var init_animation_clips = __esm({
|
|
|
102161
102312
|
});
|
|
102162
102313
|
continue;
|
|
102163
102314
|
}
|
|
102164
|
-
if (!this.overrideLeafEligible(
|
|
102315
|
+
if (!this.overrideLeafEligible(
|
|
102316
|
+
member,
|
|
102317
|
+
[...args.storagePath, member.id],
|
|
102318
|
+
args.childrenPrefix
|
|
102319
|
+
)) {
|
|
102165
102320
|
throw new Error(
|
|
102166
|
-
`Animation clip "${args.clipName}" frame ${args.frameIndex} member "${path.join(".")}" is not a writable Save
|
|
102321
|
+
`Animation clip "${args.clipName}" frame ${args.frameIndex} member "${path.join(".")}" is not a writable Save, Session, or Writable override leaf.`
|
|
102167
102322
|
);
|
|
102168
102323
|
}
|
|
102169
102324
|
}
|
|
@@ -102198,12 +102353,13 @@ var init_animation_clips = __esm({
|
|
|
102198
102353
|
);
|
|
102199
102354
|
}
|
|
102200
102355
|
const kindLabel = MemberKind[kind];
|
|
102201
|
-
if (!this.overrideLeafEligible(
|
|
102202
|
-
|
|
102203
|
-
args.member.id
|
|
102204
|
-
|
|
102356
|
+
if (!this.overrideLeafEligible(
|
|
102357
|
+
args.member,
|
|
102358
|
+
[...args.storagePath, args.member.id],
|
|
102359
|
+
args.childrenPrefix
|
|
102360
|
+
)) {
|
|
102205
102361
|
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
|
|
102362
|
+
`${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
102363
|
);
|
|
102208
102364
|
}
|
|
102209
102365
|
const violation = structuredLeafPartialViolation(
|
|
@@ -102244,24 +102400,9 @@ var init_animation_clips = __esm({
|
|
|
102244
102400
|
throw new Error(`${descent}; its value is not a ${kindLabel} record.`);
|
|
102245
102401
|
}
|
|
102246
102402
|
}
|
|
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
|
-
}
|
|
102403
|
+
overrideLeafEligible(member, storagePath, childrenPrefix) {
|
|
102404
|
+
if (member.kind === 7 /* Class */) return false;
|
|
102405
|
+
return animationTrackStorage(storagePath, this.memberById, childrenPrefix) !== null;
|
|
102265
102406
|
}
|
|
102266
102407
|
authoredChildren(targetClassId, definitionNode) {
|
|
102267
102408
|
const childEntry = mergeStoredInstanceSchema(
|
|
@@ -102285,9 +102426,8 @@ var init_animation_clips = __esm({
|
|
|
102285
102426
|
(value) => typeof value === "string"
|
|
102286
102427
|
) : []
|
|
102287
102428
|
),
|
|
102288
|
-
//
|
|
102289
|
-
// owner's resolved Children member
|
|
102290
|
-
// storage path instead of treating a shared child-class leaf as a root.
|
|
102429
|
+
// P93 §5: a child track's declaration walk continues through the
|
|
102430
|
+
// owner's resolved Children member, as the authoring pane's does.
|
|
102291
102431
|
storagePath: [childEntry.memberId]
|
|
102292
102432
|
};
|
|
102293
102433
|
}
|
|
@@ -103250,7 +103390,7 @@ function readClass(value) {
|
|
|
103250
103390
|
CLASS_VISIBILITY_KINDS,
|
|
103251
103391
|
`${label} uiVisibility`
|
|
103252
103392
|
);
|
|
103253
|
-
if (value.allowedStorage != null && !
|
|
103393
|
+
if (value.allowedStorage != null && !isClassAllowedStorage(value.allowedStorage)) {
|
|
103254
103394
|
throw new Error(`${label} allowedStorage is invalid.`);
|
|
103255
103395
|
}
|
|
103256
103396
|
if (value.genericParams !== void 0 && value.genericParams !== null) {
|
|
@@ -103632,6 +103772,14 @@ function assertProjectInterfaceDocumentValid(view, options = {}) {
|
|
|
103632
103772
|
const classes = view.classes.map(readClass);
|
|
103633
103773
|
const interfaces = view.interfaces.map(readInterface);
|
|
103634
103774
|
const membersById = new Map(members.map((member) => [member.id, member]));
|
|
103775
|
+
for (const [rootId, stamped] of view.rootStorage ?? []) {
|
|
103776
|
+
const root = membersById.get(rootId);
|
|
103777
|
+
if (root === void 0 || root.storage === stamped) continue;
|
|
103778
|
+
const declared = root.storage === void 0 ? "none" : MemberStorageKind[root.storage];
|
|
103779
|
+
throw new Error(
|
|
103780
|
+
`Project root member "${root.name}" (${rootId}) must declare ${MemberStorageKind[stamped]} storage but declares ${declared}.`
|
|
103781
|
+
);
|
|
103782
|
+
}
|
|
103635
103783
|
const classesById = new Map(
|
|
103636
103784
|
classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
|
|
103637
103785
|
);
|
|
@@ -103751,6 +103899,11 @@ function assertProjectInterfaceDocumentValid(view, options = {}) {
|
|
|
103751
103899
|
`Static member "${member.name}" (${member.id}) must be a plain non-override member.`
|
|
103752
103900
|
);
|
|
103753
103901
|
}
|
|
103902
|
+
if (member.storage === 4 /* Writable */) {
|
|
103903
|
+
throw new Error(
|
|
103904
|
+
`Static member "${member.name}" (${member.id}) cannot declare Writable storage; a static member has no placement parent to resolve it against.`
|
|
103905
|
+
);
|
|
103906
|
+
}
|
|
103754
103907
|
if (member.kind === 21) {
|
|
103755
103908
|
throw new Error(
|
|
103756
103909
|
`Generic placeholder member "${member.name}" (${member.id}) cannot be static.`
|
|
@@ -104055,6 +104208,19 @@ function assertProjectInterfaceDocumentValid(view, options = {}) {
|
|
|
104055
104208
|
if (member.mutability === void 0) delete resolved.mutability;
|
|
104056
104209
|
return resolved;
|
|
104057
104210
|
};
|
|
104211
|
+
const writableAncestor2 = createWritableAncestorLookup(
|
|
104212
|
+
(id2) => membersById.get(id2)
|
|
104213
|
+
);
|
|
104214
|
+
for (const member of members) {
|
|
104215
|
+
if (member.storage !== 1 /* Immutable */ && member.storage !== 0 /* Inherit */) {
|
|
104216
|
+
continue;
|
|
104217
|
+
}
|
|
104218
|
+
const ancestor = writableAncestor2(member);
|
|
104219
|
+
if (ancestor === null) continue;
|
|
104220
|
+
throw new Error(
|
|
104221
|
+
`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.`
|
|
104222
|
+
);
|
|
104223
|
+
}
|
|
104058
104224
|
const rootAndEntryMemberIds = /* @__PURE__ */ new Set();
|
|
104059
104225
|
for (const owner of members) {
|
|
104060
104226
|
if (typeof owner.entryMemberId === "string") {
|
|
@@ -104196,7 +104362,7 @@ function assertProjectInterfaceDocumentValid(view, options = {}) {
|
|
|
104196
104362
|
}
|
|
104197
104363
|
}
|
|
104198
104364
|
if (rawOwned.id === member.id && isAbstractMember(member)) return;
|
|
104199
|
-
if (owned.storage === 2 /* Save */ || owned.storage === 3 /* Session */) {
|
|
104365
|
+
if (owned.storage === 2 /* Save */ || owned.storage === 3 /* Session */ || owned.storage === 4 /* Writable */) {
|
|
104200
104366
|
throw new Error(
|
|
104201
104367
|
`Read-only member "${member.name}" has a non-Immutable owned default child "${owned.name}"; ${ownerLabel}.`
|
|
104202
104368
|
);
|
|
@@ -104727,7 +104893,7 @@ function assertProjectInterfaceDocumentValid(view, options = {}) {
|
|
|
104727
104893
|
return resolved.setterCode === void 0 ? "NSProperty has no setter implementation." : null;
|
|
104728
104894
|
}
|
|
104729
104895
|
const storage = resolved.storage;
|
|
104730
|
-
if (storage === 2 /* Save */ || storage === 3 /* Session */) {
|
|
104896
|
+
if (storage === 2 /* Save */ || storage === 3 /* Session */ || storage === 4 /* Writable */) {
|
|
104731
104897
|
return null;
|
|
104732
104898
|
}
|
|
104733
104899
|
if (storage === 1 /* Immutable */) {
|
|
@@ -106765,6 +106931,14 @@ function assertStagedProjectInterfaceValid(projected, changes) {
|
|
|
106765
106931
|
variants: projected.variants ?? [],
|
|
106766
106932
|
variantFolders: projected.variantFolders ?? [],
|
|
106767
106933
|
interfaces: projected.interfaces,
|
|
106934
|
+
rootStorage: writtenRootStorage(
|
|
106935
|
+
projected.project,
|
|
106936
|
+
new Set(
|
|
106937
|
+
changes.flatMap(
|
|
106938
|
+
(change) => change.recordKind === "member" ? [change.recordId] : []
|
|
106939
|
+
)
|
|
106940
|
+
)
|
|
106941
|
+
),
|
|
106768
106942
|
values: projected.values
|
|
106769
106943
|
},
|
|
106770
106944
|
{
|
|
@@ -107360,6 +107534,7 @@ var init_project_version_whole_graph_validation = __esm({
|
|
|
107360
107534
|
init_core();
|
|
107361
107535
|
init_animation_clips();
|
|
107362
107536
|
init_projectInterfaceValidation();
|
|
107537
|
+
init_project_root_members();
|
|
107363
107538
|
init_project_schema_identifier_validation();
|
|
107364
107539
|
init_packed_value_write_fold();
|
|
107365
107540
|
init_project_version_schema_commit();
|
|
@@ -109487,6 +109662,7 @@ function memberCommon(context, ownerClass, declaration, id2, owner, base) {
|
|
|
109487
109662
|
const storage = annotation(declaration.annotations, "storage");
|
|
109488
109663
|
const distribution = annotation(declaration.annotations, "distribution");
|
|
109489
109664
|
const inheritedId = declaration.modifiers.includes("override") || declaration.modifiers.includes("sealed") ? inheritedMemberId(context, ownerClass, declaration.name) : null;
|
|
109665
|
+
assertWritableStorageRules(context, ownerClass, declaration, inheritedId);
|
|
109490
109666
|
return {
|
|
109491
109667
|
id: id2,
|
|
109492
109668
|
source: sourceIdentity2(declaration, "member", declaration.name),
|
|
@@ -111523,7 +111699,74 @@ function numberArgument(value, name) {
|
|
|
111523
111699
|
}
|
|
111524
111700
|
function storageValue(value, name) {
|
|
111525
111701
|
const enumValue2 = contextualEnumArgument(value, name)?.toLowerCase();
|
|
111526
|
-
return enumValue2 === "immutable" || enumValue2 === "save" || enumValue2 === "session" ? enumValue2 : null;
|
|
111702
|
+
return enumValue2 === "immutable" || enumValue2 === "save" || enumValue2 === "session" || enumValue2 === "writable" ? enumValue2 : null;
|
|
111703
|
+
}
|
|
111704
|
+
function assertWritableStorageRules(context, ownerClass, declaration, inheritedId) {
|
|
111705
|
+
const site = `${ownerClass.name}.${declaration.name}`;
|
|
111706
|
+
const storage = annotation(declaration.annotations, "storage");
|
|
111707
|
+
const declared = storage ? contextualEnumArgument(storage, "allowed")?.toLowerCase() : void 0;
|
|
111708
|
+
if (declared === "writable" && declaration.modifiers.includes("static")) {
|
|
111709
|
+
throw new Error(
|
|
111710
|
+
`Static member ${site} cannot declare Writable storage: a static member has no parent to resolve it against. Declare Save or Session.`
|
|
111711
|
+
);
|
|
111712
|
+
}
|
|
111713
|
+
if (inheritedId === null) return;
|
|
111714
|
+
const ancestor = writableAncestor(context, inheritedId);
|
|
111715
|
+
if (ancestor === null) return;
|
|
111716
|
+
if (declared === "immutable") {
|
|
111717
|
+
throw new Error(
|
|
111718
|
+
`${site} cannot declare Immutable storage because it overrides ${ancestor}, which declares Writable. Declare Writable, Save, or Session, or omit @storage.`
|
|
111719
|
+
);
|
|
111720
|
+
}
|
|
111721
|
+
if (declared === "inherit") {
|
|
111722
|
+
throw new Error(
|
|
111723
|
+
`${site} cannot declare Inherit storage because it overrides ${ancestor}, which declares Writable. Declare Writable, Save, or Session, or omit @storage.`
|
|
111724
|
+
);
|
|
111725
|
+
}
|
|
111726
|
+
}
|
|
111727
|
+
function writableAncestor(context, memberId) {
|
|
111728
|
+
const memo = context.writableAncestors;
|
|
111729
|
+
const chain = /* @__PURE__ */ new Set();
|
|
111730
|
+
let currentId = memberId;
|
|
111731
|
+
let found = null;
|
|
111732
|
+
while (currentId !== null) {
|
|
111733
|
+
const known = memo.get(currentId);
|
|
111734
|
+
if (known !== void 0) {
|
|
111735
|
+
found = known;
|
|
111736
|
+
break;
|
|
111737
|
+
}
|
|
111738
|
+
if (chain.has(currentId)) break;
|
|
111739
|
+
chain.add(currentId);
|
|
111740
|
+
const step = storageChainStep(context, currentId);
|
|
111741
|
+
if (step === null) break;
|
|
111742
|
+
if (step.storage === "writable") {
|
|
111743
|
+
found = step.label;
|
|
111744
|
+
break;
|
|
111745
|
+
}
|
|
111746
|
+
currentId = step.overrideOf;
|
|
111747
|
+
}
|
|
111748
|
+
for (const id2 of chain) memo.set(id2, found);
|
|
111749
|
+
return found;
|
|
111750
|
+
}
|
|
111751
|
+
function storageChainStep(context, memberId) {
|
|
111752
|
+
const sourcePlacement = context.sourceMembersById.get(memberId);
|
|
111753
|
+
if (sourcePlacement !== void 0) {
|
|
111754
|
+
const { ownerClass, member } = sourcePlacement;
|
|
111755
|
+
const storage = annotation(member.annotations, "storage");
|
|
111756
|
+
return {
|
|
111757
|
+
label: `${ownerClass.name}.${member.name}`,
|
|
111758
|
+
storage: storage ? storageValue(storage, "allowed") : null,
|
|
111759
|
+
overrideOf: member.modifiers.includes("override") || member.modifiers.includes("sealed") ? inheritedMemberId(context, ownerClass, member.name) : null
|
|
111760
|
+
};
|
|
111761
|
+
}
|
|
111762
|
+
const persisted = context.baseMembers.get(memberId);
|
|
111763
|
+
if (persisted === void 0) return null;
|
|
111764
|
+
const ownerName = persisted.owner.kind === "classMember" ? context.baseClasses.get(persisted.owner.classId)?.name : void 0;
|
|
111765
|
+
return {
|
|
111766
|
+
label: ownerName === void 0 ? persisted.name : `${ownerName}.${persisted.name}`,
|
|
111767
|
+
storage: persisted.storage,
|
|
111768
|
+
overrideOf: persisted.overrideOf
|
|
111769
|
+
};
|
|
111527
111770
|
}
|
|
111528
111771
|
function referenceIdArgument(value, name) {
|
|
111529
111772
|
const raw = argument(value, name);
|
|
@@ -112503,6 +112746,7 @@ function lowerProjectSchemaV4(base, analysis, options = {}) {
|
|
|
112503
112746
|
enumOptionsByName,
|
|
112504
112747
|
loweredMembers: /* @__PURE__ */ new Map(),
|
|
112505
112748
|
entryTypesByEntryId: /* @__PURE__ */ new Map(),
|
|
112749
|
+
writableAncestors: /* @__PURE__ */ new Map(),
|
|
112506
112750
|
placements: /* @__PURE__ */ new Map(),
|
|
112507
112751
|
staticValueIdsBySymbol: staticValueIdsBySymbol3,
|
|
112508
112752
|
settleInitializerReferences: createSchemaInitializerReferenceSettlerV4({
|
|
@@ -139241,7 +139485,7 @@ var init_registry2 = __esm({
|
|
|
139241
139485
|
"schema-contract/registry.mjs"() {
|
|
139242
139486
|
"use strict";
|
|
139243
139487
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
139244
|
-
cliVersion: "0.
|
|
139488
|
+
cliVersion: "0.56.0",
|
|
139245
139489
|
projectFileUploadBatchSize: 32,
|
|
139246
139490
|
documentRecords: {
|
|
139247
139491
|
member: {
|
|
@@ -139583,8 +139827,8 @@ var init_registry2 = __esm({
|
|
|
139583
139827
|
sdkDeclarations: {
|
|
139584
139828
|
attributes: {
|
|
139585
139829
|
enums: {
|
|
139586
|
-
NeoStorage: ["Inherit", "Immutable", "Save", "Session"],
|
|
139587
|
-
NeoAllowedStorage: ["Any", "Immutable", "Save", "Session"],
|
|
139830
|
+
NeoStorage: ["Inherit", "Immutable", "Save", "Session", "Writable"],
|
|
139831
|
+
NeoAllowedStorage: ["Any", "Immutable", "Save", "Session", "Writable"],
|
|
139588
139832
|
NeoListKind: ["Ordered", "Unordered"],
|
|
139589
139833
|
NeoDictionaryKeyKind: ["String", "Enum"],
|
|
139590
139834
|
NeoClassVisibility: ["Visible", "Hidden"],
|
|
@@ -147062,7 +147306,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
|
|
|
147062
147306
|
async function main() {
|
|
147063
147307
|
const args = parseArgs(process.argv.slice(2));
|
|
147064
147308
|
if (args.command === "--version") {
|
|
147065
|
-
console.log("0.
|
|
147309
|
+
console.log("0.56.0");
|
|
147066
147310
|
return;
|
|
147067
147311
|
}
|
|
147068
147312
|
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.0 -->
|
|
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
|