@bablr/agast-vm 0.2.0 → 0.3.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.
package/lib/context.js CHANGED
@@ -11,7 +11,8 @@ function* ownTerminalsFor(range, nextTerminals, tagNodes) {
11
11
 
12
12
  for (let term = start; term && term !== pastEnd; term = nextTerminals.get(term)) {
13
13
  if (!(term === range[0] || term === range[1]) && term.type === 'OpenNodeTag') {
14
- term = nextTerminals.get(tagNodes.get(term).endTag);
14
+ term = tagNodes.get(term).closeTag;
15
+ continue;
15
16
  }
16
17
 
17
18
  yield term;
@@ -70,6 +71,14 @@ export const ContextFacade = class AgastContextFacade {
70
71
  return actuals.get(this).nodeForTag(tag);
71
72
  }
72
73
 
74
+ pathForTag(tag) {
75
+ return actuals.get(this).pathForTag(tag);
76
+ }
77
+
78
+ nodeForPath(path) {
79
+ return actuals.get(this).nodeForPath(path);
80
+ }
81
+
73
82
  unbox(value) {
74
83
  return actuals.get(this).unbox(value);
75
84
  }
@@ -84,6 +93,8 @@ export const Context = class AgastContext {
84
93
  this.prevTerminals = new WeakMap();
85
94
  this.nextTerminals = new WeakMap();
86
95
  this.tagNodes = new WeakMap();
96
+ this.tagPaths = new WeakMap();
97
+ this.pathNodes = new WeakMap();
87
98
  this.unboxedValues = new WeakMap();
88
99
  this.facade = new ContextFacade();
89
100
 
@@ -129,10 +140,26 @@ export const Context = class AgastContext {
129
140
  return ownTerminalsFor(range, this.prevTerminals, this.tagNodes);
130
141
  }
131
142
 
143
+ getPreviousTerminal(token) {
144
+ return this.prevTerminals.get(token);
145
+ }
146
+
147
+ getNextTerminal(token) {
148
+ return this.nextTerminals.get(token);
149
+ }
150
+
132
151
  nodeForTag(tag) {
133
152
  return this.tagNodes.get(tag);
134
153
  }
135
154
 
155
+ pathForTag(ref) {
156
+ return this.tagPaths.get(ref);
157
+ }
158
+
159
+ nodeForPath(path) {
160
+ return this.pathNodes.get(path);
161
+ }
162
+
136
163
  sourceTextFor(range) {
137
164
  return sourceTextFor(this.allTerminalsFor(range));
138
165
  }
package/lib/evaluate.js CHANGED
@@ -13,7 +13,8 @@ import {
13
13
  import { StreamIterable, getStreamIterator } from '@bablr/agast-helpers/stream';
14
14
  import { printExpression } from '@bablr/agast-helpers/print';
15
15
  import { reifyExpression } from '@bablr/agast-vm-helpers';
16
- import { Path, Node } from './path.js';
16
+ import { Path } from './path.js';
17
+ import { Node } from './node.js';
17
18
  import { State } from './state.js';
18
19
  import { facades } from './facades.js';
19
20
 
@@ -84,7 +85,7 @@ const __evaluate = function* agast(ctx, strategy, options = {}) {
84
85
  case 'DoctypeTag': {
85
86
  const { attributes } = terminal.value;
86
87
  const doctypeTag = buildDoctypeTag(attributes);
87
- const rootPath = Path.from(ctx);
88
+ const rootPath = Path.from(ctx, doctypeTag);
88
89
 
89
90
  if (s.path) {
90
91
  throw new Error();
@@ -124,17 +125,18 @@ const __evaluate = function* agast(ctx, strategy, options = {}) {
124
125
  throw new Error('A reference must have a non-reference value');
125
126
  }
126
127
 
127
- if (!s.path.depth) {
128
+ if (s.node?.flags.token) {
128
129
  throw new Error();
129
130
  }
130
131
 
131
- if (s.node.flags.token) {
132
- throw new Error();
132
+ if (s.path.depth) {
133
+ s.node.resolver.consume(tag);
133
134
  }
134
135
 
135
- s.node.resolver.consume(tag);
136
-
137
136
  s.path = s.path.push(ctx, tag);
137
+ s.node = null;
138
+
139
+ ctx.tagPaths.set(tag, s.path);
138
140
 
139
141
  yield* s.emit(tag);
140
142
 
@@ -147,24 +149,47 @@ const __evaluate = function* agast(ctx, strategy, options = {}) {
147
149
 
148
150
  if (reference?.type !== 'Reference') throw new Error();
149
151
 
150
- s.path = s.path.parent;
151
-
152
152
  const gapTag = buildGap();
153
153
 
154
154
  s.held = null;
155
155
 
156
+ ctx.tagPaths.set(gapTag, s.path);
157
+
158
+ s.node = s.parentNode;
159
+ s.path = s.path.parent;
160
+
156
161
  yield* s.emit(gapTag);
157
162
 
158
163
  returnValue = gapTag;
159
164
  break;
160
165
  }
161
166
 
167
+ case 'Null': {
168
+ const reference = s.result;
169
+
170
+ if (reference?.type !== 'Reference') throw new Error();
171
+
172
+ const null_ = buildNull();
173
+
174
+ ctx.tagPaths.set(null_, s.path);
175
+
176
+ s.node = s.parentNode;
177
+ s.path = s.path.parent;
178
+
179
+ yield* s.emit(null_);
180
+
181
+ returnValue = null_;
182
+ break;
183
+ }
184
+
162
185
  case 'Shift': {
163
- const { tagNodes, prevTerminals } = ctx;
164
186
  const tag = buildShift();
165
187
 
166
- const finishedNode = tagNodes.get(s.result);
167
- const finishedPath = finishedNode.path;
188
+ const finishedNode = ctx.nodeForTag(s.result);
189
+ const ref = ctx.getPreviousTerminal(finishedNode.openTag);
190
+ const finishedPath = ctx.pathForTag(ref);
191
+
192
+ ctx.pathNodes.set(finishedPath, null);
168
193
 
169
194
  s.held = { node: finishedNode, path: finishedPath };
170
195
 
@@ -180,21 +205,6 @@ const __evaluate = function* agast(ctx, strategy, options = {}) {
180
205
  break;
181
206
  }
182
207
 
183
- case 'Null': {
184
- const reference = s.result;
185
-
186
- if (reference?.type !== 'Reference') throw new Error();
187
-
188
- s.path = s.path.parent;
189
-
190
- const null_ = buildNull();
191
-
192
- yield* s.emit(null_);
193
-
194
- returnValue = null_;
195
- break;
196
- }
197
-
198
208
  case 'OpenNodeTag': {
199
209
  const { flags, language, type, intrinsicValue, attributes } = terminal.value;
200
210
  const { unboundAttributes } = options || {};
@@ -202,10 +212,13 @@ const __evaluate = function* agast(ctx, strategy, options = {}) {
202
212
  const openTag = buildNodeOpenTag(flags, language, type, intrinsicValue, attributes);
203
213
 
204
214
  if (!type) {
205
- s.node = Node.from(s.path, openTag);
215
+ s.node = Node.from(openTag);
216
+ ctx.pathNodes.set(s.path, s.node);
217
+ ctx.pathNodes.set(s.node, s.path);
206
218
  ctx.tagNodes.set(openTag, s.node);
219
+ ctx.tagPaths.set(openTag, s.path);
207
220
  } else {
208
- if (!flags.trivia && !flags.escape && s.node.type) {
221
+ if (!flags.trivia && !flags.escape) {
209
222
  if (
210
223
  reference.type !== 'Reference' &&
211
224
  reference.type !== 'Shift' &&
@@ -215,37 +228,35 @@ const __evaluate = function* agast(ctx, strategy, options = {}) {
215
228
  }
216
229
  }
217
230
 
218
- const { flags: openFlags } = openTag.value;
219
-
220
- if (!(openFlags.trivia || openFlags.escape) && !s.path.depth) {
221
- const tag = buildReference('root', false);
222
- s.path = s.path.push(ctx, tag);
223
- s.node.resolver.consume(tag);
224
- }
225
-
226
- const newNode = s.node.push(s.path, openTag);
231
+ const newNode = new Node(openTag);
227
232
 
228
233
  newNode.unboundAttributes = new Set(unboundAttributes);
229
234
 
235
+ s.node = newNode;
236
+ if (flags.trivia || flags.escape) {
237
+ s.path = s.path.push(ctx, null);
238
+ }
239
+
240
+ ctx.pathNodes.set(newNode, s.path);
241
+ ctx.pathNodes.set(s.path, newNode);
230
242
  ctx.tagNodes.set(openTag, newNode);
243
+ ctx.tagPaths.set(openTag, s.path);
231
244
 
232
- if (!intrinsicValue) {
233
- s.node = newNode;
234
- } else {
245
+ if (intrinsicValue) {
246
+ newNode.closeTag = newNode.openTag;
247
+ s.node = s.parentNode;
235
248
  s.path = s.path.parent;
236
249
 
237
- if (s.path.depth > 1) {
238
- const { properties } = s.node;
239
- const { name: refName, isArray } = reference.value;
240
-
241
- if (!isArray) {
242
- properties.set(refName, [openTag, openTag]);
243
- } else {
244
- if (!properties.has(refName)) {
245
- properties.set(refName, []);
246
- }
247
- properties.get(refName).push([openTag, openTag]);
250
+ const { properties } = s.node;
251
+ const { name: refName, isArray } = reference.value;
252
+
253
+ if (!isArray) {
254
+ properties.set(refName, [openTag, openTag]);
255
+ } else {
256
+ if (!properties.has(refName)) {
257
+ properties.set(refName, []);
248
258
  }
259
+ properties.get(refName).push([openTag, openTag]);
249
260
  }
250
261
  }
251
262
  }
@@ -269,7 +280,7 @@ const __evaluate = function* agast(ctx, strategy, options = {}) {
269
280
 
270
281
  if (!type) throw new Error(`CloseNodeTag must have type`);
271
282
 
272
- if (s.path.depth > 1 && type !== openType)
283
+ if (type !== openType)
273
284
  throw new Error(
274
285
  `Grammar close {type: ${type}} did not match open {type: ${openType}}`,
275
286
  );
@@ -277,30 +288,26 @@ const __evaluate = function* agast(ctx, strategy, options = {}) {
277
288
  if (!flags.escape && !flags.trivia) {
278
289
  const { name: refName, isArray } = s.path.reference.value;
279
290
 
280
- // is this right?
281
- if (s.path.depth > 2) {
282
- const { properties } = s.node.parent;
283
-
284
- if (!isArray) {
285
- properties.set(refName, [openTag, closeTag]);
286
- } else {
287
- if (!properties.has(refName)) {
288
- properties.set(refName, []);
289
- }
290
- properties.get(refName).push([openTag, closeTag]);
291
+ const { properties } = ctx.nodeForPath(s.path.parent);
292
+
293
+ if (!isArray) {
294
+ properties.set(refName, [openTag, closeTag]);
295
+ } else {
296
+ if (!properties.has(refName)) {
297
+ properties.set(refName, []);
291
298
  }
299
+ properties.get(refName).push([openTag, closeTag]);
292
300
  }
293
301
  }
294
302
 
295
303
  ctx.tagNodes.set(closeTag, s.node);
304
+ ctx.tagPaths.set(closeTag, s.path);
296
305
 
297
306
  s.node.closeTag = closeTag;
298
307
 
299
- s.node = s.node.parent;
308
+ s.node = s.parentNode;
300
309
 
301
- if (!(flags.trivia || flags.escape)) {
302
- s.path = s.path.parent;
303
- }
310
+ s.path = s.path.parent;
304
311
  }
305
312
 
306
313
  yield* s.emit(closeTag, flags.expression);
@@ -347,25 +354,25 @@ const __evaluate = function* agast(ctx, strategy, options = {}) {
347
354
  if (value != null) {
348
355
  const { flags, language, type, intrinsicValue } = openTag.value;
349
356
  const attributes = { ...openTag.value.attributes, [key]: value };
350
- const newStartTag = buildNodeOpenTag(flags, language, type, intrinsicValue, attributes);
357
+ const newOpenTag = buildNodeOpenTag(flags, language, type, intrinsicValue, attributes);
351
358
 
352
- let startNext = ctx.nextTerminals.get(openTag);
359
+ let openNext = ctx.nextTerminals.get(openTag);
353
360
  let startPrev = ctx.prevTerminals.get(openTag);
354
361
 
355
- ctx.prevTerminals.set(newStartTag, startPrev);
356
- ctx.nextTerminals.set(startPrev, newStartTag);
362
+ ctx.prevTerminals.set(newOpenTag, startPrev);
363
+ ctx.nextTerminals.set(startPrev, newOpenTag);
357
364
 
358
- ctx.tagNodes.set(newStartTag, s.node);
365
+ ctx.tagNodes.set(newOpenTag, ctx.tagNodes.get(openTag));
359
366
 
360
- if (startNext) {
361
- ctx.nextTerminals.set(newStartTag, startNext);
362
- ctx.prevTerminals.set(startNext, newStartTag);
367
+ if (openNext) {
368
+ ctx.nextTerminals.set(newOpenTag, openNext);
369
+ ctx.prevTerminals.set(openNext, newOpenTag);
363
370
  } else {
364
371
  // could this terminal be stored anywhere else?
365
- s.result = newStartTag;
372
+ s.result = newOpenTag;
366
373
  }
367
374
 
368
- s.node.openTag = newStartTag;
375
+ s.node.openTag = newOpenTag;
369
376
  }
370
377
 
371
378
  if (!unboundAttributes.size) {
package/lib/node.js ADDED
@@ -0,0 +1,99 @@
1
+ import { Resolver } from '@bablr/agast-helpers/tree';
2
+ import { facades, actuals } from './facades.js';
3
+
4
+ export const NodeFacade = class AgastNodeFacade {
5
+ constructor(path) {
6
+ facades.set(path, this);
7
+ }
8
+
9
+ get language() {
10
+ return actuals.get(this).language;
11
+ }
12
+
13
+ get type() {
14
+ return actuals.get(this).type;
15
+ }
16
+
17
+ get range() {
18
+ return actuals.get(this).range;
19
+ }
20
+
21
+ get openTag() {
22
+ return actuals.get(this).openTag;
23
+ }
24
+
25
+ get closeTag() {
26
+ return actuals.get(this).closeTag;
27
+ }
28
+
29
+ get flags() {
30
+ return actuals.get(this).flags;
31
+ }
32
+
33
+ get attributes() {
34
+ return actuals.get(this).attributes;
35
+ }
36
+ };
37
+
38
+ export const Node = class AgastNode {
39
+ static from(openTag) {
40
+ return new AgastNode(openTag);
41
+ }
42
+
43
+ constructor(
44
+ openTag,
45
+ closeTag = null,
46
+ properties = new Map(),
47
+ resolver = new Resolver(),
48
+ unboundAttributes = null,
49
+ ) {
50
+ this.openTag = openTag;
51
+ this.closeTag = closeTag;
52
+ this.properties = properties;
53
+ this.resolver = resolver;
54
+ this.unboundAttributes = unboundAttributes;
55
+ }
56
+
57
+ get language() {
58
+ return this.openTag.value?.language;
59
+ }
60
+
61
+ get type() {
62
+ return this.openTag.value?.type || null;
63
+ }
64
+
65
+ get flags() {
66
+ return this.openTag.value?.flags || {};
67
+ }
68
+
69
+ get attributes() {
70
+ return this.openTag.value?.attributes || {};
71
+ }
72
+
73
+ get range() {
74
+ return [this.openTag, this.closeTag];
75
+ }
76
+
77
+ branch() {
78
+ const { openTag, closeTag, properties, resolver, unboundAttributes } = this;
79
+
80
+ return new Node(
81
+ openTag,
82
+ closeTag,
83
+ new Map(properties), // there is probably a better way
84
+ resolver.branch(),
85
+ new Set(unboundAttributes),
86
+ );
87
+ }
88
+
89
+ accept(node) {
90
+ this.openTag = node.openTag;
91
+ this.closeTag = node.closeTag;
92
+ this.properties = node.properties;
93
+ this.unboundAttributes = node.unboundAttributes;
94
+
95
+ this.resolver.accept(node.resolver);
96
+
97
+ return this;
98
+ }
99
+ };
package/lib/path.js CHANGED
@@ -1,58 +1,7 @@
1
1
  import { WeakStackFrame } from '@bablr/weak-stack';
2
- import { Resolver } from '@bablr/agast-helpers/tree';
3
2
  import { skipToDepth, buildSkips } from './utils/skip.js';
4
3
  import { facades, actuals } from './facades.js';
5
4
 
6
- export const NodeFacade = class AgastNodeFacade {
7
- constructor(path) {
8
- facades.set(path, this);
9
- }
10
-
11
- get language() {
12
- return actuals.get(this).language;
13
- }
14
-
15
- get type() {
16
- return actuals.get(this).type;
17
- }
18
-
19
- get path() {
20
- return actuals.get(this).path;
21
- }
22
-
23
- get parent() {
24
- return facades.get(actuals.get(this).parent);
25
- }
26
-
27
- get range() {
28
- return actuals.get(this).range;
29
- }
30
-
31
- get openTag() {
32
- return actuals.get(this).openTag;
33
- }
34
-
35
- get closeTag() {
36
- return actuals.get(this).closeTag;
37
- }
38
-
39
- get depth() {
40
- return actuals.get(this).depth;
41
- }
42
-
43
- get flags() {
44
- return actuals.get(this).flags;
45
- }
46
-
47
- get attributes() {
48
- return actuals.get(this).attributes;
49
- }
50
-
51
- at(depth) {
52
- return facades.get(actuals.get(this).at(depth));
53
- }
54
- };
55
-
56
5
  export const PathFacade = class AgastPathFacade {
57
6
  constructor(path) {
58
7
  facades.set(path, this);
@@ -83,85 +32,6 @@ export const PathFacade = class AgastPathFacade {
83
32
  }
84
33
  };
85
34
 
86
- export const Node = class AgastNode extends WeakStackFrame {
87
- static from(path, openTag) {
88
- return AgastNode.create(path, openTag);
89
- }
90
-
91
- constructor(
92
- path,
93
- openTag,
94
- closeTag = null,
95
- properties = new Map(),
96
- resolver = new Resolver(),
97
- unboundAttributes = null,
98
- ) {
99
- super();
100
-
101
- this.path = path;
102
- this.openTag = openTag;
103
- this.closeTag = closeTag;
104
- this.properties = properties;
105
- this.resolver = resolver;
106
- this.unboundAttributes = unboundAttributes;
107
-
108
- buildSkips(this);
109
- }
110
-
111
- get language() {
112
- return this.openTag.value?.language;
113
- }
114
-
115
- get type() {
116
- return this.openTag.value?.type || null;
117
- }
118
-
119
- get flags() {
120
- return this.openTag.value?.flags || {};
121
- }
122
-
123
- get attributes() {
124
- return this.openTag.value?.attributes || {};
125
- }
126
-
127
- at(depth) {
128
- return skipToDepth(depth, this);
129
- }
130
-
131
- *parents(includeSelf = false) {
132
- if (includeSelf) yield this;
133
- let parent = this;
134
- while ((parent = parent.parent)) {
135
- yield parent;
136
- }
137
- }
138
-
139
- branch() {
140
- const { path, openTag, closeTag, properties, resolver, unboundAttributes } = this;
141
-
142
- return this.replace(
143
- path,
144
- openTag,
145
- closeTag,
146
- new Map(properties), // there is probably a better way
147
- resolver.branch(),
148
- new Set(unboundAttributes),
149
- );
150
- }
151
-
152
- accept(node) {
153
- this.path = node.path;
154
- this.openTag = node.openTag;
155
- this.closeTag = node.closeTag;
156
- this.properties = node.properties;
157
- this.unboundAttributes = node.unboundAttributes;
158
-
159
- this.resolver.accept(node.resolver);
160
-
161
- return this;
162
- }
163
- };
164
-
165
35
  export const Path = class AgastPath extends WeakStackFrame {
166
36
  static from(context, tag) {
167
37
  return Path.create(context, tag);
@@ -170,7 +40,7 @@ export const Path = class AgastPath extends WeakStackFrame {
170
40
  constructor(context, reference) {
171
41
  super();
172
42
 
173
- if (reference && reference.type !== 'Reference') {
43
+ if (reference && reference.type !== 'Reference' && reference.type !== 'DoctypeTag') {
174
44
  throw new Error('Invalid reference for path');
175
45
  }
176
46
 
@@ -182,6 +52,14 @@ export const Path = class AgastPath extends WeakStackFrame {
182
52
  new PathFacade(this);
183
53
  }
184
54
 
55
+ get name() {
56
+ return this.reference?.value.name || '[anonymous]';
57
+ }
58
+
59
+ get isArray() {
60
+ return this.reference?.value.isArray || false;
61
+ }
62
+
185
63
  at(depth) {
186
64
  return skipToDepth(depth, this);
187
65
  }
package/lib/state.js CHANGED
@@ -28,6 +28,10 @@ export const StateFacade = class AgastStateFacade {
28
28
  return actuals.get(this).node;
29
29
  }
30
30
 
31
+ get parentNode() {
32
+ return actuals.get(this).parentNode;
33
+ }
34
+
31
35
  get holding() {
32
36
  return actuals.get(this).holding;
33
37
  }
@@ -73,7 +77,7 @@ export const State = class AgastState extends WeakStackFrame {
73
77
  }
74
78
 
75
79
  *emit(terminal, suppressEmit) {
76
- const { prevTerminals, nextTerminals, tagNodes } = this.context;
80
+ const { prevTerminals, nextTerminals } = this.context;
77
81
 
78
82
  if (terminal) {
79
83
  if (prevTerminals.has(terminal)) {
@@ -107,7 +111,7 @@ export const State = class AgastState extends WeakStackFrame {
107
111
  !(
108
112
  emittable.type === 'OpenNodeTag' &&
109
113
  emittable.value.type &&
110
- tagNodes.get(emittable).unboundAttributes?.size
114
+ this.context.nodeForTag(emittable).unboundAttributes?.size
111
115
  )
112
116
  ) {
113
117
  yield emittable;
@@ -131,20 +135,36 @@ export const State = class AgastState extends WeakStackFrame {
131
135
  return !!this.parent;
132
136
  }
133
137
 
138
+ get parentNode() {
139
+ return this.ctx.nodeForPath(this.path.parent);
140
+ }
141
+
134
142
  branch() {
135
143
  const { context, path, node, result, emitted, held } = this;
136
144
 
137
- return this.push(context, path, node.branch(), result, emitted, held);
145
+ const newNode = node && node.branch();
146
+
147
+ if (newNode?.openTag) context.tagNodes.set(newNode.openTag, newNode);
148
+ if (newNode?.closeTag) context.tagNodes.set(newNode.closeTag, newNode);
149
+
150
+ return this.push(context, path, newNode, result, emitted, held);
138
151
  }
139
152
 
140
153
  accept() {
141
- const { parent } = this;
154
+ const { parent, context } = this;
142
155
 
143
156
  if (!parent) {
144
157
  return null;
145
158
  }
146
159
 
147
- parent.node.accept(this.node);
160
+ if (this.node && parent.node) {
161
+ parent.node.accept(this.node, context);
162
+ } else {
163
+ parent.node = this.node;
164
+ }
165
+
166
+ if (this.node?.openTag) context.tagNodes.set(parent.node.openTag, parent.node);
167
+ if (this.node?.closeTag) context.tagNodes.set(parent.node.closeTag, parent.node);
148
168
 
149
169
  // emitted isn't used here and probably doesn't need to be part of state
150
170
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bablr/agast-vm",
3
3
  "description": "A VM providing DOM-like guarantees about agAST trees",
4
- "version": "0.2.0",
4
+ "version": "0.3.0",
5
5
  "author": "Conrad Buck<conartist6@gmail.com>",
6
6
  "type": "module",
7
7
  "files": [
@@ -11,24 +11,19 @@
11
11
  ".": "./lib/index.js"
12
12
  },
13
13
  "sideEffects": false,
14
- "scripts": {
15
- "test": "node ./test/runner.js"
16
- },
17
14
  "dependencies": {
18
- "@bablr/agast-helpers": "0.1.6",
19
- "@bablr/agast-vm-helpers": "0.1.5",
15
+ "@bablr/agast-helpers": "0.2.0",
16
+ "@bablr/agast-vm-helpers": "0.2.0",
20
17
  "@bablr/coroutine": "0.1.0",
21
18
  "@bablr/weak-stack": "0.1.0"
22
19
  },
23
20
  "devDependencies": {
24
21
  "@bablr/agast-vm-strategy-passthrough": "github:bablr-lang/agast-vm-strategy-passthrough#2bd3a0c7311037af92c5b81941c79161499f6c9e",
25
22
  "@bablr/eslint-config-base": "github:bablr-lang/eslint-config-base#49f5952efed27f94ee9b94340eb1563c440bf64e",
26
- "@bablr/strategy_enhancer-debug-log": "0.1.1",
27
23
  "enhanced-resolve": "^5.12.0",
28
24
  "eslint": "^8.32.0",
29
25
  "eslint-import-resolver-enhanced-resolve": "^1.0.5",
30
26
  "eslint-plugin-import": "^2.27.5",
31
- "expect": "29.7.0",
32
27
  "iter-tools-es": "^7.3.1",
33
28
  "prettier": "^2.6.2"
34
29
  },