fix(lint): check no longer fails projects that inline the GSAP library by miguel-heygen · Pull Request #6018 · heygen-com/hyperframes · GitHub
Skip to content

fix(lint): check no longer fails projects that inline the GSAP library - #6018

Open
miguel-heygen wants to merge 9 commits into
mainfrom
fix/lint-inlined-gsap-determinism
Open

miguel-heygen wants to merge 9 commits into
mainfrom
fix/lint-inlined-gsap-determinism

Conversation

@miguel-heygen

@miguel-heygen miguel-heygen commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

What

hyperframes check failed any project that pastes the GSAP library inline (for example GSAP 3.14.2 in a caption template layer). non_deterministic_code scanned GSAP's own source and reported its internals: Math.random() in utils.shuffle/utils.random and Date.now() in its ticker. Because the finding is an error, check also skipped its render pass on those projects, and the author had no way to clear it short of removing GSAP.

Fix

blankInlinedGsapLibrary (packages/lint/src/utils.ts) parses the script with acorn and blanks GSAP's own code with spaces, so offsets and reported lines stay correct. non_deterministic_code then scans what is left, as before.

GSAP's code is a call anywhere in the tree that has GSAP's UMD wrapper structure: a function expression that reads the real member define.amd in its own body (not inside a nested function), called with exactly (this, function …). Each GSAP banner (/*! … GreenSock … */) or producer /* inlined: <src> */ comment whose <src> URL path is an npm gsap dist file (gsap[@version]/dist/<file>.js; a name that only contains gsap does not count) belongs to at most one wrapper. First choice is the wrapper that starts right after it, skipping only whitespace, comments, !, ; and ( (minified builds, producer comments, statement separators). A banner anywhere else owns nothing. Only wrappers that own a banner are blanked, and only their own call range.

What stays checked:

  • author code before or after the library, in the same statement (comma-joined), or in an outer IIFE, two-argument wrapper or UMD bundle around it
  • an outer wrapper that has define.amd only inside a nested library
  • an outer bundle around GSAP, even when a producer comment, a ; separator or a stray banner sits inside it
  • define.amd that appears only as text, in a string or a comment
  • a wrapper whose banner is separated from it by other code, or that has no banner
  • a script that only mentions GreenSock in a string or comment, or that fails to parse

Known limits:

  • A hand-built copy of GSAP's wrapper and banner around author code is exempt. Proving the code really is GSAP would mean pinning file contents per GSAP version and plugin. That breaks on every release and on any re-minified copy, which brings this false positive back. This rule is already text-level and easy to bypass on purpose (Math["random"]()); the aim is that nothing is exempted by accident.
  • Unminified GSAP files pasted inline are still flagged, as on main: their banner sits inside the Rollup factory, which is exactly where a bundler also puts author code that imports GSAP, so the two cannot be told apart without pinning file contents. The minified builds (gsap.min.js and every plugin's .min.js), and any copy the producer inlines with its /* inlined: */ comment, are exempt. Caption templates inline gsap.min.js.

missing_gsap_script is unchanged. It answers a different question (is GSAP loaded anywhere), where a loose marker match is the right call.

Proof

  • 23 tests in packages/lint/src/rules/core.test.ts use GSAP 3.14.2's real UMD wrapper, banner and internals. Proof runs:

    • with main's rule, the 4 library tests fail (pasted, producer-inlined, author script beside GSAP, author code before and after GSAP in one tag)
    • with this PR's first head (whole-script skip on any marker), the 5 regressions fail: same-tag author code, a "GreenSock" string, a comment, a spoofed banner, a spoofed inlining comment
    • with the second head (define.amd text check over a whole top-level statement), the 4 regressions from the second review fail: comma-joined author code, author code in an outer IIFE, and define.amd in a string and in a comment
    • with the third head (banner anywhere inside a call; define.amd found in nested functions), the 4 regressions from the third review fail: a two-argument outer wrapper, an outer UMD bundle around minified or unminified GSAP, and an outer wrapper that borrows define.amd
    • with the fourth head (banner falls back to any enclosing wrapper; adjacency skipped only whitespace and !), the 4 regressions from the fourth review fail: GSAP after a ; separator, producer-inlined unminified GSAP in a bundle, separated GSAP in a bundle, a stray banner in a bundle
      • with the fifth head (banner falls back to the innermost enclosing wrapper that wraps no other), the Rollup regression fails: a real Rollup 4 ESM-to-UMD bundle of GSAP plus Math.random() / Date.now() reports nothing
      • with the sixth head (any inlined: source containing gsap counts), the 3 regressions from the sixth review fail: a Rollup/Terser bundle inlined from gsap-composition.js, scene.js?vendor=gsap and another domain's gsap-demo/scene.js
    • mutations: skipping only whitespace and ! fails the 2 separator tests; letting the fallback own a wrapper that wraps another fails the stray-banner test
    • mutations: letting the define.amd search enter nested functions fails only the borrowed-define.amd test; choosing the outermost containing wrapper fails only the unminified-in-bundle test; dropping the adjacent-banner owner fails the 8 tests that use minified GSAP
  • All 25 minified dist/*.min.js files of gsap@3.14.2 lint clean. The full 246 KB Rollup bundle of GSAP plus author code reports both author calls (none on the previous head); the same bundle of author code alone reports both too. Lint time for the whole matrix, back to back on one box: 13.96–14.84 s here vs 13.82–13.89 s on main.

  • The fourth review's probes with the real, unchanged gsap@3.14.2 files inside an outer UMD bundle (producer-inlined gsap.js + author call; ;-separated gsap.min.js + author call): this branch reports only the author's line; GSAP alone in the bundle reports nothing. main reports GSAP's own lines in every case.

  • Real files linted at main vs this branch:

    Input main this branch
    full gsap.min.js 3.14.2 inline Math.random(), Date.now() none
    full unminified gsap.js 3.14.2 inline Math.random(), Date.now() Math.random(), Date.now() (known limit)
    gsap.min.js plus window.seed = Math.random() in the same tag GSAP's line only the author's line
    a real caption template project (GSAP 3.14.2 inline) Math.random(), Date.now() none

    Lint time moved by 10–20 ms on these inputs, within run-to-run noise.

  • Whole lint suite: 983 passed. core and utils test files: 3 runs in a row green. tsc, oxlint, oxfmt and fallow are clean.

non_deterministic_code skips a script that is GSAP itself (producer inlining comment
or GSAP banner), using the detector missing_gsap_script already had, now one shared
helper. The author's own Math.random/Date.now calls are still flagged.

@jrusso1020 jrusso1020 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed exact 6383f7e9fb1c807afe5e685c9b5f88731a28dac2 with an independent adversarial pass. Sharing the predicate preserves the old missing_gsap_script signals, and the new separate-script test checks author code beside the library.

[P1 blocker] Raw markers disable checking for arbitrary author code. packages/lint/src/utils.ts:563–568 matches GreenSock or _gsScope anywhere, including comments and string literals; packages/lint/src/rules/core.ts:943–946 then skips the whole script before stripping either. const label = "GreenSock"; const x = Math.random(); const now = Date.now(); produces zero non_deterministic_code findings; removing the label produces two. A spoofed producer banner also suppresses them. Genuine GSAP followed by author calls in the same script is unchecked too, as the body acknowledges. This affects ordinary author scripts without any library present, beyond that stated mixed-bundle limit.

Exempt only a verified library body and retain checks on author statements before/after it, or normalize known assets without giving arbitrary markers a whole-script exemption. Add negative regressions for innocent strings/comments, spoofed banners and real GSAP plus author calls in one tag.

Validation: parent and independent reviewer executed the exact-source extracted core callback and utility code with TypeScript stripped (unused parser imports removed). Plain random/time code produces two findings; string/comment/banner variants and real local GSAP 3.14.2 plus author calls produce none. Genuine GSAP alone is exempted. Read the four changed files/relevant context; no full lint suite, CLI render or exhaustive version/plugin matrix run.

Need: yes, avoid library false positives · Size: focused · Reuse: presence detection is reused, but does not establish a library exemption.

Verdict: REQUEST CHANGES
Reasoning: The whole-script exemption silently suppresses real author nondeterminism based only on an incidental marker.

— hf-review

Exempt the parsed GSAP UMD statement that carries its banner, not every script that
mentions GreenSock. Strings, comments, spoofed banners and author code before or after
the library in the same script are checked again.
@miguel-heygen

Copy link
Copy Markdown
Collaborator Author

Fixed at 11c37c3. You were right: a marker shows GSAP is present, but it cannot prove which code is GSAP.

The exemption is now a parsed span. Only a top-level UMD statement (define.amd) that has a GSAP banner or the producer's inlining comment directly before it (or inside it, in the unminified build) is blanked. Everything else in the script is scanned as before. missing_gsap_script is back to main.

I added the regressions you asked for. All 5 fail on 6383f7e and pass here: author code before and after real GSAP in one tag, a "GreenSock" string, a comment, a spoofed banner, a spoofed inlining comment. The spoofs use expression statements, so the UMD check is the only thing that rejects them; dropping it fails exactly those 2 tests.

With full real GSAP 3.14.2 plus window.seed = Math.random() in the same tag, this head reports the author's line. main reported only GSAP's line.

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 271 (base branch 271), smooth 182 of those

The gate passes.
Smoothness is reported in the artifact, not gated. A case fails only if it fails 2 of 3 runs.

Quarantined, measured but not gated (0)

Unstable (1)

  • seqplainkeys-none-px-r0-root-z100: tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo false, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true

@jrusso1020 jrusso1020 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed exact 7713b03aac6228a71cce9d06ecc817223ffd1d81, including the helper extraction pushed during this review; actual-rule probes rerun at this head. The earlier incidental string/comment cases and semicolon-separated author code before/after real GSAP are fixed. Acorn now provides statement boundaries, and missing_gsap_script is restored to main.

[P1 blocker] The parsed statement is still not a verified GSAP body. packages/lint/src/utils.ts:592–601 only requires an ExpressionStatement whose raw text contains define.amd, then exempts that whole statement. This contains no GSAP or UMD wrapper, yet produces zero nondeterminism findings:

/*! GreenSock */
window.seed = ("define.amd", Math.random());

The substring can also occur solely in a comment. A fabricated UMD wrapper with an author random call is exempt too. Thus the original spoofing failure remains after adding the second marker.

An independent pass also reproduced this with an ordinary outer IIFE containing genuine GSAP followed by window.seed = Math.random(): the nested banner and define.amd exempt the whole outer wrapper, including author code. This reproduced for 12 real GSAP 3.14.2 core/plugin files (minified and unminified).

The same boundary also swallows legitimate author code joined to genuine GSAP with a comma: replace the trailing semicolon of real gsap.min.js with , window.seed = Math.random();. Acorn makes both a single SequenceExpression statement, so the returned span includes and suppresses the author's call. Keeping a semicolon reports it correctly.

Please recognize the actual library expression/body rather than an entire marker-bearing statement, keep neighboring sequence-expression operands checked, and avoid granting arbitrary banners/wrappers a library identity (for example by verifying supported asset contents). Add wrapper and sequence-expression negatives above; checking raw define.amd is not structural UMD verification.

Validation: executed the exact-source core callback and utility code with TypeScript stripped and cached Acorn 8.17.0. Ordinary string/comment/banner-only cases and real GSAP plus a separate author statement report the author call; real GSAP alone is exempt. String/comment spoof variants, a fake wrapper and comma-joined real GSAP+author code all suppress it. Independent adversarial pass performed. No full lint suite, CLI render or exhaustive GSAP version/plugin matrix claimed.

Verdict: REQUEST CHANGES
Reasoning: The prior finding is partly repaired, but author nondeterminism can still be mistaken for GSAP internals through raw markers or a shared expression statement.

— hf-review

…ism check

Recognise GSAP's UMD wrapper by structure (factory IIFE called with this and a function,
with a real define.amd member) anywhere in the tree, and blank only that call. Author code
joined by a comma or wrapped in an outer IIFE is checked; define.amd text is not enough.
@miguel-heygen

Copy link
Copy Markdown
Collaborator Author

Fixed at 0830d41. Each probe you listed now reports the author's call:

  • Structural UMD check. The exempt node is now a CallExpression, found anywhere in the tree: a function expression whose body has a real define.amd member (not text), called with exactly (this, function …). It also needs a GSAP banner or the producer's inlining comment directly before it, or inside it. Only that call's range is blanked. ("define.amd", Math.random()) and /* define.amd */ no longer exempt anything.
  • Neighbours stay checked. Comma-joined real gsap.min.js with , window.seed = Math.random() reports the author's call, and so does real GSAP plus author code inside an outer IIFE.
  • All 12 core and plugin files and more: I ran all 51 dist/*.js files of gsap@3.14.2, each alone, comma-joined and inside an outer IIFE. 150/153 are as expected. The 3 misses are the unminified Draggable.js, which ships without a banner and stays flagged, as on main.
  • New tests: all 4 regressions from your review fail on 7713b03 and pass here. Dropping the shape check fails the outer-IIFE test, and dropping the banner check fails the separated-banner test.

One point I am not taking, with the reason in the PR body under "Known limits": a deliberately hand-built copy of GSAP's wrapper and banner around author code is still exempt. Verifying asset contents means pinning bytes per GSAP version and plugin. That breaks on every release and on any re-minified copy, which brings back the false positive this PR removes. The rule is already text-level and easy to bypass on purpose (Math["random"](), const M = Math; M.random()), so I am aiming at no accidental exemption, not at spoof-proofing. If you still want content pinning, say so and I'll take that tradeoff to the owner.

@jrusso1020 jrusso1020 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed exact 0830d41948ca82e4feb4026028745a1ee3f5671e, with a fresh independent adversarial pass. The prior incidental string/comment markers, comma-joined author calls, and no-argument outer IIFE cases now report the author call correctly. CallExpression ranges are a useful improvement over whole-statement exemption.

[P1 blocker] A containing bundle still inherits the nested GSAP call's identity. packages/lint/src/utils.ts:582–593 searches recursively through nested function bodies for define.amd, while :620–626 accepts any GSAP banner anywhere inside the candidate call. Consequently this ordinary containing wrapper is blanked in full:

(function (root, factory) {
  // Paste the genuine, unchanged gsap.min.js here, including its banner.
  window.seed = Math.random();
})(this, function () {});

With real GSAP 3.14.2, the actual helper returns both the inner library span and the entire outer call span; the actual nondeterminism callback reports no findings. Removing the outer arguments makes it report the author call. The outer function need not contain its own AMD logic: recursive traversal borrows it from GSAP. A real outer UMD bundle with its own AMD dispatch also reproduces via the nested banner. This is accidental exemption of mixed bundled author code, separate from the disclosed deliberate forgery of GSAP's complete banner/wrapper.

Bind the banner and AMD structure to the same library wrapper, excluding markers inherited solely from nested libraries, and avoid selecting enclosing mixed bundles. Add this two-argument enclosing-wrapper regression alongside the existing no-argument IIFE case.

Validation: read current helper/rule/tests, previous reviews and replies. Parent and independent actual-source probes reproduce the containing-wrapper failure. Twelve real minified/unminified GSAP core/plugin files remain exempt on their own; ordinary separate author code, plain outer IIFE and the former string/comment spoofs are checked. No full lint suite, CLI render or exhaustive version/plugin matrix run. Complete intentional forgery is acknowledged as a text-lint limitation and is not the basis of this blocker.

Verdict: REQUEST CHANGES
Reasoning: The earlier cases are repaired, but nested library markers can still grant an enclosing mixed bundle a whole-call exemption and hide real author nondeterminism.

— hf-review

…exemption

The define.amd check reads only the wrapper's own body, and each GSAP banner belongs to the
wrapper right after it, else the innermost one containing it. An outer wrapper or UMD bundle
around pasted GSAP keeps its author code checked.
@miguel-heygen

Copy link
Copy Markdown
Collaborator Author

Fixed at 6354982 by tying the banner and the AMD check to one wrapper:

  • AMD check: isUmdWrapperCall reads define.amd only in the wrapper's own body. The walk stops at nested functions, so an outer wrapper can no longer borrow GSAP's.
  • Banner owner: each banner belongs to exactly one wrapper. That is the one starting right after it (minified builds), or else the innermost wrapper containing it (unminified builds, where the banner sits inside the factory). Only owning wrappers are blanked.

The new regressions all fail on 0830d41 and pass here:

  • your two-argument containing wrapper around pasted GSAP plus author code
  • an outer UMD bundle with its own AMD dispatch around minified GSAP
  • the same bundle around unminified-style GSAP
  • an outer wrapper whose only define.amd is GSAP's

Each rule has its own mutation: letting the walk enter nested functions fails the borrowed-define.amd test, and picking the outermost wrapper fails the unminified-in-bundle test. All 51 real gsap@3.14.2 dist files behave as before (150/153; the 3 are the bannerless unminified Draggable.js). 438 lint tests pass, 3 runs in a row.

@jrusso1020 jrusso1020 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed exact 6354982c8d82739f79fce9310c876de3db88ee9e, including a fresh independent adversarial pass. Own-body AMD traversal fixes borrowed nested define.amd; the previous unmodified minified/unminified nested-bundle witnesses now report the author call.

[P1 blocker] The banner-owner fallback still exempts a containing author bundle. packages/lint/src/utils.ts:614–617 falls back to the smallest enclosing UMD whenever adjacency lookup fails, even when the banner actually introduces a nested library. This happens with an unchanged, supported asset:

(function (root, factory) {
  if (typeof define === "function" && define.amd) define([], factory);
  else factory();
})(this, function () {
  /* inlined: https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.js */
  // Paste the genuine, unchanged unminified dist/gsap.js here.
  window.seed = Math.random();
});

With actual gsap@3.14.2 bytes, the helper returns both the inner library span and the entire outer call, and the actual nondeterminism callback returns zero findings. Without the producer comment, the author's call is correctly reported. The producer comment precedes (, while Acorn's inner call start is at function; failed adjacency assigns that comment to the outer UMD. The library's own internal banner separately identifies the inner call. No invented GSAP wrapper/banner or modification to the library is required.

The same fallback also swallows author code when the real minified library's wrapper receives an ordinary concatenation separator (;!function instead of !function) after its banner. Please distinguish a banner introducing a nested call from a banner inside that call's factory; do not grant the enclosing mixed bundle ownership merely because adjacency matching failed. Add the unchanged producer-inlined unminified asset case and a separator variant as negative controls.

Validation: parent and independent reviewer reproduced this with exact-source utils and core callback, TypeScript stripped, cached Acorn 8.17.0/acorn-walk. Twelve real minified/unminified core/plugin files remain exempt alone; separate author statements, ordinary outer IIFEs and the previous two-argument wrapper, string/comment and comma cases are checked. Read current helper/rule/tests, existing reviews and author reply. No full authored lint suite, CLI render or exhaustive version/plugin matrix claimed. Intentional complete wrapper forgery remains the disclosed text-lint limitation and is not this finding.

Verdict: REQUEST CHANGES
Reasoning: Earlier witnesses are repaired, but a normal producer comment around an unchanged library still assigns its enclosing mixed bundle a whole-call exemption.

— hf-review

…nd GSAP

A banner introduces the wrapper after it across whitespace, ! ; ( and comments, so producer
comments and statement separators bind to GSAP itself. The fallback owner for a banner
inside a wrapper must wrap no other wrapper, so a bundle around GSAP never inherits it.
@miguel-heygen

Copy link
Copy Markdown
Collaborator Author

Fixed at 87570ed. You were right that the fallback was the hole. Two changes in bannerOwner:

  • Adjacency skips the real separators. From a banner, the scan skips whitespace, comments, !, ; and (, so a producer comment before (function (global, factory) and a ;!function after a banner both bind to GSAP's own wrapper.
  • The fallback cannot pick a bundle. A banner that introduces no wrapper falls back to the innermost wrapper containing it, but only if that wrapper wraps no other wrapper. GSAP's own wrapper never wraps one, and a bundle around GSAP always does, so a bundle never inherits ownership.

Your negative controls are in the tests and fail on 6354982: producer-inlined unminified GSAP in a UMD bundle, ;-separated GSAP alone and in a bundle, plus a stray banner in a bundle. Each rule has its own mutation.

Your probes with the real, unchanged gsap@3.14.2 bytes:

  • an outer UMD bundle around producer-inlined gsap.js plus author code, and around ;-separated gsap.min.js plus author code: this head reports only the author's line
  • the same bundles without author code: nothing reported

The 51-file matrix is unchanged at 150/153 (the bannerless unminified Draggable.js). 443 lint tests pass, 3 runs in a row.

@jrusso1020 jrusso1020 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed exact 87570ed431cc54a3fc666bea329750ca7e9f5331. The prior unchanged-UMD producer-comment and separator witnesses now report the author call; rejecting enclosing wrappers with another nested wrapper repairs those cases.

[P1 blocker] An ordinary flat Rollup bundle still receives a whole-bundle exemption. packages/lint/src/utils.ts:615–621 assumes that an enclosing UMD with no nested qualifying UMD wrapper is the library. Standard ESM bundling does exactly that to mixed library/author code. Reproduction, using genuine gsap@3.14.2:

import { gsap } from "gsap";
export { gsap };
window.authorSeed = Math.random();
window.authorTime = Date.now();

Build with Rollup 4.64.5, --format umd --name Composition, and inline the generated file. Rollup retains GSAP's genuine license inside its sole UMD factory, with both author assignments at the end. There is no inner UMD because GSAP entered as ESM. wrapsAnother is false, so the helper exempts the entire generated call. Parent independently regenerated a 246,319-byte bundle: exemption span [0,246318], zero nondeterminism findings, including neither author assignment. The same Rollup build of author-only code produces both findings. Fresh independent reviewer reproduced the mixed build too. No invented banner/wrapper or edited library is needed; this is separate from the disclosed deliberate forgery limit.

Do not infer library ownership from the absence of another UMD wrapper. Bound the exemption to demonstrable library code, or conservatively leave ambiguous flattened mixed bundles checked. Add an actual Rollup ESM-GSAP-plus-author fixture/regression, preserving the existing raw UMD positives and author-only control.

Validation: parent reran the current-source helper and actual core-rule callback with cached Acorn/acorn-walk and TS stripped. Twelve real minified/unminified core/plugin assets, their comma/IIFE neighbors and the earlier producer/separator cases were checked. The source and new regressions were read; no full authored lint suite, CLI render, exhaustive version/plugin matrix or author-reported perf matrix run claimed.

Verdict: REQUEST CHANGES
Reasoning: Earlier witnesses are repaired, but normal ESM-to-UMD bundling still turns GSAP's authentic license into an exemption for neighboring author nondeterminism.

— hf-review

A GSAP banner now exempts only the UMD wrapper call that starts right after
it (skipping whitespace, comments, `!`, `;` and `(`). The fallback that gave
a banner to the innermost enclosing wrapper is gone: Rollup's UMD output for
an ESM import of GSAP keeps the banner inside the one factory it shares with
author code, so that fallback exempted the whole bundle, author
Math.random() and Date.now() included.

Tradeoff: unminified dist/gsap.js pasted inline has its banner inside its
own factory, so it is flagged again, as on main. The minified gsap.min.js
and producer-inlined copies stay exempt.
@miguel-heygen

Copy link
Copy Markdown
Collaborator Author

Fixed at the root in 9b8f358. A GSAP banner now belongs only to the UMD wrapper call that starts right after it (skipping whitespace, comments, !, ;, (). The fallback to an enclosing wrapper is gone, so no wrapper inherits an exemption from a banner inside its factory, which is what Rollup's ESM-to-UMD output does with GSAP plus author code.

  • New regression: an excerpt of real Rollup 4 UMD output (import { gsap } from "gsap" plus window.authorSeed = Math.random(); window.authorTime = Date.now();). It reports both calls, and returns [] with the previous head's utils.ts (3 tests fail there: this one and the two unminified-GSAP tests below).
  • The full 246,324-byte bundle now reports both author calls; the author-only bundle reports both too.
  • Taking your "leave ambiguous flattened bundles checked" option: unminified dist/gsap.js pasted inline has its banner inside its own factory, so it is flagged again, as on main. Minified gsap.min.js (all 25 dist/*.min.js lint clean) and producer-inlined copies stay exempt; the caption templates that hit the original false positive inline gsap.min.js. Body updated with the limit.
  • Lint suite 983/983; core.test.ts 180/180.

@jrusso1020 jrusso1020 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed exact 458aafe2357022a4bf07f735f36140172c5f00f5 with a fresh independent adversarial pass. Removing the enclosing-wrapper fallback fixes the previous raw Rollup witness, and the earlier comma, outer-wrapper, separator and incidental string/comment cases remain checked. Conservatively checking raw unminified GSAP is now documented and covered.

[P1 blocker] The producer source-name marker still grants an ordinary mixed bundle a whole-call exemption. packages/lint/src/utils.ts:567 accepts any inlined: source containing gsap; :616 then assigns its adjacent UMD call as library code. Reproduction with genuine GSAP ESM:

import { gsap } from "gsap";
export { gsap };
window.authorSeed = Math.random();
window.authorTime = Date.now();

Build with Rollup UMD, then ordinary default Terser minification. Prefix the result with the producer's normal /* inlined: gsap-composition.js */ comment. The current helper exempts [36,70323], the whole generated call, and the actual rule reports zero findings. Identical minified bytes prefixed /* inlined: composition.js */ have no exemption and report both APIs. scene.js?vendor=gsap and https://example.com/gsap-demo/scene.js also suppress them. No wrapper/banner is forged: Rollup/Terser supply the ordinary UMD and the producer automatically supplies /* inlined: ${src} */ for external scripts (packages/producer/src/services/htmlCompiler.ts:1280). Parent independently reran the witness and controls.

Please stop treating a GSAP substring anywhere in a script URL/name as library identity. Restrict producer-marker recognition to supported library artifacts, or leave ambiguous author bundles checked, and add the real minified mixed-bundle + producer-comment regression with the otherwise-identical filename control. This remains accidental mixed-code exemption, separate from the disclosed deliberate reconstruction of a library wrapper/banner.

Validation: all 24 extracted added regression cases pass through the exact rule/helper with lightweight script extraction; previous-utils control fails the expected three changed cases. Independent controls passed 156 cases including all 25 real GSAP 3.14.2 minified core/plugin assets and surrounding author code, plus fresh Rollup/five Terser variants without the misleading source-name prefix. Read the current helper, rule integration, added tests, prior reviews/replies and actual producer prefix path. No full lint suite, CLI render, exhaustive version or performance matrix claimed.

Verdict: REQUEST CHANGES
Reasoning: The internal-license fallback is repaired, but an ordinary GSAP-containing filename or URL still hides author nondeterminism in producer-inlined minified bundles.

— hf-review

…dle it heads

The producer's inlined-source comment now marks library code only when its
URL path is an npm gsap dist file (gsap or gsap@<version>, then /dist/<file>.js,
query and hash ignored). A Rollup/Terser bundle of GSAP plus author code
inlined from gsap-composition.js, scene.js?vendor=gsap or another domain's
gsap-demo/scene.js keeps its own Math.random() and Date.now() checked.
@miguel-heygen

Copy link
Copy Markdown
Collaborator Author

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants