dsh-ptc-plus 0.4.1 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +164 -78
- package/README.md +165 -79
- package/assets/dsh-ptc-plus-banner-en.webp +0 -0
- package/assets/dsh-ptc-plus-banner-zh.webp +0 -0
- package/assets/ptc-plus-icon.svg +5 -0
- package/client.js +854 -336
- package/compiler-core.cjs +161 -157
- package/compiler-core.cjs.map +3 -3
- package/docs/README.md +4 -1
- package/docs/adr/0005-temporary-rejected-cell-edit-transport.md +8 -7
- package/docs/adr/0008-define-agent-operating-contract.md +2 -2
- package/docs/adr/0010-session-log-derived-recovery-tips.md +7 -0
- package/docs/adr/0016-archive-resolved-review-findings.md +3 -3
- package/docs/adr/0019-plugin-settings-and-kill-switch.md +3 -3
- package/docs/adr/0020-optional-cordis-tools-in-ptc-mode.md +2 -0
- package/docs/adr/0021-separate-host-bootstrap-from-session-runtime.md +14 -3
- package/docs/adr/0023-global-user-bindings.md +7 -7
- package/docs/adr/0025-use-versioned-logical-binding-identities.md +3 -3
- package/docs/adr/0026-persist-the-delivery-verdict-against-the-verified-candidate.md +23 -7
- package/docs/adr/0027-run-the-session-kernel-in-a-killable-helper-process.md +9 -5
- package/docs/adr/0028-attach-to-the-host-ptc-execution-seam.md +26 -6
- package/docs/adr/0031-close-semantic-obligations-by-owner.md +29 -0
- package/docs/adr/README.md +4 -4
- package/docs/architecture.md +15 -10
- package/docs/binding-review-placement-design.md +1 -1
- package/docs/client-ui.md +9 -5
- package/docs/durability-design.md +12 -9
- package/docs/installation.md +27 -9
- package/docs/runtime-reference.md +23 -12
- package/docs/semantic-validation.md +7 -3
- package/docs/stateful-binding-updates-proposal.md +8 -4
- package/docs/user-bindings.en.md +10 -7
- package/docs/user-bindings.md +9 -6
- package/docs/value-wire.md +1 -1
- package/docs/verification-optimization-work.md +41 -0
- package/docs/verification.md +53 -2
- package/index.js +39 -34
- package/internal/async-local-storage-intrinsics.js +43 -0
- package/internal/binding-declaration-contract.js +8 -0
- package/internal/binding-source-analysis.js +381 -64
- package/internal/binding-update-policy.js +7 -1
- package/internal/callable-source-facts.js +37 -1
- package/internal/cell-analysis.js +85 -17
- package/internal/compiler-intrinsics.js +9 -43
- package/internal/compiler-module-links.js +7 -4
- package/internal/config-spec.js +1 -1
- package/internal/cordis-tools-owner.js +20 -10
- package/internal/dynamic-environment-integration.js +8 -4
- package/internal/dynamic-environment-runtime.js +24 -3
- package/internal/dynamic-native-calls.js +4 -1
- package/internal/dynamic-native-runtime.js +15 -1
- package/internal/edit-transport-owner.js +80 -20
- package/internal/execution-seam-compat.js +192 -30
- package/internal/failure-reporting.js +38 -30
- package/internal/isolated-worker.js +17 -10
- package/internal/kernel-worker.js +645 -393
- package/internal/message-sources.js +14 -0
- package/internal/module-compilation.js +7 -5
- package/internal/module-transform-contract.js +32 -2
- package/internal/record-utils.js +24 -15
- package/internal/repl-memory-projection.js +10 -0
- package/internal/repl-scope-normalizer.js +72 -35
- package/internal/repl-value-observer.js +145 -46
- package/internal/runtime-config.js +62 -2
- package/internal/runtime-intrinsics.js +104 -0
- package/internal/runtime-messages.js +6 -4
- package/internal/session-cell-executor.js +26 -2
- package/internal/session-journal-recovery.js +267 -67
- package/internal/session-journal-schema.js +30 -13
- package/internal/session-journal.js +485 -44
- package/internal/session-log-view.js +5 -4
- package/internal/session-runtime.js +46 -21
- package/internal/session-state.js +7 -29
- package/internal/settings-compat.js +66 -1
- package/internal/source-position-map.js +38 -0
- package/internal/stateful-root-compiler.js +3 -1
- package/internal/typescript-transform.js +4 -2
- package/internal/user-binding-console-worker.js +115 -41
- package/internal/user-binding-draft-projection.js +3 -2
- package/internal/user-bindings-owner.js +2 -1
- package/internal/user-bindings.js +16 -3
- package/internal/validated-parse-repair.js +6 -2
- package/internal/value-wire.js +189 -94
- package/internal/worker-client.js +99 -8
- package/internal/worker-cwd-virtualization.js +82 -54
- package/internal/worker-environment.js +20 -0
- package/internal/worker-output-capture.js +187 -0
- package/internal/worker-output-fence.js +26 -0
- package/internal/worker-realm-surfaces.js +197 -0
- package/internal/worker-repl-realm.js +140 -0
- package/package.json +37 -4
- package/src/client-activity.js +12 -2
- package/src/client-authoring-view.js +121 -62
- package/src/client-console.js +4 -2
- package/src/client-copy.js +4 -2
- package/src/client-feature-gates.js +7 -9
- package/src/client-host-compat.js +104 -27
- package/src/client-repl-view.js +3 -1
- package/src/client-styles.js +12 -1
- package/src/client-tool-view.js +3 -1
- package/src/client-transport.js +2 -2
- package/src/client-workbench.js +4 -3
- package/src/client.js +56 -17
|
@@ -2,13 +2,14 @@ import { parse } from '@babel/parser'
|
|
|
2
2
|
import { AMBIENT_GLOBALS, renderDurabilityReasons } from './module-policy.js'
|
|
3
3
|
import { CELL_PARSER_PLUGINS, normalizeTypeScriptValues } from './repl-scope-normalizer.js'
|
|
4
4
|
import { identitySourceMap } from './source-position-map.js'
|
|
5
|
-
import { LEGACY_USER_BINDING_TRANSFORM, transformTypeScriptSource } from './typescript-transform.js'
|
|
5
|
+
import { LEGACY_USER_BINDING_TRANSFORM, USER_BINDING_TRANSFORM, transformTypeScriptSource } from './typescript-transform.js'
|
|
6
6
|
import { compileStatefulModule } from './module-compilation.js'
|
|
7
7
|
import { prepareProgram, classifyDurability } from './cell-analysis.js'
|
|
8
8
|
import { createCompilerSourceCache } from './compiler-source-cache.js'
|
|
9
|
+
import { bindingTypeNamespaceToken } from './binding-declaration-contract.js'
|
|
9
10
|
|
|
10
11
|
const MAX_NAME_LENGTH = 128
|
|
11
|
-
const
|
|
12
|
+
const LEGACY_GLOBAL_TYPE_NAMES = new Set([
|
|
12
13
|
'Array', 'ArrayBuffer', 'ArrayBufferView', 'AsyncIterable', 'AsyncIterableIterator',
|
|
13
14
|
'AsyncIterator', 'Awaited', 'BigInt', 'BigInt64Array', 'BigUint64Array', 'Boolean',
|
|
14
15
|
'Buffer', 'ConstructorParameters', 'DataView', 'Date', 'Error', 'EvalError', 'Exclude',
|
|
@@ -92,7 +93,13 @@ function typeReferenceRoot(node) {
|
|
|
92
93
|
return current?.type === 'Identifier' ? current.name : undefined
|
|
93
94
|
}
|
|
94
95
|
|
|
95
|
-
function
|
|
96
|
+
function typeReferenceRootNode(node) {
|
|
97
|
+
let current = node
|
|
98
|
+
while (current?.type === 'TSQualifiedName') current = current.left
|
|
99
|
+
return current?.type === 'Identifier' ? current : undefined
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function projectedType(source, node, outerTypeNames, typeContext, usedTypeNames) {
|
|
96
103
|
const replacements = []
|
|
97
104
|
const commentRanges = new Set()
|
|
98
105
|
const visit = (current, inheritedNames) => {
|
|
@@ -115,21 +122,53 @@ function projectedType(source, node, outerTypeNames = new Set(), sourceTypeNames
|
|
|
115
122
|
if (current.type === 'TSMappedType' && typeof current.typeParameter?.name === 'string') {
|
|
116
123
|
typeNames = new Set([...typeNames, current.typeParameter.name])
|
|
117
124
|
}
|
|
118
|
-
if (current.type === 'TSImportType' || current.type === 'TSTypeQuery') {
|
|
125
|
+
if (!typeContext.modern && (current.type === 'TSImportType' || current.type === 'TSTypeQuery')) {
|
|
119
126
|
replacements.push({ start: current.start, end: current.end, text: 'unknown' })
|
|
120
127
|
return
|
|
121
128
|
}
|
|
122
|
-
if (current.type === '
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
129
|
+
if (current.type === 'TSTypeQuery') {
|
|
130
|
+
const reference = current.exprName
|
|
131
|
+
const name = typeReferenceRoot(reference)
|
|
132
|
+
if (typeContext.modern && name !== undefined && !typeNames.has(name)) {
|
|
133
|
+
if (typeContext.importedNames.has(name)) {
|
|
134
|
+
throw new TypeError(`imported value ${JSON.stringify(name)} cannot be represented in the binding interface; use an explicit import(...) type query`)
|
|
135
|
+
}
|
|
136
|
+
if (typeContext.localValues.has(name)) {
|
|
137
|
+
const declaration = typeContext.localDeclarations.get(name)
|
|
138
|
+
if (declaration === undefined
|
|
139
|
+
|| !['ClassDeclaration', 'TSEnumDeclaration'].includes(declaration.type)
|
|
140
|
+
|| (reference.type !== 'Identifier' && declaration.type !== 'TSEnumDeclaration')) {
|
|
141
|
+
throw new TypeError(`local value query ${JSON.stringify(name)} cannot be represented in the binding interface; use an explicit structural type`)
|
|
142
|
+
}
|
|
143
|
+
usedTypeNames.add(name)
|
|
144
|
+
const root = typeReferenceRootNode(reference)
|
|
145
|
+
replacements.push({ start: root.start, end: root.end,
|
|
146
|
+
text: `${typeContext.typeNamespaceToken}.${name}` })
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
} else if (current.type === 'TSTypeReference' || current.type === 'TSExpressionWithTypeArguments') {
|
|
150
|
+
const reference = current.typeName ?? current.expression
|
|
151
|
+
const name = typeReferenceRoot(reference)
|
|
152
|
+
if (!typeContext.modern && (name === undefined || !typeNames.has(name)
|
|
153
|
+
&& (typeContext.sourceTypeNames.has(name) || !LEGACY_GLOBAL_TYPE_NAMES.has(name)))) {
|
|
126
154
|
replacements.push({ start: current.start, end: current.end, text: 'unknown' })
|
|
127
155
|
return
|
|
128
156
|
}
|
|
157
|
+
if (typeContext.modern && name !== undefined && !typeNames.has(name)) {
|
|
158
|
+
if (typeContext.importedNames.has(name)) {
|
|
159
|
+
throw new TypeError(`imported type ${JSON.stringify(name)} cannot be represented in the binding interface; use an explicit import(...) type or a local structural type`)
|
|
160
|
+
}
|
|
161
|
+
if (typeContext.localDeclarations.has(name)) {
|
|
162
|
+
usedTypeNames.add(name)
|
|
163
|
+
const root = typeReferenceRootNode(reference)
|
|
164
|
+
replacements.push({ start: root.start, end: root.end,
|
|
165
|
+
text: `${typeContext.typeNamespaceToken}.${name}` })
|
|
166
|
+
}
|
|
167
|
+
}
|
|
129
168
|
}
|
|
130
169
|
for (const [key, value] of Object.entries(current)) {
|
|
131
170
|
if (key === 'loc' || key === 'start' || key === 'end'
|
|
132
|
-
|| key === 'typeParameters' || key === 'typeName' || key === 'expression') continue
|
|
171
|
+
|| key === 'typeParameters' || key === 'typeName' || key === 'expression' || key === 'exprName') continue
|
|
133
172
|
if (Array.isArray(value)) value.forEach(item => visit(item, typeNames))
|
|
134
173
|
else visit(value, typeNames)
|
|
135
174
|
}
|
|
@@ -146,50 +185,50 @@ function projectedType(source, node, outerTypeNames = new Set(), sourceTypeNames
|
|
|
146
185
|
return text
|
|
147
186
|
}
|
|
148
187
|
|
|
149
|
-
function typeParameters(source, node, outerTypeNames
|
|
188
|
+
function typeParameters(source, node, outerTypeNames, typeContext, usedTypeNames) {
|
|
150
189
|
const declaration = node?.typeParameters
|
|
151
190
|
if (declaration?.type !== 'TSTypeParameterDeclaration') {
|
|
152
191
|
return { text: '', names: outerTypeNames }
|
|
153
192
|
}
|
|
154
193
|
const names = new Set([...outerTypeNames, ...typeParameterNames(declaration)])
|
|
155
|
-
return { text: projectedType(source, declaration, names,
|
|
194
|
+
return { text: projectedType(source, declaration, names, typeContext, usedTypeNames), names }
|
|
156
195
|
}
|
|
157
196
|
|
|
158
|
-
function annotation(source, node, typeNames
|
|
197
|
+
function annotation(source, node, typeNames, typeContext, usedTypeNames) {
|
|
159
198
|
const type = node?.typeAnnotation?.typeAnnotation
|
|
160
|
-
return type === undefined ? 'unknown' : projectedType(source, type, typeNames,
|
|
199
|
+
return type === undefined ? 'unknown' : projectedType(source, type, typeNames, typeContext, usedTypeNames)
|
|
161
200
|
}
|
|
162
201
|
|
|
163
|
-
function parameter(source, node, index, typeNames
|
|
202
|
+
function parameter(source, node, index, typeNames, typeContext, usedTypeNames) {
|
|
164
203
|
if (node?.type === 'TSParameterProperty') {
|
|
165
|
-
return parameter(source, node.parameter, index, typeNames,
|
|
204
|
+
return parameter(source, node.parameter, index, typeNames, typeContext, usedTypeNames)
|
|
166
205
|
}
|
|
167
206
|
if (node?.type === 'RestElement') {
|
|
168
207
|
const argument = node.argument
|
|
169
208
|
return argument?.type === 'Identifier'
|
|
170
|
-
? `...${argument.name}: ${node.typeAnnotation === undefined ? 'unknown[]' : annotation(source, node, typeNames,
|
|
209
|
+
? `...${argument.name}: ${node.typeAnnotation === undefined ? 'unknown[]' : annotation(source, node, typeNames, typeContext, usedTypeNames)}`
|
|
171
210
|
: `...args${index}: unknown[]`
|
|
172
211
|
}
|
|
173
212
|
const optional = node?.type === 'AssignmentPattern'
|
|
174
213
|
const target = optional ? node.left : node
|
|
175
214
|
if (target?.type !== 'Identifier') return `arg${index}: unknown`
|
|
176
|
-
return `${target.name}${optional || target.optional === true ? '?' : ''}: ${annotation(source, target, typeNames,
|
|
215
|
+
return `${target.name}${optional || target.optional === true ? '?' : ''}: ${annotation(source, target, typeNames, typeContext, usedTypeNames)}`
|
|
177
216
|
}
|
|
178
217
|
|
|
179
|
-
function returnType(source, node, typeNames
|
|
218
|
+
function returnType(source, node, typeNames, typeContext, usedTypeNames) {
|
|
180
219
|
const explicit = node?.returnType?.typeAnnotation
|
|
181
|
-
if (explicit !== undefined) return projectedType(source, explicit, typeNames,
|
|
220
|
+
if (explicit !== undefined) return projectedType(source, explicit, typeNames, typeContext, usedTypeNames)
|
|
182
221
|
return node?.async === true ? 'Promise<unknown>' : 'unknown'
|
|
183
222
|
}
|
|
184
223
|
|
|
185
|
-
function functionType(source, node, outerTypeNames
|
|
186
|
-
const generics = typeParameters(source, node, outerTypeNames,
|
|
224
|
+
function functionType(source, node, outerTypeNames, typeContext, usedTypeNames) {
|
|
225
|
+
const generics = typeParameters(source, node, outerTypeNames, typeContext, usedTypeNames)
|
|
187
226
|
const parameters = (node.params ?? [])
|
|
188
|
-
.map((item, index) => parameter(source, item, index, generics.names,
|
|
189
|
-
return `${generics.text}(${parameters}) => ${returnType(source, node, generics.names,
|
|
227
|
+
.map((item, index) => parameter(source, item, index, generics.names, typeContext, usedTypeNames)).join(', ')
|
|
228
|
+
return `${generics.text}(${parameters}) => ${returnType(source, node, generics.names, typeContext, usedTypeNames)}`
|
|
190
229
|
}
|
|
191
230
|
|
|
192
|
-
function inferredType(source, node, depth
|
|
231
|
+
function inferredType(source, node, depth, typeContext, usedTypeNames) {
|
|
193
232
|
if (depth > 2 || node === null || node === undefined) return 'unknown'
|
|
194
233
|
if (node.type === 'StringLiteral' || node.type === 'TemplateLiteral') return 'string'
|
|
195
234
|
if (node.type === 'NumericLiteral') return 'number'
|
|
@@ -197,7 +236,7 @@ function inferredType(source, node, depth = 0, sourceTypeNames = new Set()) {
|
|
|
197
236
|
if (node.type === 'BigIntLiteral') return 'bigint'
|
|
198
237
|
if (node.type === 'NullLiteral') return 'null'
|
|
199
238
|
if (node.type === 'ArrowFunctionExpression' || node.type === 'FunctionExpression') {
|
|
200
|
-
return functionType(source, node, new Set(),
|
|
239
|
+
return functionType(source, node, new Set(), typeContext, usedTypeNames)
|
|
201
240
|
}
|
|
202
241
|
if (node.type === 'ArrayExpression') return 'unknown[]'
|
|
203
242
|
if (node.type === 'ObjectExpression') {
|
|
@@ -208,34 +247,258 @@ function inferredType(source, node, depth = 0, sourceTypeNames = new Set()) {
|
|
|
208
247
|
? property.key.name
|
|
209
248
|
: property.key.type === 'StringLiteral' ? JSON.stringify(property.key.value) : undefined
|
|
210
249
|
if (name === undefined) return 'Record<string, unknown>'
|
|
211
|
-
members.push(`${name}: ${inferredType(source, property.value, depth + 1,
|
|
250
|
+
members.push(`${name}: ${inferredType(source, property.value, depth + 1, typeContext, usedTypeNames)}`)
|
|
212
251
|
}
|
|
213
252
|
return `{ ${members.join('; ')} }`
|
|
214
253
|
}
|
|
215
254
|
return 'unknown'
|
|
216
255
|
}
|
|
217
256
|
|
|
218
|
-
function
|
|
257
|
+
function classMemberName(member) {
|
|
258
|
+
return member.key?.type === 'Identifier'
|
|
259
|
+
? member.key.name
|
|
260
|
+
: member.key?.type === 'StringLiteral' ? JSON.stringify(member.key.value) : undefined
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function modernClassMemberName(member) {
|
|
264
|
+
const key = classMemberKey(member)
|
|
265
|
+
return classMemberName(member) ?? (key === undefined ? undefined : JSON.stringify(key))
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function classMemberKey(member) {
|
|
269
|
+
if (member.computed && !['StringLiteral', 'NumericLiteral', 'BigIntLiteral'].includes(member.key?.type)) {
|
|
270
|
+
throw new TypeError('computed class member key cannot be represented in the binding interface; use a literal property key')
|
|
271
|
+
}
|
|
272
|
+
return member.key?.type === 'Identifier'
|
|
273
|
+
? member.key.name
|
|
274
|
+
: member.key?.type === 'StringLiteral' ? member.key.value
|
|
275
|
+
: member.key?.type === 'NumericLiteral' ? String(member.key.value)
|
|
276
|
+
: member.key?.type === 'BigIntLiteral' ? String(BigInt(member.key.value)) : undefined
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function isPublicClassMember(member) {
|
|
280
|
+
return !member.static
|
|
281
|
+
&& member.accessibility !== 'private' && member.accessibility !== 'protected'
|
|
282
|
+
&& member.key?.type !== 'PrivateName'
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function parameterPropertyMember(source, node, classTypeNames, typeContext, usedTypeNames) {
|
|
286
|
+
if (node?.type !== 'TSParameterProperty' || node.accessibility === 'private' || node.accessibility === 'protected') return undefined
|
|
287
|
+
const parameterNode = node.parameter
|
|
288
|
+
const optional = parameterNode?.type === 'AssignmentPattern'
|
|
289
|
+
const target = optional ? parameterNode.left : parameterNode
|
|
290
|
+
if (target?.type !== 'Identifier') return undefined
|
|
291
|
+
return `${node.readonly === true ? 'readonly ' : ''}${target.name}${optional || target.optional === true ? '?' : ''}: ${annotation(source, target, classTypeNames, typeContext, usedTypeNames)}`
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function parameterPropertyName(node) {
|
|
295
|
+
if (node?.type !== 'TSParameterProperty' || node.accessibility === 'private' || node.accessibility === 'protected') return undefined
|
|
296
|
+
const parameter = node.parameter?.type === 'AssignmentPattern' ? node.parameter.left : node.parameter
|
|
297
|
+
return parameter?.type === 'Identifier' ? parameter.name : undefined
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function legacyClassMembers(source, node, classTypeNames, typeContext, usedTypeNames) {
|
|
219
301
|
const members = []
|
|
302
|
+
const memberNames = new Set()
|
|
220
303
|
let constructorParameters = '...args: unknown[]'
|
|
221
304
|
for (const member of node.body?.body ?? []) {
|
|
222
|
-
if (
|
|
223
|
-
|| member.accessibility === 'private' || member.key?.type === 'PrivateName') continue
|
|
224
|
-
const name = member
|
|
225
|
-
? member.key.name
|
|
226
|
-
: member.key?.type === 'StringLiteral' ? JSON.stringify(member.key.value) : undefined
|
|
305
|
+
if (!['ClassMethod', 'TSDeclareMethod'].includes(member.type)
|
|
306
|
+
|| member.static || member.computed || member.accessibility === 'private' || member.key?.type === 'PrivateName') continue
|
|
307
|
+
const name = classMemberName(member)
|
|
227
308
|
if (name === undefined) continue
|
|
228
|
-
const generics = typeParameters(source, member, classTypeNames,
|
|
309
|
+
const generics = typeParameters(source, member, classTypeNames, typeContext, usedTypeNames)
|
|
229
310
|
const parameters = (member.params ?? [])
|
|
230
|
-
.map((item, index) => parameter(source, item, index, generics.names,
|
|
231
|
-
if (member.kind === 'constructor')
|
|
311
|
+
.map((item, index) => parameter(source, item, index, generics.names, typeContext, usedTypeNames)).join(', ')
|
|
312
|
+
if (member.kind === 'constructor') {
|
|
313
|
+
constructorParameters = parameters
|
|
314
|
+
}
|
|
315
|
+
else if (member.kind === 'get' || member.kind === 'set') {
|
|
316
|
+
const signature = `${member.kind}:${name}`
|
|
317
|
+
if (memberNames.has(signature)) continue
|
|
318
|
+
members.push(member.kind === 'get'
|
|
319
|
+
? `get ${name}(): ${returnType(source, member, generics.names, typeContext, usedTypeNames)}`
|
|
320
|
+
: `set ${name}(${parameters})`)
|
|
321
|
+
memberNames.add(signature)
|
|
322
|
+
}
|
|
232
323
|
else if (member.kind === 'method') {
|
|
233
|
-
members.push(`${name}${generics.text}(${parameters}): ${returnType(source, member, generics.names,
|
|
324
|
+
members.push(`${name}${member.optional === true ? '?' : ''}${generics.text}(${parameters}): ${returnType(source, member, generics.names, typeContext, usedTypeNames)}`)
|
|
325
|
+
memberNames.add(name)
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return { constructorParameters, members, instance: `{ ${members.join('; ')} }` }
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
function classMembers(source, node, classTypeNames, typeContext, usedTypeNames) {
|
|
332
|
+
if (!typeContext.modern) return legacyClassMembers(source, node, classTypeNames, typeContext, usedTypeNames)
|
|
333
|
+
const body = node.body?.body ?? []
|
|
334
|
+
const fields = new Map()
|
|
335
|
+
const parameterProperties = new Map()
|
|
336
|
+
const prototypeMembers = new Map()
|
|
337
|
+
let constructorNode
|
|
338
|
+
for (const member of body) {
|
|
339
|
+
if (['ClassProperty', 'TSAbstractPropertyDefinition'].includes(member.type)) {
|
|
340
|
+
if (!isPublicClassMember(member)) continue
|
|
341
|
+
const key = classMemberKey(member)
|
|
342
|
+
if (key !== undefined) fields.set(key, member)
|
|
343
|
+
continue
|
|
344
|
+
}
|
|
345
|
+
if (member.type === 'ClassAccessorProperty') {
|
|
346
|
+
if (!isPublicClassMember(member)) continue
|
|
347
|
+
const key = classMemberKey(member)
|
|
348
|
+
if (key !== undefined) prototypeMembers.set(key, { kind: 'accessor', get: member, set: member })
|
|
349
|
+
continue
|
|
350
|
+
}
|
|
351
|
+
if (!['ClassMethod', 'TSDeclareMethod'].includes(member.type) || !isPublicClassMember(member)) continue
|
|
352
|
+
const key = classMemberKey(member)
|
|
353
|
+
if (key === undefined) continue
|
|
354
|
+
if (member.kind === 'constructor') {
|
|
355
|
+
constructorNode = member
|
|
356
|
+
} else if (member.kind === 'get' || member.kind === 'set') {
|
|
357
|
+
const current = prototypeMembers.get(key)
|
|
358
|
+
const descriptor = current?.kind === 'accessor' ? { ...current } : { kind: 'accessor' }
|
|
359
|
+
descriptor[member.kind] = member
|
|
360
|
+
prototypeMembers.set(key, descriptor)
|
|
361
|
+
} else if (member.kind === 'method') {
|
|
362
|
+
prototypeMembers.set(key, { kind: 'method', node: member })
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
for (const parameter of constructorNode?.params ?? []) {
|
|
366
|
+
const name = parameterPropertyName(parameter)
|
|
367
|
+
if (name !== undefined) parameterProperties.set(name, parameter)
|
|
368
|
+
}
|
|
369
|
+
const ownMember = name => parameterProperties.get(name) ?? fields.get(name)
|
|
370
|
+
const members = []
|
|
371
|
+
let constructorParameters = '...args: unknown[]'
|
|
372
|
+
for (const member of body) {
|
|
373
|
+
if (['ClassProperty', 'TSAbstractPropertyDefinition'].includes(member.type)) {
|
|
374
|
+
if (!isPublicClassMember(member)) continue
|
|
375
|
+
const key = classMemberKey(member)
|
|
376
|
+
if (key === undefined || ownMember(key) !== member) continue
|
|
377
|
+
const name = modernClassMemberName(member)
|
|
378
|
+
members.push(`${member.readonly === true ? 'readonly ' : ''}${name}${member.optional === true ? '?' : ''}: ${annotation(source, member, classTypeNames, typeContext, usedTypeNames)}`)
|
|
379
|
+
continue
|
|
380
|
+
}
|
|
381
|
+
if (member.type === 'ClassAccessorProperty') {
|
|
382
|
+
if (!isPublicClassMember(member)) continue
|
|
383
|
+
const key = classMemberKey(member)
|
|
384
|
+
const name = modernClassMemberName(member)
|
|
385
|
+
const selected = key === undefined || ownMember(key) !== undefined ? undefined : prototypeMembers.get(key)
|
|
386
|
+
if (selected?.kind !== 'accessor') continue
|
|
387
|
+
if (selected.get === member && selected.set === member) {
|
|
388
|
+
members.push(`${name}${member.optional === true ? '?' : ''}: ${annotation(source, member, classTypeNames, typeContext, usedTypeNames)}`)
|
|
389
|
+
} else {
|
|
390
|
+
const type = annotation(source, member, classTypeNames, typeContext, usedTypeNames)
|
|
391
|
+
if (selected.get === member) members.push(`get ${name}(): ${type}`)
|
|
392
|
+
if (selected.set === member) members.push(`set ${name}(value: ${type})`)
|
|
393
|
+
}
|
|
394
|
+
continue
|
|
395
|
+
}
|
|
396
|
+
if (!['ClassMethod', 'TSDeclareMethod'].includes(member.type) || !isPublicClassMember(member)) continue
|
|
397
|
+
const key = classMemberKey(member)
|
|
398
|
+
if (key === undefined) continue
|
|
399
|
+
const name = modernClassMemberName(member)
|
|
400
|
+
if (member.kind === 'constructor') {
|
|
401
|
+
if (member !== constructorNode) continue
|
|
402
|
+
const generics = typeParameters(source, member, classTypeNames, typeContext, usedTypeNames)
|
|
403
|
+
const parameters = (member.params ?? [])
|
|
404
|
+
.map((item, index) => parameter(source, item, index, generics.names, typeContext, usedTypeNames)).join(', ')
|
|
405
|
+
constructorParameters = parameters
|
|
406
|
+
for (const item of member.params ?? []) {
|
|
407
|
+
const fieldName = parameterPropertyName(item)
|
|
408
|
+
if (fieldName === undefined || ownMember(fieldName) !== item) continue
|
|
409
|
+
members.push(parameterPropertyMember(source, item, classTypeNames, typeContext, usedTypeNames))
|
|
410
|
+
}
|
|
411
|
+
continue
|
|
412
|
+
}
|
|
413
|
+
if (ownMember(key) !== undefined) continue
|
|
414
|
+
const selected = prototypeMembers.get(key)
|
|
415
|
+
if (member.kind === 'get' || member.kind === 'set') {
|
|
416
|
+
if (selected?.kind !== 'accessor' || selected[member.kind] !== member) continue
|
|
417
|
+
const generics = typeParameters(source, member, classTypeNames, typeContext, usedTypeNames)
|
|
418
|
+
const parameters = (member.params ?? [])
|
|
419
|
+
.map((item, index) => parameter(source, item, index, generics.names, typeContext, usedTypeNames)).join(', ')
|
|
420
|
+
members.push(member.kind === 'get'
|
|
421
|
+
? `get ${name}(): ${returnType(source, member, generics.names, typeContext, usedTypeNames)}`
|
|
422
|
+
: `set ${name}(${parameters})`)
|
|
423
|
+
} else if (member.kind === 'method' && selected?.kind === 'method' && selected.node === member) {
|
|
424
|
+
const generics = typeParameters(source, member, classTypeNames, typeContext, usedTypeNames)
|
|
425
|
+
const parameters = (member.params ?? [])
|
|
426
|
+
.map((item, index) => parameter(source, item, index, generics.names, typeContext, usedTypeNames)).join(', ')
|
|
427
|
+
members.push(`${name}${member.optional === true ? '?' : ''}${generics.text}(${parameters}): ${returnType(source, member, generics.names, typeContext, usedTypeNames)}`)
|
|
234
428
|
}
|
|
235
429
|
}
|
|
236
430
|
return { constructorParameters, members, instance: `{ ${members.join('; ')} }` }
|
|
237
431
|
}
|
|
238
432
|
|
|
433
|
+
function valueReferenceRootNode(node) {
|
|
434
|
+
let current = node
|
|
435
|
+
while (current?.type === 'MemberExpression' && !current.computed) current = current.object
|
|
436
|
+
return current?.type === 'Identifier' ? current : undefined
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
function classHeritage(source, node, classTypeNames, typeContext, usedTypeNames) {
|
|
440
|
+
const base = node.superClass
|
|
441
|
+
if (base === null || base === undefined) return { clause: '', instance: '' }
|
|
442
|
+
const root = valueReferenceRootNode(base)
|
|
443
|
+
if (root === undefined || !['Identifier', 'MemberExpression'].includes(base.type)) {
|
|
444
|
+
throw new TypeError('class heritage cannot be represented in the binding interface; use a named class base')
|
|
445
|
+
}
|
|
446
|
+
if (typeContext.importedNames.has(root.name)) {
|
|
447
|
+
throw new TypeError(`imported class ${JSON.stringify(root.name)} cannot be represented in the binding interface; use an explicit structural type`)
|
|
448
|
+
}
|
|
449
|
+
let reference = sourceSlice(source, base)
|
|
450
|
+
if (base.type === 'Identifier' && typeContext.localDeclarations.has(root.name)) {
|
|
451
|
+
const declaration = typeContext.localDeclarations.get(root.name)
|
|
452
|
+
if (declaration.type !== 'ClassDeclaration') {
|
|
453
|
+
throw new TypeError(`local class base ${JSON.stringify(root.name)} cannot be represented in the binding interface; use a class declaration`)
|
|
454
|
+
}
|
|
455
|
+
usedTypeNames.add(root.name)
|
|
456
|
+
reference = `${typeContext.typeNamespaceToken}.${root.name}`
|
|
457
|
+
} else if (typeContext.localValues.has(root.name)) {
|
|
458
|
+
throw new TypeError(`local class base ${JSON.stringify(root.name)} cannot be represented in the binding interface; use a class declaration`)
|
|
459
|
+
}
|
|
460
|
+
const argumentsNode = node.superTypeParameters ?? node.superTypeArguments
|
|
461
|
+
const typeArguments = argumentsNode === undefined ? ''
|
|
462
|
+
: projectedType(source, argumentsNode, classTypeNames, typeContext, usedTypeNames)
|
|
463
|
+
const instance = `${reference}${typeArguments}`
|
|
464
|
+
return { clause: ` extends ${instance}`, instance }
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
function localTypeDeclaration(source, name, node, typeContext, usedTypeNames) {
|
|
468
|
+
if (node.type === 'TSInterfaceDeclaration' || node.type === 'TSTypeAliasDeclaration'
|
|
469
|
+
|| node.type === 'TSEnumDeclaration') {
|
|
470
|
+
const ownTypeNames = new Set(typeParameterNames(node.typeParameters))
|
|
471
|
+
const text = projectedType(source, node, ownTypeNames, typeContext, usedTypeNames)
|
|
472
|
+
.replace(/^declare\s+/, '')
|
|
473
|
+
return `export ${text}`
|
|
474
|
+
}
|
|
475
|
+
if (node.type === 'ClassDeclaration') {
|
|
476
|
+
const generics = typeParameters(source, node, new Set(), typeContext, usedTypeNames)
|
|
477
|
+
const heritage = classHeritage(source, node, generics.names, typeContext, usedTypeNames)
|
|
478
|
+
const shape = classMembers(source, node, generics.names, typeContext, usedTypeNames)
|
|
479
|
+
return `export ${node.abstract === true ? 'abstract ' : ''}class ${name}${generics.text}${heritage.clause} { constructor(${shape.constructorParameters});${shape.members.length === 0 ? '' : ` ${shape.members.join('; ')};`} }`
|
|
480
|
+
}
|
|
481
|
+
throw new TypeError(`local type ${JSON.stringify(name)} cannot be represented in the binding interface; use a local interface, type alias, enum, or class`)
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
function typeDependencyDeclarations(source, roots, typeContext) {
|
|
485
|
+
if (!typeContext.modern) return []
|
|
486
|
+
const pending = [...roots]
|
|
487
|
+
const seen = new Set()
|
|
488
|
+
const declarations = []
|
|
489
|
+
while (pending.length > 0) {
|
|
490
|
+
const name = pending.shift()
|
|
491
|
+
if (seen.has(name)) continue
|
|
492
|
+
seen.add(name)
|
|
493
|
+
const node = typeContext.localDeclarations.get(name)
|
|
494
|
+
if (node === undefined) continue
|
|
495
|
+
const dependencies = new Set()
|
|
496
|
+
declarations.push(localTypeDeclaration(source, name, node, typeContext, dependencies))
|
|
497
|
+
for (const dependency of dependencies) if (!seen.has(dependency)) pending.push(dependency)
|
|
498
|
+
}
|
|
499
|
+
return declarations
|
|
500
|
+
}
|
|
501
|
+
|
|
239
502
|
function jsdocPurpose(...nodes) {
|
|
240
503
|
const comment = nodes.flatMap(node => node?.leadingComments ?? [])
|
|
241
504
|
.find(item => item.type === 'CommentBlock' && item.value.startsWith('*'))
|
|
@@ -245,51 +508,62 @@ function jsdocPurpose(...nodes) {
|
|
|
245
508
|
.find(line => line !== '' && !line.startsWith('@')) ?? ''
|
|
246
509
|
}
|
|
247
510
|
|
|
248
|
-
function symbolDescriptor(source, name, node, exportNode
|
|
511
|
+
function symbolDescriptor(source, name, node, exportNode, typeContext) {
|
|
512
|
+
const usedTypeNames = new Set()
|
|
513
|
+
const complete = descriptor => ({
|
|
514
|
+
...descriptor,
|
|
515
|
+
typeNamespaceToken: typeContext.typeNamespaceToken,
|
|
516
|
+
typeDeclarations: typeDependencyDeclarations(source, usedTypeNames, typeContext),
|
|
517
|
+
})
|
|
249
518
|
if (node?.type === 'FunctionDeclaration') {
|
|
250
|
-
const generics = typeParameters(source, node, new Set(),
|
|
519
|
+
const generics = typeParameters(source, node, new Set(), typeContext, usedTypeNames)
|
|
251
520
|
const parameters = (node.params ?? [])
|
|
252
|
-
.map((item, index) => parameter(source, item, index, generics.names,
|
|
253
|
-
return {
|
|
521
|
+
.map((item, index) => parameter(source, item, index, generics.names, typeContext, usedTypeNames)).join(', ')
|
|
522
|
+
return complete({
|
|
254
523
|
name,
|
|
255
524
|
kind: 'function',
|
|
256
525
|
purpose: jsdocPurpose(exportNode, node),
|
|
257
|
-
declaration: `function ${name}${generics.text}(${parameters}): ${returnType(source, node, generics.names,
|
|
258
|
-
member: `${name}${generics.text}(${parameters}): ${returnType(source, node, generics.names,
|
|
259
|
-
}
|
|
526
|
+
declaration: `function ${name}${generics.text}(${parameters}): ${returnType(source, node, generics.names, typeContext, usedTypeNames)}`,
|
|
527
|
+
member: `${name}${generics.text}(${parameters}): ${returnType(source, node, generics.names, typeContext, usedTypeNames)}`,
|
|
528
|
+
})
|
|
260
529
|
}
|
|
261
530
|
if (node?.type === 'ClassDeclaration') {
|
|
262
|
-
const generics = typeParameters(source, node, new Set(),
|
|
263
|
-
const
|
|
264
|
-
|
|
531
|
+
const generics = typeParameters(source, node, new Set(), typeContext, usedTypeNames)
|
|
532
|
+
const heritage = classHeritage(source, node, generics.names, typeContext, usedTypeNames)
|
|
533
|
+
const shape = classMembers(source, node, generics.names, typeContext, usedTypeNames)
|
|
534
|
+
const instance = heritage.instance === '' ? shape.instance : `${heritage.instance} & ${shape.instance}`
|
|
535
|
+
return complete({
|
|
265
536
|
name,
|
|
266
537
|
kind: 'class',
|
|
267
538
|
purpose: jsdocPurpose(exportNode, node),
|
|
268
|
-
declaration:
|
|
269
|
-
member:
|
|
270
|
-
|
|
539
|
+
declaration: `${node.abstract === true ? 'abstract ' : ''}class ${name}${generics.text}${heritage.clause} { constructor(${shape.constructorParameters});${shape.members.length === 0 ? '' : ` ${shape.members.join('; ')};`} }`,
|
|
540
|
+
member: node.abstract === true
|
|
541
|
+
? `${name}: abstract new${generics.text}(${shape.constructorParameters}) => ${instance}`
|
|
542
|
+
: `${name}: { new${generics.text}(${shape.constructorParameters}): ${instance} }`,
|
|
543
|
+
})
|
|
271
544
|
}
|
|
272
545
|
const declarator = node?.type === 'VariableDeclarator' ? node : undefined
|
|
273
546
|
const type = declarator?.id?.type !== 'Identifier'
|
|
274
547
|
? 'unknown'
|
|
275
548
|
: declarator.id.typeAnnotation !== undefined
|
|
276
|
-
? annotation(source, declarator.id, new Set(),
|
|
277
|
-
: inferredType(source, declarator.init, 0,
|
|
278
|
-
return {
|
|
549
|
+
? annotation(source, declarator.id, new Set(), typeContext, usedTypeNames)
|
|
550
|
+
: inferredType(source, declarator.init, 0, typeContext, usedTypeNames)
|
|
551
|
+
return complete({
|
|
279
552
|
name,
|
|
280
553
|
kind: 'variable',
|
|
281
554
|
purpose: jsdocPurpose(exportNode, node),
|
|
282
555
|
declaration: `const ${name}: ${type}`,
|
|
283
556
|
member: `${name}: ${type}`,
|
|
284
|
-
}
|
|
557
|
+
})
|
|
285
558
|
}
|
|
286
559
|
|
|
287
560
|
export const exportedSymbols = createCompilerSourceCache(analyzeExportedSymbols)
|
|
288
561
|
|
|
289
562
|
function analyzeExportedSymbols(source, transform) {
|
|
290
|
-
|
|
563
|
+
const metadataSource = source
|
|
564
|
+
let metadataAst
|
|
291
565
|
try {
|
|
292
|
-
|
|
566
|
+
metadataAst = parse(metadataSource, {
|
|
293
567
|
sourceType: 'module',
|
|
294
568
|
plugins: transform === LEGACY_USER_BINDING_TRANSFORM
|
|
295
569
|
? ['typescript', 'topLevelAwait', 'importAttributes'] : CELL_PARSER_PLUGINS,
|
|
@@ -298,20 +572,58 @@ function analyzeExportedSymbols(source, transform) {
|
|
|
298
572
|
} catch (error) {
|
|
299
573
|
throw new SyntaxError(`binding source could not be parsed: ${error.message}`)
|
|
300
574
|
}
|
|
301
|
-
const
|
|
302
|
-
|
|
575
|
+
const importedNames = new Set()
|
|
576
|
+
const localDeclarations = new Map()
|
|
577
|
+
const localValueNames = new Set()
|
|
578
|
+
const metadataLocals = new Map()
|
|
579
|
+
const metadataExportNodes = new Map()
|
|
580
|
+
for (const statement of metadataAst.program.body) {
|
|
303
581
|
const declaration = statement.type === 'ExportNamedDeclaration' ? statement.declaration : statement
|
|
304
582
|
if (statement.type === 'ImportDeclaration') {
|
|
305
|
-
for (const specifier of statement.specifiers)
|
|
583
|
+
for (const specifier of statement.specifiers) importedNames.add(specifier.local.name)
|
|
306
584
|
}
|
|
307
585
|
if (declaration?.type === 'TSTypeAliasDeclaration'
|
|
308
586
|
|| declaration?.type === 'TSInterfaceDeclaration'
|
|
309
587
|
|| declaration?.type === 'TSEnumDeclaration'
|
|
310
588
|
|| declaration?.type === 'TSModuleDeclaration'
|
|
311
589
|
|| declaration?.type === 'ClassDeclaration') {
|
|
312
|
-
if (declaration.id?.type === 'Identifier')
|
|
590
|
+
if (declaration.id?.type === 'Identifier') localDeclarations.set(declaration.id.name, declaration)
|
|
591
|
+
}
|
|
592
|
+
if (declaration?.type === 'TSEnumDeclaration' || declaration?.type === 'TSModuleDeclaration') {
|
|
593
|
+
if (declaration.id?.type === 'Identifier') localValueNames.add(declaration.id.name)
|
|
594
|
+
}
|
|
595
|
+
if (declaration?.type === 'FunctionDeclaration' || declaration?.type === 'ClassDeclaration') {
|
|
596
|
+
if (declaration.id !== null) {
|
|
597
|
+
localValueNames.add(declaration.id.name)
|
|
598
|
+
metadataLocals.set(declaration.id.name, declaration)
|
|
599
|
+
if (statement.type === 'ExportNamedDeclaration') metadataExportNodes.set(declaration.id.name, statement)
|
|
600
|
+
}
|
|
601
|
+
} else if (declaration?.type === 'VariableDeclaration') {
|
|
602
|
+
for (const item of declaration.declarations) {
|
|
603
|
+
for (const name of bindingNames(item.id)) {
|
|
604
|
+
localValueNames.add(name)
|
|
605
|
+
metadataLocals.set(name, item)
|
|
606
|
+
if (statement.type === 'ExportNamedDeclaration') metadataExportNodes.set(name, statement)
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
if (statement.type === 'ExportNamedDeclaration') {
|
|
611
|
+
for (const specifier of statement.specifiers) {
|
|
612
|
+
if (specifier.type === 'ExportSpecifier' && specifier.local.type === 'Identifier') {
|
|
613
|
+
metadataExportNodes.set(specifier.local.name, statement)
|
|
614
|
+
}
|
|
615
|
+
}
|
|
313
616
|
}
|
|
314
617
|
}
|
|
618
|
+
const typeContext = {
|
|
619
|
+
modern: transform === USER_BINDING_TRANSFORM,
|
|
620
|
+
importedNames,
|
|
621
|
+
localDeclarations,
|
|
622
|
+
localValues: localValueNames,
|
|
623
|
+
sourceTypeNames: new Set([...importedNames, ...localDeclarations.keys()]),
|
|
624
|
+
typeNamespaceToken: bindingTypeNamespaceToken(metadataSource),
|
|
625
|
+
}
|
|
626
|
+
let ast = metadataAst
|
|
315
627
|
if (transform !== LEGACY_USER_BINDING_TRANSFORM) {
|
|
316
628
|
source = normalizeTypeScriptValues(source, identitySourceMap(source.length), 'module').code
|
|
317
629
|
ast = parse(source, { sourceType: 'module', plugins: CELL_PARSER_PLUGINS, errorRecovery: true })
|
|
@@ -328,6 +640,13 @@ function analyzeExportedSymbols(source, transform) {
|
|
|
328
640
|
}
|
|
329
641
|
}
|
|
330
642
|
const exports = new Map()
|
|
643
|
+
const descriptor = (name, runtimeNode, exportNode, localName = name) => {
|
|
644
|
+
const metadataNode = metadataLocals.get(localName)
|
|
645
|
+
return metadataNode === undefined
|
|
646
|
+
? symbolDescriptor(source, name, runtimeNode, exportNode, typeContext)
|
|
647
|
+
: symbolDescriptor(metadataSource, name, metadataNode,
|
|
648
|
+
metadataExportNodes.get(localName) ?? metadataNode, typeContext)
|
|
649
|
+
}
|
|
331
650
|
for (const statement of ast.program.body) {
|
|
332
651
|
if (statement.type === 'ExportDefaultDeclaration' || statement.type === 'ExportAllDeclaration') {
|
|
333
652
|
throw new TypeError('binding source supports named exports only')
|
|
@@ -339,15 +658,13 @@ function analyzeExportedSymbols(source, transform) {
|
|
|
339
658
|
const declaration = statement.declaration
|
|
340
659
|
if (declaration?.type === 'FunctionDeclaration' || declaration?.type === 'ClassDeclaration') {
|
|
341
660
|
if (declaration.id === null) throw new TypeError('binding source exports must be named')
|
|
342
|
-
exports.set(declaration.id.name,
|
|
343
|
-
source, declaration.id.name, declaration, statement, sourceTypeNames,
|
|
344
|
-
))
|
|
661
|
+
exports.set(declaration.id.name, descriptor(declaration.id.name, declaration, statement))
|
|
345
662
|
continue
|
|
346
663
|
}
|
|
347
664
|
if (declaration?.type === 'VariableDeclaration') {
|
|
348
665
|
for (const item of declaration.declarations) {
|
|
349
666
|
for (const name of bindingNames(item.id)) {
|
|
350
|
-
exports.set(name,
|
|
667
|
+
exports.set(name, descriptor(name, item, statement))
|
|
351
668
|
}
|
|
352
669
|
}
|
|
353
670
|
continue
|
|
@@ -359,7 +676,7 @@ function analyzeExportedSymbols(source, transform) {
|
|
|
359
676
|
identifier(exported, 'exported binding name')
|
|
360
677
|
const target = locals.get(local)
|
|
361
678
|
if (target === undefined) throw new TypeError(`export ${JSON.stringify(exported)} has no local value declaration`)
|
|
362
|
-
exports.set(exported,
|
|
679
|
+
exports.set(exported, descriptor(exported, target, target, local))
|
|
363
680
|
}
|
|
364
681
|
}
|
|
365
682
|
if (exports.size === 0) throw new TypeError('binding source must contain at least one named value export')
|