Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2cf8722

Browse files
committed
Use a sort of "language import" for orphan awaits.
Instead of a compiler option.
1 parent d400f9d commit 2cf8722

File tree

10 files changed

+92
-35
lines changed

10 files changed

+92
-35
lines changed

compiler/src/main/scala/org/scalajs/nscplugin/GenJSCode.scala

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5355,16 +5355,23 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
53555355
js.Block(genStats, asyncExpr)
53565356

53575357
case JS_AWAIT =>
5358-
// js.await(arg)
5359-
if (!scalaJSOpts.allowOrphanJSAwait && !methodsAllowingJSAwait.contains(currentMethodSym)) {
5360-
reporter.error(pos,
5361-
"Illegal use of js.await().\n" +
5362-
"It can only be used inside a js.async {...} block, without any lambda,\n" +
5363-
"by-name argument or nested method in-between.\n" +
5364-
"If you compile for WebAssembly, you can allow arbitrary js.await()\n" +
5365-
"calls with -P:scalajs:allowOrphanJSAwait.")
5358+
// js.await(arg)(permit)
5359+
val (arg, permitValue) = genArgs2
5360+
if (!methodsAllowingJSAwait.contains(currentMethodSym)) {
5361+
// This is an orphan await
5362+
if (!(args(1).tpe <:< WasmJSPI_allowOrphanJSAwaitModuleClass.toTypeConstructor)) {
5363+
reporter.error(pos,
5364+
"Illegal use of js.await().\n" +
5365+
"It can only be used inside a js.async {...} block, without any lambda,\n" +
5366+
"by-name argument or nested method in-between.\n" +
5367+
"If you compile for WebAssembly, you can allow arbitrary js.await()\n" +
5368+
"calls by adding the following import:\n" +
5369+
"import scala.scalajs.js.wasm.JSPI.allowOrphanJSAwait")
5370+
}
53665371
}
5367-
val arg = genArgs1
5372+
/* In theory we should evaluate `permit` after `arg` but before the `JSAwait`.
5373+
* It *should* always be side-effect-free, though, so we just discard it.
5374+
*/
53685375
js.JSAwait(arg)
53695376

53705377
case DYNAMIC_IMPORT =>

compiler/src/main/scala/org/scalajs/nscplugin/JSDefinitions.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,11 @@ trait JSDefinitions {
116116
lazy val Special_unwrapFromThrowable = getMemberMethod(SpecialPackageModule, newTermName("unwrapFromThrowable"))
117117
lazy val Special_debugger = getMemberMethod(SpecialPackageModule, newTermName("debugger"))
118118

119+
lazy val WasmJSPIModule = getRequiredModule("scala.scalajs.js.wasm.JSPI")
120+
lazy val WasmJSPIModuleClass = WasmJSPIModule.moduleClass
121+
lazy val WasmJSPI_allowOrphanJSAwaitModule = getMemberModule(WasmJSPIModuleClass, newTermName("allowOrphanJSAwait"))
122+
lazy val WasmJSPI_allowOrphanJSAwaitModuleClass = WasmJSPI_allowOrphanJSAwaitModule.moduleClass
123+
119124
lazy val RuntimePackageModule = getPackageObject("scala.scalajs.runtime")
120125
lazy val Runtime_toScalaVarArgs = getMemberMethod(RuntimePackageModule, newTermName("toScalaVarArgs"))
121126
lazy val Runtime_toJSVarArgs = getMemberMethod(RuntimePackageModule, newTermName("toJSVarArgs"))

compiler/src/main/scala/org/scalajs/nscplugin/ScalaJSOptions.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,6 @@ trait ScalaJSOptions {
4343
* See the warning itself or #4129 for context.
4444
*/
4545
def warnGlobalExecutionContext: Boolean
46-
47-
/** Whether to tolerate orphan `js.await` calls for WebAssembly's JSPI. */
48-
def allowOrphanJSAwait: Boolean
4946
}
5047

5148
object ScalaJSOptions {

compiler/src/main/scala/org/scalajs/nscplugin/ScalaJSPlugin.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ class ScalaJSPlugin(val global: Global) extends NscPlugin {
6363
relSourceMap.toList.map(URIMap(_, absSourceMap))
6464
}
6565
var warnGlobalExecutionContext: Boolean = true
66-
var allowOrphanJSAwait: Boolean = false
6766
var _sourceURIMaps: List[URIMap] = Nil
6867
var relSourceMap: Option[URI] = None
6968
var absSourceMap: Option[URI] = None
@@ -114,8 +113,6 @@ class ScalaJSPlugin(val global: Global) extends NscPlugin {
114113
genStaticForwardersForNonTopLevelObjects = true
115114
} else if (option == "nowarnGlobalExecutionContext") {
116115
warnGlobalExecutionContext = false
117-
} else if (option == "allowOrphanJSAwait") {
118-
allowOrphanJSAwait = true
119116
} else if (option.startsWith("mapSourceURI:")) {
120117
val uris = option.stripPrefix("mapSourceURI:").split("->")
121118

compiler/src/test/scala/org/scalajs/nscplugin/test/JSAsyncAwaitTest.scala

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ class JSAsyncAwaitTest extends DirectTest with TestHelpers {
3636
|It can only be used inside a js.async {...} block, without any lambda,
3737
|by-name argument or nested method in-between.
3838
|If you compile for WebAssembly, you can allow arbitrary js.await()
39-
|calls with -P:scalajs:allowOrphanJSAwait.
39+
|calls by adding the following import:
40+
|import scala.scalajs.js.wasm.JSPI.allowOrphanJSAwait
4041
| js.await(x)
4142
| ^
4243
"""
@@ -54,7 +55,8 @@ class JSAsyncAwaitTest extends DirectTest with TestHelpers {
5455
|It can only be used inside a js.async {...} block, without any lambda,
5556
|by-name argument or nested method in-between.
5657
|If you compile for WebAssembly, you can allow arbitrary js.await()
57-
|calls with -P:scalajs:allowOrphanJSAwait.
58+
|calls by adding the following import:
59+
|import scala.scalajs.js.wasm.JSPI.allowOrphanJSAwait
5860
| val f: () => Int = () => js.await(x)
5961
| ^
6062
"""
@@ -72,7 +74,8 @@ class JSAsyncAwaitTest extends DirectTest with TestHelpers {
7274
|It can only be used inside a js.async {...} block, without any lambda,
7375
|by-name argument or nested method in-between.
7476
|If you compile for WebAssembly, you can allow arbitrary js.await()
75-
|calls with -P:scalajs:allowOrphanJSAwait.
77+
|calls by adding the following import:
78+
|import scala.scalajs.js.wasm.JSPI.allowOrphanJSAwait
7679
| def f(): Int = js.await(x)
7780
| ^
7881
"""
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Scala.js (https://www.scala-js.org/)
3+
*
4+
* Copyright EPFL.
5+
*
6+
* Licensed under Apache License 2.0
7+
* (https://www.apache.org/licenses/LICENSE-2.0).
8+
*
9+
* See the NOTICE file distributed with this work for
10+
* additional information regarding copyright ownership.
11+
*/
12+
13+
package scala.scalajs.js
14+
15+
/** Kind of permit for calling `js.await()`.
16+
*
17+
* A default permit is always available. It allows to call `js.await()` when
18+
* directly enclosed by a `js.async { ... }` block.
19+
*
20+
* @see [[scala.scalajs.js.async]]
21+
*/
22+
abstract class AwaitPermit private[js] ()
23+
24+
object AwaitPermit {
25+
/** Default permit for `js.await()` calls directly enclosed within a
26+
* `js.async` block.
27+
*/
28+
implicit object directlyWithinAsync extends AwaitPermit
29+
}

library/src/main/scala/scala/scalajs/js/package.scala

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,11 @@ package object js {
196196
* <h2>Orphan `await`s in WebAssembly</h2>
197197
*
198198
* When compiling for Scala.js-on-Wasm only, you can allow calls to
199-
* `js.await` anywhere, using the compiler option
200-
* `-P:scalajs:allowOrphanJSAwait`.
199+
* `js.await` anywhere, by adding the following import:
200+
*
201+
* {{{
202+
* import scala.scalajs.js.wasm.JSPI.allowOrphanJSAwait
203+
* }}}
201204
*
202205
* Calls to orphan `js.await`s are validated at run-time. There must exist
203206
* a dynamically enclosing `js.async { ... }` block on the call stack.
@@ -216,6 +219,6 @@ package object js {
216219
*
217220
* See the documentation of [[async js.async]].
218221
*/
219-
def await[A](promise: js.Promise[A]): A =
222+
def await[A](promise: js.Promise[A])(implicit permit: AwaitPermit): A =
220223
throw new java.lang.Error("stub")
221224
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Scala.js (https://www.scala-js.org/)
3+
*
4+
* Copyright EPFL.
5+
*
6+
* Licensed under Apache License 2.0
7+
* (https://www.apache.org/licenses/LICENSE-2.0).
8+
*
9+
* See the NOTICE file distributed with this work for
10+
* additional information regarding copyright ownership.
11+
*/
12+
13+
package scala.scalajs.js.wasm
14+
15+
import scala.scalajs.js
16+
17+
/** Features related to the WebAssembly JavaScript Promise Integration (JSPI). */
18+
object JSPI {
19+
/** Allow arbitrary calls to `js.await()`.
20+
*
21+
* Import this object to allow arbitrary calls to `js.await()`, even when
22+
* they are not directly nested within a `js.async { ... }` block.
23+
* The resulting code will then only link when targeting WebAssembly.
24+
*
25+
* @see [[scala.scalajs.js.async]]
26+
*/
27+
implicit object allowOrphanJSAwait extends js.AwaitPermit
28+
}

project/Build.scala

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2289,20 +2289,6 @@ object Build {
22892289
Test / scalacOptions ++= scalaJSCompilerOption("genStaticForwardersForNonTopLevelObjects"),
22902290
Test / scalacOptions ++= scalaJSCompilerOption("nowarnGlobalExecutionContext"),
22912291

2292-
Test / scalacOptions ++= {
2293-
val linkerConfig = scalaJSStage.value match {
2294-
case FastOptStage => (scalaJSLinkerConfig in (Compile, fastLinkJS)).value
2295-
case FullOptStage => (scalaJSLinkerConfig in (Compile, fullLinkJS)).value
2296-
}
2297-
2298-
if (linkerConfig.experimentalUseWebAssembly &&
2299-
linkerConfig.esFeatures.esVersion >= ESVersion.ES2017) {
2300-
scalaJSCompilerOption("allowOrphanJSAwait")
2301-
} else {
2302-
Nil
2303-
}
2304-
},
2305-
23062292
scalaJSLinkerConfig ~= { _.withSemantics(TestSuiteLinkerOptions.semantics _) },
23072293
scalaJSModuleInitializers in Test ++= TestSuiteLinkerOptions.moduleInitializers,
23082294

test-suite/js/src/test/require-orphan-await/org/scalajs/testsuite/jsinterop/JSOrphanAwaitTest.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import scala.scalajs.js
1616
import scala.scalajs.js.JSConverters._
1717
import scala.scalajs.js.|
1818

19+
import scala.scalajs.js.wasm.JSPI.allowOrphanJSAwait
20+
1921
import scala.concurrent.{Future, ExecutionContext}
2022
import scala.concurrent.ExecutionContext.Implicits.global
2123

0 commit comments

Comments
 (0)