@carbonenginejs/runtime-resource 0.8.0 → 0.9.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/LICENSE +21 -21
- package/NOTICE +29 -29
- package/README.md +67 -548
- package/dist/CjsMotherLode.js +1271 -1271
- package/dist/CjsResMan.js +3005 -3005
- package/dist/CjsResManQueue.js +214 -214
- package/dist/CjsResource.js +566 -566
- package/dist/CjsResourceSource.js +59 -59
- package/dist/_virtual/_rollupPluginBabelHelpers.js +153 -153
- package/dist/format/CjsBlueReader.js +269 -269
- package/dist/format/CjsFormat.js +192 -192
- package/dist/format/CjsReader.js +18 -18
- package/dist/format/CjsResourceProbe.js +277 -277
- package/dist/format/payloadContract.js +173 -173
- package/dist/formats/black/CjsBlackFormat.js +278 -278
- package/dist/formats/black/core/CjsBlackBinaryReader.js +153 -153
- package/dist/formats/black/core/CjsBlackPropertyReaders.js +382 -382
- package/dist/formats/black/core/CjsBlackReader.js +639 -639
- package/dist/formats/black/core/CjsBlackSchemaRegistry.js +433 -433
- package/dist/formats/black/core/black-schema-v1-2026-07-11.json.js +4 -4
- package/dist/formats/black/core/blackConstants.js +7 -7
- package/dist/formats/black/core/blackDefinitions.js +10 -10
- package/dist/formats/black/core/blackEnums.js +6 -6
- package/dist/formats/black/core/blackSchema.js +3 -3
- package/dist/formats/black/core/blackVersion.js +22 -22
- package/dist/formats/black/core/helpers.js +182 -182
- package/dist/formats/black/core/schema.js +4 -4
- package/dist/formats/black/index.js +2 -2
- package/dist/formats/bnk/CjsBnkFormat.js +125 -125
- package/dist/formats/bnk/core/graph.js +140 -140
- package/dist/formats/bnk/core/helpers.js +409 -409
- package/dist/formats/bnk/core/musicNodes.js +489 -489
- package/dist/formats/bnk/core/soundbanksInfo.js +246 -246
- package/dist/formats/bnk/index.js +2 -2
- package/dist/formats/cmf/CjsCmfFormat.js +497 -497
- package/dist/formats/cmf/core/binary.js +118 -118
- package/dist/formats/cmf/core/buffers.js +233 -233
- package/dist/formats/cmf/core/constants.js +47 -47
- package/dist/formats/cmf/core/gr2Anim.js +453 -453
- package/dist/formats/cmf/core/helpers.js +287 -287
- package/dist/formats/cmf/core/pack.js +276 -276
- package/dist/formats/cmf/core/schema.js +364 -364
- package/dist/formats/cmf/core/shared.js +268 -268
- package/dist/formats/cmf/core/writer.js +517 -517
- package/dist/formats/cmf/index.js +2 -2
- package/dist/formats/dds/CjsDdsFormat.js +193 -193
- package/dist/formats/dds/core/bc6h.js +288 -288
- package/dist/formats/dds/core/bc7.js +251 -251
- package/dist/formats/dds/core/helpers.js +815 -815
- package/dist/formats/dds/index.js +2 -2
- package/dist/formats/fbx/CjsFbxFormat.js +266 -266
- package/dist/formats/fbx/core/helpers.js +3901 -3901
- package/dist/formats/fbx/index.js +2 -2
- package/dist/formats/flac/CjsFlacFormat.js +87 -87
- package/dist/formats/flac/core/helpers.js +295 -295
- package/dist/formats/flac/index.js +2 -2
- package/dist/formats/gif/CjsGifFormat.js +87 -87
- package/dist/formats/gif/core/helpers.js +360 -360
- package/dist/formats/gif/index.js +2 -2
- package/dist/formats/gltf/CjsGltfFormat.js +290 -290
- package/dist/formats/gltf/core/helpers.js +292 -292
- package/dist/formats/gltf/core/json.js +79 -79
- package/dist/formats/gltf/core/parser.js +666 -666
- package/dist/formats/gltf/core/targets.js +163 -163
- package/dist/formats/gltf/index.js +2 -2
- package/dist/formats/gr2/CjsGr2Format.js +46 -0
- package/dist/formats/gr2/CjsGr2Format.js.map +1 -0
- package/dist/formats/gr2/core/CjsFormatGr2.js +273 -0
- package/dist/formats/gr2/core/CjsFormatGr2.js.map +1 -0
- package/dist/formats/gr2/core/bitknit2.js +280 -0
- package/dist/formats/gr2/core/bitknit2.js.map +1 -0
- package/dist/formats/gr2/core/curves.js +1047 -0
- package/dist/formats/gr2/core/curves.js.map +1 -0
- package/dist/formats/gr2/core/gsf.js +72 -0
- package/dist/formats/gr2/core/gsf.js.map +1 -0
- package/dist/formats/gr2/core/helpers.js +332 -0
- package/dist/formats/gr2/core/helpers.js.map +1 -0
- package/dist/formats/gr2/core/json.js +622 -0
- package/dist/formats/gr2/core/json.js.map +1 -0
- package/dist/formats/gr2/core/oodle1.js +388 -0
- package/dist/formats/gr2/core/oodle1.js.map +1 -0
- package/dist/formats/gr2/core/reader.js +617 -0
- package/dist/formats/gr2/core/reader.js.map +1 -0
- package/dist/formats/gr2/core/tangents.js +48 -0
- package/dist/formats/gr2/core/tangents.js.map +1 -0
- package/dist/formats/gr2/core/targets.js +351 -0
- package/dist/formats/gr2/core/targets.js.map +1 -0
- package/dist/formats/gr2/index.js +3 -0
- package/dist/formats/gr2/index.js.map +1 -0
- package/dist/formats/index.js +30 -23
- package/dist/formats/index.js.map +1 -1
- package/dist/formats/jpeg/CjsJpegFormat.js +206 -206
- package/dist/formats/jpeg/core/helpers.js +350 -350
- package/dist/formats/jpeg/core/jpeg.js +377 -377
- package/dist/formats/jpeg/index.js +2 -2
- package/dist/formats/mp3/CjsMp3Format.js +192 -192
- package/dist/formats/mp3/core/helpers.js +338 -338
- package/dist/formats/mp3/index.js +2 -2
- package/dist/formats/mp4/CjsMp4Format.js +191 -191
- package/dist/formats/mp4/core/helpers.js +449 -449
- package/dist/formats/mp4/index.js +2 -2
- package/dist/formats/obj/CjsObjFormat.js +253 -253
- package/dist/formats/obj/core/helpers.js +573 -573
- package/dist/formats/obj/core/json.js +64 -64
- package/dist/formats/obj/core/parser.js +321 -321
- package/dist/formats/obj/index.js +2 -2
- package/dist/formats/ogg/CjsOggFormat.js +88 -88
- package/dist/formats/ogg/core/helpers.js +387 -387
- package/dist/formats/ogg/core/imdct.js +178 -178
- package/dist/formats/ogg/core/vorbis.js +999 -999
- package/dist/formats/ogg/index.js +2 -2
- package/dist/formats/png/CjsPngFormat.js +195 -195
- package/dist/formats/png/core/helpers.js +583 -583
- package/dist/formats/png/index.js +2 -2
- package/dist/formats/red/CjsRedFormat.js +261 -261
- package/dist/formats/red/core/CjsRedReader.js +194 -194
- package/dist/formats/red/core/blackDefinitions.js +3 -3
- package/dist/formats/red/core/helpers.js +139 -139
- package/dist/formats/red/core/redGraph.js +68 -68
- package/dist/formats/red/core/schema.js +4 -4
- package/dist/formats/red/index.js +2 -2
- package/dist/formats/stl/CjsStlFormat.js +365 -365
- package/dist/formats/stl/core/helpers.js +261 -261
- package/dist/formats/stl/core/json.js +51 -51
- package/dist/formats/stl/core/stl.js +629 -629
- package/dist/formats/stl/core/targets.js +163 -163
- package/dist/formats/stl/index.js +2 -2
- package/dist/formats/tga/CjsTgaFormat.js +192 -192
- package/dist/formats/tga/core/helpers.js +446 -446
- package/dist/formats/tga/index.js +2 -2
- package/dist/formats/wav/CjsWavFormat.js +192 -192
- package/dist/formats/wav/core/helpers.js +328 -328
- package/dist/formats/wav/index.js +2 -2
- package/dist/formats/webm/CjsWebmFormat.js +191 -191
- package/dist/formats/webm/core/helpers.js +537 -537
- package/dist/formats/webm/index.js +2 -2
- package/dist/formats/webp/CjsWebpFormat.js +86 -86
- package/dist/formats/webp/core/helpers.js +214 -214
- package/dist/formats/webp/index.js +2 -2
- package/dist/formats/wem/CjsWemFormat.js +241 -241
- package/dist/formats/wem/core/bitStream.js +259 -259
- package/dist/formats/wem/core/codebookLibrary.js +164 -164
- package/dist/formats/wem/core/helpers.js +417 -417
- package/dist/formats/wem/core/packedCodebooksAotuv603.js +30 -30
- package/dist/formats/wem/core/ptadpcm.js +77 -77
- package/dist/formats/wem/core/resolve.js +121 -121
- package/dist/formats/wem/core/wemToOgg.js +485 -485
- package/dist/formats/wem/index.js +2 -2
- package/dist/formats/yaml/CjsYamlFormat.js +83 -83
- package/dist/formats/yaml/core/CjsYamlReader.js +305 -305
- package/dist/formats/yaml/core/helpers.js +160 -160
- package/dist/formats/yaml/index.js +2 -2
- package/dist/index.js +49 -48
- package/dist/index.js.map +1 -1
- package/dist/resourcePath.js +18 -18
- package/dist/resourceStates.js +9 -9
- package/dist/resources/AudioGeometryResData.js +47 -47
- package/dist/resources/GStateBindingCallbackData.js +31 -31
- package/dist/resources/MeshDecalData.js +37 -37
- package/dist/resources/MeshDecalLodData.js +34 -34
- package/dist/resources/Tr2EffectRes.js +71 -71
- package/dist/resources/Tr2GrannyIntersectionResult.js +60 -60
- package/dist/resources/Tr2GrannyStateRes.js +44 -44
- package/dist/resources/Tr2ImageRes.js +114 -114
- package/dist/resources/Tr2LightProfileRes.js +40 -40
- package/dist/resources/Tr2MaterialArea.js +34 -34
- package/dist/resources/Tr2MaterialMesh.js +31 -31
- package/dist/resources/Tr2MaterialRes.js +34 -34
- package/dist/resources/Tr2ShaderPermutation.js +43 -43
- package/dist/resources/Tr2TextureLodManager.js +80 -80
- package/dist/resources/Tr2TextureLodUpdateRequest.js +37 -37
- package/dist/resources/Tr2TexturePackChannel.js +37 -37
- package/dist/resources/Tr2TexturePipeline.js +52 -52
- package/dist/resources/Tr2TexturePipelineParams.js +34 -34
- package/dist/resources/Tr2TexturePipelineStepCompress.js +40 -40
- package/dist/resources/Tr2TexturePipelineStepGenerateMips.js +22 -0
- package/dist/resources/Tr2TexturePipelineStepGenerateMips.js.map +1 -0
- package/dist/resources/Tr2TexturePipelineStepLimitSize.js +34 -34
- package/dist/resources/Tr2TexturePipelineStepLoad.js +31 -31
- package/dist/resources/Tr2TexturePipelineStepPack.js +43 -43
- package/dist/resources/TriGeometryRes.js +239 -239
- package/dist/resources/TriGeometryResAreaData.js +59 -59
- package/dist/resources/TriGeometryResJointData.js +38 -38
- package/dist/resources/TriGeometryResLodData.js +88 -88
- package/dist/resources/TriGeometryResMeshData.js +63 -63
- package/dist/resources/TriGeometryResSkeletonData.js +34 -34
- package/dist/resources/TriGrannyRes.js +43 -43
- package/dist/resources/TriJointBinding.js +38 -38
- package/dist/resources/TriMorphTargetGeometryConstants.js +46 -46
- package/dist/resources/TriRtGeometryConstants.js +88 -88
- package/dist/resources/TriTextureRes.js +304 -304
- package/dist/resources/enums.js +18 -18
- package/dist/resources/resourceBoundary.js +47 -47
- package/dist/resources/texturePipelineBehavior.js +308 -308
- package/dist/texture/CjsTextureArrayRes.js +406 -406
- package/dist/texture/CjsTextureParameterProxy.js +133 -133
- package/docs/README.md +69 -0
- package/docs/architecture.md +86 -0
- package/docs/concepts/resource-lifecycle.md +217 -0
- package/docs/formats/README.md +104 -0
- package/{FORMAT-PROVENANCE.md → docs/formats/provenance.md} +173 -155
- package/docs/formats/stl.md +37 -0
- package/docs/formats/wwise.md +44 -0
- package/docs/reference/events.md +92 -0
- package/docs/reference/motherlode-cache.md +244 -0
- package/docs/reference/queues.md +102 -0
- package/docs/reference/reload.md +107 -0
- package/docs/reference/texture-arrays.md +113 -0
- package/docs/reference/texture-pipeline.md +53 -0
- package/docs/roadmap.md +104 -0
- package/format-notices/black/LICENSE +21 -21
- package/format-notices/black/NOTICE +47 -47
- package/format-notices/bnk/LICENSE +21 -21
- package/format-notices/bnk/NOTICE +20 -20
- package/format-notices/cmf/LICENSE +21 -21
- package/format-notices/cmf/NOTICE +36 -36
- package/format-notices/dds/LICENSE +21 -21
- package/format-notices/dds/NOTICE +14 -14
- package/format-notices/fbx/LICENSE +21 -21
- package/format-notices/fbx/NOTICE +14 -14
- package/format-notices/flac/LICENSE +21 -21
- package/format-notices/flac/NOTICE +14 -14
- package/format-notices/gif/LICENSE +21 -21
- package/format-notices/gif/NOTICE +14 -14
- package/format-notices/gltf/LICENSE +21 -21
- package/format-notices/gltf/NOTICE +27 -27
- package/format-notices/gr2/LICENSE +21 -0
- package/format-notices/gr2/NOTICE +60 -0
- package/format-notices/gr2/THIRD-PARTY-NOTICES.md +93 -0
- package/format-notices/jpeg/LICENSE +21 -21
- package/format-notices/jpeg/NOTICE +14 -14
- package/format-notices/mp3/LICENSE +21 -21
- package/format-notices/mp3/NOTICE +14 -14
- package/format-notices/mp4/LICENSE +21 -21
- package/format-notices/mp4/NOTICE +14 -14
- package/format-notices/obj/LICENSE +21 -21
- package/format-notices/obj/NOTICE +26 -26
- package/format-notices/ogg/LICENSE +21 -21
- package/format-notices/ogg/NOTICE +28 -28
- package/format-notices/png/LICENSE +21 -21
- package/format-notices/png/NOTICE +14 -14
- package/format-notices/red/LICENSE +21 -21
- package/format-notices/red/NOTICE +31 -31
- package/format-notices/stl/LICENSE +21 -21
- package/format-notices/stl/NOTICE +21 -21
- package/format-notices/tga/LICENSE +21 -21
- package/format-notices/tga/NOTICE +14 -14
- package/format-notices/wav/LICENSE +21 -21
- package/format-notices/wav/NOTICE +14 -14
- package/format-notices/webm/LICENSE +21 -21
- package/format-notices/webm/NOTICE +14 -14
- package/format-notices/webp/LICENSE +21 -21
- package/format-notices/webp/NOTICE +14 -14
- package/format-notices/wem/LICENSE +57 -57
- package/format-notices/wem/NOTICE +33 -33
- package/format-notices/yaml/LICENSE +21 -21
- package/format-notices/yaml/NOTICE +44 -44
- package/package.json +52 -51
- package/resource-lifecycle.md +0 -679
|
@@ -1,639 +1,639 @@
|
|
|
1
|
-
import { CjsCarbonDocument } from '@carbonenginejs/core-types/document';
|
|
2
|
-
import { CjsSchema } from '@carbonenginejs/core-types/schema';
|
|
3
|
-
import { CjsBlueReader } from '../../../format/CjsBlueReader.js';
|
|
4
|
-
import { CJS_BLACK_FOURCC, CJS_BLACK_VERSION, CJS_BLACK_FORMAT_ID } from './blackConstants.js';
|
|
5
|
-
import { CjsBlackBinaryReader } from './CjsBlackBinaryReader.js';
|
|
6
|
-
import { CjsBlackPropertyReaders } from './CjsBlackPropertyReaders.js';
|
|
7
|
-
import { CjsBlackSchemaRegistry } from './CjsBlackSchemaRegistry.js';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Reads a `.black` stream into a payload/document/runtime graph.
|
|
11
|
-
*
|
|
12
|
-
* This transport owns the binary buffer, string tables, numeric references,
|
|
13
|
-
* and binary read cursor. `ResetReadState()` clears only per-read graph state;
|
|
14
|
-
* each read entrypoint separately restores the cursor to `dataOffset`.
|
|
15
|
-
*/
|
|
16
|
-
class CjsBlackReader extends CjsBlueReader {
|
|
17
|
-
constructor(input, options = {}) {
|
|
18
|
-
super(options, {
|
|
19
|
-
schemaRegistry: CjsBlackSchemaRegistry,
|
|
20
|
-
defaultRegistry: CjsSchema,
|
|
21
|
-
includeShapeContext: true,
|
|
22
|
-
includeSourceShape: true,
|
|
23
|
-
includeEmptyPayloadType: true,
|
|
24
|
-
requirePayloadReferenceTarget: true
|
|
25
|
-
});
|
|
26
|
-
this.reader = CjsBlackBinaryReader.from(input, this);
|
|
27
|
-
this.references = new Map();
|
|
28
|
-
this.nodes = [];
|
|
29
|
-
this.nextNodeId = 1;
|
|
30
|
-
this.info = null;
|
|
31
|
-
this.readMode = "payload";
|
|
32
|
-
this.payloadDepth = 0;
|
|
33
|
-
this.payloadRootFields = null;
|
|
34
|
-
}
|
|
35
|
-
Inspect() {
|
|
36
|
-
if (this.info) return this.info;
|
|
37
|
-
const reader = this.reader;
|
|
38
|
-
reader.ExpectU32(CJS_BLACK_FOURCC, "Invalid Black FOURCC");
|
|
39
|
-
const version = reader.ReadU32();
|
|
40
|
-
if (version !== CJS_BLACK_VERSION) {
|
|
41
|
-
throw new RangeError(`Unsupported Black version: ${version}`);
|
|
42
|
-
}
|
|
43
|
-
const strings = CjsBlackReader.readStringTable(reader);
|
|
44
|
-
const wideStrings = CjsBlackReader.readWideStringTable(reader);
|
|
45
|
-
this.info = {
|
|
46
|
-
format: {
|
|
47
|
-
id: CJS_BLACK_FORMAT_ID,
|
|
48
|
-
version
|
|
49
|
-
},
|
|
50
|
-
byteLength: reader.data.byteLength,
|
|
51
|
-
dataOffset: reader.offset,
|
|
52
|
-
strings,
|
|
53
|
-
wideStrings
|
|
54
|
-
};
|
|
55
|
-
return this.info;
|
|
56
|
-
}
|
|
57
|
-
Read() {
|
|
58
|
-
return this.ReadPayload();
|
|
59
|
-
}
|
|
60
|
-
ReadDocument() {
|
|
61
|
-
const info = this.Inspect();
|
|
62
|
-
this.ResetReadState();
|
|
63
|
-
this.readMode = "document";
|
|
64
|
-
this.reader.offset = info.dataOffset;
|
|
65
|
-
const rootRef = this.ReadObject(this.reader);
|
|
66
|
-
if (!CjsCarbonDocument.isRef(rootRef)) {
|
|
67
|
-
throw new TypeError("Black root object is null");
|
|
68
|
-
}
|
|
69
|
-
this.reader.ExpectEnd("Black object graph did not read to end");
|
|
70
|
-
const includeRefIndex = this.ShouldIncludeRefIndex();
|
|
71
|
-
const refs = {};
|
|
72
|
-
if (includeRefIndex) {
|
|
73
|
-
for (const node of this.nodes) {
|
|
74
|
-
refs[String(node.id)] = {
|
|
75
|
-
kind: node.kind
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return CjsCarbonDocument.create({
|
|
80
|
-
format: info.format,
|
|
81
|
-
roots: [{
|
|
82
|
-
name: this.options.rootName || "default",
|
|
83
|
-
ref: rootRef
|
|
84
|
-
}],
|
|
85
|
-
nodes: this.nodes,
|
|
86
|
-
refs: includeRefIndex ? refs : null,
|
|
87
|
-
metadata: this.CreateDocumentMetadata(info),
|
|
88
|
-
reports: this.reports
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
ReadRuntime() {
|
|
92
|
-
const info = this.Inspect();
|
|
93
|
-
this.ResetReadState();
|
|
94
|
-
this.readMode = "runtime";
|
|
95
|
-
this.reader.offset = info.dataOffset;
|
|
96
|
-
const root = this.ReadObject(this.reader);
|
|
97
|
-
if (root === null) {
|
|
98
|
-
throw new TypeError("Black root object is null");
|
|
99
|
-
}
|
|
100
|
-
this.reader.ExpectEnd("Black object graph did not read to end");
|
|
101
|
-
this.FinalizeRuntimeInstances();
|
|
102
|
-
return {
|
|
103
|
-
root,
|
|
104
|
-
format: info.format,
|
|
105
|
-
reports: this.reports
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
ReadPayload() {
|
|
109
|
-
const info = this.Inspect();
|
|
110
|
-
this.ResetReadState();
|
|
111
|
-
this.readMode = "payload";
|
|
112
|
-
this.ValidatePayloadConfiguration();
|
|
113
|
-
this.reader.offset = info.dataOffset;
|
|
114
|
-
const object = this.ReadObject(this.reader);
|
|
115
|
-
if (object === null) {
|
|
116
|
-
throw new TypeError("Black root object is null");
|
|
117
|
-
}
|
|
118
|
-
this.reader.ExpectEnd("Black object graph did not read to end");
|
|
119
|
-
const payload = {
|
|
120
|
-
comments: this.reports,
|
|
121
|
-
object
|
|
122
|
-
};
|
|
123
|
-
if (this.ShouldIncludeDocumentMetadata()) {
|
|
124
|
-
payload.metadata = this.CreateDocumentMetadata(info);
|
|
125
|
-
}
|
|
126
|
-
return payload;
|
|
127
|
-
}
|
|
128
|
-
ReadObject(reader) {
|
|
129
|
-
if (this.readMode === "runtime") return this.ReadRuntimeObject(reader);
|
|
130
|
-
if (this.readMode === "payload") return this.ReadPayloadObject(reader);
|
|
131
|
-
const blackReference = reader.ReadU32();
|
|
132
|
-
if (blackReference === 0) return null;
|
|
133
|
-
const existing = this.references.get(blackReference);
|
|
134
|
-
if (existing) return CjsCarbonDocument.createRef(existing);
|
|
135
|
-
return this.ReadObjectPayload(reader, {
|
|
136
|
-
blackReference,
|
|
137
|
-
embedded: false
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
ReadEmbeddedObject(reader) {
|
|
141
|
-
if (this.readMode === "runtime") return this.ReadRuntimeObjectPayload(reader, {
|
|
142
|
-
blackReference: null,
|
|
143
|
-
embedded: true
|
|
144
|
-
});
|
|
145
|
-
if (this.readMode === "payload") return this.ReadPayloadObjectPayload(reader, {
|
|
146
|
-
blackReference: null,
|
|
147
|
-
embedded: true
|
|
148
|
-
});
|
|
149
|
-
return this.ReadObjectPayload(reader, {
|
|
150
|
-
blackReference: null,
|
|
151
|
-
embedded: true
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
ReadObjectPayload(reader, options) {
|
|
155
|
-
const payloadSize = reader.ReadU32();
|
|
156
|
-
const objectReader = reader.ReadBinaryReader(payloadSize);
|
|
157
|
-
const kind = objectReader.ReadStringRef();
|
|
158
|
-
const shape = this.ResolveSourceShape(kind);
|
|
159
|
-
const includeClassMetadata = this.ShouldIncludeClassMetadata();
|
|
160
|
-
const includeFieldTrace = this.ShouldIncludeFieldTrace();
|
|
161
|
-
const node = {
|
|
162
|
-
id: this.nextNodeId++,
|
|
163
|
-
kind,
|
|
164
|
-
fields: {},
|
|
165
|
-
...(includeClassMetadata ? {
|
|
166
|
-
source: shape?.source || {},
|
|
167
|
-
meta: {
|
|
168
|
-
family: shape?.family || null,
|
|
169
|
-
hashes: shape?.hashes || null,
|
|
170
|
-
blue: shape?.blue || null
|
|
171
|
-
}
|
|
172
|
-
} : {}),
|
|
173
|
-
...(includeFieldTrace ? {
|
|
174
|
-
meta: {
|
|
175
|
-
...(includeClassMetadata ? {
|
|
176
|
-
family: shape?.family || null,
|
|
177
|
-
hashes: shape?.hashes || null,
|
|
178
|
-
blue: shape?.blue || null
|
|
179
|
-
} : {}),
|
|
180
|
-
black: {
|
|
181
|
-
reference: options.blackReference,
|
|
182
|
-
embedded: options.embedded,
|
|
183
|
-
payloadSize,
|
|
184
|
-
fields: {}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
} : {}),
|
|
188
|
-
raw: null
|
|
189
|
-
};
|
|
190
|
-
this.nodes.push(node);
|
|
191
|
-
if (options.blackReference !== null) {
|
|
192
|
-
this.references.set(options.blackReference, node.id);
|
|
193
|
-
}
|
|
194
|
-
let previousBlackName = null;
|
|
195
|
-
while (!objectReader.AtEnd()) {
|
|
196
|
-
const blackName = objectReader.ReadStringRef();
|
|
197
|
-
const target = this.ResolveFieldTargetWithContext(kind, shape, blackName, previousBlackName);
|
|
198
|
-
const value = this.ReadFieldValueWithContext(objectReader, kind, blackName, target);
|
|
199
|
-
this.AssignFieldValue(node, target, value);
|
|
200
|
-
previousBlackName = blackName;
|
|
201
|
-
}
|
|
202
|
-
objectReader.ExpectEnd(`${kind} did not read to end`);
|
|
203
|
-
return CjsCarbonDocument.createRef(node.id);
|
|
204
|
-
}
|
|
205
|
-
ReadRuntimeObject(reader) {
|
|
206
|
-
const blackReference = reader.ReadU32();
|
|
207
|
-
if (blackReference === 0) return null;
|
|
208
|
-
if (this.references.has(blackReference)) {
|
|
209
|
-
return this.references.get(blackReference);
|
|
210
|
-
}
|
|
211
|
-
return this.ReadRuntimeObjectPayload(reader, {
|
|
212
|
-
blackReference,
|
|
213
|
-
embedded: false
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
ReadRuntimeObjectPayload(reader, options) {
|
|
217
|
-
const payloadSize = reader.ReadU32();
|
|
218
|
-
const objectReader = reader.ReadBinaryReader(payloadSize);
|
|
219
|
-
const kind = objectReader.ReadStringRef();
|
|
220
|
-
const shape = this.ResolveSourceShape(kind);
|
|
221
|
-
const target = this.CreateRuntimeTarget(kind, shape);
|
|
222
|
-
if (options.blackReference !== null) {
|
|
223
|
-
this.references.set(options.blackReference, target);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// Accumulate this object's fields into a plain values map, then hand
|
|
227
|
-
// the whole map to the hydration adapter. The adapter (default:
|
|
228
|
-
// Object.assign) decides how the caller's class receives its values -
|
|
229
|
-
// direct assignment, SetValues, etc. The target instance is already
|
|
230
|
-
// registered above, so back-references resolve to it while its values
|
|
231
|
-
// are still being collected (the adapter must mutate in place).
|
|
232
|
-
const values = {};
|
|
233
|
-
let previousBlackName = null;
|
|
234
|
-
while (!objectReader.AtEnd()) {
|
|
235
|
-
const blackName = objectReader.ReadStringRef();
|
|
236
|
-
const fieldTarget = this.ResolveFieldTargetWithContext(kind, shape, blackName, previousBlackName);
|
|
237
|
-
const value = this.ReadFieldValueWithContext(objectReader, kind, blackName, fieldTarget);
|
|
238
|
-
this.AssignRuntimeFieldValue(values, fieldTarget, value);
|
|
239
|
-
previousBlackName = blackName;
|
|
240
|
-
}
|
|
241
|
-
objectReader.ExpectEnd(`${kind} did not read to end`);
|
|
242
|
-
this.ApplyRuntimeValues(target, values, kind, shape);
|
|
243
|
-
return target;
|
|
244
|
-
}
|
|
245
|
-
ReadPayloadObject(reader) {
|
|
246
|
-
const blackReference = reader.ReadU32();
|
|
247
|
-
if (blackReference === 0) return null;
|
|
248
|
-
if (this.references.has(blackReference)) {
|
|
249
|
-
return this.CreatePayloadReference(this.references.get(blackReference), blackReference);
|
|
250
|
-
}
|
|
251
|
-
return this.ReadPayloadObjectPayload(reader, {
|
|
252
|
-
blackReference,
|
|
253
|
-
embedded: false
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
ReadPayloadObjectPayload(reader, options) {
|
|
257
|
-
const payloadSize = reader.ReadU32();
|
|
258
|
-
const objectReader = reader.ReadBinaryReader(payloadSize);
|
|
259
|
-
const kind = objectReader.ReadStringRef();
|
|
260
|
-
const shape = this.ResolveSourceShape(kind);
|
|
261
|
-
const target = this.CreatePayloadTarget(kind);
|
|
262
|
-
if (options.blackReference !== null) {
|
|
263
|
-
this.references.set(options.blackReference, target);
|
|
264
|
-
}
|
|
265
|
-
this.payloadDepth++;
|
|
266
|
-
try {
|
|
267
|
-
let previousBlackName = null;
|
|
268
|
-
while (!objectReader.AtEnd()) {
|
|
269
|
-
const blackName = objectReader.ReadStringRef();
|
|
270
|
-
const fieldTarget = this.ResolveFieldTargetWithContext(kind, shape, blackName, previousBlackName);
|
|
271
|
-
if (this.ShouldSkipPayloadField(fieldTarget)) {
|
|
272
|
-
this.SkipFieldValue(objectReader, fieldTarget);
|
|
273
|
-
previousBlackName = blackName;
|
|
274
|
-
continue;
|
|
275
|
-
}
|
|
276
|
-
const value = this.ReadFieldValueWithContext(objectReader, kind, blackName, fieldTarget);
|
|
277
|
-
this.AssignPayloadFieldValue(target, fieldTarget, value);
|
|
278
|
-
previousBlackName = blackName;
|
|
279
|
-
}
|
|
280
|
-
} finally {
|
|
281
|
-
this.payloadDepth--;
|
|
282
|
-
}
|
|
283
|
-
objectReader.ExpectEnd(`${kind} did not read to end`);
|
|
284
|
-
return target;
|
|
285
|
-
}
|
|
286
|
-
CreateSkippedPayloadTarget() {
|
|
287
|
-
return {};
|
|
288
|
-
}
|
|
289
|
-
GetPayloadRootFields() {
|
|
290
|
-
if (this.payloadRootFields !== null) return this.payloadRootFields;
|
|
291
|
-
const fields = this.options.payloadRootFields ?? this.options.rootFields ?? null;
|
|
292
|
-
if (!fields) {
|
|
293
|
-
this.payloadRootFields = false;
|
|
294
|
-
return this.payloadRootFields;
|
|
295
|
-
}
|
|
296
|
-
this.payloadRootFields = new Set((Array.isArray(fields) ? fields : [fields]).map(String));
|
|
297
|
-
return this.payloadRootFields;
|
|
298
|
-
}
|
|
299
|
-
ShouldSkipPayloadField(target) {
|
|
300
|
-
if (this.readMode !== "payload" || this.payloadDepth !== 1) return false;
|
|
301
|
-
const rootFields = this.GetPayloadRootFields();
|
|
302
|
-
if (!rootFields) return false;
|
|
303
|
-
const fieldName = target.unknown ? target.blackName : target.field.name;
|
|
304
|
-
return !rootFields.has(fieldName);
|
|
305
|
-
}
|
|
306
|
-
SkipFieldValue(reader, target) {
|
|
307
|
-
if (target.unknown) {
|
|
308
|
-
this.ReadUnknownFieldValue(reader, null, target.blackName);
|
|
309
|
-
return;
|
|
310
|
-
}
|
|
311
|
-
CjsBlackPropertyReaders.skipValue(reader, target.field);
|
|
312
|
-
}
|
|
313
|
-
SkipObject(reader) {
|
|
314
|
-
const blackReference = reader.ReadU32();
|
|
315
|
-
if (blackReference === 0) return;
|
|
316
|
-
if (this.references.has(blackReference)) return;
|
|
317
|
-
this.references.set(blackReference, this.CreateSkippedPayloadTarget());
|
|
318
|
-
this.SkipObjectPayload(reader);
|
|
319
|
-
}
|
|
320
|
-
SkipEmbeddedObject(reader) {
|
|
321
|
-
this.SkipObjectPayload(reader);
|
|
322
|
-
}
|
|
323
|
-
SkipObjectPayload(reader) {
|
|
324
|
-
const payloadSize = reader.ReadU32();
|
|
325
|
-
const objectReader = reader.ReadBinaryReader(payloadSize);
|
|
326
|
-
const kind = objectReader.ReadStringRef();
|
|
327
|
-
const shape = this.ResolveSourceShape(kind);
|
|
328
|
-
while (!objectReader.AtEnd()) {
|
|
329
|
-
const blackName = objectReader.ReadStringRef();
|
|
330
|
-
const fieldTarget = this.ResolveFieldTarget(kind, shape, blackName);
|
|
331
|
-
this.SkipFieldValue(objectReader, fieldTarget);
|
|
332
|
-
}
|
|
333
|
-
objectReader.ExpectEnd(`${kind} did not read to end`);
|
|
334
|
-
}
|
|
335
|
-
ShouldIncludeClassMetadata() {
|
|
336
|
-
return Boolean(this.options.includeClassMetadata || this.options.trace || this.options.debug);
|
|
337
|
-
}
|
|
338
|
-
ShouldIncludeFieldTrace() {
|
|
339
|
-
return Boolean(this.options.includeFieldTrace || this.options.trace || this.options.debug);
|
|
340
|
-
}
|
|
341
|
-
ShouldIncludeDocumentMetadata() {
|
|
342
|
-
return Boolean(this.options.includeMetadata || this.options.trace || this.options.debug || this.options.metadata);
|
|
343
|
-
}
|
|
344
|
-
ShouldIncludeRefIndex() {
|
|
345
|
-
return Boolean(this.options.includeRefIndex || this.options.trace || this.options.debug);
|
|
346
|
-
}
|
|
347
|
-
CreateDocumentMetadata(info) {
|
|
348
|
-
if (!this.ShouldIncludeDocumentMetadata()) return this.options.metadata || null;
|
|
349
|
-
return {
|
|
350
|
-
black: {
|
|
351
|
-
stringCount: info.strings.length,
|
|
352
|
-
wideStringCount: info.wideStrings.length,
|
|
353
|
-
wideStrings: info.wideStrings.slice()
|
|
354
|
-
},
|
|
355
|
-
...(this.options.metadata || {})
|
|
356
|
-
};
|
|
357
|
-
}
|
|
358
|
-
ResolveFieldTargetWithContext(kind, shape, blackName, previousBlackName = null) {
|
|
359
|
-
try {
|
|
360
|
-
return this.ResolveFieldTarget(kind, shape, blackName);
|
|
361
|
-
} catch (error) {
|
|
362
|
-
error.message = `${kind}.${blackName} after ${previousBlackName || "<start>"}: ${error.message}`;
|
|
363
|
-
throw error;
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
ReadFieldValueWithContext(reader, kind, blackName, target) {
|
|
367
|
-
try {
|
|
368
|
-
return target.unknown ? this.ReadUnknownFieldValue(reader, kind, blackName) : CjsBlackPropertyReaders.readValue(reader, target.field);
|
|
369
|
-
} catch (error) {
|
|
370
|
-
error.message = `${kind}.${blackName}: ${error.message}`;
|
|
371
|
-
throw error;
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
AssignFieldValue(node, target, value) {
|
|
375
|
-
if (target.unknown) {
|
|
376
|
-
node.raw = node.raw || {};
|
|
377
|
-
node.raw[target.blackName] = value;
|
|
378
|
-
this.AssignFieldTrace(node, target);
|
|
379
|
-
return;
|
|
380
|
-
}
|
|
381
|
-
if (target.indexed) {
|
|
382
|
-
let current = node.fields[target.field.name];
|
|
383
|
-
if (!current || typeof current !== "object" || CjsCarbonDocument.isRef(current)) {
|
|
384
|
-
current = Number.isInteger(target.index) ? [] : {};
|
|
385
|
-
node.fields[target.field.name] = current;
|
|
386
|
-
}
|
|
387
|
-
current[target.key] = value;
|
|
388
|
-
} else {
|
|
389
|
-
node.fields[target.field.name] = value;
|
|
390
|
-
}
|
|
391
|
-
this.AssignFieldTrace(node, target);
|
|
392
|
-
}
|
|
393
|
-
AssignFieldTrace(node, target) {
|
|
394
|
-
if (!this.ShouldIncludeFieldTrace()) return;
|
|
395
|
-
node.meta.black.fields[target.blackName] = {
|
|
396
|
-
field: target.field.name,
|
|
397
|
-
cppName: target.field.cppName || null,
|
|
398
|
-
member: target.member,
|
|
399
|
-
indexed: target.indexed,
|
|
400
|
-
indexToken: target.indexToken,
|
|
401
|
-
key: target.key
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
ResolveFieldTarget(kind, shape, blackName) {
|
|
405
|
-
if (!shape) {
|
|
406
|
-
throw new TypeError(`No source shape registered for Black type ${kind}`);
|
|
407
|
-
}
|
|
408
|
-
const fields = shape.fields || [];
|
|
409
|
-
const blackField = (shape.black?.fields || []).find(item => CjsBlackSchemaRegistry.matchesBlackFieldName(item, blackName));
|
|
410
|
-
if (blackField) {
|
|
411
|
-
return this.ResolveBlackFieldTarget(blackName, blackField, fields);
|
|
412
|
-
}
|
|
413
|
-
const field = fields.find(item => item.name === blackName || item.cppName === blackName);
|
|
414
|
-
if (field) {
|
|
415
|
-
return {
|
|
416
|
-
blackName,
|
|
417
|
-
wireName: blackName,
|
|
418
|
-
field,
|
|
419
|
-
member: blackName,
|
|
420
|
-
indexed: false,
|
|
421
|
-
indexToken: null,
|
|
422
|
-
index: null,
|
|
423
|
-
key: null
|
|
424
|
-
};
|
|
425
|
-
}
|
|
426
|
-
const indexed = CjsBlackReader.parseIndexedMember(blackName);
|
|
427
|
-
if (indexed) {
|
|
428
|
-
const indexedField = fields.find(item => item.cppName === indexed.member || item.name === CjsBlackReader.toJsFieldName(indexed.member));
|
|
429
|
-
if (indexedField) {
|
|
430
|
-
const key = CjsBlackReader.normalizeIndexedKey(indexed.indexToken, indexedField);
|
|
431
|
-
return {
|
|
432
|
-
blackName,
|
|
433
|
-
wireName: blackName,
|
|
434
|
-
field: indexedField,
|
|
435
|
-
member: blackName,
|
|
436
|
-
indexed: true,
|
|
437
|
-
indexToken: indexed.indexToken,
|
|
438
|
-
index: Number.isInteger(key) ? key : null,
|
|
439
|
-
key
|
|
440
|
-
};
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
if (this.ShouldCaptureUnknownField(blackName, kind, shape)) {
|
|
444
|
-
return this.ResolveUnknownFieldTarget(kind, shape, blackName);
|
|
445
|
-
}
|
|
446
|
-
throw new TypeError(`Unknown Black property ${blackName} for ${kind}`);
|
|
447
|
-
}
|
|
448
|
-
ReadUnknownFieldValue(reader, kind, blackName) {
|
|
449
|
-
const readers = this.GetUnknownFieldReaders(blackName);
|
|
450
|
-
const errors = [];
|
|
451
|
-
for (const readValue of readers) {
|
|
452
|
-
const startOffset = reader.offset;
|
|
453
|
-
try {
|
|
454
|
-
return readValue(reader);
|
|
455
|
-
} catch (error) {
|
|
456
|
-
reader.offset = startOffset;
|
|
457
|
-
errors.push(error);
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
this.reports.push({
|
|
461
|
-
level: "warning",
|
|
462
|
-
code: "unknown-black-property-unreadable",
|
|
463
|
-
kind,
|
|
464
|
-
blackName
|
|
465
|
-
});
|
|
466
|
-
throw errors[0] || new TypeError(`Unable to read unknown Black field ${blackName} for ${kind}`);
|
|
467
|
-
}
|
|
468
|
-
GetUnknownFieldReaders(blackName) {
|
|
469
|
-
const readers = [];
|
|
470
|
-
const readByKind = (kind, options = null) => {
|
|
471
|
-
const field = options ? {
|
|
472
|
-
...options,
|
|
473
|
-
kind
|
|
474
|
-
} : {
|
|
475
|
-
kind
|
|
476
|
-
};
|
|
477
|
-
readers.push(streamReader => CjsBlackPropertyReaders.readValue(streamReader, field));
|
|
478
|
-
};
|
|
479
|
-
const readByDescriptor = (descriptor = {}) => {
|
|
480
|
-
readers.push(streamReader => CjsBlackPropertyReaders.readValue(streamReader, descriptor));
|
|
481
|
-
};
|
|
482
|
-
if (this.options.allowUnknownStringFallback) {
|
|
483
|
-
readByKind("string");
|
|
484
|
-
readByKind("path");
|
|
485
|
-
}
|
|
486
|
-
const name = String(blackName || "");
|
|
487
|
-
if (name.endsWith(".dds") || name.endsWith(".png") || name.endsWith(".jpg") || /^res:\//.test(name)) {
|
|
488
|
-
readers.unshift(streamReader => CjsBlackPropertyReaders.readValue(streamReader, {
|
|
489
|
-
kind: "path"
|
|
490
|
-
}));
|
|
491
|
-
readByKind("uint32");
|
|
492
|
-
readByKind("float32");
|
|
493
|
-
}
|
|
494
|
-
if (!this.options.allowUnknownStringFallback) {
|
|
495
|
-
readByKind("path");
|
|
496
|
-
readByKind("string");
|
|
497
|
-
}
|
|
498
|
-
readByKind("objectRef");
|
|
499
|
-
readByKind("boolean");
|
|
500
|
-
readByKind("float32");
|
|
501
|
-
readByKind("float64");
|
|
502
|
-
readByKind("int32");
|
|
503
|
-
readByKind("uint32");
|
|
504
|
-
readByKind("int16");
|
|
505
|
-
readByKind("uint16");
|
|
506
|
-
readByKind("int8");
|
|
507
|
-
readByKind("uint8");
|
|
508
|
-
readByDescriptor({
|
|
509
|
-
kind: "vector3"
|
|
510
|
-
});
|
|
511
|
-
readByDescriptor({
|
|
512
|
-
kind: "vector4"
|
|
513
|
-
});
|
|
514
|
-
readByDescriptor({
|
|
515
|
-
kind: "array",
|
|
516
|
-
elementType: {
|
|
517
|
-
kind: "uint32"
|
|
518
|
-
}
|
|
519
|
-
});
|
|
520
|
-
return readers;
|
|
521
|
-
}
|
|
522
|
-
ResolveBlackFieldTarget(blackName, blackField, fields) {
|
|
523
|
-
const sourceField = fields.find(item => item.name === blackField.fieldName || item.name === blackField.name || item.cppName === blackField.cppName || item.cppName === blackField.memberPath || item.cppName === blackField.memberRoot);
|
|
524
|
-
const fieldName = blackField.fieldName || sourceField?.name || blackField.name || CjsBlackReader.toJsFieldName(blackName);
|
|
525
|
-
Boolean(blackField.name && blackField.name !== blackField.fieldName);
|
|
526
|
-
const field = {
|
|
527
|
-
...(sourceField || {}),
|
|
528
|
-
name: fieldName,
|
|
529
|
-
cppName: blackField.cppName || sourceField?.cppName || null,
|
|
530
|
-
cppType: blackField.cppType || sourceField?.cppType || null,
|
|
531
|
-
black: blackField
|
|
532
|
-
};
|
|
533
|
-
const hasIndex = Boolean(blackField.indexToken || blackField.indexKey !== undefined);
|
|
534
|
-
const storageKey = hasIndex ? blackField.indexKey ?? CjsBlackReader.normalizeIndexedKey(blackField.indexToken, field) : null;
|
|
535
|
-
const indexed = Boolean(hasIndex);
|
|
536
|
-
return {
|
|
537
|
-
blackName,
|
|
538
|
-
wireName: blackName,
|
|
539
|
-
field,
|
|
540
|
-
member: blackField.member || blackName,
|
|
541
|
-
indexed,
|
|
542
|
-
indexToken: blackField.indexToken || null,
|
|
543
|
-
index: Number.isInteger(storageKey) ? storageKey : null,
|
|
544
|
-
key: storageKey
|
|
545
|
-
};
|
|
546
|
-
}
|
|
547
|
-
ResolveUnknownFieldTarget(_kind, _shape, blackName) {
|
|
548
|
-
return {
|
|
549
|
-
blackName,
|
|
550
|
-
wireName: blackName,
|
|
551
|
-
field: {
|
|
552
|
-
name: "__blackUnknown",
|
|
553
|
-
cppName: null,
|
|
554
|
-
cppType: null,
|
|
555
|
-
black: {
|
|
556
|
-
fieldName: "__blackUnknown",
|
|
557
|
-
name: blackName,
|
|
558
|
-
memberPath: blackName,
|
|
559
|
-
memberRoot: blackName,
|
|
560
|
-
beType: "UNKNOWN"
|
|
561
|
-
}
|
|
562
|
-
},
|
|
563
|
-
member: blackName,
|
|
564
|
-
indexed: false,
|
|
565
|
-
indexToken: null,
|
|
566
|
-
index: null,
|
|
567
|
-
key: blackName,
|
|
568
|
-
unknown: true
|
|
569
|
-
};
|
|
570
|
-
}
|
|
571
|
-
ShouldCaptureUnknownField(blackName, _kind, shape) {
|
|
572
|
-
if (this.options.captureUnknownBlackFields) return true;
|
|
573
|
-
if (this.options.captureUnknownResourceFields && /^res:\//.test(String(blackName || ""))) return true;
|
|
574
|
-
if (this.options.captureUnknownWhenNoBlackFields && (!shape?.black || !shape.black.fields || !shape.black.fields.length)) return true;
|
|
575
|
-
return false;
|
|
576
|
-
}
|
|
577
|
-
ResolveClass(kind) {
|
|
578
|
-
const classes = this.options.classes || {};
|
|
579
|
-
const Schema = this.options.registry || CjsSchema;
|
|
580
|
-
return classes[kind] || Schema.GetConstructor(kind);
|
|
581
|
-
}
|
|
582
|
-
ResetReadState() {
|
|
583
|
-
super.ResetBlueReadState();
|
|
584
|
-
this.references = new Map();
|
|
585
|
-
this.nodes = [];
|
|
586
|
-
this.nextNodeId = this.options.firstId || 1;
|
|
587
|
-
this.payloadDepth = 0;
|
|
588
|
-
this.payloadRootFields = null;
|
|
589
|
-
}
|
|
590
|
-
static readStringTable(reader) {
|
|
591
|
-
const stringsReader = reader.ReadBinaryReader(reader.ReadU32());
|
|
592
|
-
const count = stringsReader.ReadU16();
|
|
593
|
-
const strings = [];
|
|
594
|
-
for (let i = 0; i < count; i++) {
|
|
595
|
-
strings[i] = stringsReader.ReadCString();
|
|
596
|
-
}
|
|
597
|
-
stringsReader.ExpectEnd("Black string table did not read to end");
|
|
598
|
-
return strings;
|
|
599
|
-
}
|
|
600
|
-
static readWideStringTable(reader) {
|
|
601
|
-
const wideStringsReader = reader.ReadBinaryReader(reader.ReadU32());
|
|
602
|
-
const count = wideStringsReader.ReadU16();
|
|
603
|
-
const wideStrings = [];
|
|
604
|
-
for (let i = 0; i < count; i++) {
|
|
605
|
-
wideStrings[i] = wideStringsReader.ReadCWString();
|
|
606
|
-
}
|
|
607
|
-
wideStringsReader.ExpectEnd("Black wide string table did not read to end");
|
|
608
|
-
return wideStrings;
|
|
609
|
-
}
|
|
610
|
-
static normalizeIndexedKey(indexToken, field) {
|
|
611
|
-
const number = Number(indexToken);
|
|
612
|
-
if (Number.isInteger(number) && String(indexToken).trim() === String(number)) return number;
|
|
613
|
-
let text = String(indexToken || "").trim();
|
|
614
|
-
text = text.replace(/^.*::/, "");
|
|
615
|
-
text = text.replace(/^TYPE_/, "");
|
|
616
|
-
const pascal = text.split(/[^A-Za-z0-9]+/).filter(Boolean).map(part => CJS_BLACK_INDEX_TOKEN_NAMES[part] || (part === "FX" ? "FX" : part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())).join("");
|
|
617
|
-
if (field?.jsType?.kind === "objectRef") {
|
|
618
|
-
return pascal ? pascal.charAt(0).toLowerCase() + pascal.slice(1) : text;
|
|
619
|
-
}
|
|
620
|
-
return pascal || text;
|
|
621
|
-
}
|
|
622
|
-
static parseIndexedMember(value) {
|
|
623
|
-
const match = String(value || "").match(/^(.+)\[([^\]]+)\]$/);
|
|
624
|
-
if (!match) return null;
|
|
625
|
-
return {
|
|
626
|
-
member: match[1],
|
|
627
|
-
indexToken: match[2]
|
|
628
|
-
};
|
|
629
|
-
}
|
|
630
|
-
static toJsFieldName(value) {
|
|
631
|
-
return String(value || "").replace(/^m_/, "");
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
const CJS_BLACK_INDEX_TOKEN_NAMES = Object.freeze({
|
|
635
|
-
SIMPLEPRIMARY: "SimplePrimary"
|
|
636
|
-
});
|
|
637
|
-
|
|
638
|
-
export { CjsBlackReader };
|
|
639
|
-
//# sourceMappingURL=CjsBlackReader.js.map
|
|
1
|
+
import { CjsCarbonDocument } from '@carbonenginejs/core-types/document';
|
|
2
|
+
import { CjsSchema } from '@carbonenginejs/core-types/schema';
|
|
3
|
+
import { CjsBlueReader } from '../../../format/CjsBlueReader.js';
|
|
4
|
+
import { CJS_BLACK_FOURCC, CJS_BLACK_VERSION, CJS_BLACK_FORMAT_ID } from './blackConstants.js';
|
|
5
|
+
import { CjsBlackBinaryReader } from './CjsBlackBinaryReader.js';
|
|
6
|
+
import { CjsBlackPropertyReaders } from './CjsBlackPropertyReaders.js';
|
|
7
|
+
import { CjsBlackSchemaRegistry } from './CjsBlackSchemaRegistry.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Reads a `.black` stream into a payload/document/runtime graph.
|
|
11
|
+
*
|
|
12
|
+
* This transport owns the binary buffer, string tables, numeric references,
|
|
13
|
+
* and binary read cursor. `ResetReadState()` clears only per-read graph state;
|
|
14
|
+
* each read entrypoint separately restores the cursor to `dataOffset`.
|
|
15
|
+
*/
|
|
16
|
+
class CjsBlackReader extends CjsBlueReader {
|
|
17
|
+
constructor(input, options = {}) {
|
|
18
|
+
super(options, {
|
|
19
|
+
schemaRegistry: CjsBlackSchemaRegistry,
|
|
20
|
+
defaultRegistry: CjsSchema,
|
|
21
|
+
includeShapeContext: true,
|
|
22
|
+
includeSourceShape: true,
|
|
23
|
+
includeEmptyPayloadType: true,
|
|
24
|
+
requirePayloadReferenceTarget: true
|
|
25
|
+
});
|
|
26
|
+
this.reader = CjsBlackBinaryReader.from(input, this);
|
|
27
|
+
this.references = new Map();
|
|
28
|
+
this.nodes = [];
|
|
29
|
+
this.nextNodeId = 1;
|
|
30
|
+
this.info = null;
|
|
31
|
+
this.readMode = "payload";
|
|
32
|
+
this.payloadDepth = 0;
|
|
33
|
+
this.payloadRootFields = null;
|
|
34
|
+
}
|
|
35
|
+
Inspect() {
|
|
36
|
+
if (this.info) return this.info;
|
|
37
|
+
const reader = this.reader;
|
|
38
|
+
reader.ExpectU32(CJS_BLACK_FOURCC, "Invalid Black FOURCC");
|
|
39
|
+
const version = reader.ReadU32();
|
|
40
|
+
if (version !== CJS_BLACK_VERSION) {
|
|
41
|
+
throw new RangeError(`Unsupported Black version: ${version}`);
|
|
42
|
+
}
|
|
43
|
+
const strings = CjsBlackReader.readStringTable(reader);
|
|
44
|
+
const wideStrings = CjsBlackReader.readWideStringTable(reader);
|
|
45
|
+
this.info = {
|
|
46
|
+
format: {
|
|
47
|
+
id: CJS_BLACK_FORMAT_ID,
|
|
48
|
+
version
|
|
49
|
+
},
|
|
50
|
+
byteLength: reader.data.byteLength,
|
|
51
|
+
dataOffset: reader.offset,
|
|
52
|
+
strings,
|
|
53
|
+
wideStrings
|
|
54
|
+
};
|
|
55
|
+
return this.info;
|
|
56
|
+
}
|
|
57
|
+
Read() {
|
|
58
|
+
return this.ReadPayload();
|
|
59
|
+
}
|
|
60
|
+
ReadDocument() {
|
|
61
|
+
const info = this.Inspect();
|
|
62
|
+
this.ResetReadState();
|
|
63
|
+
this.readMode = "document";
|
|
64
|
+
this.reader.offset = info.dataOffset;
|
|
65
|
+
const rootRef = this.ReadObject(this.reader);
|
|
66
|
+
if (!CjsCarbonDocument.isRef(rootRef)) {
|
|
67
|
+
throw new TypeError("Black root object is null");
|
|
68
|
+
}
|
|
69
|
+
this.reader.ExpectEnd("Black object graph did not read to end");
|
|
70
|
+
const includeRefIndex = this.ShouldIncludeRefIndex();
|
|
71
|
+
const refs = {};
|
|
72
|
+
if (includeRefIndex) {
|
|
73
|
+
for (const node of this.nodes) {
|
|
74
|
+
refs[String(node.id)] = {
|
|
75
|
+
kind: node.kind
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return CjsCarbonDocument.create({
|
|
80
|
+
format: info.format,
|
|
81
|
+
roots: [{
|
|
82
|
+
name: this.options.rootName || "default",
|
|
83
|
+
ref: rootRef
|
|
84
|
+
}],
|
|
85
|
+
nodes: this.nodes,
|
|
86
|
+
refs: includeRefIndex ? refs : null,
|
|
87
|
+
metadata: this.CreateDocumentMetadata(info),
|
|
88
|
+
reports: this.reports
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
ReadRuntime() {
|
|
92
|
+
const info = this.Inspect();
|
|
93
|
+
this.ResetReadState();
|
|
94
|
+
this.readMode = "runtime";
|
|
95
|
+
this.reader.offset = info.dataOffset;
|
|
96
|
+
const root = this.ReadObject(this.reader);
|
|
97
|
+
if (root === null) {
|
|
98
|
+
throw new TypeError("Black root object is null");
|
|
99
|
+
}
|
|
100
|
+
this.reader.ExpectEnd("Black object graph did not read to end");
|
|
101
|
+
this.FinalizeRuntimeInstances();
|
|
102
|
+
return {
|
|
103
|
+
root,
|
|
104
|
+
format: info.format,
|
|
105
|
+
reports: this.reports
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
ReadPayload() {
|
|
109
|
+
const info = this.Inspect();
|
|
110
|
+
this.ResetReadState();
|
|
111
|
+
this.readMode = "payload";
|
|
112
|
+
this.ValidatePayloadConfiguration();
|
|
113
|
+
this.reader.offset = info.dataOffset;
|
|
114
|
+
const object = this.ReadObject(this.reader);
|
|
115
|
+
if (object === null) {
|
|
116
|
+
throw new TypeError("Black root object is null");
|
|
117
|
+
}
|
|
118
|
+
this.reader.ExpectEnd("Black object graph did not read to end");
|
|
119
|
+
const payload = {
|
|
120
|
+
comments: this.reports,
|
|
121
|
+
object
|
|
122
|
+
};
|
|
123
|
+
if (this.ShouldIncludeDocumentMetadata()) {
|
|
124
|
+
payload.metadata = this.CreateDocumentMetadata(info);
|
|
125
|
+
}
|
|
126
|
+
return payload;
|
|
127
|
+
}
|
|
128
|
+
ReadObject(reader) {
|
|
129
|
+
if (this.readMode === "runtime") return this.ReadRuntimeObject(reader);
|
|
130
|
+
if (this.readMode === "payload") return this.ReadPayloadObject(reader);
|
|
131
|
+
const blackReference = reader.ReadU32();
|
|
132
|
+
if (blackReference === 0) return null;
|
|
133
|
+
const existing = this.references.get(blackReference);
|
|
134
|
+
if (existing) return CjsCarbonDocument.createRef(existing);
|
|
135
|
+
return this.ReadObjectPayload(reader, {
|
|
136
|
+
blackReference,
|
|
137
|
+
embedded: false
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
ReadEmbeddedObject(reader) {
|
|
141
|
+
if (this.readMode === "runtime") return this.ReadRuntimeObjectPayload(reader, {
|
|
142
|
+
blackReference: null,
|
|
143
|
+
embedded: true
|
|
144
|
+
});
|
|
145
|
+
if (this.readMode === "payload") return this.ReadPayloadObjectPayload(reader, {
|
|
146
|
+
blackReference: null,
|
|
147
|
+
embedded: true
|
|
148
|
+
});
|
|
149
|
+
return this.ReadObjectPayload(reader, {
|
|
150
|
+
blackReference: null,
|
|
151
|
+
embedded: true
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
ReadObjectPayload(reader, options) {
|
|
155
|
+
const payloadSize = reader.ReadU32();
|
|
156
|
+
const objectReader = reader.ReadBinaryReader(payloadSize);
|
|
157
|
+
const kind = objectReader.ReadStringRef();
|
|
158
|
+
const shape = this.ResolveSourceShape(kind);
|
|
159
|
+
const includeClassMetadata = this.ShouldIncludeClassMetadata();
|
|
160
|
+
const includeFieldTrace = this.ShouldIncludeFieldTrace();
|
|
161
|
+
const node = {
|
|
162
|
+
id: this.nextNodeId++,
|
|
163
|
+
kind,
|
|
164
|
+
fields: {},
|
|
165
|
+
...(includeClassMetadata ? {
|
|
166
|
+
source: shape?.source || {},
|
|
167
|
+
meta: {
|
|
168
|
+
family: shape?.family || null,
|
|
169
|
+
hashes: shape?.hashes || null,
|
|
170
|
+
blue: shape?.blue || null
|
|
171
|
+
}
|
|
172
|
+
} : {}),
|
|
173
|
+
...(includeFieldTrace ? {
|
|
174
|
+
meta: {
|
|
175
|
+
...(includeClassMetadata ? {
|
|
176
|
+
family: shape?.family || null,
|
|
177
|
+
hashes: shape?.hashes || null,
|
|
178
|
+
blue: shape?.blue || null
|
|
179
|
+
} : {}),
|
|
180
|
+
black: {
|
|
181
|
+
reference: options.blackReference,
|
|
182
|
+
embedded: options.embedded,
|
|
183
|
+
payloadSize,
|
|
184
|
+
fields: {}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
} : {}),
|
|
188
|
+
raw: null
|
|
189
|
+
};
|
|
190
|
+
this.nodes.push(node);
|
|
191
|
+
if (options.blackReference !== null) {
|
|
192
|
+
this.references.set(options.blackReference, node.id);
|
|
193
|
+
}
|
|
194
|
+
let previousBlackName = null;
|
|
195
|
+
while (!objectReader.AtEnd()) {
|
|
196
|
+
const blackName = objectReader.ReadStringRef();
|
|
197
|
+
const target = this.ResolveFieldTargetWithContext(kind, shape, blackName, previousBlackName);
|
|
198
|
+
const value = this.ReadFieldValueWithContext(objectReader, kind, blackName, target);
|
|
199
|
+
this.AssignFieldValue(node, target, value);
|
|
200
|
+
previousBlackName = blackName;
|
|
201
|
+
}
|
|
202
|
+
objectReader.ExpectEnd(`${kind} did not read to end`);
|
|
203
|
+
return CjsCarbonDocument.createRef(node.id);
|
|
204
|
+
}
|
|
205
|
+
ReadRuntimeObject(reader) {
|
|
206
|
+
const blackReference = reader.ReadU32();
|
|
207
|
+
if (blackReference === 0) return null;
|
|
208
|
+
if (this.references.has(blackReference)) {
|
|
209
|
+
return this.references.get(blackReference);
|
|
210
|
+
}
|
|
211
|
+
return this.ReadRuntimeObjectPayload(reader, {
|
|
212
|
+
blackReference,
|
|
213
|
+
embedded: false
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
ReadRuntimeObjectPayload(reader, options) {
|
|
217
|
+
const payloadSize = reader.ReadU32();
|
|
218
|
+
const objectReader = reader.ReadBinaryReader(payloadSize);
|
|
219
|
+
const kind = objectReader.ReadStringRef();
|
|
220
|
+
const shape = this.ResolveSourceShape(kind);
|
|
221
|
+
const target = this.CreateRuntimeTarget(kind, shape);
|
|
222
|
+
if (options.blackReference !== null) {
|
|
223
|
+
this.references.set(options.blackReference, target);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Accumulate this object's fields into a plain values map, then hand
|
|
227
|
+
// the whole map to the hydration adapter. The adapter (default:
|
|
228
|
+
// Object.assign) decides how the caller's class receives its values -
|
|
229
|
+
// direct assignment, SetValues, etc. The target instance is already
|
|
230
|
+
// registered above, so back-references resolve to it while its values
|
|
231
|
+
// are still being collected (the adapter must mutate in place).
|
|
232
|
+
const values = {};
|
|
233
|
+
let previousBlackName = null;
|
|
234
|
+
while (!objectReader.AtEnd()) {
|
|
235
|
+
const blackName = objectReader.ReadStringRef();
|
|
236
|
+
const fieldTarget = this.ResolveFieldTargetWithContext(kind, shape, blackName, previousBlackName);
|
|
237
|
+
const value = this.ReadFieldValueWithContext(objectReader, kind, blackName, fieldTarget);
|
|
238
|
+
this.AssignRuntimeFieldValue(values, fieldTarget, value);
|
|
239
|
+
previousBlackName = blackName;
|
|
240
|
+
}
|
|
241
|
+
objectReader.ExpectEnd(`${kind} did not read to end`);
|
|
242
|
+
this.ApplyRuntimeValues(target, values, kind, shape);
|
|
243
|
+
return target;
|
|
244
|
+
}
|
|
245
|
+
ReadPayloadObject(reader) {
|
|
246
|
+
const blackReference = reader.ReadU32();
|
|
247
|
+
if (blackReference === 0) return null;
|
|
248
|
+
if (this.references.has(blackReference)) {
|
|
249
|
+
return this.CreatePayloadReference(this.references.get(blackReference), blackReference);
|
|
250
|
+
}
|
|
251
|
+
return this.ReadPayloadObjectPayload(reader, {
|
|
252
|
+
blackReference,
|
|
253
|
+
embedded: false
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
ReadPayloadObjectPayload(reader, options) {
|
|
257
|
+
const payloadSize = reader.ReadU32();
|
|
258
|
+
const objectReader = reader.ReadBinaryReader(payloadSize);
|
|
259
|
+
const kind = objectReader.ReadStringRef();
|
|
260
|
+
const shape = this.ResolveSourceShape(kind);
|
|
261
|
+
const target = this.CreatePayloadTarget(kind);
|
|
262
|
+
if (options.blackReference !== null) {
|
|
263
|
+
this.references.set(options.blackReference, target);
|
|
264
|
+
}
|
|
265
|
+
this.payloadDepth++;
|
|
266
|
+
try {
|
|
267
|
+
let previousBlackName = null;
|
|
268
|
+
while (!objectReader.AtEnd()) {
|
|
269
|
+
const blackName = objectReader.ReadStringRef();
|
|
270
|
+
const fieldTarget = this.ResolveFieldTargetWithContext(kind, shape, blackName, previousBlackName);
|
|
271
|
+
if (this.ShouldSkipPayloadField(fieldTarget)) {
|
|
272
|
+
this.SkipFieldValue(objectReader, fieldTarget);
|
|
273
|
+
previousBlackName = blackName;
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
const value = this.ReadFieldValueWithContext(objectReader, kind, blackName, fieldTarget);
|
|
277
|
+
this.AssignPayloadFieldValue(target, fieldTarget, value);
|
|
278
|
+
previousBlackName = blackName;
|
|
279
|
+
}
|
|
280
|
+
} finally {
|
|
281
|
+
this.payloadDepth--;
|
|
282
|
+
}
|
|
283
|
+
objectReader.ExpectEnd(`${kind} did not read to end`);
|
|
284
|
+
return target;
|
|
285
|
+
}
|
|
286
|
+
CreateSkippedPayloadTarget() {
|
|
287
|
+
return {};
|
|
288
|
+
}
|
|
289
|
+
GetPayloadRootFields() {
|
|
290
|
+
if (this.payloadRootFields !== null) return this.payloadRootFields;
|
|
291
|
+
const fields = this.options.payloadRootFields ?? this.options.rootFields ?? null;
|
|
292
|
+
if (!fields) {
|
|
293
|
+
this.payloadRootFields = false;
|
|
294
|
+
return this.payloadRootFields;
|
|
295
|
+
}
|
|
296
|
+
this.payloadRootFields = new Set((Array.isArray(fields) ? fields : [fields]).map(String));
|
|
297
|
+
return this.payloadRootFields;
|
|
298
|
+
}
|
|
299
|
+
ShouldSkipPayloadField(target) {
|
|
300
|
+
if (this.readMode !== "payload" || this.payloadDepth !== 1) return false;
|
|
301
|
+
const rootFields = this.GetPayloadRootFields();
|
|
302
|
+
if (!rootFields) return false;
|
|
303
|
+
const fieldName = target.unknown ? target.blackName : target.field.name;
|
|
304
|
+
return !rootFields.has(fieldName);
|
|
305
|
+
}
|
|
306
|
+
SkipFieldValue(reader, target) {
|
|
307
|
+
if (target.unknown) {
|
|
308
|
+
this.ReadUnknownFieldValue(reader, null, target.blackName);
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
CjsBlackPropertyReaders.skipValue(reader, target.field);
|
|
312
|
+
}
|
|
313
|
+
SkipObject(reader) {
|
|
314
|
+
const blackReference = reader.ReadU32();
|
|
315
|
+
if (blackReference === 0) return;
|
|
316
|
+
if (this.references.has(blackReference)) return;
|
|
317
|
+
this.references.set(blackReference, this.CreateSkippedPayloadTarget());
|
|
318
|
+
this.SkipObjectPayload(reader);
|
|
319
|
+
}
|
|
320
|
+
SkipEmbeddedObject(reader) {
|
|
321
|
+
this.SkipObjectPayload(reader);
|
|
322
|
+
}
|
|
323
|
+
SkipObjectPayload(reader) {
|
|
324
|
+
const payloadSize = reader.ReadU32();
|
|
325
|
+
const objectReader = reader.ReadBinaryReader(payloadSize);
|
|
326
|
+
const kind = objectReader.ReadStringRef();
|
|
327
|
+
const shape = this.ResolveSourceShape(kind);
|
|
328
|
+
while (!objectReader.AtEnd()) {
|
|
329
|
+
const blackName = objectReader.ReadStringRef();
|
|
330
|
+
const fieldTarget = this.ResolveFieldTarget(kind, shape, blackName);
|
|
331
|
+
this.SkipFieldValue(objectReader, fieldTarget);
|
|
332
|
+
}
|
|
333
|
+
objectReader.ExpectEnd(`${kind} did not read to end`);
|
|
334
|
+
}
|
|
335
|
+
ShouldIncludeClassMetadata() {
|
|
336
|
+
return Boolean(this.options.includeClassMetadata || this.options.trace || this.options.debug);
|
|
337
|
+
}
|
|
338
|
+
ShouldIncludeFieldTrace() {
|
|
339
|
+
return Boolean(this.options.includeFieldTrace || this.options.trace || this.options.debug);
|
|
340
|
+
}
|
|
341
|
+
ShouldIncludeDocumentMetadata() {
|
|
342
|
+
return Boolean(this.options.includeMetadata || this.options.trace || this.options.debug || this.options.metadata);
|
|
343
|
+
}
|
|
344
|
+
ShouldIncludeRefIndex() {
|
|
345
|
+
return Boolean(this.options.includeRefIndex || this.options.trace || this.options.debug);
|
|
346
|
+
}
|
|
347
|
+
CreateDocumentMetadata(info) {
|
|
348
|
+
if (!this.ShouldIncludeDocumentMetadata()) return this.options.metadata || null;
|
|
349
|
+
return {
|
|
350
|
+
black: {
|
|
351
|
+
stringCount: info.strings.length,
|
|
352
|
+
wideStringCount: info.wideStrings.length,
|
|
353
|
+
wideStrings: info.wideStrings.slice()
|
|
354
|
+
},
|
|
355
|
+
...(this.options.metadata || {})
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
ResolveFieldTargetWithContext(kind, shape, blackName, previousBlackName = null) {
|
|
359
|
+
try {
|
|
360
|
+
return this.ResolveFieldTarget(kind, shape, blackName);
|
|
361
|
+
} catch (error) {
|
|
362
|
+
error.message = `${kind}.${blackName} after ${previousBlackName || "<start>"}: ${error.message}`;
|
|
363
|
+
throw error;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
ReadFieldValueWithContext(reader, kind, blackName, target) {
|
|
367
|
+
try {
|
|
368
|
+
return target.unknown ? this.ReadUnknownFieldValue(reader, kind, blackName) : CjsBlackPropertyReaders.readValue(reader, target.field);
|
|
369
|
+
} catch (error) {
|
|
370
|
+
error.message = `${kind}.${blackName}: ${error.message}`;
|
|
371
|
+
throw error;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
AssignFieldValue(node, target, value) {
|
|
375
|
+
if (target.unknown) {
|
|
376
|
+
node.raw = node.raw || {};
|
|
377
|
+
node.raw[target.blackName] = value;
|
|
378
|
+
this.AssignFieldTrace(node, target);
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
if (target.indexed) {
|
|
382
|
+
let current = node.fields[target.field.name];
|
|
383
|
+
if (!current || typeof current !== "object" || CjsCarbonDocument.isRef(current)) {
|
|
384
|
+
current = Number.isInteger(target.index) ? [] : {};
|
|
385
|
+
node.fields[target.field.name] = current;
|
|
386
|
+
}
|
|
387
|
+
current[target.key] = value;
|
|
388
|
+
} else {
|
|
389
|
+
node.fields[target.field.name] = value;
|
|
390
|
+
}
|
|
391
|
+
this.AssignFieldTrace(node, target);
|
|
392
|
+
}
|
|
393
|
+
AssignFieldTrace(node, target) {
|
|
394
|
+
if (!this.ShouldIncludeFieldTrace()) return;
|
|
395
|
+
node.meta.black.fields[target.blackName] = {
|
|
396
|
+
field: target.field.name,
|
|
397
|
+
cppName: target.field.cppName || null,
|
|
398
|
+
member: target.member,
|
|
399
|
+
indexed: target.indexed,
|
|
400
|
+
indexToken: target.indexToken,
|
|
401
|
+
key: target.key
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
ResolveFieldTarget(kind, shape, blackName) {
|
|
405
|
+
if (!shape) {
|
|
406
|
+
throw new TypeError(`No source shape registered for Black type ${kind}`);
|
|
407
|
+
}
|
|
408
|
+
const fields = shape.fields || [];
|
|
409
|
+
const blackField = (shape.black?.fields || []).find(item => CjsBlackSchemaRegistry.matchesBlackFieldName(item, blackName));
|
|
410
|
+
if (blackField) {
|
|
411
|
+
return this.ResolveBlackFieldTarget(blackName, blackField, fields);
|
|
412
|
+
}
|
|
413
|
+
const field = fields.find(item => item.name === blackName || item.cppName === blackName);
|
|
414
|
+
if (field) {
|
|
415
|
+
return {
|
|
416
|
+
blackName,
|
|
417
|
+
wireName: blackName,
|
|
418
|
+
field,
|
|
419
|
+
member: blackName,
|
|
420
|
+
indexed: false,
|
|
421
|
+
indexToken: null,
|
|
422
|
+
index: null,
|
|
423
|
+
key: null
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
const indexed = CjsBlackReader.parseIndexedMember(blackName);
|
|
427
|
+
if (indexed) {
|
|
428
|
+
const indexedField = fields.find(item => item.cppName === indexed.member || item.name === CjsBlackReader.toJsFieldName(indexed.member));
|
|
429
|
+
if (indexedField) {
|
|
430
|
+
const key = CjsBlackReader.normalizeIndexedKey(indexed.indexToken, indexedField);
|
|
431
|
+
return {
|
|
432
|
+
blackName,
|
|
433
|
+
wireName: blackName,
|
|
434
|
+
field: indexedField,
|
|
435
|
+
member: blackName,
|
|
436
|
+
indexed: true,
|
|
437
|
+
indexToken: indexed.indexToken,
|
|
438
|
+
index: Number.isInteger(key) ? key : null,
|
|
439
|
+
key
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
if (this.ShouldCaptureUnknownField(blackName, kind, shape)) {
|
|
444
|
+
return this.ResolveUnknownFieldTarget(kind, shape, blackName);
|
|
445
|
+
}
|
|
446
|
+
throw new TypeError(`Unknown Black property ${blackName} for ${kind}`);
|
|
447
|
+
}
|
|
448
|
+
ReadUnknownFieldValue(reader, kind, blackName) {
|
|
449
|
+
const readers = this.GetUnknownFieldReaders(blackName);
|
|
450
|
+
const errors = [];
|
|
451
|
+
for (const readValue of readers) {
|
|
452
|
+
const startOffset = reader.offset;
|
|
453
|
+
try {
|
|
454
|
+
return readValue(reader);
|
|
455
|
+
} catch (error) {
|
|
456
|
+
reader.offset = startOffset;
|
|
457
|
+
errors.push(error);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
this.reports.push({
|
|
461
|
+
level: "warning",
|
|
462
|
+
code: "unknown-black-property-unreadable",
|
|
463
|
+
kind,
|
|
464
|
+
blackName
|
|
465
|
+
});
|
|
466
|
+
throw errors[0] || new TypeError(`Unable to read unknown Black field ${blackName} for ${kind}`);
|
|
467
|
+
}
|
|
468
|
+
GetUnknownFieldReaders(blackName) {
|
|
469
|
+
const readers = [];
|
|
470
|
+
const readByKind = (kind, options = null) => {
|
|
471
|
+
const field = options ? {
|
|
472
|
+
...options,
|
|
473
|
+
kind
|
|
474
|
+
} : {
|
|
475
|
+
kind
|
|
476
|
+
};
|
|
477
|
+
readers.push(streamReader => CjsBlackPropertyReaders.readValue(streamReader, field));
|
|
478
|
+
};
|
|
479
|
+
const readByDescriptor = (descriptor = {}) => {
|
|
480
|
+
readers.push(streamReader => CjsBlackPropertyReaders.readValue(streamReader, descriptor));
|
|
481
|
+
};
|
|
482
|
+
if (this.options.allowUnknownStringFallback) {
|
|
483
|
+
readByKind("string");
|
|
484
|
+
readByKind("path");
|
|
485
|
+
}
|
|
486
|
+
const name = String(blackName || "");
|
|
487
|
+
if (name.endsWith(".dds") || name.endsWith(".png") || name.endsWith(".jpg") || /^res:\//.test(name)) {
|
|
488
|
+
readers.unshift(streamReader => CjsBlackPropertyReaders.readValue(streamReader, {
|
|
489
|
+
kind: "path"
|
|
490
|
+
}));
|
|
491
|
+
readByKind("uint32");
|
|
492
|
+
readByKind("float32");
|
|
493
|
+
}
|
|
494
|
+
if (!this.options.allowUnknownStringFallback) {
|
|
495
|
+
readByKind("path");
|
|
496
|
+
readByKind("string");
|
|
497
|
+
}
|
|
498
|
+
readByKind("objectRef");
|
|
499
|
+
readByKind("boolean");
|
|
500
|
+
readByKind("float32");
|
|
501
|
+
readByKind("float64");
|
|
502
|
+
readByKind("int32");
|
|
503
|
+
readByKind("uint32");
|
|
504
|
+
readByKind("int16");
|
|
505
|
+
readByKind("uint16");
|
|
506
|
+
readByKind("int8");
|
|
507
|
+
readByKind("uint8");
|
|
508
|
+
readByDescriptor({
|
|
509
|
+
kind: "vector3"
|
|
510
|
+
});
|
|
511
|
+
readByDescriptor({
|
|
512
|
+
kind: "vector4"
|
|
513
|
+
});
|
|
514
|
+
readByDescriptor({
|
|
515
|
+
kind: "array",
|
|
516
|
+
elementType: {
|
|
517
|
+
kind: "uint32"
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
return readers;
|
|
521
|
+
}
|
|
522
|
+
ResolveBlackFieldTarget(blackName, blackField, fields) {
|
|
523
|
+
const sourceField = fields.find(item => item.name === blackField.fieldName || item.name === blackField.name || item.cppName === blackField.cppName || item.cppName === blackField.memberPath || item.cppName === blackField.memberRoot);
|
|
524
|
+
const fieldName = blackField.fieldName || sourceField?.name || blackField.name || CjsBlackReader.toJsFieldName(blackName);
|
|
525
|
+
Boolean(blackField.name && blackField.name !== blackField.fieldName);
|
|
526
|
+
const field = {
|
|
527
|
+
...(sourceField || {}),
|
|
528
|
+
name: fieldName,
|
|
529
|
+
cppName: blackField.cppName || sourceField?.cppName || null,
|
|
530
|
+
cppType: blackField.cppType || sourceField?.cppType || null,
|
|
531
|
+
black: blackField
|
|
532
|
+
};
|
|
533
|
+
const hasIndex = Boolean(blackField.indexToken || blackField.indexKey !== undefined);
|
|
534
|
+
const storageKey = hasIndex ? blackField.indexKey ?? CjsBlackReader.normalizeIndexedKey(blackField.indexToken, field) : null;
|
|
535
|
+
const indexed = Boolean(hasIndex);
|
|
536
|
+
return {
|
|
537
|
+
blackName,
|
|
538
|
+
wireName: blackName,
|
|
539
|
+
field,
|
|
540
|
+
member: blackField.member || blackName,
|
|
541
|
+
indexed,
|
|
542
|
+
indexToken: blackField.indexToken || null,
|
|
543
|
+
index: Number.isInteger(storageKey) ? storageKey : null,
|
|
544
|
+
key: storageKey
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
ResolveUnknownFieldTarget(_kind, _shape, blackName) {
|
|
548
|
+
return {
|
|
549
|
+
blackName,
|
|
550
|
+
wireName: blackName,
|
|
551
|
+
field: {
|
|
552
|
+
name: "__blackUnknown",
|
|
553
|
+
cppName: null,
|
|
554
|
+
cppType: null,
|
|
555
|
+
black: {
|
|
556
|
+
fieldName: "__blackUnknown",
|
|
557
|
+
name: blackName,
|
|
558
|
+
memberPath: blackName,
|
|
559
|
+
memberRoot: blackName,
|
|
560
|
+
beType: "UNKNOWN"
|
|
561
|
+
}
|
|
562
|
+
},
|
|
563
|
+
member: blackName,
|
|
564
|
+
indexed: false,
|
|
565
|
+
indexToken: null,
|
|
566
|
+
index: null,
|
|
567
|
+
key: blackName,
|
|
568
|
+
unknown: true
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
ShouldCaptureUnknownField(blackName, _kind, shape) {
|
|
572
|
+
if (this.options.captureUnknownBlackFields) return true;
|
|
573
|
+
if (this.options.captureUnknownResourceFields && /^res:\//.test(String(blackName || ""))) return true;
|
|
574
|
+
if (this.options.captureUnknownWhenNoBlackFields && (!shape?.black || !shape.black.fields || !shape.black.fields.length)) return true;
|
|
575
|
+
return false;
|
|
576
|
+
}
|
|
577
|
+
ResolveClass(kind) {
|
|
578
|
+
const classes = this.options.classes || {};
|
|
579
|
+
const Schema = this.options.registry || CjsSchema;
|
|
580
|
+
return classes[kind] || Schema.GetConstructor(kind);
|
|
581
|
+
}
|
|
582
|
+
ResetReadState() {
|
|
583
|
+
super.ResetBlueReadState();
|
|
584
|
+
this.references = new Map();
|
|
585
|
+
this.nodes = [];
|
|
586
|
+
this.nextNodeId = this.options.firstId || 1;
|
|
587
|
+
this.payloadDepth = 0;
|
|
588
|
+
this.payloadRootFields = null;
|
|
589
|
+
}
|
|
590
|
+
static readStringTable(reader) {
|
|
591
|
+
const stringsReader = reader.ReadBinaryReader(reader.ReadU32());
|
|
592
|
+
const count = stringsReader.ReadU16();
|
|
593
|
+
const strings = [];
|
|
594
|
+
for (let i = 0; i < count; i++) {
|
|
595
|
+
strings[i] = stringsReader.ReadCString();
|
|
596
|
+
}
|
|
597
|
+
stringsReader.ExpectEnd("Black string table did not read to end");
|
|
598
|
+
return strings;
|
|
599
|
+
}
|
|
600
|
+
static readWideStringTable(reader) {
|
|
601
|
+
const wideStringsReader = reader.ReadBinaryReader(reader.ReadU32());
|
|
602
|
+
const count = wideStringsReader.ReadU16();
|
|
603
|
+
const wideStrings = [];
|
|
604
|
+
for (let i = 0; i < count; i++) {
|
|
605
|
+
wideStrings[i] = wideStringsReader.ReadCWString();
|
|
606
|
+
}
|
|
607
|
+
wideStringsReader.ExpectEnd("Black wide string table did not read to end");
|
|
608
|
+
return wideStrings;
|
|
609
|
+
}
|
|
610
|
+
static normalizeIndexedKey(indexToken, field) {
|
|
611
|
+
const number = Number(indexToken);
|
|
612
|
+
if (Number.isInteger(number) && String(indexToken).trim() === String(number)) return number;
|
|
613
|
+
let text = String(indexToken || "").trim();
|
|
614
|
+
text = text.replace(/^.*::/, "");
|
|
615
|
+
text = text.replace(/^TYPE_/, "");
|
|
616
|
+
const pascal = text.split(/[^A-Za-z0-9]+/).filter(Boolean).map(part => CJS_BLACK_INDEX_TOKEN_NAMES[part] || (part === "FX" ? "FX" : part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())).join("");
|
|
617
|
+
if (field?.jsType?.kind === "objectRef") {
|
|
618
|
+
return pascal ? pascal.charAt(0).toLowerCase() + pascal.slice(1) : text;
|
|
619
|
+
}
|
|
620
|
+
return pascal || text;
|
|
621
|
+
}
|
|
622
|
+
static parseIndexedMember(value) {
|
|
623
|
+
const match = String(value || "").match(/^(.+)\[([^\]]+)\]$/);
|
|
624
|
+
if (!match) return null;
|
|
625
|
+
return {
|
|
626
|
+
member: match[1],
|
|
627
|
+
indexToken: match[2]
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
static toJsFieldName(value) {
|
|
631
|
+
return String(value || "").replace(/^m_/, "");
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
const CJS_BLACK_INDEX_TOKEN_NAMES = Object.freeze({
|
|
635
|
+
SIMPLEPRIMARY: "SimplePrimary"
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
export { CjsBlackReader };
|
|
639
|
+
//# sourceMappingURL=CjsBlackReader.js.map
|