max / makenotwork
- Co-Authored-By
- Claude Opus 5 (1M context) <noreply@anthropic.com>
1 file changed,
+103 insertions,
-6 deletions
| @@ -25,7 +25,32 @@ | |||
| 25 | 25 | //! Both halves are fixed here: both trees are read, and an alias bound to | |
| 26 | 26 | //! `window` in a file is followed within that file. `HIGH_WATER` was restated | |
| 27 | 27 | //! once against the corrected measurement, which is not the same act as raising | |
| 28 | - | //! it. It has not moved since and must not. | |
| 28 | + | //! it. | |
| 29 | + | //! | |
| 30 | + | //! # The third gap, and the number moved a second time | |
| 31 | + | //! | |
| 32 | + | //! Problem `82315c45`, 2026-08-26. The two rules above both match an | |
| 33 | + | //! *assignment*, and a classic script does not need one: a bare top-level | |
| 34 | + | //! `function foo() {}` becomes a property of the global object just by being | |
| 35 | + | //! declared. Every `static/*.js` file is loaded by a plain `<script src>` -- | |
| 36 | + | //! all 61 tags in `templates/`, none carrying `type="module"` -- so all 55 of | |
| 37 | + | //! those declarations were globals this test could not see. | |
| 38 | + | //! | |
| 39 | + | //! Found by deleting one. `static/tab-item-sales.js` declared exactly one | |
| 40 | + | //! function, was called by name from `data-action`, and went whole in | |
| 41 | + | //! `1ea96868`. The seal did not move, which is the same false-progress failure | |
| 42 | + | //! `7df1a7de` was about, wearing a different hat. | |
| 43 | + | //! | |
| 44 | + | //! **The rule is per tree, and that is the point.** A top-level function in an | |
| 45 | + | //! ES module under `frontend/src` is scoped to the module and is not a global, | |
| 46 | + | //! so [`count_script_globals`] runs only over `static/*.js` while | |
| 47 | + | //! [`count_globals`] runs over both. Applying it everywhere would have counted | |
| 48 | + | //! the typed tree's own functions as the surface the typed tree exists to | |
| 49 | + | //! remove. | |
| 50 | + | //! | |
| 51 | + | //! `HIGH_WATER` was restated a second time against this. Neither restatement | |
| 52 | + | //! raised the ratchet: both corrected what it can see. It must not move for any | |
| 53 | + | //! other reason. | |
| 29 | 54 | ||
| 30 | 55 | use std::fs; | |
| 31 | 56 | use std::path::{Path, PathBuf}; | |
| @@ -76,7 +101,11 @@ | |||
| 76 | 101 | /// `saveLinkBtn` and `cancelLinkBtn` existed only because one template would | |
| 77 | 102 | /// not include the other. The include is the whole fix; the row's surviving | |
| 78 | 103 | /// verbs live in `actions-partials.js` and serve both paths. | |
| 79 | - | const HIGH_WATER: usize = 106; | |
| 104 | + | /// 161 on 2026-08-26, the second restatement and not progress. Problem | |
| 105 | + | /// `82315c45`: 55 bare top-level `function` declarations in `static/*.js` are | |
| 106 | + | /// globals in a classic script and had never been counted. 106 + 55 = 161. The | |
| 107 | + | /// surface did not change that day either; what this test can see did. | |
| 108 | + | const HIGH_WATER: usize = 161; | |
| 80 | 109 | ||
| 81 | 110 | /// Every file whose global assignments count: the legacy scripts and the typed | |
| 82 | 111 | /// modules that replaced them. | |
| @@ -134,6 +163,28 @@ | |||
| 134 | 163 | } | |
| 135 | 164 | } | |
| 136 | 165 | ||
| 166 | + | /// Count bare top-level function declarations, in one CLASSIC-script file. | |
| 167 | + | /// | |
| 168 | + | /// `82315c45`. A `<script src>` with no `type="module"` shares the global | |
| 169 | + | /// scope, so `function foo() {}` at the top level of one lands `foo` on the | |
| 170 | + | /// global object without ever writing an assignment. Neither rule in | |
| 171 | + | /// [`count_globals`] can see that, and 55 of this server's globals are that | |
| 172 | + | /// shape. | |
| 173 | + | /// | |
| 174 | + | /// **Only for `static/*.js`.** The same declaration in an ES module under | |
| 175 | + | /// `frontend/src` is scoped to the module and is not a global, so counting it | |
| 176 | + | /// there would charge the typed tree for the surface it exists to remove. | |
| 177 | + | fn count_script_globals(src: &str) -> usize { | |
| 178 | + | // Column zero is the whole test for "top level", and it is enough because | |
| 179 | + | // every one of the 55 is written that way. A declaration indented inside an | |
| 180 | + | // IIFE is correctly not counted: that is a function scope, not the global | |
| 181 | + | // object. A regex cannot know the difference and does not have to. | |
| 182 | + | regex::Regex::new(r"(?m)^(?:async )?function [A-Za-z_][A-Za-z0-9_]*\s*\(") | |
| 183 | + | .unwrap() | |
| 184 | + | .find_iter(src) | |
| 185 | + | .count() | |
| 186 | + | } | |
| 187 | + | ||
| 137 | 188 | /// Count assignments that land a name on `window`, in one file. | |
| 138 | 189 | /// | |
| 139 | 190 | /// Two forms, because the code uses two. The direct `window.foo = …` is what | |
| @@ -144,6 +195,9 @@ | |||
| 144 | 195 | /// The alias is followed only inside the file that binds it, and only when it | |
| 145 | 196 | /// was bound to `window` itself, so a local named `w` holding anything else | |
| 146 | 197 | /// contributes nothing. | |
| 198 | + | /// | |
| 199 | + | /// Runs over both trees, unlike [`count_script_globals`]: an assignment to | |
| 200 | + | /// `window` is a global wherever it is written. | |
| 147 | 201 | fn count_globals(src: &str) -> usize { | |
| 148 | 202 | // `=[^=]` matches an assignment `=` while excluding the first `=` of a | |
| 149 | 203 | // comparison operator. The regex crate has no lookahead, so this is the | |
| @@ -168,18 +222,61 @@ | |||
| 168 | 222 | fn frontend_globals_do_not_grow() { | |
| 169 | 223 | let count: usize = sources() | |
| 170 | 224 | .iter() | |
| 171 | - | .map(|path| count_globals(&fs::read_to_string(path).unwrap_or_default())) | |
| 225 | + | .map(|path| { | |
| 226 | + | let src = fs::read_to_string(path).unwrap_or_default(); | |
| 227 | + | // A bare top-level function is a global only in a classic script, | |
| 228 | + | // which is what `static/` holds and `frontend/src` does not. See | |
| 229 | + | // `count_script_globals`. | |
| 230 | + | let classic = path.parent().and_then(Path::file_name) == Some("static".as_ref()); | |
| 231 | + | count_globals(&src) | |
| 232 | + | + if classic { | |
| 233 | + | count_script_globals(&src) | |
| 234 | + | } else { | |
| 235 | + | 0 | |
| 236 | + | } | |
| 237 | + | }) | |
| 172 | 238 | .sum(); | |
| 173 | 239 | ||
| 174 | 240 | assert!( | |
| 175 | 241 | count <= HIGH_WATER, | |
| 176 | - | "global assignments across static/*.js and frontend/src rose to {count} \ | |
| 242 | + | "globals across static/*.js and frontend/src rose to {count} \ | |
| 177 | 243 | (HIGH_WATER {HIGH_WATER}). New frontend code must be a typed ES module in \ | |
| 178 | - | frontend/src registered through the dispatcher, not a global. If you REMOVED \ | |
| 179 | - | globals, lower HIGH_WATER to {count}." | |
| 244 | + | frontend/src registered through the dispatcher, not a global -- and note \ | |
| 245 | + | that a bare top-level `function` in a classic script is one too. If you \ | |
| 246 | + | REMOVED globals, lower HIGH_WATER to {count}." | |
| 180 | 247 | ); | |
| 181 | 248 | } | |
| 182 | 249 | ||
| 250 | + | #[test] | |
| 251 | + | fn the_seal_sees_a_bare_top_level_function_in_a_classic_script() { | |
| 252 | + | // `82315c45`. The shape that was invisible until 2026-08-26: no assignment | |
| 253 | + | // anywhere, and `exportItemSalesCSV` was still a global the dispatcher | |
| 254 | + | // called by name. | |
| 255 | + | assert_eq!( | |
| 256 | + | count_script_globals("function exportItemSalesCSV() {\n}\n"), | |
| 257 | + | 1 | |
| 258 | + | ); | |
| 259 | + | assert_eq!(count_script_globals("async function loadThing(id) {}"), 1); | |
| 260 | + | ||
| 261 | + | // Two shapes that are NOT the global scope, and must not be counted. | |
| 262 | + | assert_eq!( | |
| 263 | + | count_script_globals("(function () {\n function inner() {}\n})();"), | |
| 264 | + | 0, | |
| 265 | + | "a declaration inside an IIFE is a function scope" | |
| 266 | + | ); | |
| 267 | + | assert_eq!(count_script_globals("const f = function named() {};"), 0); | |
| 268 | + | } | |
| 269 | + | ||
| 270 | + | #[test] | |
| 271 | + | fn the_two_counters_do_not_double_count_one_name() { | |
| 272 | + | // A file that both declares and assigns is two globals by two routes, and | |
| 273 | + | // the seal should say two rather than collapsing them. The point is that | |
| 274 | + | // neither counter reaches into the other's shape. | |
| 275 | + | let src = "function draw() {}\nwindow.draw = draw;\n"; | |
| 276 | + | assert_eq!(count_script_globals(src), 1); | |
| 277 | + | assert_eq!(count_globals(src), 1); | |
| 278 | + | } | |
| 279 | + | ||
| 183 | 280 | #[test] | |
| 184 | 281 | fn the_seal_sees_a_global_assigned_through_an_alias() { | |
| 185 | 282 | // The hole `7df1a7de` names, as a unit. Without this the count is a |