dsh-ptc-plus 0.3.2 → 0.4.2

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 (206) hide show
  1. package/README.en.md +63 -80
  2. package/README.md +63 -80
  3. package/assets/ptc-plus-bindings-en.png +0 -0
  4. package/assets/ptc-plus-bindings-zh.png +0 -0
  5. package/assets/ptc-plus-repair-en.png +0 -0
  6. package/assets/ptc-plus-repair-zh.png +0 -0
  7. package/assets/ptc-plus-repl-workspace-en.png +0 -0
  8. package/assets/ptc-plus-repl-workspace-zh.png +0 -0
  9. package/assets/ptc-plus-settings-en.png +0 -0
  10. package/assets/ptc-plus-settings-zh.png +0 -0
  11. package/client.js +30827 -742
  12. package/compiler-amaro.cjs +5 -0
  13. package/compiler-amaro.cjs.map +6 -0
  14. package/compiler-asset-124f80c1bba92ff5fe79cfec6e8ad518f476de4a42514cae3919538887f510e8.txt +1 -0
  15. package/compiler-assets.json +3 -0
  16. package/compiler-core.cjs +556 -0
  17. package/compiler-core.cjs.map +6 -0
  18. package/compiler-platform.cjs +2 -0
  19. package/compiler-platform.cjs.map +6 -0
  20. package/compiler-typescript.cjs +388 -0
  21. package/compiler-typescript.cjs.map +6 -0
  22. package/docs/README.md +7 -0
  23. package/docs/adr/0004-declare-program-bindings-at-the-host.md +1 -1
  24. package/docs/adr/0006-rewrite-module-syntax-with-an-ast.md +5 -3
  25. package/docs/adr/0007-separate-worker-transport-from-session-semantics.md +1 -1
  26. package/docs/adr/0009-bound-expensive-acceptance-default.md +2 -0
  27. package/docs/adr/0010-session-log-derived-recovery-tips.md +59 -5
  28. package/docs/adr/0011-isolate-the-local-recovery-tip-provider.md +1 -1
  29. package/docs/adr/0012-preserve-mixed-destructuring-initialization.md +3 -1
  30. package/docs/adr/0013-isolate-repl-redeclaration-convenience.md +3 -1
  31. package/docs/adr/0014-persist-cell-rewrite-policy.md +6 -2
  32. package/docs/adr/0015-preserve-source-positions-through-rewrites.md +1 -1
  33. package/docs/adr/0016-archive-resolved-review-findings.md +1 -1
  34. package/docs/adr/0017-track-the-latest-dsh-public-surface.md +49 -0
  35. package/docs/adr/0018-use-versioned-fixture-for-ab-benchmark.md +3 -3
  36. package/docs/adr/0019-plugin-settings-and-kill-switch.md +5 -3
  37. package/docs/adr/0020-optional-cordis-tools-in-ptc-mode.md +2 -2
  38. package/docs/adr/0021-separate-host-bootstrap-from-session-runtime.md +12 -0
  39. package/docs/adr/0023-global-user-bindings.md +104 -0
  40. package/docs/adr/0024-repl-console-observation.md +33 -0
  41. package/docs/adr/0025-use-versioned-logical-binding-identities.md +119 -0
  42. package/docs/adr/0026-persist-the-delivery-verdict-against-the-verified-candidate.md +21 -0
  43. package/docs/adr/0027-run-the-session-kernel-in-a-killable-helper-process.md +37 -0
  44. package/docs/adr/0028-attach-to-the-host-ptc-execution-seam.md +103 -0
  45. package/docs/adr/0029-keep-plugin-unavailability-out-of-the-host-agent-lifecycle.md +27 -0
  46. package/docs/adr/0030-serve-both-typert-codec-generations-from-one-codec.md +27 -0
  47. package/docs/architecture.md +77 -21
  48. package/docs/binding-review-placement-design.md +200 -0
  49. package/docs/capability-projection.md +1 -1
  50. package/docs/client-ui.md +95 -19
  51. package/docs/durability-design.md +28 -10
  52. package/docs/evaluation.md +78 -6
  53. package/docs/installation.md +41 -6
  54. package/docs/publishing.md +5 -3
  55. package/docs/runtime-reference.md +76 -25
  56. package/docs/semantic-validation.md +29 -0
  57. package/docs/stateful-binding-updates-proposal.md +759 -0
  58. package/docs/user-bindings.en.md +66 -0
  59. package/docs/user-bindings.md +66 -0
  60. package/docs/value-wire.md +3 -3
  61. package/docs/verification-optimization-work.md +41 -0
  62. package/docs/verification.md +71 -0
  63. package/index.js +369 -92
  64. package/internal/ast-traversal.js +5 -2
  65. package/internal/async-local-storage-intrinsics.js +38 -0
  66. package/internal/binding-declaration-contract.js +8 -0
  67. package/internal/binding-descriptors.js +1 -0
  68. package/internal/binding-pattern-traversal.js +25 -0
  69. package/internal/binding-pattern.js +26 -29
  70. package/internal/binding-source-analysis.js +708 -0
  71. package/internal/binding-update-policy.js +72 -0
  72. package/internal/bounded-worker-round.js +56 -0
  73. package/internal/callable-definition-environment.js +42 -0
  74. package/internal/callable-source-catalog.js +129 -0
  75. package/internal/callable-source-encoding.js +47 -0
  76. package/internal/callable-source-facts.js +459 -0
  77. package/internal/callable-source-format.js +2 -0
  78. package/internal/callable-source-lowering.js +123 -0
  79. package/internal/cell-analysis-contract.js +25 -0
  80. package/internal/cell-analysis.js +253 -290
  81. package/internal/cell-completion.js +15 -0
  82. package/internal/cell-error.js +7 -0
  83. package/internal/cell-parser.js +66 -0
  84. package/internal/cell-rewriter.js +3 -677
  85. package/internal/commonjs-export-evidence.js +63 -0
  86. package/internal/commonjs-source-evidence.js +72 -0
  87. package/internal/compiler-amaro.cjs +2 -0
  88. package/internal/compiler-compression.js +12 -0
  89. package/internal/compiler-data.js +58 -0
  90. package/internal/compiler-descriptors.js +54 -0
  91. package/internal/compiler-dynamic-cache.js +48 -0
  92. package/internal/compiler-entry.js +35 -0
  93. package/internal/compiler-generated-names.js +17 -0
  94. package/internal/compiler-intrinsics.js +50 -0
  95. package/internal/compiler-module-links.js +37 -0
  96. package/internal/compiler-operations.js +61 -0
  97. package/internal/compiler-platform-factory.js +84 -0
  98. package/internal/compiler-platform.js +136 -0
  99. package/internal/compiler-record-roles.js +53 -0
  100. package/internal/compiler-region-output.js +259 -0
  101. package/internal/compiler-resource-lowering.js +103 -0
  102. package/internal/compiler-scope-facts.js +115 -0
  103. package/internal/compiler-service.js +109 -0
  104. package/internal/compiler-source-cache.js +32 -0
  105. package/internal/compiler-source-pieces.js +93 -0
  106. package/internal/compiler-source-regions.js +132 -0
  107. package/internal/compiler-storage-source.js +54 -0
  108. package/internal/compiler-text.js +15 -0
  109. package/internal/compiler-typescript.cjs +2 -0
  110. package/internal/config-spec.js +83 -27
  111. package/internal/cordis-tools-owner.js +130 -21
  112. package/internal/diagnostic.js +27 -1
  113. package/internal/direct-surface-owner.js +76 -23
  114. package/internal/dynamic-binding-evidence.js +16 -0
  115. package/internal/dynamic-environment-compiler.js +779 -0
  116. package/internal/dynamic-environment-integration.js +91 -0
  117. package/internal/dynamic-environment-runtime.js +383 -0
  118. package/internal/dynamic-native-calls.js +153 -0
  119. package/internal/dynamic-native-runtime.js +262 -0
  120. package/internal/dynamic-scope-analysis.js +90 -0
  121. package/internal/edit-transport-owner.js +27 -2
  122. package/internal/execution-seam-compat.js +193 -0
  123. package/internal/failure-reporting.js +136 -28
  124. package/internal/host-rpc.js +66 -0
  125. package/internal/isolated-worker.js +555 -0
  126. package/internal/kernel-child.js +139 -0
  127. package/internal/kernel-worker.js +1179 -233
  128. package/internal/language-semantics.js +14 -0
  129. package/internal/legacy-binding-catalog.js +48 -0
  130. package/internal/legacy-cell-analysis.js +600 -0
  131. package/internal/legacy-cell-parser.js +50 -0
  132. package/internal/legacy-cell-rewriter.js +631 -0
  133. package/internal/legacy-repl-convenience.js +291 -0
  134. package/internal/managed-module-operations.js +170 -0
  135. package/internal/module-compilation.js +322 -0
  136. package/internal/module-runtime-platform.js +19 -0
  137. package/internal/module-transform-contract.js +42 -0
  138. package/internal/native-await-declarations.js +68 -0
  139. package/internal/native-root-compilation.js +54 -0
  140. package/internal/native-root-dynamic.js +67 -0
  141. package/internal/record-utils.js +24 -15
  142. package/internal/recovery-tips.js +27 -15
  143. package/internal/rejected-cell-editor.js +13 -8
  144. package/internal/repl-convenience.js +2 -289
  145. package/internal/repl-memory-projection.js +81 -12
  146. package/internal/repl-observation-interest.js +70 -0
  147. package/internal/repl-rewrite-contract.js +6 -0
  148. package/internal/repl-scope-normalizer.js +2091 -0
  149. package/internal/repl-value-observer.js +117 -0
  150. package/internal/rpc-contract.js +52 -0
  151. package/internal/runtime-bridge-owner.js +172 -28
  152. package/internal/runtime-config.js +48 -52
  153. package/internal/runtime-contexts.js +82 -10
  154. package/internal/runtime-intrinsics.js +101 -0
  155. package/internal/runtime-messages.js +111 -0
  156. package/internal/session-cell-executor.js +402 -87
  157. package/internal/session-journal-recovery.js +684 -0
  158. package/internal/session-journal-schema.js +123 -0
  159. package/internal/session-journal.js +199 -654
  160. package/internal/session-log-view.js +42 -9
  161. package/internal/session-runtime.js +257 -95
  162. package/internal/session-state.js +247 -71
  163. package/internal/source-position-map.js +230 -71
  164. package/internal/stateful-module-compiler.js +154 -0
  165. package/internal/stateful-module-runtime.js +303 -0
  166. package/internal/stateful-root-compiler.js +600 -0
  167. package/internal/stateful-root-runtime.js +340 -0
  168. package/internal/typert-codec-compat.js +28 -0
  169. package/internal/typescript-transform.js +31 -0
  170. package/internal/user-binding-authoring.js +70 -0
  171. package/internal/user-binding-console-worker.js +244 -0
  172. package/internal/user-binding-console.js +148 -0
  173. package/internal/user-binding-draft-projection.js +335 -0
  174. package/internal/user-binding-model-context.js +31 -0
  175. package/internal/user-binding-runner.js +56 -0
  176. package/internal/user-bindings-owner.js +1065 -0
  177. package/internal/user-bindings-store.js +293 -0
  178. package/internal/user-bindings.js +361 -0
  179. package/internal/value-wire-schema.js +28 -0
  180. package/internal/value-wire.js +130 -91
  181. package/internal/worker-client.js +57 -67
  182. package/internal/worker-cwd-virtualization.js +80 -53
  183. package/internal/worker-environment.js +65 -0
  184. package/internal/worker-output-relay.js +29 -0
  185. package/internal/worker-repl-realm.js +134 -0
  186. package/internal/worker-shutdown.js +14 -0
  187. package/package.json +76 -7
  188. package/src/client-activity.js +95 -53
  189. package/src/client-authoring-view.js +580 -0
  190. package/src/client-binding-review.js +230 -0
  191. package/src/client-bindings-data.js +29 -0
  192. package/src/client-catalog.js +127 -0
  193. package/src/client-code-editor.js +84 -0
  194. package/src/client-console.js +112 -0
  195. package/src/client-copy.js +370 -0
  196. package/src/client-feature-gates.js +62 -0
  197. package/src/client-host-compat.js +150 -0
  198. package/src/client-indicator-view.js +267 -0
  199. package/src/client-repl-view.js +292 -0
  200. package/src/client-rpc.js +20 -0
  201. package/src/client-settings-view.js +221 -0
  202. package/src/client-styles.js +106 -0
  203. package/src/client-tool-view.js +108 -0
  204. package/src/client-transport.js +159 -0
  205. package/src/client-workbench.js +521 -0
  206. package/src/client.js +233 -615
@@ -0,0 +1,322 @@
1
+ import { staticModuleLinkReference } from './compiler-module-links.js'
2
+ import { parse } from '@babel/parser'
3
+ import { types as t } from '@babel/core'
4
+ import { CELL_PARSER_PLUGINS, normalizeStatefulScopes, normalizeTypeScriptValues, lowerNativeLanguageSource,
5
+ hasModuleResources } from './repl-scope-normalizer.js'
6
+ import { bindingNodes, createGeneratedNameAllocator } from './binding-pattern.js'
7
+ import { applySourceEdits, identitySourceMap, sourceOffsetAt } from './source-position-map.js'
8
+ import { applyRegionEdits, indexSourceRegions, visitRegionSource, transformRegionSource, validateRegionSource, sourceRegionData } from './compiler-region-output.js'
9
+ import { adaptDynamicCell } from './dynamic-environment-integration.js'
10
+ import { adaptLegacyModuleReferences, adaptModuleOperations } from './managed-module-operations.js'
11
+ import { markCallableSources, collectRegionCallableRanges, createRegionCallableCollector, emitRegionCallableSources, callableSourceCatalog } from './callable-source-facts.js'
12
+ import { commonJsExportEvidence } from './commonjs-source-evidence.js'
13
+ export { commonJsExportEvidence, linkCommonJsEvidenceSource } from './commonjs-source-evidence.js'
14
+ import { COMMONJS_PARAMETERS } from './compiler-scope-facts.js'
15
+ import {
16
+ LEGACY_USER_BINDING_TRANSFORM, USER_BINDING_TRANSFORM, PROTECTED_MODULE_TRANSFORM,
17
+ isStatefulUserBindingTransform, supportedUserBindingTransform, transformTypeScriptSource,
18
+ } from './typescript-transform.js'
19
+
20
+ const topLevelRegion = region => region.kind === 'program' || region.top === true
21
+
22
+ /** Keep one native export mapping while executing every source occurrence. */
23
+ function normalizeModuleExports(source, sourceMap) {
24
+ const tree = parse(source, { sourceType: 'module', errorRecovery: true,
25
+ plugins: CELL_PARSER_PLUGINS })
26
+ for (const error of tree.errors) if (error.reasonCode === 'ModuleExportUndefined') throw error
27
+ const allocate = createGeneratedNameAllocator(tree)
28
+ const exports = new Map()
29
+ const edits = []
30
+ const anonymousFunctions = []
31
+ const dependencyEdits = []
32
+ const exportName = node => node.type === 'Identifier' ? node.name : node.value
33
+ for (const statement of tree.program.body) {
34
+ if (statement.type === 'ExportDefaultDeclaration') {
35
+ const declaration = statement.declaration
36
+ const named = ['FunctionDeclaration', 'ClassDeclaration'].includes(declaration.type)
37
+ if (declaration.type === 'FunctionDeclaration' && declaration.id === null) {
38
+ // Its synthetic native binding is inaccessible to source writes. Keep
39
+ // instantiation-time identity and the native inferred name "default".
40
+ exports.set('default', { nativeFunction: statement })
41
+ anonymousFunctions.push(statement)
42
+ continue
43
+ }
44
+ const local = named && declaration.id !== null ? declaration.id.name : allocate('module_default')
45
+ exports.set('default', local)
46
+ if (named && declaration.id !== null) {
47
+ edits.push({ start: statement.start, end: declaration.start, text: '' })
48
+ } else {
49
+ const value = source.slice(declaration.start, declaration.end)
50
+ const anonymous = declaration.type === 'ClassDeclaration'
51
+ || ['FunctionExpression', 'ClassExpression', 'ArrowFunctionExpression'].includes(declaration.type) && declaration.id == null
52
+ edits.push({ start: statement.start, end: statement.end,
53
+ text: `let ${local} = (${anonymous ? `({default: (${value})}).default` : value});` })
54
+ }
55
+ continue
56
+ }
57
+ if (statement.type !== 'ExportNamedDeclaration') continue
58
+ const declaration = statement.declaration
59
+ if (declaration !== null && declaration !== undefined) {
60
+ const names = declaration.type === 'VariableDeclaration'
61
+ ? declaration.declarations.flatMap(item => bindingNodes(item.id)).map(item => item.name)
62
+ : declaration.id?.type === 'Identifier' ? [declaration.id.name] : []
63
+ for (const name of names) exports.set(name, name)
64
+ edits.push({ start: statement.start, end: declaration.start, text: '' })
65
+ continue
66
+ }
67
+ const dependencies = []
68
+ for (const specifier of statement.specifiers) {
69
+ if (specifier.exportKind === 'type') continue
70
+ const name = exportName(specifier.exported)
71
+ if (statement.source === null || statement.source === undefined) {
72
+ exports.set(name, exportName(specifier.local))
73
+ } else {
74
+ const local = allocate('module_export')
75
+ const binding = specifier.type === 'ExportNamespaceSpecifier'
76
+ ? `* as ${local}` : `{ ${JSON.stringify(exportName(specifier.local))} as ${local} }`
77
+ const dependency = `import ${binding} from ${source.slice(statement.source.start, statement.end)}`
78
+ const mapping = specifier.type === 'ExportNamespaceSpecifier' ? `* as ${JSON.stringify(name)}`
79
+ : `{ ${JSON.stringify(exportName(specifier.local))} as ${JSON.stringify(name)} }`
80
+ const selected = { native: `export ${mapping} from ${source.slice(statement.source.start, statement.end)}` }
81
+ exports.set(name, selected)
82
+ dependencies.push({ name, selected, dependency })
83
+ }
84
+ }
85
+ if (statement.source != null && statement.specifiers.length === 0) {
86
+ dependencies.push(`import ${source.slice(statement.source.start, statement.end)}`)
87
+ }
88
+ dependencyEdits.push({ start: statement.start, end: statement.end, dependencies })
89
+ }
90
+ for (const statement of anonymousFunctions) {
91
+ if (exports.get('default')?.nativeFunction !== statement) {
92
+ // An anonymous function declaration has no initializer effects or local
93
+ // source name once a later export mapping replaces its only exposure.
94
+ edits.push({ start: statement.start, end: statement.end, text: '' })
95
+ }
96
+ }
97
+ for (const { start, end, dependencies } of dependencyEdits) {
98
+ // A retained native re-export already owns linking. An extra named import
99
+ // can make Node reject an otherwise valid cyclic forwarding graph. Only
100
+ // replaced mappings need a separate import to retain their source effects
101
+ // and missing-export validation.
102
+ edits.push({ start, end, text: dependencies.filter(item => typeof item === 'string' || exports.get(item.name) !== item.selected)
103
+ .map(item => typeof item === 'string' ? item : item.dependency).join('\n') })
104
+ }
105
+ const locals = [...exports].filter(([, binding]) => typeof binding === 'string')
106
+ const native = [...exports.values()].filter(binding => binding.native !== undefined).map(binding => binding.native)
107
+ if (exports.size > 0) edits.push({ start: source.length, end: source.length,
108
+ text: `\n${locals.length > 0 ? `export { ${locals.map(([name, local]) => `${local} as ${JSON.stringify(name)}`).join(', ')} };\n` : ''}${native.join('\n')}\n` })
109
+ return applySourceEdits(source, sourceMap, edits)
110
+ }
111
+
112
+ function moduleLinkPlan(source) {
113
+ const tree = parse(source, { sourceType: 'module', errorRecovery: true,
114
+ allowUndeclaredExports: true, plugins: CELL_PARSER_PLUGINS })
115
+ const allocate = createGeneratedNameAllocator(tree)
116
+ const reader = allocate('module_import_read')
117
+ const nativeReader = allocate('module_native_read')
118
+ const internalBindings = [reader, nativeReader]
119
+ const exports = []
120
+ const stars = []
121
+ const exportName = node => node.name ?? node.value
122
+ for (const statement of tree.program.body) {
123
+ if (statement.type === 'ExportDefaultDeclaration') exports.push({ name: 'default', kind: 'native' })
124
+ if (!['ExportNamedDeclaration', 'ExportAllDeclaration'].includes(statement.type)) continue
125
+ const relation = statement.source ? { source: statement.source.value,
126
+ attributes: Object.fromEntries((statement.attributes ?? [])
127
+ .map(attribute => [exportName(attribute.key), attribute.value.value])) } : undefined
128
+ if (statement.type === 'ExportAllDeclaration') stars.push(relation)
129
+ else for (const item of statement.specifiers) {
130
+ const name = exportName(item.exported)
131
+ exports.push(relation === undefined ? { name, kind: 'accessor' }
132
+ : item.type === 'ExportNamespaceSpecifier' ? { name, kind: 'namespace', ...relation }
133
+ : { name, kind: 'forward', imported: exportName(item.local), ...relation })
134
+ }
135
+ }
136
+ const runtime = new URL('./stateful-module-runtime.js', import.meta.url).href
137
+ return { reader, internalBindings, moduleInterface: { exports, stars },
138
+ prefix: `import {readModuleImport as ${nativeReader}} from ${JSON.stringify(runtime)};\nfunction ${reader}(source,name,get,attributes){return ${nativeReader}(import.meta.url,source,name,get,attributes)}\n` }
139
+ }
140
+
141
+ function adaptStaticModuleLinks(normalized, staticLinks) {
142
+ const edits = []
143
+ visitRegionSource(normalized, { sourceType: 'module', plugins: CELL_PARSER_PLUGINS }, input => {
144
+ for (const node of input.selected.body) {
145
+ if (node.source == null || !['ImportDeclaration', 'ExportNamedDeclaration', 'ExportAllDeclaration'].includes(node.type)) continue
146
+ const source = node.source.value
147
+ const attributes = Object.fromEntries((node.attributes ?? []).map(item => [item.key.name ?? item.key.value, item.value.value]))
148
+ const reference = staticModuleLinkReference(source, attributes)
149
+ staticLinks.push({ source, reference })
150
+ edits.push({ start: sourceOffsetAt(input.sourceMap, node.source.start),
151
+ end: sourceOffsetAt(input.sourceMap, node.source.end - 1) + 1,
152
+ text: JSON.stringify(reference) })
153
+ }
154
+ }, topLevelRegion)
155
+ return applyRegionEdits(normalized, edits)
156
+ }
157
+
158
+ function commonJsBodyRange(source) {
159
+ const body = parse(source).program.body[0].body
160
+ return { start: body.start + 1, end: body.end - 1 }
161
+ }
162
+
163
+ /** Module activations share lexical updates while retaining the native linker. */
164
+ export function compileStatefulModule(source, {
165
+ transform = USER_BINDING_TRANSFORM, target = 'module', url, nativeUsing, programBindings = false,
166
+ } = {}) {
167
+ if (transform !== PROTECTED_MODULE_TRANSFORM && !supportedUserBindingTransform(transform)) {
168
+ throw new TypeError('user binding snapshot cannot prove its historical TypeScript transform')
169
+ }
170
+ const staticLinks = []
171
+ const sourceType = target === 'commonjs' ? 'commonjs' : 'module'
172
+ const callableParserOptions = { sourceType, plugins: CELL_PARSER_PLUGINS,
173
+ ...(target === 'commonjs' ? { allowAwaitOutsideFunction: undefined, allowReturnOutsideFunction: undefined } : {}) }
174
+ let mapped = { code: source, sourceMap: identitySourceMap(source.length) }
175
+ let callableSources = []
176
+ let nativeJavaScript = false
177
+ if (source.startsWith('#!')) {
178
+ // Interpreter directives belong to the source's first line, never to the
179
+ // prefixed module or CommonJS wrapper. Retain its original line boundary.
180
+ const directive = source.match(/^#![^\n\r\u2028\u2029]*/u)
181
+ mapped = applySourceEdits(source, mapped.sourceMap, [{ start: 0,
182
+ end: directive[0].length, text: '' }])
183
+ }
184
+ if (transform !== LEGACY_USER_BINDING_TRANSFORM) {
185
+ const marked = markCallableSources(mapped.code, mapped.sourceMap, callableParserOptions,
186
+ { lowerNativeSource: lowerNativeLanguageSource, nativeUsing })
187
+ callableSources = marked.callableSources
188
+ nativeJavaScript = marked.nativeJavaScript
189
+ mapped = marked
190
+ if (!nativeJavaScript) mapped = normalizeTypeScriptValues(mapped.code, mapped.sourceMap, target)
191
+ if (target !== 'commonjs' && (isStatefulUserBindingTransform(transform)
192
+ || transform === PROTECTED_MODULE_TRANSFORM && hasModuleResources(mapped.code))) {
193
+ mapped = normalizeModuleExports(mapped.code, mapped.sourceMap)
194
+ }
195
+ }
196
+ const commonJsSource = target === 'commonjs'
197
+ ? commonJsExportEvidence(mapped.code, { legacy: transform === LEGACY_USER_BINDING_TRANSFORM }) : undefined
198
+ const links = isStatefulUserBindingTransform(transform) && target === 'module'
199
+ ? moduleLinkPlan(mapped.code) : undefined
200
+ let normalized = transform === LEGACY_USER_BINDING_TRANSFORM ? mapped
201
+ : normalizeStatefulScopes(mapped.code, mapped.sourceMap, { target, moduleImport: links?.reader, nativeJavaScript, nativeUsing,
202
+ mode: transform === PROTECTED_MODULE_TRANSFORM ? 'protected-v1' : 'stateful-v1' })
203
+ // Protected entries retain native declaration policy; adapters still need
204
+ // bounded source regions after TypeScript and decorator lowering.
205
+ if (transform === PROTECTED_MODULE_TRANSFORM && normalized.sourceRegions === undefined) normalized = { ...normalized,
206
+ sourceRegions: indexSourceRegions(normalized.code, callableParserOptions) }
207
+ let protectedInterface
208
+ if (transform === PROTECTED_MODULE_TRANSFORM && target === 'module') {
209
+ const lexicalExports = normalized.moduleLexicalExports
210
+ normalized = adaptLegacyModuleReferences(normalized)
211
+ protectedInterface = normalized.moduleInterface
212
+ if (lexicalExports !== undefined) protectedInterface = { ...protectedInterface,
213
+ exports: protectedInterface.exports.map(entry => lexicalExports.has(entry.name) ? { ...entry, kind: 'accessor' } : entry) }
214
+ }
215
+ if (links !== undefined) normalized = { ...applyRegionEdits(normalized,
216
+ [{ start: 0, end: 0, text: links.prefix }]),
217
+ internalBindings: new Set([...normalized.internalBindings ?? [], ...links.internalBindings]) }
218
+ const classificationCode = normalized.code
219
+ if (links !== undefined || protectedInterface !== undefined) normalized = adaptStaticModuleLinks(normalized, staticLinks)
220
+ if (transform !== LEGACY_USER_BINDING_TRANSFORM) normalized = adaptModuleOperations(normalized, { target, url })
221
+ if (transform !== LEGACY_USER_BINDING_TRANSFORM) normalized = { ...normalized, ...adaptDynamicCell(normalized.code, normalized.sourceMap, {
222
+ sourceRegions: normalized.sourceRegions,
223
+ callableCollector: createRegionCallableCollector(callableSources),
224
+ module: true, compactOutput: true, importOperation: normalized.importOperation, sourceType, originalSource: source,
225
+ logicalRoots: programBindings,
226
+ bindings: normalized.dynamicBindings, privateBindings: normalized.privateBindings,
227
+ internalBindings: normalized.internalBindings, parserPlugins: CELL_PARSER_PLUGINS,
228
+ }) }
229
+ // The published legacy map ends at its maintained transform input.
230
+ const wrapper = target === 'commonjs' ? 'function __ptc_commonjs__(){\n' : ''
231
+ let input = normalized
232
+ if (transform === LEGACY_USER_BINDING_TRANSFORM && wrapper) {
233
+ input = applySourceEdits(input.code, input.sourceMap, [{ start: 0, end: 0, text: wrapper }])
234
+ input = applySourceEdits(input.code, input.sourceMap, [{ start: input.code.length, end: input.code.length, text: '\n}' }])
235
+ }
236
+ let transformed, nativeExtraction, emission, sources
237
+ let moduleInterface = links?.moduleInterface ?? protectedInterface
238
+ if (transform === LEGACY_USER_BINDING_TRANSFORM) {
239
+ // Preserve the historical TypeScript lowering before adapting native
240
+ // bindings. Its unexpanded output is the source indexed by shared regions.
241
+ transformed = transformTypeScriptSource(input.code)
242
+ let code = transformed.code
243
+ if (wrapper) {
244
+ nativeExtraction = commonJsBodyRange(code)
245
+ code = code.slice(nativeExtraction.start, nativeExtraction.end)
246
+ }
247
+ let entry = { code, sourceMap: identitySourceMap(code.length),
248
+ sourceRegions: indexSourceRegions(code, callableParserOptions) }
249
+ if (target === 'commonjs') entry = normalizeStatefulScopes(code, entry.sourceMap,
250
+ { mode: 'protected-v1', target, nativeJavaScript: true, deferDecorators: true, deferResources: true })
251
+ if (target === 'module') {
252
+ entry = adaptLegacyModuleReferences(entry)
253
+ moduleInterface = entry.moduleInterface
254
+ entry = adaptStaticModuleLinks(entry, staticLinks)
255
+ }
256
+ entry = adaptModuleOperations(entry, { target, url })
257
+ emission = adaptDynamicCell(entry.code, entry.sourceMap, { module: true,
258
+ sourceRegions: entry.sourceRegions,
259
+ importOperation: entry.importOperation, sourceType, originalSource: source,
260
+ bindings: entry.dynamicBindings, internalBindings: entry.internalBindings, parserPlugins: CELL_PARSER_PLUGINS,
261
+ })
262
+ } else {
263
+ const owners = normalized.callableRanges === undefined ? collectRegionCallableRanges(normalized, callableSources, callableParserOptions)
264
+ : new Map(normalized.callableRanges.map(range => [range.start, range]))
265
+ // Native JavaScript has no remaining TypeScript emission work. Retain the
266
+ // generator's exact source and owner facts instead of expanding it again.
267
+ const output = nativeJavaScript ? { ...normalized, callableRanges: [...owners.values()] }
268
+ : transformRegionSource(normalized, { ...callableParserOptions, wrapCommonJs: true }, region => {
269
+ const generated = transformTypeScriptSource(region.code, {
270
+ module: target === 'module' && !region.prefix, sourceMap: true,
271
+ // Type-only declarations and the complete module interface were
272
+ // resolved before partitioning; omitted bodies cannot erase imports.
273
+ transform: { tsEnumIsMutable: true, verbatimModuleSyntax: true,
274
+ noEmptyExport: target === 'commonjs' || !!region.prefix },
275
+ })
276
+ return emitRegionCallableSources(region, generated, owners, callableParserOptions)
277
+ })
278
+ emission = nativeJavaScript ? output : { ...output, ...applySourceEdits(normalized.code, normalized.sourceMap,
279
+ [{ start: 0, end: normalized.code.length, text: output.code, mappings: output.sourceMap }]) }
280
+ sources = callableSourceCatalog(emission.code, callableSources, output.callableRanges)
281
+ }
282
+ // Callable ownership collection validates native output's exact grammar
283
+ // regions. Only the later TypeScript/legacy emitter changes that code.
284
+ if (!nativeJavaScript) validateRegionSource(emission, { sourceType, plugins: ['importAttributes'] })
285
+ return { code: emission.code, classificationCode, transform, target, moduleInterface, commonJsSource,
286
+ staticLinks, callableSources: sources,
287
+ sourceRegions: sourceRegionData(emission.sourceRegions),
288
+ sourceMap: { normalization: input.sourceMap, typescript: transformed?.map, nativeExtraction,
289
+ ...(transform === LEGACY_USER_BINDING_TRANSFORM ? {} : { emission: emission.sourceMap }) },
290
+ }
291
+ }
292
+
293
+ export function detectModuleSourceFormat(source, { extension } = {}) {
294
+ // Synchronous CommonJS hooks may leave format undefined. For an untyped
295
+ // package Node detects module syntax, including lexical wrapper-name clashes.
296
+ // Parse without executing source, allowing the repetitions PTC owns.
297
+ if (extension === '.ts') source = normalizeTypeScriptValues(source, identitySourceMap(source.length)).code
298
+ const tree = parse(source, { sourceType: 'unambiguous', errorRecovery: true,
299
+ allowReturnOutsideFunction: true, allowNewTargetOutsideFunction: true, plugins: CELL_PARSER_PLUGINS })
300
+ const wrapperNames = new Set(COMMONJS_PARAMETERS)
301
+ const lexicalWrapperName = tree.program.body.some(node => node.type === 'VariableDeclaration' && node.kind !== 'var'
302
+ ? node.declarations.some(item => bindingNodes(item.id).some(binding => wrapperNames.has(binding.name)))
303
+ : node.type === 'ClassDeclaration' && wrapperNames.has(node.id.name))
304
+ return tree.program.sourceType === 'module' || lexicalWrapperName ? 'module' : 'commonjs'
305
+ }
306
+
307
+ export function attachModuleNamespace(source, attributes, reference, sourceRegions) {
308
+ const text = source
309
+ const names = new Set()
310
+ visitRegionSource({ code: text, sourceMap: identitySourceMap(text.length), sourceRegions }, { sourceType: 'module' }, input => {
311
+ t.traverseFast(input.tree, node => { if (t.isIdentifier(node)) names.add(node.name) })
312
+ })
313
+ const allocate = createGeneratedNameAllocator(undefined, names)
314
+ const namespace = allocate('module_native_namespace')
315
+ const register = allocate('module_register_namespace')
316
+ const runtime = new URL('./stateful-module-runtime.js', import.meta.url).href
317
+ // A namespace import adds no named-import validation and reads no exports.
318
+ // Register after successful evaluation, before native require can return.
319
+ const entries = Object.entries(attributes ?? {})
320
+ const suffix = entries.length === 0 ? '' : ` with {${entries.map(([key, value]) => `${JSON.stringify(key)}:${JSON.stringify(value)}`).join(',')}}`
321
+ return `${text}\nimport * as ${namespace} from ${JSON.stringify(reference)}${suffix};\nimport {recordStatefulModuleNamespace as ${register}} from ${JSON.stringify(runtime)};\n${register}(import.meta.url,${namespace});\n`
322
+ }
@@ -0,0 +1,19 @@
1
+ import { registerHooks } from 'node:module'
2
+ import { compilerPlatformBridge } from './compiler-platform.js'
3
+
4
+ const nativeRegisterHooks = registerHooks
5
+ const apply = Reflect.apply
6
+ // Acquire the public hook lifecycle before any owned source can replace Node
7
+ // exports or the hook prototype. The empty bootstrap hook changes no edge.
8
+ const bootstrapHook = nativeRegisterHooks({})
9
+ const deregister = bootstrapHook.deregister
10
+ apply(deregister, bootstrapHook, [])
11
+
12
+ /** Each native resolution scope has one captured registration and disposer. */
13
+ export function registerModuleResolutionHook(resolve) {
14
+ const hook = nativeRegisterHooks({ resolve })
15
+ return () => apply(deregister, hook, [])
16
+ }
17
+
18
+ export const fileURLToPath = compilerPlatformBridge.fileURLToPath
19
+ export const pathToFileURL = compilerPlatformBridge.pathToFileURL
@@ -0,0 +1,42 @@
1
+ export const LEGACY_USER_BINDING_TRANSFORM = 'amaro@1.1.11'
2
+ export const PREVIOUS_USER_BINDING_TRANSFORM = 'stateful-module-v1+amaro@1.1.11'
3
+ export const USER_BINDING_TRANSFORM = 'stateful-module-v2+amaro@1.1.11'
4
+ export const PROTECTED_MODULE_TRANSFORM = 'protected-module-v1+amaro@1.1.11'
5
+ export const MODULE_TRANSFORMS = new Set([
6
+ LEGACY_USER_BINDING_TRANSFORM,
7
+ PREVIOUS_USER_BINDING_TRANSFORM,
8
+ USER_BINDING_TRANSFORM,
9
+ PROTECTED_MODULE_TRANSFORM,
10
+ ])
11
+
12
+ export function isStatefulUserBindingTransform(transform) {
13
+ return transform === USER_BINDING_TRANSFORM || transform === PREVIOUS_USER_BINDING_TRANSFORM
14
+ }
15
+
16
+ export function moduleTransformForLanguage(languageSemantics) {
17
+ return languageSemantics === 'stateful-v1' ? USER_BINDING_TRANSFORM
18
+ : languageSemantics === 'protected-v1' ? PROTECTED_MODULE_TRANSFORM : LEGACY_USER_BINDING_TRANSFORM
19
+ }
20
+
21
+ export function historicalModuleTransformForLanguage(languageSemantics) {
22
+ return languageSemantics === 'stateful-v1' ? PREVIOUS_USER_BINDING_TRANSFORM
23
+ : languageSemantics === 'protected-v1' ? PROTECTED_MODULE_TRANSFORM : LEGACY_USER_BINDING_TRANSFORM
24
+ }
25
+
26
+ export function moduleTransformMatchesLanguage(transform, languageSemantics) {
27
+ return languageSemantics === 'stateful-v1' ? isStatefulUserBindingTransform(transform)
28
+ : languageSemantics === 'protected-v1' ? transform === PROTECTED_MODULE_TRANSFORM
29
+ : languageSemantics === 'legacy-v1' ? transform === LEGACY_USER_BINDING_TRANSFORM : false
30
+ }
31
+
32
+ export function normalizeModuleTransform(transform, languageSemantics) {
33
+ if (!MODULE_TRANSFORMS.has(transform)) throw new TypeError('invalid dsh-ptc-plus journal module transform')
34
+ if (!moduleTransformMatchesLanguage(transform, languageSemantics)) {
35
+ throw new TypeError('dsh-ptc-plus journal module transform does not match its language semantics')
36
+ }
37
+ return transform
38
+ }
39
+
40
+ export function supportedUserBindingTransform(transform) {
41
+ return isStatefulUserBindingTransform(transform) || transform === LEGACY_USER_BINDING_TRANSFORM
42
+ }
@@ -0,0 +1,68 @@
1
+ import traverseModule from '@babel/traverse'
2
+ import { types as t } from '@babel/core'
3
+
4
+ const traverse = traverseModule.default ?? traverseModule
5
+
6
+ /** Native await owns persistent declaration instantiation; references own writes. */
7
+ export function rewriteNativeAwaitDeclarations(tree, { hiddenBindings, nativePlaceholders, reference, initialize, namedValue, replaceIterationDeclaration }) {
8
+ const placeholders = []
9
+ const preserve = node => { nativePlaceholders.add(node); placeholders.push(node) }
10
+ const rootIdentifiers = node => {
11
+ if (t.isIdentifier(node)) return [node]
12
+ if (t.isObjectPattern(node)) return node.properties.flatMap(property => rootIdentifiers(property.value ?? property.argument))
13
+ if (t.isArrayPattern(node)) return node.elements.flatMap(element => rootIdentifiers(element))
14
+ // Native REPL await registers direct pattern identifiers. Default targets
15
+ // and array rest targets remain assignment references in that generation.
16
+ return []
17
+ }
18
+ const lexicalPlaceholder = name => preserve(t.variableDeclaration('let', [
19
+ t.variableDeclarator(t.identifier(name), t.identifier(name)),
20
+ ]))
21
+ const assignmentPattern = (node, path) => {
22
+ if (t.isIdentifier(node)) return reference(path, node.name)
23
+ if (t.isArrayPattern(node)) return t.arrayPattern(node.elements.map(element => element === null ? null : assignmentPattern(element, path)))
24
+ if (t.isObjectPattern(node)) return t.objectPattern(node.properties.map(property => t.isRestElement(property)
25
+ ? t.restElement(assignmentPattern(property.argument, path))
26
+ : t.objectProperty(property.key, assignmentPattern(property.value, path), property.computed, false)))
27
+ if (t.isAssignmentPattern(node)) return t.assignmentPattern(assignmentPattern(node.left, path),
28
+ t.isIdentifier(node.left) ? namedValue(node.left.name, node.right) : node.right)
29
+ return t.restElement(assignmentPattern(node.argument, path))
30
+ }
31
+ traverse(tree, {
32
+ VariableDeclaration(path) {
33
+ if (path.node.declarations.some(declaration => t.isIdentifier(declaration.id) && hiddenBindings.has(declaration.id.name))
34
+ || path.getFunctionParent() !== null || path.node.kind !== 'var' && !path.parentPath.isProgram()) return
35
+ const original = path.node
36
+ if (original.kind === 'var') {
37
+ const declaration = t.cloneNode(original, true)
38
+ for (const item of declaration.declarations) item.init = t.unaryExpression('void', t.numericLiteral(0))
39
+ preserve(t.ifStatement(t.booleanLiteral(false), t.blockStatement([declaration])))
40
+ } else for (const item of original.declarations) for (const name of rootIdentifiers(item.id)) lexicalPlaceholder(name.name)
41
+ const assignment = item => {
42
+ const value = item.init ?? t.unaryExpression('void', t.numericLiteral(0))
43
+ return t.isIdentifier(item.id) ? initialize(path, item.id.name, namedValue(item.id.name, value))
44
+ : t.assignmentExpression('=', assignmentPattern(item.id, path), value)
45
+ }
46
+ if (path.parentPath.isForOfStatement() || path.parentPath.isForInStatement()) {
47
+ replaceIterationDeclaration(path, assignmentPattern(original.declarations[0].id, path),
48
+ original.declarations.filter(item => item.init !== null).map(assignment))
49
+ } else {
50
+ const assignments = original.declarations.map(assignment)
51
+ const expression = t.inherits(assignments.length === 1 ? assignments[0] : t.sequenceExpression(assignments), original)
52
+ path.replaceWith(path.parentPath.isForStatement() ? expression : t.expressionStatement(t.unaryExpression('void', expression)))
53
+ }
54
+ path.skip()
55
+ },
56
+ ClassDeclaration(path) {
57
+ if (!path.parentPath.isProgram()) return
58
+ const name = path.node.id.name
59
+ lexicalPlaceholder(name)
60
+ const target = reference(path.parentPath, name)
61
+ path.node.type = 'ClassExpression'
62
+ const assignment = t.inherits(t.assignmentExpression('=', target, path.node), path.node)
63
+ path.replaceWith(t.expressionStatement(t.unaryExpression('void', assignment)))
64
+ path.skip()
65
+ },
66
+ })
67
+ tree.program.body.unshift(...placeholders)
68
+ }
@@ -0,0 +1,54 @@
1
+ import { parse } from '@babel/parser'
2
+ import { bindingNodes, createGeneratedNameAllocator } from './binding-pattern.js'
3
+ import { markCallableSources, collectCallableSources } from './callable-source-facts.js'
4
+ import { adaptDynamicCell } from './dynamic-environment-integration.js'
5
+ import { CELL_PARSER_PLUGINS } from './repl-scope-normalizer.js'
6
+
7
+ /** Native declarations remain frozen; dynamic entries retain their native root. */
8
+ export function adaptNativeRootDynamic(prepared, options, originalSource) {
9
+ if (prepared.collisions.length !== 0) return { ...prepared, nativeLexicals: new Set() }
10
+ const parser = { sourceType: 'script', allowAwaitOutsideFunction: true,
11
+ allowReturnOutsideFunction: true, plugins: CELL_PARSER_PLUGINS }
12
+ const marked = markCallableSources(prepared.code, prepared.sourceMap, parser)
13
+ const tree = parse(marked.code, parser)
14
+ const nativeLexicals = new Set(tree.program.body.flatMap(statement =>
15
+ statement.type === 'VariableDeclaration' && statement.kind !== 'var'
16
+ ? statement.declarations.flatMap(declaration => bindingNodes(declaration.id).map(binding => binding.name))
17
+ : statement.type === 'ClassDeclaration' ? [statement.id.name] : []))
18
+ const nativeAwait = hasRootAwait(tree.program)
19
+ const reservedBindings = new Set([...prepared.importNamespaces,
20
+ ...options.knownBindings ?? [], ...options.reservedBindings ?? []])
21
+ const allocate = createGeneratedNameAllocator(parse(marked.code, parser), reservedBindings)
22
+ const global = allocate('native_environment_global')
23
+ const established = [...options.establishedRoots ?? []]
24
+ const logicalRoots = established.filter(([, source]) => source !== 'absent').map(([name]) => name)
25
+ const nativePublications = prepared.declarations.filter(declaration => options.establishedRoots?.has(declaration.name)
26
+ && !prepared.redeclared.some(redeclaration => redeclaration.name === declaration.name))
27
+ .map(declaration => ({ name: declaration.name, writable: declaration.writable,
28
+ nativeLexical: nativeLexicals.has(declaration.name),
29
+ import: prepared.imports.get(declaration.name) }))
30
+ const dynamic = adaptDynamicCell(marked.code, marked.sourceMap, { nativeRoot: true,
31
+ environmentGlobal: global, reservedBindings, internalBindings: prepared.importNamespaces,
32
+ originalSource, parserPlugins: CELL_PARSER_PLUGINS, nativeAwait, logicalRoots: logicalRoots.length > 0 })
33
+ const callableSources = collectCallableSources(dynamic.code, marked.callableSources, parser)
34
+ return { ...prepared, code: dynamic.code, sourceMap: dynamic.sourceMap, nativeLexicals,
35
+ ...(established.length === 0 ? {} : { rootBindingFacts: true, rootBindings: {
36
+ known: [...options.knownBindings ?? []], established, candidates: [...options.rootCandidates ?? []],
37
+ dynamicOrigins: options.dynamicOrigins ?? [], legacyImports: [...options.importBindings ?? []],
38
+ } }),
39
+ importNamespaces: new Set([...prepared.importNamespaces, dynamic.dynamicEnvironmentName]),
40
+ moduleLoads: [...prepared.moduleLoads, { operation: 'native-dynamic', global, callableSources, awaitRoot: nativeAwait,
41
+ nativeLexicals: [...options.nativeLexicalBindings ?? []],
42
+ logicalRoots, writableRoots: logicalRoots.filter(name => options.writableBindings?.has(name)), nativePublications }] }
43
+ }
44
+
45
+ function hasRootAwait(node) {
46
+ if (node === null || typeof node !== 'object') return false
47
+ if (node.type === 'AwaitExpression' || node.type === 'ForOfStatement' && node.await) return true
48
+ if (['FunctionDeclaration', 'FunctionExpression', 'ArrowFunctionExpression'].includes(node.type)) return false
49
+ if (['ObjectMethod', 'ClassMethod', 'ClassPrivateMethod'].includes(node.type)) {
50
+ return node.computed && hasRootAwait(node.key)
51
+ }
52
+ return Object.entries(node).some(([key, value]) => !['loc', 'extra', 'start', 'end'].includes(key)
53
+ && (Array.isArray(value) ? value.some(hasRootAwait) : value?.type !== undefined && hasRootAwait(value)))
54
+ }
@@ -0,0 +1,67 @@
1
+ import { createDynamicEnvironmentRuntime } from './dynamic-environment-runtime.js'
2
+ import { moduleRuntimeIntrinsics as internal } from './compiler-intrinsics.js'
3
+
4
+ const { Map, Set, mapGet, mapSet, mapHas, mapDelete, setHas, setAdd, appendArray } = internal
5
+
6
+ /** Native storage and catalog-proved logical roots share a captured legacy view. */
7
+ export function createNativeRootDynamic({ intrinsics, importModule, read, write, typeOf, remove, logicalReference }) {
8
+ const interfaceOwner = {}
9
+ const runtime = createDynamicEnvironmentRuntime({ ...intrinsics, importModule, interfaceOwner }).installIntrinsics()
10
+ const descriptor = name => ({ kind: 'var', get: () => read(name),
11
+ set: (value, strict) => write(name, value, strict), delete: () => remove(name), typeof: () => typeOf(name) })
12
+ const environment = runtime.environment({
13
+ ambient(name, strict) {
14
+ return runtime.reference(name, descriptor(name), undefined, strict)
15
+ },
16
+ declareVars: runtime.declareGlobals,
17
+ createVar: descriptor,
18
+ })
19
+ runtime.setRootEnvironment(() => environment)
20
+ return {
21
+ environment(callableSources, awaitRoot = false, logicalRoots = [], writableRoots = []) {
22
+ if (logicalRoots.length === 0) {
23
+ runtime.registerSources(callableSources)
24
+ return awaitRoot ? environment.awaitActivation() : environment
25
+ }
26
+ // Each captured legacy environment keeps its own root view. Installing a
27
+ // later bridge must not change escaped eval/Function calls from old cells.
28
+ const bridgedRuntime = createDynamicEnvironmentRuntime({ ...intrinsics, importModule, interfaceOwner }).installIntrinsics()
29
+ const writable = new Set()
30
+ for (let index = 0; index < writableRoots.length; index++) setAdd(writable, writableRoots[index])
31
+ const bindings = new Map(), varFrame = new Map(), roots = new Map()
32
+ for (let index = 0; index < logicalRoots.length; index++) {
33
+ const name = logicalRoots[index], binding = logicalReference(name, setHas(writable, name))
34
+ mapSet(bindings, name, binding)
35
+ mapSet(roots, name, binding)
36
+ if (binding.kind === 'var') mapSet(varFrame, name, binding)
37
+ const remove = binding.delete
38
+ binding.delete = () => {
39
+ if (!remove()) return false
40
+ mapDelete(bindings, name)
41
+ mapDelete(varFrame, name)
42
+ return true
43
+ }
44
+ }
45
+ const bridged = bridgedRuntime.environment({ frames: [{ kind: 'lexical', bindings }], varFrame,
46
+ ambient: (name, strict) => bridgedRuntime.reference(name, descriptor(name), undefined, strict),
47
+ declareVars(names, functionNames) {
48
+ const globals = []
49
+ for (let index = 0; index < names.length; index++) {
50
+ if (!mapHas(roots, names[index])) appendArray(globals, names[index])
51
+ }
52
+ bridgedRuntime.declareGlobals(globals, functionNames)
53
+ },
54
+ createVar(name) {
55
+ const root = mapGet(roots, name)
56
+ if (root === undefined) return descriptor(name)
57
+ root.declare()
58
+ mapSet(bindings, name, root)
59
+ return root
60
+ },
61
+ })
62
+ bridgedRuntime.setRootEnvironment(() => bridged)
63
+ bridgedRuntime.registerSources(callableSources)
64
+ return awaitRoot ? bridged.awaitActivation() : bridged
65
+ },
66
+ }
67
+ }
@@ -1,14 +1,22 @@
1
1
  /** Shared structural guards for closed PTC metadata boundaries. */
2
2
 
3
+ import { runtimeIntrinsics as internal } from './runtime-intrinsics.js'
4
+
5
+ const { TypeError, isArray, reflectOwnKeys, objectGetOwnPropertyDescriptor,
6
+ objectHasOwn, objectPropertyIsEnumerable, objectFreeze, trimString, toString,
7
+ Set, setHas, setAdd, setSize, appendArray, popArray } = internal
8
+
3
9
  export function isRecord(value) {
4
- return value !== null && typeof value === 'object' && !Array.isArray(value)
10
+ return value !== null && typeof value === 'object' && !isArray(value)
5
11
  }
6
12
 
7
13
  export function assertOwnFields(value, allowed, label) {
8
- for (const key of Reflect.ownKeys(value)) {
9
- if (typeof key !== 'string' || !allowed.has(key)
10
- || !Object.prototype.propertyIsEnumerable.call(value, key)) {
11
- throw new TypeError(`invalid ${label} field ${String(key)}`)
14
+ const keys = reflectOwnKeys(value)
15
+ for (let index = 0; index < keys.length; index += 1) {
16
+ const key = keys[index]
17
+ if (typeof key !== 'string' || !setHas(allowed, key)
18
+ || !objectPropertyIsEnumerable(value, key)) {
19
+ throw new TypeError(`invalid ${label} field ${toString(key)}`)
12
20
  }
13
21
  }
14
22
  }
@@ -16,7 +24,7 @@ export function assertOwnFields(value, allowed, label) {
16
24
  export function assertFields(value, allowed, label) {
17
25
  if (!isRecord(value)) throw new TypeError(`invalid ${label}`)
18
26
  assertOwnFields(value, allowed, label)
19
- if (Reflect.ownKeys(value).length !== allowed.size) throw new TypeError(`invalid ${label} fields`)
27
+ if (reflectOwnKeys(value).length !== setSize(allowed)) throw new TypeError(`invalid ${label} fields`)
20
28
  }
21
29
 
22
30
  export function record(value, label) {
@@ -25,7 +33,7 @@ export function record(value, label) {
25
33
  }
26
34
 
27
35
  export function text(value, label) {
28
- if (typeof value !== 'string' || value.trim().length === 0) {
36
+ if (typeof value !== 'string' || trimString(value).length === 0) {
29
37
  throw new TypeError(`ptc-plus: ${label} must be a non-empty string`)
30
38
  }
31
39
  return value
@@ -37,17 +45,18 @@ export function deepFreeze(value) {
37
45
  const pending = [value]
38
46
  const seen = new Set()
39
47
  while (pending.length > 0) {
40
- const current = pending.pop()
41
- if (seen.has(current)) continue
42
- seen.add(current)
43
- for (const key of Reflect.ownKeys(current)) {
44
- const descriptor = Object.getOwnPropertyDescriptor(current, key)
45
- if (descriptor !== undefined && Object.hasOwn(descriptor, 'value')) {
48
+ const current = popArray(pending)
49
+ if (setHas(seen, current)) continue
50
+ setAdd(seen, current)
51
+ const keys = reflectOwnKeys(current)
52
+ for (let index = 0; index < keys.length; index += 1) {
53
+ const descriptor = objectGetOwnPropertyDescriptor(current, keys[index])
54
+ if (descriptor !== undefined && objectHasOwn(descriptor, 'value')) {
46
55
  const child = descriptor.value
47
- if (child !== null && typeof child === 'object') pending.push(child)
56
+ if (child !== null && typeof child === 'object') appendArray(pending, child)
48
57
  }
49
58
  }
50
- Object.freeze(current)
59
+ objectFreeze(current)
51
60
  }
52
61
  return value
53
62
  }