• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Flags: --expose-internals
2'use strict';
3require('../common');
4const fixtures = require('../common/fixtures');
5const assert = require('assert');
6const internalUtil = require('internal/util');
7const { internalBinding } = require('internal/test/binding');
8const binding = internalBinding('util');
9const spawnSync = require('child_process').spawnSync;
10
11const kArrowMessagePrivateSymbolIndex = binding.arrow_message_private_symbol;
12const kDecoratedPrivateSymbolIndex = binding.decorated_private_symbol;
13
14const decorateErrorStack = internalUtil.decorateErrorStack;
15
16// Verify that decorateErrorStack does not throw with non-objects.
17decorateErrorStack();
18decorateErrorStack(null);
19decorateErrorStack(1);
20decorateErrorStack(true);
21
22// Verify that a stack property is not added to non-Errors.
23const obj = {};
24decorateErrorStack(obj);
25assert.strictEqual(obj.stack, undefined);
26
27// Verify that the stack is decorated when possible.
28function checkStack(stack) {
29  // Matching only on a minimal piece of the stack because the string will vary
30  // greatly depending on the JavaScript engine. V8 includes `;` because it
31  // displays the line of code (`var foo bar;`) that is causing a problem.
32  // ChakraCore does not display the line of code but includes `;` in the phrase
33  // `Expected ';' `.
34  assert.ok(/;/g.test(stack));
35  // Test that it's a multiline string.
36  assert.ok(/\n/g.test(stack));
37}
38let err;
39const badSyntaxPath =
40  fixtures.path('syntax', 'bad_syntax').replace(/\\/g, '\\\\');
41
42try {
43  require(badSyntaxPath);
44} catch (e) {
45  err = e;
46}
47
48assert(typeof err, 'object');
49checkStack(err.stack);
50
51// Verify that the stack is only decorated once.
52decorateErrorStack(err);
53decorateErrorStack(err);
54checkStack(err.stack);
55
56// Verify that the stack is only decorated once for uncaught exceptions.
57const args = [
58  '-e',
59  `require('${badSyntaxPath}')`,
60];
61const result = spawnSync(process.argv[0], args, { encoding: 'utf8' });
62checkStack(result.stderr);
63
64// Verify that the stack is unchanged when there is no arrow message.
65err = new Error('foo');
66let originalStack = err.stack;
67decorateErrorStack(err);
68assert.strictEqual(originalStack, err.stack);
69
70// Verify that the arrow message is added to the start of the stack when it
71// exists.
72const arrowMessage = 'arrow_message';
73err = new Error('foo');
74originalStack = err.stack;
75
76binding.setHiddenValue(err, kArrowMessagePrivateSymbolIndex, arrowMessage);
77decorateErrorStack(err);
78
79assert.strictEqual(err.stack, `${arrowMessage}${originalStack}`);
80assert.strictEqual(
81  binding.getHiddenValue(err, kDecoratedPrivateSymbolIndex), true);
82