Skip to content

Import the Node.js with jsdom env from the Scala.js core repository. #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Jun 27, 2017

Conversation

sjrd
Copy link
Member

@sjrd sjrd commented Jun 23, 2017

This is the initial import of the Node.js with jsdom env from the Scala.js core repository. The history of this commit reflects the entire history of relevant files from the core repo, filter-branch'ed to appear as if they had always been in this repo. This commit adds the specific setup of the build and tests.

The history was obtained in a way similar to scala-js/scala-js-env-phantomjs#1. We started from commit scala-js/scala-js@d25fa8b of the core repo.

First, we identified all the paths where relevant files have lived in the past, through renamings along their history. This is the list:

js-envs/src/main/scala/org/scalajs/jsenv/nodejs/JSDOMNodeJSEnv.scala
js-envs/src/main/scala/org/scalajs/jsenv/jsdomnodejs/JSDOMNodeJSEnv.scala
jsdom-nodejs-env/src/main/scala/org/scalajs/jsenv/jsdomnodejs/JSDOMNodeJSEnv.scala

js-envs-test-suite/src/test/scala/org/scalajs/jsenv/test/JSDOMNodeJSEnvTest.scala
jsdom-nodejs-env/src/test/scala/org/scalajs/jsenv/jsdomnodejs/JSDOMNodeJSEnvTest.scala

sbt-plugin-test/withDOM/*

Based on that, we filter-branch'ed to keep only those files, using the following incantation, inspired by http://stackoverflow.com/a/6006679/1829647:

git filter-branch \
    --prune-empty \
    --index-filter '
  git ls-tree -z -r --name-only --full-tree $GIT_COMMIT \
    | grep -z -v "^js-envs/src/main/scala/org/scalajs/jsenv/nodejs/JSDOMNodeJSEnv.scala$" \
    | grep -z -v "^js-envs/src/main/scala/org/scalajs/jsenv/jsdomnodejs/JSDOMNodeJSEnv.scala$" \
    | grep -z -v "^jsdom-nodejs-env/src/main/scala/org/scalajs/jsenv/jsdomnodejs/JSDOMNodeJSEnv.scala$" \
    | grep -z -v "^js-envs-test-suite/src/test/scala/org/scalajs/jsenv/test/JSDOMNodeJSEnvTest.scala$" \
    | grep -z -v "^jsdom-nodejs-env/src/test/scala/org/scalajs/jsenv/jsdomnodejs/JSDOMNodeJSEnvTest.scala$" \
    | grep -z -v "^sbt-plugin-test/withDOM/" \
    | xargs -0 -r git rm -r --cached
  ' HEAD

That gave the result visible in https://github.com/sjrd/scala-js-env-jsdom-nodejs/tree/import-from-core-step1. Unfortunately, --prune-empty does not prune empty merge commits. We fixed that using the solution found in http://stackoverflow.com/a/38420284/1829647:

git filter-branch --prune-empty --parent-filter 'sed "s/-p //g" | xargs -r git show-branch --independent | sed "s/\</-p /g"'

giving https://github.com/sjrd/scala-js-env-jsdom-nodejs/tree/import-from-core-step2

Now, we had a clean history, except that it was orphaned wrt. the Initial commit of this repository, which is ed359fb. To have a nice PR with a history that appears to have come from the Initial commit, we reattached the first meaningful commit to the Initial commit using:

git filter-branch --parent-filter 'sed "s/ca1d58a31e27756c0d07fd65fbfdb1a3e0c6642e/ed359fb806fe202dbdf114f0063a4b66a9bc4e8f/"'

which yielded https://github.com/sjrd/scala-js-env-jsdom-nodejs/tree/import-from-core-step3.

Almost there, except that now the files from the Initial commit have been removed in the first meaningful commit of the filter-branch. We restored them using:

git filter-branch --index-filter 'git reset ed359fb806fe202dbdf114f0063a4b66a9bc4e8f -- .gitignore LICENSE README.md'

giving the history in https://github.com/sjrd/scala-js-env-jsdom-nodejs/tree/import-from-core-step4.

As a final polish, we rewrite, in commit messages, references to tickets of the form #123 to scala-js/scala-js#123, so that they point to issues in the scala-js/scala-js repository. This is done using the following incantation:

git filter-branch --msg-filter 'sed -r -e "s/(#[0-9]+)/scala-js\/scala-js\1/g"'

and gives the result in https://github.com/sjrd/scala-js-env-jsdom-nodejs/tree/import-from-core-step5.

This PR is one commit on top of that final step.

gzm0 and others added 19 commits May 7, 2014 11:13
Its elements are moved to different namespaces as follows:

Scala.js Test Suite    => scala.scalajs.testsuite
Test Bridge            => scala.scalajs.testbridge
Jasmine Test Framework => org.scalajs.jasminetest

Also, the RhinoJSEnv is updated to undefine LiveConnect classes after
including env.rhino.js. No research on why this helps has been
performed (but it does help).
This removes the annoying dependency (sic!) of the `JSEnv` API on
`ResolvedJSDependency`. This was the only part of `tools.jsdep`
that was used in the `JSEnv` API, so it decouples those.

This will be very important as we separate `jsDependencies` in a
separate plugin, as the `tools.jsdep` package should go with that,
out of the core.
This turns withDOM into a test for DOM support only, independent
of `jsDependencies`.
They all standardize on `executable`, `args` en `env`, which are
the names used by the `Initialize` constructors in `ScalaJSPlugin`.
Conflicts:

* js-envs/src/main/scala/org/scalajs/jsenv/nodejs/NodeJSEnv.scala
  Simple unrelated changes that happened to be in neighboring lines.
* sbt-plugin/src/main/scala/org/scalajs/sbtplugin/ScalaJSPluginInternal.scala
  0.6.x uses `new NodeJSEnv()` instead of `NodeJSEnv().value`.
  master was already using it but had other changes.
  Keep master.
…SEnv API.

`JSEnv#jsRunner` and friends `asyncRunner` and `comRunner` now
only take a `Seq[VirtualJSFiles]`, containing all JS files to be
given to the JS environment.

The JS environments therefore make no distinction between "library"
files and the "code" file. The disinction was arbitrary anyway,
and unifying them makes sure that all the JS files are first-class.
In particular, it forced to solve shortcomings in terms of error
handling in `JSDOMNodeJSEnv`.
While still retaining compatibility with jsdom v9.
Only trivial merge conflicts.

Additionally, the partest `run/t1430` and `run/t4729` are moved
to the blacklist in 2.12.2 and 2.13.0-M1. This brings those two
versions up to par with 2.12.0 and 2.12.1, for which they had been
blacklisted in 497e46351ae264e8b5ce8ee650515971733f9ec7.
In addition to recognizing objects extending `js.JSApp`, the sbt
plugin now recognizes "standard" main methods as well, i.e.,
objects with a method of the form

    def main(args: Array[String]): Unit = ...

If such an object is used as main class, its main method is called
using the new `ModuleInitializer.mainMethodWithArgs`.

This has the nice benefit that we can finally write a
cross-platform main object.

We "softly" deprecate `js.JSApp`: its documentation says not to
use anymore, but it does not cause a deprecation warning yet.

For backward compatibility, objects extending `js.JSApp` are
still recognized, and their `main(): Unit` method will be called.

There are some subtle scenarios regarding backward compatibility:

* If an object *both* extends `js.JSApp` and has a standard main
  method, the `main()` method of `js.JSApp` is preferred, for
  backward compatibility.
* If an object has a `main(): Unit` method but does not extend
  `js.JSApp`, it will not be *discovered*. In that case, we assume
  the old style and call `main()`. This can happen if the user
  explicitly sets the `mainClass` setting.
* If an object has *both* a `main(): Unit` method and a
  `main(args: Array[String]): Unit` method, it *will* now be
  discovered, and the new style will be assumed. This can
  potentially break compatibility, as now the standard main will
  be called. This only happens in case the user has explicitly set
  `mainClass`. Moreover, it is only problematic if `main()` does
  not behave the same as `main(Array())`, in which case the
  codebase is arguably in a bad shape to begin with.
* The very fact of recognizing *more* objects as potential main
  objects means that the sbt build can break because it cannot
  automatically choose between several discovered objects. This
  will however fail to link with a nice error message, so it is
  not too bad.

Here are some examples.

* Old-style only, `main()` is selected

    object OldStyleOnly extends js.JSApp {
      def main(): Unit = ...
    }

* New-style only, `main(Array[String])` is selected

    object NewStyleOnly {
      def main(args: Array[String]): Unit = ...
    }

* Old and new style combined, `main()` is selected

    object OldAndNewStyle extends js.JSApp {
      def main(): Unit = ...
      def main(args: Array[String]): Unit = ...
    }

* `def main(): Unit` without `js.JSApp` only, `main()` is selected

    object OldStyleNonJSApp {
      def main(): Unit = ...
    }

* Both styles of methods without `js.JSApp`, `main(Array[String])`
  is selected (potentially silently breaking)

    object OldAndNewStyleNonJSApp {
      def main(): Unit = ...
      def main(args: Array[String]): Unit = ...
    }

* Both styles exist in two different objects, sbt reports an
  ambiguity and demands that `mainClass` be set explicitly

    object OldStyle extends js.JSApp {
      def main(): Unit = ...
    }
    object NewStyle {
      def main(args: Array[String]): Unit = ...
    }
This only changes the surface API of concrete JS envs. Their
existing constructors are deprecated in favor of an overload with
a `Config` object.

This change provides in the 0.6.x series an API that can be used
in a source-compatible way between 0.6.x and 1.x. In 1.x, deeper
changes to the internal API of JS envs will be done.

We also take this opportunity to "move" `JSDOMNodeJSEnv` in a
different package `org.scalajs.jsenv.jsdomnodejs`. Since this JS
env is scheduled to be moved in a different repository in 1.x, it
should eventually be in a different package anyway.
Introduce a new surface API for JS envs with `Config` objects.
In the process, the implementation of
`org.scalajs.jsenv.nodejs.JSDOMNodeJSEnv` is transferred to the
new `org.scalajs.jsenv.jsdomnodejs.JSDOMNodeJSEnv`.
…mpat evolution.

The internal configuration of (abstract) classes in the JS env
API is now `protected def`-based, rather than based on constructor
parameters.

This can be evolved in binary-compatible ways, as we can add new
`protected def`s with default implementations in the superclasses.
So that we can move it to a different repository afterwards.

In the process, we also move the standard `NodeJSEnv` in a
dedicated project, although this one will obviously stay in the
same repository. Now that all JS environments are in different
artifacts, it makes sense that Node.js have its own artifact as
well, even though the sbt plugin will depend on that artifact.
The separation has a nice benefit that the `jsEnvsTestSuite` is
not necessary anymore, since its last tests can be moved to the
test directories of the relevant JS env implementations.
@sjrd sjrd requested a review from gzm0 June 23, 2017 14:40
@sjrd sjrd force-pushed the import-from-core branch from 19733fb to 4a6d902 Compare June 23, 2017 15:19
This is the initial import of the Node.js with jsdom env from the
Scala.js core repository. The history of this commit reflects the
entire history of relevant files from the core repo,
filter-branch'ed to appear as if they had always been in this repo.
This commit adds the specific setup of the build and tests.
@gzm0 gzm0 merged commit 58b3784 into scala-js:master Jun 27, 2017
@sjrd sjrd deleted the import-from-core branch June 27, 2017 09:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants