Info about a Scala method param when called as JS method.
Generates the Scala.js IR for a compilation unit This method iterates over all the class and interface definitions found in the compilation unit and emits their IR (.sjsir).
Generates the Scala.js IR for a compilation unit This method iterates over all the class and interface definitions found in the compilation unit and emits their IR (.sjsir).
Some classes are never actually emitted:
Some classes representing anonymous functions are not actually emitted.
Instead, a temporary representation of their apply
method is built
and recorded, so that it can be inlined as a JavaScript anonymous
function in the method that instantiates it.
Other ClassDefs are emitted according to their nature:
* Non-native JS class -> genNonNativeJSClass()
* Other JS type (<: js.Any) -> genJSClassData()
* Interface -> genInterface()
* Normal class -> genClass()
Ensures that the value of the given tree is boxed.
Ensures that the value of the given tree is boxed.
Tree to be boxed if needed.
The type of expr
as it was entering
the posterasure phase.
Ensures that the value of the given tree is boxed when used as a method result value.
Ensures that the value of the given tree is boxed when used as a method result value.
Tree to be boxed if needed.
Turn a JavaScript expression of type Unit into a statement
Extracts a value typed as Any to the given type after posterasure.
Extracts a value typed as Any to the given type after posterasure.
Tree to be extracted.
The type of expr
as it was entering
the posterasure phase.
Generate an instance of an anonymous (non-lambda) JS class inline
Generate an instance of an anonymous (non-lambda) JS class inline
Class to generate the instance of
JS class value of the super class
Arguments to the Scala constructor, which map to JS class captures
Position of the original New tree
Gen JS code for an Apply node (method call)
Gen JS code for an Apply node (method call)
There's a whole bunch of varieties of Apply nodes: regular method calls, super calls, constructor calls, isInstanceOf/asInstanceOf, primitives, JS calls, etc. They are further dispatched in here.
Gen JS code for a call to a Scala method.
Gen JS code for an array literal, in the context of tree
(its tpe
and pos
) but with the elements elems
.
Gen JS code for an array literal.
Gen JS code for an asInstanceOf cast (for reference types only)
Gen the IR ClassDef for a class definition (maybe a module class).
Gen definitions for the fields of a class.
Gen definitions for the fields of a class. The fields are initialized with the zero of their types.
Gen JS code for a call to Any.==
Gen JS code for a tree in expression position (in the IR).
Gen JS code for a tree in expression position (in the IR) or the global scope.
Gen the IR ClassDef for an interface definition.
Gen JS code for an isInstanceOf test (for reference types only)
Wraps a js.Array
to use as varargs.
Gen the IR ClassDef for a JS class or trait.
Gen JS code for a JS function class.
Gen JS code for a JS function class.
This is called when emitting a ClassDef that represents an anonymous
class extending js.FunctionN
. These are generated by the SAM
synthesizer when the target type is a js.FunctionN
. Since JS
functions are not classes, we deconstruct the ClassDef, then
reconstruct it to be a genuine Closure.
Compared to tryGenAnonFunctionClass()
, this function must
always succeed, because we really cannot afford keeping them as
anonymous classes. The good news is that it can do so, because the
body of SAM lambdas is hoisted in the enclosing class. Hence, the
apply() method is just a forwarder to calling that hoisted method.
From a class looking like this:
final class <anon>(outer, capture1, ..., captureM) extends js.FunctionN[...] { def apply(param1, ..., paramN) = { outer.lambdaImpl(param1, ..., paramN, capture1, ..., captureM) } } new <anon>(o, c1, ..., cM)
we generate a function:
lambda<o, c1, ..., cM>[notype]( outer, capture1, ..., captureM, param1, ..., paramN) { outer.lambdaImpl(param1, ..., paramN, capture1, ..., captureM) }
Generates the JSNativeMemberDef of a JS native method.
Gen JS code for LabelDef.
Gen JS code for LabelDef.
If a LabelDef reaches this method, then the only valid jumps are from within it, which means it basically represents a loop. Other kinds of LabelDefs, notably those for matches, are caught upstream and transformed in ad hoc ways.
The general transformation for
labelName(...labelParams) { rhs }: T
is the following:
block[T]: { while (true) { labelName[void]: { return@block transformedRhs } } }
where all jumps to the label inside the rhs of the form
labelName(...args)
are transformed into
...labelParams = ...args; return@labelName (void 0)
This is always correct, so it can handle arbitrary labels and jumps
such as those produced by loops, tail-recursive calls and even some
compiler plugins (see for example #1148). However, the result is
unnecessarily ugly for simple while
and do while
loops, so we have
some post-processing to simplify those.
Generate loading of a module value.
Generate loading of a module value.
Can be given either the module symbol or its module class symbol.
If the module we load refers to the global scope (i.e., it is
annotated with @JSGlobalScope
), report a compile error specifying
that a global scope object should only be used as the qualifier of a
.
-selection.
Generate loading of a module value or the global scope.
Generate loading of a module value or the global scope.
Can be given either the module symbol of its module class symbol.
Unlike genLoadModule
, this method does not fail if the module we load
refers to the global scope.
Gen JS code for a Match, i.e., a switch-able pattern match.
Gen JS code for a Match, i.e., a switch-able pattern match.
In most cases, this straightforwardly translates to a Match in the IR,
which will eventually become a switch
in JavaScript.
However, sometimes there is a guard in here, despite the fact that
matches cannot have guards (in the JVM nor in the IR). The JVM backend
emits a jump to the default clause when a guard is not fulfilled. We
cannot do that, since we do not have arbitrary jumps. We therefore use
a funny encoding with two nested Labeled
blocks. For example,
x match { case 1 if y > 0 => a case 2 => b case _ => c }
arrives at the back-end as
x match { case 1 => if (y > 0) a else default() case 2 => b case _ => default() { c } }
which we then translate into the following IR:
matchResult[I]: { default[V]: { x match { case 1 => return(matchResult) if (y > 0) a else return(default) (void 0) case 2 => return(matchResult) b case _ => () } } c }
Generates exported methods and properties for a class.
Generates exported methods and properties for a class.
symbol of the class we export for
Maybe gen JS code for a method definition.
Maybe gen JS code for a method definition.
Some methods are not emitted at all:
@JavaDefaultMethod
annotation mixed in classes.
@JavaDefaultMethod }}}
Generates the MethodDef of a (non-constructor) method
Generates the MethodDef of a (non-constructor) method
Most normal methods are emitted straightforwardly. If the result type is Unit, then the body is emitted as a statement. Otherwise, it is emitted as an expression.
The additional complexity of this method handles the transformation of
a peculiarity of recursive tail calls: the local ValDef that replaces
this
.
Gen JS code for a method definition in a class or in an impl class.
Gen JS code for a method definition in a class or in an impl class.
On the JS side, method names are mangled to encode the full signature
of the Scala method, as described in JSEncoding
, to support
overloading.
Constructors are emitted by generating their body as a statement.
Interface methods with the
@JavaDefaultMethod
annotation produce default methods forwarding to the trait impl class method.
Other (normal) methods are emitted with genMethodDef()
.
@JavaDefaultMethod }}} default methods forwarding to the trait impl class method.
Other (normal) methods are emitted with genMethodDef()
.
Gen JS code for a call to a Scala class constructor.
Gen JS code for a call to a Scala class constructor.
Gen JS code for creating a new Array: new Array[T](length)
For multidimensional arrays (dimensions > 1), the arguments can
specify up to dimensions
lengths for the first dimensions of the
array.
Gen the IR ClassDef for a non-native JS class.
Gen JS code for a Labeled block from a pattern match'es match-end, while trying to optimize it away as an If chain.
Gen JS code for a Labeled block from a pattern match'es match-end, while trying to optimize it away as an If chain.
It is important to do so at compile-time because, when successful, the resulting IR can be much better optimized by the optimizer.
The optimizer also does something similar, but *after* it has processed the body of the Labeled block, at which point it has already lost any information about stack-allocated values.
!!! There is quite of bit of code duplication with OptimizerCore.tryOptimizePatternMatch.
Generates a Scala argument from dispatched JavaScript arguments (unboxing and default parameter handling).
Generates a Scala argument from dispatched JavaScript arguments (unboxing and default parameter handling).
Gen JS code for a tree in statement position (in the IR).
Gen JS code for a tree in statement or expression position (in the IR).
Gen JS code for a tree in statement or expression position (in the IR).
This is the main transformation method. Each node of the Scala AST is transformed into an equivalent portion of the JS AST.
Gen the static forwarders to the members of a class or interface for methods of its companion object.
Gen the static forwarders to the members of a class or interface for methods of its companion object.
This is only done if there exists a companion object and it is not a JS type.
Precondition: isCandidateForForwarders(sym)
is true
Gen the static forwarders for the methods of a module class.
Gen the static forwarders for the methods of a module class.
Precondition: isCandidateForForwarders(moduleClass)
is true
Gen JS code for a try..catch or try..finally block
Gen JS code for a try..catch or try..finally block
try..finally blocks are compiled straightforwardly to try..finally blocks of JS.
try..catch blocks are a bit more subtle, as JS does not have type-based selection of exceptions to catch. We thus encode explicitly the type tests, like in:
try { ... } catch (e) { if (e.isInstanceOf[IOException]) { ... } else if (e.isInstanceOf[Exception]) { ... } else { throw e; // default, re-throw } }
Is the given Scala class, interface or module class a candidate for static forwarders?
Gen a boxing operation (tpe is the primitive type)
Gen an unboxing operation (tpe is the primitive type)