Skip to content

Processing instruction attribute map follow-ups #1504

Open

Description

@annevk

What is the issue with the DOM Standard?

While reviewing WebKit's implementation of processing instruction attributes (WebKit/WebKit#73326) I ran into three problems.

1. Copies don't get an attribute map

Clone a single node sets a ProcessingInstruction copy's target and data, but the copy's attribute map stays empty:

const pi = document.createProcessingInstruction("t", 'a="1"');
pi.cloneNode().getAttribute("a"); // null

Extract and clone the contents then set the clone's data to a substring directly rather than through replace data. So even with cloning fixed, a processing instruction cut by a range keeps a map that doesn't match its shortened data.

I suggest running update attributes from data on the copy in all three places. The WebKit patch re-parses copies from their data, which amounts to the same thing. Copying the map instead would keep entries that setAttribute() added under names the pseudo-attribute grammar can't parse, such as $, but the range steps would still need to re-parse.

2. removeAttribute() rewrites data when the name isn't there

removeAttribute(name) always runs update data from attributes, even when the map has no entry for name. That re-serializes the data and queues a characterData mutation record, and data that doesn't parse as pseudo-attributes is lost:

const pi = document.createProcessingInstruction("php", "echo 1;");
pi.removeAttribute("x");
pi.data; // ""

Element's remove an attribute by name does nothing when the attribute is missing, and neither does toggleAttribute(name, false) on a processing instruction. I suggest returning early when this's attribute map[name] doesn't exist, which is what the WebKit patch does.

I suppose I could be convinced the other way too, but it seems like we need test coverage for this at a minimum.

3. Typo

In update data from attributes, "Replace any U+003D (>)" should be U+003E.

cc @foolip @noamr

Activity

  1. foolip commented on Oct 5, 2026

    @foolip
    Member

    @noamr can you write a test for the removeAttribute() case to confirm what the current behavior in Chromium is? I think we should make it a no-op, but if it isn't I can also review a Chromium CL to make it so.

  2. foolip commented on Oct 5, 2026

    @foolip
    Member

    Typo fix in #1506.

  3. noamr commented on Oct 5, 2026

    @noamr
    Contributor

    @noamr can you write a test for the removeAttribute() case to confirm what the current behavior in Chromium is? I think we should make it a no-op, but if it isn't I can also review a Chromium CL to make it so.

    Yea blink behavior is a no-op for removing non-existing attribute. I'll add a WPT.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions