Skip to content

Commit c71aa5b

Browse files
authored
Merge branch 'scala-wasm' into fix/151-uri-normalize-wasm
2 parents 4ef8731 + 167d23d commit c71aa5b

105 files changed

Lines changed: 2208 additions & 1913 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ jobs:
8181
esVersion: [ES2015, ES2021] # Some javalib features depend on the target ES version
8282
eh-support: [true, false]
8383
env:
84-
SBT_SET_COMMAND: 'set Seq(Global/enableWasmEverywhere := true, ThisBuild/scalaJSLinkerConfig ~= (_.withESFeatures(_.withESVersion(ESVersion.${{ matrix.esVersion }})).withWasmFeatures(_.withTargetPureWasm(true).withExceptionHandling(${{ matrix.eh-support }}))))'
84+
SBT_SET_COMMAND: 'set Seq(Global/enableWasmEverywhere := true, ThisBuild/scalaJSLinkerConfig ~= (_.withESFeatures(_.withESVersion(ESVersion.${{ matrix.esVersion }})).withModuleKind(ModuleKind.MinimalWasmModule).withWasmFeatures(_.withExceptionHandling(${{ matrix.eh-support }}))))'
8585
steps:
8686
- uses: actions/checkout@v4
8787
- uses: actions/setup-java@v4

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ This is a friendly fork of Scala.js, targeting stand-alone Wasm runtimes such as
2424
### `test-suite`
2525
```sh
2626
sbt:Scala.js> set Global/enableWasmEverywhere := true
27-
sbt:Scala.js> set scalaJSLinkerConfig in testSuite.v2_12 ~= (_.withWasmFeatures(_.withTargetPureWasm(true)))
27+
sbt:Scala.js> set scalaJSLinkerConfig in testSuite.v2_12 ~= (_.withModuleKind(ModuleKind.MinimalWasmModule))
2828
sbt:Scala.js> testSuite2_12/test
2929
```
3030

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,7 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
696696
val info = jsInterop.witExportOf(dd.symbol).get
697697
for (method <- genMethod(dd)) {
698698
methodsBuilder += method
699-
witExportDefsBuilder += genWitExportDef(info, method)
699+
witExportDefsBuilder += genWitExportDef(info, dd.symbol, method)
700700
}
701701
} else {
702702
methodsBuilder ++= genMethod(dd)

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

Lines changed: 60 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,8 @@ trait GenWitInterop[G <: Global with Singleton] extends SubComponent {
134134
implicit val pos = tree.pos
135135
val sym = tree.symbol
136136
withNewLocalNameScope {
137-
val funcType = jsInterop.witFunctionTypeOf(sym)
138-
val baseParams = funcType.params.map(toWIT(_))
137+
val (paramTypes, resultType) = witMethodSignatureOf(sym)
138+
val baseParams = paramTypes.map(toWIT(_))
139139
val params = name match {
140140
case _:js.WitFunctionName.Function |
141141
_:js.WitFunctionName.ResourceConstructor |
@@ -146,7 +146,7 @@ trait GenWitInterop[G <: Global with Singleton] extends SubComponent {
146146
}
147147
val witFuncType = wit.FuncType(
148148
params,
149-
toResultWIT(funcType.resultType)
149+
toResultWIT(resultType)
150150
)
151151
js.WitNativeMemberDef(flags, moduleName, name,
152152
encodeMethodSym(sym), witFuncType)
@@ -158,8 +158,7 @@ trait GenWitInterop[G <: Global with Singleton] extends SubComponent {
158158
val sym = tree.symbol
159159

160160
val flags = js.MemberFlags.empty.withNamespace(js.MemberNamespace.PublicStatic)
161-
val funcType = jsInterop.witFunctionTypeOf(sym)
162-
161+
val (paramTypes, resultType) = witMethodSignatureOf(sym)
163162
for {
164163
methodAnnot <- sym.getAnnotation(WitResourceStaticMethodAnnotation)
165164
resourceAnnot <- sym.owner.companionClass.getAnnotation(WitResourceImportAnnotation)
@@ -170,8 +169,8 @@ trait GenWitInterop[G <: Global with Singleton] extends SubComponent {
170169
val name = js.WitFunctionName.ResourceStaticMethod(
171170
func = methodName, resource = resourceName)
172171
withNewLocalNameScope {
173-
val params = funcType.params.map(p => toWIT(p))
174-
val ft = wit.FuncType(params, toResultWIT(funcType.resultType))
172+
val params = paramTypes.map(toWIT(_))
173+
val ft = wit.FuncType(params, toResultWIT(resultType))
175174
js.WitNativeMemberDef(flags, moduleName, name, encodeMethodSym(sym), ft)
176175
}
177176
}
@@ -182,7 +181,7 @@ trait GenWitInterop[G <: Global with Singleton] extends SubComponent {
182181
val sym = tree.symbol
183182

184183
val flags = js.MemberFlags.empty.withNamespace(js.MemberNamespace.PublicStatic)
185-
val funcType = jsInterop.witFunctionTypeOf(sym)
184+
val (paramTypes, resultType) = witMethodSignatureOf(sym)
186185

187186
for {
188187
methodAnnot <- sym.getAnnotation(WitResourceConstructorAnnotation)
@@ -192,19 +191,20 @@ trait GenWitInterop[G <: Global with Singleton] extends SubComponent {
192191
} yield {
193192
val name = js.WitFunctionName.ResourceConstructor(resourceName)
194193
withNewLocalNameScope {
195-
val params = funcType.params.map(p => toWIT(p))
196-
val ft = wit.FuncType(params, toResultWIT(funcType.resultType))
194+
val params = paramTypes.map(toWIT(_))
195+
val ft = wit.FuncType(params, toResultWIT(resultType))
197196
js.WitNativeMemberDef(flags, moduleName, name, encodeMethodSym(sym), ft)
198197
}
199198
}
200199
}
201200

202-
def genWitExportDef(info: jsInterop.WitExportInfo,
201+
def genWitExportDef(info: jsInterop.WitExportInfo, sym: Symbol,
203202
methodDef: js.MethodDef): js.WitExportDef = {
204203
withNewLocalNameScope {
204+
val (paramTypes, resultType) = witMethodSignatureOf(sym)
205205
val signature = wit.FuncType(
206-
info.signature.params.map(toWIT(_)),
207-
toResultWIT(info.signature.resultType)
206+
paramTypes.map(toWIT(_)),
207+
toResultWIT(resultType)
208208
)
209209
js.WitExportDef(
210210
info.moduleName,
@@ -215,15 +215,46 @@ trait GenWitInterop[G <: Global with Singleton] extends SubComponent {
215215
}
216216
}
217217

218+
private def witMethodSignatureOf(sym: Symbol): (List[Type], Type) = {
219+
exitingPhase(currentRun.typerPhase) {
220+
val methodType = sym.tpe
221+
val params =
222+
if (methodType.paramss.isEmpty) Nil
223+
else methodType.paramss.head.map(_.tpe)
224+
(params, methodType.resultType)
225+
}
226+
}
227+
228+
private def witVariantValueTypeOf(sym: Symbol): Type = {
229+
exitingPhase(currentRun.typerPhase) {
230+
if (sym.isModuleClass) {
231+
UnitTpe
232+
} else if (sym.isClass && sym.isFinal && !sym.isTrait) {
233+
sym.primaryConstructor.paramss.flatten match {
234+
case Nil =>
235+
UnitTpe
236+
case param :: Nil =>
237+
param.tpe
238+
case _ =>
239+
throw new AssertionError(s"Invalid WIT variant case shape for $sym")
240+
}
241+
} else {
242+
throw new AssertionError(s"Invalid WIT variant case symbol $sym")
243+
}
244+
}
245+
}
246+
218247
private def toWIT(tpe: Type): wit.ValType = {
219-
unsigned2WIT.get(tpe.typeSymbolDirect).orElse {
220-
toWITMaybeArray(tpe.dealiasWiden)
248+
val widenedTpe = exitingPhase(currentRun.typerPhase)(tpe.dealiasWiden)
249+
250+
unsigned2WIT.get(widenedTpe.typeSymbolDirect).orElse {
251+
toWITMaybeArray(widenedTpe)
221252
}.orElse {
222-
primitiveIRWIT.get(toIRType(tpe.dealiasWiden))
253+
primitiveIRWIT.get(toIRType(widenedTpe))
223254
}.getOrElse {
224-
tpe.dealiasWiden.typeSymbol match {
255+
widenedTpe.typeSymbol match {
225256
case tsym if isWasmComponentTupleClass(tsym) =>
226-
wit.TupleType(tpe.typeArgs.map(toWIT(_)))
257+
wit.TupleType(widenedTpe.baseType(tsym).typeArgs.map(toWIT(_)))
227258

228259
case tsym if tsym.hasAnnotation(WitFlagsAnnotation) =>
229260
// Read numFlags from annotation parameter
@@ -236,26 +267,26 @@ trait GenWitInterop[G <: Global with Singleton] extends SubComponent {
236267
wit.FlagsType(className, numFlags)
237268

238269
case tsym if isWasmWitRecordClass(tsym) =>
239-
// TODO: it needs to be sorted by the order of record in wit definition
240270
val className = encodeClassName(tsym)
241-
val fields: List[wit.FieldType] = tsym.info.decls.collect {
242-
case f if f.isField =>
243-
val label = encodeFieldSym(f)(f.pos).name
244-
val fieldType = jsInterop.witVariantValueTypeOf(f)
245-
val valueType = toWIT(fieldType)
246-
wit.FieldType(label, valueType)
247-
}.toList
271+
val fields = exitingPhase(currentRun.typerPhase) {
272+
tsym.primaryConstructor.paramss.flatten.map { param =>
273+
(param.name.dropLocal.toString(), param.tpe)
274+
}
275+
}.map { case (fieldName, fieldType) =>
276+
val label = Names.FieldName(className, Names.SimpleFieldName(fieldName))
277+
wit.FieldType(label, toWIT(fieldType))
278+
}
248279
wit.RecordType(className, fields)
249280

250281
case tsym if isWasmWitResourceType(tsym) =>
251282
wit.ResourceType(encodeClassName(tsym))
252283

253284
case tsym if tsym.isSubClass(ComponentResultClass) && tsym.isSealed =>
254-
val List(ok, err) = tpe.typeArgs
285+
val List(ok, err) = widenedTpe.baseType(ComponentResultClass).typeArgs
255286
wit.ResultType(toResultWIT(ok), toResultWIT(err))
256287

257288
case tsym if tsym.fullName == "java.util.Optional" =>
258-
val List(t) = tpe.dealiasWiden.typeArgs
289+
val List(t) = widenedTpe.baseType(tsym).typeArgs
259290
wit.OptionType(toWIT(t))
260291

261292
case tsym if tsym.hasAnnotation(WitVariantAnnotation) && tsym.isSealed =>
@@ -266,7 +297,7 @@ trait GenWitInterop[G <: Global with Singleton] extends SubComponent {
266297
val cases = tsym.sealedChildren.toList.sortBy(_.pos.line) map { child =>
267298
// assert(child.isFinal)
268299
// assert(child.isClass)
269-
val valueType = jsInterop.witVariantValueTypeOf(child)
300+
val valueType = witVariantValueTypeOf(child)
270301
val caseTyp = if (toIRType(valueType) == jstpe.VoidType) {
271302
None
272303
} else {

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

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,6 @@ trait JSGlobalAddons extends JSDefinitions with CompatComponent {
103103
private val jsNativeLoadSpecs =
104104
mutable.Map.empty[Symbol, JSNativeLoadSpec]
105105

106-
private val componentFunctionTypes =
107-
mutable.Map.empty[Symbol, WitFunctionType]
108-
109-
private val WitVariantValueTypes =
110-
mutable.Map.empty[Symbol, Type]
111-
112106
private val exportPrefix = "$js$exported$"
113107
private val methodExportPrefix = exportPrefix + "meth$"
114108
private val propExportPrefix = exportPrefix + "prop$"
@@ -125,16 +119,10 @@ trait JSGlobalAddons extends JSDefinitions with CompatComponent {
125119
val pos: Position)
126120
extends ExportInfo
127121

128-
case class WitExportInfo(moduleName: String, name: String,
129-
signature: WitFunctionType)(
122+
case class WitExportInfo(moduleName: String, name: String)(
130123
val pos: Position)
131124
extends ExportInfo
132125

133-
case class WitFunctionType(
134-
params: List[Type],
135-
resultType: Type
136-
)
137-
138126
case class StaticExportInfo(jsName: String)(val pos: Position) extends ExportInfo
139127

140128
sealed abstract class JSName {
@@ -420,17 +408,6 @@ trait JSGlobalAddons extends JSDefinitions with CompatComponent {
420408
def jsNativeLoadSpecOfOption(sym: Symbol): Option[JSNativeLoadSpec] =
421409
jsNativeLoadSpecs.get(sym)
422410

423-
def storeWitVariantValueType(sym: Symbol, valueType: Type): Unit =
424-
WitVariantValueTypes(sym) = valueType
425-
426-
def witVariantValueTypeOf(sym: Symbol): Type =
427-
WitVariantValueTypes(sym)
428-
429-
def storeWitFunctionType(sym: Symbol, funcType: WitFunctionType): Unit =
430-
componentFunctionTypes(sym) = funcType
431-
432-
def witFunctionTypeOf(sym: Symbol): WitFunctionType =
433-
componentFunctionTypes(sym)
434411
}
435412

436413
}

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

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,7 @@ trait PrepJSExports[G <: Global with Singleton] { this: PrepJSInterop[G] =>
140140

141141
val wasmComponent = exports.collect {
142142
case info @ ExportInfo(moduleName, ExportDestination.WasmComponent(name)) =>
143-
val signature = jsInterop.WitFunctionType(
144-
(if (sym.tpe.paramss.isEmpty) Nil else sym.tpe.paramss.head).map(_.tpe),
145-
sym.tpe.resultType
146-
)
147-
jsInterop.WitExportInfo(moduleName, name, signature)(info.pos)
143+
jsInterop.WitExportInfo(moduleName, name)(info.pos)
148144
}
149145

150146
if (sym.isMethod && wasmComponent.nonEmpty) {

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

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -862,12 +862,6 @@ abstract class PrepJSInterop[G <: Global with Singleton](val global: G)
862862
reporter.error(pos,
863863
s"Return type '${returnType}' is not compatible with Component Model")
864864
}
865-
866-
val funcType = jsInterop.WitFunctionType(
867-
(if (sym.tpe.paramss.isEmpty) Nil else sym.tpe.paramss.head).map(_.tpe),
868-
sym.tpe.resultType
869-
)
870-
jsInterop.storeWitFunctionType(sym, funcType)
871865
}
872866
}
873867
}
@@ -953,12 +947,6 @@ abstract class PrepJSInterop[G <: Global with Singleton](val global: G)
953947
overridden.fullName)
954948
}
955949
}
956-
957-
val funcType = jsInterop.WitFunctionType(
958-
(if (member.tpe.paramss.isEmpty) Nil else member.tpe.paramss.head).map(_.tpe),
959-
member.tpe.resultType
960-
)
961-
jsInterop.storeWitFunctionType(member, funcType)
962950
}
963951
}
964952

@@ -991,12 +979,6 @@ abstract class PrepJSInterop[G <: Global with Singleton](val global: G)
991979
s"Public method '${member.name}' in companion object of @WitResourceImport trait must be " +
992980
"annotated with @WitResourceConstructor or @WitResourceStaticMethod")
993981
}
994-
995-
val funcType = jsInterop.WitFunctionType(
996-
(if (member.tpe.paramss.isEmpty) Nil else member.tpe.paramss.head).map(_.tpe),
997-
member.tpe.resultType
998-
)
999-
jsInterop.storeWitFunctionType(member, funcType)
1000982
}
1001983
}
1002984
}
@@ -1024,7 +1006,6 @@ abstract class PrepJSInterop[G <: Global with Singleton](val global: G)
10241006
private def validateWitVariantCase(caseSym: Symbol): Unit = {
10251007
if (caseSym.isModuleClass) {
10261008
// Regular object (enum case without payload)
1027-
jsInterop.storeWitVariantValueType(caseSym, definitions.UnitTpe)
10281009
} else if (caseSym.isClass && caseSym.isFinal && !caseSym.isTrait) {
10291010
// Final class (variant case with payload)
10301011
val primaryCtor = caseSym.primaryConstructor
@@ -1051,12 +1032,9 @@ abstract class PrepJSInterop[G <: Global with Singleton](val global: G)
10511032
} else if (!isComponentModelCompatible(fieldType)) {
10521033
reporter.error(param.pos,
10531034
s"Field '${param.name}' has type '${fieldType}' which is not compatible with Component Model. ")
1054-
} else {
1055-
jsInterop.storeWitVariantValueType(caseSym, fieldType)
10561035
}
10571036
} else {
10581037
// Zero parameters - enum case defined as a class
1059-
jsInterop.storeWitVariantValueType(caseSym, definitions.UnitTpe)
10601038
}
10611039
} else {
10621040
reporter.error(caseSym.pos,
@@ -1121,13 +1099,6 @@ abstract class PrepJSInterop[G <: Global with Singleton](val global: G)
11211099
s"Field '${param.name}' has type '${fieldType}' which is not compatible with Component Model")
11221100
}
11231101
}
1124-
// Store field types for code generation
1125-
for {
1126-
f <- sym.info.decls
1127-
if !f.isMethod && f.isField
1128-
} {
1129-
jsInterop.storeWitVariantValueType(f, f.tpe)
1130-
}
11311102
}
11321103
}
11331104

examples/test-component-model/src/main/scala/componentmodel/TestImportsImpl.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import java.util.Optional
1717
@WitImplementation
1818
object TestImportsImpl extends TestImports {
1919
override def run(): Unit = {
20+
def newCounterArray(size: Int): Array[Counter] =
21+
new Array[Counter](size)
2022

2123
val start = System.currentTimeMillis()
2224

@@ -62,6 +64,15 @@ object TestImportsImpl extends TestImports {
6264
val arr3 = Array[C1](C1.A(0), C1.B(3))
6365
assert(arr3.sameElements(roundtripListVariant(arr3)))
6466

67+
val counter1 = Counter(1)
68+
val counter2 = Counter(2)
69+
val counterArr = newCounterArray(2)
70+
assert(counterArr.length == 2)
71+
counterArr(0) = counter1
72+
counterArr(1) = counter2
73+
assert(counterArr(0).valueOf() == 1)
74+
assert(counterArr(1).valueOf() == 2)
75+
6576
assert("foo" == roundtripString("foo"))
6677
assert("" == roundtripString(""))
6778
assert(Point(0, 5) == roundtripPoint(Point(0, 5)))

ir/shared/src/main/scala/org/scalajs/ir/Serializers.scala

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ import LinkTimeProperty.{
3030
ESVersion,
3131
UseECMAScript2015Semantics,
3232
IsWebAssembly,
33-
LinkerVersion,
34-
TargetPureWasm
33+
LinkerVersion
3534
}
3635
import Types._
3736
import Tags._
@@ -1590,8 +1589,6 @@ object Serializers {
15901589
LinkTimeProperty(LinkerVersion)(StringType)
15911590
case StringLiteral("fileLevelThis") =>
15921591
JSGlobalRef(JSGlobalRef.FileLevelThis)
1593-
case StringLiteral("targetPureWasm") =>
1594-
LinkTimeProperty(TargetPureWasm)(BooleanType)
15951592
case otherItem =>
15961593
JSSelect(jsLinkingInfo, otherItem)
15971594
}
@@ -1628,8 +1625,7 @@ object Serializers {
16281625
LinkTimeProperty(UseECMAScript2015Semantics)(BooleanType)),
16291626
(StringLiteral("isWebAssembly"), LinkTimeProperty(IsWebAssembly)(BooleanType)),
16301627
(StringLiteral("linkerVersion"), LinkTimeProperty(LinkerVersion)(StringType)),
1631-
(StringLiteral("fileLevelThis"), JSGlobalRef(JSGlobalRef.FileLevelThis)),
1632-
(StringLiteral("targetPureWasm"), LinkTimeProperty(TargetPureWasm)(BooleanType))
1628+
(StringLiteral("fileLevelThis"), JSGlobalRef(JSGlobalRef.FileLevelThis))
16331629
))
16341630
} else {
16351631
throw new IOException(

0 commit comments

Comments
 (0)