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.
- package/README.en.md +63 -80
- package/README.md +63 -80
- package/assets/ptc-plus-bindings-en.png +0 -0
- package/assets/ptc-plus-bindings-zh.png +0 -0
- package/assets/ptc-plus-repair-en.png +0 -0
- package/assets/ptc-plus-repair-zh.png +0 -0
- package/assets/ptc-plus-repl-workspace-en.png +0 -0
- package/assets/ptc-plus-repl-workspace-zh.png +0 -0
- package/assets/ptc-plus-settings-en.png +0 -0
- package/assets/ptc-plus-settings-zh.png +0 -0
- package/client.js +30827 -742
- package/compiler-amaro.cjs +5 -0
- package/compiler-amaro.cjs.map +6 -0
- package/compiler-asset-124f80c1bba92ff5fe79cfec6e8ad518f476de4a42514cae3919538887f510e8.txt +1 -0
- package/compiler-assets.json +3 -0
- package/compiler-core.cjs +556 -0
- package/compiler-core.cjs.map +6 -0
- package/compiler-platform.cjs +2 -0
- package/compiler-platform.cjs.map +6 -0
- package/compiler-typescript.cjs +388 -0
- package/compiler-typescript.cjs.map +6 -0
- package/docs/README.md +7 -0
- package/docs/adr/0004-declare-program-bindings-at-the-host.md +1 -1
- package/docs/adr/0006-rewrite-module-syntax-with-an-ast.md +5 -3
- package/docs/adr/0007-separate-worker-transport-from-session-semantics.md +1 -1
- package/docs/adr/0009-bound-expensive-acceptance-default.md +2 -0
- package/docs/adr/0010-session-log-derived-recovery-tips.md +59 -5
- package/docs/adr/0011-isolate-the-local-recovery-tip-provider.md +1 -1
- package/docs/adr/0012-preserve-mixed-destructuring-initialization.md +3 -1
- package/docs/adr/0013-isolate-repl-redeclaration-convenience.md +3 -1
- package/docs/adr/0014-persist-cell-rewrite-policy.md +6 -2
- package/docs/adr/0015-preserve-source-positions-through-rewrites.md +1 -1
- package/docs/adr/0016-archive-resolved-review-findings.md +1 -1
- package/docs/adr/0017-track-the-latest-dsh-public-surface.md +49 -0
- package/docs/adr/0018-use-versioned-fixture-for-ab-benchmark.md +3 -3
- package/docs/adr/0019-plugin-settings-and-kill-switch.md +5 -3
- package/docs/adr/0020-optional-cordis-tools-in-ptc-mode.md +2 -2
- package/docs/adr/0021-separate-host-bootstrap-from-session-runtime.md +12 -0
- package/docs/adr/0023-global-user-bindings.md +104 -0
- package/docs/adr/0024-repl-console-observation.md +33 -0
- package/docs/adr/0025-use-versioned-logical-binding-identities.md +119 -0
- package/docs/adr/0026-persist-the-delivery-verdict-against-the-verified-candidate.md +21 -0
- package/docs/adr/0027-run-the-session-kernel-in-a-killable-helper-process.md +37 -0
- package/docs/adr/0028-attach-to-the-host-ptc-execution-seam.md +103 -0
- package/docs/adr/0029-keep-plugin-unavailability-out-of-the-host-agent-lifecycle.md +27 -0
- package/docs/adr/0030-serve-both-typert-codec-generations-from-one-codec.md +27 -0
- package/docs/architecture.md +77 -21
- package/docs/binding-review-placement-design.md +200 -0
- package/docs/capability-projection.md +1 -1
- package/docs/client-ui.md +95 -19
- package/docs/durability-design.md +28 -10
- package/docs/evaluation.md +78 -6
- package/docs/installation.md +41 -6
- package/docs/publishing.md +5 -3
- package/docs/runtime-reference.md +76 -25
- package/docs/semantic-validation.md +29 -0
- package/docs/stateful-binding-updates-proposal.md +759 -0
- package/docs/user-bindings.en.md +66 -0
- package/docs/user-bindings.md +66 -0
- package/docs/value-wire.md +3 -3
- package/docs/verification-optimization-work.md +41 -0
- package/docs/verification.md +71 -0
- package/index.js +369 -92
- package/internal/ast-traversal.js +5 -2
- package/internal/async-local-storage-intrinsics.js +38 -0
- package/internal/binding-declaration-contract.js +8 -0
- package/internal/binding-descriptors.js +1 -0
- package/internal/binding-pattern-traversal.js +25 -0
- package/internal/binding-pattern.js +26 -29
- package/internal/binding-source-analysis.js +708 -0
- package/internal/binding-update-policy.js +72 -0
- package/internal/bounded-worker-round.js +56 -0
- package/internal/callable-definition-environment.js +42 -0
- package/internal/callable-source-catalog.js +129 -0
- package/internal/callable-source-encoding.js +47 -0
- package/internal/callable-source-facts.js +459 -0
- package/internal/callable-source-format.js +2 -0
- package/internal/callable-source-lowering.js +123 -0
- package/internal/cell-analysis-contract.js +25 -0
- package/internal/cell-analysis.js +253 -290
- package/internal/cell-completion.js +15 -0
- package/internal/cell-error.js +7 -0
- package/internal/cell-parser.js +66 -0
- package/internal/cell-rewriter.js +3 -677
- package/internal/commonjs-export-evidence.js +63 -0
- package/internal/commonjs-source-evidence.js +72 -0
- package/internal/compiler-amaro.cjs +2 -0
- package/internal/compiler-compression.js +12 -0
- package/internal/compiler-data.js +58 -0
- package/internal/compiler-descriptors.js +54 -0
- package/internal/compiler-dynamic-cache.js +48 -0
- package/internal/compiler-entry.js +35 -0
- package/internal/compiler-generated-names.js +17 -0
- package/internal/compiler-intrinsics.js +50 -0
- package/internal/compiler-module-links.js +37 -0
- package/internal/compiler-operations.js +61 -0
- package/internal/compiler-platform-factory.js +84 -0
- package/internal/compiler-platform.js +136 -0
- package/internal/compiler-record-roles.js +53 -0
- package/internal/compiler-region-output.js +259 -0
- package/internal/compiler-resource-lowering.js +103 -0
- package/internal/compiler-scope-facts.js +115 -0
- package/internal/compiler-service.js +109 -0
- package/internal/compiler-source-cache.js +32 -0
- package/internal/compiler-source-pieces.js +93 -0
- package/internal/compiler-source-regions.js +132 -0
- package/internal/compiler-storage-source.js +54 -0
- package/internal/compiler-text.js +15 -0
- package/internal/compiler-typescript.cjs +2 -0
- package/internal/config-spec.js +83 -27
- package/internal/cordis-tools-owner.js +130 -21
- package/internal/diagnostic.js +27 -1
- package/internal/direct-surface-owner.js +76 -23
- package/internal/dynamic-binding-evidence.js +16 -0
- package/internal/dynamic-environment-compiler.js +779 -0
- package/internal/dynamic-environment-integration.js +91 -0
- package/internal/dynamic-environment-runtime.js +383 -0
- package/internal/dynamic-native-calls.js +153 -0
- package/internal/dynamic-native-runtime.js +262 -0
- package/internal/dynamic-scope-analysis.js +90 -0
- package/internal/edit-transport-owner.js +27 -2
- package/internal/execution-seam-compat.js +193 -0
- package/internal/failure-reporting.js +136 -28
- package/internal/host-rpc.js +66 -0
- package/internal/isolated-worker.js +555 -0
- package/internal/kernel-child.js +139 -0
- package/internal/kernel-worker.js +1179 -233
- package/internal/language-semantics.js +14 -0
- package/internal/legacy-binding-catalog.js +48 -0
- package/internal/legacy-cell-analysis.js +600 -0
- package/internal/legacy-cell-parser.js +50 -0
- package/internal/legacy-cell-rewriter.js +631 -0
- package/internal/legacy-repl-convenience.js +291 -0
- package/internal/managed-module-operations.js +170 -0
- package/internal/module-compilation.js +322 -0
- package/internal/module-runtime-platform.js +19 -0
- package/internal/module-transform-contract.js +42 -0
- package/internal/native-await-declarations.js +68 -0
- package/internal/native-root-compilation.js +54 -0
- package/internal/native-root-dynamic.js +67 -0
- package/internal/record-utils.js +24 -15
- package/internal/recovery-tips.js +27 -15
- package/internal/rejected-cell-editor.js +13 -8
- package/internal/repl-convenience.js +2 -289
- package/internal/repl-memory-projection.js +81 -12
- package/internal/repl-observation-interest.js +70 -0
- package/internal/repl-rewrite-contract.js +6 -0
- package/internal/repl-scope-normalizer.js +2091 -0
- package/internal/repl-value-observer.js +117 -0
- package/internal/rpc-contract.js +52 -0
- package/internal/runtime-bridge-owner.js +172 -28
- package/internal/runtime-config.js +48 -52
- package/internal/runtime-contexts.js +82 -10
- package/internal/runtime-intrinsics.js +101 -0
- package/internal/runtime-messages.js +111 -0
- package/internal/session-cell-executor.js +402 -87
- package/internal/session-journal-recovery.js +684 -0
- package/internal/session-journal-schema.js +123 -0
- package/internal/session-journal.js +199 -654
- package/internal/session-log-view.js +42 -9
- package/internal/session-runtime.js +257 -95
- package/internal/session-state.js +247 -71
- package/internal/source-position-map.js +230 -71
- package/internal/stateful-module-compiler.js +154 -0
- package/internal/stateful-module-runtime.js +303 -0
- package/internal/stateful-root-compiler.js +600 -0
- package/internal/stateful-root-runtime.js +340 -0
- package/internal/typert-codec-compat.js +28 -0
- package/internal/typescript-transform.js +31 -0
- package/internal/user-binding-authoring.js +70 -0
- package/internal/user-binding-console-worker.js +244 -0
- package/internal/user-binding-console.js +148 -0
- package/internal/user-binding-draft-projection.js +335 -0
- package/internal/user-binding-model-context.js +31 -0
- package/internal/user-binding-runner.js +56 -0
- package/internal/user-bindings-owner.js +1065 -0
- package/internal/user-bindings-store.js +293 -0
- package/internal/user-bindings.js +361 -0
- package/internal/value-wire-schema.js +28 -0
- package/internal/value-wire.js +130 -91
- package/internal/worker-client.js +57 -67
- package/internal/worker-cwd-virtualization.js +80 -53
- package/internal/worker-environment.js +65 -0
- package/internal/worker-output-relay.js +29 -0
- package/internal/worker-repl-realm.js +134 -0
- package/internal/worker-shutdown.js +14 -0
- package/package.json +76 -7
- package/src/client-activity.js +95 -53
- package/src/client-authoring-view.js +580 -0
- package/src/client-binding-review.js +230 -0
- package/src/client-bindings-data.js +29 -0
- package/src/client-catalog.js +127 -0
- package/src/client-code-editor.js +84 -0
- package/src/client-console.js +112 -0
- package/src/client-copy.js +370 -0
- package/src/client-feature-gates.js +62 -0
- package/src/client-host-compat.js +150 -0
- package/src/client-indicator-view.js +267 -0
- package/src/client-repl-view.js +292 -0
- package/src/client-rpc.js +20 -0
- package/src/client-settings-view.js +221 -0
- package/src/client-styles.js +106 -0
- package/src/client-tool-view.js +108 -0
- package/src/client-transport.js +159 -0
- package/src/client-workbench.js +521 -0
- package/src/client.js +233 -615
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Recorded compilation contracts. Live configuration cannot reinterpret history. */
|
|
2
|
+
export const LEGACY_LANGUAGE_SEMANTICS = 'legacy-v1'
|
|
3
|
+
export const STATEFUL_LANGUAGE_SEMANTICS = 'stateful-v1'
|
|
4
|
+
export const PROTECTED_LANGUAGE_SEMANTICS = 'protected-v1'
|
|
5
|
+
export const LANGUAGE_SEMANTICS = new Set([
|
|
6
|
+
LEGACY_LANGUAGE_SEMANTICS,
|
|
7
|
+
STATEFUL_LANGUAGE_SEMANTICS,
|
|
8
|
+
PROTECTED_LANGUAGE_SEMANTICS,
|
|
9
|
+
])
|
|
10
|
+
|
|
11
|
+
export function normalizeLanguageSemantics(value) {
|
|
12
|
+
if (!LANGUAGE_SEMANTICS.has(value)) throw new TypeError('invalid dsh-ptc-plus language semantics')
|
|
13
|
+
return value
|
|
14
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/** Historical legacy-v1 catalog transition, retained from c51616c8d6c8:session-state.js. */
|
|
2
|
+
export function advanceLegacyBindings(previousEntries, prepared, extractDefinition, committedRedeclarations) {
|
|
3
|
+
const entries = new Map(previousEntries)
|
|
4
|
+
const touched = new Set()
|
|
5
|
+
const redeclared = new Set((prepared.redeclared ?? []).map(declaration => declaration.name))
|
|
6
|
+
const commitGated = prepared.commitTargets
|
|
7
|
+
const committed = committedRedeclarations instanceof Set
|
|
8
|
+
? committedRedeclarations
|
|
9
|
+
: new Set([...redeclared, ...commitGated])
|
|
10
|
+
const uncommitted = new Set()
|
|
11
|
+
for (const declaration of prepared.declarations ?? []) {
|
|
12
|
+
if (typeof declaration?.name !== 'string') continue
|
|
13
|
+
const dependency = typeof declaration.commitDependency === 'string'
|
|
14
|
+
&& commitGated.has(declaration.commitDependency)
|
|
15
|
+
? declaration.commitDependency
|
|
16
|
+
: commitGated.has(declaration.name) ? declaration.name : undefined
|
|
17
|
+
if (dependency !== undefined && !committed.has(dependency)) {
|
|
18
|
+
uncommitted.add(declaration.name)
|
|
19
|
+
continue
|
|
20
|
+
}
|
|
21
|
+
touched.add(declaration.name)
|
|
22
|
+
const previous = entries.get(declaration.name)
|
|
23
|
+
const definition = extractDefinition(declaration.definitionSpan)
|
|
24
|
+
entries.set(declaration.name, {
|
|
25
|
+
kind: declaration.kind ?? 'variable',
|
|
26
|
+
definition: definition ?? previous?.definition,
|
|
27
|
+
writable: redeclared.has(declaration.name) ? previous?.writable === true : declaration.writable === true,
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
for (const name of prepared.declared) {
|
|
31
|
+
if (!uncommitted.has(name)) touched.add(name)
|
|
32
|
+
}
|
|
33
|
+
for (const name of touched) {
|
|
34
|
+
const entry = entries.get(name) ?? { kind: 'variable', writable: false }
|
|
35
|
+
entries.delete(name)
|
|
36
|
+
entries.set(name, entry)
|
|
37
|
+
}
|
|
38
|
+
const imports = new Map(prepared.imports)
|
|
39
|
+
for (const [name, binding] of imports) {
|
|
40
|
+
if (typeof binding?.commitDependency !== 'string'
|
|
41
|
+
|| !commitGated.has(binding.commitDependency)
|
|
42
|
+
|| committed.has(binding.commitDependency)) continue
|
|
43
|
+
if (previousEntries.get(name)?.import !== undefined) imports.set(name, previousEntries.get(name).import)
|
|
44
|
+
else imports.delete(name)
|
|
45
|
+
}
|
|
46
|
+
for (const [name, entry] of entries) entries.set(name, { ...entry, import: imports.get(name) })
|
|
47
|
+
return { entries, namespaces: prepared.importNamespaces }
|
|
48
|
+
}
|
|
@@ -0,0 +1,600 @@
|
|
|
1
|
+
/** Historical legacy-v1 lowering, retained from c51616c8d6c8:cell-analysis.js. */
|
|
2
|
+
import { ModuleRewriteError, rewriteModuleImportsExports } from './legacy-cell-rewriter.js'
|
|
3
|
+
import { parseExecutableCell } from './legacy-cell-parser.js'
|
|
4
|
+
import {
|
|
5
|
+
LEGACY_DEFAULT_EXPORT_BINDING,
|
|
6
|
+
LIVE_DEFAULT_EXPORT_BINDING,
|
|
7
|
+
LIVE_MODULE_SEMANTICS,
|
|
8
|
+
LEGACY_IMPORT_EXPRESSION_BOUNDARY,
|
|
9
|
+
LIVE_IMPORT_EXPRESSION_BOUNDARY,
|
|
10
|
+
redeclarationCommitTarget,
|
|
11
|
+
} from './repl-rewrite-contract.js'
|
|
12
|
+
import {
|
|
13
|
+
bindingNodes,
|
|
14
|
+
createGeneratedNameAllocator,
|
|
15
|
+
walkBindingPattern as walkPattern,
|
|
16
|
+
} from './binding-pattern.js'
|
|
17
|
+
import {
|
|
18
|
+
AMBIENT_GLOBALS,
|
|
19
|
+
DYNAMIC_MODULE_REASON,
|
|
20
|
+
classifyModuleSource,
|
|
21
|
+
renderDurabilityReason,
|
|
22
|
+
renderDurabilityReasons,
|
|
23
|
+
} from './module-policy.js'
|
|
24
|
+
import { rewriteReplRedeclarations } from './legacy-repl-convenience.js'
|
|
25
|
+
import { applySourceEdits, mapSourcePosition, mapSourceSpan } from './source-position-map.js'
|
|
26
|
+
import { SKIP_AST_CHILDREN, walkAst } from './ast-traversal.js'
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Pure AST analysis for PTC cells: binding inventory, durability classification,
|
|
30
|
+
* return rewriting, and program preparation. This module owns no worker, journal,
|
|
31
|
+
* or session state so its behavior is fully testable in isolation.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
export function declarationSpan(node) {
|
|
35
|
+
const start = node.loc?.start
|
|
36
|
+
/* c8 ignore next */
|
|
37
|
+
const end = node.loc?.end ?? start
|
|
38
|
+
/* c8 ignore next */
|
|
39
|
+
if (start === undefined) return undefined
|
|
40
|
+
return {
|
|
41
|
+
line: start.line,
|
|
42
|
+
column: start.column + 1,
|
|
43
|
+
/* c8 ignore next */
|
|
44
|
+
...(end === undefined ? {} : {
|
|
45
|
+
end: {
|
|
46
|
+
line: end.line,
|
|
47
|
+
column: end.column + 1,
|
|
48
|
+
},
|
|
49
|
+
}),
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function addPatternBindings(pattern, names) {
|
|
54
|
+
walkPattern(pattern, node => names.add(node.name))
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function addPatternDeclarations(pattern, declarations, kind = 'variable', definitionSpan = undefined, writable = false) {
|
|
58
|
+
bindingNodes(pattern).forEach(node => declarations.push({
|
|
59
|
+
name: node.name,
|
|
60
|
+
kind,
|
|
61
|
+
span: declarationSpan(node),
|
|
62
|
+
definitionSpan,
|
|
63
|
+
writable,
|
|
64
|
+
}))
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function topLevelBindings(body) {
|
|
68
|
+
return new Set(topLevelDeclarations(body).map(declaration => declaration.name))
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function topLevelDeclarations(body, variableRedeclarations = false) {
|
|
72
|
+
const declarations = []
|
|
73
|
+
for (const statement of body) {
|
|
74
|
+
if (statement.type === 'VariableDeclaration') {
|
|
75
|
+
const definitionSpan = declarationSpan(statement)
|
|
76
|
+
for (const declaration of statement.declarations) {
|
|
77
|
+
addPatternDeclarations(
|
|
78
|
+
declaration.id,
|
|
79
|
+
declarations,
|
|
80
|
+
'variable',
|
|
81
|
+
definitionSpan,
|
|
82
|
+
statement.kind !== 'const' || variableRedeclarations,
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
} else if ((statement.type === 'FunctionDeclaration' || statement.type === 'ClassDeclaration')
|
|
86
|
+
&& statement.id !== null) {
|
|
87
|
+
declarations.push({
|
|
88
|
+
name: statement.id.name,
|
|
89
|
+
kind: statement.type === 'ClassDeclaration' ? 'class' : 'function',
|
|
90
|
+
span: declarationSpan(statement.id),
|
|
91
|
+
definitionSpan: declarationSpan(statement),
|
|
92
|
+
commitDependency: redeclarationCommitTarget(statement.id.name, statement.start),
|
|
93
|
+
writable: true,
|
|
94
|
+
})
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return declarations
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function directBlockBindings(body) {
|
|
101
|
+
const names = new Set()
|
|
102
|
+
for (const statement of body) {
|
|
103
|
+
if (statement.type === 'VariableDeclaration' && statement.kind !== 'var') {
|
|
104
|
+
for (const declaration of statement.declarations) addPatternBindings(declaration.id, names)
|
|
105
|
+
} else if ((statement.type === 'FunctionDeclaration' || statement.type === 'ClassDeclaration')
|
|
106
|
+
&& statement.id !== null) {
|
|
107
|
+
names.add(statement.id.name)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return names
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function functionParameterBindings(node) {
|
|
114
|
+
const names = new Set()
|
|
115
|
+
if (node.id !== null && node.id !== undefined) names.add(node.id.name)
|
|
116
|
+
/* c8 ignore next */
|
|
117
|
+
for (const param of node.params ?? []) addPatternBindings(param, names)
|
|
118
|
+
return names
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function hasStrictDirective(body) {
|
|
122
|
+
if (body.type !== 'BlockStatement') return false
|
|
123
|
+
for (const statement of body.body) {
|
|
124
|
+
if (statement.directive === undefined) break
|
|
125
|
+
if (statement.directive === 'use strict') return true
|
|
126
|
+
}
|
|
127
|
+
return false
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function addFunctionVariables(body, names, strict) {
|
|
131
|
+
const addBlockFunction = (node, blocked) => {
|
|
132
|
+
if (!strict && node.type === 'FunctionDeclaration' && !node.async && !node.generator
|
|
133
|
+
&& !blocked.has(node.id.name)) names.add(node.id.name)
|
|
134
|
+
}
|
|
135
|
+
walkAst(body, (current, parent, key, blocked) => {
|
|
136
|
+
if (isFunction(current)) {
|
|
137
|
+
addBlockFunction(current, blocked)
|
|
138
|
+
return SKIP_AST_CHILDREN
|
|
139
|
+
}
|
|
140
|
+
if (current.type === 'StaticBlock') return SKIP_AST_CHILDREN
|
|
141
|
+
if (current.type === 'VariableDeclaration' && current.kind === 'var') {
|
|
142
|
+
for (const declaration of current.declarations) addPatternBindings(declaration.id, names)
|
|
143
|
+
}
|
|
144
|
+
const statements = current.type === 'BlockStatement' ? current.body
|
|
145
|
+
: current.type === 'SwitchCase' ? parent.cases.flatMap(branch => branch.consequent) : undefined
|
|
146
|
+
if (statements !== undefined) {
|
|
147
|
+
// Annex B creates a function-scope var only when intervening lexical
|
|
148
|
+
// declarations permit it. The declaration's own block binding is excluded.
|
|
149
|
+
for (const statement of statements) addBlockFunction(statement, blocked)
|
|
150
|
+
return new Set([...blocked, ...directBlockBindings(statements)])
|
|
151
|
+
}
|
|
152
|
+
if (['ForStatement', 'ForInStatement', 'ForOfStatement'].includes(current.type)) {
|
|
153
|
+
return new Set([...blocked, ...loopBindings(current)])
|
|
154
|
+
}
|
|
155
|
+
if (current.type === 'CatchClause' && current.param !== null && current.param.type !== 'Identifier') {
|
|
156
|
+
// The Annex B catch exception admits var names through a simple parameter,
|
|
157
|
+
// but a destructured catch binding still blocks function-scope promotion.
|
|
158
|
+
const nested = new Set(blocked)
|
|
159
|
+
addPatternBindings(current.param, nested)
|
|
160
|
+
return nested
|
|
161
|
+
}
|
|
162
|
+
}, undefined, new Set())
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function loopBindings(node) {
|
|
166
|
+
const declaration = node.type === 'ForStatement' ? node.init : node.left
|
|
167
|
+
if (declaration?.type !== 'VariableDeclaration' || declaration.kind === 'var') return new Set()
|
|
168
|
+
const names = new Set()
|
|
169
|
+
for (const entry of declaration.declarations) addPatternBindings(entry.id, names)
|
|
170
|
+
return names
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function isReferenceIdentifier(node, parent, key) {
|
|
174
|
+
/* c8 ignore next */
|
|
175
|
+
if (parent === undefined) return false
|
|
176
|
+
if ((parent.type === 'MemberExpression' || parent.type === 'OptionalMemberExpression')
|
|
177
|
+
&& key === 'property' && !parent.computed) return false
|
|
178
|
+
if ((parent.type === 'Property' || parent.type === 'MethodDefinition' || parent.type === 'PropertyDefinition')
|
|
179
|
+
&& key === 'key' && !parent.computed && !parent.shorthand) return false
|
|
180
|
+
if (['VariableDeclarator', 'FunctionDeclaration', 'FunctionExpression', 'ClassDeclaration', 'ClassExpression']
|
|
181
|
+
.includes(parent.type) && key === 'id') return false
|
|
182
|
+
if ((parent.type === 'FunctionDeclaration' || parent.type === 'FunctionExpression' || parent.type === 'ArrowFunctionExpression')
|
|
183
|
+
&& key === 'params') return false
|
|
184
|
+
if (parent.type === 'CatchClause' && key === 'param') return false
|
|
185
|
+
if (['LabeledStatement', 'BreakStatement', 'ContinueStatement'].includes(parent.type) && key === 'label') return false
|
|
186
|
+
return true
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function isStableProcessMember(node, parent) {
|
|
190
|
+
/* c8 ignore next */
|
|
191
|
+
if (node.name !== 'process' || parent?.type !== 'MemberExpression' || parent.object !== node) return false
|
|
192
|
+
const member = parent.computed
|
|
193
|
+
? parent.property?.type === 'Literal' ? parent.property.value : undefined
|
|
194
|
+
/* c8 ignore next */
|
|
195
|
+
: parent.property?.type === 'Identifier' ? parent.property.name : undefined
|
|
196
|
+
return ['stdout', 'stderr', 'cwd'].includes(member)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function staticMemberName(node) {
|
|
200
|
+
if (node?.type !== 'MemberExpression') return undefined
|
|
201
|
+
if (!node.computed && node.property?.type === 'Identifier') return node.property.name
|
|
202
|
+
if (node.computed && node.property?.type === 'Literal' && typeof node.property.value === 'string') {
|
|
203
|
+
return node.property.value
|
|
204
|
+
}
|
|
205
|
+
return undefined
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function globalObjectMember(node) {
|
|
209
|
+
return node?.type === 'MemberExpression'
|
|
210
|
+
&& node.object?.type === 'Identifier'
|
|
211
|
+
&& ['global', 'globalThis'].includes(node.object.name)
|
|
212
|
+
? staticMemberName(node)
|
|
213
|
+
: undefined
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function isFunction(node) {
|
|
217
|
+
return node.type === 'FunctionDeclaration'
|
|
218
|
+
|| node.type === 'FunctionExpression'
|
|
219
|
+
|| node.type === 'ArrowFunctionExpression'
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export class LegacyPreflightError extends Error {
|
|
223
|
+
constructor(message, node, span = undefined) {
|
|
224
|
+
super(message)
|
|
225
|
+
this.span = span ?? declarationSpan(node)
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function staticModuleClassification(moduleLoads) {
|
|
230
|
+
const reasons = new Map()
|
|
231
|
+
for (const load of moduleLoads) {
|
|
232
|
+
const classification = classifyModuleSource(load.source)
|
|
233
|
+
if (classification.status === 'forbidden') {
|
|
234
|
+
throw new LegacyPreflightError(
|
|
235
|
+
`cell import of ${load.source} is forbidden because it exposes kernel control`,
|
|
236
|
+
undefined,
|
|
237
|
+
load.position,
|
|
238
|
+
)
|
|
239
|
+
}
|
|
240
|
+
if (classification.reason !== undefined) {
|
|
241
|
+
reasons.set(renderDurabilityReason(classification.reason), classification.reason)
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return [...reasons.values()]
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/** Conservatively classify a cell before giving it non-journalable capability. */
|
|
248
|
+
export function classifyDurability(code, knownBindings = new Set()) {
|
|
249
|
+
const { body } = parseExecutableCell(code)
|
|
250
|
+
const declared = topLevelBindings(body.body)
|
|
251
|
+
const rootBindings = new Set([...knownBindings, ...declared])
|
|
252
|
+
const rootStrict = hasStrictDirective(body)
|
|
253
|
+
addFunctionVariables(body, rootBindings, rootStrict)
|
|
254
|
+
const reasons = new Map()
|
|
255
|
+
const addReason = reason => reasons.set(renderDurabilityReason(reason), reason)
|
|
256
|
+
const classifyModule = (source) => {
|
|
257
|
+
if (source?.type !== 'Literal' || typeof source.value !== 'string') {
|
|
258
|
+
addReason(DYNAMIC_MODULE_REASON)
|
|
259
|
+
return
|
|
260
|
+
}
|
|
261
|
+
const classification = classifyModuleSource(source.value)
|
|
262
|
+
if (classification.status === 'forbidden') {
|
|
263
|
+
throw new LegacyPreflightError(`cell import of ${source.value} is forbidden because it exposes kernel control`, source)
|
|
264
|
+
}
|
|
265
|
+
if (classification.reason !== undefined) addReason(classification.reason)
|
|
266
|
+
}
|
|
267
|
+
const isBound = (name, scopes) => {
|
|
268
|
+
for (let index = scopes.length - 1; index >= 0; index -= 1) {
|
|
269
|
+
if (scopes[index].has(name)) return true
|
|
270
|
+
}
|
|
271
|
+
return false
|
|
272
|
+
}
|
|
273
|
+
walkAst(body, (node, parent, parentKey, { scopes, strict }) => {
|
|
274
|
+
let nestedScopes = scopes
|
|
275
|
+
if (isFunction(node)) {
|
|
276
|
+
strict ||= hasStrictDirective(node.body)
|
|
277
|
+
nestedScopes = [...scopes, functionParameterBindings(node)]
|
|
278
|
+
} else if (node.type === 'BlockStatement' && node !== body) {
|
|
279
|
+
const names = directBlockBindings(node.body)
|
|
280
|
+
if (isFunction(parent)) addFunctionVariables(node, names, strict)
|
|
281
|
+
nestedScopes = [...scopes, names]
|
|
282
|
+
} else if (node.type === 'StaticBlock') {
|
|
283
|
+
const names = directBlockBindings(node.body)
|
|
284
|
+
for (const statement of node.body) addFunctionVariables(statement, names, true)
|
|
285
|
+
strict = true
|
|
286
|
+
nestedScopes = [...scopes, names]
|
|
287
|
+
} else if (node.type === 'ClassDeclaration' || node.type === 'ClassExpression') {
|
|
288
|
+
strict = true
|
|
289
|
+
nestedScopes = [...scopes, new Set(node.id === null ? [] : [node.id.name])]
|
|
290
|
+
} else if (node.type === 'SwitchCase') {
|
|
291
|
+
nestedScopes = [...scopes, directBlockBindings(parent.cases.flatMap(branch => branch.consequent))]
|
|
292
|
+
} else if (node.type === 'CatchClause') {
|
|
293
|
+
const names = new Set()
|
|
294
|
+
addPatternBindings(node.param, names)
|
|
295
|
+
nestedScopes = [...scopes, names]
|
|
296
|
+
} else if (['ForStatement', 'ForInStatement', 'ForOfStatement'].includes(node.type)) {
|
|
297
|
+
nestedScopes = [...scopes, loopBindings(node)]
|
|
298
|
+
}
|
|
299
|
+
if (node.type === 'ImportExpression') {
|
|
300
|
+
classifyModule(node.source)
|
|
301
|
+
}
|
|
302
|
+
if (node.type === 'CallExpression' && node.callee?.type === 'Identifier' && node.callee.name === 'require'
|
|
303
|
+
&& !isBound('require', nestedScopes)) {
|
|
304
|
+
classifyModule(node.arguments[0])
|
|
305
|
+
}
|
|
306
|
+
if (node.type === 'Identifier' && isReferenceIdentifier(node, parent, parentKey)
|
|
307
|
+
&& !isBound(node.name, nestedScopes) && AMBIENT_GLOBALS.has(node.name)
|
|
308
|
+
&& !(node.name === 'require' && parent?.type === 'CallExpression' && parent.callee === node)) {
|
|
309
|
+
addReason(Object.freeze({ kind: 'ambient', name: node.name }))
|
|
310
|
+
}
|
|
311
|
+
if (node.type === 'Identifier' && isReferenceIdentifier(node, parent, parentKey)
|
|
312
|
+
&& !isBound('process', nestedScopes) && node.name === 'process' && !isStableProcessMember(node, parent)) {
|
|
313
|
+
addReason(Object.freeze({ kind: 'ambient', name: 'process' }))
|
|
314
|
+
}
|
|
315
|
+
if (node.type === 'Identifier' && ['global', 'globalThis'].includes(node.name)
|
|
316
|
+
&& isReferenceIdentifier(node, parent, parentKey) && !isBound(node.name, nestedScopes)
|
|
317
|
+
&& !(parent?.type === 'MemberExpression' && parent.object === node)) {
|
|
318
|
+
addReason(Object.freeze({ kind: 'ambient', name: node.name }))
|
|
319
|
+
}
|
|
320
|
+
if (node.type === 'Identifier' && node.name === 'Math'
|
|
321
|
+
&& isReferenceIdentifier(node, parent, parentKey) && !isBound('Math', nestedScopes)
|
|
322
|
+
&& !(parent?.type === 'MemberExpression' && parent.object === node && staticMemberName(parent) !== undefined)) {
|
|
323
|
+
addReason(Object.freeze({ kind: 'ambient', name: 'Math' }))
|
|
324
|
+
}
|
|
325
|
+
if (node.type === 'MemberExpression'
|
|
326
|
+
&& ((node.object?.type === 'Identifier' && node.object.name === 'Math' && !isBound('Math', nestedScopes))
|
|
327
|
+
|| (globalObjectMember(node.object) === 'Math' && !isBound(node.object.object.name, nestedScopes)))
|
|
328
|
+
&& staticMemberName(node) === 'random') {
|
|
329
|
+
addReason(Object.freeze({ kind: 'math-random' }))
|
|
330
|
+
}
|
|
331
|
+
if (node.type === 'MemberExpression' && node.object?.type === 'Identifier'
|
|
332
|
+
&& ['global', 'globalThis'].includes(node.object.name) && !isBound(node.object.name, nestedScopes)) {
|
|
333
|
+
const member = staticMemberName(node)
|
|
334
|
+
if (member === undefined) addReason(Object.freeze({ kind: 'computed-global-access' }))
|
|
335
|
+
else if (member === 'process') addReason(Object.freeze({ kind: 'ambient', name: 'process' }))
|
|
336
|
+
else if (AMBIENT_GLOBALS.has(member)) addReason(Object.freeze({ kind: 'ambient', name: member }))
|
|
337
|
+
else if (member === 'global' || member === 'globalThis') addReason(Object.freeze({ kind: 'ambient', name: member }))
|
|
338
|
+
else if (member === 'Math' && !(parent?.type === 'MemberExpression' && parent.object === node
|
|
339
|
+
&& staticMemberName(parent) !== undefined)) {
|
|
340
|
+
addReason(Object.freeze({ kind: 'ambient', name: 'Math' }))
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
return { scopes: nestedScopes, strict }
|
|
344
|
+
}, undefined, { scopes: [rootBindings], strict: rootStrict })
|
|
345
|
+
return {
|
|
346
|
+
durability: reasons.size === 0 ? 'durable' : 'volatile',
|
|
347
|
+
reasons: Object.freeze([...reasons.values()]),
|
|
348
|
+
declared,
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function rewriteCellReturns(code, sourceMap, unavailableNames) {
|
|
353
|
+
const { body } = parseExecutableCell(code)
|
|
354
|
+
const edits = []
|
|
355
|
+
const allocateName = createGeneratedNameAllocator(body, unavailableNames)
|
|
356
|
+
const returnSignal = allocateName('return_signal')
|
|
357
|
+
const signalReference = `this[${JSON.stringify(returnSignal)}]`
|
|
358
|
+
|
|
359
|
+
walkAst(body, (node) => {
|
|
360
|
+
if (node !== body && isFunction(node)) return SKIP_AST_CHILDREN
|
|
361
|
+
if (node.type === 'ReturnStatement') {
|
|
362
|
+
const start = node.start
|
|
363
|
+
const end = node.end
|
|
364
|
+
const argument = node.argument === null
|
|
365
|
+
? ''
|
|
366
|
+
: code.slice(node.argument.start, node.argument.end)
|
|
367
|
+
// A ReturnStatement may be the last clause body in a switch case. The
|
|
368
|
+
// generated throw must terminate explicitly because the original return
|
|
369
|
+
// statement's semicolon is part of the replaced AST range.
|
|
370
|
+
edits.push({ start, end, text: `throw new ${signalReference}(${argument});` })
|
|
371
|
+
return SKIP_AST_CHILDREN
|
|
372
|
+
}
|
|
373
|
+
if (node.type === 'CatchClause') {
|
|
374
|
+
const bodyStart = node.body.start + 1
|
|
375
|
+
const temporary = allocateName('caught')
|
|
376
|
+
if (node.param === null) {
|
|
377
|
+
edits.push({ start: node.start + 5, end: node.start + 5, text: ` (${temporary})` })
|
|
378
|
+
edits.push({ start: bodyStart, end: bodyStart, text: `\nif (${temporary} instanceof ${signalReference}) throw ${temporary};` })
|
|
379
|
+
} else if (node.param.type === 'Identifier') {
|
|
380
|
+
edits.push({
|
|
381
|
+
start: bodyStart,
|
|
382
|
+
end: bodyStart,
|
|
383
|
+
text: `\nif (${node.param.name} instanceof ${signalReference}) throw ${node.param.name};`,
|
|
384
|
+
})
|
|
385
|
+
} else {
|
|
386
|
+
const pattern = code.slice(node.param.start, node.param.end)
|
|
387
|
+
edits.push({ start: node.param.start, end: node.param.end, text: temporary })
|
|
388
|
+
edits.push({
|
|
389
|
+
start: bodyStart,
|
|
390
|
+
end: bodyStart,
|
|
391
|
+
text: `\nif (${temporary} instanceof ${signalReference}) throw ${temporary};\nconst ${pattern} = ${temporary};`,
|
|
392
|
+
})
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
})
|
|
396
|
+
|
|
397
|
+
/* c8 ignore next */
|
|
398
|
+
edits.sort((left, right) => right.start - left.start || right.end - left.end)
|
|
399
|
+
return { ...applySourceEdits(code, sourceMap, edits), returnSignal }
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
function normalizePreparationOptions({
|
|
403
|
+
knownBindings = new Set(),
|
|
404
|
+
bindingPolicy,
|
|
405
|
+
reservedBindings = new Set(),
|
|
406
|
+
rewritesEnabled,
|
|
407
|
+
importBindings = new Map(),
|
|
408
|
+
importNamespaces = new Set(),
|
|
409
|
+
writableBindings,
|
|
410
|
+
moduleSemantics = LIVE_MODULE_SEMANTICS,
|
|
411
|
+
}) {
|
|
412
|
+
if (typeof bindingPolicy === 'boolean') {
|
|
413
|
+
bindingPolicy = {
|
|
414
|
+
variableRedeclarations: bindingPolicy,
|
|
415
|
+
functionClassRedeclarations: false,
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
if (bindingPolicy === null || typeof bindingPolicy !== 'object' || Array.isArray(bindingPolicy)
|
|
419
|
+
|| typeof bindingPolicy.variableRedeclarations !== 'boolean'
|
|
420
|
+
|| typeof bindingPolicy.functionClassRedeclarations !== 'boolean') {
|
|
421
|
+
throw new TypeError('ptc-plus: binding policy must define variableRedeclarations and functionClassRedeclarations booleans')
|
|
422
|
+
}
|
|
423
|
+
writableBindings ??= bindingPolicy.variableRedeclarations ? new Set(knownBindings) : new Set()
|
|
424
|
+
if (rewritesEnabled === null || typeof rewritesEnabled !== 'object' || Array.isArray(rewritesEnabled)
|
|
425
|
+
|| typeof rewritesEnabled.autoRewriteImports !== 'boolean'
|
|
426
|
+
|| typeof rewritesEnabled.autoStripExports !== 'boolean'
|
|
427
|
+
|| typeof rewritesEnabled.autoSplitRedeclarations !== 'boolean') {
|
|
428
|
+
throw new TypeError('ptc-plus: rewrite policy must define autoRewriteImports, autoStripExports, and autoSplitRedeclarations booleans')
|
|
429
|
+
}
|
|
430
|
+
if (moduleSemantics === null || typeof moduleSemantics !== 'object' || Array.isArray(moduleSemantics)
|
|
431
|
+
|| ![LEGACY_DEFAULT_EXPORT_BINDING, LIVE_DEFAULT_EXPORT_BINDING]
|
|
432
|
+
.includes(moduleSemantics.defaultExportBinding)
|
|
433
|
+
|| ![LEGACY_IMPORT_EXPRESSION_BOUNDARY, LIVE_IMPORT_EXPRESSION_BOUNDARY]
|
|
434
|
+
.includes(moduleSemantics.importExpressionBoundary)) {
|
|
435
|
+
throw new TypeError('ptc-plus: module semantics must define supported default-export and import-expression rules')
|
|
436
|
+
}
|
|
437
|
+
return { knownBindings, bindingPolicy, reservedBindings, rewritesEnabled,
|
|
438
|
+
importBindings, importNamespaces, writableBindings, moduleSemantics }
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
function parseMappedCell(moduleRewrite, program) {
|
|
442
|
+
try {
|
|
443
|
+
return parseExecutableCell(moduleRewrite.code, { eraseTypes: true })
|
|
444
|
+
} catch (error) {
|
|
445
|
+
if (error instanceof ModuleRewriteError) {
|
|
446
|
+
error.cellPosition = mapSourcePosition(error.cellPosition, moduleRewrite.code, program, moduleRewrite.sourceMap)
|
|
447
|
+
}
|
|
448
|
+
throw error
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
function collisionMapper(code, program, sourceMap) {
|
|
453
|
+
return declaration => {
|
|
454
|
+
/* c8 ignore next */
|
|
455
|
+
const mapped = declaration.original === true ? declaration.span : declaration.span === undefined
|
|
456
|
+
? { line: 1, column: 1 }
|
|
457
|
+
: mapSourceSpan(declaration.span, code, program, sourceMap)
|
|
458
|
+
return {
|
|
459
|
+
name: declaration.name,
|
|
460
|
+
kind: declaration.kind,
|
|
461
|
+
replaceableByVariableDeclaration: declaration.replaceableByVariableDeclaration === true,
|
|
462
|
+
...(declaration.reason === undefined ? {} : { reason: declaration.reason }),
|
|
463
|
+
...(declaration.commitDependency === undefined
|
|
464
|
+
? {}
|
|
465
|
+
: { commitDependency: declaration.commitDependency }),
|
|
466
|
+
start: { line: mapped.line, column: mapped.column },
|
|
467
|
+
/* c8 ignore next */
|
|
468
|
+
...(mapped.end === undefined ? {} : { end: mapped.end }),
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
function preparedDeclarations(moduleRewrite, parsed, program, bindingPolicy) {
|
|
474
|
+
const generatedDeclarations = topLevelDeclarations(parsed.body.body, bindingPolicy.variableRedeclarations)
|
|
475
|
+
const originalDeclarationNames = new Set(moduleRewrite.exportDeclarations.map(declaration => declaration.name))
|
|
476
|
+
return [
|
|
477
|
+
...moduleRewrite.importDeclarations.map(declaration => ({ ...declaration, writable: false })),
|
|
478
|
+
...moduleRewrite.exportDeclarations.map(declaration => ({
|
|
479
|
+
...declaration,
|
|
480
|
+
writable: bindingPolicy.variableRedeclarations,
|
|
481
|
+
})),
|
|
482
|
+
...generatedDeclarations
|
|
483
|
+
.filter(declaration => !moduleRewrite.generatedNamespaces.has(declaration.name)
|
|
484
|
+
&& !originalDeclarationNames.has(declaration.name))
|
|
485
|
+
.map(declaration => ({
|
|
486
|
+
...declaration,
|
|
487
|
+
...(declaration.definitionSpan === undefined ? {} : {
|
|
488
|
+
definitionSpan: mapSourceSpan(declaration.definitionSpan, parsed.code, program, moduleRewrite.sourceMap),
|
|
489
|
+
}),
|
|
490
|
+
})),
|
|
491
|
+
]
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
function classifyPrepared({ code, sourceMap }, program, knownBindings, moduleRewrite, staticModuleReasons) {
|
|
495
|
+
let classification
|
|
496
|
+
try {
|
|
497
|
+
classification = classifyDurability(code, knownBindings)
|
|
498
|
+
} catch (error) {
|
|
499
|
+
if (error instanceof LegacyPreflightError && error.span !== undefined) {
|
|
500
|
+
error.span = mapSourceSpan(error.span, code, program, sourceMap)
|
|
501
|
+
}
|
|
502
|
+
throw error
|
|
503
|
+
}
|
|
504
|
+
const reasons = new Map()
|
|
505
|
+
for (const reason of [...staticModuleReasons, ...classification.reasons]) {
|
|
506
|
+
reasons.set(renderDurabilityReason(reason), reason)
|
|
507
|
+
}
|
|
508
|
+
const imports = new Map(moduleRewrite.imports)
|
|
509
|
+
for (const name of classification.declared) {
|
|
510
|
+
if (!moduleRewrite.generatedNamespaces.has(name)) imports.delete(name)
|
|
511
|
+
}
|
|
512
|
+
return {
|
|
513
|
+
...classification,
|
|
514
|
+
durability: reasons.size === 0 ? 'durable' : 'volatile',
|
|
515
|
+
reasons: Object.freeze([...reasons.values()]),
|
|
516
|
+
reason: renderDurabilityReasons([...reasons.values()]),
|
|
517
|
+
imports,
|
|
518
|
+
declared: new Set([...classification.declared, ...moduleRewrite.imports.keys()]),
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
export function prepareLegacyProgram(program, options = {}) {
|
|
523
|
+
if (typeof program !== 'string') throw new TypeError('ptc-plus: program must be a string')
|
|
524
|
+
const { knownBindings, bindingPolicy, reservedBindings, rewritesEnabled,
|
|
525
|
+
importBindings, importNamespaces, writableBindings, moduleSemantics } = normalizePreparationOptions(options)
|
|
526
|
+
const unavailableGeneratedNames = new Set([
|
|
527
|
+
...knownBindings, ...reservedBindings, ...importBindings.keys(), ...importNamespaces,
|
|
528
|
+
])
|
|
529
|
+
const moduleRewrite = rewriteModuleImportsExports(
|
|
530
|
+
program, rewritesEnabled, importBindings, importNamespaces, unavailableGeneratedNames, moduleSemantics,
|
|
531
|
+
)
|
|
532
|
+
const staticModuleReasons = staticModuleClassification(moduleRewrite.moduleLoads)
|
|
533
|
+
const parsed = parseMappedCell(moduleRewrite, program)
|
|
534
|
+
const { code } = parsed
|
|
535
|
+
const { sourceMap, commitSignal } = moduleRewrite
|
|
536
|
+
const declarations = preparedDeclarations(moduleRewrite, parsed, program, bindingPolicy)
|
|
537
|
+
const collisionFor = collisionMapper(code, program, sourceMap)
|
|
538
|
+
const reserved = declarations.filter(declaration => (
|
|
539
|
+
reservedBindings.has(declaration.name)
|
|
540
|
+
|| moduleRewrite.importNamespaces.has(declaration.name)
|
|
541
|
+
|| (declaration.kind === 'import' && knownBindings.has(declaration.name))
|
|
542
|
+
))
|
|
543
|
+
const convenience = reserved.length > 0 ? {
|
|
544
|
+
executableCode: code, executableSourceMap: sourceMap,
|
|
545
|
+
collisions: reserved.map(declaration => ({ ...collisionFor(declaration),
|
|
546
|
+
reason: reservedBindings.has(declaration.name)
|
|
547
|
+
? 'reserved-program-binding-not-shadowable' : 'import-binding-redeclaration' })),
|
|
548
|
+
redeclared: [], rewrites: [],
|
|
549
|
+
} : rewriteReplRedeclarations({
|
|
550
|
+
code,
|
|
551
|
+
sourceMap,
|
|
552
|
+
body: parsed.body.body,
|
|
553
|
+
knownBindings,
|
|
554
|
+
variableRedeclarationBindings: bindingPolicy.variableRedeclarations
|
|
555
|
+
? new Set([...knownBindings].filter(name => !importBindings.has(name)))
|
|
556
|
+
: new Set(knownBindings),
|
|
557
|
+
writableBindings: new Set([...writableBindings].filter(name => !importBindings.has(name))),
|
|
558
|
+
declarations,
|
|
559
|
+
declarationSpan,
|
|
560
|
+
collisionFor,
|
|
561
|
+
bindingPolicy,
|
|
562
|
+
autoSplitRedeclarations: rewritesEnabled.autoSplitRedeclarations,
|
|
563
|
+
commitSignal,
|
|
564
|
+
})
|
|
565
|
+
const { executableCode, executableSourceMap, collisions, redeclared, rewrites } = convenience
|
|
566
|
+
const commitTargets = new Set(moduleRewrite.commitTargets)
|
|
567
|
+
for (const declaration of redeclared) {
|
|
568
|
+
if (declaration.kind === 'function' || declaration.kind === 'class') {
|
|
569
|
+
commitTargets.add(declaration.commitDependency)
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
// Generated control helpers are not ambient inputs from the user's program.
|
|
573
|
+
const classification = classifyPrepared(
|
|
574
|
+
{ code: executableCode, sourceMap: executableSourceMap },
|
|
575
|
+
program, knownBindings, moduleRewrite, staticModuleReasons,
|
|
576
|
+
)
|
|
577
|
+
let lowered = { code, sourceMap }
|
|
578
|
+
if (collisions.length === 0) {
|
|
579
|
+
lowered = rewriteCellReturns(
|
|
580
|
+
executableCode,
|
|
581
|
+
executableSourceMap,
|
|
582
|
+
unavailableGeneratedNames,
|
|
583
|
+
)
|
|
584
|
+
}
|
|
585
|
+
return {
|
|
586
|
+
code: lowered.code,
|
|
587
|
+
sourceMap: lowered.sourceMap,
|
|
588
|
+
returnSignal: lowered.returnSignal,
|
|
589
|
+
...classification,
|
|
590
|
+
declarations,
|
|
591
|
+
imports: classification.imports,
|
|
592
|
+
importNamespaces: moduleRewrite.importNamespaces,
|
|
593
|
+
collisions,
|
|
594
|
+
redeclared,
|
|
595
|
+
rewrites: [...moduleRewrite.rewrites, ...rewrites],
|
|
596
|
+
moduleLoads: moduleRewrite.moduleLoads,
|
|
597
|
+
commitSignal,
|
|
598
|
+
commitTargets,
|
|
599
|
+
}
|
|
600
|
+
}
|