@@ -93,6 +93,24 @@ class PrepJSInterop extends MacroTransform with IdentityDenotTransformer { thisP
9393 }
9494 }
9595
96+ private var dynamicImportEnclosingClasses : Set [Symbol ] = Set .empty
97+
98+ private def enterDynamicImportEnclosingClass [A ](cls : Symbol )(body : => A ): A = {
99+ val saved = dynamicImportEnclosingClasses
100+ dynamicImportEnclosingClasses = saved + cls
101+ try
102+ body
103+ finally
104+ dynamicImportEnclosingClasses = saved
105+ }
106+
107+ private def hasImplicitThisPrefixToDynamicImportEnclosingClass (tpe : Type )(using Context ): Boolean =
108+ tpe match
109+ case tpe : ThisType => dynamicImportEnclosingClasses.contains(tpe.cls)
110+ case TermRef (prefix, _) => hasImplicitThisPrefixToDynamicImportEnclosingClass(prefix)
111+ case _ => false
112+ end hasImplicitThisPrefixToDynamicImportEnclosingClass
113+
96114 /** DefDefs in class templates that export methods to JavaScript */
97115 private val exporters = mutable.Map .empty[Symbol , mutable.ListBuffer [Tree ]]
98116
@@ -297,10 +315,15 @@ class PrepJSInterop extends MacroTransform with IdentityDenotTransformer { thisP
297315
298316 assert(currentOwner.isTerm, s " unexpected owner: $currentOwner at ${tree.sourcePos}" )
299317
318+ val enclosingClass = currentOwner.enclosingClass
319+
300320 // new DynamicImportThunk { def apply(): Any = body }
301321 val dynamicImportThunkAnonClass = AnonClass (currentOwner, List (jsdefn.DynamicImportThunkType ), span) { cls =>
302322 val applySym = newSymbol(cls, nme.apply, Method , MethodType (Nil , Nil , defn.AnyType ), coord = span).entered
303- val newBody = transform(body).changeOwnerAfter(currentOwner, applySym, thisPhase)
323+ val transformedBody = enterDynamicImportEnclosingClass(enclosingClass) {
324+ transform(body)
325+ }
326+ val newBody = transformedBody.changeOwnerAfter(currentOwner, applySym, thisPhase)
304327 val applyDefDef = DefDef (applySym, newBody)
305328 List (applyDefDef)
306329 }
@@ -310,6 +333,14 @@ class PrepJSInterop extends MacroTransform with IdentityDenotTransformer { thisP
310333 .appliedToTypeTree(tpeArg)
311334 .appliedTo(dynamicImportThunkAnonClass)
312335
336+ // #17344 Make `ThisType`-based references to enclosing classes of `js.dynamicImport` explicit
337+ case tree : Ident if hasImplicitThisPrefixToDynamicImportEnclosingClass(tree.tpe) =>
338+ def rec (tpe : Type ): Tree = (tpe : @ unchecked) match // exhaustive because of the `if ... =>`
339+ case tpe : ThisType => This (tpe.cls)
340+ case tpe @ TermRef (prefix, _) => rec(prefix).select(tpe.symbol)
341+
342+ rec(tree.tpe).withSpan(tree.span)
343+
313344 // Compile-time errors and warnings for js.Dynamic.literal
314345 case Apply (Apply (fun, nameArgs), args)
315346 if fun.symbol == jsdefn.JSDynamicLiteral_applyDynamic ||
0 commit comments