@tamagui/compiler-core 0.0.0-bootstrap.0 → 3.0.0-beta.1093.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +57 -1
  3. package/dist/cjs/ast.cjs +108 -0
  4. package/dist/cjs/contracts.cjs +61 -0
  5. package/dist/cjs/diagnostics.cjs +68 -0
  6. package/dist/cjs/evaluate.cjs +602 -0
  7. package/dist/cjs/graph.cjs +335 -0
  8. package/dist/cjs/hash.cjs +48 -0
  9. package/dist/cjs/index.cjs +43 -0
  10. package/dist/cjs/ir.cjs +32 -0
  11. package/dist/cjs/lower.cjs +232 -0
  12. package/dist/cjs/materialize.cjs +222 -0
  13. package/dist/cjs/normalize.cjs +628 -0
  14. package/dist/cjs/output.cjs +148 -0
  15. package/dist/cjs/planCache.cjs +262 -0
  16. package/dist/cjs/session.cjs +127 -0
  17. package/dist/cjs/yuku.cjs +166 -0
  18. package/dist/cjs/zero.cjs +389 -0
  19. package/dist/esm/ast.mjs +79 -0
  20. package/dist/esm/ast.mjs.map +1 -0
  21. package/dist/esm/contracts.mjs +34 -0
  22. package/dist/esm/contracts.mjs.map +1 -0
  23. package/dist/esm/diagnostics.mjs +44 -0
  24. package/dist/esm/diagnostics.mjs.map +1 -0
  25. package/dist/esm/evaluate.mjs +576 -0
  26. package/dist/esm/evaluate.mjs.map +1 -0
  27. package/dist/esm/graph.mjs +313 -0
  28. package/dist/esm/graph.mjs.map +1 -0
  29. package/dist/esm/hash.mjs +26 -0
  30. package/dist/esm/hash.mjs.map +1 -0
  31. package/dist/esm/index.mjs +30 -0
  32. package/dist/esm/ir.mjs +12 -0
  33. package/dist/esm/ir.mjs.map +1 -0
  34. package/dist/esm/lower.mjs +210 -0
  35. package/dist/esm/lower.mjs.map +1 -0
  36. package/dist/esm/materialize.mjs +203 -0
  37. package/dist/esm/materialize.mjs.map +1 -0
  38. package/dist/esm/normalize.mjs +604 -0
  39. package/dist/esm/normalize.mjs.map +1 -0
  40. package/dist/esm/output.mjs +119 -0
  41. package/dist/esm/output.mjs.map +1 -0
  42. package/dist/esm/planCache.mjs +232 -0
  43. package/dist/esm/planCache.mjs.map +1 -0
  44. package/dist/esm/session.mjs +108 -0
  45. package/dist/esm/session.mjs.map +1 -0
  46. package/dist/esm/yuku.mjs +144 -0
  47. package/dist/esm/yuku.mjs.map +1 -0
  48. package/dist/esm/zero.mjs +354 -0
  49. package/dist/esm/zero.mjs.map +1 -0
  50. package/package.json +42 -4
  51. package/src/ast.ts +106 -0
  52. package/src/contracts.ts +150 -0
  53. package/src/diagnostics.ts +96 -0
  54. package/src/evaluate.ts +875 -0
  55. package/src/graph.ts +425 -0
  56. package/src/hash.ts +36 -0
  57. package/src/index.ts +15 -0
  58. package/src/ir.ts +156 -0
  59. package/src/lower.ts +435 -0
  60. package/src/materialize.ts +383 -0
  61. package/src/normalize.ts +834 -0
  62. package/src/output.ts +175 -0
  63. package/src/planCache.ts +362 -0
  64. package/src/session.ts +192 -0
  65. package/src/yuku.ts +197 -0
  66. package/src/zero.ts +609 -0
  67. package/types/ast.d.ts +11 -0
  68. package/types/ast.d.ts.map +1 -0
  69. package/types/contracts.d.ts +99 -0
  70. package/types/contracts.d.ts.map +1 -0
  71. package/types/diagnostics.d.ts +31 -0
  72. package/types/diagnostics.d.ts.map +1 -0
  73. package/types/evaluate.d.ts +48 -0
  74. package/types/evaluate.d.ts.map +1 -0
  75. package/types/graph.d.ts +51 -0
  76. package/types/graph.d.ts.map +1 -0
  77. package/types/hash.d.ts +8 -0
  78. package/types/hash.d.ts.map +1 -0
  79. package/types/index.d.ts +16 -0
  80. package/types/index.d.ts.map +1 -0
  81. package/types/ir.d.ts +120 -0
  82. package/types/ir.d.ts.map +1 -0
  83. package/types/lower.d.ts +99 -0
  84. package/types/lower.d.ts.map +1 -0
  85. package/types/materialize.d.ts +121 -0
  86. package/types/materialize.d.ts.map +1 -0
  87. package/types/normalize.d.ts +7 -0
  88. package/types/normalize.d.ts.map +1 -0
  89. package/types/output.d.ts +32 -0
  90. package/types/output.d.ts.map +1 -0
  91. package/types/planCache.d.ts +123 -0
  92. package/types/planCache.d.ts.map +1 -0
  93. package/types/session.d.ts +52 -0
  94. package/types/session.d.ts.map +1 -0
  95. package/types/yuku.d.ts +4 -0
  96. package/types/yuku.d.ts.map +1 -0
  97. package/types/zero.d.ts +99 -0
  98. package/types/zero.d.ts.map +1 -0
package/src/ast.ts ADDED
@@ -0,0 +1,106 @@
1
+ import type { AstNode } from './contracts'
2
+
3
+ const ignoredKeys = new Set(['loc', 'range', 'parent', 'comments', 'tokens'])
4
+
5
+ export function isAstNode(value: unknown): value is AstNode {
6
+ return (
7
+ typeof value === 'object' &&
8
+ value !== null &&
9
+ typeof (value as AstNode).type === 'string' &&
10
+ typeof (value as AstNode).start === 'number' &&
11
+ typeof (value as AstNode).end === 'number'
12
+ )
13
+ }
14
+
15
+ export function walkAst(
16
+ node: AstNode,
17
+ visitor: (node: AstNode, parent: AstNode | null, key: string | null) => void,
18
+ parent: AstNode | null = null,
19
+ key: string | null = null
20
+ ): void {
21
+ visitor(node, parent, key)
22
+
23
+ for (const childKey of Object.keys(node)) {
24
+ if (ignoredKeys.has(childKey)) continue
25
+ const value = node[childKey]
26
+ if (isAstNode(value)) {
27
+ walkAst(value, visitor, node, childKey)
28
+ } else if (Array.isArray(value)) {
29
+ for (const child of value) {
30
+ if (isAstNode(child)) {
31
+ walkAst(child, visitor, node, childKey)
32
+ }
33
+ }
34
+ }
35
+ }
36
+ }
37
+
38
+ /** With a source range, only descend into nodes that contain that range. */
39
+ export function findAstNode(
40
+ root: AstNode,
41
+ predicate: (node: AstNode, parent: AstNode | null, key: string | null) => boolean,
42
+ span?: Pick<AstNode, 'start' | 'end'>
43
+ ): AstNode | null {
44
+ function visit(
45
+ node: AstNode,
46
+ parent: AstNode | null,
47
+ key: string | null
48
+ ): AstNode | null {
49
+ if (span && (node.start > span.start || node.end < span.end)) return null
50
+ if (predicate(node, parent, key)) return node
51
+ for (const childKey of Object.keys(node)) {
52
+ if (ignoredKeys.has(childKey)) continue
53
+ const value = node[childKey]
54
+ if (isAstNode(value)) {
55
+ const found = visit(value, node, childKey)
56
+ if (found) return found
57
+ } else if (Array.isArray(value)) {
58
+ for (const child of value) {
59
+ if (!isAstNode(child)) continue
60
+ const found = visit(child, node, childKey)
61
+ if (found) return found
62
+ }
63
+ }
64
+ }
65
+ return null
66
+ }
67
+ return visit(root, null, null)
68
+ }
69
+
70
+ export function childNode(node: AstNode, key: string): AstNode | null {
71
+ const value = node[key]
72
+ return isAstNode(value) ? value : null
73
+ }
74
+
75
+ export function childNodes(node: AstNode, key: string): AstNode[] {
76
+ const value = node[key]
77
+ return Array.isArray(value) ? value.filter(isAstNode) : []
78
+ }
79
+
80
+ export function identifierName(node: AstNode | null): string | null {
81
+ if (!node || (node.type !== 'Identifier' && node.type !== 'JSXIdentifier')) return null
82
+ return typeof node.name === 'string' ? node.name : null
83
+ }
84
+
85
+ export function literalValue(node: AstNode | null): unknown {
86
+ if (!node) return undefined
87
+ if (node.type === 'Literal' || node.type.endsWith('Literal')) {
88
+ return node.value
89
+ }
90
+ return undefined
91
+ }
92
+
93
+ export function unwrapExpression(node: AstNode): AstNode {
94
+ let current = node
95
+ while (
96
+ current.type === 'TSAsExpression' ||
97
+ current.type === 'TSSatisfiesExpression' ||
98
+ current.type === 'TSNonNullExpression' ||
99
+ current.type === 'ParenthesizedExpression'
100
+ ) {
101
+ const expression = childNode(current, 'expression')
102
+ if (!expression) break
103
+ current = expression
104
+ }
105
+ return current
106
+ }
@@ -0,0 +1,150 @@
1
+ export interface AstNode {
2
+ type: string
3
+ start: number
4
+ end: number
5
+ [key: string]: unknown
6
+ }
7
+
8
+ export type ResolvedModuleId = string & { readonly __resolvedModuleId: unique symbol }
9
+
10
+ export interface SourceSpan {
11
+ id: ResolvedModuleId
12
+ /** UTF-16 source-string index, inclusive. */
13
+ start: number
14
+ /** UTF-16 source-string index, exclusive. */
15
+ end: number
16
+ }
17
+
18
+ export interface HostResolvedImport {
19
+ specifier: string
20
+ resolvedId: ResolvedModuleId
21
+ external?: boolean
22
+ }
23
+
24
+ export interface HostModuleInput {
25
+ id: ResolvedModuleId
26
+ source: string
27
+ /** Every import identity is canonical and resolved before the compiler sees it. */
28
+ imports: readonly HostResolvedImport[]
29
+ }
30
+
31
+ export interface HostResolvedProject {
32
+ modules: readonly HostModuleInput[]
33
+ }
34
+
35
+ export interface ProjectInput {
36
+ files: ReadonlyMap<string, string>
37
+ resolutions: ReadonlyMap<string, string>
38
+ }
39
+
40
+ export interface DefinitionSite {
41
+ id: ResolvedModuleId
42
+ name: string
43
+ start: number
44
+ end: number
45
+ initializer: AstNode | null
46
+ constant: boolean
47
+ }
48
+
49
+ export interface ReferenceSite {
50
+ id: ResolvedModuleId
51
+ name: string
52
+ start: number
53
+ end: number
54
+ }
55
+
56
+ export interface ParseDiagnostic {
57
+ kind: 'parse' | 'link'
58
+ id: ResolvedModuleId
59
+ message: string
60
+ }
61
+
62
+ export interface AnalyzerCandidate {
63
+ readonly name: string
64
+ addFile(id: string, source: string): void
65
+ removeFile(id: string): boolean
66
+ link(): void
67
+ definitionOf(id: string, localName: string): DefinitionSite | null
68
+ definitionAt(id: string, start: number, end: number): DefinitionSite | null
69
+ referencesOf(definition: DefinitionSite): ReferenceSite[]
70
+ dependenciesOf(id: string): string[]
71
+ dependentsOf(id: string): string[]
72
+ affectedBy(id: string): string[]
73
+ programOf(id: string): AstNode
74
+ sourceOf(id: string): string
75
+ parseCount(id: string): number
76
+ diagnostics(): ParseDiagnostic[]
77
+ }
78
+
79
+ export interface ExpressionReference extends SourceSpan {
80
+ readonly kind: 'expression'
81
+ }
82
+
83
+ export interface SymbolDefinition {
84
+ id: ResolvedModuleId
85
+ name: string
86
+ span: SourceSpan
87
+ initializer: ExpressionReference | null
88
+ constant: boolean
89
+ }
90
+
91
+ /** Parser-independent symbol access used by partial evaluation and element IR. */
92
+ export interface SymbolResolver {
93
+ resolveBinding(id: ResolvedModuleId, localName: string): SymbolDefinition | null
94
+ resolveReference(reference: ExpressionReference): SymbolDefinition | null
95
+ expressionNode(reference: ExpressionReference): AstNode | null
96
+ sourceOf(id: ResolvedModuleId): string
97
+ }
98
+
99
+ export interface CandidateFactory {
100
+ name: AnalyzerCandidate['name']
101
+ create(project: ProjectInput): AnalyzerCandidate
102
+ /** Parser-owned static module scan; no parser-specific node types escape this boundary. */
103
+ scanImports(id: ResolvedModuleId, source: string): string[]
104
+ }
105
+
106
+ export function resolutionKey(importer: string, specifier: string): string {
107
+ return `${importer}\0${specifier}`
108
+ }
109
+
110
+ export function resolveFromHost(
111
+ resolutions: ReadonlyMap<string, string>,
112
+ specifier: string,
113
+ importer: string
114
+ ): string | null {
115
+ return resolutions.get(resolutionKey(importer, specifier)) ?? null
116
+ }
117
+
118
+ export function resolvedModuleId(id: string): ResolvedModuleId {
119
+ const isAbsolute =
120
+ id.startsWith('/') ||
121
+ id.startsWith('\\') ||
122
+ id.startsWith('\0') ||
123
+ /^[A-Za-z]:[\\/]/.test(id) ||
124
+ /^[A-Za-z][A-Za-z\d+.-]*:\/\//.test(id)
125
+ if (!isAbsolute) {
126
+ throw new Error(`Host module id must be canonical and already resolved: ${id}`)
127
+ }
128
+ return id as ResolvedModuleId
129
+ }
130
+
131
+ export function expressionReference(
132
+ id: ResolvedModuleId,
133
+ node: Pick<AstNode, 'start' | 'end'>
134
+ ): ExpressionReference {
135
+ return { kind: 'expression', id, start: node.start, end: node.end }
136
+ }
137
+
138
+ export function spanOf(
139
+ id: ResolvedModuleId,
140
+ node: Pick<AstNode, 'start' | 'end'>
141
+ ): SourceSpan {
142
+ return { id, start: node.start, end: node.end }
143
+ }
144
+
145
+ export function textOfSpan(
146
+ source: string,
147
+ span: Pick<SourceSpan, 'start' | 'end'>
148
+ ): string {
149
+ return source.slice(span.start, span.end)
150
+ }
@@ -0,0 +1,96 @@
1
+ import type { ResolvedModuleId, SourceSpan } from './contracts'
2
+
3
+ export type BailoutCode =
4
+ | 'local/invalid-element-call'
5
+ | 'local/unsupported-element-name'
6
+ | 'local/unsupported-prop-key'
7
+ | 'local/unsupported-child'
8
+ | 'local/unsupported-expression'
9
+ | 'local/unsupported-styled-definition'
10
+ | 'local/dynamic-style-value'
11
+ | 'local/unsafe-style-spread'
12
+ | 'local/unsupported-target'
13
+ | 'local/style-resolution-failed'
14
+ | 'local/overlapping-edit'
15
+ | 'local/non-object-spread'
16
+ | 'local/static-evaluation-cycle'
17
+ | 'local/parse-error'
18
+ | 'linked/unresolved-component-binding'
19
+ | 'linked/unresolved-binding'
20
+ | 'linked/missing-initializer'
21
+ | 'linked/unresolved-import'
22
+ | 'linked/unresolved-component-config'
23
+
24
+ /**
25
+ * The zero-runtime rule a diagnostic belongs to. Set by whichever site knows the
26
+ * reason; `zeroRuleForBailout` supplies the default for the rest.
27
+ */
28
+ export type ZeroRule = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8
29
+
30
+ export interface BailoutReason {
31
+ code: BailoutCode
32
+ kind: 'local' | 'linked'
33
+ message: string
34
+ span: SourceSpan
35
+ dependencyId?: ResolvedModuleId
36
+ component?: string
37
+ specifier?: string
38
+ prop?: string
39
+ /**
40
+ * True when this diagnostic stopped its candidate from lowering. Zero mode
41
+ * reports exactly these: a diagnostic recorded alongside a successful
42
+ * lowering describes a dropped prop, not a retained runtime.
43
+ */
44
+ blocking?: boolean
45
+ /** Set where the reporting site knows better than the code-level default. */
46
+ zeroRule?: ZeroRule
47
+ /** The design's fixed text for sites that have one, used verbatim. */
48
+ zeroMessage?: string
49
+ }
50
+
51
+ /**
52
+ * The rule a bailout code belongs to when its site did not name one. Ordinary
53
+ * compiler mode ignores this entirely.
54
+ */
55
+ const ZERO_RULE_BY_CODE: Record<BailoutCode, ZeroRule> = {
56
+ 'local/invalid-element-call': 2,
57
+ 'local/unsupported-element-name': 2,
58
+ 'local/unsupported-prop-key': 3,
59
+ 'local/unsupported-child': 3,
60
+ 'local/unsupported-expression': 3,
61
+ 'local/unsupported-styled-definition': 3,
62
+ 'local/dynamic-style-value': 3,
63
+ 'local/unsafe-style-spread': 1,
64
+ 'local/unsupported-target': 6,
65
+ 'local/style-resolution-failed': 3,
66
+ 'local/overlapping-edit': 6,
67
+ 'local/non-object-spread': 1,
68
+ 'local/static-evaluation-cycle': 3,
69
+ 'local/parse-error': 3,
70
+ 'linked/unresolved-component-binding': 2,
71
+ 'linked/unresolved-binding': 2,
72
+ 'linked/missing-initializer': 3,
73
+ 'linked/unresolved-import': 2,
74
+ 'linked/unresolved-component-config': 2,
75
+ }
76
+
77
+ export function zeroRuleForBailout(reason: BailoutReason): ZeroRule {
78
+ return reason.zeroRule ?? ZERO_RULE_BY_CODE[reason.code]
79
+ }
80
+
81
+ export function localBailout(
82
+ code: Extract<BailoutCode, `local/${string}`>,
83
+ span: SourceSpan,
84
+ message: string
85
+ ): BailoutReason {
86
+ return { code, kind: 'local', message, span }
87
+ }
88
+
89
+ export function linkedBailout(
90
+ code: Extract<BailoutCode, `linked/${string}`>,
91
+ span: SourceSpan,
92
+ message: string,
93
+ dependencyId?: ResolvedModuleId
94
+ ): BailoutReason {
95
+ return { code, kind: 'linked', message, span, dependencyId }
96
+ }