Giter Site home page Giter Site logo

dom's People

Contributors

annevk avatar arkadiuszmichalski avatar autokagami avatar ayg avatar cvrebert avatar dandclark avatar domenic avatar foolip avatar gsnedders avatar hayatoito avatar jakearchibald avatar jungkees avatar jyasskin avatar lukewarlow avatar mfreed7 avatar ms2ger avatar nox avatar payingattention avatar rbyers avatar saschanaz avatar shaseley avatar shvaikalesh avatar snuggs avatar tabatkins avatar tkent-google avatar tobie avatar upsuper avatar yoavweiss avatar zcorpan avatar zirro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dom's Issues

Consider banning insertNode() of the Range's start node

Test-case:

<!doctype html>
foo
<script>
var range = document.createRange();
range.setStart(document.body.firstChild, 1);
var s = "Body children before: " + document.body.childNodes.length;
try {
  range.insertNode(range.startContainer);
  document.body.textContent = s + ", after: " + document.body.childNodes.length;
} catch (e) {
  document.body.textContent = "Exception";
}
</script>

Firefox outputs "Body children before: 2, after: 3", which matches the spec: there is no special handling of this case, and it winds up happily splitting the text node, then removing the first text node and re-inserting it back where it was, leaving the first portion no longer selected. Chrome throws. IE is the same as Firefox, but if you change the offset from 1 to 0 it outputs "Body children before: 2, after: 2", so it probably just aborts silently in that case.

IE/Firefox's behavior is just silly, and Chrome's seems a bit harsh. I'm inclined to go with Chrome, out of the options available. Failing that, I'd go with IE and at least special-case the scenario where we create an empty text node. Firefox (which is the current spec) would be my last choice.

Document.defaultCharset

IE, Blink and WebKit all have Document.defaultCharset and the usage in Chrome isn't low enough that it can be trivially removed:
https://www.chromestatus.com/metrics/feature/timeline/popularity/428

Can we specify this? The concept itself is already referenced as "an implementation-defined or user-specified default character encoding" in HTML's determining the character encoding, and assuming the side effects of that are observable, this wouldn't actually expose new information about users.

This should probably be blocked on Document.charset.

DOMTokenList#toggle: don't treat everything non-undefined as true

According to the 3rd & 4th step at https://dom.spec.whatwg.org/#dom-domtokenlist-toggle, DOMTokenList#toggle treats every non-false value of the second argument as true. In particular:

var div = document.createElement('div');
div.classList.add('a'); // <div class="a'></div>
div.classList.toggle('a', undefined); // <div class="a'></div>
div.classList.toggle('a', undefined); // <div class="a'></div>

So, according to the spec, these should be div.classList.contains('a') results after the first & second toggle invocation:

1: true
2: true

This is because force is passed and is not false so the first sub-step of the 3rd step doesn't apply.

Now, these are the results in popular browsers:
Chrome 44, Safari 8, Edge:

1: false
2: false

Firefox 40, IE 11 (edit: IE just ignores the second parameter to toggle in all cases):

1: false
2: true

Now, if you change undefined to null in both those cases, all browsers return:

1: false
2: false

This indicates all browsers cast the force value to a boolean and only some of them make an exception for undefined, treating it as an argument not passed.

IMO the Firefox & IE 11 behavior is the most sensible one. This allows to proxy the toggle method without checking the number of arguments passed:

function proxyClassListToggle(node, value, force) {
    // I don't want to do this
    if (typeof force === 'boolean') {
        node.classList.toggle(value, force);
    } else {
        node.classList.toggle(value);
    }
}
proxyClassListToggle(node, 'a');

In any case, the currently specced behavior is not matching reality and is surprising (I'd certainly not expect undefined to be treated as true).

removeEventListener doesn't handle currently dispatching events

It seems like browsers remove an event listener even from the currently dispatched event listener list. Explaining it is kinda complicated, but here's a test which fails with an implementation that is (I hope) according to spec:

    var es = [];
    var ls = [];
    var EventListener1 = function() { ls.push(this); }
    var EventListener2 = function() { ls.push(this); }
    EventListener1.prototype.handleEvent = function(event) { _handleEvent(event); }
    EventListener2.prototype.handleEvent = function(event) { _handleEvent(event); }
    var _handleEvent = function(event) {
      es.push(event);
      ls.forEach(function(l){
        event.currentTarget.removeEventListener("foo", l.handleEvent, false);
      })
    }
    // test
    var listener1 = new EventListener1();
    var listener2 = new EventListener2();
    document.addEventListener("foo", listener1.handleEvent, false);
    document.addEventListener("foo", listener2.handleEvent, false);
    var event = document.createEvent("Events");
    event.initEvent("foo",true,false);
    document.dispatchEvent(event);
    console.log(es.length); // returns 1 in Chrome + FF

So, both listeners remove themselves + the other listener, which seems to cause the currently dispatched event to only get to 1 listener since the other one is removed.

In event listener invoke the spec says to copy the event listener list, which should cause it to not be impacted by changes from removeEventListener (I'd assume).

Syntax-highlight code blocks

Now that we have Bikeshed it should be easy to syntax-highlight the code blocks.

<pre><code class="lang-html">
...
</code></pre>

Maybe I'll PR it tomorrow.

Add caniuse info boxes like the HTML spec

The HTML spec displays little info boxes with relevant caniuse data next to the definitions of various entities.
caniuse likewise has data for many DOM features. It would be nice if the DOM spec could display this data similar to the way it's done in the HTML spec.

Add "inclusive siblings" term

Selectors defines :nth-child()/etc in terms of index among siblings, and it's intended that if the element doesn't have a parent its the only sibling (so :first-child and :last-child both match, etc). I need a term for "an element + its siblings".

Missing spaces in rendered spec HTML

In a few places in the bikeshed source, this:

<a>:scope element</a> <a>context object</a>

is getting compiled to the following HTML (do a View Source on https://dom.spec.whatwg.org/):

<a data-link-type="dfn" href="https://drafts.csswg.org/selectors-4/#scope-element">:scope element</a><a data-link-type="dfn" href="#context-object">context object</a>

Note the lack of a space between the two resulting <a>s.

DOMSettableTokenList needs an associated content attribute

https://dom.spec.whatwg.org/#interface-domsettabletokenlist

A DOMSettableTokenList object is equivalent to a DOMTokenList object without an associated attribute.

The HTML specification is using the DOMSettableTokenList in places where there is an associated attribute. For e.g. HTMLAnchorElement.ping [1]:
[PutForwards=value] readonly attribute DOMSettableTokenList ping;

It needs to be a DOMSettableTokenList because PutForwards needs to be able to set the 'value' attribute on the DOMSettableTokenList.

[1] https://html.spec.whatwg.org/multipage/semantics.html#the-a-element

MutationObserver with querySelector for elements

MutationObserver is a great tool for writing small libraries that operate on specific types of elements.
Examples:

  • Libraries that extend the behavior of particular element
    ** Date/Time pickers on <input type="datetime">
    ** Additional API on some types of <link> elements
  • Libraries that modify custom elements (from outside extension of web-components)
  • Libraries that modify elements with certain attributes:
    ** Libraries that aid with specific aria-* values
    ** Libraries that handle localization of data-l10n-* elements

Currently, MutationObserver API is designed to aid code that wants to operate on all subtree operations of a given root.
But in all those cases the basic premise is that they want to handle specific set of elements. Their additions/removals and possibly modifications.

The result is that in all those cases that I encountered in my work there's a massive amount of noise generated because the library is fishing for a particular element type, while it has to retrieve all node additions/removals and filter them out manually.

In many cases, the ratio of nodes inserted (dynamically or by the parser) to elements the library wants to operate on is 100/1.

My understanding is that the platform is in much better position to optimize filtering the elements for MutationObserver than anything that the MutationObserver callback can do.
Additionally, even if the code logic would be the same, the sole fact that the mutations argument has to be constructed and then the callback for them has to be called, for many mutations that are not relevant to the MutationObserver is a waste of CPU time and memory/GC allocation.

My initial proposal would look something like this:

const observerConfig = {
  attributes: true,
  attributeFilter: ['data-l10n-id', 'data-l10n-args'],
  childNodes: true,
  querySelector: '*[data-l10n-id], *[data-l10n-args]'
}; 

var mo = new MutationObserver(onMutations);
mo.observe(this.doc, observerConfig);

function onMutations(mutations) {
  const targets = new Set();
  const removedTargets = new Set();

  for (let mutation of mutations) {
    switch (mutation.type) {
      case 'attributes':
        targets.add(mutation.target);
        break;
      case 'childList':
        mutation.addedNodes.forEach(node => targets.add(node));
        mutation.removedNodes.forEach(node => removedTargets.add(node));
        break;
    }
  }

  translateElements(targets);
  cleanupAfterElements(removedTargets);
} 

Patch HTML's base URL stuff to be in terms of DOM

Per https://www.w3.org/Bugs/Public/show_bug.cgi?id=20976#c6 base URL will become a concept of documents.

Then we need a way to set the base URL of a document from another specification. When set, this changes the URL of the document and then for each inclusive descendant, in tree order, notifies the node of a base URL change, if the node registered for base URL changes. This allows e.g., <a> to correct its URL.

We also change adopt to run these base URL change notifications. It's unclear whether they should run before the adoption notification or after, or whether the adoption notification by itself is sufficient. I suspect we want to have both separately so you don't forget any.

@ajklein @coonsta @smaug---- does this make sense to you?

Read-only OS time formatting preferences

All operating systems allow user to select time format. Usually between 12h, 24h or follow automatic.

Firefox OS is currently providing navigator.mozHour12 that can take true/false/undefined values and that nicely fits into Intl API:

(new Date()).toLocaleString(navigator.languages, {
  hour12: navigator.mozHour12,
  hour: 'numeric',
  minute: 'numeric'
});

When "use default" is used, mozHour is undefined and Intl uses the default hour12 value for the given locale. If mozHour is specified to either true or false, Intl API follows that.

There's also an event associated with it: timeformatchange that is dipatched on window.

cloneNode underspecified for attribute copying

The spec says:

Copy the following from node to copy, depending on the type of node:
...
(If Element) Its namespace, namespace prefix, local name, and its attribute list.

Copying the attribute list is underspecified. It seems like it could mean any of the following:

  1. Set copy@[[attributeList]] to node@[[attributeList]], i.e., maintain a pointer, so that manipulating either element will affect the other.
  2. Loop through node@[[attributeList]] and append each attribute to copy@[[attributeList]]. In this case, adding or removing attributes from copy will not affect node, but updating existing ones will.
  3. Loop through node@[[attributeList]] and create new Attr objects to append to copy@[[attributeList]].

Consider making `timestamp` a DOMHighResTimestamp

https://dom.spec.whatwg.org/#dom-event-timestamp

Tracking discussion from elsewhere (eg. here) about the plan to try to change Event.timestamp into a DOMHighResTimestamp. In addition to changing the type, what other spec changes are needed?

To me the main value we'd get from timestamp is if it's permitted to carry information about when logically the action occurred (which may be before the "event was created"). This can be used, for example, to get some measure of input event processing latency. WebKit has done this for input events for several years and we've been debating about how to expose this in blink/chromium even longer.

@birtles @majido @tdresser

If we find it's not compatible to make these changes to timestamp then we should still take everything we've learned here and apply it to a new field, eg. `platformTimestamp'.

More bikeshed problems

In 8f812e6 I found it unclear how to link to the URL specification. It should be <a spec=url>URL</a> according to the documentation, but that creates an internal link.

Furthermore, it ended up adding <li><a href="#concept-document-type">dfn for Document</a><span>, in §4.5</span> for something that should really be labeled "type" I think.

@tabatkins, ideas?

Consider new method: getNodesByType

Currently it is easy to get element node types from any given element in a document by getElementsByTagName, but other node types are less straight forward to access. This has many design implications.

Example 1 - comments

Comments exist so that code authors can provide commentary to the code in a way that is immediately available in the source code, but not parsed or processed for user consumption. Although comments are easy for humans to read they are hard to access dynamically, and so are largely worthless for storing any sort of data.

Example 2 - attributes

Attributes are easy to access from any given node, but are challenging to access without touch their respective node directly. This is not particularly helpful. It may be more important to know about the status of one or more attributes by name or their values without care for the element on which they reside. For instance if I wanted to find a data attribute dynamically from a large section of a document there would be no simple means to accomplish this.

Example 3 - text nodes

The most convenient way to access to text content is to ignore the DOM and instead use the less safe innerHTML property. Even still the innerHTML property does not return merely the text node value, but absolutely everything contained by the element.

getNodesByType

All of these issues can be solved by a getNodesByType method. Such a method should provide the same level of availability as the getElementsByTagName method in that:

  • The method is available on all element nodes at node creation
  • The method searches all descendants and not just immediate child nodes
  • The method returns a node list similar to the limitations expressed by the return value of getElementsByTagName

Example functionality

A functional example written in JavaScript can be found at https://github.com/prettydiff/getNodesByType/blob/master/getNodesByType.js. The code example automatically applies the proposed method to all element nodes present in the document, but not to element nodes created with the createElement method.

In order to understand the value of this recommendation I strongly suggest playing with the linked code example on any given large markup document. It is liberating to have this level of immediate access without so much need for walking the DOM tree and without reliance upon a framework.

Do not throw for query() and queryAll()

As the Web evolves, new selectors will be invented. (The CSS4 wiki contains 14 selector proposals.) As that happens, there will be selectors that are understood by some browsers but not yet others.

The current spec commands that browsers throw a SyntaxError when they don't understand a selector. Unless there is an actual syntax error (e.g. a mismatched paren), this should be handled more gracefully. Otherwise, because errors halt JS execution, any site that adopts a new selector is going to break in old browsers unless the developer knew and remembered to wrap the statement in a try/catch.

This makes code both harder to read and harder to write without bugs. For instance, what should be this simple:

var autofilled = node.matches(":autofill, :-webkit-autofill, :-moz-autofill");

becomes this mess:

var autofilled = false;

try {
  autofilled = node.matches(":autofill");

} catch (error) {                                      
  try {
    autofilled = node.matches(":-webkit-autofill");

  } catch (error) {                                      
    try {
      autofilled = node.matches(":-moz-autofill");

    } catch (error) {}
  }
}  

under the current spec.

The simplest solution would be to change the errors to warnings. This would be a welcome change, though it would make it harder to programmatically distinguish between unmatched and unsupported selectors. Perhaps a navigator.supportsSelector API should be added to make this differentiation easier.

Whatever the solution, throwing an error on an unsupported selector is hostile to the future of the web. It should be fixed.

Attribute lowercasing does not appear to match browsers or web-platform-tests

I implemented the current attribute spec in jsdom pretty exactly. However, it failed the following web-platform-test (source):

test(function() {
  var el = document.createElement("div")
  el.setAttribute("ALIGN", "left")
  assert_equals(el.getAttributeNS("", "ALIGN"), null)
  assert_equals(el.getAttributeNS("", "align"), "left")
  assert_equals(el.getAttribute("align"), "left")
}, "setAttribute should lowercase its name argument (upper case attribute)")

In my implementation null is returned for all three calls, because per spec setAttribute doesn't actually do any lowercasing.

If this is intentional we can just update web-platform-tests. I was unclear.

MutationObserver callbacks should be called before executing defer scritps

(Cloned from https://bugzilla.mozilla.org/show_bug.cgi?id=1180927)

This doesn't seem to be spec'ed currently (I filled a W3C bug [0]) but if would be nice to follow the implementation of Chrome and Safari here and execute Mutation Observer callbacks before we execute deferred scripts.

That would allow us to prototype API's with shims that rely on Mutation Observer.

[0] https://www.w3.org/Bugs/Public/show_bug.cgi?id=28920

Clarify intro text on non-normative sections

From here:

@RByers:

Ok, thanks. I'm a little confused by this sentence:

All diagrams, examples, and notes in this specification are non-normative, as are all sections explicitly marked non-normative. Everything else in this specification is normative.

Should it be changed (since there aren't actually any sections explicitly marked non-normative as far as I can see?).

@annevk:

We should maybe change that paragraph, yes. Or consistently markup non-normative sections I guess. Meh. Follow up issue?

Consider specifying document.evaluate and document.createNSResolver

These are currently left to DOM 3 XPath. However, that spec is (a) very old, and thus wrong in a lot of ways; (b) not very large. It could maybe be subsumed and thus give implementations an actual non-crazy reference.

XPathEvaluator.prototype.evaluate has ~0.7% usage and isn't going anywhere. XPathEvaluator.prototype.createNSResolver has ~0.04% and so is also likely here to stay. However XPathEvaluator.prototype.createExpression is at 0.001% and could probably be left out. Which is great because that means we can very likely kill XPathExpression.

Other features of the spec that don't seem to be implemented are XPathException and XPathNamespace.

According to a comment in Blink's source code, XPathEvaluator has a constructor in reality, even if not in the spec.

Credit to @sideshowbarker for bringing this up.

Shorter setAttribute() method

Step 2. is repeat in substep 3.1. Maybe just redefine step 3 (consider only step 2. from "getting an attribute") and we will not have to navigate to another algo?

So change:
[3]. Let attribute be the result of getting an attribute given name and the context object.
to :
[3]. Let attribute be the first attribute in context object's attribute list whose name is name, and null otherwise.

all other steps will be the same.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.