@@ -56,10 +56,11 @@ static std::optional<Luau::TypeId> getTypeIdForClass(const Luau::ScopePtr& globa
5656static Luau::TypeId getSourcemapType (const Luau::GlobalTypes& globals, Luau::TypeArena& arena, const SourceNodePtr& node);
5757
5858static void attachChildLookupFunction (const Luau::GlobalTypes& globals, Luau::TypeArena& arena, const SourceNodePtr& node, Luau::TypeId lookupFuncTy,
59- bool supportRecursiveParameter = false )
59+ bool supportsRecursiveParameter = false , bool supportsTimeoutParameter = false )
6060{
6161 Luau::attachMagicFunction (lookupFuncTy,
62- [node, &arena, &globals](Luau::TypeChecker& typeChecker, const Luau::ScopePtr& scope, const Luau::AstExprCall& expr,
62+ [node, &arena, &globals, supportsRecursiveParameter](Luau::TypeChecker& typeChecker, const Luau::ScopePtr& scope,
63+ const Luau::AstExprCall& expr,
6364 const Luau::WithPredicate<Luau::TypePackId>& withPredicate) -> std::optional<Luau::WithPredicate<Luau::TypePackId>>
6465 {
6566 if (expr.args .size < 1 )
@@ -70,7 +71,7 @@ static void attachChildLookupFunction(const Luau::GlobalTypes& globals, Luau::Ty
7071 return std::nullopt ;
7172
7273 bool recursive = false ;
73- if (expr.args .size >= 2 )
74+ if (supportsRecursiveParameter && expr.args .size >= 2 )
7475 if (auto recursiveParameter = expr.args .data [1 ]->as <Luau::AstExprConstantBool>())
7576 recursive = recursiveParameter->value ;
7677
@@ -82,7 +83,7 @@ static void attachChildLookupFunction(const Luau::GlobalTypes& globals, Luau::Ty
8283 return std::nullopt ;
8384 });
8485 Luau::attachDcrMagicFunction (lookupFuncTy,
85- [node, &arena, &globals](Luau::MagicFunctionCallContext context) -> bool
86+ [node, &arena, &globals, supportsRecursiveParameter, supportsTimeoutParameter ](Luau::MagicFunctionCallContext context) -> bool
8687 {
8788 if (context.callSite ->args .size < 1 )
8889 return false ;
@@ -91,13 +92,33 @@ static void attachChildLookupFunction(const Luau::GlobalTypes& globals, Luau::Ty
9192 if (!str)
9293 return false ;
9394
94- if (auto child = node->findChild (std::string (str->value .data , str->value .size )))
95+ bool recursive = false ;
96+ bool timeoutEnabled = false ;
97+ if (context.callSite ->args .size >= 2 )
98+ {
99+ if (auto recursiveParameter = context.callSite ->args .data [1 ]->as <Luau::AstExprConstantBool>();
100+ recursiveParameter && supportsRecursiveParameter)
101+ recursive = recursiveParameter->value ;
102+ if (supportsTimeoutParameter)
103+ timeoutEnabled = true ;
104+ }
105+
106+ auto childName = std::string (str->value .data , str->value .size );
107+ auto child = recursive ? node->findDescendant (childName) : node->findChild (childName);
108+ if (child)
95109 {
96110 asMutable (context.result )
97111 ->ty .emplace <Luau::BoundTypePack>(context.solver ->arena ->addTypePack ({getSourcemapType (globals, arena, *child)}));
98112 return true ;
99113 }
100114
115+ if (timeoutEnabled)
116+ {
117+ auto optionalInstanceType = Luau::makeOption (globals.builtinTypes , arena, getTypeIdForClass (globals.globalScope , " Instance" ).value ());
118+ asMutable (context.result )->ty .emplace <Luau::BoundTypePack>(context.solver ->arena ->addTypePack ({optionalInstanceType}));
119+ return true ;
120+ }
121+
101122 return false ;
102123 });
103124 Luau::attachTag (lookupFuncTy, kSourcemapGeneratedTag );
@@ -123,16 +144,22 @@ static void injectChildrenLookupFunctions(
123144 auto waitForChildWithTimeoutFunction = Luau::makeFunction (
124145 arena, ty, {globals.builtinTypes ->stringType , globals.builtinTypes ->numberType }, {" name" , " timeout" }, {optionalInstanceType});
125146
126- attachChildLookupFunction (globals, arena, node, findFirstChildFunction, /* supportRecursiveParameter= */ true );
127- attachChildLookupFunction (globals, arena, node, waitForChildFunction);
128- attachChildLookupFunction (globals, arena, node, waitForChildWithTimeoutFunction);
129-
147+ attachChildLookupFunction (globals, arena, node, findFirstChildFunction, /* supportsRecursiveParameter= */ true );
130148 ctv->props [" FindFirstChild" ] = Luau::makeProperty (findFirstChildFunction, " @roblox/globaltype/Instance.FindFirstChild" );
149+
131150 if (FFlag::LuauSolverV2)
151+ {
152+ attachChildLookupFunction (
153+ globals, arena, node, waitForChildFunction, /* supportsRecursiveParameter= */ false , /* supportsTimeoutParameter= */ true );
132154 ctv->props [" WaitForChild" ] = Luau::makeProperty (waitForChildFunction, " @roblox/globaltype/Instance.WaitForChild" );
155+ }
133156 else
157+ {
158+ attachChildLookupFunction (globals, arena, node, waitForChildFunction);
159+ attachChildLookupFunction (globals, arena, node, waitForChildWithTimeoutFunction);
134160 ctv->props [" WaitForChild" ] = Luau::makeProperty (
135161 Luau::makeIntersection (arena, {waitForChildFunction, waitForChildWithTimeoutFunction}), " @roblox/globaltype/Instance.WaitForChild" );
162+ }
136163 }
137164}
138165
0 commit comments