These are chat archives for chandu0101/scalajs-react-components

12th
Jun 2017
nafg
@nafg
Jun 12 2017 01:43
Which macro is this?
How long does each invocation take and how many times is it invoked?
Roberto Leibman
@rleibman
Jun 12 2017 14:24
It's the JSMacro, it gets invoked, as much as I can tell, once for every Component. Clone my project and run fastOptJS::webpack
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 17:27
oh well, if its that slow we will figure out why that is
because it really shouldnt be
an youre right in that its called once for each component
i have a draft of how we can do the callback function rewrites that the macro does using type classes instead now
that could be a nice alternative
Roberto Leibman
@rleibman
Jun 12 2017 17:59
I'd love to get that in.
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 18:36
so combined with the trait props encoding we could avoid having a macro at all
nafg
@nafg
Jun 12 2017 18:37
@rleibman mind posting a link to the definition in github?
Roberto Leibman
@rleibman
Jun 12 2017 18:37
@nafg, what definition?
Roberto Leibman
@rleibman
Jun 12 2017 18:39
@oyvindberg I'm all for that, the macro does keep the generated code looking cleaner, but IMO the cost to the compile is too much. Now, I put in a println at the start and end of the macro code.. it looks like it take a long time between "end" and the next "start": the macro itself doesn't take that long to run. Though I hope removing the macro will make the compile faster, I'm not certain it will.
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 18:40
yeah, im not convinced its really as slow as you think
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 18:40
but i would rather not have it
this is what i experimented with last night:
  case class Callback[T](f: js.Function0[T])

  implicit def CallbackToJs[T, U](implicit ev: T ToJs U): Callback[T] ToJs js.Function0[U] =
    (from: Callback[T]) => () => ev(from.f())

  implicit def CallbackFromJs[T, U](implicit ev: T FromJs U): Callback[T] FromJs js.Function0[U] =
    (from: js.Function0[U]) => Callback(() => ev(from()))

  val f: Option[(String, Int, Set[Callback[Option[String]]]) => Callback[String]] =
    Option((str, i, cbs) => Callback(() => s"w00t: $str, $i, ${cbs.map(x => x.f())}"))

  val f_js: UndefOr[js.Function3[String, Int, js.Array[js.Function0[UndefOr[String]]], js.Function0[String]]] =
    ToJs(f)

  val f_roundtripped: Option[(String, Int, Array[Callback[Option[String]]]) => Callback[String]] =
    FromJs(ToJs(f))

  val f_manually_typed_roundtripped: Option[(String, Int, Set[Callback[Option[String]]]) => Callback[String]] =
    FromJs.specify(ToJs(f)).into[Option[(String, Int, Set[Callback[Option[String]]]) => Callback[String]]]
that is a typeclass based way of transforming functions and data structures back and forth
Roberto Leibman
@rleibman
Jun 12 2017 18:42
Doesn't look confusing at all ;)
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 18:42
haha yeah right
but it's a pretty thin, user expandable integration layer
nafg
@nafg
Jun 12 2017 18:44
How does usage look?
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 18:44
you see the usage there, but to explain
say you have a function in your app, with type Option[(String, Int, Set[Callback[Option[String]]]) => Callback[String]]
these are long types to see that stuff works
and you integrate with a js library that requires something like UndefOr[js.Function3[String, Int, js.Array[js.Function0[UndefOr[String]]], js.Function0[String]]]
usage is ToJs(f)
and then user or library can provide instances of ToJs and FromJs
Roberto Leibman
@rleibman
Jun 12 2017 18:46
ok, if I understand what you're saying that simplifies the class declaration, right? but what about the constructor?
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 18:47
no, well, it simplifies usage of javascript APIs from scala.js
say when we invent things like custom data structures, callback classes cough or things like that, and javascript libraries only deal with arrays and functions
this eases the integration
it is exactly the same as half the work done by that macro
Roberto Leibman
@rleibman
Jun 12 2017 18:49
I thought the macro was generating the constructor.
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 18:49
the macro 1) finds all props passed as parameter, and collects them into a javascript object which is fed into the react component, and 2) rewrites types in this manner to get rid of scala.js specific things
Roberto Leibman
@rleibman
Jun 12 2017 18:49
Or specifically, the props part of the constructor.
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 18:49
what im proposing is a pure scala alternative to 2)
Roberto Leibman
@rleibman
Jun 12 2017 18:50
ok, but all within the context of creating the props object, right?
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 18:50
and 1) im thinking we can replace by using @ScalajsDefined traits and overrides
yes
Roberto Leibman
@rleibman
Jun 12 2017 18:52
ok, so now you need to re-write com.olvind.printers.scala to use this alternative.
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 18:54
well yes, i thought to explore it at least
though just to have said that, i very much support still that we at least get the upgrade out of the way with minimal changes
Roberto Leibman
@rleibman
Jun 12 2017 18:56
Though the compile time seriously slows down our progress. Can you duplicate my results about compile time?
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 18:58
i tried to clone your repo, but the build didnt make it far enough for me to see if it was slow
Roberto Leibman
@rleibman
Jun 12 2017 19:23
Recently? it should compile gen, macro and core projects without a problem, it fails at demo, but you should notice the speed problem at core. You can try just compiling core (which depends on macro and gen). You will have to change the sbt file to point it to the location where you have your materialui and elemental code... that's another 'TODO': downloading the js base code.
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 19:41
oh nevermind, that was outdated, will try again
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 20:01
did you try to setup the gen project with bundler so it downloads the libraries we generate?
Roberto Leibman
@rleibman
Jun 12 2017 20:04
It uses bundler to do the last webpack of the demo (and that is a thing of beauty), but hadn't gotten around to figuring out how to get the libraries required for the generation (I was going to call out to the shell and do an npm install), but if bundler can do it that's super cool!
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 20:06
ill give it a quick shot and see if my sbt skills are up to the task
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 20:15
yey, it worked
Roberto Leibman
@rleibman
Jun 12 2017 20:17
Yay!
Using the same npmSettings and npmDevSettings I set for the demo project?
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 20:19
i split npmSettings in two so it only fetches the necessary files for gen, and then ignore the rest of the settings
yay by the way
im looking at a compile that must have been going on for ten minutes now
so i think you can consider that confirmation
Roberto Leibman
@rleibman
Jun 12 2017 20:22
Good! (I mean bad! but at least it's replicated, and that's the first step in fixing a bug)
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 20:29
hmm, no idea
i bumped scala.js and restarted sbt, and it went away
or have i broken everything, perhaps :D
Roberto Leibman
@rleibman
Jun 12 2017 20:36
I'm on 0.6.17
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 20:45
pff, i thought i had understood sbt again
Roberto Leibman
@rleibman
Jun 12 2017 20:49
That sometimes happens to me, don't worry, the feeling that you understand it goes away fairly quickly.
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 20:51
all i wanted was to DRY the resource generators
also, the semverfi dependency doesnt resolve for me
Roberto Leibman
@rleibman
Jun 12 2017 20:53
I have no idea why I'm using it for in this project, it's probably safe to remove. I actually need to find a permanent solution for that library... it's pretty much dead on github but I use it extensively and have made a few changes to it (including cross-compiling it)
I'm thinking of just forking it with a new group name so that I can deploy it to maven.
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 20:56
yeah, i would have done that
also there is another issue
which is what i was trying to solve there for a second
Roberto Leibman
@rleibman
Jun 12 2017 20:57
Anyway, I see where you're going with the bunder: the npmUpdate task downloads the npms, we can chain the generation to that and use the output.
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 20:57
yes exactly
but i think we need to separate things
because the way it is now, we generate the files into src_managed for gen after gen is compiled
i thought that would be easy to fix
Roberto Leibman
@rleibman
Jun 12 2017 20:58
I am confused about that too. I tried generating them for core (because that's where they belonged)
But was not immediately successful, so I gave up.
The generator should know how to generate files, the core should generate the files it needs using the generator.
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 21:05
it seems to work to move the resource generator tasks to core
bbl
Roberto Leibman
@rleibman
Jun 12 2017 21:07
Can you post your sbt to the point you got?
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 23:08
// *****************************************************************************
// Projects
// *****************************************************************************
lazy val macros =
  project
    .in(file("macros"))
    .enablePlugins(ScalaJSPlugin)
    .settings(commonSettings)
    .settings(
      name := "scalajs-react-components-macros",
      libraryDependencies ++= Seq(
        "com.github.japgolly.scalajs-react" %%% "core"      % "1.0.0" withSources (),
        "com.github.japgolly.scalajs-react" %%% "extra"     % "1.0.0" withSources (),
        "org.scalatest"                     %%% "scalatest" % "3.0.3" % Test
      )
    )

lazy val generateMui = TaskKey[Seq[File]]("generateMui")
lazy val MuiVersion  = "0.18.1"

lazy val generateEui = TaskKey[Seq[File]]("generateEui")
lazy val EuiVersion  = "0.6.1"

lazy val generateSui = TaskKey[Seq[File]]("generateSui")
lazy val SuiVersion  = "0.68.5"

lazy val gen =
  project
    .in(file("gen"))
    .enablePlugins(ScalaJSBundlerPlugin)
    .settings(commonSettings, preventPublication, npmGenSettings)
    .settings(
      organization := "com.olvind",
      name := "generator",
      libraryDependencies ++= Seq(
        "com.lihaoyi"   %% "ammonite-ops" % "0.9.5",
        "org.scalatest" %% "scalatest"    % "3.0.3" % Test
      )
    )

lazy val core =
  project
    .in(file("core"))
    .dependsOn(macros, gen)
    .enablePlugins(ScalaJSPlugin)
    .settings(commonSettings)
    .settings(
      generateEui := {
        val res = runner.value.run(
          "com.olvind.eui.EuiRunner",
          (fullClasspath in (gen, Runtime)).value.files,
          List(
            (npmUpdate in (gen, Compile)).value / "node_modules" / "elemental",
            sourceManaged.value
          ) map (_.absolutePath),
          streams.value.log
        )

        val pathFinder: PathFinder = sourceManaged.value ** "*.scala"
        pathFinder.get.filter(_.getAbsolutePath.contains("elemental"))
      },
      generateMui := {
        val res = runner.value.run(
          "com.olvind.mui.MuiRunner",
          (fullClasspath in (gen, Runtime)).value.files,
          List(
            (npmUpdate in (gen, Compile)).value / "node_modules" / "material-ui",
            sourceManaged.value
          ) map (_.absolutePath),
          streams.value.log
        )
        val pathFinder: PathFinder = sourceManaged.value ** "*.scala"
        pathFinder.get.filter(_.getAbsolutePath.contains("material"))
      },
      generateSui := {
        val res = runner.value.run(
          "com.olvind.sui.SuiRunner",
          (fullClasspath in (gen, Runtime)).value.files,
          List(
            (npmUpdate in (gen, Compile)).value / "node_modules" / "semantic-ui-react" / "dist" / "commonjs",
            sourceManaged.value
          ) map (_.absolutePath),
          streams.value.log
        )
        val pathFinder: PathFinder = sourceManaged.value ** "*.scala"
        pathFinder.get.filter(_.getAbsolutePath.contains("semanticui"))
      }
    )
    .settings(
      sourceGenerators in Compile += generateMui,
      sourceGenerators in Compile += generateEui,
//      sourceGenerators in Compile += generateSui,
      libraryDependencies ++= Seq(
        "com.lihaoyi"                       %%% "upickle"     % "0.4.4" withSources (),
        "com.github.japgolly.scalajs-react" %%% "core"        % "1.0.0" withSources (),
        "com.github.japgolly.scalajs-react" %%% "extra"       % "1.0.0" withSources (),
        "com.github.japgolly.scalacss"      %%% "core"        % "0.5.3" withSources (),
        "com.github.japgolly.scalacss"      %%% "ext-react"   % "0.5.3" withSources (),
        "org.scala-js"                      %%% "scalajs-dom" % "0.9.2" withSources (),
        "org.scalacheck"                    %%% "scalacheck"  % "1.13.5" % Test,
        "org.scalatest"                     %%% "scalatest"   % "3.0.3" % Test
      )
    )

val jsDir = "demo/assets"

lazy val preventPublication = Seq(publishArtifact := false, publish := (), packagedArtifacts := Map.empty) // doesn't work - https:
Roberto Leibman
@rleibman
Jun 12 2017 23:08
Thanks!
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 23:22
that doesnt mkdir /core/target/scala-2.12/src_managed by the way, i should have warned you
also i do believe all those scalac flags you added are at least part of the reason why compiling is slow. i just commented them out, and compiled core in 70 seconds
Øyvind Raddum Berg
@oyvindberg
Jun 12 2017 23:59
err, i dont know any longer. now nothing compiles at all! ive never seen sbt/scala misbehave like this before