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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { LIVE_MODULE_SEMANTICS } from './repl-rewrite-contract.js'
|
|
2
2
|
import { LEGACY_LANGUAGE_SEMANTICS, STATEFUL_LANGUAGE_SEMANTICS,
|
|
3
3
|
PROTECTED_LANGUAGE_SEMANTICS, normalizeLanguageSemantics } from './language-semantics.js'
|
|
4
|
+
import { moduleTransformForLanguage, normalizeModuleTransform } from './module-transform-contract.js'
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Translate the public compatibility settings into the execution policy used
|
|
@@ -15,8 +16,10 @@ export function executionPolicies(config, replayRecord = undefined) {
|
|
|
15
16
|
const bindingPolicy = Object.freeze({ ...replayRecord.bindingPolicy })
|
|
16
17
|
const rewritesEnabled = Object.freeze({ ...replayRecord.rewritePolicy })
|
|
17
18
|
const moduleSemantics = Object.freeze({ ...replayRecord.moduleSemantics })
|
|
19
|
+
const languageSemantics = normalizeLanguageSemantics(replayRecord.languageSemantics ?? LEGACY_LANGUAGE_SEMANTICS)
|
|
18
20
|
return Object.freeze({
|
|
19
|
-
languageSemantics
|
|
21
|
+
languageSemantics,
|
|
22
|
+
moduleTransform: normalizeModuleTransform(replayRecord.moduleTransform, languageSemantics),
|
|
20
23
|
bindingPolicy,
|
|
21
24
|
rewritesEnabled,
|
|
22
25
|
moduleSemantics,
|
|
@@ -25,6 +28,7 @@ export function executionPolicies(config, replayRecord = undefined) {
|
|
|
25
28
|
if (config.bindingUpdates === 'stateful' && config.legacyBindingSettings !== true) {
|
|
26
29
|
return Object.freeze({
|
|
27
30
|
languageSemantics: STATEFUL_LANGUAGE_SEMANTICS,
|
|
31
|
+
moduleTransform: moduleTransformForLanguage(STATEFUL_LANGUAGE_SEMANTICS),
|
|
28
32
|
bindingPolicy: Object.freeze({ variableRedeclarations: true, functionClassRedeclarations: true }),
|
|
29
33
|
rewritesEnabled: Object.freeze({ autoRewriteImports: true, autoStripExports: true, autoSplitRedeclarations: true }),
|
|
30
34
|
moduleSemantics: LIVE_MODULE_SEMANTICS,
|
|
@@ -33,6 +37,7 @@ export function executionPolicies(config, replayRecord = undefined) {
|
|
|
33
37
|
if (config.bindingUpdates === 'protected' && config.legacyBindingSettings !== true) {
|
|
34
38
|
return Object.freeze({
|
|
35
39
|
languageSemantics: PROTECTED_LANGUAGE_SEMANTICS,
|
|
40
|
+
moduleTransform: moduleTransformForLanguage(PROTECTED_LANGUAGE_SEMANTICS),
|
|
36
41
|
bindingPolicy: Object.freeze({ variableRedeclarations: false, functionClassRedeclarations: false }),
|
|
37
42
|
// Module syntax is part of the language in protected mode too. The
|
|
38
43
|
// policy protects existing names; it does not remove valid syntax.
|
|
@@ -42,6 +47,7 @@ export function executionPolicies(config, replayRecord = undefined) {
|
|
|
42
47
|
}
|
|
43
48
|
return Object.freeze({
|
|
44
49
|
languageSemantics: LEGACY_LANGUAGE_SEMANTICS,
|
|
50
|
+
moduleTransform: moduleTransformForLanguage(LEGACY_LANGUAGE_SEMANTICS),
|
|
45
51
|
bindingPolicy: Object.freeze({
|
|
46
52
|
variableRedeclarations: config.looseTopLevelRedeclarations === true,
|
|
47
53
|
functionClassRedeclarations: config.looseTopLevelFunctionClassRedeclarations === true,
|
|
@@ -43,6 +43,16 @@ function callableSourceStart(source, node) {
|
|
|
43
43
|
return start + tokens.getToken().start
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
function removeCallableSourceMarks(source, prefix, suffix, sources, options) {
|
|
47
|
+
const tree = parse(prefix + source + suffix, options)
|
|
48
|
+
const markers = new Set(sources.entries.map(entry => entry.marker))
|
|
49
|
+
const offset = prefix.length
|
|
50
|
+
const edits = tree.comments.filter(comment => markers.has(comment.value)
|
|
51
|
+
&& comment.start >= offset && comment.end <= offset + source.length)
|
|
52
|
+
.map(comment => ({ start: comment.start - offset, end: comment.end - offset, text: '' }))
|
|
53
|
+
return edits.length === 0 ? source : applySourceEdits(source, identitySourceMap(source.length), edits).code
|
|
54
|
+
}
|
|
55
|
+
|
|
46
56
|
export function callableMarkerPosition(node, source, comments) {
|
|
47
57
|
if (node.type !== 'ArrowFunctionExpression') return node.body.start + 1
|
|
48
58
|
let start = source.lastIndexOf('=>', node.body.start - 1)
|
|
@@ -129,6 +139,7 @@ export function markCallableSources(source, sourceMap = identitySourceMap(source
|
|
|
129
139
|
const nativeFunctions = typedRecords.map(record => markedNodes.get(record.marker))
|
|
130
140
|
.filter(node => t.isFunction(node) && !isMethod(node)).sort((left, right) => left.start - right.start)
|
|
131
141
|
const nativeRecipes = new Map()
|
|
142
|
+
const aliasMarkers = []
|
|
132
143
|
const nativeFunctionIndex = start => {
|
|
133
144
|
let low = 0, high = nativeFunctions.length
|
|
134
145
|
while (low < high) {
|
|
@@ -175,7 +186,17 @@ export function markCallableSources(source, sourceMap = identitySourceMap(source
|
|
|
175
186
|
original = lowered.source
|
|
176
187
|
const entries = [...originals].map(([key, text]) => [key, key === marker ? original : text])
|
|
177
188
|
for (const [node, fact] of markedCallableOwners(lowered.emitted, entries)) {
|
|
178
|
-
|
|
189
|
+
const generated = lowered.emittedSource.slice(node.start, node.end)
|
|
190
|
+
aliasMarkers.push([generated, fact.marker])
|
|
191
|
+
const generatedMethod = isMethod(node)
|
|
192
|
+
const markerFree = removeCallableSourceMarks(
|
|
193
|
+
generated,
|
|
194
|
+
generatedMethod ? 'class Source {' : '(',
|
|
195
|
+
generatedMethod ? '}' : ')',
|
|
196
|
+
sources,
|
|
197
|
+
options,
|
|
198
|
+
)
|
|
199
|
+
if (markerFree !== generated) aliasMarkers.push([markerFree, fact.marker])
|
|
179
200
|
}
|
|
180
201
|
}
|
|
181
202
|
// Prefer source-preserving erasure. Runtime TypeScript constructs such as
|
|
@@ -202,6 +223,7 @@ export function markCallableSources(source, sourceMap = identitySourceMap(source
|
|
|
202
223
|
} catch {
|
|
203
224
|
lowerCallable()
|
|
204
225
|
}
|
|
226
|
+
original = removeCallableSourceMarks(original, prefix, suffix, sources, options)
|
|
205
227
|
entry.buffer = sources.buffers.length
|
|
206
228
|
sources.buffers.push(original)
|
|
207
229
|
entry.start = 0
|
|
@@ -209,6 +231,8 @@ export function markCallableSources(source, sourceMap = identitySourceMap(source
|
|
|
209
231
|
originals.set(marker, original)
|
|
210
232
|
if (!method && t.isFunction(node)) nativeRecipes.set(node, { node, start, end: node.end, text: original })
|
|
211
233
|
}
|
|
234
|
+
const finalFacts = factMap(sources)
|
|
235
|
+
for (const [generated, marker] of aliasMarkers) sources.aliases.push([generated, originalText(finalFacts.get(marker))])
|
|
212
236
|
return { ...marked, callableSources: sources, nativeJavaScript }
|
|
213
237
|
}
|
|
214
238
|
|
|
@@ -273,6 +297,18 @@ export function collectCallableSources(code, sources, parserOptions = {}, transf
|
|
|
273
297
|
}).concat(sources.aliases ?? [])
|
|
274
298
|
}
|
|
275
299
|
|
|
300
|
+
/** Restore only callable marks whose transformed starts have exact source-map ownership. */
|
|
301
|
+
export function restoreMappedCallableSourceMarks(mapped, input, transformation, sources, parserOptions = {}) {
|
|
302
|
+
if (sources === undefined || sources.length === 0) return mapped
|
|
303
|
+
const { tree, owners } = callableSourceOwners(mapped.code, sources, parserOptions,
|
|
304
|
+
{ code: input, map: transformation.map })
|
|
305
|
+
const edits = [...owners].map(([node, fact]) => {
|
|
306
|
+
const start = callableMarkerPosition(node, mapped.code, tree.comments)
|
|
307
|
+
return { start, end: start, text: `/*${fact.marker}*/` }
|
|
308
|
+
})
|
|
309
|
+
return edits.length === 0 ? mapped : applySourceEdits(mapped.code, mapped.sourceMap, edits)
|
|
310
|
+
}
|
|
311
|
+
|
|
276
312
|
/** Emission ranges come from typed nodes and exact generator mappings. */
|
|
277
313
|
export function regionCallableRanges(input, generated, sourceRanges, parserOptions) {
|
|
278
314
|
if (!sourceRanges?.length) return []
|
|
@@ -17,10 +17,10 @@ import {
|
|
|
17
17
|
renderDurabilityReason,
|
|
18
18
|
renderDurabilityReasons,
|
|
19
19
|
} from './module-policy.js'
|
|
20
|
-
import { applySourceEdits, mapSourcePosition, mapSourceSpan } from './source-position-map.js'
|
|
20
|
+
import { applySourceEdits, mapSourcePosition, mapSourceSpan, sourceRangeHasOriginalText } from './source-position-map.js'
|
|
21
21
|
import { SKIP_AST_CHILDREN, walkAst } from './ast-traversal.js'
|
|
22
22
|
import { compileStatefulRoot } from './stateful-root-compiler.js'
|
|
23
|
-
import { CELL_PARSER_PLUGINS, bindCompilerIntrinsics, lowerStatefulDecorators, lowerStatefulResources, lowerNativeLanguageSource, normalizeStatefulScopes } from './repl-scope-normalizer.js'
|
|
23
|
+
import { CELL_PARSER_PLUGINS, bindCompilerIntrinsics, lowerStatefulDecorators, lowerStatefulResources, lowerNativeLanguageSource, normalizationFailureInput, normalizeStatefulScopes } from './repl-scope-normalizer.js'
|
|
24
24
|
import { markCallableSources, collectCallableSources } from './callable-source-facts.js'
|
|
25
25
|
import { LegacyPreflightError, prepareLegacyProgram } from './legacy-cell-analysis.js'
|
|
26
26
|
import { adaptLegacyModuleImports } from './managed-module-operations.js'
|
|
@@ -220,6 +220,49 @@ function isFunction(node) {
|
|
|
220
220
|
|| node.type === 'ArrowFunctionExpression'
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
+
function lowerCellImportMeta(result, importMeta, originalSource) {
|
|
224
|
+
if (!result.code.includes('import')) return result
|
|
225
|
+
const tree = parseSource(result.code, {
|
|
226
|
+
sourceType: 'unambiguous',
|
|
227
|
+
errorRecovery: true,
|
|
228
|
+
allowAwaitOutsideFunction: true,
|
|
229
|
+
allowImportExportEverywhere: true,
|
|
230
|
+
allowReturnOutsideFunction: true,
|
|
231
|
+
allowUndeclaredExports: true,
|
|
232
|
+
plugins: CELL_PARSER_PLUGINS,
|
|
233
|
+
}).program
|
|
234
|
+
const references = []
|
|
235
|
+
walkAst(tree, (node) => {
|
|
236
|
+
if (node.type === 'MetaProperty' && node.meta?.name === 'import' && node.property?.name === 'meta') {
|
|
237
|
+
references.push(node)
|
|
238
|
+
}
|
|
239
|
+
})
|
|
240
|
+
if (references.length === 0) return result
|
|
241
|
+
if (importMeta === null || typeof importMeta !== 'object'
|
|
242
|
+
|| typeof importMeta.url !== 'string' || typeof importMeta.filename !== 'string'
|
|
243
|
+
|| typeof importMeta.dirname !== 'string') {
|
|
244
|
+
const node = references[0]
|
|
245
|
+
throw new ModuleRewriteError('import.meta requires the session module base', mapSourcePosition({
|
|
246
|
+
line: node.loc.start.line,
|
|
247
|
+
column: node.loc.start.column + 1,
|
|
248
|
+
}, result.code, originalSource, result.sourceMap))
|
|
249
|
+
}
|
|
250
|
+
const binding = createGeneratedNameAllocator(tree)('import_meta')
|
|
251
|
+
const directiveEnd = tree.directives.at(-1)?.end ?? tree.interpreter?.end ?? 0
|
|
252
|
+
const declaration = `\nconst ${binding}={__proto__:null,url:${JSON.stringify(importMeta.url)},filename:${JSON.stringify(importMeta.filename)},dirname:${JSON.stringify(importMeta.dirname)}};\n`
|
|
253
|
+
const edits = [
|
|
254
|
+
{ start: directiveEnd, end: directiveEnd, text: declaration },
|
|
255
|
+
...references.map(node => ({
|
|
256
|
+
start: node.start,
|
|
257
|
+
end: node.end,
|
|
258
|
+
text: binding,
|
|
259
|
+
mappings: [{ generatedStart: 0, generatedEnd: binding.length,
|
|
260
|
+
originalStart: node.start, originalEnd: node.end }],
|
|
261
|
+
})),
|
|
262
|
+
]
|
|
263
|
+
return { ...result, ...applySourceEdits(result.code, result.sourceMap, edits), importMetaBinding: binding }
|
|
264
|
+
}
|
|
265
|
+
|
|
223
266
|
|
|
224
267
|
function staticModuleClassification(moduleLoads) {
|
|
225
268
|
const reasons = new Map()
|
|
@@ -240,7 +283,9 @@ function staticModuleClassification(moduleLoads) {
|
|
|
240
283
|
}
|
|
241
284
|
|
|
242
285
|
/** Conservatively classify a cell before giving it non-journalable capability. */
|
|
243
|
-
export function classifyDurability(code, knownBindings = new Set(), {
|
|
286
|
+
export function classifyDurability(code, knownBindings = new Set(), {
|
|
287
|
+
sourceType = 'script', internalModules = new Set(), sourceMap = undefined, originalSource = undefined,
|
|
288
|
+
} = {}) {
|
|
244
289
|
let body
|
|
245
290
|
let moduleLoads = []
|
|
246
291
|
if (sourceType === 'module') {
|
|
@@ -280,14 +325,16 @@ export function classifyDurability(code, knownBindings = new Set(), { sourceType
|
|
|
280
325
|
const reasons = new Map()
|
|
281
326
|
const addReason = reason => reasons.set(renderDurabilityReason(reason), reason)
|
|
282
327
|
for (const reason of staticModuleClassification(moduleLoads)) addReason(reason)
|
|
283
|
-
const classifyModule = (source) => {
|
|
328
|
+
const classifyModule = (source, form) => {
|
|
284
329
|
if (source?.type !== 'Literal' || typeof source.value !== 'string') {
|
|
285
330
|
addReason(DYNAMIC_MODULE_REASON)
|
|
286
331
|
return
|
|
287
332
|
}
|
|
288
333
|
const classification = classifyModuleSource(source.value)
|
|
289
334
|
if (classification.status === 'forbidden') {
|
|
290
|
-
|
|
335
|
+
const span = sourceMap === undefined || originalSource === undefined ? declarationSpan(source)
|
|
336
|
+
: mapSourceSpan(declarationSpan(source), code, originalSource, sourceMap)
|
|
337
|
+
throw new PreflightError(`cell ${form} of ${source.value} is forbidden because it exposes kernel control`, undefined, span)
|
|
291
338
|
}
|
|
292
339
|
if (classification.reason !== undefined) addReason(classification.reason)
|
|
293
340
|
}
|
|
@@ -297,11 +344,12 @@ export function classifyDurability(code, knownBindings = new Set(), { sourceType
|
|
|
297
344
|
}
|
|
298
345
|
return false
|
|
299
346
|
}
|
|
300
|
-
walkAst(body, (node, parent, parentKey, { scopes, strict }) => {
|
|
347
|
+
walkAst(body, (node, parent, parentKey, { scopes, strict, thisIsGlobal }) => {
|
|
301
348
|
let nestedScopes = scopes
|
|
302
349
|
if (isFunction(node)) {
|
|
303
350
|
strict ||= hasStrictDirective(node.body)
|
|
304
351
|
nestedScopes = [...scopes, functionParameterBindings(node)]
|
|
352
|
+
if (node.type !== 'ArrowFunctionExpression') thisIsGlobal = false
|
|
305
353
|
} else if (node.type === 'BlockStatement' && node !== body) {
|
|
306
354
|
const names = directBlockBindings(node.body)
|
|
307
355
|
if (isFunction(parent)) addFunctionVariables(node, names, strict)
|
|
@@ -324,11 +372,16 @@ export function classifyDurability(code, knownBindings = new Set(), { sourceType
|
|
|
324
372
|
nestedScopes = [...scopes, loopBindings(node)]
|
|
325
373
|
}
|
|
326
374
|
if (node.type === 'ImportExpression') {
|
|
327
|
-
classifyModule(node.source)
|
|
375
|
+
classifyModule(node.source, 'import')
|
|
376
|
+
}
|
|
377
|
+
const sourceOwnedThis = sourceMap === undefined
|
|
378
|
+
|| sourceRangeHasOriginalText(sourceMap, code, originalSource, node.start, node.end)
|
|
379
|
+
if (node.type === 'ThisExpression' && thisIsGlobal && sourceOwnedThis) {
|
|
380
|
+
addReason(Object.freeze({ kind: 'ambient', name: 'globalThis' }))
|
|
328
381
|
}
|
|
329
382
|
if (node.type === 'CallExpression' && node.callee?.type === 'Identifier' && node.callee.name === 'require'
|
|
330
383
|
&& !isBound('require', nestedScopes)) {
|
|
331
|
-
classifyModule(node.arguments[0])
|
|
384
|
+
classifyModule(node.arguments[0], 'require')
|
|
332
385
|
}
|
|
333
386
|
if (node.type === 'Identifier' && isReferenceIdentifier(node, parent, parentKey)
|
|
334
387
|
&& !isBound(node.name, nestedScopes) && AMBIENT_GLOBALS.has(node.name)
|
|
@@ -367,8 +420,8 @@ export function classifyDurability(code, knownBindings = new Set(), { sourceType
|
|
|
367
420
|
addReason(Object.freeze({ kind: 'ambient', name: 'Math' }))
|
|
368
421
|
}
|
|
369
422
|
}
|
|
370
|
-
return { scopes: nestedScopes, strict }
|
|
371
|
-
}, undefined, { scopes: [rootBindings], strict: rootStrict })
|
|
423
|
+
return { scopes: nestedScopes, strict, thisIsGlobal }
|
|
424
|
+
}, undefined, { scopes: [rootBindings], strict: rootStrict, thisIsGlobal: sourceType === 'script' })
|
|
372
425
|
return {
|
|
373
426
|
durability: reasons.size === 0 ? 'durable' : 'volatile',
|
|
374
427
|
reasons: Object.freeze([...reasons.values()]),
|
|
@@ -454,31 +507,46 @@ export function prepareProgram(program, options = {}) {
|
|
|
454
507
|
let normalized
|
|
455
508
|
let prepared
|
|
456
509
|
let callableSources
|
|
510
|
+
let diagnosticInput
|
|
457
511
|
const intrinsicContext = { bindings: new Set() }
|
|
458
512
|
try {
|
|
459
513
|
const marked = markCallableSources(program, undefined, { plugins: CELL_PARSER_PLUGINS, allowImportExportEverywhere: true, allowUndeclaredExports: true },
|
|
460
514
|
{ lowerNativeSource: lowerNativeLanguageSource, nativeUsing: options.nativeUsing })
|
|
515
|
+
const moduleMetadata = lowerCellImportMeta(marked, options.importMeta, program)
|
|
516
|
+
diagnosticInput = moduleMetadata
|
|
461
517
|
callableSources = marked.callableSources
|
|
462
|
-
normalized = normalizeStatefulScopes(
|
|
463
|
-
nativeJavaScript: marked.nativeJavaScript,
|
|
518
|
+
normalized = normalizeStatefulScopes(moduleMetadata.code, moduleMetadata.sourceMap, { mode: options.languageSemantics,
|
|
519
|
+
callableSources, nativeJavaScript: marked.nativeJavaScript,
|
|
520
|
+
deferDecorators: true, deferResources: true, intrinsicContext })
|
|
521
|
+
if (moduleMetadata.importMetaBinding !== undefined) {
|
|
522
|
+
normalized.internalBindings = new Set(normalized.internalBindings)
|
|
523
|
+
normalized.internalBindings.add(moduleMetadata.importMetaBinding)
|
|
524
|
+
}
|
|
525
|
+
diagnosticInput = normalized
|
|
464
526
|
prepared = compileStatefulRoot(normalized.code, { ...options, sourceMap: normalized.sourceMap,
|
|
465
527
|
internalBindings: normalized.internalBindings, dynamicBindings: normalized.dynamicBindings,
|
|
466
528
|
privateBindings: normalized.privateBindings, originalSource: program })
|
|
467
529
|
} catch (error) {
|
|
468
530
|
if (error instanceof ModuleRewriteError) throw error
|
|
469
531
|
const position = error.loc === undefined ? undefined : { line: error.loc.line, column: error.loc.column + 1 }
|
|
470
|
-
|
|
471
|
-
|
|
532
|
+
const failureInput = normalizationFailureInput(error) ?? diagnosticInput
|
|
533
|
+
throw new ModuleRewriteError(error.message, failureInput === undefined ? position
|
|
534
|
+
: mapSourcePosition(position, failureInput.code, program, failureInput.sourceMap))
|
|
472
535
|
}
|
|
473
536
|
prepared = { ...prepared, deferredHelpers: normalized.deferredHelpers }
|
|
474
537
|
intrinsicContext.expression = `this[${JSON.stringify(prepared.rootRuntimeName)}].intrinsics`
|
|
475
538
|
const classificationSource = bindCompilerIntrinsics(lowerStatefulDecorators(
|
|
476
|
-
{ ...prepared, code: prepared.classificationCode
|
|
539
|
+
{ ...prepared, code: prepared.classificationCode, sourceMap: prepared.classificationSourceMap },
|
|
540
|
+
undefined, intrinsicContext), intrinsicContext)
|
|
477
541
|
prepared = bindCompilerIntrinsics(lowerStatefulDecorators(prepared, undefined, intrinsicContext), intrinsicContext)
|
|
478
542
|
prepared = lowerStatefulResources(prepared, { intrinsicContext, nativeUsing: options.nativeUsing })
|
|
479
543
|
const parsed = parseExecutableCell(prepared.code, { eraseTypes: true })
|
|
480
|
-
const
|
|
481
|
-
|
|
544
|
+
const classificationCode = parseExecutableCell(classificationSource.code, { eraseTypes: true }).code
|
|
545
|
+
const classification = classifyDurability(classificationCode,
|
|
546
|
+
new Set([...(options.knownBindings ?? []), ...prepared.declared]), {
|
|
547
|
+
sourceMap: classificationSource.sourceMap,
|
|
548
|
+
originalSource: program,
|
|
549
|
+
})
|
|
482
550
|
const reasons = [...staticModuleClassification(prepared.moduleLoads), ...classification.reasons]
|
|
483
551
|
const lowered = rewriteCellReturns(parsed.code, prepared.sourceMap,
|
|
484
552
|
new Set([...prepared.declared, ...(options.knownBindings ?? [])]))
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import { stringifyCompilerData } from './compiler-data.js'
|
|
2
2
|
import { compilerStorageSource } from './compiler-storage-source.js'
|
|
3
3
|
import { compilerDescriptorSource } from './compiler-descriptors.js'
|
|
4
|
+
import { runtimeIntrinsics } from './runtime-intrinsics.js'
|
|
4
5
|
|
|
5
6
|
/** Compiler operations are captured before an owned realm executes user code. */
|
|
6
7
|
const defaultRealmFunction = Function
|
|
7
8
|
const realms = new WeakMap()
|
|
8
|
-
const
|
|
9
|
-
const weakMapGet = uncurry(WeakMap.prototype.get)
|
|
10
|
-
const weakMapSet = uncurry(WeakMap.prototype.set)
|
|
11
|
-
const mapKeys = uncurry(Map.prototype.keys)
|
|
12
|
-
const mapIteratorNext = uncurry(Object.getPrototypeOf(new Map().keys()).next)
|
|
9
|
+
const { weakMapGet, weakMapSet } = runtimeIntrinsics
|
|
13
10
|
|
|
14
11
|
export function captureCompilerIntrinsics(realmFunction = defaultRealmFunction) {
|
|
15
12
|
let intrinsics = weakMapGet(realms, realmFunction)
|
|
@@ -21,7 +18,8 @@ export function captureCompilerIntrinsics(realmFunction = defaultRealmFunction)
|
|
|
21
18
|
const object=properties.Object;
|
|
22
19
|
const symbol=Symbol;
|
|
23
20
|
return {Object:object,WeakMap,WeakSet,unscopables:symbol.unscopables,Reflect:{apply:nativeReflect.apply,
|
|
24
|
-
construct:nativeReflect.construct,
|
|
21
|
+
construct:nativeReflect.construct,deleteProperty:nativeReflect.deleteProperty,has:nativeReflect.has,
|
|
22
|
+
ownKeys:nativeReflect.ownKeys,defineProperty:properties.reflectDefineProperty,
|
|
25
23
|
get decorate(){return nativeReflect.decorate}},TypeError,ReferenceError,SyntaxError,Error,Symbol,String,Number,
|
|
26
24
|
Promise:{resolve:Promise.resolve.bind(Promise),reject:Promise.reject.bind(Promise)},
|
|
27
25
|
SuppressedError:typeof SuppressedError==='function'?SuppressedError:undefined,
|
|
@@ -36,49 +34,17 @@ export const moduleCompilerIntrinsics = captureCompilerIntrinsics()
|
|
|
36
34
|
/** Internal graph records use captured collection operations. Source-owned
|
|
37
35
|
* objects and callbacks keep their original realm and observable methods. */
|
|
38
36
|
export const moduleRuntimeIntrinsics = {
|
|
37
|
+
...runtimeIntrinsics,
|
|
39
38
|
Object: moduleCompilerIntrinsics.Object,
|
|
40
39
|
Reflect: moduleCompilerIntrinsics.Reflect,
|
|
41
40
|
Error: moduleCompilerIntrinsics.Error,
|
|
42
|
-
|
|
43
|
-
mapGet: uncurry(Map.prototype.get),
|
|
44
|
-
mapHas: uncurry(Map.prototype.has),
|
|
45
|
-
mapSet: uncurry(Map.prototype.set),
|
|
46
|
-
mapDelete: uncurry(Map.prototype.delete),
|
|
47
|
-
mapClear: uncurry(Map.prototype.clear),
|
|
48
|
-
mapSize: uncurry(Object.getOwnPropertyDescriptor(Map.prototype, 'size').get),
|
|
49
|
-
mapFirstKey: value => mapIteratorNext(mapKeys(value)).value,
|
|
50
|
-
mapForEach: uncurry(Map.prototype.forEach),
|
|
51
|
-
setHas: uncurry(Set.prototype.has),
|
|
52
|
-
setAdd: uncurry(Set.prototype.add),
|
|
53
|
-
setDelete: uncurry(Set.prototype.delete),
|
|
54
|
-
setClear: uncurry(Set.prototype.clear),
|
|
55
|
-
setForEach: uncurry(Set.prototype.forEach),
|
|
56
|
-
weakMapHas: uncurry(WeakMap.prototype.has),
|
|
57
|
-
weakMapGet, weakMapSet,
|
|
58
|
-
isArray: Array.isArray,
|
|
59
|
-
includes: uncurry(Array.prototype.includes),
|
|
60
|
-
join: uncurry(Array.prototype.join),
|
|
61
|
-
sliceString: uncurry(String.prototype.slice),
|
|
62
|
-
replaceAllString: uncurry(String.prototype.replaceAll),
|
|
63
|
-
includesString: uncurry(String.prototype.includes),
|
|
64
|
-
floor: Math.floor,
|
|
65
|
-
min: Math.min,
|
|
66
|
-
max: Math.max,
|
|
41
|
+
TypeError: moduleCompilerIntrinsics.TypeError,
|
|
67
42
|
// Only private native Promises enter this boundary. Source promises and the
|
|
68
43
|
// public result keep their prototypes; private reactions cannot select a
|
|
69
44
|
// source constructor/species or dynamically dispatch through then/catch.
|
|
70
45
|
observeOwnedPromise: moduleCompilerIntrinsics.observeOwnedPromise,
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
return target
|
|
75
|
-
},
|
|
76
|
-
copyArray(source, start = 0, end = source.length, target = []) {
|
|
77
|
-
for (let index = start; index < end; index++) this.appendArray(target, source[index])
|
|
78
|
-
return target
|
|
79
|
-
},
|
|
80
|
-
sort: uncurry(Array.prototype.sort),
|
|
81
|
-
compare: uncurry(String.prototype.localeCompare),
|
|
82
|
-
startsWith: uncurry(String.prototype.startsWith),
|
|
46
|
+
promiseThen: moduleCompilerIntrinsics.promiseThen,
|
|
47
|
+
promiseResolve: moduleCompilerIntrinsics.Promise.resolve,
|
|
48
|
+
promiseReject: moduleCompilerIntrinsics.Promise.reject,
|
|
83
49
|
stringify: stringifyCompilerData,
|
|
84
50
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { fileURLToPath } from 'node:url'
|
|
2
2
|
|
|
3
3
|
const encodeReference = encodeURIComponent
|
|
4
|
+
const objectEntries = Object.entries
|
|
5
|
+
const sortArray = Function.prototype.call.bind(Array.prototype.sort)
|
|
6
|
+
const jsonStringify = JSON.stringify
|
|
4
7
|
|
|
5
8
|
// These ambient inputs must remain outside source-owned CommonJS bindings.
|
|
6
9
|
export const commonJsCompilerGlobals = new Set(['process'])
|
|
@@ -21,14 +24,14 @@ const ATTRIBUTED_LINK_KIND = 'static-attributed'
|
|
|
21
24
|
* attribute-free links keep the reference they had before attributes were
|
|
22
25
|
* distinguished. */
|
|
23
26
|
export function staticModuleLinkReference(source, attributes) {
|
|
24
|
-
const entries =
|
|
27
|
+
const entries = objectEntries(attributes ?? {})
|
|
25
28
|
if (entries.length === 0) return compilerModuleReference(STATIC_LINK_KIND, source)
|
|
26
|
-
entries
|
|
27
|
-
return compilerModuleReference(ATTRIBUTED_LINK_KIND,
|
|
29
|
+
sortArray(entries, (left, right) => left[0] < right[0] ? -1 : left[0] > right[0] ? 1 : 0)
|
|
30
|
+
return compilerModuleReference(ATTRIBUTED_LINK_KIND, jsonStringify([source, entries]))
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
/** Compiler helpers resolve from their own URL, independently of source-owned
|
|
31
34
|
* wrapper bindings and the ESM translator's restricted CommonJS require. */
|
|
32
35
|
export function commonJsCompilerImport(url) {
|
|
33
|
-
return `process.getBuiltinModule('module').createRequire(${
|
|
36
|
+
return `process.getBuiltinModule('module').createRequire(${jsonStringify(url.href)})(${jsonStringify(fileURLToPath(url))})`
|
|
34
37
|
}
|
package/internal/config-spec.js
CHANGED
|
@@ -96,7 +96,7 @@ export const CONFIG_FIELDS = Object.freeze([
|
|
|
96
96
|
{
|
|
97
97
|
key: 'userBindingsEnabled',
|
|
98
98
|
type: 'boolean',
|
|
99
|
-
default:
|
|
99
|
+
default: true,
|
|
100
100
|
label: '启用全局用户 Binding',
|
|
101
101
|
labelEn: 'Enable Global User Bindings',
|
|
102
102
|
description: '管理 TypeScript helper,并将已启用条目作为跨会话的默认 REPL 绑定。',
|
|
@@ -133,12 +133,22 @@ function requireCompanionServices(agent) {
|
|
|
133
133
|
|
|
134
134
|
async function companionSkillDirectory(agentPresets) {
|
|
135
135
|
const preset = await agentPresets.resolve(CORDIS_PRESET_ID)
|
|
136
|
-
if (typeof preset?.path !== 'string' || !isAbsolute(preset.path)) {
|
|
137
|
-
throw new Error('ptc-plus: DSH cordis preset did not expose an absolute composition path')
|
|
138
|
-
}
|
|
139
136
|
if (typeof preset.broken === 'string' && preset.broken.length > 0) {
|
|
140
137
|
throw new Error(`ptc-plus: DSH cordis preset is unavailable: ${preset.broken}`)
|
|
141
138
|
}
|
|
139
|
+
// The generations that discover presets from their composition directories
|
|
140
|
+
// publish an absolute path, and the preset's sibling `skills` directory is
|
|
141
|
+
// then the companion Skill root. A generation that declares presets without
|
|
142
|
+
// any composition path publishes no root through this surface at all, so the
|
|
143
|
+
// report names that missing publication instead of claiming a shape failure
|
|
144
|
+
// on a healthy host. A published path that is not absolute is still a
|
|
145
|
+
// contract contradiction.
|
|
146
|
+
if (preset?.path === undefined) {
|
|
147
|
+
throw new Error('ptc-plus: the installed DSH agentPresets generation publishes no composition path for the "cordis" preset, so it does not publish the companion Skill root that cordisToolsEnabled mounts')
|
|
148
|
+
}
|
|
149
|
+
if (typeof preset.path !== 'string' || !isAbsolute(preset.path)) {
|
|
150
|
+
throw new Error('ptc-plus: DSH cordis preset did not expose an absolute composition path')
|
|
151
|
+
}
|
|
142
152
|
return join(dirname(preset.path), 'skills')
|
|
143
153
|
}
|
|
144
154
|
|
|
@@ -329,6 +339,7 @@ export function createCordisToolsOwner(
|
|
|
329
339
|
|
|
330
340
|
const installAgent = (agent) => {
|
|
331
341
|
if (disposed) return Promise.resolve()
|
|
342
|
+
if (withdrawn.has(agent)) return Promise.resolve()
|
|
332
343
|
const mounted = mounts.get(agent)
|
|
333
344
|
if (mounted !== undefined) {
|
|
334
345
|
return mounted.withdrawn === true ? Promise.resolve() : mounted.activation
|
|
@@ -416,11 +427,11 @@ export function createCordisToolsOwner(
|
|
|
416
427
|
/**
|
|
417
428
|
* Install for a call the host makes on its own behalf.
|
|
418
429
|
*
|
|
419
|
-
*
|
|
420
|
-
* when a listener rejects, so a scope this owner cannot
|
|
421
|
-
* instead of failing an operation another plugin asked
|
|
422
|
-
* enumeration stays strict: there the plugin speaks for
|
|
423
|
-
* have published, and `ready` reports the same failure.
|
|
430
|
+
* The public host lifecycle announces `agent/created` serially and rejects
|
|
431
|
+
* `agents.create()` when a listener rejects, so a scope this owner cannot
|
|
432
|
+
* serve must withdraw instead of failing an operation another plugin asked
|
|
433
|
+
* for. Install-time enumeration stays strict: there the plugin speaks for
|
|
434
|
+
* what it claims to have published, and `ready` reports the same failure.
|
|
424
435
|
*/
|
|
425
436
|
const installForHost = (agent) => {
|
|
426
437
|
let activation
|
|
@@ -451,8 +462,7 @@ export function createCordisToolsOwner(
|
|
|
451
462
|
if (disposed) return
|
|
452
463
|
for (const agent of [...pending]) {
|
|
453
464
|
void Promise.resolve().then(() => installAgent(agent)).catch(error => {
|
|
454
|
-
|
|
455
|
-
ctx.logger?.warn?.('ptc-plus: deferred Cordis activation failed', error)
|
|
465
|
+
withdraw(agent, error)
|
|
456
466
|
})
|
|
457
467
|
}
|
|
458
468
|
})
|
|
@@ -34,15 +34,19 @@ export function adaptDynamicCell(code, sourceMap, options) {
|
|
|
34
34
|
let setup
|
|
35
35
|
if (options.module === true) {
|
|
36
36
|
const runtimeUrl = new URL('./dynamic-environment-runtime.js', import.meta.url)
|
|
37
|
+
const interfaceOwner = allocate('dynamic_interface_owner')
|
|
38
|
+
const runtimeOptions = `{interfaceOwner:${interfaceOwner}${options.importOperation === undefined
|
|
39
|
+
? '' : `,importModule:${options.importOperation}`}}`
|
|
37
40
|
if (options.sourceType === 'module') {
|
|
38
41
|
const factory = allocate('dynamic_factory')
|
|
39
|
-
setup = `\nimport {createDynamicEnvironmentRuntime as ${factory}} from ${JSON.stringify(runtimeUrl.href)};\n`
|
|
40
|
-
expression = `${factory}(${
|
|
41
|
-
options = { ...options, internalBindings: new Set([...options.internalBindings ?? [], factory]) }
|
|
42
|
+
setup = `\nimport {createDynamicEnvironmentRuntime as ${factory}} from ${JSON.stringify(runtimeUrl.href)};\nfunction ${interfaceOwner}(){}\n`
|
|
43
|
+
expression = `${factory}(${runtimeOptions}).installIntrinsics().environment({strict:true,getThis:()=>void 0})`
|
|
44
|
+
options = { ...options, internalBindings: new Set([...options.internalBindings ?? [], factory, interfaceOwner]) }
|
|
42
45
|
} else {
|
|
43
46
|
const names = ['exports', 'module', 'require', '__filename', '__dirname', 'arguments']
|
|
44
47
|
const bindings = names.map(name => `[${JSON.stringify(name)},{kind:"param",get:()=>${name}${name === 'arguments' && strict ? '' : `,set:v=>${name}=v`}}]`).join(',')
|
|
45
|
-
setup = `\nconst ${environmentName}=${commonJsCompilerImport(runtimeUrl)}.createDynamicEnvironmentRuntime(${
|
|
48
|
+
setup = `\nfunction ${interfaceOwner}(){}\nconst ${environmentName}=${commonJsCompilerImport(runtimeUrl)}.createDynamicEnvironmentRuntime(${runtimeOptions}).installIntrinsics().environment({strict:${strict},getThis:()=>this,getNewTarget:()=>new.target,allowNewTarget:true,nativeBindings:[${bindings}]});\n`
|
|
49
|
+
options = { ...options, internalBindings: new Set([...options.internalBindings ?? [], interfaceOwner]) }
|
|
46
50
|
}
|
|
47
51
|
} else setup = options.nativeRoot === true ? `\nconst ${environmentName}=${options.environmentGlobal};\n`
|
|
48
52
|
: `\nconst ${environmentName}=${options.rootRuntime}.dynamic();\n`
|
|
@@ -16,6 +16,17 @@ function captureReflection(reflect) {
|
|
|
16
16
|
return captured
|
|
17
17
|
}
|
|
18
18
|
const defaultIntrinsics = { intrinsicEval: eval, realmFunction: Function, globalObject: globalThis, reflect: captureReflection(Reflect) }
|
|
19
|
+
let programAmbientResolver
|
|
20
|
+
|
|
21
|
+
/** Install the worker-owned resolver used by explicitly adapted program modules. */
|
|
22
|
+
export function installProgramAmbientResolver(resolve) {
|
|
23
|
+
if (programAmbientResolver !== undefined) throw new Error('program ambient resolver is already installed')
|
|
24
|
+
if (typeof resolve !== 'function') throw new TypeError('program ambient resolver must be a function')
|
|
25
|
+
programAmbientResolver = resolve
|
|
26
|
+
return () => {
|
|
27
|
+
if (programAmbientResolver === resolve) programAmbientResolver = undefined
|
|
28
|
+
}
|
|
29
|
+
}
|
|
19
30
|
|
|
20
31
|
const isObject = value => value !== null && (typeof value === 'object' || typeof value === 'function')
|
|
21
32
|
const isMap = types.isMap
|
|
@@ -45,7 +56,7 @@ const asBindings = value => {
|
|
|
45
56
|
export function createDynamicEnvironmentRuntime({
|
|
46
57
|
importModule = (source, options) => import(source, options),
|
|
47
58
|
intrinsicEval = defaultIntrinsics.intrinsicEval, realmFunction = defaultIntrinsics.realmFunction, globalObject = defaultIntrinsics.globalObject,
|
|
48
|
-
errors, reflect = defaultIntrinsics.reflect, object, interfaceOwner,
|
|
59
|
+
errors, reflect = defaultIntrinsics.reflect, object, interfaceOwner, resolveAmbient = programAmbientResolver,
|
|
49
60
|
} = {}) {
|
|
50
61
|
const intrinsics = captureCompilerIntrinsics(realmFunction)
|
|
51
62
|
const { unscopables, Object: intrinsicObject, array: internalArray } = intrinsics
|
|
@@ -143,7 +154,10 @@ export function createDynamicEnvironmentRuntime({
|
|
|
143
154
|
return deleted
|
|
144
155
|
},
|
|
145
156
|
}, object, strict)
|
|
146
|
-
const ambientReference = (name, strict) =>
|
|
157
|
+
const ambientReference = (name, strict) => {
|
|
158
|
+
const resolved = resolveAmbient?.(name)
|
|
159
|
+
if (resolved !== undefined) return reference(name, resolved, undefined, strict)
|
|
160
|
+
return reference(name, {
|
|
147
161
|
get() {
|
|
148
162
|
if (!reflect.has(globalObject, name)) throw new errors.ReferenceError(`${name} is not defined`)
|
|
149
163
|
return reflect.get(globalObject, name, globalObject)
|
|
@@ -154,7 +168,8 @@ export function createDynamicEnvironmentRuntime({
|
|
|
154
168
|
},
|
|
155
169
|
typeof: () => reflect.has(globalObject, name) ? typeof reflect.get(globalObject, name, globalObject) : 'undefined',
|
|
156
170
|
delete: () => reflect.deleteProperty(globalObject, name),
|
|
157
|
-
|
|
171
|
+
}, undefined, strict)
|
|
172
|
+
}
|
|
158
173
|
|
|
159
174
|
function environment({ frames = [], varFrame = new internal.Map(), strict = false, origin, lexicalContext = {},
|
|
160
175
|
getThis = () => globalObject, getNewTarget = () => undefined, allowNewTarget = false,
|
|
@@ -170,6 +185,12 @@ export function createDynamicEnvironmentRuntime({
|
|
|
170
185
|
importModule,
|
|
171
186
|
internalArray,
|
|
172
187
|
expose: nativeCalls.exposedValue,
|
|
188
|
+
exposeProperty(receiver, key) {
|
|
189
|
+
if (receiver === null || receiver === undefined) {
|
|
190
|
+
throw new errors.TypeError(`Cannot read properties of ${receiver}`)
|
|
191
|
+
}
|
|
192
|
+
return nativeCalls.exposedMemberValue(receiver, reflect.get(object(receiver), key, receiver))
|
|
193
|
+
},
|
|
173
194
|
prepareCall: nativeCalls.prepareCall,
|
|
174
195
|
prepareInvocation: nativeCalls.prepareInvocation,
|
|
175
196
|
releaseMemberReceiver: nativeCalls.releaseMemberReceiver,
|
|
@@ -42,7 +42,10 @@ export function rewriteNativeCalls(tree, environment, { origin, skip, operations
|
|
|
42
42
|
parent.node.computed = true
|
|
43
43
|
parent.node.key = t.stringLiteral(path.node.name)
|
|
44
44
|
}
|
|
45
|
-
path.
|
|
45
|
+
if (path.isMemberExpression() && !t.isSuper(path.node.object) && !t.isPrivateName(path.node.property)) {
|
|
46
|
+
const key = path.node.computed ? path.node.property : t.stringLiteral(path.node.property.name)
|
|
47
|
+
path.replaceWith(t.inherits(helper('exposeProperty', [path.node.object, key]), path.node))
|
|
48
|
+
} else path.replaceWith(t.inherits(helper('expose', [path.node]), path.node))
|
|
46
49
|
path.skip()
|
|
47
50
|
}
|
|
48
51
|
const prepare = (callee, target, optional = false) => {
|
|
@@ -11,6 +11,7 @@ const exposedIntrinsics = new internal.WeakMap()
|
|
|
11
11
|
const sources = createCallableSourceRegistry()
|
|
12
12
|
const callableSources = new internal.WeakMap()
|
|
13
13
|
const callableSourceTargets = new internal.WeakMap()
|
|
14
|
+
const callableInterfaces = new internal.WeakMap()
|
|
14
15
|
const sourceTarget = origin => typeof origin === 'string' ? origin : origin?.target
|
|
15
16
|
const copyArguments = (source, start = 0, result = []) => internal.copyArray(source, start, source.length, result)
|
|
16
17
|
const invocationScopes = new AsyncLocalStorage()
|
|
@@ -114,7 +115,19 @@ export function createNativeCallAdapter({ realmFunction, intrinsicEval, reflect,
|
|
|
114
115
|
internal.weakMapSet(state.callableSources, compiled, source)
|
|
115
116
|
return compiled
|
|
116
117
|
}
|
|
117
|
-
const exposedValue = value =>
|
|
118
|
+
const exposedValue = value => {
|
|
119
|
+
const exposed = internal.mapGet(selected.exposed, value) ?? internal.weakMapGet(exposedIntrinsics, value)
|
|
120
|
+
if (exposed !== undefined) return exposed
|
|
121
|
+
if (typeof value === 'function' && !internal.weakMapHas(callableInterfaces, value)) {
|
|
122
|
+
internal.weakMapSet(callableInterfaces, value, selected)
|
|
123
|
+
}
|
|
124
|
+
return value
|
|
125
|
+
}
|
|
126
|
+
const exposedMemberValue = (receiver, value) => {
|
|
127
|
+
const owner = typeof receiver === 'function' ? internal.weakMapGet(callableInterfaces, receiver) : undefined
|
|
128
|
+
const exposed = owner === undefined ? undefined : internal.mapGet(owner.exposed, value)
|
|
129
|
+
return exposed ?? exposedValue(value)
|
|
130
|
+
}
|
|
118
131
|
const propagate = (error, origin) => {
|
|
119
132
|
recordExceptionOrigin(error, sourceTarget(origin), { reset: true })
|
|
120
133
|
for (let scope = currentScope(); scope !== undefined; scope = scope.parent) {
|
|
@@ -218,6 +231,7 @@ export function createNativeCallAdapter({ realmFunction, intrinsicEval, reflect,
|
|
|
218
231
|
return {
|
|
219
232
|
install,
|
|
220
233
|
exposedValue,
|
|
234
|
+
exposedMemberValue,
|
|
221
235
|
isEval: callee => callee === state.intrinsicEval || internal.mapHas(selected.exposed, state.intrinsicEval) && callee === internal.mapGet(selected.exposed, state.intrinsicEval),
|
|
222
236
|
evaluate(compiled, environment) {
|
|
223
237
|
// Bootstrap originals never leave this owner. Direct eval must use the
|