fix(public): defer helper promote until after Public.$init - #3426
Closed
bpamiri wants to merge 1 commit into
Closed
Conversation
Adobe CF 2023 + CommandBox first cold start threw EmptyStackException at onapplicationstart.cfc $createObjectFromRoot. 4.0.6 ran $scanAndPromoteIncludedGlobals inside Public.$init after the helpers include. Restore the 4.0.5 include-and-return $init and promote after $createObjectFromRoot returns so the 3302 helpers-on-this surface still applies once the include nest has unwound. Refs #3379 Signed-off-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Peter Amiri <peter@alurium.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adobe CF 2023 + CommandBox throws
EmptyStackExceptionfromNeoPageContext.popSuperScopeon the first request after a cold start. The stack lands onvendor/wheels/events/onapplicationstart.cfc:409($createObjectFromRoot→Public.$init). Discarding the 4.0.6 files and going back to 4.0.5 clears it. A later page load that compiles a second time also succeeds.This PR is that first-boot EmptyStack path only. It is not the torn-down
application.wo/onErrorString[]report on issue 3379. NoonError,EventHandlerInterface, oronSessionEndedits.Related to #3379.
Root cause (confirmed)
The desk hypothesis holds. I compared the three trees rather than taking the write-up as given.
onapplicationstart.cfc:409→$createObjectFromRoot(path="wheels", fileName="Public", method="$init"). Adobe then pops a super-scope insideUDFMethod.invoke(NeoPageContext.popSuperScope) and the stack is empty.Public.$init(commit6bff05441f/ compat-matrix: engine-job failures are invisible (continue-on-error) — harden after burning down pre-existing leg debt #3302): afterinclude "/wheels/public/helpers.cfm"it now calls$scanAndPromoteIncludedGlobals(). That helper is a parent-class method onwheels.Global. 4.0.5$initis include + return only.include+ parent-method promote nests Adobe's include page-context with a super-scope push. On the first compile ofhelpers.cfmafter a CommandBox cold start,popSuperScoperuns against an empty stack. A later request succeeds because the include is already compiled, matching the report.this. The memoized$promoteIncludedGlobalsToThis()wrapper cannot be used here: Global's pseudo-constructor already cached a pre-include key list forwheels.Public.Hoisting the include into a helper and still calling the scan from
$initis the other obvious shape. I discarded it. 4.0.5$initis include-and-return and does not throw. If the inherited scan extra-pops,$init's own return still EmptyStacks. The safe contract is the one that already worked:$initdoes not call the scan. Promote after$createObjectFromRootreturns, once that Invoke has fully unwound.4.0.5 vs 4.0.6 vs develop
Public.$init51eb6e47include "/wheels/public/helpers.cfm"thenreturn this5928131d$scanAndPromoteIncludedGlobals(), then returnc64f6a9b$createObjectFromRoot(..., Public, $init): 4.0.5 line 419, 4.0.6 and develop line 409. Same call.What changed
Public.$initis include-and-return again (the 4.0.5 shape). It does not call$scanAndPromoteIncludedGlobals().onapplicationstart.cfccalls$scanAndPromoteIncludedGlobals()on the Public instance after$createObjectFromRootreturns, so the compat-matrix: engine-job failures are invisible (continue-on-error) — harden after burning down pre-existing leg debt #3302 helpers-on-thissurface still applies once the include nest has unwound.Application.cfccopies does the same two-step. Those paths replaceapplication.wheels.publicafter$init; without the follow-up scan they would drop helpers on Lucee 6 / Adobe.onSessionEndis untouched.Tests
vendor/wheels/tests/specs/events/PublicInitColdStartSpec.cfc(extendswheels.WheelsTest)$initbody has no$scanAndPromoteIncludedGlobalscall (the 4.0.6 nest)onapplicationstartand the four shippedApplication.cfccopies promote after$createObjectFromRootreturns$initthen$scanAndPromoteIncludedGlobals()puts$$findMatchingRoutesonthis(compat-matrix: engine-job failures are invisible (continue-on-error) — harden after burning down pre-existing leg debt #3302)RouteTesterHardeningSpecandDispatchPublicHardenerSpeccall the scan after$initbefore they use$$findMatchingRoutesAdobe CF 2023 + CommandBox first-boot cannot be fully simulated here. The spec pins the contract that prevents the nest.
Out of scope
Left on issue 3379, not this PR:
application.woduringonError(Element wo is undefined in a Java object of type class [Ljava.lang.String;)EventHandlerInterfacemissing-template during$invokefromonErrorApplication.cfc(that drop would remove the developonSessionEndguard)Type of Change
changelog.d/3379-first-boot-emptystack.fixed.md)Test Plan
wheels test --core --ci --filter=events(new spec)wheels test --core --ci(full framework suite)