- From: Lachlan Hunt <lachlan.hunt@lachy.id.au>
- Date: Sat, 12 Jul 2008 12:23:45 +0200
- To: public-webapps <public-webapps@w3.org>
Hi, Recently, we had discussion on pubilc-webapi about what should be done with the current NSResolver, and whether or not it was causing more problems than it's worth. I realise that there is work going into implementing the current NSResolver as currently specced, but no implementation has shipped yet, so it's not too late, and the implementation experience has been very useful for this research and in making a more informed decision. There are a few alternative proposals that have been discussed, including the following * Dropping the feature (or bug, if you prefer) entirely * Deferring it until v2 and having browsers ship without support for NSResolver in inital implementations - (Note: The spec already allows implementations to ship without such support anyway) * Use the JS Object notation: {"prefix": "uri", ...} * Requiring a Node with appropriate namespace declarations to be passed. * Defining a new native object that can have namespace declarations added to it by scripts. var resolver = new NamespaceResolver() resolver.add("prefix", "uri"); * Defining the nsresolver to be a DOMString with various possible syntaxes: - a space separated set of "prefix=uri prefix2=uri2" - JSON syntax '{"prefix": "uri"}' - the @namespace syntax defined in CSS. "@namespace 'defaultns'; @namespace prefix 'uri'" "@namespace url(defaultns); @namespace prefix url(uri)" All of these have advantages and disadvantages and I intend to evaluate each one. But first, the problems with the current function approach that need to be addressed, a the use cases that need to be addressed by any potential solution. * Resolving the default namespace The DOM 3 Core Node.lookupNamespaceURI required null to be passed in order to obtain the default namespace, but it would be better for both authors and implementers if this were "" instead. Browsers differ significantly in how they implement Node.lookupNamespaceURI() anyway, so perhaps the theoretical compatibility with the DOM 3 Core spec isn't all that necessary. * null/undefined Return Values The spec currently requires null and undefined return values to be treated the same as an empty string. This was done to make things more convenient for authors. However, Boris has reported this is an implementation problem because they are converted to "null" and "undefined" as a result of the return value being defined as a DOMString. * Hostile resolver - DOM Modification Functions could potentially modify the DOM while resolving namespaces, which could result in non-interoperable behaviour. To ensure as much interop as possible, the spec could require all prefixes and the default NS to be resolved prior to finding any potential match. But this prevents implementations from performing optimisations, such as not resolving namespaces in unnecessary cases. Should the implementation only return matches present during the post modification DOM? Consider <p><svg:svg>...</svg:svg></p> querySelectorAll("p, svg|svg", resolver); If the implementation sees that the p matches without having to resolve the SVG prefix, but then while resolving it to see if the <svg:svg> element matches, the P element is removed from the DOM. Should the p element still be returned? Possible behaviour to define to handle this: - Leave it explicitly undefined, allow for potentially non-interoperable behaviour here. (Not ideal) - Require all prefixes to be resolved first - Allow exception to be thrown * Moving nodes between documents If lookupNamespaceURI() moves a node from an XML document to an HTML document using document.adoptNode(), the case sensitivity of selectors is unclear. e.g. Assume this script is running in an HTML document var otherDocument = ... // some other XML document. var foo = otherDocument.getElementById("foo"); function resolver() { document.adoptNode(foo); // Move node from otherDocument to this one return ""; } foo.querySelector("p", resolver); Because foo was initially in an XML document, the selector would have been case insensitive. But since the resolver moved it into an HTML document while resolving the default ns, does it now become case insensitive? Possible ways to handle this: * Require the selector to remain case sensitive * Allow implementation to throw exception; same as DOM Modification issue above * Hanging How to protect against silly authors that do this? function resolver() { while(true); } or other things causing infinite loops or infinite recursion. Loops could just run forever, browsers already need to ensure they don't completely hang the UI. For recursion, browsers will throw a recursion exception when it reaches the recursion limit. * Navigating away from the page var iframe = getElementById("theIframe"); function resolver() { iframe.location = "..."; } iframe.document.querySelectorAll("p", resolver); I'm not really sure what should or could happen there. Should it return no results? Does it keep the document around in memory until the query finishes and returns the elements that were in the document? Throw an exception? * Returning inconsistent results If the browser resolves a prefix multiple times, e.g. if given the selector "x|p x|span", what if it returns inconsistent results? Opera currently does this, but still uses first value returned anyway. There are probably a few other issues that I have forgotten about. But given the relatively large amount of time devoted entirely to this NSResolver issue, and the relatively minor use cases compared with the authors who won't even use namespaces, it's clear that the function is more trouble than it's worth, so it really is worth investigating alternative solutions. The use cases, problems and requirements that need to be addresses by any possible solution are: * Relatively easy for authors to use * Easy for browsers to implement * Must be able to declare the default namespace * Must be able to declare prefixes * Must be able to declare prefixes independently from those used in the document * Must be suitable for use in all implementations, not just ECMAScript * Must not suffer from the same problems as the function approach * Easy to define in the spec These are the potential solutions, and their pros and cons. * Use the JS Object notation: {"prefix": "uri", ...} (Hash map) pro: Easy and familiar for authors pro: Browsers already support it con: Only suitable for ECMAScript, though other language bindings could use their own Map implementation * Requiring a Node with appropriate namespace declarations to be passed. pro: Easy for implementations to obtain the namespaces con: More complex for authors to create a node and set all necessary namespaces con: Using a Node from the document itself ties the script to use the same prefixes as the document. * Defining a new native object that can have namespace declarations added to it by scripts. var resolver = new NamespaceResolver() resolver.add("prefix", "uri"); pro: Easy for authors to use pro: Relatively easy for implementers to implement con: Requires me to specify a new interface * DOMString: a space separated set of "prefix=uri prefix2=uri2" pro: Easy for authors con: Requires new parsing requirements to be specified and implemented con: Need to reserve a special prefix for declaring the default ns DOMString: JSON syntax '{"prefix": "uri"}' pro: Easy and familiar for authors pro: Easy for browsers to implement con: Need to reserve a special prefix for declaring the default ns con: Quite verbose for authors DOMString: the @namespace syntax defined in CSS. "@namespace 'defaultns'; @namespace prefix 'uri'" "@namespace url(defaultns); @namespace prefix url(uri)" pro: Familiar syntax for authors pro: Syntax and parsing requirements already defined in CSS pro: Already implemented by browsers pro: Shifts case sensitivity of prefixes issue from this spec into css3-namespaces (makes them case insensitive) pro: Already handles both prefixes and the default ns pro: Suitable for non-ECMAScript languages as well pro: Easy for me to define con: Slightly verbose for authors, but less verbose than JSON con: Browsers need to fix their buggy case folding implementations Given the overall simplicity of the @namespace approach for authors, implementers and spec writers, I'm in favour of replacing the current NSResolver approach in the spec entirely. I will draft up the replacement specification for this shortly and pending any major objections, hopefully this will allow us to resolve this issue once and for all. -- Lachlan Hunt - Opera Software http://lachy.id.au/ http://www.opera.com/
Received on Saturday, 12 July 2008 10:24:28 UTC