Resampling footage audio divided by the requested mix rate, so a rate of 0 panicked. The test decodes a 44.1 kHz WAV at rate 0 and expects a read of the requested length. Without the guard it panics with 'attempt to divide by zero'.
Nothing cleared a `Value::Layer` reference when its layer was deleted, so the id stayed behind:
`env_pixels` resolved it to nothing and rendered no environment at all, while the UI showed "None",
which is documented as "fall back to the comp's Environment Layer". The delete path already
unparents children and drops a track matte that pointed at a deleted layer; a layer reference now
goes the same way, in the same history step, so undo restores the layer and the reference together.
This covers every layer-reference property, not only an Environment light's Source: 73 of them
across the effects (Clone Source, Set Matte, Back Layer, Water Surface, Sky, Ground…). Keyframes
carry the same value kind as the property, as in `essential.rs`, and are fixed too.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The setters go through `comp.settings`, which defaults to the Composition Settings dialog's
centre anchor, so `comp.width = 800` on a 400-wide comp shifted every unparented layer — and
all of its position keys — by 200 px. A script that resized a precomp then found its pixel
coordinates had moved under it.
After Effects' width and height setters only change the frame; moving the contents is what
"resize from centre" scripts do for themselves. The setters now pass `anchor: 0` (top left).
The dialog, which is where the anchor belongs, is untouched.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The Composition Settings dialog draws 「ピクセル縦横比」 and 「フレーム縦横比」, and its checkbox reads
「縦横比を 1:1 (1.00) に固定」. Three existing rows said アスペクト比.
Co-Authored-By: DeepSeek V4.1 Flash <noreply@deepseek.com>
The menu is the authority and it disagreed with this table in three ways: five rows had been
translated that AE leaves in English (Key Cleaner, Advanced Spill Suppressor, Unmult,
Twirl (Legacy) and mocha shape), eight use a half-width ampersand, and a handful differ only in
spacing (Cineon コンバーター, 3D カメラトラッカー, 基本3D). Five effects the table skipped do have
names: コンプレッサー, 歪み, ゲート, カールノイズ and VR 平面として投影.
Co-Authored-By: DeepSeek V4.1 Flash <noreply@deepseek.com>
Adobe help calls it エクスプレッション制御 in prose; the Effect menu says 式制御. The menu is what
a user reads, so it wins.
Co-Authored-By: DeepSeek V4.1 Flash <noreply@deepseek.com>
Read from the Effect menu: OCIO CDL 変換, OCIO 色空間変換, OCIO 表示変換, OCIO ファイル変換 and
OCIO Look トランスフォーム. AE draws 稲妻(高度) and 輝度&コントラスト with half-width marks while
平均化(イコライズ) keeps full-width ones, so the punctuation follows the menu per effect.
Co-Authored-By: DeepSeek V4.1 Flash <noreply@deepseek.com>
An array replacer now copies each source object once per call, so a cycle stays a cycle and the native check throws TypeError, while shared objects still serialize. Documents which threads evaluate expressions, what the 256 KiB guard covers (tested on a 512 KiB thread), that it does not apply on wasm32, and why eval is indirect.
Key Cleaner is キークリーナー and Advanced Spill Suppressor is 高度なスピルサプレッション —
neither is a brand name, and Adobe's keying page names both. The doc comment claimed the
VR and OCIO sets repeat their English names here; the VR rows are Japanese now and the OCIO
rows do not exist, so it says what is true instead.
Co-Authored-By: DeepSeek V4.1 Flash <noreply@deepseek.com>
285 of 307 ids. The 22 that stay English are the ones no source names: the OCIO set,
Screen Key, Unmult, Curl Noise, Puppet, Twirl (Legacy), Stereo 3D Controls, the two face
tracking effects, Mocha shape, Paint, and three audio effects.
Co-Authored-By: DeepSeek V4.1 Flash <noreply@deepseek.com>
Adobe's per-effect pages say 色合い / レベル / 露出 / ストローク / ストロボライト, but its effect
list says 色かぶり補正 / レベル補正 / 露光量 / 線 / ストロボ, and the list is what AE's
interface follows. The interface wins.
Co-Authored-By: DeepSeek V4.1 Flash <noreply@deepseek.com>
The Timeline drew a layer-valued property (an Environment light's Source, a
Displacement Map's layer parameter) as read-only text holding the raw layer
id, so a light's Source could not be chosen in the UI at all - only through
prop.set from the command line, scripting or MCP. Effect Controls already
had a working drop-down for exactly these values: extract it into one shared
widgets::layer_picker (the current entry, "None" first, then "N. name" for
every layer of the comp, the list built only while the popup is open) and
draw it from both panels.
In the Timeline the pick writes through the same set closure as every other
value arm - an undoable prop.set (layer id, or null for None) - and
registers timeline.prop.<uid>.value like its neighbours, so the row names
the layer instead of exposing its id. Effect Controls keeps its rect,
automation id and write; its closed dropdown's "None", previously a
hardcoded literal, now follows the interface language. The dead "Layer {n}"
id text leaves the i18n catalogs with it.
ui_layer_source_picker drives both panels headlessly (open, pick, undo,
dismiss, current-entry highlight, translated None, picking None to clear a
set value), and an ignored wgpu snapshot test keeps the visual record
reproducible.
Tint is 色合い, Levels is レベル, Exposure is 露出, Stroke is ストローク and Strobe Light is
ストロボライト. The list used for cross-checking carried Photoshop's words for three of them.
Co-Authored-By: DeepSeek V4.1 Flash <noreply@deepseek.com>
Every selector of a comma list cloned the whole declaration block, and every
element scanned every rule, so a sub-megabyte <style> could demand billions of
string pairs. Selectors now index one shared block, the sheets are capped at
20 000 selectors and 50 000 declarations, rules are bucketed by id/class/type
so an element checks only candidates, and matching work over all elements is
charged against a 50M-step budget that fails the import instead of doing it.
eval, Function and the generator/async function constructors now check the nesting of their source like the expression text. join, toLocaleString, flat and JSON.stringify check the run's stack use per level, results nested past the detached levels become [object], and Proxy/Reflect are no longer available to expressions. Each of these overflowed the stack and aborted the app.
148 of the 307 ids. Names from AE 2026's Japanese interface and from Adobe's Japanese help,
which is what settles the `CC` rows staying English and `Smart Blur` being `ブラー(詳細)`.
Three rows rest on elimination and are called out in the PR.
Co-Authored-By: DeepSeek V4.1 Flash <noreply@deepseek.com>
Found while testing crates/geom/src/lib.rs:362-390 (pivot check at line 367)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The per-accessor count checks from #1235 already reject the audit's trigger
(a MAT4 accessor with count 10^11); a regression test now pins it. What was
left: accessors without a bufferView were capped at 16M components each, but
nothing backs them, so one capped accessor referenced from many primitives
allocated 64 MB per reference. The cap is now one budget for the whole file.
Per-element offsets use checked arithmetic as well.
The test checked that Japanese text falls back to an installed Japanese
family, but left the process-global CJK locale at the host's: on a zh-CN
host with a Chinese face installed, han_order puts the Chinese families
first for the shared ideographs and the Japanese-family assertion fails.
Set ja-JP under the TEST_CJK_LOCALE lock and clear the request when the
test ends, as the zh-CN test beside it does.
Tests: effectcraft-text 75 lib + 3 integration passed; cargo fmt --all -- --check passed.
The macOS fallback test selected the first installed family from the
Simplified list, so a Mac that also has PingFang SC (or Microsoft YaHei /
Noto Sans CJK SC) picked that one and then failed an assertion that only
accepted the three macOS faces. Accept any family from the list -- every one
is Chinese -- and check that each installed macOS face covers the shared
ideographs instead.
Also exercise fallback_for itself under a zh-CN request, which the direct
resolve_in lookup bypassed, and serialise the process-global locale with the
layout CJK test so a cached family order cannot leak between them.
Tests: effectcraft-text 75 lib + 3 integration passed; effectcraft-render
233 passed, 1 ignored; cargo fmt --all -- --check and cargo clippy -p
effectcraft-text --all-targets -- -D warnings clean.
The camera's Set Focus Distance to Layer command compared only 'd <= 0.0', which NaN passes, and two finite but extreme positions can overflow their difference to infinity; a stored non-finite focus distance serializes as null and leaves the project unsavable. Reject it, fall back to the zoom plane in the camera evaluation, and count a non-finite focus or depth as in focus. The Classic 3D blur radius itself was unbounded: a 0%-scaled or very distant layer scales it by up to 1e9, and the padded blur buffer sized from it aborts the process. Cap each plane's radius to a padded buffer that fits the renderer's 16 Mpx layer budget, don't blur planes whose pixels cover under a thousandth of a comp pixel, saturate the padded sizes, and refuse padded buffers past the project's maximum layer size. Regression tests for each guard.
The search test now pins every row (layer, Contents, group, path/fill/
Transform) so a future regression that re-adds the inner Contents row or
reorders the flattening fails loudly. Docstrings cover the functions the
diff touches (group_row, all, rec, push_group) for CodeRabbit's
docstring-coverage pre-merge check.