dsh-ptc-plus 0.3.1 → 0.3.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 +6 -0
- package/README.md +6 -0
- package/assets/ptc-plus-bindings-en.png +0 -0
- package/assets/ptc-plus-bindings-zh.png +0 -0
- package/client.js +43 -9
- package/docs/adr/0006-rewrite-module-syntax-with-an-ast.md +1 -1
- package/docs/adr/0007-separate-worker-transport-from-session-semantics.md +15 -3
- package/docs/adr/0013-isolate-repl-redeclaration-convenience.md +7 -3
- package/docs/adr/0014-persist-cell-rewrite-policy.md +7 -5
- package/docs/adr/0019-plugin-settings-and-kill-switch.md +3 -3
- package/docs/adr/0021-separate-host-bootstrap-from-session-runtime.md +5 -3
- package/docs/architecture.md +14 -6
- package/docs/client-ui.md +5 -5
- package/docs/durability-design.md +42 -20
- package/docs/program-data-plane.md +6 -0
- package/docs/runtime-reference.md +10 -3
- package/index.js +8 -3
- package/internal/cell-analysis.js +72 -12
- package/internal/cell-rewriter.js +128 -4
- package/internal/config-spec.js +10 -0
- package/internal/edit-transport-owner.js +1 -1
- package/internal/kernel-worker.js +11 -0
- package/internal/repl-convenience.js +94 -6
- package/internal/repl-rewrite-contract.js +15 -0
- package/internal/runtime-config.js +1 -0
- package/internal/session-cell-executor.js +65 -15
- package/internal/session-journal.js +328 -61
- package/internal/session-runtime.js +91 -7
- package/internal/session-state.js +36 -3
- package/package.json +7 -5
- package/src/client-activity.js +38 -9
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
pathToHead,
|
|
8
8
|
reduceStateOperations,
|
|
9
9
|
recoverJournal,
|
|
10
|
+
visibleExecutableCallSeqs,
|
|
10
11
|
} from './session-journal.js'
|
|
11
12
|
import { normalizeBindingDescriptors } from './binding-descriptors.js'
|
|
12
13
|
import { resolveConfig } from './runtime-config.js'
|
|
@@ -41,6 +42,13 @@ function rewritePolicy(config) {
|
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
44
|
|
|
45
|
+
function bindingPolicy(config) {
|
|
46
|
+
return {
|
|
47
|
+
variableRedeclarations: config.looseTopLevelRedeclarations,
|
|
48
|
+
functionClassRedeclarations: config.looseTopLevelFunctionClassRedeclarations,
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
44
52
|
function resolvedRuntimeConfig(config) {
|
|
45
53
|
return Object.freeze(resolveConfig(config))
|
|
46
54
|
}
|
|
@@ -67,12 +75,25 @@ class SessionKernel {
|
|
|
67
75
|
constructor({ config, history, cwd, session, withInitiator }) {
|
|
68
76
|
this.config = config
|
|
69
77
|
this.history = history
|
|
78
|
+
this.initialRecoveryBoundary = history.available === false && history.volatileSuffix.length > 0
|
|
79
|
+
? {
|
|
80
|
+
failedCallSeq: history.volatileSuffix[0].seq,
|
|
81
|
+
frontierCallSeq: history.head === undefined ? null : history.nodes[history.head]?.callSeq ?? null,
|
|
82
|
+
}
|
|
83
|
+
: undefined
|
|
84
|
+
this.surfaceGeneration = undefined
|
|
85
|
+
try {
|
|
86
|
+
this.surfaceGeneration = session?.surface?.replaceGeneration
|
|
87
|
+
} catch {
|
|
88
|
+
this.surfaceGeneration = undefined
|
|
89
|
+
}
|
|
70
90
|
this.cwd = cwd
|
|
71
91
|
this.session = session
|
|
72
92
|
this.withInitiator = withInitiator
|
|
73
93
|
this.durability = durabilityState()
|
|
74
94
|
this.bindingCatalog = new BindingCatalog()
|
|
75
95
|
this.replayed = false
|
|
96
|
+
this.liveCallSeqs = new Set()
|
|
76
97
|
this.recoveryNotice = history.volatileSuffix.length === 0
|
|
77
98
|
? undefined
|
|
78
99
|
: recoveryDiagnostic(history.volatileSuffix.length)
|
|
@@ -136,10 +157,62 @@ class SessionKernel {
|
|
|
136
157
|
}
|
|
137
158
|
|
|
138
159
|
async execute(request, config) {
|
|
139
|
-
const recoveryBoundaries =
|
|
160
|
+
const recoveryBoundaries = this.initialRecoveryBoundary === undefined
|
|
161
|
+
? []
|
|
162
|
+
: [this.initialRecoveryBoundary]
|
|
163
|
+
this.initialRecoveryBoundary = undefined
|
|
140
164
|
const finishResult = result => recoveryBoundaries.length === 0
|
|
141
165
|
? result
|
|
142
166
|
: { ...result, recoveryBoundaries: recoveryBoundaries.map(boundary => ({ ...boundary })) }
|
|
167
|
+
let currentGeneration
|
|
168
|
+
try {
|
|
169
|
+
currentGeneration = this.session?.surface?.replaceGeneration
|
|
170
|
+
} catch {
|
|
171
|
+
currentGeneration = undefined
|
|
172
|
+
}
|
|
173
|
+
if (currentGeneration !== undefined && currentGeneration !== this.surfaceGeneration) {
|
|
174
|
+
this.surfaceGeneration = currentGeneration
|
|
175
|
+
const visibleCallSeqs = visibleExecutableCallSeqs(this.session)
|
|
176
|
+
const contractsLiveState = [...this.liveCallSeqs].some(callSeq => (
|
|
177
|
+
!(visibleCallSeqs instanceof Set) || !visibleCallSeqs.has(callSeq)
|
|
178
|
+
))
|
|
179
|
+
if ((config.durableReplay && !this.replayed) || contractsLiveState) {
|
|
180
|
+
const worker = this.client.worker
|
|
181
|
+
if (worker !== undefined) await this.client.reset(worker)
|
|
182
|
+
this.rollbackToDurable()
|
|
183
|
+
if (config.durableReplay) {
|
|
184
|
+
this.recoveryNotice = undefined
|
|
185
|
+
try {
|
|
186
|
+
this.history = recoverJournal(this.session, request.callSeq, {
|
|
187
|
+
visibleCallSeqs,
|
|
188
|
+
})
|
|
189
|
+
} catch (error) {
|
|
190
|
+
this.history = emptyHistory()
|
|
191
|
+
this.recoveryNotice = recoveryDiagnostic(1)
|
|
192
|
+
this.initialRecoveryBoundary = undefined
|
|
193
|
+
}
|
|
194
|
+
if (this.history.volatileSuffix.length > 0) {
|
|
195
|
+
this.recoveryNotice = recoveryDiagnostic(this.history.volatileSuffix.length)
|
|
196
|
+
}
|
|
197
|
+
this.initialRecoveryBoundary = this.history.available === false && this.history.volatileSuffix.length > 0
|
|
198
|
+
? {
|
|
199
|
+
failedCallSeq: this.history.volatileSuffix[0].seq,
|
|
200
|
+
frontierCallSeq: this.history.head === undefined
|
|
201
|
+
? null
|
|
202
|
+
: this.history.nodes[this.history.head]?.callSeq ?? null,
|
|
203
|
+
}
|
|
204
|
+
: undefined
|
|
205
|
+
if (this.initialRecoveryBoundary !== undefined) {
|
|
206
|
+
recoveryBoundaries.push(this.initialRecoveryBoundary)
|
|
207
|
+
this.initialRecoveryBoundary = undefined
|
|
208
|
+
}
|
|
209
|
+
} else {
|
|
210
|
+
this.history = emptyHistory()
|
|
211
|
+
this.replayed = true
|
|
212
|
+
this.recoveryNotice = recoveryDiagnostic(1)
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
143
216
|
if (!this.replayed && config.durableReplay) {
|
|
144
217
|
let skipped = 0
|
|
145
218
|
while (!this.replayed) {
|
|
@@ -175,6 +248,7 @@ class SessionKernel {
|
|
|
175
248
|
}
|
|
176
249
|
const recovered = recoverJournal(this.session, request.callSeq, {
|
|
177
250
|
extraBoundaries: [boundary],
|
|
251
|
+
visibleCallSeqs: visibleExecutableCallSeqs(this.session),
|
|
178
252
|
})
|
|
179
253
|
recoveryBoundaries.push(boundary)
|
|
180
254
|
this.history = recovered
|
|
@@ -245,6 +319,7 @@ class SessionKernel {
|
|
|
245
319
|
throw new ReplayFailure(node, error)
|
|
246
320
|
}
|
|
247
321
|
}
|
|
322
|
+
for (const node of path) this.liveCallSeqs.add(node.callSeq)
|
|
248
323
|
}
|
|
249
324
|
|
|
250
325
|
completeJournal(journal, status, result, volatileReason, diagnostics = [], completion = undefined) {
|
|
@@ -272,6 +347,7 @@ class SessionKernel {
|
|
|
272
347
|
this.durability = durabilityState()
|
|
273
348
|
this.replayed = false
|
|
274
349
|
this.bindingCatalog = new BindingCatalog()
|
|
350
|
+
this.liveCallSeqs.clear()
|
|
275
351
|
}
|
|
276
352
|
|
|
277
353
|
settleCell(active, result, terminate = false) {
|
|
@@ -313,6 +389,9 @@ class SessionKernel {
|
|
|
313
389
|
this.bindingCatalog = active.appliedBindingCatalog
|
|
314
390
|
?? active.priorBindingCatalog.advance(prepared, request.program)
|
|
315
391
|
}
|
|
392
|
+
if (replay === undefined && !terminate) {
|
|
393
|
+
this.liveCallSeqs.add(request.callSeq ?? request.sourceCallSeq)
|
|
394
|
+
}
|
|
316
395
|
this.active = undefined
|
|
317
396
|
if (terminate) void this.client.reset(worker)
|
|
318
397
|
active.finish(result)
|
|
@@ -458,10 +537,13 @@ export class SessionRuntime {
|
|
|
458
537
|
sourceCallSeq = liveToolCallSeq(session, callId, 'run_code')
|
|
459
538
|
callSeq = persistedCallSeq ?? sourceCallSeq
|
|
460
539
|
} else {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
540
|
+
sourceCallSeq = persistedCallSeq
|
|
541
|
+
if (sourceCallSeq === undefined) {
|
|
542
|
+
try {
|
|
543
|
+
sourceCallSeq = liveToolCallSeq(session, callId, 'run_code')
|
|
544
|
+
} catch {
|
|
545
|
+
sourceCallSeq = undefined
|
|
546
|
+
}
|
|
465
547
|
}
|
|
466
548
|
}
|
|
467
549
|
} catch (error) {
|
|
@@ -472,7 +554,9 @@ export class SessionRuntime {
|
|
|
472
554
|
let history
|
|
473
555
|
try {
|
|
474
556
|
history = cellConfig.durableReplay
|
|
475
|
-
? recoverJournal(session, callSeq
|
|
557
|
+
? recoverJournal(session, callSeq, {
|
|
558
|
+
visibleCallSeqs: visibleExecutableCallSeqs(session),
|
|
559
|
+
})
|
|
476
560
|
: emptyHistory()
|
|
477
561
|
} catch (error) {
|
|
478
562
|
return completed({ logs: [], error: { kind: 'recovery', message: `cannot reconstruct REPL from session log: ${messageOf(error)}` } })
|
|
@@ -489,7 +573,7 @@ export class SessionRuntime {
|
|
|
489
573
|
const journal = createJournal(
|
|
490
574
|
/* c8 ignore next */
|
|
491
575
|
this.pendingNoops.get(sessionId) ?? [],
|
|
492
|
-
cellConfig
|
|
576
|
+
bindingPolicy(cellConfig),
|
|
493
577
|
rewritePolicy(cellConfig),
|
|
494
578
|
)
|
|
495
579
|
const workerReservation = kernel.reserveWorkerConfiguration(cellConfig)
|
|
@@ -23,6 +23,7 @@ export class BindingCatalog {
|
|
|
23
23
|
#definitions
|
|
24
24
|
#imports
|
|
25
25
|
#namespaces
|
|
26
|
+
#writable
|
|
26
27
|
|
|
27
28
|
constructor(
|
|
28
29
|
known = new Set(),
|
|
@@ -30,6 +31,7 @@ export class BindingCatalog {
|
|
|
30
31
|
namespaces = new Set(),
|
|
31
32
|
kinds = new Map(),
|
|
32
33
|
definitions = new Map(),
|
|
34
|
+
writable = new Set(),
|
|
33
35
|
) {
|
|
34
36
|
this.#known = new Set(known)
|
|
35
37
|
this.#kinds = new Map([...this.#known].map(name => [name, kinds.get(name) ?? 'variable']))
|
|
@@ -38,6 +40,7 @@ export class BindingCatalog {
|
|
|
38
40
|
.map(name => [name, definitions.get(name)]))
|
|
39
41
|
this.#imports = new Map(imports)
|
|
40
42
|
this.#namespaces = new Set(namespaces)
|
|
43
|
+
this.#writable = new Set([...writable].filter(name => this.#known.has(name)))
|
|
41
44
|
Object.freeze(this)
|
|
42
45
|
}
|
|
43
46
|
|
|
@@ -46,28 +49,58 @@ export class BindingCatalog {
|
|
|
46
49
|
knownBindings: new Set(this.#known),
|
|
47
50
|
importBindings: new Map(this.#imports),
|
|
48
51
|
importNamespaces: new Set(this.#namespaces),
|
|
52
|
+
writableBindings: new Set(this.#writable),
|
|
49
53
|
}
|
|
50
54
|
}
|
|
51
55
|
|
|
52
|
-
advance(prepared, source = undefined) {
|
|
56
|
+
advance(prepared, source = undefined, committedRedeclarations = undefined) {
|
|
53
57
|
const known = new Set(this.#known)
|
|
54
58
|
const kinds = new Map(this.#kinds)
|
|
55
59
|
const definitions = new Map(this.#definitions)
|
|
60
|
+
const writable = new Set(this.#writable)
|
|
56
61
|
const touched = new Set()
|
|
62
|
+
const redeclared = new Set((prepared.redeclared ?? []).map(declaration => declaration.name))
|
|
63
|
+
const commitGated = prepared.commitTargets
|
|
64
|
+
const committed = committedRedeclarations instanceof Set
|
|
65
|
+
? committedRedeclarations
|
|
66
|
+
: new Set([...redeclared, ...commitGated])
|
|
67
|
+
const uncommitted = new Set()
|
|
57
68
|
const extractDefinition = sourceDefinitionExtractor(source)
|
|
58
69
|
for (const declaration of prepared.declarations ?? []) {
|
|
59
70
|
if (typeof declaration?.name !== 'string') continue
|
|
71
|
+
const dependency = typeof declaration.commitDependency === 'string'
|
|
72
|
+
&& commitGated.has(declaration.commitDependency)
|
|
73
|
+
? declaration.commitDependency
|
|
74
|
+
: commitGated.has(declaration.name) ? declaration.name : undefined
|
|
75
|
+
if (dependency !== undefined && !committed.has(dependency)) {
|
|
76
|
+
uncommitted.add(declaration.name)
|
|
77
|
+
continue
|
|
78
|
+
}
|
|
60
79
|
touched.add(declaration.name)
|
|
61
80
|
kinds.set(declaration.name, declaration.kind ?? 'variable')
|
|
62
81
|
const definition = extractDefinition(declaration.definitionSpan)
|
|
63
82
|
if (definition !== undefined) definitions.set(declaration.name, definition)
|
|
83
|
+
if (!redeclared.has(declaration.name)) {
|
|
84
|
+
if (declaration.writable === true) writable.add(declaration.name)
|
|
85
|
+
else writable.delete(declaration.name)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
for (const name of prepared.declared) {
|
|
89
|
+
if (!uncommitted.has(name)) touched.add(name)
|
|
64
90
|
}
|
|
65
|
-
for (const name of prepared.declared) touched.add(name)
|
|
66
91
|
for (const name of touched) {
|
|
67
92
|
known.delete(name)
|
|
68
93
|
known.add(name)
|
|
69
94
|
}
|
|
70
|
-
|
|
95
|
+
const imports = new Map(prepared.imports)
|
|
96
|
+
for (const [name, binding] of imports) {
|
|
97
|
+
if (typeof binding?.commitDependency !== 'string'
|
|
98
|
+
|| !commitGated.has(binding.commitDependency)
|
|
99
|
+
|| committed.has(binding.commitDependency)) continue
|
|
100
|
+
if (this.#imports.has(name)) imports.set(name, this.#imports.get(name))
|
|
101
|
+
else imports.delete(name)
|
|
102
|
+
}
|
|
103
|
+
return new BindingCatalog(known, imports, prepared.importNamespaces, kinds, definitions, writable)
|
|
71
104
|
}
|
|
72
105
|
|
|
73
106
|
snapshot() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-ptc-plus",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "A session-bound agent-native REPL for DeepSeek Harness PTC mode.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.js",
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
"docs",
|
|
18
18
|
"assets/dsh-ptc-plus-banner-en.webp",
|
|
19
19
|
"assets/dsh-ptc-plus-banner-zh.webp",
|
|
20
|
+
"assets/ptc-plus-bindings-en.png",
|
|
21
|
+
"assets/ptc-plus-bindings-zh.png",
|
|
20
22
|
"assets/ptc-plus-repair-zh.png",
|
|
21
23
|
"assets/ptc-plus-repair-en.png",
|
|
22
24
|
"assets/ptc-plus-settings-en.png",
|
|
@@ -97,10 +99,10 @@
|
|
|
97
99
|
}
|
|
98
100
|
},
|
|
99
101
|
"devDependencies": {
|
|
100
|
-
"@deepseek-ai/dsh-settings": "
|
|
101
|
-
"@deepseek-ai/dsh-skill-filesystem": "
|
|
102
|
-
"@deepseek-ai/dsh-tool-cordis": "
|
|
103
|
-
"@deepseek-ai/dsh-tools": "
|
|
102
|
+
"@deepseek-ai/dsh-settings": "next",
|
|
103
|
+
"@deepseek-ai/dsh-skill-filesystem": "next",
|
|
104
|
+
"@deepseek-ai/dsh-tool-cordis": "next",
|
|
105
|
+
"@deepseek-ai/dsh-tools": "next",
|
|
104
106
|
"esbuild": "0.28.2",
|
|
105
107
|
"yaml": "^2.9.0"
|
|
106
108
|
}
|
package/src/client-activity.js
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
|
-
const JOURNAL_VERSIONS = new Set([1, 2, 3])
|
|
1
|
+
const JOURNAL_VERSIONS = new Set([1, 2, 3, 4])
|
|
2
2
|
const JOURNAL_STATUSES = new Set(['durable', 'volatile', 'discarded', 'noop'])
|
|
3
3
|
const BINDING_MODES = new Set(['loose', 'strict'])
|
|
4
4
|
const JOURNAL_FIELDS = new Set([
|
|
5
|
+
'version', 'bindingPolicy', 'rewritePolicy', 'moduleSemantics', 'status', 'calls', 'operations',
|
|
6
|
+
'confirms', 'diagnostics', 'completion', 'volatileReason',
|
|
7
|
+
])
|
|
8
|
+
const PREDECESSOR_JOURNAL_FIELDS = new Set([
|
|
5
9
|
'version', 'bindingMode', 'rewritePolicy', 'status', 'calls', 'operations',
|
|
6
10
|
'confirms', 'diagnostics', 'completion', 'volatileReason',
|
|
7
11
|
])
|
|
8
|
-
const LEGACY_JOURNAL_FIELDS = new Set([...
|
|
12
|
+
const LEGACY_JOURNAL_FIELDS = new Set([...PREDECESSOR_JOURNAL_FIELDS].filter(key => key !== 'rewritePolicy'))
|
|
13
|
+
const BINDING_POLICY_FIELDS = new Set(['variableRedeclarations', 'functionClassRedeclarations'])
|
|
9
14
|
const REWRITE_POLICY_FIELDS = new Set([
|
|
10
15
|
'autoRewriteImports', 'autoStripExports', 'autoSplitRedeclarations',
|
|
11
16
|
])
|
|
17
|
+
const MODULE_SEMANTICS_FIELDS = new Set(['defaultExportBinding'])
|
|
18
|
+
const DEFAULT_EXPORT_BINDINGS = new Set(['legacy-variable', 'live-readonly'])
|
|
12
19
|
const CALL_SUCCESS_FIELDS = new Set(['global', 'member', 'args', 'ok', 'value', 'settle'])
|
|
13
20
|
const CALL_ERROR_FIELDS = new Set(['global', 'member', 'args', 'ok', 'error', 'settle'])
|
|
14
21
|
const OPERATION_FIELDS = new Set(['action', 'name'])
|
|
@@ -30,9 +37,11 @@ const REWRITE_FIELDS = new Set(['kind', 'description', 'source'])
|
|
|
30
37
|
const REWRITE_KINDS = new Set(['import', 'redeclaration', 'export'])
|
|
31
38
|
const REWRITE_POLICY_BY_KIND = Object.freeze({
|
|
32
39
|
import: 'autoRewriteImports',
|
|
33
|
-
redeclaration: 'autoSplitRedeclarations',
|
|
34
40
|
export: 'autoStripExports',
|
|
35
41
|
})
|
|
42
|
+
const MIXED_REDECLARATION = 'split a mixed top-level declaration while preserving native pattern initialization'
|
|
43
|
+
const FUNCTION_REDECLARATION = 'reassigned an existing top-level function declaration for REPL continuity'
|
|
44
|
+
const CLASS_REDECLARATION = 'reassigned an existing top-level class declaration for REPL continuity'
|
|
36
45
|
const EDIT_TARGET_FIELDS = new Set(['targetCallSeq'])
|
|
37
46
|
const DERIVED_RUN_FIELDS = new Set(['code', 'description'])
|
|
38
47
|
const RECOVERY_BOUNDARY_FIELDS = new Set(['failedCallSeq', 'frontierCallSeq'])
|
|
@@ -209,6 +218,16 @@ function isValidRewritePolicy(value) {
|
|
|
209
218
|
&& [...REWRITE_POLICY_FIELDS].every(key => typeof value[key] === 'boolean')
|
|
210
219
|
}
|
|
211
220
|
|
|
221
|
+
function isValidBindingPolicy(value) {
|
|
222
|
+
return hasExactFields(value, BINDING_POLICY_FIELDS)
|
|
223
|
+
&& [...BINDING_POLICY_FIELDS].every(key => typeof value[key] === 'boolean')
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function isValidModuleSemantics(value) {
|
|
227
|
+
return hasExactFields(value, MODULE_SEMANTICS_FIELDS)
|
|
228
|
+
&& DEFAULT_EXPORT_BINDINGS.has(value.defaultExportBinding)
|
|
229
|
+
}
|
|
230
|
+
|
|
212
231
|
function isValidCall(value) {
|
|
213
232
|
if (!isRecord(value) || (value.ok !== true && value.ok !== false)) return false
|
|
214
233
|
const fields = value.ok ? CALL_SUCCESS_FIELDS : CALL_ERROR_FIELDS
|
|
@@ -249,10 +268,16 @@ function isReadableJournalUnchecked(value) {
|
|
|
249
268
|
if (!isRecord(value) || !JOURNAL_VERSIONS.has(value.version) || !JOURNAL_STATUSES.has(value.status)) {
|
|
250
269
|
return false
|
|
251
270
|
}
|
|
252
|
-
const
|
|
253
|
-
const
|
|
254
|
-
|
|
255
|
-
|
|
271
|
+
const predecessor = value.version !== 4
|
|
272
|
+
const fields = value.version === 1 ? LEGACY_JOURNAL_FIELDS : predecessor ? PREDECESSOR_JOURNAL_FIELDS : JOURNAL_FIELDS
|
|
273
|
+
const required = predecessor
|
|
274
|
+
? ['version', 'bindingMode', 'status', 'calls', 'operations', 'diagnostics']
|
|
275
|
+
: ['version', 'bindingPolicy', 'rewritePolicy', 'moduleSemantics', 'status', 'calls', 'operations', 'diagnostics']
|
|
276
|
+
if (value.version !== 1 && value.version !== 4) required.push('rewritePolicy')
|
|
277
|
+
if (!hasClosedFields(value, fields, required)
|
|
278
|
+
|| (predecessor && !BINDING_MODES.has(value.bindingMode))
|
|
279
|
+
|| (value.version === 4 && !isValidBindingPolicy(value.bindingPolicy))
|
|
280
|
+
|| (value.version === 4 && !isValidModuleSemantics(value.moduleSemantics))
|
|
256
281
|
|| (value.version !== 1 && !isValidRewritePolicy(value.rewritePolicy))
|
|
257
282
|
|| !Array.isArray(value.calls) || !value.calls.every(isValidCall)
|
|
258
283
|
|| !Array.isArray(value.operations) || !value.operations.every(isValidOperation)
|
|
@@ -295,7 +320,12 @@ function isValidRewrites(value, journal) {
|
|
|
295
320
|
&& Array.isArray(value) && value.every(rewrite => (
|
|
296
321
|
hasClosedFields(rewrite, REWRITE_FIELDS, ['kind', 'description'])
|
|
297
322
|
&& REWRITE_KINDS.has(rewrite.kind)
|
|
298
|
-
&&
|
|
323
|
+
&& (rewrite.kind === 'redeclaration'
|
|
324
|
+
? (rewrite.description === FUNCTION_REDECLARATION || rewrite.description === CLASS_REDECLARATION)
|
|
325
|
+
? journal.version === 4 && isValidBindingPolicy(journal.bindingPolicy)
|
|
326
|
+
&& journal.bindingPolicy.functionClassRedeclarations === true
|
|
327
|
+
: journal.rewritePolicy.autoSplitRedeclarations === true
|
|
328
|
+
: journal.rewritePolicy[REWRITE_POLICY_BY_KIND[rewrite.kind]] === true)
|
|
299
329
|
&& typeof rewrite.description === 'string' && rewrite.description.length > 0
|
|
300
330
|
&& (rewrite.source === undefined || typeof rewrite.source === 'string')
|
|
301
331
|
))
|
|
@@ -377,7 +407,6 @@ function resultText(block) {
|
|
|
377
407
|
}
|
|
378
408
|
}
|
|
379
409
|
|
|
380
|
-
const MIXED_REDECLARATION = 'split a mixed top-level declaration while preserving native pattern initialization'
|
|
381
410
|
const GENERATED_RUN_CODE_DESCRIPTION_KEY = 'dshPtcPlusRunCodeDescription'
|
|
382
411
|
|
|
383
412
|
function rewriteFeature(rewrites, predicate, key) {
|