Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F82530815
index.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
Wed, Sep 11, 22:59
Size
19 KB
Mime Type
text/x-c++
Expires
Fri, Sep 13, 22:59 (1 d, 23 h)
Engine
blob
Format
Raw Data
Handle
20710292
Attached To
rOACCT Open Access Compliance Check Tool (OACCT)
index.js
View Options
"use strict"
;
Object
.
defineProperty
(
exports
,
"__esModule"
,
{
value
:
true
});
exports
.
default
=
void
0
;
var
_helperPluginUtils
=
require
(
"@babel/helper-plugin-utils"
);
var
_tdz
=
require
(
"./tdz"
);
var
_core
=
require
(
"@babel/core"
);
const
DONE
=
new
WeakSet
();
var
_default
=
(
0
,
_helperPluginUtils
.
declare
)((
api
,
opts
)
=>
{
api
.
assertVersion
(
7
);
const
{
throwIfClosureRequired
=
false
,
tdz
:
tdzEnabled
=
false
}
=
opts
;
if
(
typeof
throwIfClosureRequired
!==
"boolean"
)
{
throw
new
Error
(
`
.
throwIfClosureRequired
must
be
a
boolean
,
or
undefined
`
);
}
if
(
typeof
tdzEnabled
!==
"boolean"
)
{
throw
new
Error
(
`
.
tdz
must
be
a
boolean
,
or
undefined
`
);
}
return
{
name
:
"transform-block-scoping"
,
visitor
:
{
VariableDeclaration
(
path
)
{
const
{
node
,
parent
,
scope
}
=
path
;
if
(
!
isBlockScoped
(
node
))
return
;
convertBlockScopedToVar
(
path
,
null
,
parent
,
scope
,
true
);
if
(
node
.
_tdzThis
)
{
const
nodes
=
[
node
];
for
(
let
i
=
0
;
i
<
node
.
declarations
.
length
;
i
++
)
{
const
decl
=
node
.
declarations
[
i
];
const
assign
=
_core
.
types
.
assignmentExpression
(
"="
,
_core
.
types
.
cloneNode
(
decl
.
id
),
decl
.
init
||
scope
.
buildUndefinedNode
());
assign
.
_ignoreBlockScopingTDZ
=
true
;
nodes
.
push
(
_core
.
types
.
expressionStatement
(
assign
));
decl
.
init
=
this
.
addHelper
(
"temporalUndefined"
);
}
node
.
_blockHoist
=
2
;
if
(
path
.
isCompletionRecord
())
{
nodes
.
push
(
_core
.
types
.
expressionStatement
(
scope
.
buildUndefinedNode
()));
}
path
.
replaceWithMultiple
(
nodes
);
}
},
Loop
(
path
,
state
)
{
const
{
parent
,
scope
}
=
path
;
path
.
ensureBlock
();
const
blockScoping
=
new
BlockScoping
(
path
,
path
.
get
(
"body"
),
parent
,
scope
,
throwIfClosureRequired
,
tdzEnabled
,
state
);
const
replace
=
blockScoping
.
run
();
if
(
replace
)
path
.
replaceWith
(
replace
);
},
CatchClause
(
path
,
state
)
{
const
{
parent
,
scope
}
=
path
;
const
blockScoping
=
new
BlockScoping
(
null
,
path
.
get
(
"body"
),
parent
,
scope
,
throwIfClosureRequired
,
tdzEnabled
,
state
);
blockScoping
.
run
();
},
"BlockStatement|SwitchStatement|Program"
(
path
,
state
)
{
if
(
!
ignoreBlock
(
path
))
{
const
blockScoping
=
new
BlockScoping
(
null
,
path
,
path
.
parent
,
path
.
scope
,
throwIfClosureRequired
,
tdzEnabled
,
state
);
blockScoping
.
run
();
}
}
}
};
});
exports
.
default
=
_default
;
function
ignoreBlock
(
path
)
{
return
_core
.
types
.
isLoop
(
path
.
parent
)
||
_core
.
types
.
isCatchClause
(
path
.
parent
);
}
const
buildRetCheck
=
(
0
,
_core
.
template
)(
`
if
(
typeof
RETURN
===
"object"
)
return
RETURN
.
v
;
`
);
function
isBlockScoped
(
node
)
{
if
(
!
_core
.
types
.
isVariableDeclaration
(
node
))
return
false
;
if
(
node
[
_core
.
types
.
BLOCK_SCOPED_SYMBOL
])
return
true
;
if
(
node
.
kind
!==
"let"
&&
node
.
kind
!==
"const"
)
return
false
;
return
true
;
}
function
isInLoop
(
path
)
{
const
loopOrFunctionParent
=
path
.
find
(
path
=>
path
.
isLoop
()
||
path
.
isFunction
());
return
loopOrFunctionParent
==
null
?
void
0
:
loopOrFunctionParent
.
isLoop
();
}
function
convertBlockScopedToVar
(
path
,
node
,
parent
,
scope
,
moveBindingsToParent
=
false
)
{
if
(
!
node
)
{
node
=
path
.
node
;
}
if
(
isInLoop
(
path
)
&&
!
_core
.
types
.
isFor
(
parent
))
{
for
(
let
i
=
0
;
i
<
node
.
declarations
.
length
;
i
++
)
{
const
declar
=
node
.
declarations
[
i
];
declar
.
init
=
declar
.
init
||
scope
.
buildUndefinedNode
();
}
}
node
[
_core
.
types
.
BLOCK_SCOPED_SYMBOL
]
=
true
;
node
.
kind
=
"var"
;
if
(
moveBindingsToParent
)
{
const
parentScope
=
scope
.
getFunctionParent
()
||
scope
.
getProgramParent
();
for
(
const
name
of
Object
.
keys
(
path
.
getBindingIdentifiers
()))
{
const
binding
=
scope
.
getOwnBinding
(
name
);
if
(
binding
)
binding
.
kind
=
"var"
;
scope
.
moveBindingTo
(
name
,
parentScope
);
}
}
}
function
isVar
(
node
)
{
return
_core
.
types
.
isVariableDeclaration
(
node
,
{
kind
:
"var"
})
&&
!
isBlockScoped
(
node
);
}
const
letReferenceBlockVisitor
=
_core
.
traverse
.
visitors
.
merge
([{
Loop
:
{
enter
(
path
,
state
)
{
state
.
loopDepth
++
;
},
exit
(
path
,
state
)
{
state
.
loopDepth
--
;
}
},
Function
(
path
,
state
)
{
if
(
state
.
loopDepth
>
0
)
{
path
.
traverse
(
letReferenceFunctionVisitor
,
state
);
}
else
{
path
.
traverse
(
_tdz
.
visitor
,
state
);
}
return
path
.
skip
();
}
},
_tdz
.
visitor
]);
const
letReferenceFunctionVisitor
=
_core
.
traverse
.
visitors
.
merge
([{
ReferencedIdentifier
(
path
,
state
)
{
const
ref
=
state
.
letReferences
.
get
(
path
.
node
.
name
);
if
(
!
ref
)
return
;
const
localBinding
=
path
.
scope
.
getBindingIdentifier
(
path
.
node
.
name
);
if
(
localBinding
&&
localBinding
!==
ref
)
return
;
state
.
closurify
=
true
;
}
},
_tdz
.
visitor
]);
const
hoistVarDeclarationsVisitor
=
{
enter
(
path
,
self
)
{
const
{
node
,
parent
}
=
path
;
if
(
path
.
isForStatement
())
{
if
(
isVar
(
node
.
init
,
node
))
{
const
nodes
=
self
.
pushDeclar
(
node
.
init
);
if
(
nodes
.
length
===
1
)
{
node
.
init
=
nodes
[
0
];
}
else
{
node
.
init
=
_core
.
types
.
sequenceExpression
(
nodes
);
}
}
}
else
if
(
path
.
isFor
())
{
if
(
isVar
(
node
.
left
,
node
))
{
self
.
pushDeclar
(
node
.
left
);
node
.
left
=
node
.
left
.
declarations
[
0
].
id
;
}
}
else
if
(
isVar
(
node
,
parent
))
{
path
.
replaceWithMultiple
(
self
.
pushDeclar
(
node
).
map
(
expr
=>
_core
.
types
.
expressionStatement
(
expr
)));
}
else
if
(
path
.
isFunction
())
{
return
path
.
skip
();
}
}
};
const
loopLabelVisitor
=
{
LabeledStatement
({
node
},
state
)
{
state
.
innerLabels
.
push
(
node
.
label
.
name
);
}
};
const
continuationVisitor
=
{
enter
(
path
,
state
)
{
if
(
path
.
isAssignmentExpression
()
||
path
.
isUpdateExpression
())
{
for
(
const
name
of
Object
.
keys
(
path
.
getBindingIdentifiers
()))
{
if
(
state
.
outsideReferences
.
get
(
name
)
!==
path
.
scope
.
getBindingIdentifier
(
name
))
{
continue
;
}
state
.
reassignments
[
name
]
=
true
;
}
}
else
if
(
path
.
isReturnStatement
())
{
state
.
returnStatements
.
push
(
path
);
}
}
};
function
loopNodeTo
(
node
)
{
if
(
_core
.
types
.
isBreakStatement
(
node
))
{
return
"break"
;
}
else
if
(
_core
.
types
.
isContinueStatement
(
node
))
{
return
"continue"
;
}
}
const
loopVisitor
=
{
Loop
(
path
,
state
)
{
const
oldIgnoreLabeless
=
state
.
ignoreLabeless
;
state
.
ignoreLabeless
=
true
;
path
.
traverse
(
loopVisitor
,
state
);
state
.
ignoreLabeless
=
oldIgnoreLabeless
;
path
.
skip
();
},
Function
(
path
)
{
path
.
skip
();
},
SwitchCase
(
path
,
state
)
{
const
oldInSwitchCase
=
state
.
inSwitchCase
;
state
.
inSwitchCase
=
true
;
path
.
traverse
(
loopVisitor
,
state
);
state
.
inSwitchCase
=
oldInSwitchCase
;
path
.
skip
();
},
"BreakStatement|ContinueStatement|ReturnStatement"
(
path
,
state
)
{
const
{
node
,
scope
}
=
path
;
if
(
node
[
this
.
LOOP_IGNORE
])
return
;
let
replace
;
let
loopText
=
loopNodeTo
(
node
);
if
(
loopText
)
{
if
(
node
.
label
)
{
if
(
state
.
innerLabels
.
indexOf
(
node
.
label
.
name
)
>=
0
)
{
return
;
}
loopText
=
`
$
{
loopText
}
|
$
{
node
.
label
.
name
}
`
;
}
else
{
if
(
state
.
ignoreLabeless
)
return
;
if
(
_core
.
types
.
isBreakStatement
(
node
)
&&
state
.
inSwitchCase
)
return
;
}
state
.
hasBreakContinue
=
true
;
state
.
map
[
loopText
]
=
node
;
replace
=
_core
.
types
.
stringLiteral
(
loopText
);
}
if
(
path
.
isReturnStatement
())
{
state
.
hasReturn
=
true
;
replace
=
_core
.
types
.
objectExpression
([
_core
.
types
.
objectProperty
(
_core
.
types
.
identifier
(
"v"
),
node
.
argument
||
scope
.
buildUndefinedNode
())]);
}
if
(
replace
)
{
replace
=
_core
.
types
.
returnStatement
(
replace
);
replace
[
this
.
LOOP_IGNORE
]
=
true
;
path
.
skip
();
path
.
replaceWith
(
_core
.
types
.
inherits
(
replace
,
node
));
}
}
};
class
BlockScoping
{
constructor
(
loopPath
,
blockPath
,
parent
,
scope
,
throwIfClosureRequired
,
tdzEnabled
,
state
)
{
this
.
parent
=
parent
;
this
.
scope
=
scope
;
this
.
state
=
state
;
this
.
throwIfClosureRequired
=
throwIfClosureRequired
;
this
.
tdzEnabled
=
tdzEnabled
;
this
.
blockPath
=
blockPath
;
this
.
block
=
blockPath
.
node
;
this
.
outsideLetReferences
=
new
Map
();
this
.
hasLetReferences
=
false
;
this
.
letReferences
=
new
Map
();
this
.
body
=
[];
if
(
loopPath
)
{
this
.
loopParent
=
loopPath
.
parent
;
this
.
loopLabel
=
_core
.
types
.
isLabeledStatement
(
this
.
loopParent
)
&&
this
.
loopParent
.
label
;
this
.
loopPath
=
loopPath
;
this
.
loop
=
loopPath
.
node
;
}
}
run
()
{
const
block
=
this
.
block
;
if
(
DONE
.
has
(
block
))
return
;
DONE
.
add
(
block
);
const
needsClosure
=
this
.
getLetReferences
();
this
.
checkConstants
();
if
(
_core
.
types
.
isFunction
(
this
.
parent
)
||
_core
.
types
.
isProgram
(
this
.
block
))
{
this
.
updateScopeInfo
();
return
;
}
if
(
!
this
.
hasLetReferences
)
return
;
if
(
needsClosure
)
{
this
.
wrapClosure
();
}
else
{
this
.
remap
();
}
this
.
updateScopeInfo
(
needsClosure
);
if
(
this
.
loopLabel
&&
!
_core
.
types
.
isLabeledStatement
(
this
.
loopParent
))
{
return
_core
.
types
.
labeledStatement
(
this
.
loopLabel
,
this
.
loop
);
}
}
checkConstants
()
{
const
scope
=
this
.
scope
;
const
state
=
this
.
state
;
for
(
const
name
of
Object
.
keys
(
scope
.
bindings
))
{
const
binding
=
scope
.
bindings
[
name
];
if
(
binding
.
kind
!==
"const"
)
continue
;
for
(
const
violation
of
binding
.
constantViolations
)
{
const
readOnlyError
=
state
.
addHelper
(
"readOnlyError"
);
const
throwNode
=
_core
.
types
.
callExpression
(
readOnlyError
,
[
_core
.
types
.
stringLiteral
(
name
)]);
if
(
violation
.
isAssignmentExpression
())
{
violation
.
get
(
"right"
).
replaceWith
(
_core
.
types
.
sequenceExpression
([
throwNode
,
violation
.
get
(
"right"
).
node
]));
}
else
if
(
violation
.
isUpdateExpression
())
{
violation
.
replaceWith
(
_core
.
types
.
sequenceExpression
([
throwNode
,
violation
.
node
]));
}
else
if
(
violation
.
isForXStatement
())
{
violation
.
ensureBlock
();
violation
.
node
.
body
.
body
.
unshift
(
_core
.
types
.
expressionStatement
(
throwNode
));
}
}
}
}
updateScopeInfo
(
wrappedInClosure
)
{
const
blockScope
=
this
.
blockPath
.
scope
;
const
parentScope
=
blockScope
.
getFunctionParent
()
||
blockScope
.
getProgramParent
();
const
letRefs
=
this
.
letReferences
;
for
(
const
key
of
letRefs
.
keys
())
{
const
ref
=
letRefs
.
get
(
key
);
const
binding
=
blockScope
.
getBinding
(
ref
.
name
);
if
(
!
binding
)
continue
;
if
(
binding
.
kind
===
"let"
||
binding
.
kind
===
"const"
)
{
binding
.
kind
=
"var"
;
if
(
wrappedInClosure
)
{
if
(
blockScope
.
hasOwnBinding
(
ref
.
name
))
{
blockScope
.
removeBinding
(
ref
.
name
);
}
}
else
{
blockScope
.
moveBindingTo
(
ref
.
name
,
parentScope
);
}
}
}
}
remap
()
{
const
letRefs
=
this
.
letReferences
;
const
outsideLetRefs
=
this
.
outsideLetReferences
;
const
scope
=
this
.
scope
;
const
blockPathScope
=
this
.
blockPath
.
scope
;
for
(
const
key
of
letRefs
.
keys
())
{
const
ref
=
letRefs
.
get
(
key
);
if
(
scope
.
parentHasBinding
(
key
)
||
scope
.
hasGlobal
(
key
))
{
const
binding
=
scope
.
getOwnBinding
(
key
);
if
(
binding
)
{
const
parentBinding
=
scope
.
parent
.
getOwnBinding
(
key
);
if
(
binding
.
kind
===
"hoisted"
&&
(
!
parentBinding
||
isVar
(
parentBinding
.
path
.
parent
)))
{
continue
;
}
scope
.
rename
(
ref
.
name
);
}
if
(
blockPathScope
.
hasOwnBinding
(
key
))
{
blockPathScope
.
rename
(
ref
.
name
);
}
}
}
for
(
const
key
of
outsideLetRefs
.
keys
())
{
const
ref
=
letRefs
.
get
(
key
);
if
(
isInLoop
(
this
.
blockPath
)
&&
blockPathScope
.
hasOwnBinding
(
key
))
{
blockPathScope
.
rename
(
ref
.
name
);
}
}
}
wrapClosure
()
{
if
(
this
.
throwIfClosureRequired
)
{
throw
this
.
blockPath
.
buildCodeFrameError
(
"Compiling let/const in this block would add a closure "
+
"(throwIfClosureRequired)."
);
}
const
block
=
this
.
block
;
const
outsideRefs
=
this
.
outsideLetReferences
;
if
(
this
.
loop
)
{
for
(
const
name
of
Array
.
from
(
outsideRefs
.
keys
()))
{
const
id
=
outsideRefs
.
get
(
name
);
if
(
this
.
scope
.
hasGlobal
(
id
.
name
)
||
this
.
scope
.
parentHasBinding
(
id
.
name
))
{
outsideRefs
.
delete
(
id
.
name
);
this
.
letReferences
.
delete
(
id
.
name
);
this
.
scope
.
rename
(
id
.
name
);
this
.
letReferences
.
set
(
id
.
name
,
id
);
outsideRefs
.
set
(
id
.
name
,
id
);
}
}
}
this
.
has
=
this
.
checkLoop
();
this
.
hoistVarDeclarations
();
const
args
=
Array
.
from
(
outsideRefs
.
values
(),
node
=>
_core
.
types
.
cloneNode
(
node
));
const
params
=
args
.
map
(
id
=>
_core
.
types
.
cloneNode
(
id
));
const
isSwitch
=
this
.
blockPath
.
isSwitchStatement
();
const
fn
=
_core
.
types
.
functionExpression
(
null
,
params
,
_core
.
types
.
blockStatement
(
isSwitch
?
[
block
]
:
block
.
body
));
this
.
addContinuations
(
fn
);
let
call
=
_core
.
types
.
callExpression
(
_core
.
types
.
nullLiteral
(),
args
);
let
basePath
=
".callee"
;
const
hasYield
=
_core
.
traverse
.
hasType
(
fn
.
body
,
"YieldExpression"
,
_core
.
types
.
FUNCTION_TYPES
);
if
(
hasYield
)
{
fn
.
generator
=
true
;
call
=
_core
.
types
.
yieldExpression
(
call
,
true
);
basePath
=
".argument"
+
basePath
;
}
const
hasAsync
=
_core
.
traverse
.
hasType
(
fn
.
body
,
"AwaitExpression"
,
_core
.
types
.
FUNCTION_TYPES
);
if
(
hasAsync
)
{
fn
.
async
=
true
;
call
=
_core
.
types
.
awaitExpression
(
call
);
basePath
=
".argument"
+
basePath
;
}
let
placeholderPath
;
let
index
;
if
(
this
.
has
.
hasReturn
||
this
.
has
.
hasBreakContinue
)
{
const
ret
=
this
.
scope
.
generateUid
(
"ret"
);
this
.
body
.
push
(
_core
.
types
.
variableDeclaration
(
"var"
,
[
_core
.
types
.
variableDeclarator
(
_core
.
types
.
identifier
(
ret
),
call
)]));
placeholderPath
=
"declarations.0.init"
+
basePath
;
index
=
this
.
body
.
length
-
1
;
this
.
buildHas
(
ret
);
}
else
{
this
.
body
.
push
(
_core
.
types
.
expressionStatement
(
call
));
placeholderPath
=
"expression"
+
basePath
;
index
=
this
.
body
.
length
-
1
;
}
let
callPath
;
if
(
isSwitch
)
{
const
{
parentPath
,
listKey
,
key
}
=
this
.
blockPath
;
this
.
blockPath
.
replaceWithMultiple
(
this
.
body
);
callPath
=
parentPath
.
get
(
listKey
)[
key
+
index
];
}
else
{
block
.
body
=
this
.
body
;
callPath
=
this
.
blockPath
.
get
(
"body"
)[
index
];
}
const
placeholder
=
callPath
.
get
(
placeholderPath
);
let
fnPath
;
if
(
this
.
loop
)
{
const
loopId
=
this
.
scope
.
generateUid
(
"loop"
);
const
p
=
this
.
loopPath
.
insertBefore
(
_core
.
types
.
variableDeclaration
(
"var"
,
[
_core
.
types
.
variableDeclarator
(
_core
.
types
.
identifier
(
loopId
),
fn
)]));
placeholder
.
replaceWith
(
_core
.
types
.
identifier
(
loopId
));
fnPath
=
p
[
0
].
get
(
"declarations.0.init"
);
}
else
{
placeholder
.
replaceWith
(
fn
);
fnPath
=
placeholder
;
}
fnPath
.
unwrapFunctionEnvironment
();
}
addContinuations
(
fn
)
{
const
state
=
{
reassignments
:
{},
returnStatements
:
[],
outsideReferences
:
this
.
outsideLetReferences
};
this
.
scope
.
traverse
(
fn
,
continuationVisitor
,
state
);
for
(
let
i
=
0
;
i
<
fn
.
params
.
length
;
i
++
)
{
const
param
=
fn
.
params
[
i
];
if
(
!
state
.
reassignments
[
param
.
name
])
continue
;
const
paramName
=
param
.
name
;
const
newParamName
=
this
.
scope
.
generateUid
(
param
.
name
);
fn
.
params
[
i
]
=
_core
.
types
.
identifier
(
newParamName
);
this
.
scope
.
rename
(
paramName
,
newParamName
,
fn
);
state
.
returnStatements
.
forEach
(
returnStatement
=>
{
returnStatement
.
insertBefore
(
_core
.
types
.
expressionStatement
(
_core
.
types
.
assignmentExpression
(
"="
,
_core
.
types
.
identifier
(
paramName
),
_core
.
types
.
identifier
(
newParamName
))));
});
fn
.
body
.
body
.
push
(
_core
.
types
.
expressionStatement
(
_core
.
types
.
assignmentExpression
(
"="
,
_core
.
types
.
identifier
(
paramName
),
_core
.
types
.
identifier
(
newParamName
))));
}
}
getLetReferences
()
{
const
block
=
this
.
block
;
let
declarators
=
[];
if
(
this
.
loop
)
{
const
init
=
this
.
loop
.
left
||
this
.
loop
.
init
;
if
(
isBlockScoped
(
init
))
{
declarators
.
push
(
init
);
const
names
=
_core
.
types
.
getBindingIdentifiers
(
init
);
for
(
const
name
of
Object
.
keys
(
names
))
{
this
.
outsideLetReferences
.
set
(
name
,
names
[
name
]);
}
}
}
const
addDeclarationsFromChild
=
(
path
,
node
)
=>
{
node
=
node
||
path
.
node
;
if
(
_core
.
types
.
isClassDeclaration
(
node
)
||
_core
.
types
.
isFunctionDeclaration
(
node
)
||
isBlockScoped
(
node
))
{
if
(
isBlockScoped
(
node
))
{
convertBlockScopedToVar
(
path
,
node
,
block
,
this
.
scope
);
}
declarators
=
declarators
.
concat
(
node
.
declarations
||
node
);
}
if
(
_core
.
types
.
isLabeledStatement
(
node
))
{
addDeclarationsFromChild
(
path
.
get
(
"body"
),
node
.
body
);
}
};
if
(
block
.
body
)
{
const
declarPaths
=
this
.
blockPath
.
get
(
"body"
);
for
(
let
i
=
0
;
i
<
block
.
body
.
length
;
i
++
)
{
addDeclarationsFromChild
(
declarPaths
[
i
]);
}
}
if
(
block
.
cases
)
{
const
declarPaths
=
this
.
blockPath
.
get
(
"cases"
);
for
(
let
i
=
0
;
i
<
block
.
cases
.
length
;
i
++
)
{
const
consequents
=
block
.
cases
[
i
].
consequent
;
for
(
let
j
=
0
;
j
<
consequents
.
length
;
j
++
)
{
const
declar
=
consequents
[
j
];
addDeclarationsFromChild
(
declarPaths
[
i
],
declar
);
}
}
}
for
(
let
i
=
0
;
i
<
declarators
.
length
;
i
++
)
{
const
declar
=
declarators
[
i
];
const
keys
=
_core
.
types
.
getBindingIdentifiers
(
declar
,
false
,
true
);
for
(
const
key
of
Object
.
keys
(
keys
))
{
this
.
letReferences
.
set
(
key
,
keys
[
key
]);
}
this
.
hasLetReferences
=
true
;
}
if
(
!
this
.
hasLetReferences
)
return
;
const
state
=
{
letReferences
:
this
.
letReferences
,
closurify
:
false
,
loopDepth
:
0
,
tdzEnabled
:
this
.
tdzEnabled
,
addHelper
:
name
=>
this
.
state
.
addHelper
(
name
)
};
if
(
isInLoop
(
this
.
blockPath
))
{
state
.
loopDepth
++
;
}
this
.
blockPath
.
traverse
(
letReferenceBlockVisitor
,
state
);
return
state
.
closurify
;
}
checkLoop
()
{
const
state
=
{
hasBreakContinue
:
false
,
ignoreLabeless
:
false
,
inSwitchCase
:
false
,
innerLabels
:
[],
hasReturn
:
false
,
isLoop
:
!!
this
.
loop
,
map
:
{},
LOOP_IGNORE
:
Symbol
()
};
this
.
blockPath
.
traverse
(
loopLabelVisitor
,
state
);
this
.
blockPath
.
traverse
(
loopVisitor
,
state
);
return
state
;
}
hoistVarDeclarations
()
{
this
.
blockPath
.
traverse
(
hoistVarDeclarationsVisitor
,
this
);
}
pushDeclar
(
node
)
{
const
declars
=
[];
const
names
=
_core
.
types
.
getBindingIdentifiers
(
node
);
for
(
const
name
of
Object
.
keys
(
names
))
{
declars
.
push
(
_core
.
types
.
variableDeclarator
(
names
[
name
]));
}
this
.
body
.
push
(
_core
.
types
.
variableDeclaration
(
node
.
kind
,
declars
));
const
replace
=
[];
for
(
let
i
=
0
;
i
<
node
.
declarations
.
length
;
i
++
)
{
const
declar
=
node
.
declarations
[
i
];
if
(
!
declar
.
init
)
continue
;
const
expr
=
_core
.
types
.
assignmentExpression
(
"="
,
_core
.
types
.
cloneNode
(
declar
.
id
),
_core
.
types
.
cloneNode
(
declar
.
init
));
replace
.
push
(
_core
.
types
.
inherits
(
expr
,
declar
));
}
return
replace
;
}
buildHas
(
ret
)
{
const
body
=
this
.
body
;
const
has
=
this
.
has
;
if
(
has
.
hasBreakContinue
)
{
for
(
const
key
of
Object
.
keys
(
has
.
map
))
{
body
.
push
(
_core
.
types
.
ifStatement
(
_core
.
types
.
binaryExpression
(
"==="
,
_core
.
types
.
identifier
(
ret
),
_core
.
types
.
stringLiteral
(
key
)),
has
.
map
[
key
]));
}
}
if
(
has
.
hasReturn
)
{
body
.
push
(
buildRetCheck
({
RETURN
:
_core
.
types
.
identifier
(
ret
)
}));
}
}
}
Event Timeline
Log In to Comment