Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #39 from scalacenter/jsdom-support
#38 Add support for jsdom
- Loading branch information
Showing
10 changed files
with
309 additions
and
30 deletions.
There are no files selected for viewing
9 changes: 9 additions & 0 deletions
9
sbt-scalajs-bundler/src/main/scala/org/scalajs/sbtplugin/FrameworkDetectorWrapper.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package org.scalajs.sbtplugin | ||
|
||
import org.scalajs.core.tools.linker.backend.ModuleKind | ||
import org.scalajs.jsenv.JSEnv | ||
|
||
// HACK Because FrameworkDetector is private | ||
class FrameworkDetectorWrapper(jsEnv: JSEnv, moduleKind: ModuleKind, moduleIdentifier: Option[String]) { | ||
val wrapped = new FrameworkDetector(jsEnv, moduleKind, moduleIdentifier) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
107 changes: 107 additions & 0 deletions
107
sbt-scalajs-bundler/src/main/scala/scalajsbundler/JSDOMNodeJSEnv.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
package scalajsbundler | ||
|
||
import java.io.OutputStream | ||
|
||
import org.scalajs.core.tools.io.{FileVirtualFile, FileVirtualJSFile, VirtualJSFile} | ||
import org.scalajs.core.tools.jsdep.ResolvedJSDependency | ||
import org.scalajs.jsenv.{AsyncJSRunner, ComJSRunner, JSRunner} | ||
import org.scalajs.core.ir.Utils.escapeJS | ||
import org.scalajs.jsenv.nodejs.AbstractNodeJSEnv | ||
import sbt._ | ||
|
||
// HACK Copy of Scala.js’ JSDOMNodeJSEnv. The only change is the ability to pass the directory in which jsdom has been installed | ||
class JSDOMNodeJSEnv( | ||
jsDomDirectory: File, | ||
nodejsPath: String = "node", | ||
addArgs: Seq[String] = Seq.empty, | ||
addEnv: Map[String, String] = Map.empty | ||
) extends AbstractNodeJSEnv(nodejsPath, addArgs, addEnv, sourceMap = false) { | ||
|
||
protected def vmName: String = "Node.js with JSDOM" | ||
|
||
override def jsRunner(libs: Seq[ResolvedJSDependency], | ||
code: VirtualJSFile): JSRunner = { | ||
new DOMNodeRunner(libs, code) | ||
} | ||
|
||
override def asyncRunner(libs: Seq[ResolvedJSDependency], | ||
code: VirtualJSFile): AsyncJSRunner = { | ||
new AsyncDOMNodeRunner(libs, code) | ||
} | ||
|
||
override def comRunner(libs: Seq[ResolvedJSDependency], | ||
code: VirtualJSFile): ComJSRunner = { | ||
new ComDOMNodeRunner(libs, code) | ||
} | ||
|
||
protected class DOMNodeRunner(libs: Seq[ResolvedJSDependency], code: VirtualJSFile) | ||
extends ExtRunner(libs, code) with AbstractDOMNodeRunner | ||
|
||
protected class AsyncDOMNodeRunner(libs: Seq[ResolvedJSDependency], code: VirtualJSFile) | ||
extends AsyncExtRunner(libs, code) with AbstractDOMNodeRunner | ||
|
||
protected class ComDOMNodeRunner(libs: Seq[ResolvedJSDependency], code: VirtualJSFile) | ||
extends AsyncDOMNodeRunner(libs, code) with NodeComJSRunner | ||
|
||
protected trait AbstractDOMNodeRunner extends AbstractNodeRunner { | ||
|
||
protected def codeWithJSDOMContext(): Seq[VirtualJSFile] = { | ||
val scriptsJSPaths = getLibJSFiles().map { | ||
case file: FileVirtualFile => file.path | ||
case file => libCache.materialize(file).getAbsolutePath | ||
} | ||
val scriptsStringPath = scriptsJSPaths.map('"' + escapeJS(_) + '"') | ||
val jsDOMCode = { | ||
s""" | ||
|(function () { | ||
| const jsdom = require("jsdom"); | ||
| var windowKeys = []; | ||
| | ||
| jsdom.env({ | ||
| html: "", | ||
| virtualConsole: jsdom.createVirtualConsole().sendTo(console), | ||
| created: function (error, window) { | ||
| if (error == null) { | ||
| window["__ScalaJSEnv"] = __ScalaJSEnv; | ||
| window["scalajsCom"] = global.scalajsCom; | ||
| windowKeys = Object.keys(window); | ||
| } else { | ||
| console.log(error); | ||
| } | ||
| }, | ||
| scripts: [${scriptsStringPath.mkString(", ")}], | ||
| onload: function (window) { | ||
| for (var k in window) { | ||
| if (windowKeys.indexOf(k) == -1) | ||
| global[k] = window[k]; | ||
| } | ||
| | ||
| ${code.content} | ||
| } | ||
| }); | ||
|})(); | ||
|""".stripMargin | ||
} | ||
val codeFile = jsDomDirectory / "codeWithJSDOMContext.js" | ||
IO.write(codeFile, jsDOMCode) | ||
Seq(FileVirtualJSFile(codeFile)) | ||
} | ||
|
||
override protected def getJSFiles(): Seq[VirtualJSFile] = | ||
initFiles() ++ customInitFiles() ++ codeWithJSDOMContext() | ||
|
||
/** Libraries are loaded via scripts in Node.js */ | ||
override protected def getLibJSFiles(): Seq[VirtualJSFile] = | ||
libs.map(_.lib) | ||
|
||
// Send code to Stdin | ||
override protected def sendVMStdin(out: OutputStream): Unit = { | ||
/* Do not factor this method out into AbstractNodeRunner or when mixin in | ||
* the traits it would use AbstractExtRunner.sendVMStdin due to | ||
* linearization order. | ||
*/ | ||
sendJS(getJSFiles(), out) | ||
} | ||
} | ||
|
||
} |
30 changes: 30 additions & 0 deletions
30
sbt-scalajs-bundler/src/main/scala/scalajsbundler/JsDomTestEntries.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package scalajsbundler | ||
|
||
import sbt._ | ||
import JS.syntax._ | ||
|
||
object JsDomTestEntries { | ||
|
||
/** | ||
* Loads the output of Scala.js and exports all its exported properties to the global namespace, | ||
* so that they are found by jsdom. | ||
* @param sjsOutput Scala.js output | ||
* @param loaderFile File to write the loader to | ||
*/ | ||
def writeLoader(sjsOutput: File, loaderFile: File): Unit = { | ||
val window = JS.ref("window") | ||
val require = JS.ref("require") | ||
val Object = JS.ref("Object") | ||
val loader = | ||
JS.let( | ||
require.apply(JS.str(sjsOutput.absolutePath)) | ||
) { tests => | ||
((Object `.` "keys").apply(tests) `.` "forEach").apply(JS.fun { key => | ||
window.bracket(key) := tests.bracket(key) // Export all properties of the Scala.js module to the global namespace | ||
}) | ||
} | ||
|
||
IO.write(loaderFile, loader.show) | ||
} | ||
|
||
} |
21 changes: 21 additions & 0 deletions
21
sbt-scalajs-bundler/src/main/scala/scalajsbundler/Npm.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package scalajsbundler | ||
|
||
import sbt._ | ||
|
||
object Npm { | ||
|
||
/** | ||
* Runs the `npm` command | ||
* @param args Command arguments | ||
* @param workingDir Working directory of the process | ||
* @param logger Logger | ||
*/ | ||
def run(args: String*)(workingDir: File, logger: Logger): Unit = | ||
Commands.run((npm +: args).mkString(" "), workingDir, logger) | ||
|
||
private val npm = sys.props("os.name").toLowerCase match { | ||
case os if os.contains("win") ⇒ "cmd /c npm" | ||
case _ ⇒ "npm" | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.