@neocompose/cli 0.21.2 → 0.21.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/dist/neo.mjs +391 -85
- package/package.json +1 -1
- package/skills/neocompose-cli/SKILL.md +1 -1
- package/skills/neocompose-cli/references/animation-and-world-authoring.md +3 -0
- package/skills/neocompose-cli/references/cli-development.md +1 -1
- package/skills/neocompose-cli/references/commands-and-sync.md +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.21.4] - 2026-08-03
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- `neo pull --reset` emits the canonical `SpriteInfo.Empty` spelling for the
|
|
8
|
+
required empty-sprite sentinel and does not mistake its empty file id for a
|
|
9
|
+
missing project file.
|
|
10
|
+
- Parameterized declaration templates compile with their class-header scope
|
|
11
|
+
without being evaluated before a concrete invocation supplies arguments.
|
|
12
|
+
- Canonical lowering reuses persisted generic argument identities, so a fresh
|
|
13
|
+
reset remains a semantic no-op instead of creating replacement binding rows.
|
|
14
|
+
|
|
15
|
+
## [0.21.3] - 2026-08-03
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- `neo push` paints its preparation spinner before workspace discovery,
|
|
20
|
+
lowering, and NeoScript compilation begin, so large projects no longer look
|
|
21
|
+
stalled before the push plan appears.
|
|
22
|
+
- Animation segment frame values are emitted through the required `value`
|
|
23
|
+
constructor argument. Required sprites use the canonical `SpriteInfo.Empty`
|
|
24
|
+
value; `null` is reserved for nullable `SpriteInfo?` values.
|
|
25
|
+
|
|
3
26
|
## [0.21.2] - 2026-08-03
|
|
4
27
|
|
|
5
28
|
### Fixed
|
package/dist/neo.mjs
CHANGED
|
@@ -842,7 +842,7 @@ function vectorTypes() {
|
|
|
842
842
|
members: structuredLeafFieldProperties(name)
|
|
843
843
|
}));
|
|
844
844
|
}
|
|
845
|
-
var NEOSCRIPT_KEYWORDS, NEOSCRIPT_INFERRED_LOCAL_KEYWORD, NEOSCRIPT_CONSTRUCTOR_KEYWORD, NEOSCRIPT_PRIMITIVE_TYPES, NEOSCRIPT_BUILTIN_TYPES, NEOSCRIPT_OPERATORS, NEOSCRIPT_STATEMENT_SNIPPETS, STRING_TYPE, INT_TYPE, FLOAT_TYPE, BOOL_TYPE, IMAGE_REF_TYPE, FLOAT_OPTIONAL_TYPE, NEOSCRIPT_STRUCTURED_LEAF_FIELDS, NEOSCRIPT_IMAGE_REGISTRY_TYPE, NEOSCRIPT_AUDIO_CLIP_REGISTRY_TYPE, NEOSCRIPT_PENDING_SYMBOL_ID_PREFIX, REGISTRY_ENTRY_TYPES, NEOSCRIPT_GLOBALS, NEOSCRIPT_BUILTIN_TYPE_SYMBOLS;
|
|
845
|
+
var NEOSCRIPT_KEYWORDS, NEOSCRIPT_INFERRED_LOCAL_KEYWORD, NEOSCRIPT_CONSTRUCTOR_KEYWORD, NEOSCRIPT_PRIMITIVE_TYPES, NEOSCRIPT_BUILTIN_TYPES, NEOSCRIPT_OPERATORS, NEOSCRIPT_STATEMENT_SNIPPETS, STRING_TYPE, INT_TYPE, FLOAT_TYPE, BOOL_TYPE, IMAGE_REF_TYPE, SPRITE_INFO_TYPE, FLOAT_OPTIONAL_TYPE, NEOSCRIPT_STRUCTURED_LEAF_FIELDS, NEOSCRIPT_IMAGE_REGISTRY_TYPE, NEOSCRIPT_AUDIO_CLIP_REGISTRY_TYPE, NEOSCRIPT_PENDING_SYMBOL_ID_PREFIX, REGISTRY_ENTRY_TYPES, NEOSCRIPT_GLOBALS, NEOSCRIPT_SPRITE_INFO_EMPTY_MEMBER_ID, NEOSCRIPT_SPRITE_INFO_EMPTY_VALUE, NEOSCRIPT_BUILTIN_TYPE_SYMBOLS;
|
|
846
846
|
var init_language_spec = __esm({
|
|
847
847
|
"../packages/neoscript-language/src/language-spec.ts"() {
|
|
848
848
|
"use strict";
|
|
@@ -1006,6 +1006,10 @@ var init_language_spec = __esm({
|
|
|
1006
1006
|
kind: "primitive",
|
|
1007
1007
|
name: "ImageRef"
|
|
1008
1008
|
};
|
|
1009
|
+
SPRITE_INFO_TYPE = {
|
|
1010
|
+
kind: "primitive",
|
|
1011
|
+
name: "SpriteInfo"
|
|
1012
|
+
};
|
|
1009
1013
|
FLOAT_OPTIONAL_TYPE = {
|
|
1010
1014
|
kind: "primitive",
|
|
1011
1015
|
name: "float",
|
|
@@ -1148,12 +1152,26 @@ var init_language_spec = __esm({
|
|
|
1148
1152
|
"Returns whether a dialogue pointer has been visited."
|
|
1149
1153
|
)
|
|
1150
1154
|
];
|
|
1155
|
+
NEOSCRIPT_SPRITE_INFO_EMPTY_MEMBER_ID = "builtin:SpriteInfo:property:Empty";
|
|
1156
|
+
NEOSCRIPT_SPRITE_INFO_EMPTY_VALUE = Object.freeze({
|
|
1157
|
+
fileId: "",
|
|
1158
|
+
sliceIndex: 0
|
|
1159
|
+
});
|
|
1151
1160
|
NEOSCRIPT_BUILTIN_TYPE_SYMBOLS = [
|
|
1152
1161
|
{
|
|
1153
1162
|
id: "builtin:SpriteInfo",
|
|
1154
1163
|
name: "SpriteInfo",
|
|
1155
1164
|
kind: "builtin",
|
|
1156
1165
|
members: [
|
|
1166
|
+
{
|
|
1167
|
+
...property(
|
|
1168
|
+
"SpriteInfo",
|
|
1169
|
+
"Empty",
|
|
1170
|
+
SPRITE_INFO_TYPE,
|
|
1171
|
+
"An authored empty sprite at slice zero."
|
|
1172
|
+
),
|
|
1173
|
+
static: true
|
|
1174
|
+
},
|
|
1157
1175
|
// `FileId` and `SliceIndex` come from the field table above — they are
|
|
1158
1176
|
// the writable, addressable fields, not derived properties (D11).
|
|
1159
1177
|
...structuredLeafFieldProperties("SpriteInfo"),
|
|
@@ -9027,7 +9045,8 @@ var init_strict_resolver = __esm({
|
|
|
9027
9045
|
);
|
|
9028
9046
|
case "call":
|
|
9029
9047
|
if (expression.callee.kind === "ident" && expression.callee.name === "Reference" && Array.isArray(expression.typeArguments)) {
|
|
9030
|
-
|
|
9048
|
+
const [referenceTypeArgument] = expression.typeArguments;
|
|
9049
|
+
if (expression.typeArguments.length !== 1 || referenceTypeArgument === void 0) {
|
|
9031
9050
|
throw new CompileError(
|
|
9032
9051
|
"Reference requires exactly one generic target type.",
|
|
9033
9052
|
expression.pos
|
|
@@ -9039,7 +9058,7 @@ var init_strict_resolver = __esm({
|
|
|
9039
9058
|
expression.pos
|
|
9040
9059
|
);
|
|
9041
9060
|
}
|
|
9042
|
-
const referencedType = this.resolveType(
|
|
9061
|
+
const referencedType = this.resolveType(referenceTypeArgument);
|
|
9043
9062
|
if (expected !== void 0 && !isNeoScriptTypeAssignable(referencedType, expected, this.project)) {
|
|
9044
9063
|
throw new CompileError(
|
|
9045
9064
|
`Reference target ${this.describe(referencedType)} is not assignable to ${this.describe(expected)}.`,
|
|
@@ -9093,7 +9112,7 @@ var init_strict_resolver = __esm({
|
|
|
9093
9112
|
if (requiredConstructor === null && !callMatchesDeclaredOverloadNames(declared, expression)) {
|
|
9094
9113
|
this.rejectConstructorProjectionInConstructionBody(expression);
|
|
9095
9114
|
}
|
|
9096
|
-
const projectionCall = requiredConstructor === null && expression.argumentNames === void 0 && callHasPositionalArguments(expression) && declaredTarget
|
|
9115
|
+
const projectionCall = requiredConstructor === null && declaredTarget?.constructorSignature !== void 0 && (expression.argumentNames === void 0 && callHasPositionalArguments(expression) || expression.argumentNames !== void 0 && declaredTarget.constructorSignature.namedProjections !== void 0);
|
|
9097
9116
|
if (declared.length > 0 && !projectionCall) {
|
|
9098
9117
|
return this.resolveDeclaredConstructor(
|
|
9099
9118
|
className,
|
|
@@ -9102,13 +9121,13 @@ var init_strict_resolver = __esm({
|
|
|
9102
9121
|
expression.pos
|
|
9103
9122
|
);
|
|
9104
9123
|
}
|
|
9105
|
-
if (expression.argumentNames) {
|
|
9124
|
+
if (expression.argumentNames && !projectionCall) {
|
|
9106
9125
|
throw new CompileError(
|
|
9107
9126
|
"Named constructor arguments require a declaration-aware project source context.",
|
|
9108
9127
|
expression.pos
|
|
9109
9128
|
);
|
|
9110
9129
|
}
|
|
9111
|
-
if (expression.initializer && expression.initializer.length > 0) {
|
|
9130
|
+
if (expression.initializer && expression.initializer.length > 0 && !projectionCall) {
|
|
9112
9131
|
throw new CompileError(
|
|
9113
9132
|
"Object initializers are available to project source construction and are not executable NeoScript constructors.",
|
|
9114
9133
|
expression.pos
|
|
@@ -9116,9 +9135,10 @@ var init_strict_resolver = __esm({
|
|
|
9116
9135
|
}
|
|
9117
9136
|
return this.resolveClassConstructor(
|
|
9118
9137
|
className,
|
|
9119
|
-
expression
|
|
9138
|
+
expression,
|
|
9120
9139
|
scope,
|
|
9121
|
-
expression.pos
|
|
9140
|
+
expression.pos,
|
|
9141
|
+
expected
|
|
9122
9142
|
);
|
|
9123
9143
|
}
|
|
9124
9144
|
case "annotated":
|
|
@@ -9739,6 +9759,12 @@ var init_strict_resolver = __esm({
|
|
|
9739
9759
|
}
|
|
9740
9760
|
resolveMemberNatural(receiverAst, name, scope, pos, optional) {
|
|
9741
9761
|
if (receiverAst.kind === "ident" && !scope.lookup(receiverAst.name)) {
|
|
9762
|
+
if (receiverAst.name === "SpriteInfo" && name === "Empty") {
|
|
9763
|
+
return literal(
|
|
9764
|
+
{ kind: "primitive", name: "SpriteInfo" },
|
|
9765
|
+
{ ...NEOSCRIPT_SPRITE_INFO_EMPTY_VALUE }
|
|
9766
|
+
);
|
|
9767
|
+
}
|
|
9742
9768
|
const staticType = this.project.typeByName.get(receiverAst.name);
|
|
9743
9769
|
if (staticType && staticType.kind !== "enum") {
|
|
9744
9770
|
if (optional) {
|
|
@@ -9769,6 +9795,11 @@ var init_strict_resolver = __esm({
|
|
|
9769
9795
|
pos
|
|
9770
9796
|
);
|
|
9771
9797
|
}
|
|
9798
|
+
if (member.id === NEOSCRIPT_SPRITE_INFO_EMPTY_MEMBER_ID) {
|
|
9799
|
+
return literal(member.type, {
|
|
9800
|
+
...NEOSCRIPT_SPRITE_INFO_EMPTY_VALUE
|
|
9801
|
+
});
|
|
9802
|
+
}
|
|
9772
9803
|
if (member.computed === true) {
|
|
9773
9804
|
return {
|
|
9774
9805
|
pointer: {
|
|
@@ -10515,7 +10546,7 @@ var init_strict_resolver = __esm({
|
|
|
10515
10546
|
type: optional ? { ...delegateType.returnType, nullable: true } : delegateType.returnType
|
|
10516
10547
|
};
|
|
10517
10548
|
}
|
|
10518
|
-
resolveClassConstructor(className,
|
|
10549
|
+
resolveClassConstructor(className, expression, scope, pos, expected) {
|
|
10519
10550
|
const schemaClass2 = this.project.typeByName.get(className);
|
|
10520
10551
|
if (!schemaClass2 || schemaClass2.kind !== "class") {
|
|
10521
10552
|
throw new CompileError(
|
|
@@ -10537,26 +10568,86 @@ var init_strict_resolver = __esm({
|
|
|
10537
10568
|
pos
|
|
10538
10569
|
);
|
|
10539
10570
|
}
|
|
10571
|
+
const targetType = this.constructorTargetType(
|
|
10572
|
+
schemaClass2,
|
|
10573
|
+
expression,
|
|
10574
|
+
expected
|
|
10575
|
+
);
|
|
10576
|
+
const parameters = signature.parameters.map((parameter3) => ({
|
|
10577
|
+
...parameter3,
|
|
10578
|
+
valueType: substituteTypeParameters(
|
|
10579
|
+
parameter3.valueType,
|
|
10580
|
+
targetType,
|
|
10581
|
+
schemaClass2
|
|
10582
|
+
),
|
|
10583
|
+
parameterType: substituteTypeParameters(
|
|
10584
|
+
parameter3.parameterType,
|
|
10585
|
+
targetType,
|
|
10586
|
+
schemaClass2
|
|
10587
|
+
)
|
|
10588
|
+
}));
|
|
10589
|
+
const argumentsList2 = expression.args;
|
|
10590
|
+
const namedProjections = signature.namedProjections;
|
|
10591
|
+
if (expression.argumentNames !== void 0) {
|
|
10592
|
+
if (namedProjections === void 0) {
|
|
10593
|
+
throw new CompileError(
|
|
10594
|
+
`Class '${className}' exposes no named constructor projection.`,
|
|
10595
|
+
pos
|
|
10596
|
+
);
|
|
10597
|
+
}
|
|
10598
|
+
if (argumentsList2.length !== namedProjections.length) {
|
|
10599
|
+
throw new CompileError(
|
|
10600
|
+
`${className} constructor requires ${namedProjections.length} named argument${namedProjections.length === 1 ? "" : "s"} but got ${argumentsList2.length}.`,
|
|
10601
|
+
pos
|
|
10602
|
+
);
|
|
10603
|
+
}
|
|
10604
|
+
if (expression.argumentNames.length !== argumentsList2.length) {
|
|
10605
|
+
throw new CompileError(
|
|
10606
|
+
`${className} constructor projection requires every argument to be named.`,
|
|
10607
|
+
pos
|
|
10608
|
+
);
|
|
10609
|
+
}
|
|
10610
|
+
}
|
|
10540
10611
|
const requiredCount = signature.parameters.filter(
|
|
10541
10612
|
(parameter3) => parameter3.required
|
|
10542
10613
|
).length;
|
|
10543
|
-
if (argumentsList2.length < requiredCount) {
|
|
10614
|
+
if (expression.argumentNames === void 0 && argumentsList2.length < requiredCount) {
|
|
10544
10615
|
throw new CompileError(
|
|
10545
10616
|
`${className} constructor requires ${requiredCount} argument${requiredCount === 1 ? "" : "s"} but got ${argumentsList2.length}.`,
|
|
10546
10617
|
pos
|
|
10547
10618
|
);
|
|
10548
10619
|
}
|
|
10549
|
-
if (argumentsList2.length >
|
|
10620
|
+
if (expression.argumentNames === void 0 && argumentsList2.length > parameters.length) {
|
|
10550
10621
|
throw new CompileError(
|
|
10551
|
-
`${className} constructor accepts at most ${
|
|
10622
|
+
`${className} constructor accepts at most ${parameters.length} argument${parameters.length === 1 ? "" : "s"} but got ${argumentsList2.length}.`,
|
|
10552
10623
|
pos
|
|
10553
10624
|
);
|
|
10554
10625
|
}
|
|
10555
10626
|
const fields = argumentsList2.map((argument2, index) => {
|
|
10556
|
-
const
|
|
10627
|
+
const projectionName = expression.argumentNames?.[index];
|
|
10628
|
+
const projection = projectionName === void 0 ? void 0 : namedProjections?.find(
|
|
10629
|
+
(candidate) => candidate.name === projectionName
|
|
10630
|
+
);
|
|
10631
|
+
if (projectionName !== void 0 && projection === void 0) {
|
|
10632
|
+
throw new CompileError(
|
|
10633
|
+
`Class '${className}' has no constructor projection named '${projectionName}'.`,
|
|
10634
|
+
argument2.pos
|
|
10635
|
+
);
|
|
10636
|
+
}
|
|
10637
|
+
if (projection !== void 0 && expression.argumentNames?.findIndex(
|
|
10638
|
+
(candidate) => candidate === projection.name
|
|
10639
|
+
) !== index) {
|
|
10640
|
+
throw new CompileError(
|
|
10641
|
+
`Constructor argument '${projection.name}' is supplied more than once.`,
|
|
10642
|
+
argument2.pos
|
|
10643
|
+
);
|
|
10644
|
+
}
|
|
10645
|
+
const parameter3 = projection === void 0 ? parameters[index] : parameters.find(
|
|
10646
|
+
(candidate) => candidate.memberId === projection.memberId
|
|
10647
|
+
);
|
|
10557
10648
|
if (!parameter3) {
|
|
10558
10649
|
throw new Error(
|
|
10559
|
-
`NeoScript constructor ${className} lost parameter ${index + 1} after argument-count validation.`
|
|
10650
|
+
projection === void 0 ? `NeoScript constructor ${className} lost parameter ${index + 1} after argument-count validation.` : `NeoScript constructor ${className} projection '${projection.name}' names missing member '${projection.memberId}'.`
|
|
10560
10651
|
);
|
|
10561
10652
|
}
|
|
10562
10653
|
const value = this.resolveExpression(
|
|
@@ -10576,7 +10667,20 @@ var init_strict_resolver = __esm({
|
|
|
10576
10667
|
valuePointer: value.pointer
|
|
10577
10668
|
};
|
|
10578
10669
|
});
|
|
10579
|
-
|
|
10670
|
+
if (namedProjections !== void 0 && expression.argumentNames !== void 0) {
|
|
10671
|
+
for (const projection of namedProjections) {
|
|
10672
|
+
if (!expression.argumentNames.includes(projection.name)) {
|
|
10673
|
+
throw new CompileError(
|
|
10674
|
+
`${className} constructor is missing named argument '${projection.name}'.`,
|
|
10675
|
+
pos
|
|
10676
|
+
);
|
|
10677
|
+
}
|
|
10678
|
+
}
|
|
10679
|
+
}
|
|
10680
|
+
fields.push(
|
|
10681
|
+
...this.resolveCallSiteInitializerFields(schemaClass2, expression, scope)
|
|
10682
|
+
);
|
|
10683
|
+
const schemaClassInfo = toWireType(targetType, this.project);
|
|
10580
10684
|
if (schemaClassInfo.type !== 7 /* Class */) {
|
|
10581
10685
|
throw new Error(
|
|
10582
10686
|
`NeoScript constructor ${className} has non-Class return type ${this.describe(signature.returnType)}.`
|
|
@@ -10590,10 +10694,35 @@ var init_strict_resolver = __esm({
|
|
|
10590
10694
|
info: { schemaClassInfo, fields }
|
|
10591
10695
|
}
|
|
10592
10696
|
},
|
|
10593
|
-
type: { ...
|
|
10697
|
+
type: { ...targetType, nullable: false },
|
|
10594
10698
|
writability: "session" /* Session */
|
|
10595
10699
|
};
|
|
10596
10700
|
}
|
|
10701
|
+
constructorTargetType(schemaClass2, expression, expected) {
|
|
10702
|
+
const typeArguments = expression.typeArguments?.map(
|
|
10703
|
+
(argument2) => this.resolveType(argument2)
|
|
10704
|
+
);
|
|
10705
|
+
if (typeArguments !== void 0 && typeArguments.length !== (schemaClass2.typeParameters?.length ?? 0)) {
|
|
10706
|
+
throw new CompileError(
|
|
10707
|
+
`Class '${schemaClass2.name}' expects ${schemaClass2.typeParameters?.length ?? 0} type argument${schemaClass2.typeParameters?.length === 1 ? "" : "s"} but got ${typeArguments.length}.`,
|
|
10708
|
+
expression.pos
|
|
10709
|
+
);
|
|
10710
|
+
}
|
|
10711
|
+
if (typeArguments !== void 0) {
|
|
10712
|
+
return {
|
|
10713
|
+
kind: "named",
|
|
10714
|
+
typeId: schemaClass2.id,
|
|
10715
|
+
typeArguments
|
|
10716
|
+
};
|
|
10717
|
+
}
|
|
10718
|
+
if (expected?.kind === "named" && expected.typeId === schemaClass2.id) {
|
|
10719
|
+
return { ...expected, nullable: false };
|
|
10720
|
+
}
|
|
10721
|
+
return {
|
|
10722
|
+
kind: "named",
|
|
10723
|
+
typeId: schemaClass2.id
|
|
10724
|
+
};
|
|
10725
|
+
}
|
|
10597
10726
|
/**
|
|
10598
10727
|
* P43 §7.1. P29's `new T(id: "…")` projection names a class-default row,
|
|
10599
10728
|
* which is exactly the wrong identity inside a construction body: member
|
|
@@ -38004,10 +38133,10 @@ function isSpriteValue(value) {
|
|
|
38004
38133
|
if (!Number.isInteger(sliceIndex)) return false;
|
|
38005
38134
|
return sliceIndex >= 0;
|
|
38006
38135
|
}
|
|
38007
|
-
function
|
|
38136
|
+
function emptySpriteValue() {
|
|
38008
38137
|
return { fileId: "", sliceIndex: 0 };
|
|
38009
38138
|
}
|
|
38010
|
-
function
|
|
38139
|
+
function isEmptySpriteValue(value) {
|
|
38011
38140
|
if (!value || typeof value !== "object") return false;
|
|
38012
38141
|
return getField(value, "fileId") === "" && getField(value, "sliceIndex") === 0;
|
|
38013
38142
|
}
|
|
@@ -38910,6 +39039,7 @@ var init_world_system_classes_generated = __esm({
|
|
|
38910
39039
|
{
|
|
38911
39040
|
memberId: "system_cbd6db9a-f473-44b5-b913-7cdc06452f35",
|
|
38912
39041
|
memberKind: "sprite",
|
|
39042
|
+
defaultValue: { fileId: "", sliceIndex: 0 },
|
|
38913
39043
|
required: true,
|
|
38914
39044
|
schemaKey: "Sprite"
|
|
38915
39045
|
},
|
|
@@ -39032,6 +39162,7 @@ var init_world_system_classes_generated = __esm({
|
|
|
39032
39162
|
{
|
|
39033
39163
|
memberId: "system_e9288ba9-f5a2-4485-8443-6afb155b31e0",
|
|
39034
39164
|
memberKind: "sprite",
|
|
39165
|
+
defaultValue: { fileId: "", sliceIndex: 0 },
|
|
39035
39166
|
required: true,
|
|
39036
39167
|
schemaKey: "Sprite"
|
|
39037
39168
|
},
|
|
@@ -39516,6 +39647,12 @@ var init_world_system_classes_generated = __esm({
|
|
|
39516
39647
|
docsText: "One value at a frame index inside a segment. It holds until the next row\nyou author, or until the segment's Duration runs out.",
|
|
39517
39648
|
extendsWorldKind: "animationFrameBase",
|
|
39518
39649
|
isAbstract: false,
|
|
39650
|
+
constructorProjections: [
|
|
39651
|
+
{
|
|
39652
|
+
memberId: "system_b71d1f73-da72-49de-ab9a-911cc9bffa43",
|
|
39653
|
+
parameterName: "value"
|
|
39654
|
+
}
|
|
39655
|
+
],
|
|
39519
39656
|
genericParams: [
|
|
39520
39657
|
{ id: "system_887b11d3-e56a-47ff-8d01-e2fcefb846a1", name: "T" }
|
|
39521
39658
|
],
|
|
@@ -42586,7 +42723,7 @@ function stampGenericBindings(value, member, args) {
|
|
|
42586
42723
|
}
|
|
42587
42724
|
function shouldSkipRequiredChildDefault(member) {
|
|
42588
42725
|
if (member.defaultValue !== void 0) return false;
|
|
42589
|
-
return
|
|
42726
|
+
return isMemberAudioBase(member);
|
|
42590
42727
|
}
|
|
42591
42728
|
function shouldMaterializeChildDefault(member) {
|
|
42592
42729
|
if (isMemberClassBase(member) && member.partial === true) return false;
|
|
@@ -42658,7 +42795,7 @@ function primitiveFallbackValue(document, member) {
|
|
|
42658
42795
|
if (isMemberLookupBase(member)) return { value: [] };
|
|
42659
42796
|
if (isMemberDialogueLookupBase(member)) return { value: [] };
|
|
42660
42797
|
if (isMemberSpriteBase(member)) {
|
|
42661
|
-
return { value:
|
|
42798
|
+
return { value: emptySpriteValue() };
|
|
42662
42799
|
}
|
|
42663
42800
|
if (isMemberAudioBase(member)) {
|
|
42664
42801
|
return { value: pendingAudioValue() };
|
|
@@ -42682,7 +42819,7 @@ function primitiveFallbackValue(document, member) {
|
|
|
42682
42819
|
function isPendingFileMemberValue(member, body) {
|
|
42683
42820
|
const value = body.value;
|
|
42684
42821
|
if (isMemberSpriteBase(member)) {
|
|
42685
|
-
return
|
|
42822
|
+
return isEmptySpriteValue(value);
|
|
42686
42823
|
}
|
|
42687
42824
|
if (isMemberAudioBase(member)) {
|
|
42688
42825
|
return isPendingAudioValue(value);
|
|
@@ -42768,11 +42905,18 @@ function validateDecimalMemberValue(member, body) {
|
|
|
42768
42905
|
}
|
|
42769
42906
|
function validateSpriteMemberValue(document, member, body) {
|
|
42770
42907
|
const spriteValue = body.value;
|
|
42908
|
+
if (spriteValue === null) {
|
|
42909
|
+
if (!member.required) return;
|
|
42910
|
+
throw new Error(
|
|
42911
|
+
`Sprite member "${member.name}" is required and cannot be null.`
|
|
42912
|
+
);
|
|
42913
|
+
}
|
|
42771
42914
|
if (!isSpriteValue(spriteValue)) {
|
|
42772
42915
|
throw new Error(
|
|
42773
42916
|
"Sprite value must be { fileId: string, sliceIndex: integer >= 0 }."
|
|
42774
42917
|
);
|
|
42775
42918
|
}
|
|
42919
|
+
if (isEmptySpriteValue(spriteValue)) return;
|
|
42776
42920
|
validateSpriteFileRegistration(document, member, spriteValue.fileId);
|
|
42777
42921
|
}
|
|
42778
42922
|
function validateSpriteFileRegistration(document, member, fileId) {
|
|
@@ -44456,7 +44600,13 @@ function lowerFieldMember(context, ownerClass, declaration, id2, commonInput, ba
|
|
|
44456
44600
|
classId,
|
|
44457
44601
|
...partial ? { partial: true } : {},
|
|
44458
44602
|
schemaKeyOrder: base?.kind === "class" ? base.schemaKeyOrder : null,
|
|
44459
|
-
classArguments: lowerClassArguments(
|
|
44603
|
+
classArguments: lowerClassArguments(
|
|
44604
|
+
context,
|
|
44605
|
+
ownerClass,
|
|
44606
|
+
id2,
|
|
44607
|
+
fieldType,
|
|
44608
|
+
base?.kind === "class" ? base.classArguments : void 0
|
|
44609
|
+
)
|
|
44460
44610
|
};
|
|
44461
44611
|
}
|
|
44462
44612
|
throw new Error(
|
|
@@ -44993,6 +45143,9 @@ function lowerExpressionValue(context, expression, declaredExpected, ownerClass,
|
|
|
44993
45143
|
}
|
|
44994
45144
|
switch (expression.kind) {
|
|
44995
45145
|
case "litNull":
|
|
45146
|
+
if (!expected.nullable) {
|
|
45147
|
+
throw new Error(`Required value ${path} cannot be null.`);
|
|
45148
|
+
}
|
|
44996
45149
|
return null;
|
|
44997
45150
|
case "litBool":
|
|
44998
45151
|
case "litString":
|
|
@@ -45212,6 +45365,9 @@ function lowerExpressionValue(context, expression, declaredExpected, ownerClass,
|
|
|
45212
45365
|
);
|
|
45213
45366
|
}
|
|
45214
45367
|
case "member": {
|
|
45368
|
+
if (expected.name === "SpriteInfo" && expression.name === "Empty" && expression.receiver.kind === "ident" && expression.receiver.name === "SpriteInfo") {
|
|
45369
|
+
return { fileId: "", sliceIndex: 0 };
|
|
45370
|
+
}
|
|
45215
45371
|
const fileId = projectFileIdForPath(context, expression);
|
|
45216
45372
|
if (fileId !== null) return { fileId };
|
|
45217
45373
|
if (expression.name === "Slice" || expression.receiver.kind === "call") {
|
|
@@ -45525,7 +45681,7 @@ function genericParameterName(context, genericParamId) {
|
|
|
45525
45681
|
}
|
|
45526
45682
|
return "object";
|
|
45527
45683
|
}
|
|
45528
|
-
function lowerClassArguments(context, ownerClass, ownerMemberId, type) {
|
|
45684
|
+
function lowerClassArguments(context, ownerClass, ownerMemberId, type, baseArguments) {
|
|
45529
45685
|
const classId = context.classIdsByName.get(type.name);
|
|
45530
45686
|
if (!classId) return {};
|
|
45531
45687
|
const parameters = [
|
|
@@ -45541,7 +45697,8 @@ function lowerClassArguments(context, ownerClass, ownerMemberId, type) {
|
|
|
45541
45697
|
result[parameterId] = { kind: "generic", genericParamId: ownerParameter };
|
|
45542
45698
|
continue;
|
|
45543
45699
|
}
|
|
45544
|
-
const
|
|
45700
|
+
const baseBinding = baseArguments?.[parameterId];
|
|
45701
|
+
const memberId = baseBinding?.kind === "member" ? baseBinding.memberId : derivedGenericArgumentMemberId(ownerMemberId, parameterId);
|
|
45545
45702
|
result[parameterId] = { kind: "member", memberId };
|
|
45546
45703
|
lowerGenericArgument(
|
|
45547
45704
|
context,
|
|
@@ -45561,6 +45718,7 @@ function lowerExtendsBindings(context, declaration, baseClassId, argumentsValue)
|
|
|
45561
45718
|
];
|
|
45562
45719
|
const result = {};
|
|
45563
45720
|
const declarationId = materializedId(declaration, "class", declaration.name);
|
|
45721
|
+
const baseBindings = context.baseClasses.get(declarationId)?.extendsGenericBindings ?? {};
|
|
45564
45722
|
for (const [[parameterName, parameterId], argumentType] of zip(
|
|
45565
45723
|
parameters,
|
|
45566
45724
|
argumentsValue
|
|
@@ -45570,7 +45728,8 @@ function lowerExtendsBindings(context, declaration, baseClassId, argumentsValue)
|
|
|
45570
45728
|
result[parameterId] = { kind: "generic", genericParamId: local };
|
|
45571
45729
|
continue;
|
|
45572
45730
|
}
|
|
45573
|
-
const
|
|
45731
|
+
const baseBinding = baseBindings[parameterId];
|
|
45732
|
+
const memberId = baseBinding?.kind === "member" ? baseBinding.memberId : derivedGenericArgumentMemberId(declarationId, parameterId);
|
|
45574
45733
|
result[parameterId] = { kind: "member", memberId };
|
|
45575
45734
|
lowerGenericArgument(
|
|
45576
45735
|
context,
|
|
@@ -47596,6 +47755,15 @@ function renderDefaultValue(context, member, wrapper) {
|
|
|
47596
47755
|
`${member.kind === "sprite" ? "Sprite" : "Audio"} member ${JSON.stringify(member.name)} default stores a file value with no fileId. Emitting it as null would delete the default on the next push.`
|
|
47597
47756
|
);
|
|
47598
47757
|
}
|
|
47758
|
+
if (value.fileId.length === 0) {
|
|
47759
|
+
const sliceIndex = typeof value.sliceIndex === "number" ? value.sliceIndex : 0;
|
|
47760
|
+
if (member.kind === "sprite" && sliceIndex === 0) {
|
|
47761
|
+
return "SpriteInfo.Empty";
|
|
47762
|
+
}
|
|
47763
|
+
throw new Error(
|
|
47764
|
+
`${member.kind === "sprite" ? "Sprite" : "Audio"} member ${JSON.stringify(member.name)} default stores an invalid empty file value.`
|
|
47765
|
+
);
|
|
47766
|
+
}
|
|
47599
47767
|
const symbol = context.fileSymbols.get(value.fileId);
|
|
47600
47768
|
const target = symbol ?? (member.kind === "sprite" ? `Reference<NeoImage>(id: ${quote(value.fileId)})` : `Reference<NeoAudioClip>(id: ${quote(value.fileId)})`);
|
|
47601
47769
|
return member.kind === "sprite" ? `${target}.Slice(${typeof value.sliceIndex === "number" ? value.sliceIndex : 0})` : target;
|
|
@@ -48532,6 +48700,7 @@ function validateFinalizedFileAssignmentsV4(records2, options = {}) {
|
|
|
48532
48700
|
return;
|
|
48533
48701
|
}
|
|
48534
48702
|
if (!isObjectRecord2(value)) return;
|
|
48703
|
+
if (isEmptySpriteValue(value)) return;
|
|
48535
48704
|
if (isStructuredLeafPartialValue(value)) {
|
|
48536
48705
|
visitSpriteFileField(
|
|
48537
48706
|
value[STRUCTURED_LEAF_PARTIAL_KEY].fileId,
|
|
@@ -52532,7 +52701,10 @@ function classToLanguageType(schemaClass2, context) {
|
|
|
52532
52701
|
}
|
|
52533
52702
|
function constructorSignature(schemaClass2, members, context, genericEnvironment) {
|
|
52534
52703
|
if (schemaClass2.isAbstract) return {};
|
|
52535
|
-
|
|
52704
|
+
const projections = inheritedConstructorProjections(schemaClass2, context);
|
|
52705
|
+
if (projections.length === 0 && !isClosedClass(schemaClass2.id, context.vm.classes)) {
|
|
52706
|
+
return {};
|
|
52707
|
+
}
|
|
52536
52708
|
if (resolveAllowedStorage(schemaClass2.id, context.vm.classes) === "immutable" /* Immutable */) {
|
|
52537
52709
|
return { constructorUnavailableReason: "immutableOnly" };
|
|
52538
52710
|
}
|
|
@@ -52553,11 +52725,43 @@ function constructorSignature(schemaClass2, members, context, genericEnvironment
|
|
|
52553
52725
|
defaultValue: "defaultValue" in resolved ? resolved.defaultValue : void 0
|
|
52554
52726
|
};
|
|
52555
52727
|
} catch {
|
|
52728
|
+
if (projections.some((projection) => projection.memberId === memberId)) {
|
|
52729
|
+
return { required: true };
|
|
52730
|
+
}
|
|
52556
52731
|
return null;
|
|
52557
52732
|
}
|
|
52558
52733
|
}
|
|
52559
52734
|
);
|
|
52560
|
-
return {
|
|
52735
|
+
return {
|
|
52736
|
+
constructorSignature: {
|
|
52737
|
+
...signature,
|
|
52738
|
+
...projections.length === 0 ? {} : {
|
|
52739
|
+
namedProjections: projections.map((projection) => ({
|
|
52740
|
+
name: projection.parameterName,
|
|
52741
|
+
memberId: projection.memberId
|
|
52742
|
+
}))
|
|
52743
|
+
}
|
|
52744
|
+
}
|
|
52745
|
+
};
|
|
52746
|
+
}
|
|
52747
|
+
function inheritedConstructorProjections(schemaClass2, context) {
|
|
52748
|
+
const classesById = new Map(
|
|
52749
|
+
context.vm.classes.map((candidate) => [candidate.id, candidate])
|
|
52750
|
+
);
|
|
52751
|
+
const projections = [];
|
|
52752
|
+
const claimed = /* @__PURE__ */ new Set();
|
|
52753
|
+
const visited = /* @__PURE__ */ new Set();
|
|
52754
|
+
let current = schemaClass2;
|
|
52755
|
+
while (current !== void 0 && !visited.has(current.id)) {
|
|
52756
|
+
visited.add(current.id);
|
|
52757
|
+
for (const projection of current.constructorProjections ?? []) {
|
|
52758
|
+
if (claimed.has(projection.parameterName)) continue;
|
|
52759
|
+
claimed.add(projection.parameterName);
|
|
52760
|
+
projections.push(projection);
|
|
52761
|
+
}
|
|
52762
|
+
current = current.extendsClassId ? classesById.get(current.extendsClassId) : void 0;
|
|
52763
|
+
}
|
|
52764
|
+
return projections;
|
|
52561
52765
|
}
|
|
52562
52766
|
function declaredConstructors(schemaClass2, context) {
|
|
52563
52767
|
const requiredConstructorId2 = schemaClass2.requiredConstructorId;
|
|
@@ -54266,13 +54470,37 @@ function throwNamedBodyCompileFailure(args) {
|
|
|
54266
54470
|
});
|
|
54267
54471
|
}
|
|
54268
54472
|
function resolveMemberDeclaredTypeInfo(member, members) {
|
|
54473
|
+
return resolveMemberDeclaredTypeInfoInternal(member, members, /* @__PURE__ */ new Set());
|
|
54474
|
+
}
|
|
54475
|
+
function resolveMemberDeclaredTypeInfoInternal(member, members, seen) {
|
|
54269
54476
|
const resolved = resolveMember2(member, members);
|
|
54477
|
+
const memberId = getField(resolved, "id");
|
|
54478
|
+
if (typeof memberId === "string" && seen.has(memberId)) return null;
|
|
54479
|
+
const nextSeen = typeof memberId === "string" ? /* @__PURE__ */ new Set([...seen, memberId]) : new Set(seen);
|
|
54270
54480
|
if (isMemberNSPropertyBase(resolved)) return resolved.returnTypeInfo;
|
|
54271
54481
|
if (isMemberClassBase(resolved)) {
|
|
54482
|
+
const typeArguments = Object.fromEntries(
|
|
54483
|
+
Object.entries(resolved.classArguments ?? {}).flatMap(
|
|
54484
|
+
([genericParamId, binding]) => {
|
|
54485
|
+
if (binding.kind !== "member") return [];
|
|
54486
|
+
const argumentMember = members.find(
|
|
54487
|
+
(candidate) => candidate.id === binding.memberId
|
|
54488
|
+
);
|
|
54489
|
+
if (argumentMember === void 0) return [];
|
|
54490
|
+
const argumentType = resolveMemberDeclaredTypeInfoInternal(
|
|
54491
|
+
argumentMember,
|
|
54492
|
+
members,
|
|
54493
|
+
nextSeen
|
|
54494
|
+
);
|
|
54495
|
+
return argumentType === null ? [] : [[genericParamId, { ...argumentType, required: true }]];
|
|
54496
|
+
}
|
|
54497
|
+
)
|
|
54498
|
+
);
|
|
54272
54499
|
return {
|
|
54273
54500
|
type: 7 /* Class */,
|
|
54274
54501
|
required: resolved.required,
|
|
54275
|
-
classId: resolved.classId
|
|
54502
|
+
classId: resolved.classId,
|
|
54503
|
+
...Object.keys(typeArguments).length === 0 ? {} : { typeArguments }
|
|
54276
54504
|
};
|
|
54277
54505
|
}
|
|
54278
54506
|
if (isMemberEnumBase(resolved)) {
|
|
@@ -54299,7 +54527,11 @@ function resolveMemberDeclaredTypeInfo(member, members) {
|
|
|
54299
54527
|
(candidate) => candidate.id === resolved.entryMemberId
|
|
54300
54528
|
);
|
|
54301
54529
|
if (entry === void 0) return null;
|
|
54302
|
-
const entryTypeInfo =
|
|
54530
|
+
const entryTypeInfo = resolveMemberDeclaredTypeInfoInternal(
|
|
54531
|
+
entry,
|
|
54532
|
+
members,
|
|
54533
|
+
nextSeen
|
|
54534
|
+
);
|
|
54303
54535
|
if (entryTypeInfo === null) return null;
|
|
54304
54536
|
return {
|
|
54305
54537
|
type: resolved.kind,
|
|
@@ -54315,7 +54547,7 @@ function resolveMemberDeclaredTypeInfo(member, members) {
|
|
|
54315
54547
|
if (collection === void 0) return null;
|
|
54316
54548
|
return lookupDeclaredTypeInfo(
|
|
54317
54549
|
resolved,
|
|
54318
|
-
|
|
54550
|
+
resolveMemberDeclaredTypeInfoInternal(collection, members, nextSeen)
|
|
54319
54551
|
);
|
|
54320
54552
|
}
|
|
54321
54553
|
if (!memberKindSupportsStorage(resolved.kind)) return null;
|
|
@@ -75266,15 +75498,16 @@ function replayStoredConstructionV4(args) {
|
|
|
75266
75498
|
member: compileMember,
|
|
75267
75499
|
valueRow: candidate,
|
|
75268
75500
|
valueId: args.valueId,
|
|
75269
|
-
//
|
|
75270
|
-
//
|
|
75271
|
-
initializerOwnerClass: null
|
|
75501
|
+
// Instance calls are self-contained. Declaration calls inherit the class
|
|
75502
|
+
// header parameters that are in lexical scope at their source site.
|
|
75503
|
+
initializerOwnerClass: args.initializerOwnerClass ?? null
|
|
75272
75504
|
});
|
|
75273
75505
|
if (!isMemberValue(candidate) || !isInitValueContent(candidate)) {
|
|
75274
75506
|
throw new Error(
|
|
75275
75507
|
`Construction replay for value "${args.valueId}" did not compile an initializer row.`
|
|
75276
75508
|
);
|
|
75277
75509
|
}
|
|
75510
|
+
if (args.evaluate === false) return /* @__PURE__ */ new Map();
|
|
75278
75511
|
const materialized = materializeInitializerValue({
|
|
75279
75512
|
document,
|
|
75280
75513
|
// Constructor-only rows have no structural member owner. Use the same
|
|
@@ -76384,7 +76617,7 @@ function lowerRowBackedDefault(context, member, backed, baseData3, binding) {
|
|
|
76384
76617
|
const assignmentSlices = objectInitializerSlices(binding.initializer);
|
|
76385
76618
|
for (const assignment of expression.initializer ?? []) {
|
|
76386
76619
|
const childMember = classMemberByName(context, classId, assignment.name);
|
|
76387
|
-
if (
|
|
76620
|
+
if (inheritedConstructorProjections2(context.classes, schemaClass2.id).some(
|
|
76388
76621
|
(projection) => projection.memberId === childMember.id
|
|
76389
76622
|
)) {
|
|
76390
76623
|
throw new Error(
|
|
@@ -76797,7 +77030,7 @@ function lowerSeedRow(context, member, sourceExpression, source, valueId, path,
|
|
|
76797
77030
|
effectiveClass.id,
|
|
76798
77031
|
assignment.name
|
|
76799
77032
|
);
|
|
76800
|
-
if (
|
|
77033
|
+
if (inheritedConstructorProjections2(
|
|
76801
77034
|
context.classes,
|
|
76802
77035
|
effectiveClass.id
|
|
76803
77036
|
).some((projection) => projection.memberId === childMember.id)) {
|
|
@@ -77095,15 +77328,17 @@ function lowerValueRow(context, member, sourceExpression, expectedValueId, sourc
|
|
|
77095
77328
|
`Value ${expectedValueId} stores constructor arguments but its declared member ${resolvedMember.name} is not a Class.`
|
|
77096
77329
|
);
|
|
77097
77330
|
}
|
|
77098
|
-
|
|
77099
|
-
|
|
77100
|
-
|
|
77101
|
-
|
|
77102
|
-
|
|
77103
|
-
(
|
|
77104
|
-
|
|
77105
|
-
|
|
77106
|
-
|
|
77331
|
+
if (source.purpose === "stored") {
|
|
77332
|
+
context.initializerReconciliations.set(expectedValueId, {
|
|
77333
|
+
valueId: expectedValueId,
|
|
77334
|
+
code,
|
|
77335
|
+
storedConstructorArgs: storedConstructorArgs === null ? null : structuredClone(storedConstructorArgs),
|
|
77336
|
+
settleFields: expression.kind === "new" ? (expression.initializer ?? []).map(
|
|
77337
|
+
(assignment) => assignment.name
|
|
77338
|
+
) : [],
|
|
77339
|
+
site: referenceSite(source, expression)
|
|
77340
|
+
});
|
|
77341
|
+
}
|
|
77107
77342
|
const value2 = lowerClassValue(
|
|
77108
77343
|
context,
|
|
77109
77344
|
resolvedMember,
|
|
@@ -77143,7 +77378,12 @@ function lowerValueRow(context, member, sourceExpression, expectedValueId, sourc
|
|
|
77143
77378
|
}
|
|
77144
77379
|
function lowerValueBody(context, member, expression, base, source, environment, authoredSlice) {
|
|
77145
77380
|
const next = valueFileFields(base);
|
|
77146
|
-
if (expression.kind === "litNull")
|
|
77381
|
+
if (expression.kind === "litNull") {
|
|
77382
|
+
if (member.required) {
|
|
77383
|
+
throw new Error(`Required member ${member.name} cannot store null.`);
|
|
77384
|
+
}
|
|
77385
|
+
return { ...next, value: null };
|
|
77386
|
+
}
|
|
77147
77387
|
switch (member.kind) {
|
|
77148
77388
|
case "null":
|
|
77149
77389
|
return { ...next, value: null };
|
|
@@ -77293,7 +77533,7 @@ function lowerClassValue(context, member, expression, base, source, outerEnviron
|
|
|
77293
77533
|
}
|
|
77294
77534
|
for (const assignment of expression.initializer ?? []) {
|
|
77295
77535
|
const childMember = classMemberByName(context, classId, assignment.name);
|
|
77296
|
-
if (
|
|
77536
|
+
if (inheritedConstructorProjections2(context.classes, schemaClass2.id).some(
|
|
77297
77537
|
(projection) => projection.memberId === childMember.id
|
|
77298
77538
|
)) {
|
|
77299
77539
|
throw new Error(
|
|
@@ -77475,7 +77715,7 @@ function classInheritanceChain(classes, classId) {
|
|
|
77475
77715
|
}
|
|
77476
77716
|
return chain;
|
|
77477
77717
|
}
|
|
77478
|
-
function
|
|
77718
|
+
function inheritedConstructorProjections2(classes, classId) {
|
|
77479
77719
|
const resolved = [];
|
|
77480
77720
|
const claimed = /* @__PURE__ */ new Set();
|
|
77481
77721
|
for (const schemaClass2 of classInheritanceChain(classes, classId)) {
|
|
@@ -77496,7 +77736,7 @@ function inheritedProjectionSchemaKey(classes, classId, memberId) {
|
|
|
77496
77736
|
return null;
|
|
77497
77737
|
}
|
|
77498
77738
|
function resolveConstructorProjectionArguments(context, schemaClass2, expression, ownerValueId, environment, source) {
|
|
77499
|
-
const projections =
|
|
77739
|
+
const projections = inheritedConstructorProjections2(
|
|
77500
77740
|
context.classes,
|
|
77501
77741
|
schemaClass2.id
|
|
77502
77742
|
);
|
|
@@ -78127,6 +78367,9 @@ function expressionAnchorPos(expression) {
|
|
|
78127
78367
|
}
|
|
78128
78368
|
function lowerFileValue(context, member, expression) {
|
|
78129
78369
|
if (member.kind === "sprite") {
|
|
78370
|
+
if (isSpriteInfoEmptyExpression(expression)) {
|
|
78371
|
+
return { fileId: "", sliceIndex: 0 };
|
|
78372
|
+
}
|
|
78130
78373
|
if (expression.kind !== "call" || expression.callee.kind !== "member" || expression.callee.name !== "Slice") {
|
|
78131
78374
|
throw new Error(
|
|
78132
78375
|
`Sprite member ${member.name} requires Image.Slice(index).`
|
|
@@ -79114,7 +79357,8 @@ function emitValueBody(context, member, value, visited, targetTyped, environment
|
|
|
79114
79357
|
context,
|
|
79115
79358
|
kind,
|
|
79116
79359
|
`Audio member ${JSON.stringify(String(member.name ?? member.id))}`,
|
|
79117
|
-
body
|
|
79360
|
+
body,
|
|
79361
|
+
member.required === true
|
|
79118
79362
|
);
|
|
79119
79363
|
}
|
|
79120
79364
|
if (kind === 5)
|
|
@@ -79364,7 +79608,12 @@ function storedValueConstructor(context, schemaClass2, constructorArgs) {
|
|
|
79364
79608
|
return selected2;
|
|
79365
79609
|
}
|
|
79366
79610
|
function storedConstructorArgumentSource(context, type, value, environment, visited, cloneAggregateArguments = false) {
|
|
79367
|
-
if (value === null)
|
|
79611
|
+
if (value === null) {
|
|
79612
|
+
if (!type.nullable) {
|
|
79613
|
+
throw new Error("Required constructor argument stores null.");
|
|
79614
|
+
}
|
|
79615
|
+
return "null";
|
|
79616
|
+
}
|
|
79368
79617
|
switch (type.kind) {
|
|
79369
79618
|
case "null":
|
|
79370
79619
|
return "null";
|
|
@@ -79396,7 +79645,8 @@ function storedConstructorArgumentSource(context, type, value, environment, visi
|
|
|
79396
79645
|
{
|
|
79397
79646
|
id: "__constructor_arg__",
|
|
79398
79647
|
name: "argument",
|
|
79399
|
-
kind: 11 /* Sprite
|
|
79648
|
+
kind: 11 /* Sprite */,
|
|
79649
|
+
required: !type.nullable
|
|
79400
79650
|
},
|
|
79401
79651
|
value
|
|
79402
79652
|
);
|
|
@@ -79405,7 +79655,8 @@ function storedConstructorArgumentSource(context, type, value, environment, visi
|
|
|
79405
79655
|
context,
|
|
79406
79656
|
12 /* Audio */,
|
|
79407
79657
|
"constructor argument",
|
|
79408
|
-
value
|
|
79658
|
+
value,
|
|
79659
|
+
!type.nullable
|
|
79409
79660
|
);
|
|
79410
79661
|
case "enum":
|
|
79411
79662
|
return enumValue(
|
|
@@ -79790,7 +80041,7 @@ function manifestMemberTypeName(context, member) {
|
|
|
79790
80041
|
return fixedSourceTypeNameForKind(member.kind) ?? member.kind;
|
|
79791
80042
|
}
|
|
79792
80043
|
function constructorProjectionSource(context, classId, body, visited, environment) {
|
|
79793
|
-
const projections =
|
|
80044
|
+
const projections = inheritedConstructorProjections2(
|
|
79794
80045
|
context.manifestClasses,
|
|
79795
80046
|
classId
|
|
79796
80047
|
);
|
|
@@ -80180,8 +80431,13 @@ function delegateValue(context, body) {
|
|
|
80180
80431
|
}
|
|
80181
80432
|
return target.name;
|
|
80182
80433
|
}
|
|
80183
|
-
function fileValue(context, kind, label, body) {
|
|
80184
|
-
if (body === null || body === void 0)
|
|
80434
|
+
function fileValue(context, kind, label, body, required2) {
|
|
80435
|
+
if (body === null || body === void 0) {
|
|
80436
|
+
if (required2) {
|
|
80437
|
+
throw new Error(`${label} is required and cannot store null.`);
|
|
80438
|
+
}
|
|
80439
|
+
return "null";
|
|
80440
|
+
}
|
|
80185
80441
|
if (!isObjectRecord2(body)) {
|
|
80186
80442
|
throw new Error(
|
|
80187
80443
|
`${label} stores ${JSON.stringify(body)}, which is not a file value record.`
|
|
@@ -80193,12 +80449,18 @@ function fileValue(context, kind, label, body) {
|
|
|
80193
80449
|
);
|
|
80194
80450
|
}
|
|
80195
80451
|
if (body.fileId.length === 0) {
|
|
80196
|
-
|
|
80452
|
+
if (kind === 11 && numberOr2(body.sliceIndex, 0) === 0) {
|
|
80453
|
+
return "SpriteInfo.Empty";
|
|
80454
|
+
}
|
|
80455
|
+
throw new Error(`${label} stores an invalid empty file value.`);
|
|
80197
80456
|
}
|
|
80198
80457
|
const base = fileRegistrySource(context, kind, body.fileId);
|
|
80199
80458
|
if (kind !== 11) return base;
|
|
80200
80459
|
return `${base}.Slice(${numberOr2(body.sliceIndex, 0)})`;
|
|
80201
80460
|
}
|
|
80461
|
+
function isSpriteInfoEmptyExpression(expression) {
|
|
80462
|
+
return expression.kind === "member" && expression.name === "Empty" && expression.receiver.kind === "ident" && expression.receiver.name === "SpriteInfo";
|
|
80463
|
+
}
|
|
80202
80464
|
function fileRegistrySource(context, kind, fileId) {
|
|
80203
80465
|
const symbol = context.fileSymbols.get(fileId);
|
|
80204
80466
|
if (symbol !== void 0) {
|
|
@@ -80223,7 +80485,9 @@ function structuredLeafSource(context, kind, member, body) {
|
|
|
80223
80485
|
${assignments.map((entry) => indentNeoSourceNonEmptyLines(entry, 2)).join(",\n")}
|
|
80224
80486
|
}`;
|
|
80225
80487
|
}
|
|
80226
|
-
if (kind === 11 /* Sprite */)
|
|
80488
|
+
if (kind === 11 /* Sprite */) {
|
|
80489
|
+
return fileValue(context, 11, label, body, member.required === true);
|
|
80490
|
+
}
|
|
80227
80491
|
if (body === null) return "null";
|
|
80228
80492
|
if (!isObjectRecord2(body)) return "new()";
|
|
80229
80493
|
return `new(${structuredLeafFieldKeys(kind).map((key) => scalar(body[key])).join(", ")})`;
|
|
@@ -83940,11 +84204,12 @@ function replayAnimationDeclarationInitializersV4(records2, document) {
|
|
|
83940
84204
|
});
|
|
83941
84205
|
if (initializers.length === 0) return document;
|
|
83942
84206
|
const rootKinds = /* @__PURE__ */ new Map();
|
|
84207
|
+
const rootOwners = /* @__PURE__ */ new Map();
|
|
83943
84208
|
const owners = resolveOwnerMembersForValues(
|
|
83944
84209
|
document,
|
|
83945
84210
|
new Set(initializers.map(({ row }) => row.id)),
|
|
83946
84211
|
void 0,
|
|
83947
|
-
|
|
84212
|
+
rootOwners,
|
|
83948
84213
|
rootKinds
|
|
83949
84214
|
);
|
|
83950
84215
|
const pulled = /* @__PURE__ */ new Map();
|
|
@@ -83969,12 +84234,20 @@ function replayAnimationDeclarationInitializersV4(records2, document) {
|
|
|
83969
84234
|
if (!classBelongsToAnimationFamily(document.classes, declaredClassId)) {
|
|
83970
84235
|
continue;
|
|
83971
84236
|
}
|
|
84237
|
+
const rootOwner = rootOwners.get(row.id);
|
|
84238
|
+
const rootOwnerId = Reflect.get(rootOwner ?? {}, "id");
|
|
84239
|
+
const initializerOwnerClass = typeof rootOwnerId !== "string" ? null : findSchemaPlacement(rootOwnerId, document.classes)?.ownerClass ?? null;
|
|
83972
84240
|
const replay = replayStoredConstructionV4({
|
|
83973
84241
|
records: pulled,
|
|
83974
84242
|
valueId: row.id,
|
|
83975
84243
|
code,
|
|
83976
84244
|
member: owner,
|
|
83977
|
-
compileDocumentBodies: true
|
|
84245
|
+
compileDocumentBodies: true,
|
|
84246
|
+
initializerOwnerClass,
|
|
84247
|
+
// A parameterized declaration is a template. Its arguments exist only
|
|
84248
|
+
// at concrete construction sites, so validate the authored body here
|
|
84249
|
+
// without fabricating values for the class header parameters.
|
|
84250
|
+
evaluate: initializerOwnerClass?.requiredConstructorId === void 0 || initializerOwnerClass.requiredConstructorId === null
|
|
83978
84251
|
});
|
|
83979
84252
|
for (const [id2, value] of replay) {
|
|
83980
84253
|
if (!isMemberValue(value)) {
|
|
@@ -84358,6 +84631,7 @@ var init_workspace_status = __esm({
|
|
|
84358
84631
|
init_project_documents();
|
|
84359
84632
|
init_animation_clips();
|
|
84360
84633
|
init_classes();
|
|
84634
|
+
init_inheritance();
|
|
84361
84635
|
init_members();
|
|
84362
84636
|
init_value_row_owner_members();
|
|
84363
84637
|
init_project2();
|
|
@@ -94858,7 +95132,7 @@ async function downloadProjectVersionTransactionResult(args) {
|
|
|
94858
95132
|
cursor = page.continueCursor;
|
|
94859
95133
|
}
|
|
94860
95134
|
}
|
|
94861
|
-
async function
|
|
95135
|
+
async function preparePushStatus(workspace, options) {
|
|
94862
95136
|
const status = computeWorkspaceStatus(workspace);
|
|
94863
95137
|
if (status.conflictedFiles.length > 0) {
|
|
94864
95138
|
throw new Error(
|
|
@@ -94887,22 +95161,7 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
|
|
|
94887
95161
|
changes: status.changes,
|
|
94888
95162
|
binaryChanges: status.binaryChanges ?? []
|
|
94889
95163
|
});
|
|
94890
|
-
if (status.changes.length === 0)
|
|
94891
|
-
if (options.json === true) {
|
|
94892
|
-
console.log(
|
|
94893
|
-
JSON.stringify({
|
|
94894
|
-
type: "push-plan",
|
|
94895
|
-
dryRun: options.dryRun,
|
|
94896
|
-
changeCount: 0,
|
|
94897
|
-
staticValueSeedCount: 0,
|
|
94898
|
-
changes: []
|
|
94899
|
-
})
|
|
94900
|
-
);
|
|
94901
|
-
} else {
|
|
94902
|
-
console.log("Nothing to push \u2014 working copy is clean.");
|
|
94903
|
-
}
|
|
94904
|
-
return;
|
|
94905
|
-
}
|
|
95164
|
+
if (status.changes.length === 0) return status;
|
|
94906
95165
|
const initConversions = status.initConversions ?? [];
|
|
94907
95166
|
if (initConversions.length > 0 && options.json !== true) {
|
|
94908
95167
|
for (const line of describeInitConversions(initConversions)) warn(line);
|
|
@@ -94974,8 +95233,40 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
|
|
|
94974
95233
|
} catch (error) {
|
|
94975
95234
|
reportDryRunFailure(error, options.json === true);
|
|
94976
95235
|
process.exitCode = 1;
|
|
94977
|
-
return;
|
|
95236
|
+
return null;
|
|
95237
|
+
}
|
|
95238
|
+
}
|
|
95239
|
+
return status;
|
|
95240
|
+
}
|
|
95241
|
+
async function runPush(workspace, options, preparationOverride) {
|
|
95242
|
+
const preparation = preparationOverride === void 0 ? process.stdout.isTTY === true && options.json !== true ? spinner("Preparing push\u2026") : null : preparationOverride;
|
|
95243
|
+
let status;
|
|
95244
|
+
try {
|
|
95245
|
+
status = await preparePushStatus(workspace, options);
|
|
95246
|
+
} catch (error) {
|
|
95247
|
+
preparation?.fail("Push preparation failed.");
|
|
95248
|
+
throw error;
|
|
95249
|
+
}
|
|
95250
|
+
if (status === null) {
|
|
95251
|
+
preparation?.fail("Push preparation failed.");
|
|
95252
|
+
return;
|
|
95253
|
+
}
|
|
95254
|
+
preparation?.stop();
|
|
95255
|
+
if (status.changes.length === 0) {
|
|
95256
|
+
if (options.json === true) {
|
|
95257
|
+
console.log(
|
|
95258
|
+
JSON.stringify({
|
|
95259
|
+
type: "push-plan",
|
|
95260
|
+
dryRun: options.dryRun,
|
|
95261
|
+
changeCount: 0,
|
|
95262
|
+
staticValueSeedCount: 0,
|
|
95263
|
+
changes: []
|
|
95264
|
+
})
|
|
95265
|
+
);
|
|
95266
|
+
} else {
|
|
95267
|
+
console.log("Nothing to push \u2014 working copy is clean.");
|
|
94978
95268
|
}
|
|
95269
|
+
return;
|
|
94979
95270
|
}
|
|
94980
95271
|
if (options.json === true) {
|
|
94981
95272
|
console.log(
|
|
@@ -98100,14 +98391,29 @@ async function main() {
|
|
|
98100
98391
|
return;
|
|
98101
98392
|
}
|
|
98102
98393
|
case "push": {
|
|
98103
|
-
const
|
|
98104
|
-
const
|
|
98105
|
-
|
|
98106
|
-
|
|
98107
|
-
|
|
98108
|
-
|
|
98109
|
-
|
|
98110
|
-
|
|
98394
|
+
const json = boolFlag(args, "json");
|
|
98395
|
+
const preparation = process.stdout.isTTY === true && json !== true ? spinner("Preparing push\u2026") : null;
|
|
98396
|
+
let handedOffPreparation = false;
|
|
98397
|
+
try {
|
|
98398
|
+
const workspace = loadWorkspaceForCommand(args);
|
|
98399
|
+
const { runPush: runPush2 } = await Promise.resolve().then(() => (init_push(), push_exports));
|
|
98400
|
+
handedOffPreparation = true;
|
|
98401
|
+
await runPush2(
|
|
98402
|
+
workspace,
|
|
98403
|
+
{
|
|
98404
|
+
dryRun: boolFlag(args, "dry-run"),
|
|
98405
|
+
summary: stringFlag(args, "summary"),
|
|
98406
|
+
acceptBump: boolFlag(args, "accept-bump"),
|
|
98407
|
+
json
|
|
98408
|
+
},
|
|
98409
|
+
preparation
|
|
98410
|
+
);
|
|
98411
|
+
} catch (error) {
|
|
98412
|
+
if (!handedOffPreparation) {
|
|
98413
|
+
preparation?.fail("Push preparation failed.");
|
|
98414
|
+
}
|
|
98415
|
+
throw error;
|
|
98416
|
+
}
|
|
98111
98417
|
return;
|
|
98112
98418
|
}
|
|
98113
98419
|
case "status": {
|
package/package.json
CHANGED
|
@@ -66,12 +66,15 @@ Use complete values in normal member initialization:
|
|
|
66
66
|
|
|
67
67
|
```neo
|
|
68
68
|
Sprite = Images.Hero.Slice(0);
|
|
69
|
+
Placeholder = SpriteInfo.Empty;
|
|
69
70
|
Position = new(0, 0, 0);
|
|
70
71
|
Tint = Color(1, 1, 1, 1);
|
|
71
72
|
```
|
|
72
73
|
|
|
73
74
|
A bare `Images.Hero` yields a file ID only in a file-valued field context.
|
|
74
75
|
Use `.Slice(index)` for a complete `SpriteInfo`.
|
|
76
|
+
Use `SpriteInfo.Empty` for an authored non-null empty sprite. Use `null` only
|
|
77
|
+
when the declared type is nullable `SpriteInfo?`.
|
|
75
78
|
|
|
76
79
|
NeoScript may read or write structured fields when the receiver's effective
|
|
77
80
|
storage permits it:
|
|
@@ -73,7 +73,7 @@ wrappers.
|
|
|
73
73
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
74
74
|
|
|
75
75
|
```html
|
|
76
|
-
<!-- reviewed-through-cli: 0.21.
|
|
76
|
+
<!-- reviewed-through-cli: 0.21.4 -->
|
|
77
77
|
```
|
|
78
78
|
|
|
79
79
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -37,6 +37,10 @@ validation — so a rejection that used to cost a real push and return an opaque
|
|
|
37
37
|
`preparation-failed` now reports before anything is sent. It does not prompt,
|
|
38
38
|
upload, commit, or rewrite source.
|
|
39
39
|
|
|
40
|
+
Interactive pushes show `Preparing push…` before workspace discovery,
|
|
41
|
+
lowering, and compilation begin. JSON and non-TTY output remain structured and
|
|
42
|
+
do not emit that terminal-only spinner.
|
|
43
|
+
|
|
40
44
|
A clean dry-run does not promise a clean push. The workspace holds its
|
|
41
45
|
last-pulled state, so everything that grades the live head is still server-only:
|
|
42
46
|
re-verification of the uploaded bundle bytes, project-file staging, the
|