Commit Graph
172 Commits
Author SHA1 Message Date
SGavrl b744b9b437 Honor Fetch credentials across origins 2026-07-31 03:52:05 +00:00
SGavrl 5c34e74f10 Connect document font faces to rendering 2026-07-31 03:31:21 +00:00
SGavrl 9455d18439 Allow reusing disconnected intersection observers 2026-07-31 02:56:06 +00:00
SGavrl bae1259afe Track responsive image candidates in lifecycle 2026-07-31 01:55:25 +00:00
SGavrl c5210b1684 Connect image elements to render resources 2026-07-31 01:32:19 +00:00
SGavrl 90ed9afcad Clone DOM elements without reparsing 2026-07-31 00:54:22 +00:00
SGavrl f61493fbd1 Reject unsuccessful script responses 2026-07-30 23:25:09 +00:00
SGavrl 10b8492116 Improve modern layout and viewport rendering 2026-07-30 20:24:57 +00:00
SGavrl fa6503c560 dom: apply dynamically linked stylesheets 2026-07-26 22:33:36 +00:00
SGavrl 9c71700824 dom: support live select option construction 2026-07-26 22:11:29 +00:00
SGavrl 9ffc071ce0 dom: settle async inline style updates 2026-07-26 21:31:14 +00:00
SGavrl 9dfc67af74 dom: expose browser window constructor identity 2026-07-26 20:07:45 +00:00
SGavrl 3d02525f35 dom: expose media text track cues 2026-07-26 14:50:57 +00:00
SGavrl ec5950da06 dom: deliver standalone event target listeners 2026-07-26 14:27:29 +00:00
SGavrl 3618549842 render: unify responsive geometry and inline gradients 2026-07-26 11:51:44 +00:00
SGavrl 29d0bce3f5 render: expose WebGL as unavailable without backend 2026-07-26 11:14:43 +00:00
SGavrl 228a5723ce render: support modern framework content and geometry 2026-07-26 10:50:31 +00:00
SGavrl 5de5d07c24 render: support streamed framework hydration
Make attribute maps live, preserve parser script execution state, and expose
element scrolling used by React commit callbacks. Connect fallback web streams
so React Router and Remix hydration payloads flow through codec transforms.
2026-07-23 10:59:51 +00:00
SGavrl 2652ee64a4 render: real-world CSS rendering parity
Colors: oklch()/oklab() and color-mix(); linear-gradient backgrounds.
Grid: named-line placement, repeat() expansion, drop whitespace-only
grid items; upgrade taffy 0.7 -> 0.12 so aspect-ratio images in
auto-height rows no longer collapse to slivers.
CSS: @layer, nesting, @property, :is()/:where(), clamp(), @media not all;
source/track/param/area and svg desc/metadata as display:none.
Images: webp + intrinsic sizing, srcset/picture, browser UA + Accept for
CDN fetches, grey placeholder on failure; width/height HTML attributes
rank below author CSS with aspect-ratio preserved for auto axes.
2026-07-11 19:52:36 +00:00
SGavrl 399181b975 render: expose real geometry to JS behind the render feature
getBoundingClientRect, offsetWidth/Height, and offsetTop/Left now read
real box geometry from the obscura-render layout cache when the render
feature is compiled in. elementFromPoint inherits correct hit-testing
because it already delegates to getBoundingClientRect per element.

Adds a render feature on obscura-js (propagated through obscura-browser
and obscura-cli), a lazily-computed layout cache and viewport in
ObscuraState (feature-gated, cleared on navigation), and an
op_layout_geometry op. bootstrap.js probes the op with typeof, so the
default scraping build is unchanged and falls through to the synthetic
rect.

With --features render, block siblings stack and flex children place
horizontally at correct positions, and elementFromPoint resolves the
right element. Default build returns the synthetic rect unchanged.
Obstacle course 33/33; obscura-js unit failures identical to main.
2026-06-30 20:36:43 +00:00
SGavrl 9d0e7d63dc Merge pull request #515 from mnaza/fix/domparser-xml-504
fix(js): surface a parsererror for malformed XML in DOMParser
2026-08-07 16:52:28 +00:00
SGavrl d361e41185 Merge pull request #548 from mnaza/fix/cssstyledeclaration-global-546
fix(js): expose CSSStyleDeclaration as a real global interface
2026-08-07 16:51:57 +00:00
SGavrl 8cd9a001f1 Merge pull request #555 from mnaza/fix/event-constructor-conformance-552
fix(js): make Event/CustomEvent constructors match WebIDL
2026-08-07 16:49:41 +00:00
Andrey Mnatsakanov 452cc8554f fix(js): run string timer handlers as global-scope scripts at fire time
A string setTimeout/setInterval handler was compiled with new Function(fn) at
scheduling time. That diverged from the HTML spec in two ways: top-level
var/function declarations in the body stayed local to the compiled function
instead of becoming globals, and a syntax error was caught eagerly at
scheduling and turned into a silent no-op (that still returned a timer id)
rather than surfacing when the timer fires.

Defer string handlers to fire-time indirect eval ((0, eval)(src)), which runs
in the true global scope like a classic script, so declarations become global
and a SyntaxError is thrown when the timer elapses. Matches the dynamic-script
path, which already uses indirect eval for the same reason. Function handlers
are unchanged.

Fixes #558
2026-08-04 17:40:19 +02:00
Andrey Mnatsakanov af1e15f6c8 fix(js): make Event/CustomEvent constructors match WebIDL
The Event and CustomEvent constructors diverged from Chrome in three
observable ways:

- new Event() / new CustomEvent() with no argument did not throw, though the
  type argument is required (Chrome: "1 argument required, but only 0
  present."). initEvent/initMouseEvent already had this check; the
  constructors did not.
- the type argument was not coerced to a string, so new Event(123).type was
  the number 123 instead of "123".
- CustomEvent.detail defaulted to undefined; WebIDL CustomEventInit specifies
  `any detail = null`.

Add the required-argument guard to both constructors, coerce type via
String(t) (inherited by every subclass through super), and default detail to
null. createEvent() builds events with an explicit '' type, so the arity
guard leaves the type-"" uninitialized-event path intact.

Fixes #552
2026-08-04 11:00:01 +02:00
Andrey Mnatsakanov a0e1ba5f85 fix(js): expose CSSStyleDeclaration as a real global interface
CSSStyleDeclaration was added to the _preHideInternals non-enumerable
pre-declaration list (commit c7e7c70) on the assumption that its later
`globalThis.X = X` assignment would fill in the value. But it was the only
one of the 22 WebIDL interfaces with no such assignment, so its value stayed
undefined: `typeof window.CSSStyleDeclaration` was "undefined" while
`'CSSStyleDeclaration' in window` was true, and because it is the type of
element.style / getComputedStyle(), `el.style instanceof CSSStyleDeclaration`
threw "Right-hand side of 'instanceof' is not callable" (Chrome returns true).

Assign globalThis.CSSStyleDeclaration alongside the other interface globals.
The property was already declared writable/configurable, so the assignment
only updates the value and it remains enumerable:false, like a real browser.

Fixes #546
2026-08-04 10:35:24 +02:00
Andrey Mnatsakanov 53295faa59 fix(js): surface a parsererror for malformed XML in DOMParser
DOMParser.parseFromString always HTML-parsed, even for XML mime types, so
malformed XML never produced the <parsererror> element Chrome emits and
error-detection code (doc.querySelector('parsererror')) never triggered. obscura
has no XML parser, so full XML semantics stay out of scope; instead, for XML
mime types run a conservative well-formedness check (tag balance, single root,
terminated comment/CDATA/PI, skipping quoted attribute regions) and, on a clear
error, make the document surface a <parsererror>. The check defaults to
well-formed when ambiguous, so valid XML is never falsely flagged.

Fixes #504
2026-08-04 08:43:45 +02:00
SGavrl 6a55b63fa6 fix(js): isolate bootstrap declarations 2026-08-03 16:31:30 +00:00
SGavrl 1518ca2a70 Merge remote-tracking branch 'origin/main' into maintainer/pr-514-review
# Conflicts:
#	crates/obscura-js/js/bootstrap.js
2026-08-03 15:35:42 +00:00
SGavrl 42f7fad709 Merge pull request #507 from mnaza/fix/insert-adjacent-html-495
fix(js): case-insensitive insertAdjacentHTML that keeps table/select fragments
2026-08-03 15:33:34 +00:00
SGavrl 62ada5ebb9 Merge pull request #494 from mnaza/fix/clonenode-structural-490
fix(js): clone nodes structurally instead of via div.innerHTML
2026-08-03 15:32:18 +00:00
Diego Cavalcante c7e7c703b7 fix(js): expose WebIDL interfaces as non-enumerable, like a real browser
`bootstrap.js` publishes its DOM interfaces with `globalThis.Node = Node`,
which defaults to `enumerable: true`. A real browser exposes every WebIDL
interface on the global as `enumerable: false`, so the difference is a
one-liner for any script that cares:

    Object.getOwnPropertyDescriptor(window, 'Node').enumerable
    // real Chrome: false     obscura: true

It also means `Object.keys(window)` and `for...in` over the global enumerate
22 names a browser would never list.

The file already has the mechanism for this -- `_preHideInternals()`
pre-declares internal globals with `enumerable: false`, and its own comment
notes that later `globalThis.x = value` assignments only update the value and
leave the descriptor intact. This just adds the WebIDL names to that list, so
no assignment site changes.

Before: 9 of 10 sampled interfaces enumerable. After: 0 of 10, matching Chrome.

Regression: interfaces still callable (`typeof Node === 'function'`),
`instanceof Node` / `instanceof Element` hold, `querySelector` works, Hacker
News still yields 30 results under `--stealth`, snapshot builds clean.

Composes with #537 -- verified with both applied: `var Node` pages run, the
JSF/RichFaces case loads (jQuery/A4J/RichFaces all live), and enumerability
stays at 0/10.
2026-08-02 01:26:42 -03:00
SGavrl 108e777418 Merge remote-tracking branch 'origin/main' into maintainer/pr-492-fix 2026-08-01 19:51:52 +00:00
SGavrl 037e321a79 Merge remote-tracking branch 'origin/main' into maintainer/pr-517-tests 2026-08-01 19:47:51 +00:00
SGavrl 2275d8fea0 Merge remote-tracking branch 'origin/main' into maintainer/pr-509-fix
# Conflicts:
#	crates/obscura-js/src/runtime.rs
2026-08-01 19:39:24 +00:00
SGavrl 0428099b0f Merge remote-tracking branch 'origin/main' into maintainer/pr-509-fix 2026-08-01 16:04:37 +00:00
SGavrl 76e5280c32 fix(dom): preserve namespaced attribute qualified names 2026-08-01 16:00:52 +00:00
SGavrl 1e305135e3 Merge remote-tracking branch 'origin/main' into maintainer/pr-514-review 2026-08-01 15:58:03 +00:00
SGavrl a2fd4d1735 fix(js): parse fragments in their insertion context 2026-08-01 15:54:51 +00:00
SGavrl 35fa61032b Merge remote-tracking branch 'origin/main' into maintainer/pr-507-review 2026-08-01 15:50:23 +00:00
SGavrl 907e15d85d perf(js): avoid per-element style sync objects 2026-08-01 15:46:25 +00:00
SGavrl 82aa320084 Merge remote-tracking branch 'origin/main' into maintainer/pr-492-fix 2026-08-01 15:44:40 +00:00
SGavrl 5d7a02041a fix(js): preserve inline styles when cloning 2026-08-01 15:41:45 +00:00
SGavrl c327354911 Merge remote-tracking branch 'origin/main' into maintainer/pr-494-review 2026-08-01 15:40:11 +00:00
SGavrl 16b6a09546 Merge remote-tracking branch 'origin/main' into maintainer/pr-517-tests 2026-08-01 15:37:17 +00:00
SGavrl b5c2f9cc4e Merge branch 'maintainer/pr-508-review' into maintainer/pr-510-review
# Conflicts:
#	crates/obscura-js/src/runtime.rs
2026-08-01 15:30:32 +00:00
SGavrl caf51975bb Merge remote-tracking branch 'origin/main' into maintainer/pr-508-review 2026-08-01 15:28:07 +00:00
SGavrl 3f5dd23778 Merge remote-tracking branch 'origin/main' into maintainer/pr-510-review 2026-08-01 15:28:02 +00:00
SGavrl d93ff517fc fix(js): keep performance clock bounded 2026-08-01 15:20:35 +00:00
SGavrl bb21452f90 Merge pull request #532 from alectimison-maker/fix/dynamic-script-data-urls
fix(js): execute dynamic data URL scripts
2026-07-31 17:43:45 +00:00