Page MenuHomePhabricator

Parsoid fails for OBJECT element
Closed, ResolvedPublic

Description

For instance if some Parser tag extension returns OBJECT tag as a root element it will make Parsoid fail.
This is because Parsoid depends on ability to set and read property 'data' of elements, but for OBJECT it is not possible, because OBJECT always has data set, and it is string.

More info: http://www.w3schools.com/tags/att_object_data.asp

Also:
var element = document.createElement('object');
typeof element.data; string
element.data = {a:1}
element.data.a
undefined


Version: unspecified
Severity: normal

Details

Reference
bz57394

Event Timeline

bzimport raised the priority of this task from to Medium.Nov 22 2014, 2:33 AM
bzimport added a project: Parsoid.
bzimport set Reference to bz57394.

This seems to be a bug in domino. It should not confuse the data attribute with the .data node object member.

(In reply to comment #1)

This seems to be a bug in domino. It should not confuse the data attribute
with
the .data node object member.

I don't think it's a domino (or domino only) problem, try in a browser:
element = document.createElement('object');
element.setAttribute('data','123');
console.log(element.data);

(In reply to comment #3)

This is indeed correct for object elements according to
http://www.whatwg.org/specs/web-apps/current-work/multipage/the-iframe-
element.html#the-object-element

Gabriel: Do you have a suggestion what the proper fix should look like? Use in Parsoid property different than "data"? (That would be a massive search and replace.)

I see two options here:

  1. Rename data to some other non-conflicting 'expando' property.

Example: .dataobject to rhyme with .dataset

This is used by jquery et al to store a string key for $.data.

  1. Move all data out of the elements themselves and store them in an external data structure keyed on the id of the element. Jquery does this too, but uses an 'expando' property as in 1) instead of the id.

/cc Arlo as he is working on external metadata and stable ids.

I suggest we first do a refactor to use uniformly use:

DU.data(node)

for getters, and maybe

DU.data(node, new_data)

for setters?

Then we can easily experiment with/bikeshed different implementations of DU.data() under the hood -- first probably using a new 'parsoid-data' or 'dataobject' attribute, then later benchmarking against using an external map keyed on id, or an es6 weak map, or an es6 private field, etc.

(In reply to comment #7)

I suggest we first do a refactor to use uniformly use:

DU.data(node)

for getters, and maybe

DU.data(node, new_data)

for setters?

Then we can easily experiment with/bikeshed different implementations of
DU.data() under the hood -- first probably using a new 'parsoid-data' or
'dataobject' attribute, then later benchmarking against using an external map
keyed on id, or an es6 weak map, or an es6 private field, etc.

This plan sounds good to me. I could work on that. Gabriel: Could you confirm that you are ok with that solution?

I'm not a fan of giving DU internal state, so IMO it might make more sense to use either

DU.data(node, env)

or env.getNodeData(node)

I'd suggest both should return a reference to the actual object, which can be modified as needed. To completely replace the data entry, env.setNodeData(node, newData) could be used. Using separate getter/setters lets us add default values too.

We discussed this more on IRC and figured that we could avoid giving DU internal state by attaching extra info to the document object in the longer term and to each node in the shorter term. That would leave us with DU.data(node) I guess.

Change 106429 had a related patch set uploaded by Arlolra:
WIP: Move .data off DOM nodes

https://gerrit.wikimedia.org/r/106429

Change 106429 merged by jenkins-bot:
Move .data off DOM nodes

https://gerrit.wikimedia.org/r/106429