@matter/general 0.12.6-alpha.0-20250304-03716637c → 0.13.0-alpha.0-20250307-ebf84a05a

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.
@@ -390,12 +390,138 @@ export namespace Diagnostic {
390
390
  .map(([key]) => key)
391
391
  .join(" ");
392
392
  }
393
+
394
+ /**
395
+ * Extract message and stack diagnostic details.
396
+ */
397
+ export function messageAndStackFor(
398
+ error: any,
399
+ parentStack?: string[],
400
+ ): { message: string; stack?: unknown[]; stackLines?: string[] } {
401
+ let message: string | undefined;
402
+ let rawStack: string | undefined;
403
+ if (error !== undefined && error !== null) {
404
+ if (typeof error === "string" || typeof error === "number") {
405
+ return { message: `${error}` };
406
+ }
407
+ if ("message" in error) {
408
+ ({ message, stack: rawStack } = error);
409
+ } else if (error.message) {
410
+ message = typeof error.message === "string" ? message : error.toString();
411
+ }
412
+ }
413
+ if (message === undefined || message === null || message === "") {
414
+ if (error !== undefined && error !== null) {
415
+ message = error.constructor.name;
416
+ if (!message || message === "Error") {
417
+ message = "(unknown error)";
418
+ }
419
+ } else {
420
+ message = "(unknown error)";
421
+ }
422
+ }
423
+ if (!rawStack) {
424
+ return { message };
425
+ }
426
+
427
+ rawStack = rawStack.toString();
428
+
429
+ // Strip extra node garbage off stack from node asserts
430
+ rawStack = rawStack.replace(/^.*?\n\nError: /gs, "Error: ");
431
+
432
+ // Strip off redundant error tag from v8
433
+ if (rawStack.startsWith("Error: ")) {
434
+ rawStack = rawStack.slice(7);
435
+ }
436
+
437
+ // Strip off redundant message from v8
438
+ const pos = rawStack.indexOf(message);
439
+ if (pos !== -1) {
440
+ rawStack = rawStack.slice(pos + message.length).trim();
441
+ }
442
+
443
+ // Extract raw lines
444
+ let stackLines = rawStack
445
+ .split("\n")
446
+ .map(line => line.trim())
447
+ .filter(line => line !== "");
448
+
449
+ // Node helpfully gives us this if there's no message. It's not even the name of the error class, just "Error"
450
+ if (stackLines[0] === "Error") {
451
+ stackLines.shift();
452
+ }
453
+
454
+ // If there's a parent stack, identify the portion of the stack in common so we don't have to repeat it. The stacks
455
+ // may be truncated by the VM so this is not 100% guaranteed correct with recursive functions, but accidental
456
+ // mismatches are unlikely
457
+ let truncatedToParent = false;
458
+ if (parentStack) {
459
+ let truncateTo = 0;
460
+
461
+ // For each line in the stack, find the line in the parent. Skip the last two lines because truncating them
462
+ // won't save space
463
+ stackSearch: for (; truncateTo < stackLines.length - 1; truncateTo++) {
464
+ let parentPos = parentStack.indexOf(stackLines[truncateTo]);
465
+ if (parentPos === -1) {
466
+ continue;
467
+ }
468
+
469
+ // Found the line. If all subsequent lines match then we truncate. If either stack terminates before the
470
+ // other, assume the stacks are truncated and consider a match
471
+ parentPos++;
472
+ for (
473
+ let pos = truncateTo + 1;
474
+ pos < stackLines.length && parentPos < parentStack.length;
475
+ pos++, parentPos++
476
+ ) {
477
+ if (stackLines[pos] !== parentStack[parentPos]) {
478
+ continue stackSearch;
479
+ }
480
+ }
481
+
482
+ // Found a match. Truncate but leave the top-most shared frame to make it clear where the commonality
483
+ // with the parent starts
484
+ stackLines = stackLines.slice(0, truncateTo + 1);
485
+ truncatedToParent = true;
486
+ break;
487
+ }
488
+ }
489
+
490
+ // Spiff up stack lines a bit
491
+ const stack = Array<unknown>();
492
+ for (const line of stackLines) {
493
+ const match1 = line.match(/^at\s+(?:(\S|\S.*\S)\s+\(([^)]+)\)|(<anonymous>))$/);
494
+ if (match1) {
495
+ const value = [Diagnostic.weak("at "), match1[1] ?? match1[3]];
496
+ if (match1[2] !== undefined) {
497
+ value.push(Diagnostic.weak(" ("), Diagnostic.weak(match1[2]), Diagnostic.weak(")"));
498
+ }
499
+ stack.push(Diagnostic.squash(...value));
500
+ continue;
501
+ }
502
+
503
+ const match2 = line.match(/^at\s+(\S.*)(:\d+:\d+)$/);
504
+ if (match2) {
505
+ stack.push(Diagnostic.squash(Diagnostic.weak("at "), match2[1], Diagnostic.weak(match2[2])));
506
+ continue;
507
+ }
508
+
509
+ stack.push(line);
510
+ }
511
+
512
+ // Add truncation note
513
+ if (truncatedToParent) {
514
+ stack.push(Diagnostic.weak("(see parent frames)"));
515
+ }
516
+
517
+ return { message, stack, stackLines };
518
+ }
393
519
  }
394
520
 
395
521
  function formatError(error: any, options: { messagePrefix?: string; parentStack?: string[] } = {}) {
396
522
  const { messagePrefix, parentStack } = options;
397
523
 
398
- const messageAndStack = messageAndStackFor(error, parentStack);
524
+ const messageAndStack = Diagnostic.messageAndStackFor(error, parentStack);
399
525
  let { stack, stackLines } = messageAndStack;
400
526
 
401
527
  let { message } = messageAndStack;
@@ -456,123 +582,3 @@ function formatError(error: any, options: { messagePrefix?: string; parentStack?
456
582
 
457
583
  return list as Diagnostic;
458
584
  }
459
-
460
- function messageAndStackFor(error: any, parentStack?: string[]) {
461
- let message: string | undefined;
462
- let rawStack: string | undefined;
463
- if (error !== undefined && error !== null) {
464
- if (typeof error === "string" || typeof error === "number") {
465
- return { message: `${error}` };
466
- }
467
- if ("message" in error) {
468
- ({ message, stack: rawStack } = error);
469
- } else if (error.message) {
470
- message = typeof error.message === "string" ? message : error.toString();
471
- }
472
- }
473
- if (message === undefined || message === null || message === "") {
474
- if (error !== undefined && error !== null) {
475
- message = error.constructor.name;
476
- if (!message || message === "Error") {
477
- message = "(unknown error)";
478
- }
479
- } else {
480
- message = "(unknown error)";
481
- }
482
- }
483
- if (!rawStack) {
484
- return { message };
485
- }
486
-
487
- rawStack = rawStack.toString();
488
-
489
- // Strip extra node garbage off stack from node asserts
490
- rawStack = rawStack.replace(/^.*?\n\nError: /gs, "Error: ");
491
-
492
- // Strip off redundant error tag from v8
493
- if (rawStack.startsWith("Error: ")) {
494
- rawStack = rawStack.slice(7);
495
- }
496
-
497
- // Strip off redundant message from v8
498
- const pos = rawStack.indexOf(message);
499
- if (pos !== -1) {
500
- rawStack = rawStack.slice(pos + message.length).trim();
501
- }
502
-
503
- // Extract raw lines
504
- let stackLines = rawStack
505
- .split("\n")
506
- .map(line => line.trim())
507
- .filter(line => line !== "");
508
-
509
- // Node helpfully gives us this if there's no message. It's not even the name of the error class, just "Error"
510
- if (stackLines[0] === "Error") {
511
- stackLines.shift();
512
- }
513
-
514
- // If there's a parent stack, identify the portion of the stack in common so we don't have to repeat it. The stacks
515
- // may be truncated by the VM so this is not 100% guaranteed correct with recursive functions, but accidental
516
- // mismatches are unlikely
517
- let truncatedToParent = false;
518
- if (parentStack) {
519
- let truncateTo = 0;
520
-
521
- // For each line in the stack, find the line in the parent. Skip the last two lines because truncating them
522
- // won't save space
523
- stackSearch: for (; truncateTo < stackLines.length - 1; truncateTo++) {
524
- let parentPos = parentStack.indexOf(stackLines[truncateTo]);
525
- if (parentPos === -1) {
526
- continue;
527
- }
528
-
529
- // Found the line. If all subsequent lines match then we truncate. If either stack terminates before the
530
- // other, assume the stacks are truncated and consider a match
531
- parentPos++;
532
- for (
533
- let pos = truncateTo + 1;
534
- pos < stackLines.length && parentPos < parentStack.length;
535
- pos++, parentPos++
536
- ) {
537
- if (stackLines[pos] !== parentStack[parentPos]) {
538
- continue stackSearch;
539
- }
540
- }
541
-
542
- // Found a match. Truncate but leave the top-most shared frame to make it clear where the commonality
543
- // with the parent starts
544
- stackLines = stackLines.slice(0, truncateTo + 1);
545
- truncatedToParent = true;
546
- break;
547
- }
548
- }
549
-
550
- // Spiff up stack lines a bit
551
- const stack = Array<unknown>();
552
- for (const line of stackLines) {
553
- const match1 = line.match(/^at\s+(?:(\S|\S.*\S)\s+\(([^)]+)\)|(<anonymous>))$/);
554
- if (match1) {
555
- const value = [Diagnostic.weak("at "), match1[1] ?? match1[3]];
556
- if (match1[2] !== undefined) {
557
- value.push(Diagnostic.weak(" ("), Diagnostic.weak(match1[2]), Diagnostic.weak(")"));
558
- }
559
- stack.push(Diagnostic.squash(...value));
560
- continue;
561
- }
562
-
563
- const match2 = line.match(/^at\s+(\S.*)(:\d+:\d+)$/);
564
- if (match2) {
565
- stack.push(Diagnostic.squash(Diagnostic.weak("at "), match2[1], Diagnostic.weak(match2[2])));
566
- continue;
567
- }
568
-
569
- stack.push(line);
570
- }
571
-
572
- // Add truncation note
573
- if (truncatedToParent) {
574
- stack.push(Diagnostic.weak("(see parent frames)"));
575
- }
576
-
577
- return { message, stack, stackLines };
578
- }
@@ -691,3 +691,16 @@ function ensureIndented(text: string) {
691
691
  if (MatterError.formatterFor === MatterError.defaultFormatterFactory) {
692
692
  MatterError.formatterFor = LogFormat;
693
693
  }
694
+
695
+ if (typeof MatterHooks !== "undefined") {
696
+ MatterHooks.messageAndStackFor = (error: unknown, parentStack?: string[]) => {
697
+ const { message, stack, stackLines } = Diagnostic.messageAndStackFor(error, parentStack);
698
+
699
+ let stackStr;
700
+ if (stack) {
701
+ stackStr = stack.map(frame => LogFormat.ansi(frame).trim()).join("\n");
702
+ }
703
+
704
+ return { message, stack: stackStr, stackLines };
705
+ };
706
+ }