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