ui: an <IMG> with an empty src names no file
`src=""` was stored verbatim, so the region carried `texture: Some("")`, the resolve asked
the size probe for a nameless file and the renderer searched the patch chain for one and
logged `texture miss: ''` — a defect-shaped warning that can name neither a file nor an
asker. `""` clears on every other texture setter here, as the reference's path arm treats
it like nil (`0x770200`), and `a9ed091eb` closed the three that had stored one; this was
the last route in the UI that still could.
Found by sweeping the rest rather than by a new sighting, and two of the leads this list
carried are now dead: the `CursorPayload` arm it called most likely is unreachable in a
live session (`extract/mod.rs:1020` guards the whole block with `if capture.is_some()`),
and `PortraitSource::File` cannot be empty — `temporary_portrait` always returns a `.blp`.
The M2 and WMO sides filter at parse, and `texture_url("")` would read `'.blp'` rather than
`''`, so the warning's own text says the UI sprite path is where it came from.
Whether this closes the one line in grom's log is unproven: it sat in `benilla-2.log` at
+20.717s, that run may predate `a9ed091eb`, and three measurement launches have since
rotated his logs out. The test is the next sighting: with the filter removed it reports
`texture: Some("")`, and in the fixture the nameless path also reserved the probe's 48 px
of flow under the image — in game the probe answers nothing for a miss, so only the chain
search and the warning were real.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
This commit is contained in:
@@ -288,6 +288,11 @@ fn build(model: &mut Model, fh: FrameHandle, blocks: &[Block]) {
|
||||
let anchors = point
|
||||
.map(|p| vec![anchor_for(prev_block, frame_id, p, next_y)])
|
||||
.unwrap_or_default();
|
||||
// `src=""` names no file, as `""` does on every texture setter (`0x770200`).
|
||||
// Kept, it was the one path left in the UI that could put an empty string where a
|
||||
// texture path goes, and the renderer then searched the patch chain for a nameless
|
||||
// file and warned about a miss it could name neither the file nor the asker of.
|
||||
let src = src.clone().filter(|p| !p.is_empty());
|
||||
model.region_data.insert(
|
||||
rh,
|
||||
RegionData {
|
||||
|
||||
@@ -552,6 +552,54 @@ fn the_books_unsized_crest_is_its_arts_texel_square_not_the_whole_page() {
|
||||
);
|
||||
}
|
||||
|
||||
/// `<IMG src="">` names no file. `""` clears on every texture setter here, as the reference's path
|
||||
/// arm treats it like nil (`0x770200`), but the SimpleHTML image path stored the empty string: the
|
||||
/// region then carried `texture: Some("")`, the resolve asked the size probe for a nameless file,
|
||||
/// and the renderer searched the patch chain and logged `texture miss: ''` — a defect-shaped
|
||||
/// warning naming neither a file nor an asker. It was the last unguarded route in the UI.
|
||||
#[test]
|
||||
fn an_img_with_an_empty_src_names_no_file() {
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
let asked: Rc<RefCell<Vec<String>>> = Rc::new(RefCell::new(Vec::new()));
|
||||
let seen = Rc::clone(&asked);
|
||||
let mut s = script();
|
||||
s.set_texture_size_probe(Box::new(move |path| {
|
||||
seen.borrow_mut().push(path.to_string());
|
||||
Some((64, 48))
|
||||
}));
|
||||
page(&s);
|
||||
s.run(
|
||||
r#"Page:SetText("<HTML><BODY><P>a</P>" ..
|
||||
"<IMG src=\"\"/>" ..
|
||||
"<P>b</P></BODY></HTML>")"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let b = blocks(&s, "Page");
|
||||
assert_eq!(
|
||||
b.len(),
|
||||
3,
|
||||
"the image block is still made, art or none: {b:?}"
|
||||
);
|
||||
assert!(
|
||||
b.iter().all(|x| x.texture.as_deref() != Some("")),
|
||||
"a nameless file was stored as this image's texture: {b:?}"
|
||||
);
|
||||
assert!(
|
||||
!asked.borrow().iter().any(|p| p.is_empty()),
|
||||
"the patch chain was searched for a nameless file: {:?}",
|
||||
asked.borrow()
|
||||
);
|
||||
// And nothing is reserved in the flow for art that does not exist.
|
||||
assert_eq!(
|
||||
b[2].anchor.unwrap(),
|
||||
(Point::TopLeft, Point::BottomLeft, 0.0, 0.0, Rel::Block(0)),
|
||||
"an image with no art reserved height anyway"
|
||||
);
|
||||
}
|
||||
|
||||
/// An unfloated image reserves `GetHeight()` in the flow (`0x78ad07`), its art's texel height when
|
||||
/// it has no `height=`; a floated one reserves nothing, so text runs over it in the reference too.
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user