@@ -1185,9 +1185,9 @@ class JSCodeGen()(implicit ctx: Context) {
1185
1185
genCoercion(tree, receiver, code)
1186
1186
else if (code == JSPrimitives .THROW )
1187
1187
genThrow(tree, args)
1188
- else /* if (primitives .isJSPrimitive(code))
1189
- genJSPrimitive(tree, receiver, args, code)
1190
- else*/
1188
+ else if (JSPrimitives .isJSPrimitive(code))
1189
+ genJSPrimitive(tree, args, code, isStat )
1190
+ else
1191
1191
throw new FatalError (s " Unknown primitive: ${tree.symbol.fullName} at: $pos" )
1192
1192
}
1193
1193
@@ -2200,6 +2200,171 @@ class JSCodeGen()(implicit ctx: Context) {
2200
2200
}
2201
2201
}
2202
2202
2203
+ /** Gen JS code for a Scala.js-specific primitive method */
2204
+ private def genJSPrimitive (tree : Apply , args : List [Tree ], code : Int ,
2205
+ isStat : Boolean ): js.Tree = {
2206
+
2207
+ import JSPrimitives ._
2208
+
2209
+ implicit val pos = tree.span
2210
+
2211
+ def genArgs1 : js.Tree = {
2212
+ assert(args.size == 1 ,
2213
+ s " Expected exactly 1 argument for JS primitive $code but got " +
2214
+ s " ${args.size} at $pos" )
2215
+ genExpr(args.head)
2216
+ }
2217
+
2218
+ def genArgs2 : (js.Tree , js.Tree ) = {
2219
+ assert(args.size == 2 ,
2220
+ s " Expected exactly 2 arguments for JS primitive $code but got " +
2221
+ s " ${args.size} at $pos" )
2222
+ (genExpr(args.head), genExpr(args.tail.head))
2223
+ }
2224
+
2225
+ def genArgsVarLength : List [js.TreeOrJSSpread ] =
2226
+ genActualJSArgs(tree.symbol, args)
2227
+
2228
+ def resolveReifiedJSClassSym (arg : Tree ): Symbol = {
2229
+ def fail (): Symbol = {
2230
+ ctx.error(
2231
+ tree.symbol.name.toString + " must be called with a constant " +
2232
+ " classOf[T] representing a class extending js.Any " +
2233
+ " (not a trait nor an object)" ,
2234
+ tree.sourcePos)
2235
+ NoSymbol
2236
+ }
2237
+ arg match {
2238
+ case Literal (value) if value.tag == Constants .ClazzTag =>
2239
+ val classSym = value.typeValue.typeSymbol
2240
+ if (isJSType(classSym) && ! classSym.is(Trait ) && ! classSym.is(ModuleClass ))
2241
+ classSym
2242
+ else
2243
+ fail()
2244
+ case _ =>
2245
+ fail()
2246
+ }
2247
+ }
2248
+
2249
+ (code : @ switch) match {
2250
+ case DYNNEW =>
2251
+ // js.Dynamic.newInstance(clazz)(actualArgs: _*)
2252
+ val (jsClass, actualArgs) = extractFirstArg(genArgsVarLength)
2253
+ js.JSNew (jsClass, actualArgs)
2254
+
2255
+ case ARR_CREATE =>
2256
+ // js.Array(elements: _*)
2257
+ js.JSArrayConstr (genArgsVarLength)
2258
+
2259
+ case CONSTRUCTOROF =>
2260
+ // runtime.constructorOf(clazz)
2261
+ val classSym = resolveReifiedJSClassSym(args.head)
2262
+ if (classSym == NoSymbol )
2263
+ js.Undefined () // compile error emitted by resolveReifiedJSClassSym
2264
+ else
2265
+ genLoadJSConstructor(classSym)
2266
+
2267
+ /*
2268
+ case CREATE_INNER_JS_CLASS | CREATE_LOCAL_JS_CLASS =>
2269
+ // runtime.createInnerJSClass(clazz, superClass)
2270
+ // runtime.createLocalJSClass(clazz, superClass, fakeNewInstances)
2271
+ val classSym = resolveReifiedJSClassSym(args(0))
2272
+ val superClassValue = genExpr(args(1))
2273
+ if (classSym == NoSymbol) {
2274
+ js.Undefined() // compile error emitted by resolveReifiedJSClassSym
2275
+ } else {
2276
+ val captureValues = {
2277
+ if (code == CREATE_INNER_JS_CLASS) {
2278
+ val outer = genThis()
2279
+ List.fill(classSym.info.decls.count(_.isClassConstructor))(outer)
2280
+ } else {
2281
+ val ArrayValue(_, fakeNewInstances) = args(2)
2282
+ fakeNewInstances.flatMap(genCaptureValuesFromFakeNewInstance(_))
2283
+ }
2284
+ }
2285
+ js.CreateJSClass(encodeClassRef(classSym),
2286
+ superClassValue :: captureValues)
2287
+ }
2288
+
2289
+ case WITH_CONTEXTUAL_JS_CLASS_VALUE =>
2290
+ // withContextualJSClassValue(jsclass, inner)
2291
+ val jsClassValue = genExpr(args(0))
2292
+ withScopedVars(
2293
+ contextualJSClassValue := Some(jsClassValue)
2294
+ ) {
2295
+ genStatOrExpr(args(1), isStat)
2296
+ }
2297
+ */
2298
+
2299
+ case LINKING_INFO =>
2300
+ // runtime.linkingInfo
2301
+ js.JSLinkingInfo ()
2302
+
2303
+ case DEBUGGER =>
2304
+ // js.special.debugger()
2305
+ js.Debugger ()
2306
+
2307
+ case UNITVAL =>
2308
+ // BoxedUnit.UNIT, which is the boxed version of ()
2309
+ js.Undefined ()
2310
+
2311
+ case JS_NATIVE =>
2312
+ // js.native
2313
+ ctx.error(
2314
+ " js.native may only be used as stub implementation in facade types" ,
2315
+ tree.sourcePos)
2316
+ js.Undefined ()
2317
+
2318
+ case TYPEOF =>
2319
+ // js.typeOf(arg)
2320
+ val arg = genArgs1
2321
+ genAsInstanceOf(js.JSUnaryOp (js.JSUnaryOp .typeof, arg), defn.StringType )
2322
+
2323
+ case IN =>
2324
+ // js.special.in(arg1, arg2)
2325
+ val (arg1, arg2) = genArgs2
2326
+ js.Unbox (js.JSBinaryOp (js.JSBinaryOp .in, arg1, arg2), 'Z' )
2327
+
2328
+ case INSTANCEOF =>
2329
+ // js.special.instanceof(arg1, arg2)
2330
+ val (arg1, arg2) = genArgs2
2331
+ js.Unbox (js.JSBinaryOp (js.JSBinaryOp .instanceof, arg1, arg2), 'Z' )
2332
+
2333
+ case DELETE =>
2334
+ // js.special.delete(arg1, arg2)
2335
+ val (arg1, arg2) = genArgs2
2336
+ js.JSDelete (js.JSBracketSelect (arg1, arg2))
2337
+
2338
+ case FORIN =>
2339
+ /* js.special.forin(arg1, arg2)
2340
+ *
2341
+ * We must generate:
2342
+ *
2343
+ * val obj = arg1
2344
+ * val f = arg2
2345
+ * for (val key in obj) {
2346
+ * f(key)
2347
+ * }
2348
+ *
2349
+ * with temporary vals, because `arg2` must be evaluated only
2350
+ * once, and after `arg1`.
2351
+ */
2352
+ val (arg1, arg2) = genArgs2
2353
+ val objVarDef = js.VarDef (freshLocalIdent(" obj" ), jstpe.AnyType ,
2354
+ mutable = false , arg1)
2355
+ val fVarDef = js.VarDef (freshLocalIdent(" f" ), jstpe.AnyType ,
2356
+ mutable = false , arg2)
2357
+ val keyVarIdent = freshLocalIdent(" key" )
2358
+ val keyVarRef = js.VarRef (keyVarIdent)(jstpe.AnyType )
2359
+ js.Block (
2360
+ objVarDef,
2361
+ fVarDef,
2362
+ js.ForIn (objVarDef.ref, keyVarIdent, {
2363
+ js.JSFunctionApply (fVarDef.ref, List (keyVarRef))
2364
+ }))
2365
+ }
2366
+ }
2367
+
2203
2368
/** Gen actual actual arguments to Scala method call.
2204
2369
* Returns a list of the transformed arguments.
2205
2370
*
0 commit comments