dsh-ptc-plus 0.4.2 → 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 +166 -76
- package/README.md +167 -77
- 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 +593 -306
- package/compiler-core.cjs +162 -160
- package/compiler-core.cjs.map +3 -3
- package/docs/README.md +3 -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 +1 -1
- 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 +4 -0
- 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 +6 -5
- package/docs/binding-review-placement-design.md +1 -1
- package/docs/client-ui.md +8 -4
- package/docs/durability-design.md +7 -7
- package/docs/installation.md +26 -8
- package/docs/runtime-reference.md +18 -11
- package/docs/semantic-validation.md +7 -3
- package/docs/user-bindings.en.md +7 -6
- package/docs/user-bindings.md +6 -5
- package/docs/value-wire.md +1 -1
- package/docs/verification.md +38 -1
- package/index.js +39 -34
- package/internal/async-local-storage-intrinsics.js +12 -7
- package/internal/callable-source-facts.js +37 -1
- package/internal/cell-analysis.js +64 -9
- package/internal/config-spec.js +1 -1
- package/internal/cordis-tools-owner.js +20 -10
- package/internal/edit-transport-owner.js +80 -20
- package/internal/execution-seam-compat.js +192 -30
- package/internal/kernel-worker.js +162 -72
- package/internal/message-sources.js +14 -0
- package/internal/module-compilation.js +2 -1
- package/internal/repl-memory-projection.js +10 -0
- package/internal/repl-scope-normalizer.js +72 -35
- package/internal/repl-value-observer.js +141 -45
- package/internal/runtime-config.js +62 -2
- package/internal/runtime-intrinsics.js +3 -0
- package/internal/runtime-messages.js +6 -4
- package/internal/session-cell-executor.js +24 -1
- package/internal/session-journal-recovery.js +267 -67
- package/internal/session-journal.js +466 -40
- package/internal/session-log-view.js +5 -4
- package/internal/session-runtime.js +45 -21
- package/internal/session-state.js +7 -29
- package/internal/settings-compat.js +66 -1
- package/internal/source-position-map.js +19 -0
- package/internal/user-binding-console-worker.js +23 -9
- package/internal/user-binding-draft-projection.js +3 -2
- package/internal/user-bindings-owner.js +2 -1
- package/internal/user-bindings.js +6 -1
- package/internal/validated-parse-repair.js +6 -2
- package/internal/value-wire.js +95 -30
- package/internal/worker-client.js +99 -8
- package/internal/worker-cwd-virtualization.js +10 -9
- 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 +10 -4
- package/package.json +36 -4
- package/src/client-activity.js +4 -1
- 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,4 +1,5 @@
|
|
|
1
1
|
import { create as createDomain } from 'node:domain'
|
|
2
|
+
import { Console } from 'node:console'
|
|
2
3
|
import { createRequire, registerHooks } from 'node:module'
|
|
3
4
|
import { managedModuleImport, managedRequire, readModuleImport, statefulModuleLink } from './stateful-module-runtime.js'
|
|
4
5
|
import { staticModuleLinkReference } from './compiler-module-links.js'
|
|
@@ -6,9 +7,8 @@ import { compileStatefulModule, createUserModuleCompilationHooks } from './state
|
|
|
6
7
|
import { USER_BINDING_TRANSFORM, LEGACY_USER_BINDING_TRANSFORM } from './module-transform-contract.js'
|
|
7
8
|
import { isAbsolute, resolve } from 'node:path'
|
|
8
9
|
import repl from 'node:repl'
|
|
9
|
-
import { PassThrough } from 'node:stream'
|
|
10
|
+
import { PassThrough, Writable } from 'node:stream'
|
|
10
11
|
import { pathToFileURL } from 'node:url'
|
|
11
|
-
import { formatWithOptions } from 'node:util'
|
|
12
12
|
import { MessageChannel, parentPort, workerData } from 'node:worker_threads'
|
|
13
13
|
import { synchronizeBuiltinEsmExports } from './builtin-esm-sync.js'
|
|
14
14
|
import { createPrivateAsyncLocalStorage } from './async-local-storage-intrinsics.js'
|
|
@@ -17,6 +17,13 @@ import { DURABLE_IMPORTS, FORBIDDEN_IMPORTS } from './module-policy.js'
|
|
|
17
17
|
import { decodeValue, encodeValue } from './value-wire.js'
|
|
18
18
|
import { LEGACY_USER_BINDINGS_REUSE_POLICY, LIVE_USER_BINDINGS_SHADOW_POLICY, normalizeUserBindingNames } from './session-journal-schema.js'
|
|
19
19
|
import { installWorkerCwdVirtualization } from './worker-cwd-virtualization.js'
|
|
20
|
+
import {
|
|
21
|
+
WORKER_REALM_MUTATION,
|
|
22
|
+
assignWorkerRealmProperty,
|
|
23
|
+
defineWorkerRealmProperty,
|
|
24
|
+
deleteWorkerRealmProperty,
|
|
25
|
+
installProcessControlGuards,
|
|
26
|
+
} from './worker-realm-surfaces.js'
|
|
20
27
|
import { createReplValueObserver, supportsAwaitLexicals, previewBindingValue } from './repl-value-observer.js'
|
|
21
28
|
import { createStatefulRootRuntime } from './stateful-root-runtime.js'
|
|
22
29
|
import { createNativeRootDynamic } from './native-root-dynamic.js'
|
|
@@ -24,6 +31,7 @@ import { moduleRuntimeIntrinsics } from './compiler-intrinsics.js'
|
|
|
24
31
|
import { compilerDescriptors } from './compiler-descriptors.js'
|
|
25
32
|
import { createCellCompletionObserver } from './cell-completion.js'
|
|
26
33
|
import { WORKER_SHUTDOWN_ACKNOWLEDGEMENT, WORKER_SHUTDOWN_REQUEST } from './worker-shutdown.js'
|
|
34
|
+
import { outputFenceMarker } from './worker-output-fence.js'
|
|
27
35
|
import { WORKER_REPL_OPTIONS, createWorkerControlPromise, createWorkerReplErrorHandler,
|
|
28
36
|
createWorkerUncaughtExceptionHandler,
|
|
29
37
|
disableWorkerReplDomain,
|
|
@@ -34,7 +42,9 @@ import { installProgramAmbientResolver } from './dynamic-environment-runtime.js'
|
|
|
34
42
|
const { Object, Map, Set, Proxy, Error,
|
|
35
43
|
mapGet, mapSet, mapHas, mapDelete, mapClear, mapSize, mapForEach,
|
|
36
44
|
setHas, setAdd, setDelete, setClear, setForEach,
|
|
37
|
-
everyArray, someArray, appendArray, copyArray, join,
|
|
45
|
+
everyArray, someArray, appendArray, copyArray, join, sliceString, endsWith,
|
|
46
|
+
bufferConcat, bufferIsBuffer, bufferToString,
|
|
47
|
+
Reflect: privateReflect, promiseResolve, promiseReject } = moduleRuntimeIntrinsics
|
|
38
48
|
const PublicPromise = globalThis.Promise
|
|
39
49
|
const jsonStringify = globalThis.JSON.stringify
|
|
40
50
|
const bufferByteLength = globalThis.Buffer.byteLength
|
|
@@ -195,6 +205,7 @@ registerHooks({
|
|
|
195
205
|
const logScope = createPrivateAsyncLocalStorage()
|
|
196
206
|
const userBindingActivationScope = createPrivateAsyncLocalStorage()
|
|
197
207
|
const pending = new Map()
|
|
208
|
+
const pendingOutputStarts = new Map()
|
|
198
209
|
const installedGlobals = new Set()
|
|
199
210
|
const installedGlobalOriginals = new Map()
|
|
200
211
|
const PROCESS_CONTROLS = setFromArray(['exit', 'abort', 'kill', 'chdir'])
|
|
@@ -252,14 +263,32 @@ class CellReturn extends Error {
|
|
|
252
263
|
evaluationScope.getStore().completed = true
|
|
253
264
|
}
|
|
254
265
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
266
|
+
/**
|
|
267
|
+
* Convert one captured descriptor chunk with plugin-private operations.
|
|
268
|
+
*
|
|
269
|
+
* The private Writable decodes string writes into Buffers, and a cell may
|
|
270
|
+
* replace `Buffer.prototype.toString` or a typed-array join. Converting here
|
|
271
|
+
* with captured operations keeps the model-visible log record from running user
|
|
272
|
+
* code that could rewrite, forge, or fail the logs of the cell that printed
|
|
273
|
+
* them.
|
|
274
|
+
*/
|
|
275
|
+
function outputText(chunk) {
|
|
276
|
+
if (typeof chunk === 'string') return chunk
|
|
277
|
+
// The private Writable hands over Buffers, and a direct write may pass any
|
|
278
|
+
// Uint8Array view. Any other chunk type fails in the captured conversion,
|
|
279
|
+
// exactly as the replaced stream method would reject it.
|
|
280
|
+
return bufferToString(bufferIsBuffer(chunk) ? chunk : bufferConcat([chunk]), 'utf8')
|
|
259
281
|
}
|
|
260
282
|
|
|
261
283
|
function appendText(current, text) {
|
|
262
|
-
if (current.open !== true
|
|
284
|
+
if (current.open !== true) {
|
|
285
|
+
if (!current.lateOutputReported) {
|
|
286
|
+
current.lateOutputReported = true
|
|
287
|
+
channel.postMessage({ type: 'late-output', id: current.id })
|
|
288
|
+
}
|
|
289
|
+
return
|
|
290
|
+
}
|
|
291
|
+
if (current.outputLimited) return
|
|
263
292
|
const bytes = bufferByteLength(jsonStringify(text), 'utf8') + (current.logs.length === 0 ? 0 : 1)
|
|
264
293
|
if (current.logBytes + bytes > current.maxOutputBytes) {
|
|
265
294
|
current.outputLimited = true
|
|
@@ -270,26 +299,39 @@ function appendText(current, text) {
|
|
|
270
299
|
appendArray(current.logs, text)
|
|
271
300
|
}
|
|
272
301
|
|
|
273
|
-
const
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
302
|
+
const consoleOutput = new Writable({
|
|
303
|
+
write(chunk, _encoding, callback) {
|
|
304
|
+
const current = logScope.getStore()
|
|
305
|
+
if (current !== undefined) {
|
|
306
|
+
const text = outputText(chunk)
|
|
307
|
+
appendText(current, endsWith(text, '\n') ? sliceString(text, 0, -1) : text)
|
|
308
|
+
}
|
|
309
|
+
callback()
|
|
310
|
+
},
|
|
311
|
+
})
|
|
312
|
+
const nativeStdoutWrite = process.stdout.write.bind(process.stdout)
|
|
313
|
+
const nativeStderrWrite = process.stderr.write.bind(process.stderr)
|
|
314
|
+
const consoleView = new Console({
|
|
315
|
+
stdout: consoleOutput,
|
|
316
|
+
stderr: consoleOutput,
|
|
317
|
+
colorMode: false,
|
|
318
|
+
inspectOptions: { depth: 4, maxArrayLength: 100, maxStringLength: 10_000 },
|
|
280
319
|
})
|
|
281
|
-
|
|
320
|
+
defineWorkerRealmProperty(WORKER_REALM_MUTATION.STABLE, 'console',
|
|
321
|
+
context, 'console', { configurable: true, value: consoleView })
|
|
282
322
|
|
|
283
323
|
function captureWrite(chunk, ...rest) {
|
|
284
324
|
const current = logScope.getStore()
|
|
285
|
-
if (current
|
|
325
|
+
if (current !== undefined) appendText(current, outputText(chunk))
|
|
286
326
|
const callback = typeof rest[0] === 'function' ? rest[0]
|
|
287
327
|
: typeof rest[1] === 'function' ? rest[1] : undefined
|
|
288
328
|
if (callback !== undefined) queueMicrotask(() => callback(null))
|
|
289
329
|
return true
|
|
290
330
|
}
|
|
291
|
-
process.stdout.write
|
|
292
|
-
process.
|
|
331
|
+
assignWorkerRealmProperty(WORKER_REALM_MUTATION.STABLE, 'process.stdout.write/process.stderr.write',
|
|
332
|
+
process.stdout, 'write', captureWrite)
|
|
333
|
+
assignWorkerRealmProperty(WORKER_REALM_MUTATION.STABLE, 'process.stdout.write/process.stderr.write',
|
|
334
|
+
process.stderr, 'write', captureWrite)
|
|
293
335
|
|
|
294
336
|
function markVolatile(reason) {
|
|
295
337
|
const current = activeExecution
|
|
@@ -307,23 +349,7 @@ function completionDurability(execution) {
|
|
|
307
349
|
}
|
|
308
350
|
}
|
|
309
351
|
|
|
310
|
-
|
|
311
|
-
const properties = setValuesArray(PROCESS_CONTROLS)
|
|
312
|
-
for (let index = 0; index < properties.length; index += 1) {
|
|
313
|
-
const property = properties[index]
|
|
314
|
-
const descriptor = Object.getOwnPropertyDescriptor(process, property)
|
|
315
|
-
Object.defineProperty(process, property, {
|
|
316
|
-
configurable: false,
|
|
317
|
-
enumerable: descriptor?.enumerable ?? true,
|
|
318
|
-
writable: false,
|
|
319
|
-
value: () => {
|
|
320
|
-
throw new Error(`process.${property} is forbidden inside the REPL kernel`)
|
|
321
|
-
},
|
|
322
|
-
})
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
guardProcessControls()
|
|
352
|
+
installProcessControlGuards(process, setValuesArray(PROCESS_CONTROLS))
|
|
327
353
|
installWorkerCwdVirtualization(sessionCwd, originalRequire, reason => {
|
|
328
354
|
if (suppressReplCwdObservation) {
|
|
329
355
|
suppressReplCwdObservation = false
|
|
@@ -340,7 +366,7 @@ function selectProvidedRequire(args) {
|
|
|
340
366
|
return managedRequire(activeExecution?.languageSemantics === 'legacy-v1' ? replParent : sessionReplParent ?? replParent,
|
|
341
367
|
activeExecution?.languageSemantics === 'legacy-v1' ? originalRequire : providedRequire)
|
|
342
368
|
}
|
|
343
|
-
|
|
369
|
+
defineWorkerRealmProperty(WORKER_REALM_MUTATION.STABLE, 'cell module metadata', context, 'require', {
|
|
344
370
|
configurable: true,
|
|
345
371
|
value: new Proxy(providedRequire, {
|
|
346
372
|
apply: (_, receiver, args) => privateReflect.apply(selectProvidedRequire(args), receiver, args),
|
|
@@ -393,13 +419,16 @@ async function verifyEvaluation() {
|
|
|
393
419
|
await evaluate(CONFORMANCE_CELL)
|
|
394
420
|
const marker = new Error('PTC Plus REPL settlement probe')
|
|
395
421
|
Object.defineProperty(marker, 'stack', { get() { throw new Error('REPL must not format an error before settlement') } })
|
|
396
|
-
|
|
397
|
-
|
|
422
|
+
assignWorkerRealmProperty(WORKER_REALM_MUTATION.TEMPORARY, undefined,
|
|
423
|
+
context, '__ptc_settlement_probe__', marker)
|
|
424
|
+
assignWorkerRealmProperty(WORKER_REALM_MUTATION.TEMPORARY, undefined,
|
|
425
|
+
context, '__ptc_completion_probe__', CellReturn)
|
|
398
426
|
try {
|
|
399
427
|
const values = [marker, null, undefined, false, 0]
|
|
400
428
|
for (let valueIndex = 0; valueIndex < values.length; valueIndex += 1) {
|
|
401
429
|
const value = values[valueIndex]
|
|
402
|
-
|
|
430
|
+
assignWorkerRealmProperty(WORKER_REALM_MUTATION.TEMPORARY, undefined,
|
|
431
|
+
context, '__ptc_settlement_probe__', value)
|
|
403
432
|
const sources = ['throw __ptc_settlement_probe__', 'await Promise.reject(__ptc_settlement_probe__)']
|
|
404
433
|
for (let sourceIndex = 0; sourceIndex < sources.length; sourceIndex += 1) {
|
|
405
434
|
const source = sources[sourceIndex]
|
|
@@ -414,7 +443,8 @@ async function verifyEvaluation() {
|
|
|
414
443
|
let syntaxRejected = false
|
|
415
444
|
try { await evaluate('const =') } catch (error) { syntaxRejected = error?.name === 'SyntaxError' }
|
|
416
445
|
if (!syntaxRejected) throw new Error('REPL did not preserve syntax failure')
|
|
417
|
-
|
|
446
|
+
assignWorkerRealmProperty(WORKER_REALM_MUTATION.TEMPORARY, undefined,
|
|
447
|
+
context, '__ptc_settlement_probe__', new CellReturn(promiseResolve(marker)))
|
|
418
448
|
const returned = await evaluate('throw __ptc_settlement_probe__')
|
|
419
449
|
if (!returned.hasValue || returned.value !== marker) throw new Error('REPL did not preserve cell return')
|
|
420
450
|
await evaluate(CONFORMANCE_CELL)
|
|
@@ -422,8 +452,10 @@ async function verifyEvaluation() {
|
|
|
422
452
|
const expression = await evaluate('42', '__ptc_completion_probe__')
|
|
423
453
|
if (expression.value !== 42) throw new Error('REPL did not preserve expression completion')
|
|
424
454
|
} finally {
|
|
425
|
-
|
|
426
|
-
|
|
455
|
+
deleteWorkerRealmProperty(WORKER_REALM_MUTATION.RESTORE, undefined,
|
|
456
|
+
context, '__ptc_settlement_probe__')
|
|
457
|
+
deleteWorkerRealmProperty(WORKER_REALM_MUTATION.RESTORE, undefined,
|
|
458
|
+
context, '__ptc_completion_probe__')
|
|
427
459
|
}
|
|
428
460
|
}
|
|
429
461
|
|
|
@@ -578,7 +610,7 @@ function namespaceGlobalGetter(name) {
|
|
|
578
610
|
}
|
|
579
611
|
|
|
580
612
|
function installNamespaceGlobal(name) {
|
|
581
|
-
|
|
613
|
+
defineWorkerRealmProperty(WORKER_REALM_MUTATION.PROGRAM, undefined, globalThis, name, {
|
|
582
614
|
configurable: true,
|
|
583
615
|
get: namespaceGlobalGetter(name),
|
|
584
616
|
})
|
|
@@ -616,7 +648,9 @@ function restoreDynamicNamespaceGlobals() {
|
|
|
616
648
|
const names = mapKeysArray(originalDynamicNamespaceGlobals)
|
|
617
649
|
for (let index = 0; index < names.length; index += 1) {
|
|
618
650
|
const name = names[index]
|
|
619
|
-
setHas(installedGlobals, name)
|
|
651
|
+
setHas(installedGlobals, name)
|
|
652
|
+
? installNamespaceGlobal(name)
|
|
653
|
+
: deleteWorkerRealmProperty(WORKER_REALM_MUTATION.RESTORE, undefined, globalThis, name)
|
|
620
654
|
}
|
|
621
655
|
mapClear(originalDynamicNamespaceGlobals)
|
|
622
656
|
}
|
|
@@ -634,9 +668,13 @@ function installBindings(message) {
|
|
|
634
668
|
} else if (original.userGlobalEntryId !== undefined
|
|
635
669
|
&& (mapGet(userBindingNames, name) !== original.userGlobalEntryId
|
|
636
670
|
|| attachment !== original.attachment)) {
|
|
637
|
-
|
|
638
|
-
} else if (original.descriptor === undefined)
|
|
639
|
-
|
|
671
|
+
deleteWorkerRealmProperty(WORKER_REALM_MUTATION.RESTORE, undefined, context, name)
|
|
672
|
+
} else if (original.descriptor === undefined) {
|
|
673
|
+
deleteWorkerRealmProperty(WORKER_REALM_MUTATION.RESTORE, undefined, context, name)
|
|
674
|
+
} else {
|
|
675
|
+
defineWorkerRealmProperty(WORKER_REALM_MUTATION.RESTORE, undefined,
|
|
676
|
+
context, name, original.descriptor)
|
|
677
|
+
}
|
|
640
678
|
}
|
|
641
679
|
setClear(installedGlobals)
|
|
642
680
|
mapClear(installedGlobalOriginals)
|
|
@@ -692,7 +730,8 @@ function installBindings(message) {
|
|
|
692
730
|
|
|
693
731
|
if (descriptor !== undefined) {
|
|
694
732
|
mapSet(installedGlobalOriginals, descriptor.name, capturedGlobalDescriptor(descriptor.name))
|
|
695
|
-
|
|
733
|
+
defineWorkerRealmProperty(WORKER_REALM_MUTATION.PROGRAM, undefined,
|
|
734
|
+
context, descriptor.name, { configurable: true, value: BoundError })
|
|
696
735
|
setAdd(installedGlobals, descriptor.name)
|
|
697
736
|
}
|
|
698
737
|
}
|
|
@@ -751,14 +790,18 @@ function rootBindingStorage(name, nativeLexical = false) {
|
|
|
751
790
|
}
|
|
752
791
|
let propertyRead = false
|
|
753
792
|
try {
|
|
754
|
-
|
|
793
|
+
defineWorkerRealmProperty(WORKER_REALM_MUTATION.TEMPORARY, undefined,
|
|
794
|
+
context, name, { configurable: true, get() { propertyRead = true } })
|
|
755
795
|
runInWorkerReplRealm(name, { displayErrors: false })
|
|
756
796
|
return propertyRead ? 'property' : 'lexical'
|
|
757
797
|
} catch {
|
|
758
798
|
return 'unknown'
|
|
759
799
|
} finally {
|
|
760
|
-
if (original === undefined)
|
|
761
|
-
|
|
800
|
+
if (original === undefined) {
|
|
801
|
+
deleteWorkerRealmProperty(WORKER_REALM_MUTATION.RESTORE, undefined, context, name)
|
|
802
|
+
} else {
|
|
803
|
+
defineWorkerRealmProperty(WORKER_REALM_MUTATION.RESTORE, undefined, context, name, original)
|
|
804
|
+
}
|
|
762
805
|
}
|
|
763
806
|
}
|
|
764
807
|
|
|
@@ -806,7 +849,9 @@ function removePerNameUserBindingEntry(id) {
|
|
|
806
849
|
if (setHas(installedGlobals, name)) {
|
|
807
850
|
const original = mapGet(installedGlobalOriginals, name)
|
|
808
851
|
if (original.attachment === installed) original.descriptor = undefined
|
|
809
|
-
} else if (descriptorsEqual(Object.getOwnPropertyDescriptor(context, name), installed))
|
|
852
|
+
} else if (descriptorsEqual(Object.getOwnPropertyDescriptor(context, name), installed)) {
|
|
853
|
+
deleteWorkerRealmProperty(WORKER_REALM_MUTATION.RESTORE, undefined, context, name)
|
|
854
|
+
}
|
|
810
855
|
// Lifecycle removal permits reattachment; explicit deletion retains absent.
|
|
811
856
|
mapDelete(userBindingSources, name)
|
|
812
857
|
}
|
|
@@ -892,13 +937,14 @@ async function activatePerNameUserBindings(snapshot, shadowedNames, cwd, reusePo
|
|
|
892
937
|
const source = mapGet(userBindingSources, name)
|
|
893
938
|
if (source !== undefined && source.state !== 'provider') continue
|
|
894
939
|
const descriptor = Object.getOwnPropertyDescriptor(context, name)
|
|
895
|
-
|
|
940
|
+
defineWorkerRealmProperty(WORKER_REALM_MUTATION.USER, undefined, context, name, {
|
|
896
941
|
configurable: true,
|
|
897
942
|
enumerable: true,
|
|
898
943
|
get: () => entry.scope === 'namespace' ? view : namespace[name],
|
|
899
944
|
set(value) {
|
|
900
945
|
const receiver = this === contextGlobal ? context : this
|
|
901
|
-
|
|
946
|
+
defineWorkerRealmProperty(WORKER_REALM_MUTATION.USER, undefined,
|
|
947
|
+
receiver, name, { configurable: true, enumerable: true, writable: true, value })
|
|
902
948
|
if (receiver === context) recordUserBindingAssignment(name)
|
|
903
949
|
},
|
|
904
950
|
})
|
|
@@ -916,8 +962,13 @@ async function activatePerNameUserBindings(snapshot, shadowedNames, cwd, reusePo
|
|
|
916
962
|
for (let index = installedNames.length - 1; index >= 0; index--) {
|
|
917
963
|
const installed = installedNames[index]
|
|
918
964
|
mapDelete(userBindingNames, installed.name)
|
|
919
|
-
if (installed.descriptor === undefined)
|
|
920
|
-
|
|
965
|
+
if (installed.descriptor === undefined) {
|
|
966
|
+
deleteWorkerRealmProperty(WORKER_REALM_MUTATION.RESTORE, undefined,
|
|
967
|
+
context, installed.name)
|
|
968
|
+
} else {
|
|
969
|
+
defineWorkerRealmProperty(WORKER_REALM_MUTATION.RESTORE, undefined,
|
|
970
|
+
context, installed.name, installed.descriptor)
|
|
971
|
+
}
|
|
921
972
|
}
|
|
922
973
|
const previousEntries = mapEntriesArray(previousSources)
|
|
923
974
|
for (let previousIndex = 0; previousIndex < previousEntries.length; previousIndex += 1) {
|
|
@@ -941,7 +992,9 @@ function removeUserBindingEntry(id, shadowedNames) {
|
|
|
941
992
|
const name = previous.names[index]
|
|
942
993
|
if (mapGet(userBindingNames, name) !== id) continue
|
|
943
994
|
mapDelete(userBindingNames, name)
|
|
944
|
-
if (!setHas(shadowedNames, name))
|
|
995
|
+
if (!setHas(shadowedNames, name)) {
|
|
996
|
+
deleteWorkerRealmProperty(WORKER_REALM_MUTATION.RESTORE, undefined, context, name)
|
|
997
|
+
}
|
|
945
998
|
}
|
|
946
999
|
mapDelete(userBindingEntries, id)
|
|
947
1000
|
}
|
|
@@ -1070,13 +1123,13 @@ async function activateUserBindings(snapshot, shadowedNames, cwd, reusePolicy, i
|
|
|
1070
1123
|
}
|
|
1071
1124
|
Object.freeze(view)
|
|
1072
1125
|
const descriptor = Object.getOwnPropertyDescriptor(context, entry.name)
|
|
1073
|
-
|
|
1126
|
+
defineWorkerRealmProperty(WORKER_REALM_MUTATION.USER, undefined, context, entry.name, {
|
|
1074
1127
|
configurable: true,
|
|
1075
1128
|
enumerable: true,
|
|
1076
1129
|
get: () => view,
|
|
1077
1130
|
set(value) {
|
|
1078
1131
|
recordUserBindingAssignment(entry.name, true)
|
|
1079
|
-
|
|
1132
|
+
defineWorkerRealmProperty(WORKER_REALM_MUTATION.USER, undefined, context, entry.name, {
|
|
1080
1133
|
configurable: true,
|
|
1081
1134
|
enumerable: true,
|
|
1082
1135
|
writable: true,
|
|
@@ -1094,13 +1147,13 @@ async function activateUserBindings(snapshot, shadowedNames, cwd, reusePolicy, i
|
|
|
1094
1147
|
for (let symbolIndex = 0; symbolIndex < entry.symbols.length; symbolIndex += 1) {
|
|
1095
1148
|
const symbol = entry.symbols[symbolIndex]
|
|
1096
1149
|
const descriptor = Object.getOwnPropertyDescriptor(context, symbol)
|
|
1097
|
-
|
|
1150
|
+
defineWorkerRealmProperty(WORKER_REALM_MUTATION.USER, undefined, context, symbol, {
|
|
1098
1151
|
configurable: true,
|
|
1099
1152
|
enumerable: true,
|
|
1100
1153
|
get: () => namespace[symbol],
|
|
1101
1154
|
set(value) {
|
|
1102
1155
|
recordUserBindingAssignment(symbol, true)
|
|
1103
|
-
|
|
1156
|
+
defineWorkerRealmProperty(WORKER_REALM_MUTATION.USER, undefined, context, symbol, {
|
|
1104
1157
|
configurable: true,
|
|
1105
1158
|
enumerable: true,
|
|
1106
1159
|
writable: true,
|
|
@@ -1130,8 +1183,13 @@ async function activateUserBindings(snapshot, shadowedNames, cwd, reusePolicy, i
|
|
|
1130
1183
|
for (let index = installedNames.length - 1; index >= 0; index--) {
|
|
1131
1184
|
const installed = installedNames[index]
|
|
1132
1185
|
mapDelete(userBindingNames, installed.name)
|
|
1133
|
-
if (installed.descriptor === undefined)
|
|
1134
|
-
|
|
1186
|
+
if (installed.descriptor === undefined) {
|
|
1187
|
+
deleteWorkerRealmProperty(WORKER_REALM_MUTATION.RESTORE, undefined,
|
|
1188
|
+
context, installed.name)
|
|
1189
|
+
} else {
|
|
1190
|
+
defineWorkerRealmProperty(WORKER_REALM_MUTATION.RESTORE, undefined,
|
|
1191
|
+
context, installed.name, installed.descriptor)
|
|
1192
|
+
}
|
|
1135
1193
|
}
|
|
1136
1194
|
if (evaluated !== undefined) mapDelete(userBindingModuleParents, evaluated.moduleUrl)
|
|
1137
1195
|
removeUserBindingEntry(entry.id, shadowedNames)
|
|
@@ -1147,7 +1205,6 @@ async function activateUserBindings(snapshot, shadowedNames, cwd, reusePolicy, i
|
|
|
1147
1205
|
|
|
1148
1206
|
async function closeExecution(execution) {
|
|
1149
1207
|
activeRun = undefined
|
|
1150
|
-
execution.open = false
|
|
1151
1208
|
const settling = []
|
|
1152
1209
|
mapForEach(pending, call => {
|
|
1153
1210
|
if (call.runId === execution.id) appendArray(settling, call.settled)
|
|
@@ -1199,7 +1256,13 @@ function refreshLegacyPublication(name) {
|
|
|
1199
1256
|
}
|
|
1200
1257
|
}
|
|
1201
1258
|
|
|
1202
|
-
function
|
|
1259
|
+
function writeOutputFence(write, marker) {
|
|
1260
|
+
return new ControlPromise((resolve, reject) => {
|
|
1261
|
+
write(marker, error => error === null || error === undefined ? resolve() : reject(error))
|
|
1262
|
+
})
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
async function sendCompletion(message, execution, userBindings, committedRedeclarations, outcome) {
|
|
1203
1266
|
const publicationNames = execution.nativePublications === undefined
|
|
1204
1267
|
? [] : mapKeysArray(execution.nativePublications)
|
|
1205
1268
|
for (let index = 0; index < publicationNames.length; index += 1) refreshLegacyPublication(publicationNames[index])
|
|
@@ -1208,9 +1271,18 @@ function sendCompletion(message, execution, userBindings, committedRedeclaration
|
|
|
1208
1271
|
if (perName) reconcileUserBindingNames()
|
|
1209
1272
|
else reconcileUserBindingShadows(shadowedNames)
|
|
1210
1273
|
const names = message.observeNames ?? []
|
|
1274
|
+
await writeOutputFence(nativeStdoutWrite, outputFenceMarker(message.outputFence, 'stdout', 'end'))
|
|
1275
|
+
await writeOutputFence(nativeStderrWrite, outputFenceMarker(message.outputFence, 'stderr', 'end'))
|
|
1276
|
+
// Program-call settlement and value encoding belong to this physical run, so
|
|
1277
|
+
// structured output from a drained continuation keeps its cell ownership
|
|
1278
|
+
// until this completion is posted. Output from the same scheduling execution
|
|
1279
|
+
// after this point is background output and carries the attribution
|
|
1280
|
+
// diagnostic instead of being attached to a later cell.
|
|
1281
|
+
execution.open = false
|
|
1211
1282
|
channel.postMessage({
|
|
1212
1283
|
type: 'done',
|
|
1213
1284
|
id: message.id,
|
|
1285
|
+
outputFence: message.outputFence,
|
|
1214
1286
|
logs: execution.logs,
|
|
1215
1287
|
...completionDurability(execution),
|
|
1216
1288
|
committedRedeclarations: setValuesArray(committedRedeclarations),
|
|
@@ -1234,6 +1306,12 @@ function sendCompletion(message, execution, userBindings, committedRedeclaration
|
|
|
1234
1306
|
|
|
1235
1307
|
async function runCell(message) {
|
|
1236
1308
|
if (activeExecution !== undefined) throw new Error('kernel received overlapping cells')
|
|
1309
|
+
await writeOutputFence(nativeStdoutWrite, outputFenceMarker(message.outputFence, 'stdout', 'start'))
|
|
1310
|
+
await writeOutputFence(nativeStderrWrite, outputFenceMarker(message.outputFence, 'stderr', 'start'))
|
|
1311
|
+
await new ControlPromise(resolve => {
|
|
1312
|
+
mapSet(pendingOutputStarts, message.id, { outputFence: message.outputFence, resolve })
|
|
1313
|
+
channel.postMessage({ type: 'output-start', id: message.id, outputFence: message.outputFence })
|
|
1314
|
+
})
|
|
1237
1315
|
activeRun = message.id
|
|
1238
1316
|
const execution = {
|
|
1239
1317
|
id: message.id,
|
|
@@ -1263,12 +1341,12 @@ async function runCell(message) {
|
|
|
1263
1341
|
try {
|
|
1264
1342
|
completion = await logScope.run(execution, async () => {
|
|
1265
1343
|
const namespaceError = installBindings(message)
|
|
1266
|
-
|
|
1344
|
+
defineWorkerRealmProperty(WORKER_REALM_MUTATION.TEMPORARY, undefined, context, message.returnSignal, {
|
|
1267
1345
|
configurable: true,
|
|
1268
1346
|
value: CellReturn,
|
|
1269
1347
|
})
|
|
1270
1348
|
appendArray(cellGlobals, message.returnSignal)
|
|
1271
|
-
|
|
1349
|
+
defineWorkerRealmProperty(WORKER_REALM_MUTATION.TEMPORARY, undefined, context, message.commitSignal, {
|
|
1272
1350
|
configurable: true,
|
|
1273
1351
|
value(name) {
|
|
1274
1352
|
setAdd(committedRedeclarations, name)
|
|
@@ -1286,7 +1364,8 @@ async function runCell(message) {
|
|
|
1286
1364
|
return storage === 'lexical' || setHas(legacyNative, name)
|
|
1287
1365
|
&& (storage === 'local' || storage === 'property') && writableRootProperty(name)
|
|
1288
1366
|
})
|
|
1289
|
-
|
|
1367
|
+
defineWorkerRealmProperty(WORKER_REALM_MUTATION.TEMPORARY, undefined,
|
|
1368
|
+
context, message.rootRuntimeName, {
|
|
1290
1369
|
configurable: true,
|
|
1291
1370
|
value: statefulRoots.begin({ ...message.rootBindings,
|
|
1292
1371
|
legacyLexicals,
|
|
@@ -1324,7 +1403,7 @@ async function runCell(message) {
|
|
|
1324
1403
|
throw new StaticImportFailure(error, load.position)
|
|
1325
1404
|
}
|
|
1326
1405
|
if (load.global !== undefined) {
|
|
1327
|
-
|
|
1406
|
+
defineWorkerRealmProperty(WORKER_REALM_MUTATION.TEMPORARY, undefined, context, load.global, {
|
|
1328
1407
|
configurable: true,
|
|
1329
1408
|
value: namespace,
|
|
1330
1409
|
})
|
|
@@ -1364,9 +1443,12 @@ async function runCell(message) {
|
|
|
1364
1443
|
outcome = failureOutcome(error, 'encode', message.program)
|
|
1365
1444
|
}
|
|
1366
1445
|
}
|
|
1367
|
-
sendCompletion(message, execution, userBindings, committedRedeclarations, outcome)
|
|
1446
|
+
await sendCompletion(message, execution, userBindings, committedRedeclarations, outcome)
|
|
1368
1447
|
} finally {
|
|
1369
|
-
for (let index = 0; index < cellGlobals.length; index += 1)
|
|
1448
|
+
for (let index = 0; index < cellGlobals.length; index += 1) {
|
|
1449
|
+
deleteWorkerRealmProperty(WORKER_REALM_MUTATION.RESTORE, undefined,
|
|
1450
|
+
context, cellGlobals[index])
|
|
1451
|
+
}
|
|
1370
1452
|
activeRun = undefined
|
|
1371
1453
|
activeExecution = undefined
|
|
1372
1454
|
execution.exceptionOrigins.close()
|
|
@@ -1415,6 +1497,14 @@ channel.on('message', (message) => {
|
|
|
1415
1497
|
}
|
|
1416
1498
|
return
|
|
1417
1499
|
}
|
|
1500
|
+
if (message?.type === 'output-start-ack') {
|
|
1501
|
+
const pendingStart = mapGet(pendingOutputStarts, message.id)
|
|
1502
|
+
if (pendingStart !== undefined && pendingStart.outputFence === message.outputFence) {
|
|
1503
|
+
mapDelete(pendingOutputStarts, message.id)
|
|
1504
|
+
pendingStart.resolve()
|
|
1505
|
+
}
|
|
1506
|
+
return
|
|
1507
|
+
}
|
|
1418
1508
|
if (message?.type === 'run') void runCell(message)
|
|
1419
1509
|
})
|
|
1420
1510
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Producer identity shared by Host messages and Client history projections. */
|
|
2
|
+
export const PTC_MESSAGE_SOURCE_KIND = 'plugin:ptc-plus'
|
|
3
|
+
|
|
4
|
+
/** Read the current producer identity and its historical pre-migration wrapper. */
|
|
5
|
+
export function isPtcMessageSource(source) {
|
|
6
|
+
return source?.kind === PTC_MESSAGE_SOURCE_KIND
|
|
7
|
+
|| (source?.kind === 'plugin' && source.plugin === 'ptc-plus')
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** DSH owns aggregate runtime-context messages independently of PTC messages. */
|
|
11
|
+
export function isHostRuntimeContextSource(source) {
|
|
12
|
+
return source?.kind === 'runtime-context'
|
|
13
|
+
|| (source?.kind === 'plugin' && source.plugin === '@deepseek-ai/dsh-system-prompt')
|
|
14
|
+
}
|
|
@@ -187,7 +187,7 @@ export function compileStatefulModule(source, {
|
|
|
187
187
|
callableSources = marked.callableSources
|
|
188
188
|
nativeJavaScript = marked.nativeJavaScript
|
|
189
189
|
mapped = marked
|
|
190
|
-
if (!nativeJavaScript) mapped = normalizeTypeScriptValues(mapped.code, mapped.sourceMap, target)
|
|
190
|
+
if (!nativeJavaScript) mapped = normalizeTypeScriptValues(mapped.code, mapped.sourceMap, target, callableSources)
|
|
191
191
|
if (target !== 'commonjs' && (isStatefulUserBindingTransform(transform)
|
|
192
192
|
|| transform === PROTECTED_MODULE_TRANSFORM && hasModuleResources(mapped.code))) {
|
|
193
193
|
mapped = normalizeModuleExports(mapped.code, mapped.sourceMap)
|
|
@@ -199,6 +199,7 @@ export function compileStatefulModule(source, {
|
|
|
199
199
|
? moduleLinkPlan(mapped.code) : undefined
|
|
200
200
|
let normalized = transform === LEGACY_USER_BINDING_TRANSFORM ? mapped
|
|
201
201
|
: normalizeStatefulScopes(mapped.code, mapped.sourceMap, { target, moduleImport: links?.reader, nativeJavaScript, nativeUsing,
|
|
202
|
+
callableSources,
|
|
202
203
|
mode: transform === PROTECTED_MODULE_TRANSFORM ? 'protected-v1' : 'stateful-v1' })
|
|
203
204
|
// Protected entries retain native declaration policy; adapters still need
|
|
204
205
|
// bounded source regions after TypeScript and decorator lowering.
|
|
@@ -26,6 +26,16 @@ const PROJECTION_STATE_FIELDS = new Set(['generation', 'memory', 'pendingReplCal
|
|
|
26
26
|
const PENDING_CALL_FIELDS = new Set(['callId', 'seq'])
|
|
27
27
|
const REPL_MEMORY_META_VERSION = 5
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Bound one definition source to the presentation budget. Producers apply this
|
|
31
|
+
* before a catalog entry can carry more than the validated metadata shape.
|
|
32
|
+
*/
|
|
33
|
+
export function boundedDefinitionSource(source) {
|
|
34
|
+
return source.length <= MAX_DEFINITION_SOURCE_LENGTH
|
|
35
|
+
? source
|
|
36
|
+
: `${source.slice(0, MAX_DEFINITION_SOURCE_LENGTH - 3)}...`
|
|
37
|
+
}
|
|
38
|
+
|
|
29
39
|
function isReuseCount(value) {
|
|
30
40
|
return Number.isSafeInteger(value) && value >= 0
|
|
31
41
|
}
|