Fix -commonjs compilation crash and empty output (#1990) - #2117
Open
tangtaizong666 wants to merge 1 commit into
Open
Fix -commonjs compilation crash and empty output (#1990)#2117tangtaizong666 wants to merge 1 commit into
tangtaizong666 wants to merge 1 commit into
Conversation
Compiling anything with -commonjs crashed with a null dereference: doCJSModule ran genBasicFunction without an active FunctionContext. The enqueued compilation lambda in genBasicFunction captures curFunction()->typedClassContext / legacyClassContext at enqueue time, and doCJSModule was the only genBasicFunction entry point that did not establish a context first. Create a top-level FunctionContext, mirroring doLazyFunction. With the crash fixed, CJS modules were still compiled to empty bytecode (CommonJS module count: 0) at the default optimization level, because the optimizer does not treat CJS module functions as roots: - deleteUnusedFunctionsAndVariables removed them: they have no IR users, as they are only referenced from the module's CJS module table. - analyzeFunctionCallsites marked them allCallsitesKnownInStrictMode/unreachable, gutting their bodies, since only the global function was exempted as "called by the runtime". FuncSigOpts already handles CJS module functions, so this brings the other two passes in line with it. Add a regression test that compiles and runs a CommonJS module at the default optimization level, -O0, and -O. Fixes facebook#1990
Contributor
|
Hmm. CommonJS isn't supported or maintained, it is just we haven't deleted it yet. But this is a small change that fixes something that does exist. We will discuss whether we want to take it. Thanks! |
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
Fixes #1990.
hermes -commonjssegfaulted on any input. The crash is a null dereference ingenBasicFunction: its enqueued compilation lambda capturescurFunction()->typedClassContext/legacyClassContextat enqueue time, anddoCJSModulewas the onlygenBasicFunctionentry point that did not establish an activeFunctionContextfirst (doIt,doItInScopeanddoLazyFunctionall do). In a release buildcurFunction()returns the nullfunctionContext_, which matches the ASan trace in the issue (ESTreeIRGen-func.cpp:390:43, READ at offset 0x148). The fix creates a top-levelFunctionContext, mirroringdoLazyFunction.With the crash fixed,
-commonjsstill silently produced empty bytecode (CommonJS module count: 0, nothing executed) at the default optimization level, because two optimizer passes do not treat CJS module functions as roots — they have no IR users, they are only referenced from the module's CJS module table and called by the runtime'srequiremachinery:deleteUnusedFunctionsAndVariablesdeleted them as unused (onmain, DCE explicitly skipsM->findCJSModule(&F); that check was lost in this helper onstatic_h).analyzeFunctionCallsitesmarked themallCallsitesKnownInStrictMode/unreachableand their bodies were gutted, producing a segfault at-O; only the global function was exempted as "called by the runtime".FuncSigOptsalready special-cases CJS module functions (F.isGlobalScope() || M->findCJSModule(&F)), so this brings the other two passes in line with it. These are the only twoisGlobalScope()special cases inlib/Optimizerwithout the CJS check.Test Plan
New regression test
test/hermes/cjs-module.jscompiles and runs a CommonJS module at the default optimization level,-O0and-O. TDD verified against each fix:hermes -commonjs test.js→Segmentation fault(exit 139) at any opt level.-O0runs correctly, but default/-Oproduce no output (module deleted as unused), and after also fixingdeleteUnusedFunctionsAndVariables,-Osegfaults on the guttedunreachablebody — each optimizer fix addresses an observed failure mode.Multi-module
require()round trip (also with-Oand-O -fstatic-require):lit suites for the affected components (
test/hermes,test/IRGen,test/Optimizer,test/BCGen,test/Sema,test/AST,test/Parser, release Linux build): 1046 passes, 0 failures caused by this change (the 640 pre-existing failures in my environment are all missingshermes/hbcdumpbinaries, verified by grepping every failure log).Code formatted with clang-format (no diff).