@tlockney/cdp-kernel 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +78 -478
  2. package/THIRD-PARTY-NOTICES +62 -0
  3. package/dist/bun-target.d.ts +2 -2
  4. package/dist/bun-target.js +30 -8
  5. package/dist/cdp.d.ts +8 -1
  6. package/dist/cdp.js +31 -11
  7. package/dist/celld-target.d.ts +1 -1
  8. package/dist/celld-target.js +54 -19
  9. package/dist/children.d.ts +29 -0
  10. package/dist/children.js +114 -0
  11. package/dist/debugger.d.ts +1 -1
  12. package/dist/debugger.js +21 -10
  13. package/dist/deno-types.d.ts +30 -0
  14. package/dist/deno-types.js +93 -0
  15. package/dist/globals.d.ts +3 -3
  16. package/dist/globals.js +3 -3
  17. package/dist/kernel.d.ts +7 -1
  18. package/dist/kernel.js +348 -68
  19. package/dist/language-service-worker.d.ts +1 -0
  20. package/dist/language-service-worker.js +88 -0
  21. package/dist/language-service.d.ts +64 -0
  22. package/dist/language-service.js +128 -0
  23. package/dist/main.js +102 -8
  24. package/dist/mod.d.ts +6 -3
  25. package/dist/mod.js +6 -3
  26. package/dist/notebook-types.d.ts +62 -0
  27. package/dist/notebook-types.js +310 -0
  28. package/dist/package.d.ts +2 -2
  29. package/dist/package.js +3 -3
  30. package/dist/parent.d.ts +12 -0
  31. package/dist/parent.js +39 -0
  32. package/dist/port-holder.d.ts +13 -0
  33. package/dist/port-holder.js +105 -0
  34. package/dist/sourcemap.d.ts +7 -2
  35. package/dist/sourcemap.js +9 -3
  36. package/dist/strip-esbuild.d.ts +2 -0
  37. package/dist/strip-esbuild.js +44 -0
  38. package/dist/strip-sucrase.d.ts +2 -0
  39. package/dist/strip-sucrase.js +78 -0
  40. package/dist/target.d.ts +58 -6
  41. package/dist/target.js +412 -54
  42. package/dist/text.d.ts +5 -1
  43. package/dist/text.js +55 -2
  44. package/dist/transform.d.ts +30 -1
  45. package/dist/transform.js +68 -44
  46. package/dist/wire.d.ts +8 -1
  47. package/dist/wire.js +3 -1
  48. package/dist/workerd-target.d.ts +7 -1
  49. package/dist/workerd-target.js +102 -8
  50. package/dist/workers-project.js +13 -2
  51. package/dist/ws-client.d.ts +5 -1
  52. package/dist/ws-client.js +46 -13
  53. package/dist/zmtp.d.ts +9 -1
  54. package/dist/zmtp.js +42 -1
  55. package/package.json +17 -6
  56. package/runtime/bootstrap.mjs +233 -42
  57. package/runtime/bun-channel.d.mts +3 -0
  58. package/runtime/bun-channel.mjs +2 -2
  59. package/runtime/comm.mjs +11 -1
  60. package/runtime/deno-compat.d.mts +2 -0
  61. package/runtime/deno-compat.mjs +14 -1
  62. package/runtime/display.mjs +8 -1
  63. package/runtime/introspect.mjs +1 -1
  64. package/runtime/node-hooks.d.mts +48 -0
  65. package/runtime/node-hooks.mjs +257 -41
  66. package/runtime/workerd-worker.mjs +77 -6
@@ -0,0 +1,78 @@
1
+ // A type stripper in plain JavaScript, for a kernel host that can't run
2
+ // esbuild's native binary or WebAssembly (#234). sucrase is an optional
3
+ // dependency, imported only when a kernel picks it (see loadTypeStripper).
4
+ //
5
+ // sucrase removes types without parsing them fully or lowering anything,
6
+ // and keeps every line where it was. What it leaves alone, a cell can't
7
+ // use: decorators and `accessor` fields (which acorn and V8 don't parse
8
+ // yet, #142) and namespaces with values (which it drops), so those are
9
+ // rejected here with a clear error.
10
+ import { parse } from "acorn";
11
+ import { transform } from "sucrase";
12
+ import { CellSyntaxError } from "./transform.js";
13
+ const FILE = "cell.tsx";
14
+ function jsxSettings(options) {
15
+ const jsx = options.jsx;
16
+ if (jsx?.mode === "automatic") {
17
+ return { jsxRuntime: "automatic", jsxImportSource: jsx.importSource, production: !jsx.development };
18
+ }
19
+ return {
20
+ jsxRuntime: "classic",
21
+ jsxPragma: jsx?.factory ?? "React.createElement",
22
+ jsxFragmentPragma: jsx?.fragment ?? "React.Fragment",
23
+ production: true,
24
+ };
25
+ }
26
+ // A namespace that isn't `declare`d: sucrase drops it, values and all.
27
+ const NAMESPACE = /^[ \t]*(?:export\s+)?(?:namespace|module)\s+[\w$.]+\s*\{/m;
28
+ /** A clearer error than acorn's for syntax sucrase leaves in the output. */
29
+ function unsupported(js) {
30
+ if (!js.includes("@") && !js.includes("accessor"))
31
+ return null;
32
+ try {
33
+ parse(js, { ecmaVersion: "latest", sourceType: "module", allowAwaitOutsideFunction: true });
34
+ return null;
35
+ }
36
+ catch (err) {
37
+ const pos = err.pos;
38
+ if (typeof pos !== "number")
39
+ return null;
40
+ if (js[pos] === "@")
41
+ return "decorators are not supported with the sucrase type stripper";
42
+ if (/\baccessor\s*$/.test(js.slice(0, pos)))
43
+ return "accessor fields are not supported with the sucrase type stripper";
44
+ return null;
45
+ }
46
+ }
47
+ export const stripTypes = (code, options, sourcemap) => {
48
+ if (NAMESPACE.test(code)) {
49
+ throw new CellSyntaxError("namespaces are not supported with the sucrase type stripper; use declare namespace for types only");
50
+ }
51
+ // Like the esbuild stripper: prefer TSX, fall back to TS for `<T>x`
52
+ // assertions.
53
+ let firstError;
54
+ for (const transforms of [["typescript", "jsx"], ["typescript"]]) {
55
+ try {
56
+ const result = transform(code, {
57
+ transforms: [...transforms],
58
+ ...jsxSettings(options),
59
+ // As verbatimModuleSyntax: only `import type` goes.
60
+ keepUnusedImports: true,
61
+ disableESTransforms: true,
62
+ filePath: FILE,
63
+ ...(sourcemap ? { sourceMapOptions: { compiledFilename: FILE } } : {}),
64
+ });
65
+ const reason = unsupported(result.code);
66
+ if (reason !== null)
67
+ throw new CellSyntaxError(reason);
68
+ return { code: result.code, mappings: result.sourceMap?.mappings ?? "" };
69
+ }
70
+ catch (err) {
71
+ if (err instanceof CellSyntaxError)
72
+ throw err;
73
+ firstError ??= err;
74
+ }
75
+ }
76
+ const message = firstError instanceof Error ? firstError.message : String(firstError);
77
+ throw new CellSyntaxError(message.replace(`Error transforming ${FILE}: `, ""));
78
+ };
package/dist/target.d.ts CHANGED
@@ -3,7 +3,7 @@ import { type CellTransformOptions, transformCell } from "./transform.ts";
3
3
  import type { DebugChannel } from "./debugger.ts";
4
4
  /** Targets driven over CDP. */
5
5
  export type CdpRuntime = "node" | "deno";
6
- /** Bun and workerd have their own backends: src/bun-target.ts, src/workerd-target.ts. */
6
+ /** Bun, workerd and celld have their own backends: src/bun-target.ts, src/workerd-target.ts, src/celld-target.ts. */
7
7
  export type RuntimeName = CdpRuntime | "bun" | "workerd" | "celld";
8
8
  /** What the kernel needs from a target runtime. */
9
9
  export interface KernelTarget {
@@ -42,7 +42,12 @@ export interface KernelTarget {
42
42
  inspect(path: string, detail: number): Promise<string | null>;
43
43
  /** The Debugger domain, on targets driven over CDP (#18). */
44
44
  readonly debug?: DebugChannel;
45
- replyInput(value: string | null): void;
45
+ /** Answers the target's pending prompt; `interrupted` makes it throw instead (#121). */
46
+ replyInput(value: string | null, interrupted?: boolean): void;
47
+ /** What the host waits on, for a kernel that has stopped answering (#237). */
48
+ diagnose?(): Promise<CdpParams>;
49
+ /** Lets go of the last cell's result and error, once they are shown (#286). */
50
+ releaseResults?(): Promise<void>;
46
51
  kill(): void;
47
52
  }
48
53
  export interface LaunchOptions {
@@ -56,7 +61,14 @@ export declare function launchCommand(runtime: CdpRuntime, bootstrap: string, {
56
61
  cmd: string;
57
62
  args: string[];
58
63
  };
59
- /** Messages the bootstrap sends through the CDP binding. */
64
+ /**
65
+ * The esbuild binary this host's esbuild runs, for a Node target to compile
66
+ * imported TypeScript Node can't strip (#73); null when it can't be found.
67
+ * Resolved from esbuild's own location, so it's found in a node_modules
68
+ * install and in Deno's npm cache alike.
69
+ */
70
+ export declare function esbuildBinary(resolve?: (specifier: string) => string, platform?: string, arch?: string): string | null;
71
+ /** Messages the bootstrap sends: message records on stdout, or Bun's channel. */
60
72
  export type TargetMessage = {
61
73
  kind: "iopub";
62
74
  msg_type: string;
@@ -70,24 +82,51 @@ export type TargetMessage = {
70
82
  password: boolean;
71
83
  barrier: number;
72
84
  };
85
+ /** The parsed value, or undefined for text that isn't JSON. */
86
+ export declare function parseJson(text: string): unknown;
73
87
  export declare function isTargetMessage(value: unknown): value is TargetMessage;
74
88
  /**
75
89
  * Splits one output pipe into text and barrier markers, and releases them
76
- * in order. A gated marker (one that announces a binding message) pauses
90
+ * in order. A gated marker (one that announces a message) pauses
77
91
  * the pipe until `gate(n)` resolves, i.e. until that message has been
78
92
  * delivered, so later output can't overtake it. A possible partial marker
79
93
  * at the end of a chunk is held back until the next chunk decides it.
94
+ *
95
+ * With `onMessage`, the pipe also carries message records. A record stands
96
+ * where its gated marker would, and pauses the pipe the same way.
80
97
  */
81
98
  export declare class PipeDemux {
82
99
  #private;
83
100
  readonly onText: (text: string) => void;
84
101
  readonly gate: (n: number) => Promise<void>;
85
- constructor(onText: (text: string) => void, gate?: (n: number) => Promise<void>);
102
+ readonly onMessage: ((msg: TargetMessage) => void) | null;
103
+ constructor(onText: (text: string) => void, gate?: (n: number) => Promise<void>, onMessage?: ((msg: TargetMessage) => void) | null);
86
104
  push(chunk: string): void;
87
105
  waitFor(n: number): Promise<void>;
106
+ /** Where the pipe stands, for a state dump (#237). */
107
+ state(): {
108
+ reached: number;
109
+ waitingFor: number[];
110
+ gatedOn: number | null;
111
+ queued: number;
112
+ held: number;
113
+ };
88
114
  /** Release everything (the process died). */
89
115
  close(): void;
90
116
  }
117
+ /**
118
+ * Removes the runtime's own stderr lines (see INSPECTOR_CHATTER) and passes
119
+ * everything else on. A chatter line can arrive split across chunks, so a
120
+ * trailing partial line that could still turn out to be one is held back
121
+ * until its newline arrives; any other partial line passes straight through.
122
+ */
123
+ export declare class StderrFilter {
124
+ #private;
125
+ constructor(runtime: CdpRuntime, emit: (text: string) => void);
126
+ push(chunk: string): void;
127
+ /** Releases a held partial line (the process died). */
128
+ flush(): void;
129
+ }
91
130
  /** Promises keyed by barrier number, resolvable before or after first use. */
92
131
  export declare class Gates {
93
132
  #private;
@@ -118,13 +157,22 @@ export declare class Target implements KernelTarget {
118
157
  executable?: string;
119
158
  denoCompat?: boolean;
120
159
  denoConfig?: string;
160
+ startTimeoutMs?: number;
121
161
  }): Promise<Target>;
122
162
  /** The Debugger domain on this target's session, for src/debugger.ts. */
123
163
  get debug(): DebugChannel;
164
+ /**
165
+ * What the host is waiting on, whether the runtime still evaluates, runs
166
+ * immediates and runs timers, and where its JavaScript is if it is
167
+ * running any, for a kernel that has stopped answering (#237). The probes
168
+ * go over the control session, which no cell holds.
169
+ */
170
+ diagnose(): Promise<CdpParams>;
124
171
  /** Resolves once all output and messages sent so far have been delivered. */
125
172
  flush(): Promise<void>;
126
173
  /** Runs transformed cell code. Rejects with Interrupted after interrupt(). */
127
174
  evaluate(script: string): Promise<EvaluateResult>;
175
+ releaseResults(): Promise<void>;
128
176
  /**
129
177
  * Deno calls IsolateHandle::terminate_execution from another thread. The
130
178
  * CDP equivalent is Runtime.terminateExecution, sent on a second session
@@ -133,6 +181,10 @@ export declare class Target implements KernelTarget {
133
181
  * evaluate is abandoned here and the session stays usable.
134
182
  */
135
183
  interrupt(): Promise<void>;
184
+ /**
185
+ * For synchronous functions. With awaitPromise the inspector would wrap
186
+ * even a plain return value in a promise it holds only weakly (#55).
187
+ */
136
188
  callFunctionOn(functionDeclaration: string, args: CdpParams[]): Promise<CdpParams>;
137
189
  /** The broadcastResult step of Deno's execute flow (jupyter/mod.rs). */
138
190
  broadcastResult(executionCount: number, result: RemoteObject): Promise<void>;
@@ -158,6 +210,6 @@ export declare class Target implements KernelTarget {
158
210
  propertyNames(expression: string): Promise<string[]>;
159
211
  inspect(path: string, detail: number): Promise<string | null>;
160
212
  lexicalNames(): Promise<string[]>;
161
- replyInput(value: string | null): void;
213
+ replyInput(value: string | null, interrupted?: boolean): void;
162
214
  kill(): void;
163
215
  }