Skip to content

Commit b2a207d

Browse files
authored
Merge pull request #1 from sjrd/import-from-core
Import the PhantomJS env from the Scala.js core repository.
2 parents 51c45de + 686d8a3 commit b2a207d

File tree

18 files changed

+1398
-0
lines changed

18 files changed

+1398
-0
lines changed

.travis.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
sudo: false
2+
language: scala
3+
scala:
4+
- 2.10.6
5+
- 2.11.11
6+
- 2.12.2
7+
jdk:
8+
- oraclejdk8
9+
install:
10+
- if [[ "${TRAVIS_SCALA_VERSION}" == "2.10.6" ]]; then TEST_SBT_PLUGIN=true; else TEST_SBT_PLUGIN=false; fi
11+
# The default ivy resolution takes way too much time, and times out Travis builds.
12+
# We use coursier instead.
13+
- mkdir -p $HOME/.sbt/0.13/plugins/
14+
- echo 'addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC3")' > $HOME/.sbt/0.13/plugins/coursier.sbt
15+
# While there is no published version of Scala.js 1.x, we have to locally build a snapshot.
16+
- git clone https://github.com/scala-js/scala-js.git
17+
- cd scala-js
18+
- git checkout f21e7f5ea652fe4a186f1ecd8c0070fbb80edc80
19+
- sbt ++$TRAVIS_SCALA_VERSION ir/publishLocal tools/publishLocal jsEnvs/publishLocal jsEnvsTestKit/publishLocal
20+
- |
21+
if [[ "${TEST_SBT_PLUGIN}" == "true" ]]; then
22+
sbt ++$TRAVIS_SCALA_VERSION testAdapter/publishLocal sbtPlugin/publishLocal &&
23+
sbt ++2.11.11 compiler/publishLocal library/publishLocal testInterface/publishLocal
24+
fi
25+
- cd ..
26+
script:
27+
- sbt ++$TRAVIS_SCALA_VERSION scalajs-phantomjs-env/test scalajs-phantomjs-env/doc
28+
- |
29+
if [[ "${TEST_SBT_PLUGIN}" == "true" ]]; then
30+
sbt scalajs-phantomjs-env/publishLocal sbt-scalajs-env-phantomjs/publishLocal && \
31+
cd sbt-plugin-test && \
32+
sbt jetty9/run && \
33+
cd ..
34+
fi
35+
cache:
36+
directories:
37+
- $HOME/.ivy2/cache
38+
- $HOME/.sbt
39+
- $HOME/.coursier/cache
40+
before_cache:
41+
- find $HOME/.ivy2/cache -name "ivydata-*.properties" -print -delete
42+
- find $HOME/.sbt -name "*.lock" -print -delete
43+
- rm $HOME/.sbt/0.13/plugins/coursier.sbt

build.sbt

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
val scalaJSVersion = "1.0.0-SNAPSHOT"
2+
3+
inThisBuild(Seq(
4+
version := "0.1.0-SNAPSHOT",
5+
organization := "org.scala-js",
6+
7+
crossScalaVersions := Seq("2.10.6", "2.11.11", "2.12.2"),
8+
scalaVersion := "2.10.6",
9+
scalacOptions ++= Seq("-deprecation", "-feature", "-Xfatal-warnings"),
10+
11+
homepage := Some(url("https://www.scala-js.org/")),
12+
licenses += ("BSD New",
13+
url("https://github.com/scala-js/scala-js-env-phantomjs/blob/master/LICENSE")),
14+
scmInfo := Some(ScmInfo(
15+
url("https://github.com/scala-js/scala-js-env-phantomjs"),
16+
"scm:git:git@github.com:scala-js/scala-js-env-phantomjs.git",
17+
Some("scm:git:git@github.com:scala-js/scala-js-env-phantomjs.git")))
18+
))
19+
20+
val commonSettings = Def.settings(
21+
// Scaladoc linking
22+
apiURL := {
23+
val name = moduleName.value
24+
val v = version.value
25+
Some(url(s"https://www.scala-js.org/api/$name/$v/"))
26+
},
27+
autoAPIMappings := true,
28+
29+
publishMavenStyle := true,
30+
publishTo := {
31+
val nexus = "https://oss.sonatype.org/"
32+
if (isSnapshot.value)
33+
Some("snapshots" at nexus + "content/repositories/snapshots")
34+
else
35+
Some("releases" at nexus + "service/local/staging/deploy/maven2")
36+
},
37+
pomExtra := (
38+
<developers>
39+
<developer>
40+
<id>sjrd</id>
41+
<name>Sébastien Doeraene</name>
42+
<url>https://github.com/sjrd/</url>
43+
</developer>
44+
<developer>
45+
<id>gzm0</id>
46+
<name>Tobias Schlatter</name>
47+
<url>https://github.com/gzm0/</url>
48+
</developer>
49+
<developer>
50+
<id>nicolasstucki</id>
51+
<name>Nicolas Stucki</name>
52+
<url>https://github.com/nicolasstucki/</url>
53+
</developer>
54+
</developers>
55+
),
56+
pomIncludeRepository := { _ => false }
57+
)
58+
59+
lazy val root: Project = project.in(file(".")).
60+
settings(
61+
publishArtifact in Compile := false,
62+
publish := {},
63+
publishLocal := {},
64+
65+
clean := clean.dependsOn(
66+
clean in `scalajs-phantomjs-env`,
67+
clean in `sbt-scalajs-env-phantomjs`
68+
).value
69+
)
70+
71+
lazy val `scalajs-phantomjs-env`: Project = project.in(file("phantomjs-env")).
72+
settings(
73+
commonSettings,
74+
75+
libraryDependencies ++= Seq(
76+
"org.scala-js" %% "scalajs-js-envs" % scalaJSVersion,
77+
"org.eclipse.jetty" % "jetty-websocket" % "8.1.16.v20140903" % "provided",
78+
"org.eclipse.jetty" % "jetty-server" % "8.1.16.v20140903" % "provided",
79+
80+
"com.novocode" % "junit-interface" % "0.11" % "test",
81+
"org.scala-js" %% "scalajs-js-envs-test-kit" % scalaJSVersion % "test"
82+
)
83+
)
84+
85+
lazy val `sbt-scalajs-env-phantomjs`: Project = project.in(file("phantomjs-sbt-plugin")).
86+
settings(
87+
commonSettings,
88+
89+
sbtPlugin := true,
90+
scalaBinaryVersion :=
91+
CrossVersion.binaryScalaVersion(scalaVersion.value),
92+
93+
addSbtPlugin("org.scala-js" % "sbt-scalajs" % scalaJSVersion),
94+
95+
// Add API mappings for sbt (seems they don't export their API URL)
96+
apiMappings ++= {
97+
val deps = (externalDependencyClasspath in Compile).value
98+
val sbtJars = deps filter { attributed =>
99+
val p = attributed.data.getPath
100+
p.contains("/org.scala-sbt/") && p.endsWith(".jar")
101+
}
102+
val docUrl =
103+
url(s"http://www.scala-sbt.org/${sbtVersion.value}/api/")
104+
sbtJars.map(_.data -> docUrl).toMap
105+
}
106+
).
107+
dependsOn(`scalajs-phantomjs-env`)
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/* __ *\
2+
** ________ ___ / / ___ __ ____ PhantomJS support for Scala.js **
3+
** / __/ __// _ | / / / _ | __ / // __/ (c) 2013-2017, LAMP/EPFL **
4+
** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ https://www.scala-js.org/ **
5+
** /____/\___/_/ |_/____/_/ | |__/ /____/ **
6+
** |/____/ **
7+
\* */
8+
9+
package org.scalajs.jsenv.phantomjs
10+
11+
import javax.servlet.http.HttpServletRequest
12+
13+
import org.eclipse.jetty.server.Server
14+
import org.eclipse.jetty.server.nio.SelectChannelConnector
15+
import org.eclipse.jetty.websocket.{WebSocket, WebSocketHandler}
16+
import org.eclipse.jetty.util.component.{LifeCycle, AbstractLifeCycle}
17+
import org.eclipse.jetty.util.log
18+
19+
private[phantomjs] final class JettyWebsocketManager(
20+
wsListener: WebsocketListener) extends WebsocketManager { thisMgr =>
21+
22+
private[this] var webSocketConn: WebSocket.Connection = null
23+
private[this] var closed = false
24+
25+
// We can just set the logger here, since we are supposed to be protected by
26+
// the private ClassLoader that loads us reflectively.
27+
log.Log.setLog(new WSLogger("root"))
28+
29+
private[this] val connector = new SelectChannelConnector
30+
31+
connector.setHost("localhost")
32+
connector.setPort(0)
33+
34+
private[this] val server = new Server()
35+
36+
server.addConnector(connector)
37+
server.setHandler(new WebSocketHandler {
38+
// Support Hixie 76 for Phantom.js
39+
getWebSocketFactory().setMinVersion(-1)
40+
41+
override def doWebSocketConnect(
42+
request: HttpServletRequest, protocol: String): WebSocket =
43+
new ComWebSocketListener
44+
})
45+
46+
server.addLifeCycleListener(new AbstractLifeCycle.AbstractLifeCycleListener {
47+
override def lifeCycleStarted(event: LifeCycle): Unit = {
48+
if (event.isRunning())
49+
wsListener.onRunning()
50+
}
51+
})
52+
53+
private class ComWebSocketListener extends WebSocket.OnTextMessage {
54+
override def onOpen(connection: WebSocket.Connection): Unit = {
55+
thisMgr.synchronized {
56+
if (isConnected)
57+
throw new IllegalStateException("Client connected twice")
58+
connection.setMaxIdleTime(Int.MaxValue)
59+
webSocketConn = connection
60+
}
61+
wsListener.onOpen()
62+
}
63+
64+
override def onClose(statusCode: Int, reason: String): Unit = {
65+
thisMgr.synchronized {
66+
webSocketConn = null
67+
closed = true
68+
}
69+
wsListener.onClose()
70+
server.stop()
71+
72+
if (statusCode != 1000) {
73+
throw new Exception("Abnormal closing of connection. " +
74+
s"Code: $statusCode, Reason: $reason")
75+
}
76+
}
77+
78+
override def onMessage(message: String): Unit =
79+
wsListener.onMessage(message)
80+
}
81+
82+
private class WSLogger(fullName: String) extends log.AbstractLogger {
83+
private[this] var debugEnabled = false
84+
85+
def debug(msg: String, args: Object*): Unit =
86+
if (debugEnabled) log("DEBUG", msg, args)
87+
88+
def debug(msg: String, thrown: Throwable): Unit =
89+
if (debugEnabled) log("DEBUG", msg, thrown)
90+
91+
def debug(thrown: Throwable): Unit =
92+
if (debugEnabled) log("DEBUG", thrown)
93+
94+
def getName(): String = fullName
95+
96+
def ignore(ignored: Throwable): Unit = ()
97+
98+
def info(msg: String, args: Object*): Unit = log("INFO", msg, args)
99+
def info(msg: String, thrown: Throwable): Unit = log("INFO", msg, thrown)
100+
def info(thrown: Throwable): Unit = log("INFO", thrown)
101+
102+
def warn(msg: String, args: Object*): Unit = log("WARN", msg, args)
103+
def warn(msg: String, thrown: Throwable): Unit = log("WARN", msg, thrown)
104+
def warn(thrown: Throwable): Unit = log("WARN", thrown)
105+
106+
def isDebugEnabled(): Boolean = debugEnabled
107+
def setDebugEnabled(enabled: Boolean): Unit = debugEnabled = enabled
108+
109+
private def log(lvl: String, msg: String, args: Object*): Unit =
110+
wsListener.log(s"$lvl: $msg " + args.mkString(", "))
111+
112+
private def log(lvl: String, msg: String, thrown: Throwable): Unit =
113+
wsListener.log(s"$lvl: $msg $thrown\n{$thrown.getStackStrace}")
114+
115+
private def log(lvl: String, thrown: Throwable): Unit =
116+
wsListener.log(s"$lvl: $thrown\n{$thrown.getStackStrace}")
117+
118+
protected def newLogger(fullName: String) = new WSLogger(fullName)
119+
}
120+
121+
def start(): Unit = server.start()
122+
123+
def stop(): Unit = server.stop()
124+
125+
def isConnected: Boolean = webSocketConn != null && !closed
126+
def isClosed: Boolean = closed
127+
128+
def localPort: Int = connector.getLocalPort()
129+
130+
def sendMessage(msg: String): Unit = synchronized {
131+
if (webSocketConn != null)
132+
webSocketConn.sendMessage(msg)
133+
}
134+
135+
}

0 commit comments

Comments
 (0)