4. def times2(xs: List[Int]): List[Int] = {
var result: List[Int] = Nil
var i = 0
while (i < xs.length) {
result = result :+ (xs(i) * 2)
i += 1
}
result
}
3
5. def times2(xs: List[Int]): List[Int] = {
var result: List[Int] = Nil
for (i <- 0 until xs.length) {
result = result :+ (xs(i) * 2)
}
result
}
4
6. def times2(xs: List[Int]): List[Int] = {
val builder = List.newBuilder[Int]
for (i <- 0 until xs.length) {
builder += xs(i) * 2
}
builder.result()
}
5
7. def times2(xs: List[Int]): List[Int] = {
val builder = List.newBuilder[Int]
for (x <- xs) {
builder += x * 2
}
builder.result()
}
6
8. def times2(xs: List[Int]): List[Int] = {
for (x <- xs)
yield x * 2
}
def times2(xs: List[Int]): List[Int] = {
xs.map(x => x * 2)
}
7
13. var test = {
genIsScalaJSObject(obj) &&
genIsClassNameInAncestors(...)
}
def typeOfTest(typeString: String): js.Tree = ...
if (isAncestorOfString)
test = test || typeOfTest("string")
if (isAncestorOfHijackedNumberClass) {
test = test || typeOfTest("number")
if (useBigIntForLongs)
test = test || genCallHelper("isLong", obj)
}
if (isAncestorOfBoxedBooleanClass)
test = test || typeOfTest("boolean")
if (isAncestorOfBoxedCharacterClass)
test = test || (obj instanceof envField("Char"))
test
11
14. var test = {
genIsScalaJSObject(obj) &&
genIsClassNameInAncestors(...)
}
def typeOfTest(typeString: String): js.Tree = ...
if (isAncestorOfString)
test = test || typeOfTest("string")
if (isAncestorOfHijackedNumberClass) {
test = test || typeOfTest("number")
if (useBigIntForLongs)
test = test || genCallHelper("isLong", obj)
}
if (isAncestorOfBoxedBooleanClass)
test = test || typeOfTest("boolean")
if (isAncestorOfBoxedCharacterClass)
test = test || (obj instanceof envField("Char"))
test
11
15. val test0 = {
genIsScalaJSObject(obj) &&
genIsClassNameInAncestors(...)
}
def typeOfTest(typeString: String): js.Tree = ...
val test1 =
if (isAncestorOfString) test0 || typeOfTest("string")
else test0
val test3 = if (isAncestorOfHijackedNumberClass) {
val test2 = test1 || typeOfTest("number")
if (useBigIntForLongs) test2 || genCallHelper("isLong", obj)
else test2
}
val test4 =
if (isAncestorOfBoxedBooleanClass) test3 || typeOfTest("boolean")
else test3
val test5 =
if (isAncestorOfBoxedCharacterClass) test4 || (obj instanceof envField("Char"))
else test4
test5
12
16. val test0 = {
genIsScalaJSObject(obj) &&
genIsClassNameInAncestors(...)
}
def typeOfTest(typeString: String): js.Tree = ...
val test1 =
if (isAncestorOfString) test0 || typeOfTest("string")
else test0
val test3 = if (isAncestorOfHijackedNumberClass) {
val test2 = test1 || typeOfTest("number")
if (useBigIntForLongs) test2 || genCallHelper("isLong", obj)
else test2
}
val test4 =
if (isAncestorOfBoxedBooleanClass) test3 || typeOfTest("boolean")
else test3
val test5 =
if (isAncestorOfBoxedCharacterClass) test4 || (obj instanceof envField("Char"))
else test4
test5
12
17. val test0 = {
genIsScalaJSObject(obj) &&
genIsClassNameInAncestors(...)
}
def typeOfTest(typeString: String): js.Tree = ...
val test1 =
if (isAncestorOfString) test0 || typeOfTest("string")
else test0
val test3 = if (isAncestorOfHijackedNumberClass) {
val test2 = test1 || typeOfTest("number")
if (useBigIntForLongs) test2 || genCallHelper("isLong", obj)
else test2
}
val test4 =
if (isAncestorOfBoxedBooleanClass) test3 || typeOfTest("boolean")
else test3
val test5 =
if (isAncestorOfBoxedCharacterClass) test4 || (obj instanceof envField("Char"))
else test4
test5
12
18. val test0 = {
genIsScalaJSObject(obj) &&
genIsClassNameInAncestors(...)
}
def typeOfTest(typeString: String): js.Tree = ...
val test1 =
if (isAncestorOfString) test0 || typeOfTest("string")
else test0
val test3 = if (isAncestorOfHijackedNumberClass) {
val test2 = test1 || typeOfTest("number")
if (useBigIntForLongs) test2 || genCallHelper("isLong", obj)
else test2
}
val test4 =
if (isAncestorOfBoxedBooleanClass) test3 || typeOfTest("boolean")
else test3
val test5 =
if (isAncestorOfBoxedCharacterClass) test4 || (obj instanceof envField("Char"))
else test4
test5
12
32. /** A backend of a standard Scala.js linker. */
abstract class LinkerBackend {
/** Core specification that this linker backend implements. */
val coreSpec: CoreSpec
/** Symbols this backend needs to be present in the linking unit. */
val symbolRequirements: SymbolRequirement
/** Emit the given LinkingUnit to the target output. */
def emit(unit: LinkingUnit, output: LinkerOutput, logger: Logger)(
implicit ec: ExecutionContext): Future[Unit]
}
23
33. /** The basic backend for the Scala.js linker. */
final class BasicLinkerBackend(config: LinkerBackendImpl.Config)
extends LinkerBackend {
val coreSpec = config.commonConfig.coreSpec
private[this] val emitter = new Emitter(config.commonConfig)
val symbolRequirements: SymbolRequirement = emitter.symbolRequirements
def emit(unit: LinkingUnit, output: LinkerOutput, logger: Logger)(
implicit ec: ExecutionContext): Future[Unit] = {
...
val builder = new JSFileBuilder
emitter.emitAll(unit, builder, logger)
OutputFileImpl.fromOutputFile(output.jsFile)
.writeFull(builer.complete())
...
}
}
24
34. /** The Closure backend of the Scala.js linker. */
final class ClosureLinkerBackend(config: LinkerBackendImpl.Config)
extends LinkerBackend {
val coreSpec = config.commonConfig.coreSpec
private[this] val emitter = new Emitter(config.commonConfig)
val symbolRequirements: SymbolRequirement = emitter.symbolRequirements
def emit(unit: LinkingUnit, output: LinkerOutput, logger: Logger)(
implicit ec: ExecutionContext): Future[Unit] = {
...
val builer = new ClosureModuleBuilder
emitter.emitAll(unit, builer, logger)
val closureModules = makeClosureModules(builder.result())
val result = closureCompiler.compileModules(..., closureModules, ...)
writeResult(result, ...)
...
}
}
25
36. /** A JavaScript execution environment.
*
* This can run and interact with JavaScript code.
*
* Any implementation is expected to be fully thread-safe.
*/
trait JSEnv {
/** Human-readable name for this [[JSEnv]] */
val name: String
/** Starts a new (asynchronous) JS run. */
def start(input: Input, config: RunConfig): JSRun
/** Like [[start]], but initializes a communication channel. */
def startWithCom(input: Input, config: RunConfig,
onMessage: String => Unit): JSComRun
}
27
39. def genMethod(className: String, method: MethodDef)(
implicit globalKnowledge: GlobalKnowledge): WithGlobals[js.Tree] = {
val methodBody = method.body.getOrElse(
throw new AssertionError("Cannot generate an abstract method"))
implicit val pos = method.pos
val namespace = method.flags.namespace
val methodFunWithGlobals: WithGlobals[js.Function] =
desugarToFunction(className, method.args, methodBody, method.resultType)
methodFunWithGlobals.flatMap { methodFun =>
if (namespace != MemberNamespace.Public) {
...
} else {
if (useClasses) {
for (propName <- genPropertyName(method.name)) yield {
js.MethodDef(static = false, propName, methodFun.args,
methodFun.body)
}
} else {
genAddToPrototype(className, method.name, methodFun)
}
}
}
}
30
40. def genMethod(className: String, method: MethodDef)(
implicit globalKnowledge: GlobalKnowledge): WithGlobals[js.Tree] = {
val methodBody = method.body.getOrElse(
throw new AssertionError("Cannot generate an abstract method"))
implicit val pos = method.pos
val namespace = method.flags.namespace
val methodFunWithGlobals: WithGlobals[js.Function] =
desugarToFunction(className, method.args, methodBody, method.resultType)
methodFunWithGlobals.flatMap { methodFun =>
if (namespace != MemberNamespace.Public) {
...
} else {
if (useClasses) {
for (propName <- genPropertyName(method.name)) yield {
js.MethodDef(static = false, propName, methodFun.args,
methodFun.body)
}
} else {
genAddToPrototype(className, method.name, methodFun)
}
}
}
}
30
41. def genMethod(className: String, method: MethodDef)(
implicit globalKnowledge: GlobalKnowledge): WithGlobals[js.Tree] = {
val methodBody = method.body.getOrElse(
throw new AssertionError("Cannot generate an abstract method"))
implicit val pos = method.pos
val namespace = method.flags.namespace
val methodFunWithGlobals: WithGlobals[js.Function] =
desugarToFunction(className, method.args, methodBody, method.resultType)
methodFunWithGlobals.flatMap { methodFun =>
if (namespace != MemberNamespace.Public) {
...
} else {
if (useClasses) {
for (propName <- genPropertyName(method.name)) yield {
js.MethodDef(static = false, propName, methodFun.args,
methodFun.body)
}
} else {
genAddToPrototype(className, method.name, methodFun)
}
}
}
}
30
42. def genMethod(className: String, method: MethodDef)(
implicit globalKnowledge: GlobalKnowledge): WithGlobals[js.Tree] = {
val methodBody = method.body.getOrElse(
throw new AssertionError("Cannot generate an abstract method"))
implicit val pos = method.pos
val namespace = method.flags.namespace
val methodFunWithGlobals: WithGlobals[js.Function] =
desugarToFunction(className, method.args, methodBody, method.resultType)
methodFunWithGlobals.flatMap { methodFun =>
if (namespace != MemberNamespace.Public) {
...
} else {
if (useClasses) {
for (propName <- genPropertyName(method.name)) yield {
js.MethodDef(static = false, propName, methodFun.args,
methodFun.body)
}
} else {
genAddToPrototype(className, method.name, methodFun)
}
}
}
}
30
43. /** A monad that associates a set of global variable names to a value. */
private[emitter] final case class WithGlobals[+A](
value: A, globalVarNames: Set[String]) {
def map[B](f: A => B): WithGlobals[B] =
WithGlobals(f(value), globalVarNames)
def flatMap[B](f: A => WithGlobals[B]): WithGlobals[B] = {
val t = f(value)
WithGlobals(t.value, globalVarNames ++ t.globalVarNames)
}
}
private[emitter] object WithGlobals {
/** Constructs a `WithGlobals` with an empty set `globalVarNames`. */
def apply[A](value: A): WithGlobals[A] =
new WithGlobals(value, Set.empty)
def list[A](xs: List[WithGlobals[A]]): WithGlobals[List[A]] =
...
def option[A](xs: Option[WithGlobals[A]]): WithGlobals[Option[A]] =
...
} 31