@@ -251,23 +251,34 @@ const operations = Object.freeze({
251
251
if ( args != null ) {
252
252
if ( calleeNode . type === "MemberExpression" ) {
253
253
const object = getStaticValueR ( calleeNode . object , initialScope )
254
- const property = calleeNode . computed
255
- ? getStaticValueR ( calleeNode . property , initialScope )
256
- : { value : calleeNode . property . name }
257
-
258
- if ( object != null && property != null ) {
259
- const receiver = object . value
260
- const methodName = property . value
261
- if ( callAllowed . has ( receiver [ methodName ] ) ) {
262
- return { value : receiver [ methodName ] ( ...args ) }
254
+ if ( object != null ) {
255
+ if (
256
+ object . value == null &&
257
+ ( object . optional || node . optional )
258
+ ) {
259
+ return { value : undefined , optional : true }
263
260
}
264
- if ( callPassThrough . has ( receiver [ methodName ] ) ) {
265
- return { value : args [ 0 ] }
261
+ const property = calleeNode . computed
262
+ ? getStaticValueR ( calleeNode . property , initialScope )
263
+ : { value : calleeNode . property . name }
264
+
265
+ if ( property != null ) {
266
+ const receiver = object . value
267
+ const methodName = property . value
268
+ if ( callAllowed . has ( receiver [ methodName ] ) ) {
269
+ return { value : receiver [ methodName ] ( ...args ) }
270
+ }
271
+ if ( callPassThrough . has ( receiver [ methodName ] ) ) {
272
+ return { value : args [ 0 ] }
273
+ }
266
274
}
267
275
}
268
276
} else {
269
277
const callee = getStaticValueR ( calleeNode , initialScope )
270
278
if ( callee != null ) {
279
+ if ( callee . value == null && node . optional ) {
280
+ return { value : undefined , optional : true }
281
+ }
271
282
const func = callee . value
272
283
if ( callAllowed . has ( func ) ) {
273
284
return { value : func ( ...args ) }
@@ -340,7 +351,8 @@ const operations = Object.freeze({
340
351
if ( left != null ) {
341
352
if (
342
353
( node . operator === "||" && Boolean ( left . value ) === true ) ||
343
- ( node . operator === "&&" && Boolean ( left . value ) === false )
354
+ ( node . operator === "&&" && Boolean ( left . value ) === false ) ||
355
+ ( node . operator === "??" && left . value != null )
344
356
) {
345
357
return left
346
358
}
@@ -356,16 +368,25 @@ const operations = Object.freeze({
356
368
357
369
MemberExpression ( node , initialScope ) {
358
370
const object = getStaticValueR ( node . object , initialScope )
359
- const property = node . computed
360
- ? getStaticValueR ( node . property , initialScope )
361
- : { value : node . property . name }
362
-
363
- if (
364
- object != null &&
365
- property != null &&
366
- ! isGetter ( object . value , property . value )
367
- ) {
368
- return { value : object . value [ property . value ] }
371
+ if ( object != null ) {
372
+ if ( object . value == null && ( object . optional || node . optional ) ) {
373
+ return { value : undefined , optional : true }
374
+ }
375
+ const property = node . computed
376
+ ? getStaticValueR ( node . property , initialScope )
377
+ : { value : node . property . name }
378
+
379
+ if ( property != null && ! isGetter ( object . value , property . value ) ) {
380
+ return { value : object . value [ property . value ] }
381
+ }
382
+ }
383
+ return null
384
+ } ,
385
+
386
+ ChainExpression ( node , initialScope ) {
387
+ const expression = getStaticValueR ( node . expression , initialScope )
388
+ if ( expression != null ) {
389
+ return { value : expression . value }
369
390
}
370
391
return null
371
392
} ,
@@ -493,7 +514,7 @@ const operations = Object.freeze({
493
514
* Get the value of a given node if it's a static value.
494
515
* @param {Node } node The node to get.
495
516
* @param {Scope|undefined } initialScope The scope to start finding variable.
496
- * @returns {{value:any}|null } The static value of the node, or `null`.
517
+ * @returns {{value:any}|{value:undefined,optional?:true}| null } The static value of the node, or `null`.
497
518
*/
498
519
function getStaticValueR ( node , initialScope ) {
499
520
if ( node != null && Object . hasOwnProperty . call ( operations , node . type ) ) {
@@ -506,7 +527,7 @@ function getStaticValueR(node, initialScope) {
506
527
* Get the value of a given node if it's a static value.
507
528
* @param {Node } node The node to get.
508
529
* @param {Scope } [initialScope] The scope to start finding variable. Optional. If this scope was given, this tries to resolve identifier references which are in the given node as much as possible.
509
- * @returns {{value:any}|null } The static value of the node, or `null`.
530
+ * @returns {{value:any}|{value:undefined,optional?:true}| null } The static value of the node, or `null`.
510
531
*/
511
532
export function getStaticValue ( node , initialScope = null ) {
512
533
try {
0 commit comments