@@ -25,13 +25,13 @@ const {
25
25
isDeepEqual,
26
26
isDeepStrictEqual
27
27
} = require ( 'internal/util/comparisons' ) ;
28
- const { AssertionError, TypeError } = require ( 'internal/errors' ) ;
28
+ const { AssertionError, TypeError, errorCache } = require ( 'internal/errors' ) ;
29
29
const { openSync, closeSync, readSync } = require ( 'fs' ) ;
30
30
const { parseExpressionAt } = require ( 'internal/deps/acorn/dist/acorn' ) ;
31
31
const { inspect } = require ( 'util' ) ;
32
32
const { EOL } = require ( 'os' ) ;
33
+ const nativeModule = require ( 'native_module' ) ;
33
34
34
- const codeCache = new Map ( ) ;
35
35
// Escape control characters but not \n and \t to keep the line breaks and
36
36
// indentation intact.
37
37
// eslint-disable-next-line no-control-regex
@@ -146,6 +146,60 @@ function getBuffer(fd, assertLine) {
146
146
return buffers ;
147
147
}
148
148
149
+ function getErrMessage ( call ) {
150
+ const filename = call . getFileName ( ) ;
151
+ const line = call . getLineNumber ( ) - 1 ;
152
+ const column = call . getColumnNumber ( ) - 1 ;
153
+ const identifier = `${ filename } ${ line } ${ column } ` ;
154
+
155
+ if ( errorCache . has ( identifier ) ) {
156
+ return errorCache . get ( identifier ) ;
157
+ }
158
+
159
+ // Skip Node.js modules!
160
+ if ( filename . endsWith ( '.js' ) && nativeModule . exists ( filename . slice ( 0 , - 3 ) ) ) {
161
+ errorCache . set ( identifier , undefined ) ;
162
+ return ;
163
+ }
164
+
165
+ var fd ;
166
+ try {
167
+ fd = openSync ( filename , 'r' , 0o666 ) ;
168
+ const buffers = getBuffer ( fd , line ) ;
169
+ const code = Buffer . concat ( buffers ) . toString ( 'utf8' ) ;
170
+ const nodes = parseExpressionAt ( code , column ) ;
171
+ // Node type should be "CallExpression" and some times
172
+ // "SequenceExpression".
173
+ const node = nodes . type === 'CallExpression' ? nodes : nodes . expressions [ 0 ] ;
174
+ const name = node . callee . name ;
175
+ // Calling `ok` with .apply or .call is uncommon but we use a simple
176
+ // safeguard nevertheless.
177
+ if ( name !== 'apply' && name !== 'call' ) {
178
+ // Only use `assert` and `assert.ok` to reference the "real API" and
179
+ // not user defined function names.
180
+ const ok = name === 'ok' ? '.ok' : '' ;
181
+ const args = node . arguments ;
182
+ var message = code
183
+ . slice ( args [ 0 ] . start , args [ args . length - 1 ] . end )
184
+ . replace ( escapeSequencesRegExp , escapeFn ) ;
185
+ message = 'The expression evaluated to a falsy value:' +
186
+ `${ EOL } ${ EOL } assert${ ok } (${ message } )${ EOL } ` ;
187
+ }
188
+ // Make sure to always set the cache! No matter if the message is
189
+ // undefined or not
190
+ errorCache . set ( identifier , message ) ;
191
+
192
+ return message ;
193
+
194
+ } catch ( e ) {
195
+ // Invalidate cache to prevent trying to read this part again.
196
+ errorCache . set ( identifier , undefined ) ;
197
+ } finally {
198
+ if ( fd !== undefined )
199
+ closeSync ( fd ) ;
200
+ }
201
+ }
202
+
149
203
function innerOk ( args , fn ) {
150
204
var [ value , message ] = args ;
151
205
@@ -168,54 +222,12 @@ function innerOk(args, fn) {
168
222
const call = err . stack [ 0 ] ;
169
223
Error . prepareStackTrace = tmpPrepare ;
170
224
171
- const filename = call . getFileName ( ) ;
172
- const line = call . getLineNumber ( ) - 1 ;
173
- const column = call . getColumnNumber ( ) - 1 ;
174
- const identifier = `${ filename } ${ line } ${ column } ` ;
225
+ // TODO(BridgeAR): fix the "generatedMessage property"
226
+ // Since this is actually a generated message, it has to be
227
+ // determined differently from now on.
175
228
176
- if ( codeCache . has ( identifier ) ) {
177
- message = codeCache . get ( identifier ) ;
178
- } else {
179
- var fd ;
180
- try {
181
- fd = openSync ( filename , 'r' , 0o666 ) ;
182
- const buffers = getBuffer ( fd , line ) ;
183
- const code = Buffer . concat ( buffers ) . toString ( 'utf8' ) ;
184
- const nodes = parseExpressionAt ( code , column ) ;
185
- // Node type should be "CallExpression" and some times
186
- // "SequenceExpression".
187
- const node = nodes . type === 'CallExpression' ?
188
- nodes :
189
- nodes . expressions [ 0 ] ;
190
- // TODO: fix the "generatedMessage property"
191
- // Since this is actually a generated message, it has to be
192
- // determined differently from now on.
193
-
194
- const name = node . callee . name ;
195
- // Calling `ok` with .apply or .call is uncommon but we use a simple
196
- // safeguard nevertheless.
197
- if ( name !== 'apply' && name !== 'call' ) {
198
- // Only use `assert` and `assert.ok` to reference the "real API" and
199
- // not user defined function names.
200
- const ok = name === 'ok' ? '.ok' : '' ;
201
- const args = node . arguments ;
202
- message = code
203
- . slice ( args [ 0 ] . start , args [ args . length - 1 ] . end )
204
- . replace ( escapeSequencesRegExp , escapeFn ) ;
205
- message = 'The expression evaluated to a falsy value:' +
206
- `${ EOL } ${ EOL } assert${ ok } (${ message } )${ EOL } ` ;
207
- }
208
- // Make sure to always set the cache! No matter if the message is
209
- // undefined or not
210
- codeCache . set ( identifier , message ) ;
211
- } catch ( e ) {
212
- // Invalidate cache to prevent trying to read this part again.
213
- codeCache . set ( identifier , undefined ) ;
214
- } finally {
215
- if ( fd !== undefined )
216
- closeSync ( fd ) ;
217
- }
218
- }
229
+ // Make sure it would be "null" in case that is used.
230
+ message = getErrMessage ( call ) || message ;
219
231
}
220
232
innerFail ( {
221
233
actual : value ,
0 commit comments