@zyno-io/ts-reflection 26.913.2245 → 26.917.1736

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.
@@ -11,8 +11,19 @@
11
11
  * instead of being decoded with different semantics.
12
12
  */
13
13
  export declare function decodeCompactMetadataV1<T>(serialized: string, references: readonly unknown[], resolveType?: (index: number) => unknown): T;
14
+ /**
15
+ * Lazily reconstruct metadata serialized by the native type compiler.
16
+ *
17
+ * V2 stores repeated object and array subtrees in a graph table. The returned
18
+ * proxy intentionally does not parse that table until metadata is inspected.
19
+ * Compiler-generated assignments such as `metadata.classType = Target` are
20
+ * retained as overrides and therefore do not force eager materialization.
21
+ */
22
+ export declare function decodeCompactMetadataV2<T extends object>(serialized: string, references: readonly unknown[], resolveType?: (index: number) => unknown): T;
14
23
  /** Create one lazy metadata-type registry for a generated module. */
15
24
  export declare function createCompactMetadataRegistryV1(serialized: string, references: readonly unknown[]): (index: number) => unknown;
25
+ /** Create one fully lazy V2 metadata-type registry for a generated module. */
26
+ export declare function createCompactMetadataRegistryV2(serialized: string, references: readonly unknown[]): (index: number) => unknown;
16
27
  /** Resolve metadata published by a type-only external import at first use. */
17
28
  export declare function resolveCompactMetadataAliasV1(loadModule: (() => unknown) | ((specifier: string) => unknown), specifierOrExportName: string, exportNameOrTypeName: string, maybeTypeName?: string): unknown;
18
29
  //# sourceMappingURL=compact-metadata.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"compact-metadata.d.ts","sourceRoot":"","sources":["../../src/reflection/compact-metadata.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,OAAO,EAAE,EAAE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,GAAG,CAAC,CAE1I;AAED,qEAAqE;AACrE,wBAAgB,+BAA+B,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,OAAO,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAmB9H;AAED,8EAA8E;AAC9E,wBAAgB,6BAA6B,CACzC,UAAU,EAAE,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,EAC9D,qBAAqB,EAAE,MAAM,EAC7B,oBAAoB,EAAE,MAAM,EAC5B,aAAa,CAAC,EAAE,MAAM,GACvB,OAAO,CAqBT"}
1
+ {"version":3,"file":"compact-metadata.d.ts","sourceRoot":"","sources":["../../src/reflection/compact-metadata.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,OAAO,EAAE,EAAE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,GAAG,CAAC,CAE1I;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,MAAM,EACpD,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,SAAS,OAAO,EAAE,EAC9B,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,GACzC,CAAC,CAMH;AAED,qEAAqE;AACrE,wBAAgB,+BAA+B,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,OAAO,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAmB9H;AAED,8EAA8E;AAC9E,wBAAgB,+BAA+B,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,OAAO,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAyB9H;AAED,8EAA8E;AAC9E,wBAAgB,6BAA6B,CACzC,UAAU,EAAE,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,EAC9D,qBAAqB,EAAE,MAAM,EAC7B,oBAAoB,EAAE,MAAM,EAC5B,aAAa,CAAC,EAAE,MAAM,GACvB,OAAO,CAqBT"}
@@ -2,7 +2,9 @@ package main
2
2
 
3
3
  import (
4
4
  "bytes"
5
+ "crypto/sha256"
5
6
  "encoding/json"
7
+ "fmt"
6
8
  "strconv"
7
9
  "strings"
8
10
 
@@ -12,13 +14,15 @@ import (
12
14
 
13
15
  const (
14
16
  compactMetadataRuntimeSpec = "@zyno-io/ts-reflection/type-metadata-runtime"
15
- compactMetadataDecoderName = "decodeCompactMetadataV1"
16
- compactMetadataRegistryName = "createCompactMetadataRegistryV1"
17
+ compactMetadataDecoderName = "decodeCompactMetadataV2"
18
+ compactMetadataRegistryName = "createCompactMetadataRegistryV2"
17
19
  compactMetadataAliasResolverName = "resolveCompactMetadataAliasV1"
18
20
  compactMetadataReferenceKey = "$tsf"
19
21
  compactMetadataImportKey = "$tsfImport"
20
22
  compactMetadataAliasKey = "$tsfAlias"
21
23
  compactMetadataTypeKey = "$tsfType"
24
+ compactMetadataNodeKey = "$tsfNode"
25
+ compactMetadataGraphMinBytes = 64
22
26
  )
23
27
 
24
28
  type compactMetadataEncoding struct {
@@ -32,6 +36,23 @@ type compactMetadataEncoder struct {
32
36
  referenceIndexes map[string]int
33
37
  referenceKey func(*shimast.Node) (string, bool)
34
38
  runtimeRecipe func(*compactMetadataEncoder, *shimast.Node) bool
39
+ graph *compactMetadataGraph
40
+ graphRoot *shimast.Node
41
+ }
42
+
43
+ type compactMetadataGraphNode struct {
44
+ key string
45
+ size int
46
+ container bool
47
+ shareable bool
48
+ }
49
+
50
+ type compactMetadataGraph struct {
51
+ info map[*shimast.Node]compactMetadataGraphNode
52
+ counts map[string]int
53
+ indexes map[string]int
54
+ nodes []*shimast.Node
55
+ roots map[*shimast.Node]bool
35
56
  }
36
57
 
37
58
  type compactMetadataRuntimeInterner struct {
@@ -129,7 +150,47 @@ func encodeCompactMetadataWithRuntimeRecipes(
129
150
  }
130
151
  }
131
152
 
153
+ func encodeCompactMetadataV2WithRuntimeRecipes(
154
+ root *shimast.Node,
155
+ referenceKey func(*shimast.Node) (string, bool),
156
+ runtimeRecipe func(*compactMetadataEncoder, *shimast.Node) bool,
157
+ metadataTypeResolver string,
158
+ preserveArrayElements bool,
159
+ ) compactMetadataEncoding {
160
+ encoder := &compactMetadataEncoder{
161
+ referenceIndexes: map[string]int{},
162
+ referenceKey: referenceKey,
163
+ runtimeRecipe: runtimeRecipe,
164
+ }
165
+ encoder.graph = buildCompactMetadataGraph(root, referenceKey, metadataTypeResolver)
166
+ if preserveArrayElements && root != nil && root.Kind == shimast.KindArrayLiteralExpression {
167
+ for _, element := range root.AsArrayLiteralExpression().Elements.Nodes {
168
+ encoder.graph.roots[element] = true
169
+ }
170
+ }
171
+ encoder.buffer.WriteString("[2,")
172
+ encoder.writeValue(root)
173
+ encoder.buffer.WriteString(",[")
174
+ for index := 0; index < len(encoder.graph.nodes); index++ {
175
+ if index != 0 {
176
+ encoder.buffer.WriteByte(',')
177
+ }
178
+ node := encoder.graph.nodes[index]
179
+ encoder.graphRoot = node
180
+ encoder.writeValue(node)
181
+ encoder.graphRoot = nil
182
+ }
183
+ encoder.buffer.WriteString("]]")
184
+ return compactMetadataEncoding{
185
+ serialized: encoder.buffer.String(),
186
+ references: encoder.references,
187
+ }
188
+ }
189
+
132
190
  func (encoder *compactMetadataEncoder) writeValue(node *shimast.Node) {
191
+ if encoder.writeGraphReference(node) {
192
+ return
193
+ }
133
194
  start := encoder.buffer.Len()
134
195
  referenceStart := len(encoder.references)
135
196
  if encoder.writeJSONValue(node) {
@@ -140,6 +201,26 @@ func (encoder *compactMetadataEncoder) writeValue(node *shimast.Node) {
140
201
  encoder.writeReference(node)
141
202
  }
142
203
 
204
+ func (encoder *compactMetadataEncoder) writeGraphReference(node *shimast.Node) bool {
205
+ if encoder.graph == nil || node == nil || node == encoder.graphRoot || encoder.graph.roots[node] {
206
+ return false
207
+ }
208
+ info, ok := encoder.graph.info[node]
209
+ if !ok || !info.container || !info.shareable || info.size < compactMetadataGraphMinBytes || encoder.graph.counts[info.key] < 2 {
210
+ return false
211
+ }
212
+ index, ok := encoder.graph.indexes[info.key]
213
+ if !ok {
214
+ index = len(encoder.graph.nodes)
215
+ encoder.graph.indexes[info.key] = index
216
+ encoder.graph.nodes = append(encoder.graph.nodes, node)
217
+ }
218
+ encoder.buffer.WriteString(`{"` + compactMetadataNodeKey + `":`)
219
+ encoder.buffer.WriteString(strconv.Itoa(index))
220
+ encoder.buffer.WriteByte('}')
221
+ return true
222
+ }
223
+
143
224
  func (encoder *compactMetadataEncoder) writeJSONValue(node *shimast.Node) bool {
144
225
  if node == nil {
145
226
  return false
@@ -215,7 +296,8 @@ func (encoder *compactMetadataEncoder) writeObject(object *shimast.ObjectLiteral
215
296
  }
216
297
 
217
298
  func isCompactMetadataReservedKey(name string) bool {
218
- return name == compactMetadataReferenceKey || name == compactMetadataImportKey || name == compactMetadataAliasKey || name == compactMetadataTypeKey
299
+ return name == compactMetadataReferenceKey || name == compactMetadataImportKey || name == compactMetadataAliasKey ||
300
+ name == compactMetadataTypeKey || name == compactMetadataNodeKey
219
301
  }
220
302
 
221
303
  func compactMetadataPropertyName(property *shimast.Node) (string, bool) {
@@ -302,6 +384,164 @@ func (encoder *compactMetadataEncoder) writeReferenceMarker(index int) {
302
384
  encoder.buffer.WriteByte('}')
303
385
  }
304
386
 
387
+ func buildCompactMetadataGraph(
388
+ root *shimast.Node,
389
+ referenceKey func(*shimast.Node) (string, bool),
390
+ metadataTypeResolver string,
391
+ ) *compactMetadataGraph {
392
+ graph := &compactMetadataGraph{
393
+ info: map[*shimast.Node]compactMetadataGraphNode{},
394
+ counts: map[string]int{},
395
+ indexes: map[string]int{},
396
+ roots: map[*shimast.Node]bool{},
397
+ }
398
+ var fingerprint func(*shimast.Node) compactMetadataGraphNode
399
+ fingerprint = func(node *shimast.Node) compactMetadataGraphNode {
400
+ if node == nil {
401
+ return compactMetadataGraphNode{}
402
+ }
403
+ if cached, ok := graph.info[node]; ok {
404
+ return cached
405
+ }
406
+ if node.Kind == shimast.KindParenthesizedExpression {
407
+ result := fingerprint(node.AsParenthesizedExpression().Expression)
408
+ graph.info[node] = result
409
+ return result
410
+ }
411
+ result := compactMetadataGraphNode{}
412
+ var signature strings.Builder
413
+ switch node.Kind {
414
+ case shimast.KindObjectLiteralExpression:
415
+ object := node.AsObjectLiteralExpression()
416
+ if object == nil || object.Properties == nil {
417
+ result = compactMetadataGraphNode{key: compactMetadataFingerprint("o"), size: 2, container: true, shareable: true}
418
+ break
419
+ }
420
+ if len(object.Properties.Nodes) == 1 {
421
+ if name, ok := compactMetadataPropertyName(object.Properties.Nodes[0]); ok && isCompactMetadataReservedKey(name) {
422
+ break
423
+ }
424
+ }
425
+ signature.WriteString("object:")
426
+ size := 2
427
+ shareable := true
428
+ for _, property := range object.Properties.Nodes {
429
+ name, ok := compactMetadataPropertyName(property)
430
+ assignment := property.AsPropertyAssignment()
431
+ if !ok || name == "__proto__" || assignment == nil {
432
+ shareable = false
433
+ break
434
+ }
435
+ child := fingerprint(assignment.Initializer)
436
+ if !child.shareable {
437
+ shareable = false
438
+ break
439
+ }
440
+ signature.WriteString(strconv.Quote(name))
441
+ signature.WriteByte(':')
442
+ signature.WriteString(child.key)
443
+ signature.WriteByte(';')
444
+ size += len(strconv.Quote(name)) + 1 + child.size + 1
445
+ }
446
+ if shareable {
447
+ result = compactMetadataGraphNode{key: compactMetadataFingerprint(signature.String()), size: size, container: true, shareable: true}
448
+ }
449
+ case shimast.KindArrayLiteralExpression:
450
+ array := node.AsArrayLiteralExpression()
451
+ signature.WriteString("array:")
452
+ size := 2
453
+ shareable := array != nil
454
+ if shareable && array.Elements != nil {
455
+ for _, element := range array.Elements.Nodes {
456
+ if element == nil || element.Kind == shimast.KindOmittedExpression || element.Kind == shimast.KindSpreadElement {
457
+ shareable = false
458
+ break
459
+ }
460
+ child := fingerprint(element)
461
+ if !child.shareable {
462
+ shareable = false
463
+ break
464
+ }
465
+ signature.WriteString(child.key)
466
+ signature.WriteByte(';')
467
+ size += child.size + 1
468
+ }
469
+ }
470
+ if shareable {
471
+ result = compactMetadataGraphNode{key: compactMetadataFingerprint(signature.String()), size: size, container: true, shareable: true}
472
+ }
473
+ case shimast.KindStringLiteral, shimast.KindNoSubstitutionTemplateLiteral:
474
+ value, _ := json.Marshal(node.Text())
475
+ result = compactMetadataGraphNode{key: compactMetadataFingerprint("string:" + string(value)), size: len(value), shareable: true}
476
+ case shimast.KindNumericLiteral:
477
+ if json.Valid([]byte(node.Text())) {
478
+ result = compactMetadataGraphNode{key: compactMetadataFingerprint("number:" + node.Text()), size: len(node.Text()), shareable: true}
479
+ }
480
+ case shimast.KindTrueKeyword:
481
+ result = compactMetadataGraphNode{key: compactMetadataFingerprint("true"), size: 4, shareable: true}
482
+ case shimast.KindFalseKeyword:
483
+ result = compactMetadataGraphNode{key: compactMetadataFingerprint("false"), size: 5, shareable: true}
484
+ case shimast.KindNullKeyword:
485
+ result = compactMetadataGraphNode{key: compactMetadataFingerprint("null"), size: 4, shareable: true}
486
+ case shimast.KindPrefixUnaryExpression:
487
+ unary := node.AsPrefixUnaryExpression()
488
+ if unary != nil && unary.Operator == shimast.KindMinusToken && unary.Operand != nil && unary.Operand.Kind == shimast.KindNumericLiteral {
489
+ value := "-" + unary.Operand.Text()
490
+ if json.Valid([]byte(value)) {
491
+ result = compactMetadataGraphNode{key: compactMetadataFingerprint("number:" + value), size: len(value), shareable: true}
492
+ }
493
+ }
494
+ default:
495
+ if index, ok := compactMetadataTypeRecipe(node, metadataTypeResolver); ok {
496
+ value := fmt.Sprintf("type:%d", index)
497
+ result = compactMetadataGraphNode{key: compactMetadataFingerprint(value), size: len(value) + 8, shareable: true}
498
+ } else if referenceKey != nil {
499
+ if key, ok := referenceKey(node); ok {
500
+ result = compactMetadataGraphNode{key: compactMetadataFingerprint("reference:" + key), size: len(key) + 8, shareable: true}
501
+ }
502
+ }
503
+ }
504
+ graph.info[node] = result
505
+ if result.container && result.shareable && result.size >= compactMetadataGraphMinBytes {
506
+ graph.counts[result.key]++
507
+ }
508
+ return result
509
+ }
510
+ fingerprint(root)
511
+ return graph
512
+ }
513
+
514
+ func compactMetadataFingerprint(value string) string {
515
+ hash := sha256.Sum256([]byte(value))
516
+ return string(hash[:])
517
+ }
518
+
519
+ func compactMetadataEncodingForSizeGuard(
520
+ metadata *shimast.Node,
521
+ imports *astImportRegistry,
522
+ runtimeReferences *compactMetadataRuntimeInterner,
523
+ metadataTypeResolver string,
524
+ preserveArrayElements bool,
525
+ inlinePureJSON bool,
526
+ ) compactMetadataEncoding {
527
+ runtimeRecipe := func(encoder *compactMetadataEncoder, expression *shimast.Node) bool {
528
+ return writeCompactMetadataRuntimeRecipe(encoder, expression, imports, metadataTypeResolver)
529
+ }
530
+ if inlinePureJSON {
531
+ encoding := encodeCompactMetadataWithRuntimeRecipes(metadata, runtimeReferences.deduplicationKey, runtimeRecipe)
532
+ if len(encoding.references) == 0 && !strings.Contains(encoding.serialized, `"$tsf`) {
533
+ return encoding
534
+ }
535
+ }
536
+ return encodeCompactMetadataV2WithRuntimeRecipes(
537
+ metadata,
538
+ runtimeReferences.deduplicationKey,
539
+ runtimeRecipe,
540
+ metadataTypeResolver,
541
+ preserveArrayElements,
542
+ )
543
+ }
544
+
305
545
  func materializeCompactMetadataExpression(
306
546
  ec *shimprinter.EmitContext,
307
547
  imports *astImportRegistry,
@@ -322,9 +562,10 @@ func materializeCompactAliasMetadataExpression(
322
562
  runtimeReferences *compactMetadataRuntimeInterner,
323
563
  template expressionTemplate,
324
564
  metadataTypeResolver string,
565
+ inlinePureJSON bool,
325
566
  ) *shimast.Node {
326
567
  metadata := template.materialize(ec, imports)
327
- return materializeCompactMetadataNode(ec, imports, runtimeReferences, metadata, metadataTypeResolver, false, true)
568
+ return materializeCompactMetadataNode(ec, imports, runtimeReferences, metadata, metadataTypeResolver, false, inlinePureJSON)
328
569
  }
329
570
 
330
571
  func materializeCompactMetadataRegistry(
@@ -351,12 +592,46 @@ func materializeCompactMetadataNode(
351
592
  registry bool,
352
593
  inlinePureJSON bool,
353
594
  ) *shimast.Node {
354
- encoding := encodeCompactMetadataWithRuntimeRecipes(
595
+ encodeV1 := func() compactMetadataEncoding {
596
+ return encodeCompactMetadataWithRuntimeRecipes(
597
+ metadata,
598
+ runtimeReferences.deduplicationKey,
599
+ func(encoder *compactMetadataEncoder, expression *shimast.Node) bool {
600
+ return writeCompactMetadataRuntimeRecipe(encoder, expression, imports, metadataTypeResolver)
601
+ },
602
+ )
603
+ }
604
+ if inlinePureJSON {
605
+ encoding := encodeV1()
606
+ if len(encoding.references) == 0 && !strings.Contains(encoding.serialized, `"$tsf`) {
607
+ parsed := ec.Factory.NewCallExpression(
608
+ ec.Factory.NewPropertyAccessExpression(
609
+ ec.Factory.NewIdentifier("JSON"),
610
+ nil,
611
+ ec.Factory.NewIdentifier("parse"),
612
+ shimast.NodeFlagsNone,
613
+ ),
614
+ nil,
615
+ nil,
616
+ ec.Factory.NewNodeList([]*shimast.Node{ec.Factory.NewStringLiteral(encoding.serialized, shimast.TokenFlagsNone)}),
617
+ shimast.NodeFlagsNone,
618
+ )
619
+ return ec.Factory.NewElementAccessExpression(
620
+ parsed,
621
+ nil,
622
+ ec.Factory.NewNumericLiteral("1", shimast.TokenFlagsNone),
623
+ shimast.NodeFlagsNone,
624
+ )
625
+ }
626
+ }
627
+ encoding := encodeCompactMetadataV2WithRuntimeRecipes(
355
628
  metadata,
356
629
  runtimeReferences.deduplicationKey,
357
630
  func(encoder *compactMetadataEncoder, expression *shimast.Node) bool {
358
631
  return writeCompactMetadataRuntimeRecipe(encoder, expression, imports, metadataTypeResolver)
359
632
  },
633
+ metadataTypeResolver,
634
+ registry,
360
635
  )
361
636
  references := make([]*shimast.Node, 0, len(encoding.references))
362
637
  for _, reference := range encoding.references {
@@ -366,26 +641,6 @@ func materializeCompactMetadataNode(
366
641
  // its original binding.
367
642
  references = append(references, ec.Factory.DeepCloneNode(reference))
368
643
  }
369
- if inlinePureJSON && len(references) == 0 && !strings.Contains(encoding.serialized, `"$tsf`) {
370
- parsed := ec.Factory.NewCallExpression(
371
- ec.Factory.NewPropertyAccessExpression(
372
- ec.Factory.NewIdentifier("JSON"),
373
- nil,
374
- ec.Factory.NewIdentifier("parse"),
375
- shimast.NodeFlagsNone,
376
- ),
377
- nil,
378
- nil,
379
- ec.Factory.NewNodeList([]*shimast.Node{ec.Factory.NewStringLiteral(encoding.serialized, shimast.TokenFlagsNone)}),
380
- shimast.NodeFlagsNone,
381
- )
382
- return ec.Factory.NewElementAccessExpression(
383
- parsed,
384
- nil,
385
- ec.Factory.NewNumericLiteral("1", shimast.TokenFlagsNone),
386
- shimast.NodeFlagsNone,
387
- )
388
- }
389
644
  helperName := compactMetadataDecoderName
390
645
  if registry {
391
646
  helperName = compactMetadataRegistryName
@@ -6,18 +6,22 @@ import (
6
6
  "strings"
7
7
 
8
8
  shimast "github.com/microsoft/typescript-go/shim/ast"
9
+ shimprinter "github.com/microsoft/typescript-go/shim/printer"
9
10
  "github.com/samchon/ttsc/packages/ttsc/driver"
10
11
  )
11
12
 
13
+ const maxCompactMetadataPayloadBytes = 1024 * 1024
14
+
12
15
  type emissionPlans map[string]*fileEmissionPlan
13
16
 
14
17
  type fileEmissionPlan struct {
15
- calls map[int]callEmissionPlan
16
- classes map[int]classEmissionPlan
17
- aliases *expressionTemplate
18
- metadataTypes []expressionTemplate
19
- metadataTypeResolver string
20
- commonJS bool
18
+ calls map[int]callEmissionPlan
19
+ classes map[int]classEmissionPlan
20
+ aliases *expressionTemplate
21
+ metadataTypes []expressionTemplate
22
+ metadataTypeResolver string
23
+ decodePureJSONAliases bool
24
+ commonJS bool
21
25
  }
22
26
 
23
27
  type callEmissionPlan struct {
@@ -95,8 +99,9 @@ func buildEmissionPlans(reg *registry, program *driver.Program, emitTypeAliases
95
99
  continue
96
100
  }
97
101
  plan := &fileEmissionPlan{
98
- calls: map[int]callEmissionPlan{},
99
- classes: map[int]classEmissionPlan{},
102
+ calls: map[int]callEmissionPlan{},
103
+ classes: map[int]classEmissionPlan{},
104
+ decodePureJSONAliases: emitMetadataRuntimeImport,
100
105
  }
101
106
  metadataTypes := newMetadataTypeInterner(info.file.Text())
102
107
  if program != nil && program.TSProgram != nil {
@@ -145,6 +150,9 @@ func buildEmissionPlans(reg *registry, program *driver.Program, emitTypeAliases
145
150
  plan.aliases = &template
146
151
  }
147
152
  }
153
+ if err := validateCompactMetadataSizes(info, plan); err != nil {
154
+ return nil, err
155
+ }
148
156
  if !emitMetadataRuntimeImport {
149
157
  if requirement := metadataRuntimeRequirement(plan); requirement != "" {
150
158
  return nil, fmt.Errorf(
@@ -162,6 +170,88 @@ func buildEmissionPlans(reg *registry, program *driver.Program, emitTypeAliases
162
170
  return plans, nil
163
171
  }
164
172
 
173
+ func validateCompactMetadataSizes(info *fileInfo, plan *fileEmissionPlan) error {
174
+ if info == nil || info.file == nil || plan == nil {
175
+ return nil
176
+ }
177
+ ec := shimprinter.NewEmitContext()
178
+ imports := newAstImportRegistry(ec, info.file, plan.commonJS)
179
+ runtimeReferences := newCompactMetadataRuntimeInterner(ec, info.file)
180
+ validate := func(surface string, template expressionTemplate, preserveArrayElements bool, inlinePureJSON bool) error {
181
+ metadata := template.materialize(ec, imports)
182
+ encoding := compactMetadataEncodingForSizeGuard(
183
+ metadata,
184
+ imports,
185
+ runtimeReferences,
186
+ plan.metadataTypeResolver,
187
+ preserveArrayElements,
188
+ inlinePureJSON,
189
+ )
190
+ if len(encoding.serialized) > maxCompactMetadataPayloadBytes {
191
+ return fmt.Errorf(
192
+ "%s: compact metadata for %s is %d bytes after graph interning; limit is %d bytes",
193
+ info.file.FileName(),
194
+ surface,
195
+ len(encoding.serialized),
196
+ maxCompactMetadataPayloadBytes,
197
+ )
198
+ }
199
+ return nil
200
+ }
201
+
202
+ classPositions := make([]int, 0, len(plan.classes))
203
+ for position := range plan.classes {
204
+ classPositions = append(classPositions, position)
205
+ }
206
+ sort.Ints(classPositions)
207
+ for _, position := range classPositions {
208
+ class := plan.classes[position]
209
+ if err := validate("class "+class.name, class.metadata, false, false); err != nil {
210
+ return err
211
+ }
212
+ }
213
+ callPositions := make([]int, 0, len(plan.calls))
214
+ for position := range plan.calls {
215
+ callPositions = append(callPositions, position)
216
+ }
217
+ sort.Ints(callPositions)
218
+ for _, position := range callPositions {
219
+ call := plan.calls[position]
220
+ if err := validate("call "+call.name, call.metadata, false, false); err != nil {
221
+ return err
222
+ }
223
+ }
224
+ if plan.aliases != nil {
225
+ if err := validate("exported aliases", *plan.aliases, false, !plan.decodePureJSONAliases); err != nil {
226
+ return err
227
+ }
228
+ }
229
+ if len(plan.metadataTypes) != 0 {
230
+ elements := make([]*shimast.Node, 0, len(plan.metadataTypes))
231
+ for _, template := range plan.metadataTypes {
232
+ elements = append(elements, template.materialize(ec, imports))
233
+ }
234
+ metadata := ec.Factory.NewArrayLiteralExpression(ec.Factory.NewNodeList(elements), false)
235
+ encoding := compactMetadataEncodingForSizeGuard(
236
+ metadata,
237
+ imports,
238
+ runtimeReferences,
239
+ plan.metadataTypeResolver,
240
+ true,
241
+ false,
242
+ )
243
+ if len(encoding.serialized) > maxCompactMetadataPayloadBytes {
244
+ return fmt.Errorf(
245
+ "%s: compact metadata for shared type registry is %d bytes after graph interning; limit is %d bytes",
246
+ info.file.FileName(),
247
+ len(encoding.serialized),
248
+ maxCompactMetadataPayloadBytes,
249
+ )
250
+ }
251
+ }
252
+ return nil
253
+ }
254
+
165
255
  // metadataRuntimeRequirement reports the first generated construct that cannot
166
256
  // be emitted without TSF's compact metadata runtime. Alias registries made only
167
257
  // of JSON stay self-contained; all other current metadata surfaces use runtime
@@ -170,7 +260,7 @@ func metadataRuntimeRequirement(plan *fileEmissionPlan) string {
170
260
  if plan == nil {
171
261
  return ""
172
262
  }
173
- if plan.aliases != nil && !compactMetadataIsPureJSON(plan.aliases.parsed) {
263
+ if plan.aliases != nil && (plan.decodePureJSONAliases || !compactMetadataIsPureJSON(plan.aliases.parsed)) {
174
264
  if names := runtimeAliasMetadataNames(plan.aliases.parsed); len(names) != 0 {
175
265
  return "reflected alias metadata for " + strings.Join(names, ", ")
176
266
  }
@@ -236,6 +326,10 @@ func aliasMetadataExpression(info *fileInfo, reg *registry) string {
236
326
  }
237
327
  continue
238
328
  }
329
+ if ref, ok := reexportedTypeMetadataReference(info, reg, name); ok {
330
+ entries = append(entries, quote(name)+": "+externalImportedTypeExpr(ref, name))
331
+ continue
332
+ }
239
333
  if alias, owner, _, ok := resolveExportedAlias(info, reg, name, map[string]bool{}); ok {
240
334
  if len(alias.params) == 0 {
241
335
  if expr := cachedAliasTypeExpr(owner, reg, alias); expr != "" && !metadataExprTooLarge(expr) {
@@ -256,6 +350,56 @@ func aliasMetadataExpression(info *fileInfo, reg *registry) string {
256
350
  return "{" + strings.Join(entries, ", ") + "}"
257
351
  }
258
352
 
353
+ // Re-exporting a type must not copy the owner's complete structural metadata
354
+ // into every barrel. Point at the immediate owning module when this compilation
355
+ // emits that module's alias table; it may itself contain another recipe when the
356
+ // export crosses more than one barrel. Declaration-only dependencies do not
357
+ // necessarily publish runtime alias metadata, so keep their structural metadata
358
+ // at the first emitted boundary instead of producing an unresolvable recipe.
359
+ func reexportedTypeMetadataReference(info *fileInfo, reg *registry, name string) (importRef, bool) {
360
+ if info == nil || reg == nil {
361
+ return importRef{}, false
362
+ }
363
+ if ref, ok := info.reexports[name]; ok {
364
+ if target := reg.byPath[ref.source]; canPublishTypeMetadata(target) && exportedTypeMetadataExists(target, reg, ref.exportName) {
365
+ ref.spec = emittedMetadataOwnerSpecifier(info, target, ref.spec)
366
+ return ref, ref.spec != "" && ref.exportName != ""
367
+ }
368
+ }
369
+ for _, ref := range info.exportStar {
370
+ target := reg.byPath[ref.source]
371
+ if !canPublishTypeMetadata(target) || !exportedTypeMetadataExists(target, reg, name) {
372
+ continue
373
+ }
374
+ ref.exportName = name
375
+ ref.spec = emittedMetadataOwnerSpecifier(info, target, ref.spec)
376
+ return ref, ref.spec != ""
377
+ }
378
+ return importRef{}, false
379
+ }
380
+
381
+ func canPublishTypeMetadata(info *fileInfo) bool {
382
+ return info != nil && info.file != nil && !info.file.IsDeclarationFile
383
+ }
384
+
385
+ func emittedMetadataOwnerSpecifier(info *fileInfo, target *fileInfo, spec string) string {
386
+ if info == nil || info.file == nil || target == nil || target.file == nil || !strings.HasPrefix(spec, ".") {
387
+ return spec
388
+ }
389
+ // Use an explicit runtime file rather than syntactically appending `.js` to
390
+ // the source specifier. The latter turns `./directory` into a nonexistent
391
+ // `./directory.js` instead of the emitted `./directory/index.js`.
392
+ return moduleSpecifierForOutput(info.file.FileName(), target.file.FileName(), true)
393
+ }
394
+
395
+ func exportedTypeMetadataExists(info *fileInfo, reg *registry, name string) bool {
396
+ if _, _, _, ok := resolveExportedAlias(info, reg, name, map[string]bool{}); ok {
397
+ return true
398
+ }
399
+ _, _, _, ok := resolveExportedInterfaceDecl(info, reg, name, map[string]bool{})
400
+ return ok
401
+ }
402
+
259
403
  func cachedAliasTypeExpr(info *fileInfo, reg *registry, alias aliasInfo) string {
260
404
  if alias.metadataTooLarge {
261
405
  return ""
@@ -317,6 +317,7 @@ func metadataTransform(plans emissionPlans) driver.PluginTransform {
317
317
  runtimeReferences,
318
318
  *plan.aliases,
319
319
  plan.metadataTypeResolver,
320
+ !plan.decodePureJSONAliases,
320
321
  ))
321
322
  }
322
323
  declarations := []*shimast.Node{}
@@ -233,6 +233,10 @@ func TestMetadataRuntimeRequirementAllowsPureJSONAliases(t *testing.T) {
233
233
  if got := metadataRuntimeRequirement(plan); got != "" {
234
234
  t.Fatalf("pure JSON aliases require metadata runtime: %s", got)
235
235
  }
236
+ plan.decodePureJSONAliases = true
237
+ if got := metadataRuntimeRequirement(plan); got != "reflected alias metadata" {
238
+ t.Fatalf("lazy pure JSON alias requirement = %q", got)
239
+ }
236
240
  }
237
241
 
238
242
  func TestMetadataRuntimeRequirementRejectsRuntimeAliasValues(t *testing.T) {
@@ -348,6 +352,7 @@ func TestCompactMetadataEncoderEscapesReferenceMarkerCollision(t *testing.T) {
348
352
  `{"$tsfImport": [0, "Model"]}`,
349
353
  `{"$tsfAlias": [0, "Alias", "Alias"]}`,
350
354
  `{"$tsfType": 0}`,
355
+ `{"$tsfNode": 0}`,
351
356
  } {
352
357
  template, err := parseExpressionTemplate(source)
353
358
  if err != nil {
@@ -417,6 +422,113 @@ func TestCompactMetadataEncoderDeduplicatesGeneratedRuntimeThunks(t *testing.T)
417
422
  }
418
423
  }
419
424
 
425
+ func TestCompactMetadataV2InternsRepeatedGraphsWithRuntimeReferences(t *testing.T) {
426
+ file := parseTestSourceFile(t, "/project/model.ts", `class Model {}`)
427
+ template, err := parseExpressionTemplate(`{
428
+ first: {kind: 16, classType: () => Model, properties: [{name: "value", type: {kind: 6}}]},
429
+ second: {kind: 16, classType: () => Model, properties: [{name: "value", type: {kind: 6}}]}
430
+ }`)
431
+ if err != nil {
432
+ t.Fatal(err)
433
+ }
434
+ ec := shimprinter.NewEmitContext()
435
+ interner := newCompactMetadataRuntimeInterner(ec, file)
436
+ encoding := encodeCompactMetadataV2WithRuntimeRecipes(template.parsed, interner.deduplicationKey, nil, "", false)
437
+ if !strings.HasPrefix(encoding.serialized, `[2,`) {
438
+ t.Fatalf("V2 compact payload = %s", encoding.serialized)
439
+ }
440
+ if strings.Count(encoding.serialized, `{"$tsfNode":0}`) != 2 {
441
+ t.Fatalf("repeated graph was not interned: %s", encoding.serialized)
442
+ }
443
+ if len(encoding.references) != 1 {
444
+ t.Fatalf("runtime references = %d, want 1", len(encoding.references))
445
+ }
446
+ }
447
+
448
+ func TestAliasMetadataUsesOwnerRecipesForReexports(t *testing.T) {
449
+ originFile := parseTestSourceFile(t, "/project/origin/index.ts", `export type Shared = { value: string }`)
450
+ barrelFile := parseTestSourceFile(t, "/project/barrel.ts", `export * from "./origin"`)
451
+ origin := &fileInfo{
452
+ file: originFile,
453
+ moduleKey: moduleKey(originFile.FileName()),
454
+ aliases: map[string]aliasInfo{"Shared": {body: `{ value: string }`, exported: true}},
455
+ interfaces: map[string][]interfaceInfo{},
456
+ reexports: map[string]importRef{},
457
+ }
458
+ barrel := &fileInfo{
459
+ file: barrelFile,
460
+ moduleKey: moduleKey(barrelFile.FileName()),
461
+ aliases: map[string]aliasInfo{},
462
+ interfaces: map[string][]interfaceInfo{},
463
+ reexports: map[string]importRef{},
464
+ exportStar: []importRef{{source: origin.moduleKey, spec: "./origin"}},
465
+ }
466
+ reg := &registry{byPath: map[string]*fileInfo{origin.moduleKey: origin, barrel.moduleKey: barrel}}
467
+
468
+ got := aliasMetadataExpression(barrel, reg)
469
+ assertContainsAll(t, got, `"Shared": __tsf_runtime_alias__("./origin/index.js", "Shared", "Shared")`)
470
+ assertNotContains(t, got, `name: "value"`)
471
+ }
472
+
473
+ func TestAliasMetadataExpandsDeclarationOnlyReexportBoundary(t *testing.T) {
474
+ originFile := parseTestSourceFile(t, "/dependencies/origin.d.ts", `export type Shared = { value: string }`)
475
+ barrelFile := parseTestSourceFile(t, "/project/barrel.ts", `export * from "external-package"`)
476
+ origin := &fileInfo{
477
+ file: originFile,
478
+ moduleKey: moduleKey(originFile.FileName()),
479
+ aliases: map[string]aliasInfo{"Shared": {body: `{ value: string }`, exported: true}},
480
+ interfaces: map[string][]interfaceInfo{},
481
+ reexports: map[string]importRef{},
482
+ }
483
+ barrel := &fileInfo{
484
+ file: barrelFile,
485
+ moduleKey: moduleKey(barrelFile.FileName()),
486
+ aliases: map[string]aliasInfo{},
487
+ interfaces: map[string][]interfaceInfo{},
488
+ reexports: map[string]importRef{},
489
+ exportStar: []importRef{{source: origin.moduleKey, spec: "external-package"}},
490
+ }
491
+ reg := &registry{byPath: map[string]*fileInfo{origin.moduleKey: origin, barrel.moduleKey: barrel}}
492
+
493
+ got := aliasMetadataExpression(barrel, reg)
494
+ assertContainsAll(t, got, `"Shared":`, `name: "value"`)
495
+ assertNotContains(t, got, `__tsf_runtime_alias__`)
496
+ }
497
+
498
+ func TestCompactMetadataSizeGuardRejectsOversizedPayload(t *testing.T) {
499
+ file := parseTestSourceFile(t, "/project/oversized.ts", `class Oversized {}`)
500
+ template, err := parseExpressionTemplate(`{kind: 2, typeName: "` + strings.Repeat("x", maxCompactMetadataPayloadBytes) + `"}`)
501
+ if err != nil {
502
+ t.Fatal(err)
503
+ }
504
+ plan := &fileEmissionPlan{
505
+ calls: map[int]callEmissionPlan{},
506
+ classes: map[int]classEmissionPlan{1: {name: "Oversized", metadata: template}},
507
+ commonJS: true,
508
+ }
509
+ err = validateCompactMetadataSizes(&fileInfo{file: file}, plan)
510
+ if err == nil || !strings.Contains(err.Error(), "limit is 1048576 bytes") {
511
+ t.Fatalf("size guard error = %v", err)
512
+ }
513
+ }
514
+
515
+ func TestCompactMetadataSizeGuardMeasuresAfterGraphInterning(t *testing.T) {
516
+ file := parseTestSourceFile(t, "/project/compacted.ts", `class Compacted {}`)
517
+ repeated := strings.Repeat("x", maxCompactMetadataPayloadBytes/2+1024)
518
+ template, err := parseExpressionTemplate(`{first: {value: "` + repeated + `"}, second: {value: "` + repeated + `"}}`)
519
+ if err != nil {
520
+ t.Fatal(err)
521
+ }
522
+ plan := &fileEmissionPlan{
523
+ calls: map[int]callEmissionPlan{},
524
+ classes: map[int]classEmissionPlan{1: {name: "Compacted", metadata: template}},
525
+ commonJS: true,
526
+ }
527
+ if err := validateCompactMetadataSizes(&fileInfo{file: file}, plan); err != nil {
528
+ t.Fatalf("compacted metadata failed size guard: %v", err)
529
+ }
530
+ }
531
+
420
532
  func TestMetadataTypeInternerKeepsRuntimeExpressionsAtUseSite(t *testing.T) {
421
533
  interner := newMetadataTypeInterner("")
422
534
  runtime := `{kind: 16, classType: () => LocalModel}`
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=1,t=`$tsf`,n=`$tsfImport`,r=`$tsfAlias`,i=`$tsfType`;function a(e,t,n){return l(c(e),t,n)}function o(e,t){let n=c(e);if(!Array.isArray(n))throw Error(`Invalid TSF compact metadata registry`);let r=Array(n.length),i=new Uint8Array(n.length),a=e=>{if(!Number.isSafeInteger(e)||e<0||e>=n.length)throw Error(`Invalid TSF compact metadata type ${e}`);return i[e]||(i[e]=1,r[e]=n[e],r[e]=l(n[e],t,a)),r[e]};return a}function s(e,t,n,r){let[i,a,o]=r===void 0?[e,t,n]:[()=>e(t),n,r],s;try{let e=i();e&&typeof e==`object`&&(s=e)}catch{}let c=s?.__tsfTypeAliases?.[a];return c&&typeof c==`object`?{...c,typeName:o}:{kind:16,typeName:o,classType:()=>s?.[a]}}function c(t){let n=JSON.parse(t);if(!Array.isArray(n)||n.length!==2||n[0]!==e)throw Error(`Unsupported TSF compact metadata format`);return n[1]}function l(e,a,o){if(!e||typeof e!=`object`)return e;if(f(e))return u(a,e[t]);if(p(e)){let t=e[n],[r,i]=t.length===2?t:[t[0],t[2]],o=d(a,r,t.length===3?t[1]:void 0);return()=>o()?.[i]}if(m(e)){let t=e[r],[n,i,o]=t.length===3?t:[t[0],t[2],t[3]];return s(d(a,n,t.length===4?t[1]:void 0),i,o)}if(h(e)){if(!o)throw Error(`Missing TSF compact metadata type registry`);return o(e[i])}if(Array.isArray(e)){for(let t=0;t<e.length;t++)e[t]=l(e[t],a,o);return e}let c=e;for(let e of Object.keys(c))c[e]=l(c[e],a,o);return c}function u(e,t){if(t<0||t>=e.length)throw Error(`Invalid TSF compact metadata reference ${t}`);return e[t]}function d(e,t,n){let r=u(e,t);if(typeof r!=`function`)throw Error(`Invalid TSF compact metadata module loader ${t}`);return n===void 0?r:()=>{try{return r(n)}catch{return}}}function f(e){if(Array.isArray(e))return!1;let n=Object.keys(e);return n.length===1&&n[0]===t&&Number.isSafeInteger(e[t])}function p(e){if(Array.isArray(e))return!1;let t=Object.keys(e),r=e[n];return t.length===1&&t[0]===n&&Array.isArray(r)&&(r.length===2||r.length===3)&&Number.isSafeInteger(r[0])&&typeof r[1]==`string`&&(r.length===2||typeof r[2]==`string`)}function m(e){if(Array.isArray(e))return!1;let t=Object.keys(e),n=e[r];return t.length===1&&t[0]===r&&Array.isArray(n)&&(n.length===3||n.length===4)&&Number.isSafeInteger(n[0])&&typeof n[1]==`string`&&typeof n[2]==`string`&&(n.length===3||typeof n[3]==`string`)}function h(e){if(Array.isArray(e))return!1;let t=Object.keys(e);return t.length===1&&t[0]===i&&Number.isSafeInteger(e[i])}exports.createCompactMetadataRegistryV1=o,exports.decodeCompactMetadataV1=a,exports.resolveCompactMetadataAliasV1=s;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=1,t=`$tsf`,n=`$tsfImport`,r=`$tsfAlias`,i=`$tsfType`,a=`$tsfNode`;function o(e,t,n){return p(d(e),t,n)}function s(e,t,n){return h(()=>{let[r,i]=f(e);return p(r,t,n,m(i,t,n))})}function c(e,t){let n=d(e);if(!Array.isArray(n))throw Error(`Invalid TSF compact metadata registry`);let r=Array.from({length:n.length}),i=new Uint8Array(n.length),a=e=>{if(!Number.isSafeInteger(e)||e<0||e>=n.length)throw Error(`Invalid TSF compact metadata type ${e}`);return i[e]||(i[e]=1,r[e]=n[e],r[e]=p(n[e],t,a)),r[e]};return a}function l(e,t){let n,r,i,a,o=s=>{if(!n){let[s,c]=f(e);if(!Array.isArray(s))throw Error(`Invalid TSF compact metadata registry`);n=s,i=Array.from({length:s.length}),a=new Uint8Array(s.length),r=m(c,t,o)}if(!Number.isSafeInteger(s)||s<0||s>=n.length)throw Error(`Invalid TSF compact metadata type ${s}`);return a[s]||(a[s]=1,i[s]=n[s],i[s]=p(n[s],t,o,r)),i[s]};return o}function u(e,t,n,r){let[i,a,o]=r===void 0?[e,t,n]:[()=>e(t),n,r],s;try{let e=i();e&&typeof e==`object`&&(s=e)}catch{}let c=s?.__tsfTypeAliases?.[a];return c&&typeof c==`object`?{...c,typeName:o}:{kind:16,typeName:o,classType:()=>s?.[a]}}function d(t){let n=JSON.parse(t);if(!Array.isArray(n)||n.length!==2||n[0]!==e)throw Error(`Unsupported TSF compact metadata format`);return n[1]}function f(e){let t=JSON.parse(e);if(!Array.isArray(t)||t.length!==3||t[0]!==2||!Array.isArray(t[2]))throw Error(`Unsupported TSF compact metadata format`);return[t[1],t[2]]}function p(e,o,s,c){if(!e||typeof e!=`object`)return e;if(v(e))return g(o,e[t]);if(y(e)){let t=e[n],[r,i]=t.length===2?t:[t[0],t[2]],a=_(o,r,t.length===3?t[1]:void 0);return()=>a()?.[i]}if(b(e)){let t=e[r],[n,i,a]=t.length===3?t:[t[0],t[2],t[3]];return u(_(o,n,t.length===4?t[1]:void 0),i,a)}if(x(e)){if(!s)throw Error(`Missing TSF compact metadata type registry`);return s(e[i])}if(S(e)){if(!c)throw Error(`Missing TSF compact metadata node registry`);return c(e[a])}if(Array.isArray(e)){for(let t=0;t<e.length;t++)e[t]=p(e[t],o,s,c);return e}let l=e;for(let e of Object.keys(l))l[e]=p(l[e],o,s,c);return l}function m(e,t,n){let r=Array.from({length:e.length}),i=new Uint8Array(e.length),a=o=>{if(!Number.isSafeInteger(o)||o<0||o>=e.length)throw Error(`Invalid TSF compact metadata node ${o}`);return i[o]||(i[o]=1,r[o]=e[o],r[o]=p(e[o],t,n,a)),r[o]};return a}function h(e){let t={},n=!1,r=()=>{if(n)return;let r=e();if(!r||typeof r!=`object`)throw Error(`Invalid TSF compact metadata root`);for(let e of Reflect.ownKeys(r)){if(Object.prototype.hasOwnProperty.call(t,e))continue;let n=Object.getOwnPropertyDescriptor(r,e);n&&Object.defineProperty(t,e,n)}n=!0};return new Proxy(t,{get(e,t,n){return r(),Reflect.get(e,t,n)},set(e,t,n){return Reflect.set(e,t,n,e)},has(e,t){return r(),Reflect.has(e,t)},ownKeys(e){return r(),Reflect.ownKeys(e)},getOwnPropertyDescriptor(e,t){return r(),Reflect.getOwnPropertyDescriptor(e,t)},defineProperty(e,t,n){return Reflect.defineProperty(e,t,n)},deleteProperty(e,t){return r(),Reflect.deleteProperty(e,t)},getPrototypeOf(e){return r(),Reflect.getPrototypeOf(e)},setPrototypeOf(e,t){return r(),Reflect.setPrototypeOf(e,t)},isExtensible(e){return Reflect.isExtensible(e)},preventExtensions(e){return r(),Reflect.preventExtensions(e)}})}function g(e,t){if(t<0||t>=e.length)throw Error(`Invalid TSF compact metadata reference ${t}`);return e[t]}function _(e,t,n){let r=g(e,t);if(typeof r!=`function`)throw Error(`Invalid TSF compact metadata module loader ${t}`);return n===void 0?r:()=>{try{return r(n)}catch{return}}}function v(e){if(Array.isArray(e))return!1;let n=Object.keys(e);return n.length===1&&n[0]===t&&Number.isSafeInteger(e[t])}function y(e){if(Array.isArray(e))return!1;let t=Object.keys(e),r=e[n];return t.length===1&&t[0]===n&&Array.isArray(r)&&(r.length===2||r.length===3)&&Number.isSafeInteger(r[0])&&typeof r[1]==`string`&&(r.length===2||typeof r[2]==`string`)}function b(e){if(Array.isArray(e))return!1;let t=Object.keys(e),n=e[r];return t.length===1&&t[0]===r&&Array.isArray(n)&&(n.length===3||n.length===4)&&Number.isSafeInteger(n[0])&&typeof n[1]==`string`&&typeof n[2]==`string`&&(n.length===3||typeof n[3]==`string`)}function x(e){if(Array.isArray(e))return!1;let t=Object.keys(e);return t.length===1&&t[0]===i&&Number.isSafeInteger(e[i])}function S(e){if(Array.isArray(e))return!1;let t=Object.keys(e);return t.length===1&&t[0]===a&&Number.isSafeInteger(e[a])}exports.createCompactMetadataRegistryV1=c,exports.createCompactMetadataRegistryV2=l,exports.decodeCompactMetadataV1=o,exports.decodeCompactMetadataV2=s,exports.resolveCompactMetadataAliasV1=u;
@@ -1,18 +1,36 @@
1
1
  //#region src/reflection/compact-metadata.ts
2
- var e = "$tsf", t = "$tsfImport", n = "$tsfAlias", r = "$tsfType";
3
- function i(e, t, n) {
4
- return c(s(e), t, n);
2
+ var e = "$tsf", t = "$tsfImport", n = "$tsfAlias", r = "$tsfType", i = "$tsfNode";
3
+ function a(e, t, n) {
4
+ return f(u(e), t, n);
5
5
  }
6
- function a(e, t) {
7
- let n = s(e);
6
+ function o(e, t, n) {
7
+ return m(() => {
8
+ let [r, i] = d(e);
9
+ return f(r, t, n, p(i, t, n));
10
+ });
11
+ }
12
+ function s(e, t) {
13
+ let n = u(e);
8
14
  if (!Array.isArray(n)) throw Error("Invalid TSF compact metadata registry");
9
- let r = Array(n.length), i = new Uint8Array(n.length), a = (e) => {
15
+ let r = Array.from({ length: n.length }), i = new Uint8Array(n.length), a = (e) => {
10
16
  if (!Number.isSafeInteger(e) || e < 0 || e >= n.length) throw Error(`Invalid TSF compact metadata type ${e}`);
11
- return i[e] || (i[e] = 1, r[e] = n[e], r[e] = c(n[e], t, a)), r[e];
17
+ return i[e] || (i[e] = 1, r[e] = n[e], r[e] = f(n[e], t, a)), r[e];
12
18
  };
13
19
  return a;
14
20
  }
15
- function o(e, t, n, r) {
21
+ function c(e, t) {
22
+ let n, r, i, a, o = (s) => {
23
+ if (!n) {
24
+ let [s, c] = d(e);
25
+ if (!Array.isArray(s)) throw Error("Invalid TSF compact metadata registry");
26
+ n = s, i = Array.from({ length: s.length }), a = new Uint8Array(s.length), r = p(c, t, o);
27
+ }
28
+ if (!Number.isSafeInteger(s) || s < 0 || s >= n.length) throw Error(`Invalid TSF compact metadata type ${s}`);
29
+ return a[s] || (a[s] = 1, i[s] = n[s], i[s] = f(n[s], t, o, r)), i[s];
30
+ };
31
+ return o;
32
+ }
33
+ function l(e, t, n, r) {
16
34
  let [i, a, o] = r === void 0 ? [
17
35
  e,
18
36
  t,
@@ -36,44 +54,108 @@ function o(e, t, n, r) {
36
54
  classType: () => s?.[a]
37
55
  };
38
56
  }
39
- function s(e) {
57
+ function u(e) {
40
58
  let t = JSON.parse(e);
41
59
  if (!Array.isArray(t) || t.length !== 2 || t[0] !== 1) throw Error("Unsupported TSF compact metadata format");
42
60
  return t[1];
43
61
  }
44
- function c(i, a, s) {
45
- if (!i || typeof i != "object") return i;
46
- if (d(i)) return l(a, i[e]);
47
- if (f(i)) {
48
- let e = i[t], [n, r] = e.length === 2 ? e : [e[0], e[2]], o = u(a, n, e.length === 3 ? e[1] : void 0);
49
- return () => o()?.[r];
62
+ function d(e) {
63
+ let t = JSON.parse(e);
64
+ if (!Array.isArray(t) || t.length !== 3 || t[0] !== 2 || !Array.isArray(t[2])) throw Error("Unsupported TSF compact metadata format");
65
+ return [t[1], t[2]];
66
+ }
67
+ function f(a, o, s, c) {
68
+ if (!a || typeof a != "object") return a;
69
+ if (_(a)) return h(o, a[e]);
70
+ if (v(a)) {
71
+ let e = a[t], [n, r] = e.length === 2 ? e : [e[0], e[2]], i = g(o, n, e.length === 3 ? e[1] : void 0);
72
+ return () => i()?.[r];
50
73
  }
51
- if (p(i)) {
52
- let e = i[n], [t, r, s] = e.length === 3 ? e : [
74
+ if (y(a)) {
75
+ let e = a[n], [t, r, i] = e.length === 3 ? e : [
53
76
  e[0],
54
77
  e[2],
55
78
  e[3]
56
79
  ];
57
- return o(u(a, t, e.length === 4 ? e[1] : void 0), r, s);
80
+ return l(g(o, t, e.length === 4 ? e[1] : void 0), r, i);
58
81
  }
59
- if (m(i)) {
82
+ if (b(a)) {
60
83
  if (!s) throw Error("Missing TSF compact metadata type registry");
61
- return s(i[r]);
84
+ return s(a[r]);
85
+ }
86
+ if (x(a)) {
87
+ if (!c) throw Error("Missing TSF compact metadata node registry");
88
+ return c(a[i]);
62
89
  }
63
- if (Array.isArray(i)) {
64
- for (let e = 0; e < i.length; e++) i[e] = c(i[e], a, s);
65
- return i;
90
+ if (Array.isArray(a)) {
91
+ for (let e = 0; e < a.length; e++) a[e] = f(a[e], o, s, c);
92
+ return a;
66
93
  }
67
- let h = i;
68
- for (let e of Object.keys(h)) h[e] = c(h[e], a, s);
69
- return h;
94
+ let u = a;
95
+ for (let e of Object.keys(u)) u[e] = f(u[e], o, s, c);
96
+ return u;
97
+ }
98
+ function p(e, t, n) {
99
+ let r = Array.from({ length: e.length }), i = new Uint8Array(e.length), a = (o) => {
100
+ if (!Number.isSafeInteger(o) || o < 0 || o >= e.length) throw Error(`Invalid TSF compact metadata node ${o}`);
101
+ return i[o] || (i[o] = 1, r[o] = e[o], r[o] = f(e[o], t, n, a)), r[o];
102
+ };
103
+ return a;
70
104
  }
71
- function l(e, t) {
105
+ function m(e) {
106
+ let t = {}, n = !1, r = () => {
107
+ if (n) return;
108
+ let r = e();
109
+ if (!r || typeof r != "object") throw Error("Invalid TSF compact metadata root");
110
+ for (let e of Reflect.ownKeys(r)) {
111
+ if (Object.prototype.hasOwnProperty.call(t, e)) continue;
112
+ let n = Object.getOwnPropertyDescriptor(r, e);
113
+ n && Object.defineProperty(t, e, n);
114
+ }
115
+ n = !0;
116
+ };
117
+ return new Proxy(t, {
118
+ get(e, t, n) {
119
+ return r(), Reflect.get(e, t, n);
120
+ },
121
+ set(e, t, n) {
122
+ return Reflect.set(e, t, n, e);
123
+ },
124
+ has(e, t) {
125
+ return r(), Reflect.has(e, t);
126
+ },
127
+ ownKeys(e) {
128
+ return r(), Reflect.ownKeys(e);
129
+ },
130
+ getOwnPropertyDescriptor(e, t) {
131
+ return r(), Reflect.getOwnPropertyDescriptor(e, t);
132
+ },
133
+ defineProperty(e, t, n) {
134
+ return Reflect.defineProperty(e, t, n);
135
+ },
136
+ deleteProperty(e, t) {
137
+ return r(), Reflect.deleteProperty(e, t);
138
+ },
139
+ getPrototypeOf(e) {
140
+ return r(), Reflect.getPrototypeOf(e);
141
+ },
142
+ setPrototypeOf(e, t) {
143
+ return r(), Reflect.setPrototypeOf(e, t);
144
+ },
145
+ isExtensible(e) {
146
+ return Reflect.isExtensible(e);
147
+ },
148
+ preventExtensions(e) {
149
+ return r(), Reflect.preventExtensions(e);
150
+ }
151
+ });
152
+ }
153
+ function h(e, t) {
72
154
  if (t < 0 || t >= e.length) throw Error(`Invalid TSF compact metadata reference ${t}`);
73
155
  return e[t];
74
156
  }
75
- function u(e, t, n) {
76
- let r = l(e, t);
157
+ function g(e, t, n) {
158
+ let r = h(e, t);
77
159
  if (typeof r != "function") throw Error(`Invalid TSF compact metadata module loader ${t}`);
78
160
  return n === void 0 ? r : () => {
79
161
  try {
@@ -83,25 +165,30 @@ function u(e, t, n) {
83
165
  }
84
166
  };
85
167
  }
86
- function d(t) {
168
+ function _(t) {
87
169
  if (Array.isArray(t)) return !1;
88
170
  let n = Object.keys(t);
89
171
  return n.length === 1 && n[0] === e && Number.isSafeInteger(t[e]);
90
172
  }
91
- function f(e) {
173
+ function v(e) {
92
174
  if (Array.isArray(e)) return !1;
93
175
  let n = Object.keys(e), r = e[t];
94
176
  return n.length === 1 && n[0] === t && Array.isArray(r) && (r.length === 2 || r.length === 3) && Number.isSafeInteger(r[0]) && typeof r[1] == "string" && (r.length === 2 || typeof r[2] == "string");
95
177
  }
96
- function p(e) {
178
+ function y(e) {
97
179
  if (Array.isArray(e)) return !1;
98
180
  let t = Object.keys(e), r = e[n];
99
181
  return t.length === 1 && t[0] === n && Array.isArray(r) && (r.length === 3 || r.length === 4) && Number.isSafeInteger(r[0]) && typeof r[1] == "string" && typeof r[2] == "string" && (r.length === 3 || typeof r[3] == "string");
100
182
  }
101
- function m(e) {
183
+ function b(e) {
102
184
  if (Array.isArray(e)) return !1;
103
185
  let t = Object.keys(e);
104
186
  return t.length === 1 && t[0] === r && Number.isSafeInteger(e[r]);
105
187
  }
188
+ function x(e) {
189
+ if (Array.isArray(e)) return !1;
190
+ let t = Object.keys(e);
191
+ return t.length === 1 && t[0] === i && Number.isSafeInteger(e[i]);
192
+ }
106
193
  //#endregion
107
- export { a as createCompactMetadataRegistryV1, i as decodeCompactMetadataV1, o as resolveCompactMetadataAliasV1 };
194
+ export { s as createCompactMetadataRegistryV1, c as createCompactMetadataRegistryV2, a as decodeCompactMetadataV1, o as decodeCompactMetadataV2, l as resolveCompactMetadataAliasV1 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zyno-io/ts-reflection",
3
- "version": "26.913.2245",
3
+ "version": "26.917.1736",
4
4
  "description": "Browser-neutral TypeScript reflection and runtime metadata",
5
5
  "license": "MIT",
6
6
  "files": [