Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F100103120
BasicEvaluatedExpression.js
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Tue, Jan 28, 05:19
Size
10 KB
Mime Type
text/x-c++
Expires
Thu, Jan 30, 05:19 (2 d)
Engine
blob
Format
Raw Data
Handle
23878399
Attached To
rOACCT Open Access Compliance Check Tool (OACCT)
BasicEvaluatedExpression.js
View Options
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict"
;
/** @typedef {import("estree").Node} EsTreeNode */
/** @typedef {import("./JavascriptParser").VariableInfoInterface} VariableInfoInterface */
const
TypeUnknown
=
0
;
const
TypeUndefined
=
1
;
const
TypeNull
=
2
;
const
TypeString
=
3
;
const
TypeNumber
=
4
;
const
TypeBoolean
=
5
;
const
TypeRegExp
=
6
;
const
TypeConditional
=
7
;
const
TypeArray
=
8
;
const
TypeConstArray
=
9
;
const
TypeIdentifier
=
10
;
const
TypeWrapped
=
11
;
const
TypeTemplateString
=
12
;
const
TypeBigInt
=
13
;
class
BasicEvaluatedExpression
{
constructor
()
{
this
.
type
=
TypeUnknown
;
/** @type {[number, number]} */
this
.
range
=
undefined
;
/** @type {boolean} */
this
.
falsy
=
false
;
/** @type {boolean} */
this
.
truthy
=
false
;
/** @type {boolean | undefined} */
this
.
nullish
=
undefined
;
/** @type {boolean} */
this
.
sideEffects
=
true
;
/** @type {boolean | undefined} */
this
.
bool
=
undefined
;
/** @type {number | undefined} */
this
.
number
=
undefined
;
/** @type {bigint | undefined} */
this
.
bigint
=
undefined
;
/** @type {RegExp | undefined} */
this
.
regExp
=
undefined
;
/** @type {string | undefined} */
this
.
string
=
undefined
;
/** @type {BasicEvaluatedExpression[] | undefined} */
this
.
quasis
=
undefined
;
/** @type {BasicEvaluatedExpression[] | undefined} */
this
.
parts
=
undefined
;
/** @type {any[] | undefined} */
this
.
array
=
undefined
;
/** @type {BasicEvaluatedExpression[] | undefined} */
this
.
items
=
undefined
;
/** @type {BasicEvaluatedExpression[] | undefined} */
this
.
options
=
undefined
;
/** @type {BasicEvaluatedExpression | undefined} */
this
.
prefix
=
undefined
;
/** @type {BasicEvaluatedExpression | undefined} */
this
.
postfix
=
undefined
;
this
.
wrappedInnerExpressions
=
undefined
;
/** @type {string | undefined} */
this
.
identifier
=
undefined
;
/** @type {VariableInfoInterface} */
this
.
rootInfo
=
undefined
;
/** @type {() => string[]} */
this
.
getMembers
=
undefined
;
/** @type {EsTreeNode} */
this
.
expression
=
undefined
;
}
isUnknown
()
{
return
this
.
type
===
TypeUnknown
;
}
isNull
()
{
return
this
.
type
===
TypeNull
;
}
isUndefined
()
{
return
this
.
type
===
TypeUndefined
;
}
isString
()
{
return
this
.
type
===
TypeString
;
}
isNumber
()
{
return
this
.
type
===
TypeNumber
;
}
isBigInt
()
{
return
this
.
type
===
TypeBigInt
;
}
isBoolean
()
{
return
this
.
type
===
TypeBoolean
;
}
isRegExp
()
{
return
this
.
type
===
TypeRegExp
;
}
isConditional
()
{
return
this
.
type
===
TypeConditional
;
}
isArray
()
{
return
this
.
type
===
TypeArray
;
}
isConstArray
()
{
return
this
.
type
===
TypeConstArray
;
}
isIdentifier
()
{
return
this
.
type
===
TypeIdentifier
;
}
isWrapped
()
{
return
this
.
type
===
TypeWrapped
;
}
isTemplateString
()
{
return
this
.
type
===
TypeTemplateString
;
}
/**
* Is expression a primitive or an object type value?
* @returns {boolean | undefined} true: primitive type, false: object type, undefined: unknown/runtime-defined
*/
isPrimitiveType
()
{
switch
(
this
.
type
)
{
case
TypeUndefined
:
case
TypeNull
:
case
TypeString
:
case
TypeNumber
:
case
TypeBoolean
:
case
TypeBigInt
:
case
TypeWrapped
:
case
TypeTemplateString
:
return
true
;
case
TypeRegExp
:
case
TypeArray
:
case
TypeConstArray
:
return
false
;
default
:
return
undefined
;
}
}
/**
* Is expression a runtime or compile-time value?
* @returns {boolean} true: compile time value, false: runtime value
*/
isCompileTimeValue
()
{
switch
(
this
.
type
)
{
case
TypeUndefined
:
case
TypeNull
:
case
TypeString
:
case
TypeNumber
:
case
TypeBoolean
:
case
TypeRegExp
:
case
TypeConstArray
:
case
TypeBigInt
:
return
true
;
default
:
return
false
;
}
}
/**
* Gets the compile-time value of the expression
* @returns {any} the javascript value
*/
asCompileTimeValue
()
{
switch
(
this
.
type
)
{
case
TypeUndefined
:
return
undefined
;
case
TypeNull
:
return
null
;
case
TypeString
:
return
this
.
string
;
case
TypeNumber
:
return
this
.
number
;
case
TypeBoolean
:
return
this
.
bool
;
case
TypeRegExp
:
return
this
.
regExp
;
case
TypeConstArray
:
return
this
.
array
;
case
TypeBigInt
:
return
this
.
bigint
;
default
:
throw
new
Error
(
"asCompileTimeValue must only be called for compile-time values"
);
}
}
isTruthy
()
{
return
this
.
truthy
;
}
isFalsy
()
{
return
this
.
falsy
;
}
isNullish
()
{
return
this
.
nullish
;
}
/**
* Can this expression have side effects?
* @returns {boolean} false: never has side effects
*/
couldHaveSideEffects
()
{
return
this
.
sideEffects
;
}
asBool
()
{
if
(
this
.
truthy
)
return
true
;
if
(
this
.
falsy
||
this
.
nullish
)
return
false
;
if
(
this
.
isBoolean
())
return
this
.
bool
;
if
(
this
.
isNull
())
return
false
;
if
(
this
.
isUndefined
())
return
false
;
if
(
this
.
isString
())
return
this
.
string
!==
""
;
if
(
this
.
isNumber
())
return
this
.
number
!==
0
;
if
(
this
.
isBigInt
())
return
this
.
bigint
!==
BigInt
(
0
);
if
(
this
.
isRegExp
())
return
true
;
if
(
this
.
isArray
())
return
true
;
if
(
this
.
isConstArray
())
return
true
;
if
(
this
.
isWrapped
())
{
return
(
this
.
prefix
&&
this
.
prefix
.
asBool
())
||
(
this
.
postfix
&&
this
.
postfix
.
asBool
())
?
true
:
undefined
;
}
if
(
this
.
isTemplateString
())
{
const
str
=
this
.
asString
();
if
(
typeof
str
===
"string"
)
return
str
!==
""
;
}
return
undefined
;
}
asNullish
()
{
const
nullish
=
this
.
isNullish
();
if
(
nullish
===
true
||
this
.
isNull
()
||
this
.
isUndefined
())
return
true
;
if
(
nullish
===
false
)
return
false
;
if
(
this
.
isTruthy
())
return
false
;
if
(
this
.
isBoolean
())
return
false
;
if
(
this
.
isString
())
return
false
;
if
(
this
.
isNumber
())
return
false
;
if
(
this
.
isBigInt
())
return
false
;
if
(
this
.
isRegExp
())
return
false
;
if
(
this
.
isArray
())
return
false
;
if
(
this
.
isConstArray
())
return
false
;
if
(
this
.
isTemplateString
())
return
false
;
if
(
this
.
isRegExp
())
return
false
;
return
undefined
;
}
asString
()
{
if
(
this
.
isBoolean
())
return
`
$
{
this
.
bool
}
`
;
if
(
this
.
isNull
())
return
"null"
;
if
(
this
.
isUndefined
())
return
"undefined"
;
if
(
this
.
isString
())
return
this
.
string
;
if
(
this
.
isNumber
())
return
`
$
{
this
.
number
}
`
;
if
(
this
.
isBigInt
())
return
`
$
{
this
.
bigint
}
`
;
if
(
this
.
isRegExp
())
return
`
$
{
this
.
regExp
}
`
;
if
(
this
.
isArray
())
{
let
array
=
[];
for
(
const
item
of
this
.
items
)
{
const
itemStr
=
item
.
asString
();
if
(
itemStr
===
undefined
)
return
undefined
;
array
.
push
(
itemStr
);
}
return
`
$
{
array
}
`
;
}
if
(
this
.
isConstArray
())
return
`
$
{
this
.
array
}
`
;
if
(
this
.
isTemplateString
())
{
let
str
=
""
;
for
(
const
part
of
this
.
parts
)
{
const
partStr
=
part
.
asString
();
if
(
partStr
===
undefined
)
return
undefined
;
str
+=
partStr
;
}
return
str
;
}
return
undefined
;
}
setString
(
string
)
{
this
.
type
=
TypeString
;
this
.
string
=
string
;
this
.
sideEffects
=
false
;
return
this
;
}
setUndefined
()
{
this
.
type
=
TypeUndefined
;
this
.
sideEffects
=
false
;
return
this
;
}
setNull
()
{
this
.
type
=
TypeNull
;
this
.
sideEffects
=
false
;
return
this
;
}
setNumber
(
number
)
{
this
.
type
=
TypeNumber
;
this
.
number
=
number
;
this
.
sideEffects
=
false
;
return
this
;
}
setBigInt
(
bigint
)
{
this
.
type
=
TypeBigInt
;
this
.
bigint
=
bigint
;
this
.
sideEffects
=
false
;
return
this
;
}
setBoolean
(
bool
)
{
this
.
type
=
TypeBoolean
;
this
.
bool
=
bool
;
this
.
sideEffects
=
false
;
return
this
;
}
setRegExp
(
regExp
)
{
this
.
type
=
TypeRegExp
;
this
.
regExp
=
regExp
;
this
.
sideEffects
=
false
;
return
this
;
}
setIdentifier
(
identifier
,
rootInfo
,
getMembers
)
{
this
.
type
=
TypeIdentifier
;
this
.
identifier
=
identifier
;
this
.
rootInfo
=
rootInfo
;
this
.
getMembers
=
getMembers
;
this
.
sideEffects
=
true
;
return
this
;
}
setWrapped
(
prefix
,
postfix
,
innerExpressions
)
{
this
.
type
=
TypeWrapped
;
this
.
prefix
=
prefix
;
this
.
postfix
=
postfix
;
this
.
wrappedInnerExpressions
=
innerExpressions
;
this
.
sideEffects
=
true
;
return
this
;
}
setOptions
(
options
)
{
this
.
type
=
TypeConditional
;
this
.
options
=
options
;
this
.
sideEffects
=
true
;
return
this
;
}
addOptions
(
options
)
{
if
(
!
this
.
options
)
{
this
.
type
=
TypeConditional
;
this
.
options
=
[];
this
.
sideEffects
=
true
;
}
for
(
const
item
of
options
)
{
this
.
options
.
push
(
item
);
}
return
this
;
}
setItems
(
items
)
{
this
.
type
=
TypeArray
;
this
.
items
=
items
;
this
.
sideEffects
=
items
.
some
(
i
=>
i
.
couldHaveSideEffects
());
return
this
;
}
setArray
(
array
)
{
this
.
type
=
TypeConstArray
;
this
.
array
=
array
;
this
.
sideEffects
=
false
;
return
this
;
}
setTemplateString
(
quasis
,
parts
,
kind
)
{
this
.
type
=
TypeTemplateString
;
this
.
quasis
=
quasis
;
this
.
parts
=
parts
;
this
.
templateStringKind
=
kind
;
this
.
sideEffects
=
parts
.
some
(
p
=>
p
.
sideEffects
);
return
this
;
}
setTruthy
()
{
this
.
falsy
=
false
;
this
.
truthy
=
true
;
this
.
nullish
=
false
;
return
this
;
}
setFalsy
()
{
this
.
falsy
=
true
;
this
.
truthy
=
false
;
return
this
;
}
setNullish
(
value
)
{
this
.
nullish
=
value
;
return
this
;
}
setRange
(
range
)
{
this
.
range
=
range
;
return
this
;
}
setSideEffects
(
sideEffects
=
true
)
{
this
.
sideEffects
=
sideEffects
;
return
this
;
}
setExpression
(
expression
)
{
this
.
expression
=
expression
;
return
this
;
}
}
/**
* @param {string} flags regexp flags
* @returns {boolean} is valid flags
*/
BasicEvaluatedExpression
.
isValidRegExpFlags
=
flags
=>
{
const
len
=
flags
.
length
;
if
(
len
===
0
)
return
true
;
if
(
len
>
4
)
return
false
;
// cspell:word gimy
let
remaining
=
0
b0000
;
// bit per RegExp flag: gimy
for
(
let
i
=
0
;
i
<
len
;
i
++
)
switch
(
flags
.
charCodeAt
(
i
))
{
case
103
/* g */
:
if
(
remaining
&
0
b1000
)
return
false
;
remaining
|=
0
b1000
;
break
;
case
105
/* i */
:
if
(
remaining
&
0
b0100
)
return
false
;
remaining
|=
0
b0100
;
break
;
case
109
/* m */
:
if
(
remaining
&
0
b0010
)
return
false
;
remaining
|=
0
b0010
;
break
;
case
121
/* y */
:
if
(
remaining
&
0
b0001
)
return
false
;
remaining
|=
0
b0001
;
break
;
default
:
return
false
;
}
return
true
;
};
module
.
exports
=
BasicEvaluatedExpression
;
Event Timeline
Log In to Comment