as-test 1.1.1 → 1.1.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 CHANGED
@@ -1,11 +1,19 @@
1
1
  # Change Log
2
2
 
3
- ## v1.1.1
3
+ ## 2026-05-13 - v1.1.2
4
+
5
+ - update build and run faliures to provide helpful error messages and reproduction commands and instructions
6
+ - remove confirmation from ast clean
7
+ - feat: make coverage gaps hierarchical and easier to scan, with parent-before-child grouping, tree-style connectors, collapsed nested gaps by default, and `--show-coverage=all` / `--verbose` expansion.
8
+ - feat: add richer coverage point names including `DefaultValue`, `Ternary`, `IfBranch`, `Assignment`, `Loop`, `Return`, and `Throw` so uncovered points describe the actual construct instead of falling back to broad labels.
9
+ - fix: make coverage snippets underline the emitted construct span instead of recomputing from the raw column, so cases like inline `if (...) ...` and assignments highlight the right text.
10
+
11
+ ## 2026-05-12 -v1.1.1
4
12
 
5
13
  - add `ast clean` command to remove build outputs, coverage outputs, crash reports, and logs.
6
14
  - remove deps
7
15
 
8
- ## v1.1.0
16
+ ## 2026-05-12 -v1.1.0
9
17
 
10
18
  ### Upgrading to 1.1.0
11
19
 
@@ -46,7 +54,7 @@
46
54
 
47
55
  - feat: add per-mode `default: boolean` selection so modes can be included in implicit runs or kept manual-only.
48
56
  - feat: add `ast clean` to remove configured build outputs, coverage outputs, crash reports, and logs.
49
- - feat: make `ast clean` remove everything by default, prompt with `[Y/n]` before a full clean, and allow `-f` / `--force` to skip that confirmation.
57
+ - feat: make `ast clean` remove everything by default without prompting.
50
58
  - fix: restore unnamed root-config execution alongside named default modes when `--mode` is omitted.
51
59
  - fix: make `ast clean` ignore mode `default: false` flags and treat an omitted `--mode` as a full clean across every configured mode.
52
60
  - fix: make `ast clean --mode ...` stay scoped to the selected mode(s) and skip shared output paths that are still owned by unselected modes instead of deleting them.
package/README.md CHANGED
@@ -253,18 +253,25 @@ fuzz("bounded integer addition", (left: i32, right: i32): bool => {
253
253
  Pass a third argument to override the operation count for one target without changing the global fuzz config:
254
254
 
255
255
  ```ts
256
- fuzz("hot path stays stable", (): void => {
257
- expect(1 + 1).toBe(2);
258
- }, 250);
256
+ fuzz(
257
+ "hot path stays stable",
258
+ (): void => {
259
+ expect(1 + 1).toBe(2);
260
+ },
261
+ 250,
262
+ );
259
263
  ```
260
264
 
261
265
  Or pass it as the second argument to `.generate(...)`:
262
266
 
263
267
  ```ts
264
- fuzz("ascii strings survive concatenation boundaries", (input: string): bool => {
265
- expect(input.length <= 40).toBe(true);
266
- return true;
267
- }).generate((seed: FuzzSeed, run: (input: string) => bool): void => {
268
+ fuzz(
269
+ "ascii strings survive concatenation boundaries",
270
+ (input: string): bool => {
271
+ expect(input.length <= 40).toBe(true);
272
+ return true;
273
+ },
274
+ ).generate((seed: FuzzSeed, run: (input: string) => bool): void => {
268
275
  run(seed.string({ charset: "ascii", min: 0, max: 40 }));
269
276
  }, 250);
270
277
  ```
@@ -336,168 +336,190 @@
336
336
  }
337
337
  ]
338
338
  },
339
- "outDir": {
340
- "type": "string",
341
- "description": "Mode-specific build output directory. If omitted, defaults to <outDir>/<mode-name>."
342
- },
343
- "logs": {
344
- "type": "string",
345
- "description": "Mode-specific log output directory."
346
- },
347
- "coverageDir": {
348
- "type": "string",
349
- "description": "Mode-specific coverage output directory."
350
- },
351
- "snapshotDir": {
352
- "type": "string",
353
- "description": "Mode-specific snapshot directory."
354
- },
355
- "config": {
356
- "type": "string",
357
- "description": "Mode-specific asconfig path or \"none\"."
358
- },
359
- "coverage": {
360
- "description": "Mode-specific coverage settings.",
361
- "oneOf": [
362
- {
363
- "type": "boolean"
364
- },
365
- {
366
- "type": "object",
367
- "additionalProperties": true,
368
- "properties": {
369
- "enabled": {
370
- "type": "boolean"
371
- },
372
- "includeSpecs": {
373
- "type": "boolean"
374
- }
375
- }
376
- }
377
- ]
378
- },
379
- "fuzz": {
380
- "type": "object",
381
- "additionalProperties": false,
382
- "description": "Mode-specific fuzz overrides applied before running `ast fuzz` or `ast test --fuzz` in this mode.",
383
- "properties": {
384
- "input": {
385
- "type": "array",
386
- "items": {
387
- "type": "string"
388
- }
389
- },
390
- "runs": {
391
- "type": "number"
392
- },
393
- "seed": {
394
- "type": "number"
395
- },
396
- "maxInputBytes": {
397
- "type": "number"
398
- },
399
- "target": {
339
+ "outDir": {
400
340
  "type": "string",
401
- "enum": ["bindings"]
341
+ "description": "Mode-specific build output directory. If omitted, defaults to <outDir>/<mode-name>."
402
342
  },
403
- "corpusDir": {
404
- "type": "string"
343
+ "logs": {
344
+ "type": "string",
345
+ "description": "Mode-specific log output directory."
405
346
  },
406
- "crashDir": {
407
- "type": "string"
408
- }
409
- }
410
- },
411
- "buildOptions": {
412
- "type": "object",
413
- "additionalProperties": false,
414
- "properties": {
415
- "cmd": {
347
+ "coverageDir": {
416
348
  "type": "string",
417
- "description": "Mode-specific custom build command template."
349
+ "description": "Mode-specific coverage output directory."
418
350
  },
419
- "args": {
420
- "type": "array",
421
- "items": {
422
- "type": "string"
423
- }
351
+ "snapshotDir": {
352
+ "type": "string",
353
+ "description": "Mode-specific snapshot directory."
424
354
  },
425
- "target": {
355
+ "config": {
426
356
  "type": "string",
427
- "enum": ["wasi", "bindings", "web"]
357
+ "description": "Mode-specific asconfig path or \"none\"."
428
358
  },
429
- "env": {
430
- "description": "Mode-specific build environment overrides.",
359
+ "coverage": {
360
+ "description": "Mode-specific coverage settings.",
431
361
  "oneOf": [
432
362
  {
433
- "type": "string"
363
+ "type": "boolean"
434
364
  },
435
365
  {
366
+ "type": "object",
367
+ "additionalProperties": true,
368
+ "properties": {
369
+ "enabled": {
370
+ "type": "boolean"
371
+ },
372
+ "includeSpecs": {
373
+ "type": "boolean"
374
+ }
375
+ }
376
+ }
377
+ ]
378
+ },
379
+ "fuzz": {
380
+ "type": "object",
381
+ "additionalProperties": false,
382
+ "description": "Mode-specific fuzz overrides applied before running `ast fuzz` or `ast test --fuzz` in this mode.",
383
+ "properties": {
384
+ "input": {
436
385
  "type": "array",
437
386
  "items": {
438
387
  "type": "string"
439
388
  }
440
389
  },
441
- {
442
- "type": "object",
443
- "additionalProperties": {
444
- "type": "string"
445
- }
390
+ "runs": {
391
+ "type": "number"
392
+ },
393
+ "seed": {
394
+ "type": "number"
395
+ },
396
+ "maxInputBytes": {
397
+ "type": "number"
398
+ },
399
+ "target": {
400
+ "type": "string",
401
+ "enum": ["bindings"]
402
+ },
403
+ "corpusDir": {
404
+ "type": "string"
405
+ },
406
+ "crashDir": {
407
+ "type": "string"
446
408
  }
447
- ]
448
- }
449
- }
450
- },
451
- "runOptions": {
452
- "type": "object",
453
- "additionalProperties": false,
454
- "properties": {
455
- "runtime": {
409
+ }
410
+ },
411
+ "buildOptions": {
456
412
  "type": "object",
457
413
  "additionalProperties": false,
458
414
  "properties": {
459
415
  "cmd": {
460
416
  "type": "string",
461
- "description": "Mode-specific runtime command."
417
+ "description": "Mode-specific custom build command template."
418
+ },
419
+ "args": {
420
+ "type": "array",
421
+ "items": {
422
+ "type": "string"
423
+ }
462
424
  },
463
- "browser": {
425
+ "target": {
464
426
  "type": "string",
465
- "description": "Mode-specific browser for web targets. Use chrome, chromium, firefox, webkit, or an executable path."
427
+ "enum": ["wasi", "bindings", "web"]
428
+ },
429
+ "env": {
430
+ "description": "Mode-specific build environment overrides.",
431
+ "oneOf": [
432
+ {
433
+ "type": "string"
434
+ },
435
+ {
436
+ "type": "array",
437
+ "items": {
438
+ "type": "string"
439
+ }
440
+ },
441
+ {
442
+ "type": "object",
443
+ "additionalProperties": {
444
+ "type": "string"
445
+ }
446
+ }
447
+ ]
466
448
  }
467
449
  }
468
450
  },
469
- "reporter": {
470
- "description": "Mode-specific reporter config.",
471
- "oneOf": [
472
- {
473
- "type": "string"
474
- },
475
- {
451
+ "runOptions": {
452
+ "type": "object",
453
+ "additionalProperties": false,
454
+ "properties": {
455
+ "runtime": {
476
456
  "type": "object",
477
457
  "additionalProperties": false,
478
458
  "properties": {
479
- "name": {
459
+ "cmd": {
460
+ "type": "string",
461
+ "description": "Mode-specific runtime command."
462
+ },
463
+ "browser": {
464
+ "type": "string",
465
+ "description": "Mode-specific browser for web targets. Use chrome, chromium, firefox, webkit, or an executable path."
466
+ }
467
+ }
468
+ },
469
+ "reporter": {
470
+ "description": "Mode-specific reporter config.",
471
+ "oneOf": [
472
+ {
480
473
  "type": "string"
481
474
  },
482
- "options": {
475
+ {
476
+ "type": "object",
477
+ "additionalProperties": false,
478
+ "properties": {
479
+ "name": {
480
+ "type": "string"
481
+ },
482
+ "options": {
483
+ "type": "array",
484
+ "items": {
485
+ "type": "string"
486
+ }
487
+ },
488
+ "outDir": {
489
+ "type": "string"
490
+ },
491
+ "outFile": {
492
+ "type": "string"
493
+ }
494
+ },
495
+ "required": ["name"]
496
+ }
497
+ ]
498
+ },
499
+ "env": {
500
+ "description": "Mode-specific runtime environment overrides.",
501
+ "oneOf": [
502
+ {
503
+ "type": "string"
504
+ },
505
+ {
483
506
  "type": "array",
484
507
  "items": {
485
508
  "type": "string"
486
509
  }
487
510
  },
488
- "outDir": {
489
- "type": "string"
490
- },
491
- "outFile": {
492
- "type": "string"
511
+ {
512
+ "type": "object",
513
+ "additionalProperties": {
514
+ "type": "string"
515
+ }
493
516
  }
494
- },
495
- "required": ["name"]
517
+ ]
496
518
  }
497
- ]
519
+ }
498
520
  },
499
521
  "env": {
500
- "description": "Mode-specific runtime environment overrides.",
522
+ "description": "Mode-wide environment variables merged before build/run-specific env.",
501
523
  "oneOf": [
502
524
  {
503
525
  "type": "string"
@@ -517,28 +539,6 @@
517
539
  ]
518
540
  }
519
541
  }
520
- },
521
- "env": {
522
- "description": "Mode-wide environment variables merged before build/run-specific env.",
523
- "oneOf": [
524
- {
525
- "type": "string"
526
- },
527
- {
528
- "type": "array",
529
- "items": {
530
- "type": "string"
531
- }
532
- },
533
- {
534
- "type": "object",
535
- "additionalProperties": {
536
- "type": "string"
537
- }
538
- }
539
- ]
540
- }
541
- }
542
542
  }
543
543
  ]
544
544
  },
@@ -8,21 +8,24 @@ fuzz("bounded integer addition", (left: i32, right: i32): bool => {
8
8
  run(seed.i32({ min: -1000, max: 1000 }), seed.i32({ min: -1000, max: 1000 }));
9
9
  });
10
10
 
11
- fuzz("numeric matchers stay consistent for bounded integers", (value: i32): bool => {
12
- expect(value).toBeNumber();
13
- expect(value).toBeInteger();
14
- expect(value).toBeFinite();
15
- expect(value).toBe(value);
16
- expect(value).toBeGreaterOrEqualTo(-1000);
17
- expect(value).toBeLessThanOrEqualTo(1000);
11
+ fuzz(
12
+ "numeric matchers stay consistent for bounded integers",
13
+ (value: i32): bool => {
14
+ expect(value).toBeNumber();
15
+ expect(value).toBeInteger();
16
+ expect(value).toBeFinite();
17
+ expect(value).toBe(value);
18
+ expect(value).toBeGreaterOrEqualTo(-1000);
19
+ expect(value).toBeLessThanOrEqualTo(1000);
18
20
 
19
- if (value != 0) {
20
- expect(value).toBeTruthy();
21
- } else {
22
- expect(value).toBeFalsy();
23
- }
21
+ if (value != 0) {
22
+ expect(value).toBeTruthy();
23
+ } else {
24
+ expect(value).toBeFalsy();
25
+ }
24
26
 
25
- return true;
26
- }).generate((seed: FuzzSeed, run: (value: i32) => bool): void => {
27
+ return true;
28
+ },
29
+ ).generate((seed: FuzzSeed, run: (value: i32) => bool): void => {
27
30
  run(seed.i32({ min: -1000, max: 1000 }));
28
31
  }, 250);
@@ -59,8 +59,10 @@ fuzz("seed perf bytes/array", (_n: i32): bool => true).generate(
59
59
  let score = 0;
60
60
  for (let i = 0; i < 64; i++) {
61
61
  score += seed.bytes(PERF_BYTES).length;
62
- score += seed.array<i32>((s) => s.i32({ min: -9, max: 9 }), PERF_ARRAY)
63
- .length;
62
+ score += seed.array<i32>(
63
+ (s) => s.i32({ min: -9, max: 9 }),
64
+ PERF_ARRAY,
65
+ ).length;
64
66
  }
65
67
  run(score);
66
68
  },
@@ -4,6 +4,10 @@ export class CoverPoint {
4
4
  public line: i32 = 0;
5
5
  public column: i32 = 0;
6
6
  public type: string = "";
7
+ public parentHash: string = "";
8
+ public scopeKind: string = "";
9
+ public scopeName: string = "";
10
+ public depth: i32 = 0;
7
11
  public executed: boolean = false;
8
12
  }
9
13
 
@@ -29,6 +33,10 @@ export function __REGISTER_RAW(
29
33
  line: i32,
30
34
  column: i32,
31
35
  type: string,
36
+ parentHash: string = "",
37
+ scopeKind: string = "",
38
+ scopeName: string = "",
39
+ depth: i32 = 0,
32
40
  ): void {
33
41
  if (Coverage.SN.allIndex.has(hash)) return;
34
42
  const point = new CoverPoint();
@@ -37,6 +45,10 @@ export function __REGISTER_RAW(
37
45
  point.line = line;
38
46
  point.column = column;
39
47
  point.type = type;
48
+ point.parentHash = parentHash;
49
+ point.scopeKind = scopeKind;
50
+ point.scopeName = scopeName;
51
+ point.depth = depth;
40
52
  Coverage.SN.points++;
41
53
  Coverage.SN.allIndex.set(hash, Coverage.SN.all.length);
42
54
  Coverage.SN.all.push(point);
package/assembly/index.ts CHANGED
@@ -445,10 +445,7 @@ function runFuzzers(): void {
445
445
  for (let i = 0; i < entryFuzzers.length; i++) {
446
446
  const fuzzer = unchecked(entryFuzzers[i]);
447
447
  prepareFuzzIteration();
448
- const result = fuzzer.run(
449
- config.seed,
450
- resolveFuzzerRuns(fuzzer, config),
451
- );
448
+ const result = fuzzer.run(config.seed, resolveFuzzerRuns(fuzzer, config));
452
449
  report.fuzzers.push(result);
453
450
  }
454
451
  sendReport(report.serialize());
@@ -551,6 +548,10 @@ class CoveragePointReport {
551
548
  column: i32 = 0;
552
549
  type: string = "";
553
550
  executed: bool = false;
551
+ parentHash: string = "";
552
+ scopeKind: string = "";
553
+ scopeName: string = "";
554
+ depth: i32 = 0;
554
555
 
555
556
  serialize(): string {
556
557
  return (
@@ -566,6 +567,14 @@ class CoveragePointReport {
566
567
  quote(this.type) +
567
568
  ',"executed":' +
568
569
  (this.executed ? "true" : "false") +
570
+ ',"parentHash":' +
571
+ quote(this.parentHash) +
572
+ ',"scopeKind":' +
573
+ quote(this.scopeKind) +
574
+ ',"scopeName":' +
575
+ quote(this.scopeName) +
576
+ ',"depth":' +
577
+ this.depth.toString() +
569
578
  "}"
570
579
  );
571
580
  }
@@ -635,6 +644,10 @@ function toCoveragePointReport(point: CoverPoint): CoveragePointReport {
635
644
  out.column = point.column;
636
645
  out.type = point.type;
637
646
  out.executed = point.executed;
647
+ out.parentHash = point.parentHash;
648
+ out.scopeKind = point.scopeKind;
649
+ out.scopeName = point.scopeName;
650
+ out.depth = point.depth;
638
651
  return out;
639
652
  }
640
653
 
@@ -354,7 +354,13 @@ export class Expectation<T> extends Tests {
354
354
  // @ts-ignore
355
355
  const passed = this._left.indexOf(value) >= 0;
356
356
  // @ts-ignore
357
- this._resolve(passed, "toMatch", q(this._left as string), q(value), message);
357
+ this._resolve(
358
+ passed,
359
+ "toMatch",
360
+ q(this._left as string),
361
+ q(value),
362
+ message,
363
+ );
358
364
  }
359
365
 
360
366
  /**