google / google/closure-compiler
Object prototype methods in compiled output fail due to undefined arg (-O ADVANCED)
- Dominant language
- JavaScript
- Stars
- 7.7k
- Forks
- 1.2k
- Avg merge
- 2d 12h
- Merged PRs (30d)
- 6
Description
# Issue
I have rolled an ES module into one large file, including thousands of NPM deps (very large AST), and I am feeding it to the compiler. The output is not executable due to calls like `Object.keys(undefined)` existing in the output.
Here is the original source (intentional type mismatches as a test):
```javascript
import marked from 'marked';
import sanitizeHtml from 'sanitize-html';
/**
* A Markdown note.
*
* @param {string} text
* The text to display.
*
* @return {string}
*/
function NoteWithMarkdown(text) {
const html = sanitizeHtml(
marked(text),
);
return html;
}
/** @type {string} */
const a = 5;
console.log(/** @type {number} */ (a));
console.log(
NoteWithMarkdown('#h1\n##h2'),
);
```
# Precompiled input
The rolled-up dev output fed to the compiler is here: https://pastebin.com/raw/sZRgUjTd
It executes as expected, logging data to the console. This can be compiled with `-O ADVANCED`, but the output fails at execution time (via `node dist/exe.js`) due to the issue mentioned above. With `--debug --formatting PRETTY_PRINT` flags:
```none
file:///home/christian/PersonalProjects/markdown-test/dist/exe.js:3025
var $keys$$ = Object.keys($map$jscomp$6$$).join("|"), $replace$jscomp$1$$ = $getReplacer$$($map$jscomp$6$$), $re$$ = new RegExp("&(?:" + ($keys$$ + "|#[xX][\\da-fA-F]+|#\\d+);"), "g");
^
TypeError: Cannot convert undefined or null to object
at Function.keys ()
at $getStrictDecoder$$ (file:///home/christian/PersonalProjects/markdown-test/dist/exe.js:3025:26)
at file:///home/christian/PersonalProjects/markdown-test/dist/exe.js:3045:37
at $createCommonjsModule$$ (file:///home/christian/PersonalProjects/markdown-test/dist/exe.js:926:7)
at file:///home/christian/PersonalProjects/markdown-test/dist/exe.js:3020:17
at ModuleJob.run (internal/modules/esm/module_job.js:146:23)
at async Loader.import (internal/modules/esm/loader.js:165:24)
at async Object.loadESM (internal/process/esm_loader.js:68:5)
```
# Compiled output
The source for this file can be found here (too big for PasteBin): https://drive.google.com/file/d/16NLCW824NQDPv7yYMP1jL6tX7FMbKKQS/view?usp=sharing
This error persists through multiple calls to Object prototype methods including setPrototypeOf etc. After naively patching the AST to use calls like `Object.keys(val || {})`, we get to an error regarding the library import:
```none
file:///home/christian/PersonalProjects/markdown-test/dist/exe.patched.js:11797
var $parser$jscomp$4$$ = new $lib$5$$.$Parser$({
^
TypeError: $lib$5$$.$Parser$ is not a constructor
at sanitizeHtml (file:///home/christian/PersonalProjects/markdown-test/dist/exe.patched.js:11797:28)
at file:///home/christian/PersonalProjects/markdown-test/dist/exe.patched.js:12002:3
at ModuleJob.run (internal/modules/esm/module_job.js:146:23)
at async Loader.import (internal/modules/esm/loader.js:165:24)
at async Object.loadESM (internal/process/esm_loader.js:68:5)
```
And this error I have no idea how to solve, it is quite beyond me.
Like the other issue I opened today, I understand this is low priority, but I want to document it anyway. This is effectively stress-testing due to the amount of real-life code that is being fed into the compiler in this example, and it is unsurprising that one or two errors bubble up and break the output. However, once the compiler can produce acceptable output for this example, it would likely be a while before a similar bug is discovered - it is extremely rare that the compiler produces outputs with execution-time errors that do not exist in the source in my experience, and only occurs for extremely advanced (and technically unsupported) use cases like this, where we are piping in thousands of real-life NPM dependencies.
Contributor guide
Assessment
This issue has not been assessed yet.