Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F100650789
BlockStatement.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
Sat, Feb 1, 12:50
Size
10 KB
Mime Type
text/x-java
Expires
Mon, Feb 3, 12:50 (1 d, 21 h)
Engine
blob
Format
Raw Data
Handle
24007121
Attached To
rOACCT Open Access Compliance Check Tool (OACCT)
BlockStatement.js
View Options
import
Node
from
'./Node.js'
;
import
Scope
from
'./Scope.js'
;
import
destructure
from
'../utils/destructure.js'
;
function
isUseStrict
(
node
)
{
if
(
!
node
)
return
false
;
if
(
node
.
type
!==
'ExpressionStatement'
)
return
false
;
if
(
node
.
expression
.
type
!==
'Literal'
)
return
false
;
return
node
.
expression
.
value
===
'use strict'
;
}
export
default
class
BlockStatement
extends
Node
{
createScope
()
{
this
.
parentIsFunction
=
/Function/
.
test
(
this
.
parent
.
type
);
this
.
isFunctionBlock
=
this
.
parentIsFunction
||
this
.
parent
.
type
===
'Root'
;
this
.
scope
=
new
Scope
({
block
:
!
this
.
isFunctionBlock
,
parent
:
this
.
parent
.
findScope
(
false
),
declare
:
id
=>
this
.
createdDeclarations
.
push
(
id
)
});
if
(
this
.
parentIsFunction
)
{
this
.
parent
.
params
.
forEach
(
node
=>
{
this
.
scope
.
addDeclaration
(
node
,
'param'
);
});
}
}
initialise
(
transforms
)
{
this
.
thisAlias
=
null
;
this
.
argumentsAlias
=
null
;
this
.
defaultParameters
=
[];
this
.
createdDeclarations
=
[];
// normally the scope gets created here, during initialisation,
// but in some cases (e.g. `for` statements), we need to create
// the scope early, as it pertains to both the init block and
// the body of the statement
if
(
!
this
.
scope
)
this
.
createScope
();
this
.
body
.
forEach
(
node
=>
node
.
initialise
(
transforms
));
this
.
scope
.
consolidate
();
}
findLexicalBoundary
()
{
if
(
this
.
type
===
'Program'
)
return
this
;
if
(
/^Function/
.
test
(
this
.
parent
.
type
))
return
this
;
return
this
.
parent
.
findLexicalBoundary
();
}
findScope
(
functionScope
)
{
if
(
functionScope
&&
!
this
.
isFunctionBlock
)
return
this
.
parent
.
findScope
(
functionScope
);
return
this
.
scope
;
}
getArgumentsAlias
()
{
if
(
!
this
.
argumentsAlias
)
{
this
.
argumentsAlias
=
this
.
scope
.
createIdentifier
(
'arguments'
);
}
return
this
.
argumentsAlias
;
}
getArgumentsArrayAlias
()
{
if
(
!
this
.
argumentsArrayAlias
)
{
this
.
argumentsArrayAlias
=
this
.
scope
.
createIdentifier
(
'argsArray'
);
}
return
this
.
argumentsArrayAlias
;
}
getThisAlias
()
{
if
(
!
this
.
thisAlias
)
{
this
.
thisAlias
=
this
.
scope
.
createIdentifier
(
'this'
);
}
return
this
.
thisAlias
;
}
getIndentation
()
{
if
(
this
.
indentation
===
undefined
)
{
const
source
=
this
.
program
.
magicString
.
original
;
const
useOuter
=
this
.
synthetic
||
!
this
.
body
.
length
;
let
c
=
useOuter
?
this
.
start
:
this
.
body
[
0
].
start
;
while
(
c
&&
source
[
c
]
!==
'\n'
)
c
-=
1
;
this
.
indentation
=
''
;
// eslint-disable-next-line no-constant-condition
while
(
true
)
{
c
+=
1
;
const
char
=
source
[
c
];
if
(
char
!==
' '
&&
char
!==
'\t'
)
break
;
this
.
indentation
+=
char
;
}
const
indentString
=
this
.
program
.
magicString
.
getIndentString
();
// account for dedented class constructors
let
parent
=
this
.
parent
;
while
(
parent
)
{
if
(
parent
.
kind
===
'constructor'
&&
!
parent
.
parent
.
parent
.
superClass
)
{
this
.
indentation
=
this
.
indentation
.
replace
(
indentString
,
''
);
}
parent
=
parent
.
parent
;
}
if
(
useOuter
)
this
.
indentation
+=
indentString
;
}
return
this
.
indentation
;
}
transpile
(
code
,
transforms
)
{
const
indentation
=
this
.
getIndentation
();
const
introStatementGenerators
=
[];
if
(
this
.
argumentsAlias
)
{
introStatementGenerators
.
push
((
start
,
prefix
,
suffix
)
=>
{
const
assignment
=
`
$
{
prefix
}
var
$
{
this
.
argumentsAlias
}
=
arguments$
{
suffix
}
`
;
code
.
appendLeft
(
start
,
assignment
);
});
}
if
(
this
.
thisAlias
)
{
introStatementGenerators
.
push
((
start
,
prefix
,
suffix
)
=>
{
const
assignment
=
`
$
{
prefix
}
var
$
{
this
.
thisAlias
}
=
this
$
{
suffix
}
`
;
code
.
appendLeft
(
start
,
assignment
);
});
}
if
(
this
.
argumentsArrayAlias
)
{
introStatementGenerators
.
push
((
start
,
prefix
,
suffix
)
=>
{
const
i
=
this
.
scope
.
createIdentifier
(
'i'
);
const
assignment
=
`
$
{
prefix
}
var
$
{
i
}
=
arguments
.
length
,
$
{
this
.
argumentsArrayAlias
}
=
Array
(
$
{
i
});
\
n$
{
indentation
}
while
(
$
{
i
}
--
)
$
{
this
.
argumentsArrayAlias
}[
$
{
i
}]
=
arguments
[
$
{
i
}]
$
{
suffix
}
`
;
code
.
appendLeft
(
start
,
assignment
);
});
}
if
(
/Function/
.
test
(
this
.
parent
.
type
))
{
this
.
transpileParameters
(
this
.
parent
.
params
,
code
,
transforms
,
indentation
,
introStatementGenerators
);
}
else
if
(
'CatchClause'
===
this
.
parent
.
type
)
{
this
.
transpileParameters
(
[
this
.
parent
.
param
],
code
,
transforms
,
indentation
,
introStatementGenerators
);
}
if
(
transforms
.
letConst
&&
this
.
isFunctionBlock
)
{
this
.
transpileBlockScopedIdentifiers
(
code
);
}
super
.
transpile
(
code
,
transforms
);
if
(
this
.
createdDeclarations
.
length
)
{
introStatementGenerators
.
push
((
start
,
prefix
,
suffix
)
=>
{
const
assignment
=
`
$
{
prefix
}
var
$
{
this
.
createdDeclarations
.
join
(
', '
)}
$
{
suffix
}
`
;
code
.
appendLeft
(
start
,
assignment
);
});
}
if
(
this
.
synthetic
)
{
if
(
this
.
parent
.
type
===
'ArrowFunctionExpression'
)
{
const
expr
=
this
.
body
[
0
];
if
(
introStatementGenerators
.
length
)
{
code
.
appendLeft
(
this
.
start
,
`
{
`
)
.
prependRight
(
this
.
end
,
`
$
{
this
.
parent
.
getIndentation
()}}
`
);
code
.
prependRight
(
expr
.
start
,
`\
n$
{
indentation
}
return
`
);
code
.
appendLeft
(
expr
.
end
,
`
;
\
n
`
);
}
else
if
(
transforms
.
arrow
)
{
code
.
prependRight
(
expr
.
start
,
`
{
return
`
);
code
.
appendLeft
(
expr
.
end
,
`
;
}
`
);
}
}
else
if
(
introStatementGenerators
.
length
)
{
code
.
prependRight
(
this
.
start
,
`
{
`
).
appendLeft
(
this
.
end
,
`
}
`
);
}
}
let
start
;
if
(
isUseStrict
(
this
.
body
[
0
]))
{
start
=
this
.
body
[
0
].
end
;
}
else
if
(
this
.
synthetic
||
this
.
parent
.
type
===
'Root'
)
{
start
=
this
.
start
;
}
else
{
start
=
this
.
start
+
1
;
}
const
prefix
=
`\
n$
{
indentation
}
`
;
let
suffix
=
';'
;
introStatementGenerators
.
forEach
((
fn
,
i
)
=>
{
if
(
i
===
introStatementGenerators
.
length
-
1
)
suffix
=
`
;
\
n
`
;
fn
(
start
,
prefix
,
suffix
);
});
}
transpileParameters
(
params
,
code
,
transforms
,
indentation
,
introStatementGenerators
)
{
params
.
forEach
(
param
=>
{
if
(
param
.
type
===
'AssignmentPattern'
&&
param
.
left
.
type
===
'Identifier'
)
{
if
(
transforms
.
defaultParameter
)
{
introStatementGenerators
.
push
((
start
,
prefix
,
suffix
)
=>
{
const
lhs
=
`
$
{
prefix
}
if
(
$
{
param
.
left
.
name
}
===
void
0
)
$
{
param
.
left
.
name
}
`
;
code
.
prependRight
(
param
.
left
.
end
,
lhs
)
.
move
(
param
.
left
.
end
,
param
.
right
.
end
,
start
)
.
appendLeft
(
param
.
right
.
end
,
suffix
);
});
}
}
else
if
(
param
.
type
===
'RestElement'
)
{
if
(
transforms
.
spreadRest
)
{
introStatementGenerators
.
push
((
start
,
prefix
,
suffix
)
=>
{
const
penultimateParam
=
params
[
params
.
length
-
2
];
if
(
penultimateParam
)
{
code
.
remove
(
penultimateParam
?
penultimateParam
.
end
:
param
.
start
,
param
.
end
);
}
else
{
let
start
=
param
.
start
,
end
=
param
.
end
;
// TODO https://gitlab.com/Rich-Harris/buble/issues/8
while
(
/\s/
.
test
(
code
.
original
[
start
-
1
]))
start
-=
1
;
while
(
/\s/
.
test
(
code
.
original
[
end
]))
end
+=
1
;
code
.
remove
(
start
,
end
);
}
const
name
=
param
.
argument
.
name
;
const
len
=
this
.
scope
.
createIdentifier
(
'len'
);
const
count
=
params
.
length
-
1
;
if
(
count
)
{
code
.
prependRight
(
start
,
`
$
{
prefix
}
var
$
{
name
}
=
[],
$
{
len
}
=
arguments
.
length
-
$
{
count
};
\
n$
{
indentation
}
while
(
$
{
len
}
--
>
0
)
$
{
name
}[
$
{
len
}
]
=
arguments
[
$
{
len
}
+
$
{
count
}
]
$
{
suffix
}
`
);
}
else
{
code
.
prependRight
(
start
,
`
$
{
prefix
}
var
$
{
name
}
=
[],
$
{
len
}
=
arguments
.
length
;
\
n$
{
indentation
}
while
(
$
{
len
}
--
)
$
{
name
}[
$
{
len
}
]
=
arguments
[
$
{
len
}
]
$
{
suffix
}
`
);
}
});
}
}
else
if
(
param
.
type
!==
'Identifier'
)
{
if
(
transforms
.
parameterDestructuring
)
{
const
ref
=
this
.
scope
.
createIdentifier
(
'ref'
);
destructure
(
code
,
id
=>
this
.
scope
.
createIdentifier
(
id
),
({
name
})
=>
this
.
scope
.
resolveName
(
name
),
param
,
ref
,
false
,
introStatementGenerators
);
code
.
prependRight
(
param
.
start
,
ref
);
}
}
});
}
transpileBlockScopedIdentifiers
(
code
)
{
Object
.
keys
(
this
.
scope
.
blockScopedDeclarations
).
forEach
(
name
=>
{
const
declarations
=
this
.
scope
.
blockScopedDeclarations
[
name
];
for
(
const
declaration
of
declarations
)
{
let
cont
=
false
;
// TODO implement proper continue...
if
(
declaration
.
kind
===
'for.let'
)
{
// special case
const
forStatement
=
declaration
.
node
.
findNearest
(
'ForStatement'
);
if
(
forStatement
.
shouldRewriteAsFunction
)
{
const
outerAlias
=
this
.
scope
.
createIdentifier
(
name
);
const
innerAlias
=
forStatement
.
reassigned
[
name
]
?
this
.
scope
.
createIdentifier
(
name
)
:
name
;
declaration
.
name
=
outerAlias
;
code
.
overwrite
(
declaration
.
node
.
start
,
declaration
.
node
.
end
,
outerAlias
,
{
storeName
:
true
}
);
forStatement
.
aliases
[
name
]
=
{
outer
:
outerAlias
,
inner
:
innerAlias
};
for
(
const
identifier
of
declaration
.
instances
)
{
const
alias
=
forStatement
.
body
.
contains
(
identifier
)
?
innerAlias
:
outerAlias
;
if
(
name
!==
alias
)
{
code
.
overwrite
(
identifier
.
start
,
identifier
.
end
,
alias
,
{
storeName
:
true
});
}
}
cont
=
true
;
}
}
if
(
!
cont
)
{
const
alias
=
this
.
scope
.
createIdentifier
(
name
);
if
(
name
!==
alias
)
{
const
declarationParent
=
declaration
.
node
.
parent
;
declaration
.
name
=
alias
;
code
.
overwrite
(
declaration
.
node
.
start
,
declaration
.
node
.
end
,
alias
,
{
storeName
:
true
}
);
if
(
declarationParent
.
type
===
'Property'
&&
declarationParent
.
shorthand
)
{
declarationParent
.
shorthand
=
false
;
code
.
prependLeft
(
declaration
.
node
.
start
,
`
$
{
name
}
:
`
);
}
for
(
const
identifier
of
declaration
.
instances
)
{
identifier
.
rewritten
=
true
;
const
identifierParent
=
identifier
.
parent
;
code
.
overwrite
(
identifier
.
start
,
identifier
.
end
,
alias
,
{
storeName
:
true
});
if
(
identifierParent
.
type
===
'Property'
&&
identifierParent
.
shorthand
)
{
identifierParent
.
shorthand
=
false
;
code
.
prependLeft
(
identifier
.
start
,
`
$
{
name
}
:
`
);
}
}
}
}
}
});
}
}
Event Timeline
Log In to Comment