Skip to content

fix(types): move timer declarations into declare-global so bare calls resolve them - #8828

Open
axuj wants to merge 1 commit into
lynx-family:developfrom
axuj:fix/global-timer-declarations
Open

fix(types): move timer declarations into declare-global so bare calls resolve them#8828
axuj wants to merge 1 commit into
lynx-family:developfrom
axuj:fix/global-timer-declarations

Conversation

@axuj

@axuj axuj commented Aug 24, 2026

Copy link
Copy Markdown

Problem

The four timer declarations in js_libraries/types/types/common/global.d.ts sit outside the file's declare global {} block. That file is a module (top-level imports), so these module-scoped declare functions are private — bare-global call sites in application code never resolve to them. Every ReactLynx/Rspeedy project instead falls back to injected @types/node or DOM signatures, which accept forwarded extra args.

Lynx host timers actually drop forwarded args and fire the callback zero-arg (core/runtime/js/bindings/js_app.cc, core/runtime/lepusng/napi/worklet/napi_lepus_lynx.cc — both consume only callback+delay and invoke with an empty arg list), so code like setTimeout(fn, ms, arg) passes typecheck yet silently breaks on device.

Our project hit this exact bug: a bottom-sheet close callback scheduled via setTimeout(fn, duration, target, dismiss, generation) worked on web and never fired on device, leaving UI state stuck (icon never reset).

Evidence in this repo

examples/vanilla/src/rspeedy-env.d.ts already works around it by hand:

import type { LynxSetTimeout } from '@lynx-js/types';
declare global { const setTimeout: LynxSetTimeout; }

Fix

Move the four declarations inside the existing declare global {} block so they reach global scope. Signatures unchanged; misleading parameter name number renamed to delay.

Validation

npm run after proves both halves of the fix: bare two-arg calls resolve against the mounted declarations, and forwarded-extra-arg calls fail typecheck with TS2554, matching real device behavior.

… resolve them

common/global.d.ts is a module (it imports SystemInfo et al.), and the four
bare 'declare function' timer declarations sat OUTSIDE its declare-global
block. Module-scoped declarations are private: bare-global call sites in
application code never resolved to them — every ReactLynx/Rspeedy project
silently fell back to @types/node or DOM signatures instead, which accept
forwarded extra args that Lynx host timers actually drop (js_app.cc /
napi_lepus_lynx.cc fire the callback zero-arg), so forwarded calls pass
typecheck yet break on device.

Move the four declarations inside declare-global (signature unchanged,
misleading parameter name 'number' renamed to 'delay') and document the
two-arg contract.
@cla-assistant

cla-assistant Bot commented Aug 24, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

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.

1 participant