Files
NotAlexNoyleandClaude Fable 5.1 d331e4ed29 T-505 item 3: the parts' pictures by part (engine 0073), the express second frame back; item 4 next
The owner's "cheaper part pictures" (2026-11-03). Engine 0073: each rect of a frame's parts list carries a
signature of its own (its outermost fixed or sticky layer's subtree, every subtree layer's last paint as the
stamp of one up-only counter, the part's scale, quarter-pixel phase, place inside its rect and size);
compose_post3/start3 (overview_ok 4) take the signatures the daemon holds and the pass reads only the rects
not in the list; the poll's 54 ints carry each rect's signature and the rects read. The daemon keeps eight
part pictures by signature and, with JIHAD_GPU_PARTS_PER=1 (or <state>/parts-per), sends the list; without
it E2's rule. The express lane's second frame on the first in flight is back when both are without their
parts (JIHAD_GPU_EXPRESS_SECOND_PARTS=1 or <state>/express-second-parts): its dress puts back what lay
beneath the first's parts and beneath the first's base's parts from the slot records (serials, the rows
read, a slot's previous record kept aside), never on a first that is itself two deep. JIHAD_GPU_VERIFY=1
now verifies the express lane's frames (the reference composed before the job; verifyCompare shared with the
main lane) and JIHAD_GPU_TEST_DRESS_HOLD=<pre|mid>:<ms> holds a first frame's dress so the second's copy
catches it. Both switches off by default: the defaults are the owner's call.

By finger: desktop Wikipedia 10.8 -> 11.4 fps flowing (its contents panel, the part that changes, is 310 of
the 340 KB: the lever is bounded by the changing part's size), the long page 19.2 / 19.4 / 18.1. Verify after
the pan mark: 0 wrong rows in every run on both pages, 142 two-deep frames among them, 55-80 of those with
the first's dress held (docs/rounds/t505-2026-11-03/notes.txt).

The inspector's review (Codex out of credits): REVISE, seven findings, all fixed (impl-review-findings-t505-
cpuparts.md, review 3). The verify then exposed a latent main-lane fault from review 2's F4 (2026-11-02): a
second job whose in-flight base the parts rule refused built on the newest finished frame but told the engine
it was the previous composite, so the frame was recorded 316 rows off and the next own-slot frames copied
wrong rows; fixed (srcInFlight in gpuJobStart; 0 wrong in three runs after).

Also: build/desktop/build-goanna.sh takes a jobs argument like the ARM script (the host short of memory);
tools/device/t502/README.md documents the switches; the kit's R4 criterion, the build site's T-505 row and
PICKUP's top section carry the state; the three variants run this head (default-check x3 passes).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-03 12:47:59 -05:00

32 KiB

Engine Source & Modifications (MPL-2.0 compliance)

cavekit-licensing-branding R3 / R4 — engine origin, patches, and branding strip. Brought up to date 2026-10-08 (it had listed four patches under old names).

Jihad Browser renders with the UXP / Goanna web engine (MPL-2.0). This document records the engine's origin and every modification made to it, so the MPL-2.0 obligation to keep modified files under the MPL with their source available is met.

Origin

  • Upstream: UXP — https://repo.palemoon.org/MoonchildProductions/UXP, pristine at the release RB_20261027 (6b18be917d462369593bfe611230a7003fd7d945, 2026-10-26) — UXP_TAG / UXP_BASE in build/engine/engine-version.env. (Until 2026-11-03: RB_20261006, 5f290d1, 2026-10-04; until 2026-10-12: master b2594a4, 2026-06-30.)
  • Our modified engine: the branch jihad/uxp-RB_20261027 of the fork NotAlexNoyle/UXP-Jihad, at UXP_PIN (52ad9ab66ebbc1c28133a330ee2f35819565d61e), present in this repository as the submodule third_party/uxp. The device build compiles that tree.
  • The modifications as patches: build/desktop/patches/ holds every change as a patch against UXP_BASE. build/engine/patch-queue.sh --check proves the patches, applied in order, produce exactly the UXP_PIN tree. How the two are kept in step: docs/ENGINE.md §2.

Modifications to the engine (all MPL-2.0, source here)

Every modified UXP file stays under the MPL-2.0. These patches are the source of the modifications; the same changes are the commits of jihad/uxp-RB_20261027, one per patch.

Patch Files What it changes
0001-js-format-overflow.patch js/src/jit/x64/BaseAssembler-x64.h GCC 9: source pragma for -Wformat-overflow (js/src re-escalates it)
0002-configure-warnings.patch build/moz.configure/warnings.configure GCC 9: warnings.configure adjustment
0003-gfx-init-and-omtc.patch gfx/thebes/gfxPlatform.cpp, gfx/thebes/gfxPlatformGtk.cpp, toolkit/xre/nsEmbedFunctions.cpp JIHAD_DISABLE_OMTC forces the in-process BasicLayerManager; gfx started inside XRE_InitEmbedding2
0004-gtk-headless-guards.patch widget/gtk/gtk2drawing.c, widget/gtk/nsLookAndFeel.cpp, widget/gtk/nsNativeThemeGTK.cpp GTK realize/theme/look-and-feel paths guarded so libxul runs with no X server
0005-puppetwidget-offscreen-zoom.patch widget/PuppetWidget.cpp, widget/PuppetWidget.h PuppetWidget offscreen render, zoom and damage tracking; the jihad_offscreen_* exports
0006-headless-toolkit.patch embedding/components/printingui/moz.build, gfx/2d/2D.h, gfx/2d/Factory.cpp (+19 more) MOZ_WIDGET_TOOLKIT=headless: gfxPlatformHeadless, widget/headless, build wiring
0007-nss-mainthread-marshal.patch security/manager/ssl/nsNSSComponent.cpp NSS EnsureNSSInitialized main-thread fast path; the jihad_init_nss export
0008-plugin-headless-nativehandle.patch dom/plugins/ipc/PluginInstanceChild.cpp, dom/plugins/ipc/PluginInstanceParent.cpp, dom/plugins/ipc/PluginMessageUtils.h NativeWindowHandle for the headless platform so plugin IPC compiles
0009-misc-headless.patch ipc/chromium/src/base/message_loop.cc, toolkit/xre/nsXREDirProvider.cpp Headless build fixes (message loop, XRE directory provider)
0010-branding-strip.patch docshell/base/nsAboutRedirector.cpp, modules/libpref/init/all.js, toolkit/xre/nsAppRunner.cpp Pale Moon / Basilisk / Moonchild branding stripped (cavekit-licensing-branding R3)
0011-appcompat-guid.patch xulrunner/configure.in, xulrunner/confvars.sh The AppCompat GUID (xulrunner configure)
0012-popup-instrumentation.patch layout/xul/nsXULPopupManager.cpp XUL popup instrumentation and offscreen compositing of popups
0013-xpi-install-embedding.patch toolkit/mozapps/extensions/AddonManager.jsm, toolkit/mozapps/extensions/amInstallTrigger.js AddonManager / amInstallTrigger work without a browser element
0014-badcertlistener-embedding.patch docshell/base/nsDocShell.cpp, embedding/browser/nsDocShellTreeOwner.cpp Certificate errors reach the embedder (bad-cert listener)
0015-find-embedder-no-jscontext.patch embedding/components/find/nsWebBrowserFind.cpp Find-in-page without a JS context
0016-npapi-windowless-headless.patch dom/plugins/base/nsNPAPIPlugin.cpp NPAPI windowless plugins under the headless toolkit
0017-npapi-webos-palm-host.patch dom/plugins/ipc/JihadNPNInterpose.cpp, dom/plugins/ipc/PluginInstanceChild.cpp, dom/plugins/ipc/PluginInstanceChild.h (+2 more) The webOS (Palm) NPAPI host: NPEvent union, JihadNPNInterpose
0018-npapi-child-process-loader.patch ipc/glue/GeckoChildProcessHost.cpp The plugin child process launched through our loader
0019-bhm-null-manager-guard.patch xpcom/threads/BackgroundHangMonitor.cpp BackgroundHangMonitor null-manager guard
0020-npapi-composite-without-imagebridge.patch dom/plugins/ipc/PluginInstanceParent.cpp Plugin compositing without ImageBridge
0021-npapi-windowless-invalidate-offscreen.patch dom/plugins/base/nsPluginInstanceOwner.cpp Windowless plugin invalidation into the offscreen widget
0022-npapi-recvshow-copy-frameid.patch dom/plugins/ipc/PluginInstanceParent.cpp Plugin RecvShow copies the frame id
0023-npapi-operational-logging.patch dom/base/nsObjectLoadingContent.cpp, dom/plugins/base/nsNPAPIPlugin.cpp, dom/plugins/base/nsPluginHost.cpp (+5 more) Plugin operational logging
0024-npapi-webos-plugin-input.patch dom/plugins/base/npapi.h, dom/plugins/base/nsPluginHost.cpp, dom/plugins/base/nsPluginHost.h (+6 more) webOS plugin input, the frozen plugin YAP commands, the frame path
0025-npapi-pmlog-named-semaphore-abi.patch ipc/app/moz.build, ipc/contentproc/JihadPmLogSem.c, ipc/contentproc/moz.build (+1 more) PmLog named-semaphore ABI shim for the plugin container
0026-npapi-plugin-repaint-rate.patch dom/plugins/ipc/PluginInstanceChild.cpp Plugin child repaint rate (frame clock)
0027-npapi-plugin-cpu-boost.patch dom/plugins/ipc/PluginModuleParent.cpp CPU boost while a plugin plays
0028-npapi-plugin-frame-seq.patch dom/plugins/ipc/PluginInstanceParent.cpp Plugin frame counter export (jihad_plugin_frame_seq)
0029-npapi-plugin-pull-frame.patch dom/plugins/ipc/PPluginInstance.ipdl, dom/plugins/ipc/PluginInstanceChild.cpp, dom/plugins/ipc/PluginInstanceChild.h (+1 more) Plugin frames pulled from the daemon's clock (JihadRequestFrame IPDL)
0030-cubeb-pulse-webos-virtual-sink.patch media/libcubeb/src/cubeb_pulse.c cubeb Pulse: the webOS virtual sink (JIHAD_PULSE_SINK)
0031-npapi-JIHAD_PLUGIN_SELF_DRIVE-0-turns-the-plugin-chi.patch dom/plugins/ipc/PluginInstanceChild.cpp JIHAD_PLUGIN_SELF_DRIVE=0 turns the plugin child's own repaint timer off
0032-videocontrols-fix-scrubber-flicker-settle-interpolat.patch toolkit/content/widgets/videocontrols.xml Video controls: scrubber flicker and settle, interpolated thumb
0033-videocontrols-surface-media-errors-for-audio-only-co.patch toolkit/content/widgets/videocontrols.xml Video controls: media errors shown for audio-only content
0034-cubeb-classify-media-streams-export-a-playing-stream.patch media/libcubeb/src/cubeb_pulse.c cubeb: media.role classification; jihad_pulse_active_streams export
0035-gfx-BasicPlanarYCbCrImage-CopyData-must-not-report-f.patch gfx/layers/basic/BasicImages.cpp gfx: BasicPlanarYCbCrImage::CopyData no longer reports failure under delayed conversion
0036-extensions-a-link-or-navigation-to-an-.xpi-must-reac.patch toolkit/mozapps/extensions/amContentHandler.js A link or navigation to an .xpi reaches the install flow without a browser window
0037-plugins-an-instance-with-no-window-to-be-given-is-wi.patch dom/plugins/base/nsPluginInstanceOwner.cpp A plugin instance with no window is windowless instead of a null dereference
0038-plugin-container-do-not-hand-the-bundled-library-pat.patch ipc/contentproc/plugin-container.cpp plugin-container does not hand the bundled library path to what the plugin runs
0039-addons-an-add-on-naming-both-the-AppCompat-GUID-and-.patch toolkit/mozapps/extensions/internal/XPIProvider.jsm XPIProvider: an add-on naming the AppCompat GUID and the toolkit matches the entry that fits
0040-gpu-compositor-an-in-process-OpenGL-compositor-behin.patch gfx/layers/client/ClientPaintedLayer.cpp, gfx/layers/composite/LayerManagerComposite.{h,cpp}, gfx/layers/ipc/CompositorBridgeParent.{h,cpp}, gfx/layers/opengl/CompositingRenderTargetOGL.{h,cpp}, gfx/layers/opengl/CompositorOGL.{h,cpp}, gfx/layers/opengl/TextureHostOGL.cpp, gfx/thebes/gfxPlatform.cpp, gfx/thebes/gfxPlatformHeadless.{h,cpp}, gfx/thebes/gfxPrefs.h, modules/libpref/init/all.js, widget/PuppetWidget.{h,cpp} T-502: with JIHAD_GPU_COMPOSITOR set, an in-process OpenGL compositor (an EGL pbuffer, two renderbuffer window targets) behind the offscreen widget, pulled a frame at a time by the daemon (jihad_offscreen_compose_start/_poll/_forget, jihad_offscreen_compositor_seq, jihad_offscreen_set_view); the layer tree's own diff drives band readbacks and scissored partial composites; the window's flipped view kept and the rows reversed in the read; tiled content layers on by default (layers.enable-tiles); the read thread, the GPU swizzle pass and the snapshot road are opt-in (docs/RENDERING-OPTIONS.md); nothing changes without the env
0041-gl-the-Adreno-220-whole-texture-uploads-BGRA-uploads.patch gfx/gl/GLContext.{h,cpp}, gfx/gl/GLContextEGL.h, gfx/gl/GLContextProviderEGL.cpp, gfx/gl/GLTextureImage.{h,cpp}, gfx/gl/GLUploadHelpers.cpp GLRenderer::AdrenoTM220; CanUploadSubTextures() false for the Adreno 2xx "(TM)" spellings and the 220 (a sub-image update costs 16x a whole upload); an EGL context prefers BGRA uploads where GL_EXT_texture_format_BGRA8888 exists, with GLES-legal types (4x faster than RGBA when the GPU is idle); GLContextEGL::JihadCreateSharedContext (a 1x1 pbuffer context sharing the compositor's objects, for a readback thread); fresh texture names per upload opt-in (JIHAD_GPU_FRESH_TEX=1)
0042-gpu-compositor-the-card-s-scroll-applied-in-the-comp.patch gfx/gl/GLContext.h, gfx/gl/GLContextEGL.h, gfx/gl/GLContextProviderEGL.cpp, gfx/layers/LayerTreeInvalidation.{h,cpp}, gfx/layers/Layers.cpp, gfx/layers/composite/AsyncCompositionManager.{h,cpp}, gfx/layers/composite/LayerManagerComposite.{h,cpp}, gfx/layers/ipc/CompositorBridgeParent.{h,cpp}, gfx/layers/opengl/CompositorOGL.{h,cpp}, layout/base/FrameLayerBuilder.cpp, layout/base/nsDisplayList.cpp, layout/base/nsLayoutUtils.cpp, layout/generic/nsGfxScrollFrame.cpp, widget/PuppetWidget.{h,cpp} T-502: the card's scroll applied by the composition manager as APZ would (root scroll metadata and the scrollport as a scroll clip for a root scroll frame with a displayport, the displayport set from layout, no intermediate surface for a scaled container); the context's pbuffer at the frame's size (the Adreno 220 bins an FBO render by the surface's size); scroll-only frames composed band by band on their own 768x256 pbuffer and FBO with the row shift behind the GPU; a done-fd that wakes the daemon when a job finishes; the diff treats the root-content layer's scroll as a shift and is scaled to frame pixels
0043-npapi-the-Palm-event-paths-only-where-npapi.h-define.patch dom/plugins/ipc/PluginInstanceChild.cpp, dom/plugins/base/nsPluginHost.cpp T-387: the Palm gain-focus system event and the spotlight export built only where npapi.h defines Palm's NPEvent (the headless toolkit the device builds), so the desktop GTK engine builds again for the desktop tests; the desktop spotlight export returns 0
0044-gpu-compositor-tile-textures-converted-at-1x1-and-ke.patch gfx/gl/GLTextureImage.{h,cpp}, gfx/layers/opengl/CompositorOGL.cpp T-504: on the GPU path a new tile texture is converted while it is 1x1 (a framebuffer clear and a 1x1 write) and a texture image's texture goes to a pool instead of being deleted: the Adreno 220 converts a texture's storage on its first write after its first draw (~18 ms a 256x256 tile, measured in tools/device/gpu-bench.c sections 12-15), which every new tile paid on its first change
0045-gpu-compositor-no-edge-antialiasing-for-an-axis-alig.patch gfx/layers/opengl/CompositorOGL.cpp, gfx/layers/ipc/CompositorBridgeParent.cpp T-504: on the GPU path an axis-aligned scale gets no edge antialiasing (its shader variants compiled on first use, ~150 ms each, in the first frame of a zoom); JIHAD_GPU_PHASES also logs each slow composite's phases and each slow draw
0046-gpu-compositor-the-root-scroll-frame-s-clip-widened-.patch layout/base/nsLayoutUtils.{h,cpp}, layout/generic/nsGfxScrollFrame.cpp T-505: jihad_layout_set_overscan widens the root scroll frame's clip on the GPU path by the rows the daemon's frame carries above and below what the card shows (overscan), so the card has content to pan into between frames
0047-gpu-compositor-a-given-up-frame-writes-nothing-test-.patch gfx/layers/ipc/CompositorBridgeParent.cpp, gfx/layers/opengl/CompositorOGL.{h,cpp}, widget/PuppetWidget.cpp T-509: a compose job the daemon forgot writes nothing into its slot (cancelled); test switches JIHAD_GPU_TEST_NO_EGL (no GL context, as an EGL failure) and JIHAD_GPU_TEST_STALL (a job held 6 s)
0048-gpu-compositor-the-frame-s-paint-and-its-compose-pos.patch widget/PuppetWidget.{h,cpp} T-515: the frame's layer paint (jihad_offscreen_paint_layers, the main thread) and its compose job (jihad_offscreen_compose_post, any thread, at a view and scroll it is given) apart, so the daemon's express lane composes and publishes frames while the main thread runs the page's script; the job list under a mutex (a poll without a wait holds it throughout); jihad_offscreen_compose_peek (a job's state without its result); a forgotten job's cancelled flag only with abandoned
0049-layers-a-composite-acknowledged-after-the-widget-is-.patch gfx/layers/client/ClientLayerManager.cpp T-515: DidComposite returns when the widget is gone (a card closed while a compose job it had asked for was waited out; its acknowledgement reached the main thread after the page was torn down: SIGSEGV at 0)
0050-gpu-compositor-every-compose-job-compose-and-read-on.patch widget/PuppetWidget.cpp, gfx/layers/ipc/CompositorBridgeParent.cpp, gfx/layers/opengl/CompositorOGL.cpp T-516: with JIHAD_GPU_TIMELINE=1 every compose job, compose and read logged with a timestamp on the daemon's clock (otherwise sampled), so a slow frame's time can be placed
0051-webgl-contexts-on-the-device-s-GPU-on-the-GPU-path-s.patch dom/canvas/WebGLContext.cpp, dom/canvas/WebGLContextValidate.cpp, widget/headless/GfxInfo.cpp, gfx/gl/GLContextEGL.h, gfx/gl/GLContextProviderEGL.cpp, gfx/gl/SharedSurface.cpp, gfx/layers/client/ClientCanvasLayer.cpp T-511: WebGL on the GPU path asks EGL for its context (the headless default provider is null) and is not blocklisted there (headless GfxInfo); the Adreno 220's GL_INVALID_ENUM for GL_STENCIL_BACK_WRITEMASK queried in its own error scope; every pbuffer context on the GPU path in one share group under a 1x1 root, a WebGL canvas handing the compositor its texture (SurfaceFactory_GLTexture, zero copy; JIHAD_GPU_NO_SHARE=1: unshared, read back through a canvas-sized pbuffer); a context released from its thread before it is destroyed (the next teardown faulted in libGLESv2)
0055-gpu-compositor-a-band-frame-s-regions-composed-in-on.patch gfx/layers/composite/LayerManagerComposite.{h,cpp}, gfx/layers/ipc/CompositorBridgeParent.cpp T-517: a band frame's bands and column chunks composed as regions of one composite (JihadSetRegions: the transaction and BeginFrame/EndFrame once, per region its world, Prepare and RenderLayer); JIHAD_GPU_PASS_PER_REGION=1 as before
0056-layers-a-tile-wholly-outside-the-clip-is-not-locked-.patch gfx/layers/composite/TiledContentHost.cpp T-517: a tile whose transformed bounds miss the clip (in the render target's coordinates) is skipped before its texture is locked and bound; JIHAD_GPU_NO_TILE_CULL=1 for A/B
0057-gpu-diagnostics-off-by-default-behind-JIHAD_GPU_LOG-.patch gfx/2d/JihadGpuLog.h (new, exported), gfx/2d/moz.build, the GPU path's files in gfx/gl, gfx/layers, layout/base/nsLayoutUtils.cpp, widget/PuppetWidget.cpp T-512: the [jihad-gpu] diagnostics behind one gate (JIHAD_GPU_LOG=1, or a device round's JIHAD_GPU_TIMELINE/VERIFY/DUMP_EVERY), failures and fallbacks unconditional; T-517: the page's layer transactions and every compose job's tile uploads on JIHAD_GPU_TIMELINE
0058-gpu-compositor-the-review-of-Tier-87-fixed-scratch-p.patch gfx/gl/GLContextProviderEGL.cpp, gfx/layers/composite/AsyncCompositionManager.{h,cpp}, gfx/layers/ipc/CompositorBridgeParent.cpp, gfx/layers/opengl/CompositorOGL.{h,cpp}, gfx/layers/opengl/TextureHostOGL.cpp, widget/PuppetWidget.cpp T-513: the review of Tier 87 (context/impl/impl-review-findings-gpu-2.md E1-E7 and Codex's C1): the band scratch is each compositor's own (two cards shared one and overran it); a closed card's frame-sized and band pbuffers and the window targets', band target's and swizzle pass's GL objects are freed (16 MB of GPU memory a card before); a band frame of 257-320 rows stacked in the frame-sized target makes that surface current first; a WebGL canvas's texture name is the producer's to delete; the reads carry their request's cancel flag (JihadSetCancel), so a read given up past the daemon's bound stops after glReadPixels and never copies into the slot, on the opt-in scratch, swizzle and read-thread paths too, counted by jihad_offscreen_late_writes(); a frame whose chunks pass the 12-band cap takes the whole path; a sticky layer's stuck probe reaches twice the composite's scroll step
0059-layout-the-GPU-path-s-root-displayport-and-clip-at-a.patch layout/base/nsLayoutUtils.cpp, layout/generic/nsGfxScrollFrame.cpp T-524: once the pres shell has a resolution the root's displayport base and clip are layout device px: jihad_layout_set_displayport2 takes the card's shift and gives the base and margins times the resolution, and the root's display-list clip (the scroll port) is no longer divided by it (desktop Wikipedia at 2.33: the card's right third white, nothing past 479 CSS px hit-testable)
(0060 until 2026-11-03: security-the-built-in-roots-rolled-forward-to-UXP-release, T-529's certdata.txt from the release branch at 037cc5f614) security/nss/lib/ckfw/builtins/certdata.txt DROPPED at the move to RB_20261027 (the owner, 2026-11-02): the tag ships that very file (byte-identical: [NSS] Update certdata to Sept 2026 status 4a68bbbd53 and [NSS] Remove emSign roots (eMudhra compromise) 037cc5f614 are in the base), so the built-in roots are the base's; audit-roots.py checks them against it. The patches after it moved up one number
0060-security-a-certificate-error-is-not-TLS-intolerance-.patch security/manager/ssl/nsNSSIOLayer.cpp T-534: a SEC_ERROR_* / mozilla::pkix / bad-cert-domain failure is never retried at a lower TLS version (the retry tripped a TLS 1.3 server's downgrade sentinel and a revoked certificate read "SSL_ERROR_RX_MALFORMED_SERVER_HELLO")
0061-layout-the-GPU-path-s-root-displayport-base-is-the-d.patch layout/base/nsLayoutUtils.{h,cpp}, layout/generic/nsGfxScrollFrame.cpp T-527: on the GPU path the root's displayport base set by the daemon (0059's jihad_layout_set_displayport2) is kept by the paint (nsLayoutUtils::JihadKeepsDisplayPortBase): nsLayoutUtils::PaintFrame's DecideScrollableLayer replaced it on every paint with the composition size at the origin in CSS px, and a zoomed-in card's first paint without margins covered 660 of the 531..861 CSS px shown (docs/rounds/t527-2026-10-25/notes.txt)
0062-gpu-compositor-a-tall-band-surface-for-a-change-that.patch gfx/gl/GLContextEGL.h, gfx/gl/GLContextProviderEGL.cpp, gfx/layers/ipc/CompositorBridgeParent.cpp, gfx/layers/opengl/CompositorOGL.{h,cpp} T-527 (R8): a change that does not fit the 256-row band surface takes a second, 512-row band surface (JIHAD_GPU_BAND_TALL, its own pbuffer and target) instead of the frame-sized target; frames are packed for the band surface first. The 480 px WebGL cube's job 15-30 ms where it took ~45
0063-widget-a-GPU-path-layer-paint-with-nothing-pending-i.patch widget/PuppetWidget.{h,cpp}, layout/base/nsLayoutUtils.cpp T-527: the daemon's layer paint returns at once after the first when nothing is pending (no invalid region, no paint task, no view-manager flush owed): the display list is not built again for nothing (JIHAD_GPU_PAINT_ALWAYS=1: every time); a moved displayport base schedules the root's paint (the margins' comparison saw no change). Desktop Wikipedia's pan 23.6 fps and the long page's 33.1, verify 0 rows wrong: the compositor thread stays the bound
0064-gpu-compositor-a-band-surface-that-cannot-be-made-at.patch gfx/layers/opengl/CompositorOGL.{h,cpp} T-527 (review): a band surface or its target that cannot be made at a width is not made again every band frame (a line each into /var); the frame's own surface does the pass
0065-widget-the-layer-paint-skip-repaints-after-a-resolut.patch widget/PuppetWidget.{h,cpp}, gfx/layers/opengl/CompositorOGL.{h,cpp} T-527 (review 2026-10-26): 0064's skip repaints when the pres shell's resolution differs from the one painted (SetResolution schedules no paint, and a page with no root scroll frame — about:addons — stayed at the old resolution after a zoom across 1.1) and asks the whole widget chain (invalidations land on the child); 0065's failed band surface is tried again after 30 s
0066-gpu-compositor-a-compose-that-asks-for-its-bands-onl.patch widget/PuppetWidget.cpp, gfx/layers/opengl/CompositorOGL.h, gfx/layers/ipc/CompositorBridgeParent.cpp T-516: compose flag 16 — read only the bands asked for, not the rows the tree changed (still reported); the daemon's first frame at a new zoom reads the card's view alone (942 of 1224 rows): double taps by finger 40/40 within 250 ms, the slowest 227 ms where 276-301
0067-gpu-compositor-a-frame-s-fixed-and-stuck-rects-go-ba.patch widget/PuppetWidget.{h,cpp}, gfx/layers/opengl/CompositorOGL.h, gfx/layers/ipc/CompositorBridgeParent.cpp T-544: jihad_offscreen_compose_poll2 returns a frame's fixed and stuck rects with its poll; the daemon passes them to the card (JihadStuckBlock), which holds desktop Wikipedia's sticky sidebars still between frames of a pan (they moved with the page and jumped back)
0068-gpu-compositor-the-overview-s-windows-and-parts-the-.patch widget/PuppetWidget.cpp, gfx/layers/opengl/CompositorOGL.{h,cpp}, gfx/layers/ipc/CompositorBridgeParent.cpp, gfx/layers/composite/AsyncCompositionManager.{h,cpp} T-504: compose flags 32 and 64 (jihad_offscreen_overview_ok) — an overview window (fixed and stuck layers at opacity 0, cleared transparent, read with its alpha, so rows no tile covered read alpha 0) and the overview's parts (only the fixed and stuck layers, with their alpha); a fixed sticky probe for both, and the verify guard keeps the probe's state; the daemon stitches a half-size picture of the page around a zoom-in point for a double tap out after a pan
0069-gpu-compositor-a-frame-without-its-parts-flag-128-an.patch widget/PuppetWidget.cpp, gfx/layers/opengl/CompositorOGL.h, gfx/layers/ipc/CompositorBridgeParent.{h,cpp}, gfx/layers/ipc/CompositableTransactionParent.cpp T-505: compose flag 128 (jihad_offscreen_overview_ok answers 2) — a frame without its parts: every fixed and sticky layer at opacity 0 in the composite and the diff, no fixed rows, keeps or columns, each part reported as its layer's whole rect; the parts' generation (compositable updates under a fixed or sticky layer) as the poll's thirtieth int; JIHAD_GPU_REQLOG=1 names each composite request's source
0070-gpu-compositor-the-diff-leaves-the-card-s-scroll-out.patch gfx/layers/ipc/CompositorBridgeParent.cpp T-505: the diff leaves the card's scroll out of a frame with no base to copy (built on its slot's own frame) too, kept only when the shift it measured is the card's since the last composite; a layer transaction during a pan is no longer the whole frame changed for such frames
0071-gpu-compositor-the-parts-picture-in-the-frame-s-own-.patch widget/PuppetWidget.{h,cpp}, gfx/layers/opengl/CompositorOGL.{h,cpp}, gfx/layers/ipc/CompositorBridgeParent.{h,cpp}, gfx/layers/composite/LayerManagerComposite.{h,cpp} T-505 (E2): jihad_offscreen_compose_post2/start2 (overview_ok answers 3): a frame without its parts reads the parts' picture in its own job when their signature (layers, content, attributes, sizes) is not the daemon's — the parts alone, packed on the band surface, read with their alpha; the poll's 49 ints (signature, the pass's bytes, flags: a content layer above a part / too big, the card's hold set); no column reads without the parts; 0071 only without the parts or without fixed rects
0072-gpu-compositor-a-frame-without-its-parts-composes-th.patch gfx/layers/composite/LayerManagerComposite.{h,cpp}, gfx/layers/ipc/CompositorBridgeParent.{h,cpp} T-505: a frame without its parts reads the changed rows whole, so its diff-driven partial composite covers them across the frame's width (JihadWholeRows; the columns beside a narrow change used to be the window target's last composite: the long page's wrong verify frame, 2026-11-02); the inspector's review fixes: one sample time per job, fixed rects joined again after the reduction, the parts' signature over a cut part's slice, every part's clip and mask, blend modes as covered; the parts pass under the job's cancel flag
0073-gpu-compositor-the-parts-picture-by-part-each-rect-i.patch gfx/layers/ipc/CompositorBridgeParent.{h,cpp}, gfx/layers/ipc/CompositableTransactionParent.cpp, gfx/layers/opengl/CompositorOGL.h, widget/PuppetWidget.{h,cpp} T-505 (the owner's "cheaper part pictures", 2026-11-03): each rect of a frame's parts list carries a signature of its own (its outermost fixed or sticky layer's subtree, every subtree layer's last paint as the stamp of one counter that only goes up — every compositable update stamps its layer, part or not — the part's scale and quarter-pixel phase, where it sits inside the rect and its size; a rect no part's rect meets takes every part's with its index and place); jihad_offscreen_compose_post3/start3 (overview_ok 4) take the list of signatures the daemon holds and the pass composes and reads only the rects not in it, packed in rect order; the poll's 54 ints carry each rect's signature and the rects read. The whole signature keeps post2/start2's meaning. The inspector's review 3 (F2, F3, F6) folded in
0054-gpu-compositor-kept-rects-all-saved-before-any-is-wr.patch gfx/layers/opengl/CompositorOGL.cpp, widget/PuppetWidget.cpp, dom/canvas/WebGLContext.cpp, widget/headless/GfxInfo.cpp T-517/T-511 review: a window-moved shift saves every kept rect before writing any; jihad_offscreen_gpu_given_up() / jihad_gpu_compositor_on(), so WebGL makes no EGL contexts once the daemon has given the GPU path up
0053-gpu-compositor-a-shift-that-is-the-daemon-s-window-m.patch gfx/layers/opengl/CompositorOGL.{h,cpp}, widget/PuppetWidget.cpp T-517: a compose job's shift may be the daemon's move of the frame's window in its segment (flag 8): the rows are in place, only the kept rects are copied from where they were
0052-gpu-compositor-the-frame-s-bands-read-as-one-column-.patch widget/PuppetWidget.{h,cpp}, gfx/layers/ipc/CompositorBridgeParent.cpp, gfx/layers/opengl/CompositorOGL.{h,cpp} T-511: a compose job may give its bands' stale columns (flag 4); with no shift, kept rows or fixed columns, the bands are read as the one column the change and they span when it is under three quarters of the width; the poll reports the change's columns (twelve ints); JIHAD_GPU_NO_COLUMN_READ=1 reads whole rows

The move to RB_20261027 (2026-11-03)

update-engine.sh RB_20261027 / --finish (docs/ENGINE.md §6): 12 upstream commits since RB_20261006, 11 files, one overlapping the queue (certdata.txt, patch 0060, byte-identical — dropped, above). The owner's word (2026-11-02): the certificate and HTTPS changes get special attention. Each commit and its disposition:

Upstream commit What it changes Disposition
037cc5f614 [NSS] Remove emSign roots (eMudhra compromise) security/nss/lib/ckfw/builtins/certdata.txt certificate: taken with the base; the device had it since 2026-10-25 through patch 0060 (now dropped); audit-roots.py 0 findings against the base
4a68bbbd53 [NSS] Update certdata to Sept 2026 status certdata.txt certificate: the same
6b18be917d [js] Avoid OOB array copy js/src/vm/SelfHosting.cpp memory safety: taken; the desktop JS-driven tests and the device checklist
d42616bb12 Remove the URI_LOADABLE_BY_ANYONE flag from the jar: protocol modules/libjar/nsJARProtocolHandler.cpp security hardening: taken; Jihad's own jar: pages (about:settings, about:personas, the start pages, the add-on pane) checked on the device
bae7a6ec8f [gfx] Prevent feTile rect calculations from overflowing gfx/2d/FilterNodeSoftware.cpp memory safety: taken; an SVG filter page on the device
8fea2ad823 [layout] Ensure frame table is valid after adjusting selection layout/generic/nsSelection.cpp memory safety: taken; selection on the device
c4339b14dc Use strong ref for animation mutation observer batch targets dom/base/nsDOMMutationObserver.h memory safety: taken
e86caa48f5 [XPCOM] Lock during nsComponentManager memory reports xpcom/components/nsComponentManager.{h,cpp} taken
5762097bc2 Update SQLite lib to 3.54.1 db/sqlite3/src/sqlite3.{c,h} taken; cookies and history across the update checked on the device
612a8991df, 38e09d2368, 5c991eadc0 the executable extensions list xpcom/io/nsLocalFileWin.cpp Windows only: no effect here

No PSM, TLS protocol, HSTS or certificate-UI change is in the range; Jihad's TLS floor (patch 0060, formerly 0061) and the Trust dialog's error gate apply unchanged.

Branding strip (cavekit-licensing-branding R3) — patch 0010

Part of the engine branch since the patch series was committed (patch 0010; it was once a sed step in build-goanna.sh). The UA product is already Goanna (netwerk/protocol/http/nsHttpHandler.cpp mProduct); this removes the residual Pale Moon / Basilisk / Moonchild strings so a strings(1) scan of the shipped artifacts is clean:

File Change
modules/libpref/init/all.js extensions.blocklist.url (basilisk-browser.org) → about:blank; captivedetect.canonicalURL (detectportal.palemoon.org) → example.com; two comment URLs neutralized
docshell/base/nsAboutRedirector.cpp about:credits target (palemoon.org Contributors) → the Jihad credits URL
toolkit/xre/nsAppRunner.cpp dead MOZ_APP_NAME == "basilisk"/"palemoon" literals (always false for the xulrunner app) → "n/a" — behavior identical, literals removed

How the strip is verified, and its result, is an acceptance criterion — context/kits/cavekit-licensing-branding.md R3. The check itself is a strings scan of libxul.so, jihad-browserserver and goanna.js for basilisk/palemoon/moonchild.

Trademark note

Per the UXP redistribution terms, an engine build shipped under a name other than Pale Moon / Basilisk must strip that project's branding. "Jihad Browser" is the product name of this fork and implies no endorsement by any upstream. See the top-level LICENSE for the full component/license breakdown and the Apache-2.0 ↔ MPL-2.0 compatibility statement.