2

几周前,我将我的 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

window中定义org.scalajs.domjs.Dynamic

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

啊哈! global被定义scala.scalajs.js为扩展scala.Dynamic。但我认为jsRoutes应该解释为js.Dynamic. 它是 Play 服务器生成的路由。

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

再后来——修复

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

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

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

href有一个类型String并且urljs.Dynamic但产生一个字符串。我认为这就是问题所在。

然而,修复很简单:添加toString

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

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

4

1 回答 1

3

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

(IR 检查错误也类似于VerifyErrorJVM 上的 s。

一般来说,IR 检查错误有 3 个来源:

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

您遇到的是后一个问题。这是相当罕见的。基本上,如果您将 type 的值分配(通过=或传递函数参数等)给 typejs.Dynamic的值,就会发生这种情况scala.Dynamic。例如:

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

类型检查器接受该片段,因为在编译时js.Dynamicextends scala.Dynamic。这对于js.Dynamic首先暴露其活力是必要的,因此我们无法改变这一点。但是,在链接和运行时,js.Dynamic它是 JavaScript 类型(因为它 extends js.Any)并且scala.Dynamic是 Scala 类型,并且 JavaScript 类型绝不是 Scala 类型的子类型。


那么,这让你何去何从?

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

scala.Dynamic手动编写(或只是Dynamic)作为类型的情况极为罕见(这样做可能总是一个错误),但它可能是由编译器推断出来的,例如,如果你有两个 if 分支/else 返回两种不同的scala.Dynamic.

在没有看到有问题的代码片段的情况下,我只能这么说。

于 2021-02-12T09:56:50.083 回答