@smthrs/plan 0.0.0-stage → 1.0.0-rc.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/CHANGELOG.md +183 -0
- package/LICENSE +21 -0
- package/README.md +228 -2
- package/dist/cjs/CachePolicy.d.ts +131 -0
- package/dist/cjs/CachePolicy.d.ts.map +1 -0
- package/dist/cjs/CachePolicy.js +50 -0
- package/dist/cjs/CachePolicy.js.map +7 -0
- package/dist/cjs/Effects.d.ts +240 -0
- package/dist/cjs/Effects.d.ts.map +1 -0
- package/dist/cjs/Effects.js +76 -0
- package/dist/cjs/Effects.js.map +7 -0
- package/dist/cjs/FileSet.d.ts +288 -0
- package/dist/cjs/FileSet.d.ts.map +1 -0
- package/dist/cjs/FileSet.js +191 -0
- package/dist/cjs/FileSet.js.map +7 -0
- package/dist/cjs/GraphBuildError.d.ts +122 -0
- package/dist/cjs/GraphBuildError.d.ts.map +1 -0
- package/dist/cjs/GraphBuildError.js +71 -0
- package/dist/cjs/GraphBuildError.js.map +7 -0
- package/dist/cjs/KeyMaterial.d.ts +102 -0
- package/dist/cjs/KeyMaterial.d.ts.map +1 -0
- package/dist/cjs/KeyMaterial.js +64 -0
- package/dist/cjs/KeyMaterial.js.map +7 -0
- package/dist/cjs/Node.d.ts +606 -0
- package/dist/cjs/Node.d.ts.map +1 -0
- package/dist/cjs/Node.js +207 -0
- package/dist/cjs/Node.js.map +7 -0
- package/dist/cjs/Placement.d.ts +117 -0
- package/dist/cjs/Placement.d.ts.map +1 -0
- package/dist/cjs/Placement.js +46 -0
- package/dist/cjs/Placement.js.map +7 -0
- package/dist/cjs/Plan.d.ts +440 -0
- package/dist/cjs/Plan.d.ts.map +1 -0
- package/dist/cjs/Plan.js +508 -0
- package/dist/cjs/Plan.js.map +7 -0
- package/dist/cjs/PlanDiff.d.ts +58 -0
- package/dist/cjs/PlanDiff.d.ts.map +1 -0
- package/dist/cjs/PlanDiff.js +124 -0
- package/dist/cjs/PlanDiff.js.map +7 -0
- package/dist/cjs/Planned.d.ts +121 -0
- package/dist/cjs/Planned.d.ts.map +1 -0
- package/dist/cjs/Planned.js +72 -0
- package/dist/cjs/Planned.js.map +7 -0
- package/dist/cjs/Repetition.d.ts +31 -0
- package/dist/cjs/Repetition.d.ts.map +1 -0
- package/dist/cjs/Repetition.js +36 -0
- package/dist/cjs/Repetition.js.map +7 -0
- package/dist/cjs/Scheduling.d.ts +89 -0
- package/dist/cjs/Scheduling.d.ts.map +1 -0
- package/dist/cjs/Scheduling.js +76 -0
- package/dist/cjs/Scheduling.js.map +7 -0
- package/dist/cjs/StepKey.d.ts +333 -0
- package/dist/cjs/StepKey.d.ts.map +1 -0
- package/dist/cjs/StepKey.js +311 -0
- package/dist/cjs/StepKey.js.map +7 -0
- package/dist/cjs/index.d.ts +91 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +59 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/cjs/internal/ConflictAnnotation.d.ts +59 -0
- package/dist/cjs/internal/ConflictAnnotation.d.ts.map +1 -0
- package/dist/cjs/internal/ConflictAnnotation.js +247 -0
- package/dist/cjs/internal/ConflictAnnotation.js.map +7 -0
- package/dist/cjs/internal/EffectCandidates.d.ts +19 -0
- package/dist/cjs/internal/EffectCandidates.d.ts.map +1 -0
- package/dist/cjs/internal/EffectCandidates.js +92 -0
- package/dist/cjs/internal/EffectCandidates.js.map +7 -0
- package/dist/cjs/internal/JsonMirror.d.ts +34 -0
- package/dist/cjs/internal/JsonMirror.d.ts.map +1 -0
- package/dist/cjs/internal/JsonMirror.js +195 -0
- package/dist/cjs/internal/JsonMirror.js.map +7 -0
- package/dist/cjs/internal/effects.d.ts +245 -0
- package/dist/cjs/internal/effects.d.ts.map +1 -0
- package/dist/cjs/internal/effects.js +290 -0
- package/dist/cjs/internal/effects.js.map +7 -0
- package/dist/cjs/internal/node.d.ts +526 -0
- package/dist/cjs/internal/node.d.ts.map +1 -0
- package/dist/cjs/internal/node.js +312 -0
- package/dist/cjs/internal/node.js.map +7 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/test/PlanFixtures.d.ts +127 -0
- package/dist/cjs/test/PlanFixtures.d.ts.map +1 -0
- package/dist/cjs/test/PlanFixtures.js +59 -0
- package/dist/cjs/test/PlanFixtures.js.map +7 -0
- package/dist/esm/CachePolicy.d.ts +131 -0
- package/dist/esm/CachePolicy.d.ts.map +1 -0
- package/dist/esm/CachePolicy.js +117 -0
- package/dist/esm/CachePolicy.js.map +1 -0
- package/dist/esm/Effects.d.ts +240 -0
- package/dist/esm/Effects.d.ts.map +1 -0
- package/dist/esm/Effects.js +167 -0
- package/dist/esm/Effects.js.map +1 -0
- package/dist/esm/FileSet.d.ts +288 -0
- package/dist/esm/FileSet.d.ts.map +1 -0
- package/dist/esm/FileSet.js +324 -0
- package/dist/esm/FileSet.js.map +1 -0
- package/dist/esm/GraphBuildError.d.ts +122 -0
- package/dist/esm/GraphBuildError.d.ts.map +1 -0
- package/dist/esm/GraphBuildError.js +146 -0
- package/dist/esm/GraphBuildError.js.map +1 -0
- package/dist/esm/KeyMaterial.d.ts +102 -0
- package/dist/esm/KeyMaterial.d.ts.map +1 -0
- package/dist/esm/KeyMaterial.js +85 -0
- package/dist/esm/KeyMaterial.js.map +1 -0
- package/dist/esm/Node.d.ts +606 -0
- package/dist/esm/Node.d.ts.map +1 -0
- package/dist/esm/Node.js +521 -0
- package/dist/esm/Node.js.map +1 -0
- package/dist/esm/Placement.d.ts +117 -0
- package/dist/esm/Placement.d.ts.map +1 -0
- package/dist/esm/Placement.js +65 -0
- package/dist/esm/Placement.js.map +1 -0
- package/dist/esm/Plan.d.ts +440 -0
- package/dist/esm/Plan.d.ts.map +1 -0
- package/dist/esm/Plan.js +673 -0
- package/dist/esm/Plan.js.map +1 -0
- package/dist/esm/PlanDiff.d.ts +58 -0
- package/dist/esm/PlanDiff.d.ts.map +1 -0
- package/dist/esm/PlanDiff.js +159 -0
- package/dist/esm/PlanDiff.js.map +1 -0
- package/dist/esm/Planned.d.ts +121 -0
- package/dist/esm/Planned.d.ts.map +1 -0
- package/dist/esm/Planned.js +147 -0
- package/dist/esm/Planned.js.map +1 -0
- package/dist/esm/Repetition.d.ts +31 -0
- package/dist/esm/Repetition.d.ts.map +1 -0
- package/dist/esm/Repetition.js +24 -0
- package/dist/esm/Repetition.js.map +1 -0
- package/dist/esm/Scheduling.d.ts +89 -0
- package/dist/esm/Scheduling.d.ts.map +1 -0
- package/dist/esm/Scheduling.js +82 -0
- package/dist/esm/Scheduling.js.map +1 -0
- package/dist/esm/StepKey.d.ts +333 -0
- package/dist/esm/StepKey.d.ts.map +1 -0
- package/dist/esm/StepKey.js +478 -0
- package/dist/esm/StepKey.js.map +1 -0
- package/dist/esm/index.d.ts +91 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +91 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/internal/ConflictAnnotation.d.ts +59 -0
- package/dist/esm/internal/ConflictAnnotation.d.ts.map +1 -0
- package/dist/esm/internal/ConflictAnnotation.js +332 -0
- package/dist/esm/internal/ConflictAnnotation.js.map +1 -0
- package/dist/esm/internal/EffectCandidates.d.ts +19 -0
- package/dist/esm/internal/EffectCandidates.d.ts.map +1 -0
- package/dist/esm/internal/EffectCandidates.js +86 -0
- package/dist/esm/internal/EffectCandidates.js.map +1 -0
- package/dist/esm/internal/JsonMirror.d.ts +34 -0
- package/dist/esm/internal/JsonMirror.d.ts.map +1 -0
- package/dist/esm/internal/JsonMirror.js +204 -0
- package/dist/esm/internal/JsonMirror.js.map +1 -0
- package/dist/esm/internal/effects.d.ts +245 -0
- package/dist/esm/internal/effects.d.ts.map +1 -0
- package/dist/esm/internal/effects.js +459 -0
- package/dist/esm/internal/effects.js.map +1 -0
- package/dist/esm/internal/node.d.ts +526 -0
- package/dist/esm/internal/node.d.ts.map +1 -0
- package/dist/esm/internal/node.js +564 -0
- package/dist/esm/internal/node.js.map +1 -0
- package/dist/esm/test/PlanFixtures.d.ts +127 -0
- package/dist/esm/test/PlanFixtures.d.ts.map +1 -0
- package/dist/esm/test/PlanFixtures.js +60 -0
- package/dist/esm/test/PlanFixtures.js.map +1 -0
- package/docs/README.md +165 -0
- package/docs/api.md +1475 -0
- package/docs/concepts/authoring-ast.md +203 -0
- package/docs/concepts/effects-and-conflicts.md +135 -0
- package/docs/concepts/plan-value.md +168 -0
- package/docs/concepts/step-keys.md +179 -0
- package/docs/guides/author-a-node-graph.md +182 -0
- package/docs/guides/compile-a-plan.md +146 -0
- package/docs/guides/declare-file-effects.md +143 -0
- package/docs/guides/diff-two-plans.md +101 -0
- package/docs/installation.md +71 -0
- package/docs/quickstart.md +128 -0
- package/docs/testing.md +73 -0
- package/docs/troubleshooting.md +314 -0
- package/package.json +254 -3
- package/src/CachePolicy.ts +143 -0
- package/src/Effects.ts +284 -0
- package/src/FileSet.ts +411 -0
- package/src/GraphBuildError.ts +158 -0
- package/src/KeyMaterial.ts +106 -0
- package/src/Node.ts +871 -0
- package/src/Placement.ts +99 -0
- package/src/Plan.ts +868 -0
- package/src/PlanDiff.ts +199 -0
- package/src/Planned.ts +208 -0
- package/src/Repetition.ts +33 -0
- package/src/Scheduling.ts +154 -0
- package/src/StepKey.ts +710 -0
- package/src/index.ts +103 -0
- package/src/internal/ConflictAnnotation.ts +374 -0
- package/src/internal/EffectCandidates.ts +89 -0
- package/src/internal/JsonMirror.ts +255 -0
- package/src/internal/effects.ts +543 -0
- package/src/internal/node.ts +858 -0
- package/src/test/PlanFixtures.ts +76 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The inert JSON mirror of a value: what `JSON.stringify` would see, as data.
|
|
3
|
+
*
|
|
4
|
+
* The AST stores payloads this way, the plan compiler stores key material this
|
|
5
|
+
* way, and a plan diff compares declarations this way, so all three share the
|
|
6
|
+
* one walk. A planned value is the only member with no JSON meaning of its
|
|
7
|
+
* own, and each caller decides what it becomes.
|
|
8
|
+
*
|
|
9
|
+
* @since 0.1.0
|
|
10
|
+
* @private
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { GraphBuildError } from "../GraphBuildError.ts"
|
|
14
|
+
import * as Planned from "../Planned.ts"
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* One container being cloned: the object walked, the clone being filled, and
|
|
18
|
+
* the member position the walk has reached. `keys` is `undefined` for an
|
|
19
|
+
* array, whose members are positional.
|
|
20
|
+
*
|
|
21
|
+
* @since 0.1.0
|
|
22
|
+
* @private
|
|
23
|
+
*/
|
|
24
|
+
interface CloneFrame {
|
|
25
|
+
readonly source: Record<string, unknown> | ReadonlyArray<unknown>
|
|
26
|
+
readonly output: Record<string, unknown> | Array<unknown>
|
|
27
|
+
readonly descriptors: PropertyDescriptorMap
|
|
28
|
+
readonly keys: ReadonlyArray<string> | undefined
|
|
29
|
+
readonly path: ClonePath
|
|
30
|
+
/** Sources whose callable `toJSON` resolved to this container. */
|
|
31
|
+
readonly replaced: ReadonlyArray<object>
|
|
32
|
+
index: number
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Where the walk stands, as a link to its parent rather than a copy of the
|
|
37
|
+
* whole path. Payload depth is bounded only by the caller, and copying the
|
|
38
|
+
* path at each member made a clone cost memory quadratic in that depth: a
|
|
39
|
+
* 20,000-deep payload held 20,000 live frames whose paths together ran to
|
|
40
|
+
* hundreds of millions of entries, several gigabytes, for a result that is
|
|
41
|
+
* linear. The path is read only to name a member in a refusal, so it stays a
|
|
42
|
+
* chain here and is flattened at the throw.
|
|
43
|
+
*
|
|
44
|
+
* `undefined` is the root, whose path is empty.
|
|
45
|
+
*
|
|
46
|
+
* @since 0.1.0
|
|
47
|
+
* @private
|
|
48
|
+
*/
|
|
49
|
+
type ClonePath = { readonly parent: ClonePath; readonly key: string } | undefined
|
|
50
|
+
|
|
51
|
+
/** The chain read outwards, root first: the array the refusals report. */
|
|
52
|
+
const clonePath = (path: ClonePath): ReadonlyArray<string> => {
|
|
53
|
+
const keys: Array<string> = []
|
|
54
|
+
for (let current = path; current !== undefined; current = current.parent) keys.push(current.key)
|
|
55
|
+
return keys.reverse()
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const payloadError = (at: ClonePath, reason: string): GraphBuildError => {
|
|
59
|
+
const path = clonePath(at)
|
|
60
|
+
return new GraphBuildError({
|
|
61
|
+
code: "invalid_payload",
|
|
62
|
+
node: "payload",
|
|
63
|
+
path,
|
|
64
|
+
message: `Plan payload at ${path.length === 0 ? "$" : `$.${path.join(".")}`} ${reason}`
|
|
65
|
+
})
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const cyclicPayloadError = (at: ClonePath): GraphBuildError => {
|
|
69
|
+
const path = clonePath(at)
|
|
70
|
+
return new GraphBuildError({
|
|
71
|
+
code: "cyclic_payload",
|
|
72
|
+
node: "payload",
|
|
73
|
+
path,
|
|
74
|
+
message: `Plan payload at ${
|
|
75
|
+
path.length === 0 ? "$" : `$.${path.join(".")}`
|
|
76
|
+
} has a toJSON method that returns itself`
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const inheritedDataProperty = (
|
|
81
|
+
value: object,
|
|
82
|
+
key: PropertyKey
|
|
83
|
+
):
|
|
84
|
+
| { readonly kind: "data"; readonly value: unknown }
|
|
85
|
+
| { readonly kind: "accessor" }
|
|
86
|
+
| { readonly kind: "missing" } =>
|
|
87
|
+
{
|
|
88
|
+
let current: object | null = value
|
|
89
|
+
while (current !== null) {
|
|
90
|
+
const descriptor = Object.getOwnPropertyDescriptor(current, key)
|
|
91
|
+
if (descriptor !== undefined) {
|
|
92
|
+
return "value" in descriptor ? { kind: "data", value: descriptor.value } : { kind: "accessor" }
|
|
93
|
+
}
|
|
94
|
+
current = Object.getPrototypeOf(current) as object | null
|
|
95
|
+
}
|
|
96
|
+
return { kind: "missing" }
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Clones the JSON mirror of the input, so {@link module:StepKey.content} over
|
|
101
|
+
* the clone and the input produce the same key and the clone holds only inert
|
|
102
|
+
* JSON data. The walk uses an explicit stack, memoizes shared references and
|
|
103
|
+
* cycles, honors callable `toJSON`, omits object members without a JSON
|
|
104
|
+
* representation, and writes `null` for those values in arrays.
|
|
105
|
+
*
|
|
106
|
+
* `toJSON` receives the key canonical serialization passes it: the member
|
|
107
|
+
* name, the array index, or `""` at the root. Its replacement is therefore
|
|
108
|
+
* memoized per source and key, since one shared source may serialize
|
|
109
|
+
* differently at two positions. A source met again inside its own
|
|
110
|
+
* replacement reuses that replacement, so a cycle through `toJSON` clones as
|
|
111
|
+
* a cycle whatever key it recurs at.
|
|
112
|
+
*
|
|
113
|
+
* A planned value becomes whatever `plannedValue` returns for it. Refusals
|
|
114
|
+
* throw a {@link GraphBuildError} naming the member's path.
|
|
115
|
+
*
|
|
116
|
+
* @since 0.1.0
|
|
117
|
+
* @private
|
|
118
|
+
*/
|
|
119
|
+
export const jsonMirror = (
|
|
120
|
+
input: unknown,
|
|
121
|
+
plannedValue: (value: unknown, reference: Planned.Reference) => unknown
|
|
122
|
+
): unknown => {
|
|
123
|
+
const missing = Symbol("missing JSON representation")
|
|
124
|
+
const seen = new WeakMap<object, unknown>()
|
|
125
|
+
const replacedAt = new WeakMap<object, Map<string, unknown>>()
|
|
126
|
+
const open = new Map<object, unknown>()
|
|
127
|
+
let result: unknown
|
|
128
|
+
const frames: Array<CloneFrame> = []
|
|
129
|
+
/** Resolves one member, opening a frame when it is an unseen container. */
|
|
130
|
+
const enter = (
|
|
131
|
+
initial: unknown,
|
|
132
|
+
place: (member: unknown | typeof missing) => void,
|
|
133
|
+
path: ClonePath
|
|
134
|
+
): void => {
|
|
135
|
+
let current = initial
|
|
136
|
+
const key = path === undefined ? "" : path.key
|
|
137
|
+
const replacements: Array<object> = []
|
|
138
|
+
const resolving = new WeakSet<object>()
|
|
139
|
+
const finish = (member: unknown | typeof missing): void => {
|
|
140
|
+
for (const replacement of replacements) {
|
|
141
|
+
let byKey = replacedAt.get(replacement)
|
|
142
|
+
if (byKey === undefined) replacedAt.set(replacement, byKey = new Map())
|
|
143
|
+
byKey.set(key, member)
|
|
144
|
+
}
|
|
145
|
+
place(member)
|
|
146
|
+
}
|
|
147
|
+
while (true) {
|
|
148
|
+
const reference = Planned.reference(current)
|
|
149
|
+
if (reference !== undefined) {
|
|
150
|
+
finish(plannedValue(current, reference))
|
|
151
|
+
return
|
|
152
|
+
}
|
|
153
|
+
const kind = typeof current
|
|
154
|
+
if (current === null || (kind !== "object" && kind !== "function")) {
|
|
155
|
+
finish(kind === "undefined" || kind === "symbol" ? missing : current)
|
|
156
|
+
return
|
|
157
|
+
}
|
|
158
|
+
const source = current as object
|
|
159
|
+
if (seen.has(source)) {
|
|
160
|
+
finish(seen.get(source))
|
|
161
|
+
return
|
|
162
|
+
}
|
|
163
|
+
if (resolving.has(source)) {
|
|
164
|
+
throw cyclicPayloadError(path)
|
|
165
|
+
}
|
|
166
|
+
const toJSON = inheritedDataProperty(source, "toJSON")
|
|
167
|
+
if (toJSON.kind === "accessor") {
|
|
168
|
+
throw payloadError(path, "has an accessor-backed toJSON member")
|
|
169
|
+
}
|
|
170
|
+
if (toJSON.kind === "data" && typeof toJSON.value === "function") {
|
|
171
|
+
const byKey = replacedAt.get(source)
|
|
172
|
+
if (byKey !== undefined && byKey.has(key)) {
|
|
173
|
+
finish(byKey.get(key))
|
|
174
|
+
return
|
|
175
|
+
}
|
|
176
|
+
if (open.has(source)) {
|
|
177
|
+
finish(open.get(source))
|
|
178
|
+
return
|
|
179
|
+
}
|
|
180
|
+
resolving.add(source)
|
|
181
|
+
replacements.push(source)
|
|
182
|
+
current = Reflect.apply(toJSON.value, source, [key])
|
|
183
|
+
continue
|
|
184
|
+
}
|
|
185
|
+
if (kind === "function") {
|
|
186
|
+
seen.set(source, missing)
|
|
187
|
+
finish(missing)
|
|
188
|
+
return
|
|
189
|
+
}
|
|
190
|
+
const prototype = Object.getPrototypeOf(source)
|
|
191
|
+
if (!Array.isArray(source) && prototype !== Object.prototype && prototype !== null) {
|
|
192
|
+
throw payloadError(path, "has an unsupported prototype and no data-valued toJSON method")
|
|
193
|
+
}
|
|
194
|
+
const container = current as Record<string, unknown> | ReadonlyArray<unknown>
|
|
195
|
+
const descriptors = Object.getOwnPropertyDescriptors(container) as PropertyDescriptorMap
|
|
196
|
+
const output: Record<string, unknown> | Array<unknown> = Array.isArray(container)
|
|
197
|
+
? []
|
|
198
|
+
: Object.create(null) as Record<string, unknown>
|
|
199
|
+
seen.set(container, output)
|
|
200
|
+
finish(output)
|
|
201
|
+
frames.push({
|
|
202
|
+
source: container,
|
|
203
|
+
output,
|
|
204
|
+
descriptors,
|
|
205
|
+
keys: Array.isArray(container)
|
|
206
|
+
? undefined
|
|
207
|
+
: Reflect.ownKeys(descriptors).filter((key): key is string =>
|
|
208
|
+
typeof key === "string" && descriptors[key]!.enumerable === true
|
|
209
|
+
),
|
|
210
|
+
path,
|
|
211
|
+
replaced: replacements,
|
|
212
|
+
index: 0
|
|
213
|
+
})
|
|
214
|
+
for (const replacement of replacements) open.set(replacement, output)
|
|
215
|
+
return
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
enter(input, (member) => {
|
|
219
|
+
result = member === missing ? undefined : member
|
|
220
|
+
}, undefined)
|
|
221
|
+
while (frames.length > 0) {
|
|
222
|
+
const frame = frames[frames.length - 1]!
|
|
223
|
+
if (frame.index >= (frame.keys ?? frame.source as ReadonlyArray<unknown>).length) {
|
|
224
|
+
frames.pop()
|
|
225
|
+
for (const replacement of frame.replaced) open.delete(replacement)
|
|
226
|
+
continue
|
|
227
|
+
}
|
|
228
|
+
const position = frame.index
|
|
229
|
+
frame.index = position + 1
|
|
230
|
+
if (frame.keys === undefined) {
|
|
231
|
+
const members = frame.output as Array<unknown>
|
|
232
|
+
const descriptor = frame.descriptors[String(position)]
|
|
233
|
+
if (descriptor !== undefined && !("value" in descriptor)) {
|
|
234
|
+
throw payloadError({ parent: frame.path, key: String(position) }, "is an accessor")
|
|
235
|
+
}
|
|
236
|
+
enter(descriptor === undefined ? undefined : descriptor.value, (member) => {
|
|
237
|
+
members.push(member === missing ? null : member)
|
|
238
|
+
}, { parent: frame.path, key: String(position) })
|
|
239
|
+
} else {
|
|
240
|
+
const key = frame.keys[position]!
|
|
241
|
+
const descriptor = frame.descriptors[key]!
|
|
242
|
+
if (!("value" in descriptor)) throw payloadError({ parent: frame.path, key }, "is an accessor")
|
|
243
|
+
enter(descriptor.value, (member) => {
|
|
244
|
+
if (member === missing) return
|
|
245
|
+
Object.defineProperty(frame.output, key, {
|
|
246
|
+
configurable: true,
|
|
247
|
+
enumerable: true,
|
|
248
|
+
value: member,
|
|
249
|
+
writable: true
|
|
250
|
+
})
|
|
251
|
+
}, { parent: frame.path, key })
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return result
|
|
255
|
+
}
|