chore(lint): enable no-undef for the native browser shims - #68
Conversation
common/Native/ stubs window, document, navigator, console, setTimeout and performance for the embedded JS context used by DoctRenderer/x2t. Nothing in CI executes that bundle - the QUnit suites run in a real browser, where these stubs are never loaded - so an undeclared identifier here reaches production completely unexercised. Enable no-undef for those files and run eslint in the code-style job. Scoped deliberately: repo-wide the rule reports ~86k violations across 1437 identifiers, almost all legitimate cross-module namespaces (AscCommon, AscDFH, Asc, AscFormat), which would need a globals list larger than the rule is worth. browser is set to false for these files because they provide the browser globals rather than consuming them; leaving it on makes every stub read as a redeclaration of a built-in. The three host globals injected by the converter before any script runs are declared instead, with references to where core installs them. jquery_native.js is ignored, matching tests/code-style/check.py. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: James Manuel <moodyjmz@users.noreply.github.com>
|
CI has now run, and the guard behaves exactly as intended.
Two caveats in the
|
Merge #65 before this PR#65 (the Grunt → webpack build migration) touches two of the same files, and one of them is a guaranteed conflict. It's the larger, older PR and it's green — this one should rebase onto it, not the other way round. 1.
Whichever lands second conflicts, and the reflexive "take theirs" resolution silently discards the other side's intent. The resolution must be the union of both lists — #65's entries are the useful baseline for any future repo-wide lint, and this PR's single entry is what the scoped Worth noting the two are complementary rather than redundant: #65 adds an 2. Correction to this PR's descriptionThe body states that No functional impact on this PR: Suggested order
|
Follow-up to #67. Merge #67 first — see "Expected CI state" below.
Why
common/Native/stubswindow,document,navigator,console,setTimeoutandperformancefor the embedded JS context that DoctRenderer/x2t runs. It is the one part of this tree that no test ever executes:tests/runAll.jsand theunit-testsjob drive QUnit in a real browser vianode-qunit-puppeteer, where these stubs are never loaded and the real platform objects are used instead.So an undeclared identifier in these files reaches production entirely unexercised. That is exactly how
console.errorcame to reference an undeclaredparamand abort every converter operation that logged an error — silent save failure, ExitCode 86, data loss. Five weeks of dormancy, then production.no-undefcatches it..eslintrc.yamldid not enable it, and nothing ran eslint at all — there is no eslint reference inbuild/package.json, no rootpackage.json, and thecode-stylejob only rantests/code-style/check.py(license headers, LF endings, trailing newline).Proof it's a real guard
Against
mainas it stands today:With #67's one-word fix applied: clean, exit 0. One error, the right error, no noise.
Why it's scoped to common/Native
Repo-wide,
no-undefreports 85,854 violations across 1,437 distinct identifiers, measured per directory (common 26,446 / word 27,779 / cell 15,658 / slide 7,574 / pdf 6,543 / visio 1,854). The top offenders are legitimate cross-module namespaces:AscCommonAscDFHAscAscFormatAscCommonExcelMaking that green would need a globals list larger than the rule is worth, so this PR does not attempt it. Widening the scope later is a separate conversation with a separate cost.
Why
browser: falseCounter-intuitive but load-bearing. These files provide the browser globals rather than consuming them. With
browser: truethe existingno-redeclarerule fires on every stub —navigator,document,console,setTimeout,setInterval,clearTimeout,clearInterval,performance,Image— and buries the one real defect in eleven false ones. I hit exactly that while building this; the first draft reported 12 problems, of which 11 were noise.With
browser: false, the three globals the converter genuinely injects before any script runs are declared explicitly, each pointing at wherecoreinstalls it:window(the global object itself)doctrenderer.cpp:579—global_js->set("window", global_js)nativedoctrenderer.cpp:583—global_js->set("native", oNativeCtrl)CreateEmbedObjectjs_internal/v8/v8_base.cpp:218—InsertToGlobal(...)Split into two per-file override blocks because
native.jsdeclaresAsc/AscCommon/AscFormat/AscDFHitself, whereasnative_graphics.jsconsumesAscCommonfrom it —editors.cpp(GetAllScript) concatenates them in that order. DeclaringAscCommonglobally for both would tripno-redeclareonnative.js's ownvar AscCommon = {}.jquery_native.jsis ignored via.eslintignore, matchingtests/code-style/check.py's ownexclude_files.Expected CI state
code-stylewill fail on this branch until #67 merges, with exactly:That failure is the demonstration, not a defect in this PR. Merge #67, and this goes green with no changes.
Divergence cost
.eslintrc.yamland.github/workflows/check-build.ymlboth exist upstream, so this is real fork divergence. It is confined to anoverrides:block appended to the end of one file and one step added to one job — upstream touches neither often — and.eslintignoreis a new file, so it cannot conflict. Judged worth it: the alternative is relying on nobody ever again writing an undeclared identifier in the only directory CI cannot reach.