ScalaJS fullLinkJS 错误

ScalaJS fullLinkJS errors

几周前,我将我的 Play+ScalaJS 项目从 ScalaJS 0.6.32 升级到了 1.4.0。一切都在开发中运行良好。今天我尝试部署它,因此第一次执行了 fullLinkJS。它产生了一些错误:

sbt:browser> fullLinkJS
[info] Full optimizing /Users/bwbecker/oat/src/oat3/_browser/target/scala-2.12/browser-opt
[error] c91662c1ae832d6a8493/oat/browser/views/bulkmail/BMailCreateView.scala(125:43:Apply): scala.Dynamic expected but any found for tree of type org.scalajs.ir.Trees$JSSelect
[error] c91662c1ae832d6a8493/oat/browser/views/components/filteredTable/FilteredBMailTable.scala(81:53:Apply): scala.Dynamic expected but any found for tree of type org.scalajs.ir.Trees$JSSelect
[error] c91662c1ae832d6a8493/oat/browser/models/Autocomplete.scala(156:18:Apply): scala.Dynamic expected but any found for tree of type org.scalajs.ir.Trees$JSSelect
[error] c91662c1ae832d6a8493/oat/browser/views/virtualq/QueueAddEditView.scala(90:52:Apply): scala.Dynamic expected but any found for tree of type org.scalajs.ir.Trees$JSSelect
[error] c91662c1ae832d6a8493/oat/browser/views/bulkmail/edit/BMailSendView.scala(273:62:Apply): scala.Dynamic expected but any found for tree of type org.scalajs.ir.Trees$JSSelect
[error] c91662c1ae832d6a8493/oat/browser/views/bulkmail/TemplateListView.scala(42:64:Apply): scala.Dynamic expected but any found for tree of type org.scalajs.ir.Trees$JSSelect
...

我已经查看了源代码中大约一打引用行。他们中的大多数指的是 Play 路由或调用 url 方法。其余的涉及调用 jQuery.

该项目有一个跨平台的子项目。那个做 fullLinkJS 就好了。还有一个特定于客户端的 ScalaJS 项目。这就是错误发生的地方。

我正在使用 ScalaJS 1.4.0 和 Play 2.6.25。

关于如何进行的建议?

后来看了@sjrd的回复

违规代码示例:

private val wapp = routes.oat.wapp.controllers.BMailCtrl
...
window.location.href = wapp.edit(emailId).url // this is the line flagged with the error

windoworg.scalajs.dom 中定义为 js.Dynamic.

routes 在我的代码中定义为 val routes: js.Dynamic = global.jsRoutesjs.Dynamic 类型注释是由 IntelliJ 推断的。

啊哈! globalscala.scalajs.js 中定义为扩展 scala.Dynamic。但我认为 jsRoutes 应该解释为 js.Dynamic。这是Play服务器产生的路由。

看来我需要更改访问这些人的方式。研究,特别是 Scala.js GlobalScope.

稍后——修复

我正在记录我在这里所做的事情,以便我可以将 sjrd 的回答标记为“答案”。

如前所述,我的大部分 IR 验证错误都在表格的行上

window.location.href = wapp.edit(emailId).url

href 的类型为 Stringurljs.Dynamic 但会生成一个字符串。我认为这是问题所在。

但是,修复很简单:添加 toString:

window.location.href = wapp.edit(emailId).url.toString

所有其他 IR 验证错误都是此错误的变体,具有类似的修复。

您看到的错误是“IR 检查错误”。它们意味着编译器生成的 .sjsir 文件中存在不一致。默认情况下,它们仅针对 fullOpt 任务进行检查,这就是您之前没有见过它们的原因。然而,这并不意味着 IR 对 fastOpt 更有效(它是相同的 IR!),所以错误一直存在(潜在),但现在只是浮出水面。有 IR 检查错误意味着优化器,或者只是 JavaScript 代码生成器,可以产生无意义的结果。

(IR 检查错误也类似于 JVM 上的 VerifyErrors。

广义上讲,IR 检查错误有 3 个来源:

  • 使用传递库的二进制不兼容版本在极少数情况下会导致 IR 检查错误,即使没有 linking error 出现也是如此。
  • Scala.js 核心工具链(编译器,linker)中的错误
  • Scala.js 类型系统中一个特别已知的(并且有点故意的)不健全问题:js.Dynamic <: scala.Dynamic causes unsoundness in the IR

您遇到的是后一个问题。这是非常罕见的。基本上,如果您将类型 js.Dynamic 的值赋值(通过 = 或传递函数参数等)到类型 scala.Dynamic 的值,就会发生这种情况。例如:

val jsDyn = js.Dynamic.literal(foo = "bar")
val scalaDyn: scala.Dynamic = jsDyn

类型检查器接受该片段,因为在编译时,js.Dynamic 扩展了 scala.Dynamic。这对于 js.Dynamic 首先暴露其活力是必要的,因此我们无法更改它。然而,在 link- 和 运行- 时间,js.Dynamic 是一个 JavaScript 类型(因为它扩展了 js.Any)并且 scala.Dynamic 是一个 Scala类型,并且 JavaScript 类型永远不是 Scala 类型的子类型。


那你会怎样呢?

查看错误信息指向的代码。您将需要确定一个地方,其中 js.Dynamic(或扩展 scala.Dynamic 的任何其他 JS 类型,但 js.Dynamic 通常是唯一的类似类型)分配给 scala.Dynamic.

手写 scala.Dynamic(或只是 Dynamic)作为一个类型是极其罕见的(而且这样做可能总是错误的),但它可能是这样的 由编译器推断 ,例如,如果您有 if/else 的两个分支,那么 return scala.Dynamic.

的两个不同子类型

这就是我在没有看到有问题的代码片段的情况下所能说的。