-Ensures that editing code never crashes (outside of JSC/V8 bugs)
JavaScript can still crash -- you just get an unhandled exception instead of a segfault. It's not clear to me why that would be better.
I think the kind of crashes Ojan is talking about are ones caused by DOM mutation events. When we're in a middle of a composite event and fire a DOMModified or whatever appropriate mutation event is, JavaScript can come in and remove node, delete the entire document, or some other crazy things. To avoid this, we have to consider all possible ways in which DOM can be modified. This is really hard to do, and implementing some of editing commands in JavaScript will at least stop us from crashing although it'll probably end in some unexpected behavior. But I'd suspect unexpected behavior is better than crashing for most of users. - Sometimes, instead of an unhandled exception, you'll just get incorrect
behavior that's very hard to track down.
But many incorrect behaviors we get in editing is to produce incorrect DOM, and that's very easy to detect & fix using inspector. Or we have a problem where Position / VisiblePosition becomes null or point to somewhere we don't intend to point but this problem can be solved if we had used JavaScript although incorrect behavior problem persists.
Cons:
-Potentially slower since DOM calls are now JS-->C++ -Potential for regressions due to holes in the layout test coverage -Not statically typed
I notice that you don't mention the added complexity of gluing two languages together for core DOM operations. I think that's probably the main con.
If we exposed a good set of APIs to JavaScript, then I don't think gluing will be much of an issue. Things like typing style and undo/redo could pose a challenge though. However, I don't agree that refactoring inevitably introduces just as many
bugs as rewriting. I would submit that the entire history of the WebKit project demonstrates the value of refactoring over rewriting.
I would agree that refactoring is better than rewriting in general. And porting all commands without making regression is extremely hard at the moment. However, there's something to consider here. Bugs like https://bugs.webkit.org/show_bug.cgi?id=25607 (*Need a way to catch (and cancel?) any execCommand. Maybe document.onexeccommand = ?*) indicate that web developers want more control over how editing commands are performed. For example, new version of Google docs doesn't use our editing ability but rather implements its own, and I'm very sad and embarrassed about it since I've been working full-time just to improve RTE in WebKit. Now, suppose we provided some solution to the bug 25607 and started to let sites overriding editing commands. Naturally, we want to make it easier for web developers to implement their own editing commands. Things like ApplyStyleCommand or typing style might be something developer want to have access to then. Or otherwise they have to implement an equivalent function, class, etc... in JavaScript themselves. And if we did provide a good set of APIs such that web developers themselves can implement their own editing commands, then there's no reason we can't implement our editing commands in terms of those public APIs, putting aside, whether we should do it or not. To put it another way, our not being able to implement the existing editing commands using the public APIs indicates that we're not providing good set of APIs now. Best, Ryosuke
On Aug 4, 2010, at 3:48 PM, Ryosuke Niwa wrote:
I think the kind of crashes Ojan is talking about are ones caused by DOM mutation events. When we're in a middle of a composite event and fire a DOMModified or whatever appropriate mutation event is, JavaScript can come in and remove node, delete the entire document, or some other crazy things. To avoid this, we have to consider all possible ways in which DOM can be modified. This is really hard to do, and implementing some of editing commands in JavaScript will at least stop us from crashing although it'll probably end in some unexpected behavior. But I'd suspect unexpected behavior is better than crashing for most of users.
It’s possible we’ll address this by changing how DOM mutation events work. It’s true that in JavaScript you can’t use a raw pointer by accident, since all pointers to the DOM are automatically RefPtr.
To put it another way, our not being able to implement the existing editing commands using the public APIs indicates that we're not providing good set of APIs now.
Designing and creating a new lower level set of editing functions that you could build higher level commands on top of them seems like a worthwhile thing to do. I’m hoping that our existing editing code provides some clues about what we’d need. I’d love to see some specific proposals. -- Darin
On Tue, Aug 3, 2010 at 5:06 PM, Simon Fraser <simon.fraser@apple.com> wrote:
I assume you plan on maintaining support for the DOM Range API? <http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html>
Yes. We're stuck with them unfortunately. On Tue, Aug 3, 2010 at 5:07 PM, Geoffrey Garen <ggaren@apple.com> wrote:
-Ensures that the APIs we expose to the web are at least good enough for our own editing code
I don't think this necessarily follows. Not everything exposed to the internal editing implementation would necessarily be exposed to the web. If we required that everything exposed to the internal editing implementation be exposed to the web, that would substantially slow development, since every new API would need to be vetted and possibly standardized. So this is either not true or a substantial con.
This would have been a fine point without the last sentence here. I'm not sure how to read that sentence without the implication that I'm either being stupid or manipulative. FWIW, I do think that everything exposed to the internal editing implementation should eventually be exposed to the web. I'll expand on that below. On Wed, Aug 4, 2010 at 3:07 PM, Geoffrey Garen <ggaren@apple.com> wrote:
Are they correspondingly bad at C++? If so, that might be an argument for using JavaScript instead of C++, but a better solution would probably be to find engineers who are good at C++.
I understand your point and I agree with it. But, that's not the point Alex was making and this phrasing is unnecessarily confrontational.
-Ensures that editing code never crashes (outside of JSC/V8 bugs)
JavaScript can still crash -- you just get an unhandled exception instead of a segfault. It's not clear to me why that would be better. I can think of reasons why it would be worse:
Incorrect behavior + an unhandled exception seems better to me than crashing. It's an especially bad user experience to crash while editing given the implied data-loss.
You're not considering the hurt that the editing JavaScript code could put on website code. If the editing memory footprint is large, the GC hit on other websites could be substantial.
I hadn't considered this. Good point. On Wed, Aug 4, 2010 at 12:53 PM, Maciej Stachowiak <mjs@apple.com> wrote:
(1) A new editing API exposed to Web content. (2) A new set of fundamental abstractions to build editing on top of (which maybe has to be the same as #1?) (3) A change in implementation language for much of the editing code from C++ to JavaScript. (4) A from-scratch rewrite of the whole editing subsystem, rather than an incremental refactoring.
On Aug 4, 2010 4:30:01 PM PDT, Darin Adler <darin@apple.com> wrote:
On Aug 4, 2010, at 3:48 PM, Ryosuke Niwa wrote: To put it another way, our not being able to implement the existing editing commands using the public APIs indicates that we're not providing good set of APIs now.
Designing and creating a new lower level set of editing functions that you could build higher level commands on top of them seems like a worthwhile thing to do. I’m hoping that our existing editing code provides some clues about what we’d need. I’d love to see some specific proposals.
On Tue, Aug 3, 2010 at 4:38 PM, Darin Adler <darin@apple.com> wrote:
Inventing a new layer to rebuild editing on top could well be good. Exposing that layer itself to webpages seems like it makes the job even harder rather than easier! Hidden implementation details can be changed more easily than exposed APIs.
I agree that these can be separated out. 1 and 2 are the ones I really care about. 3 and 4 were just an idea of one way to get there. I'm not attached to them. I was picturing that we would first implement all or most of our editing code on top of the editing API and then, once we were confident with it, expose it as a webkit prefixed set of APIs that we propose to the appropriate standards body. I'd like to see an approach to this where we move (incrementally) in the direction of a clearly defined editing API that the editing code uses that we can eventually expose to the web. I'll try and make some concrete proposals in the coming days. On Aug 4, 2010 4:30:01 PM PDT, Darin Adler <darin@apple.com> wrote:
On Aug 4, 2010, at 3:48 PM, Ryosuke Niwa wrote:
I think the kind of crashes Ojan is talking about are ones caused by DOM mutation events. <snip> It’s possible we’ll address this by changing how DOM mutation events work.
We need to change how DOM mutation events work regardless of this proposal IMO. So, lets keep that a separate discussion.
On Aug 4, 2010, at 6:12 PM, Ojan Vafai wrote:
On Tue, Aug 3, 2010 at 5:07 PM, Geoffrey Garen <ggaren@apple.com> wrote:
-Ensures that the APIs we expose to the web are at least good enough for our own editing code
I don't think this necessarily follows. Not everything exposed to the internal editing implementation would necessarily be exposed to the web. If we required that everything exposed to the internal editing implementation be exposed to the web, that would substantially slow development, since every new API would need to be vetted and possibly standardized. So this is either not true or a substantial con.
This would have been a fine point without the last sentence here. I'm not sure how to read that sentence without the implication that I'm either being stupid or manipulative. FWIW, I do think that everything exposed to the internal editing implementation should eventually be exposed to the web. I'll expand on that below.
I think Geoff is not saying that you are stupid or manipulative, just that he disagrees with your conclusion. There are many reasons someone could be wrong, for example that they are honestly mistaken. When I think someone is wrong, I usually assume they are honestly mistaken and can probably be persuaded through logic. Or else, perhaps I am mistaken and will learn that through discussion. When someone else disagrees with me and says I am wrong, I try to assume they thought I made an honest mistake. Sometimes people actually do think I am stupid or are stupid themselves, but I find it makes technical discussions go better if I don't focus on those possibilities. Short version: let's all try to assume good faith on the part of our fellow webkit-dev posters. (That being said, I think a few parts of Geoff's message were a little too snarky, but I think the point you cited here is a reasonable one and not stated in an overly combative way.)
On Tue, Aug 3, 2010 at 4:38 PM, Darin Adler <darin@apple.com> wrote:
Inventing a new layer to rebuild editing on top could well be good. Exposing that layer itself to webpages seems like it makes the job even harder rather than easier! Hidden implementation details can be changed more easily than exposed APIs.
I agree that these can be separated out. 1 and 2 are the ones I really care about. 3 and 4 were just an idea of one way to get there. I'm not attached to them.
I was picturing that we would first implement all or most of our editing code on top of the editing API and then, once we were confident with it, expose it as a webkit prefixed set of APIs that we propose to the appropriate standards body. I'd like to see an approach to this where we move (incrementally) in the direction of a clearly defined editing API that the editing code uses that we can eventually expose to the web.
I'll try and make some concrete proposals in the coming days.
I think this carries an assumption that the right internal abstractions are necessarily also a sensible public API. I don't know if that is a good assumption. First: It is tempting to argue along the lines of "the pieces needed to implement API X must be powerful primitives which should be exposed as API in their own right". But at some level, there has to be a next layer of implementation down that is not exposed, so clearly this line of argument has limits. It can't be API turtles all the way down. Second, often the right internal implementation strategy bears very little relation to the proper public API. For example, CSS is a reasonable constraint-based system to express layout and style rules. Web designers seem to get along ok with it. But internally it's implemented via the render tree, which is a very different abstraction, though it relates to CSS concepts. Exposing the render tree in every detail would greatly constrain our ability to change implementation strategy in the future. So this is one clear-cut case where the implementation abstractions do not necessarily make sense as API. To give a simpler and more pervasive example, we use refcounting throughout many pieces of WebCore, but it would not be appropriate to expose to Web content because it's too low-level. I could cite endless examples where the public API exposed to Web content ends up very different from internal abstractions. The DOM is probably the one major subsystem where there is a lot of similarity, and even then, many critical implementation interfaces are not exposed, nor should they be. Third, in the case of editing specifically, much of the existing behavior, in response to user actions and things like the execCommand API, has *really* weird quirks. And some of its behavior is probably wrong in light of what other browsers do. It may be that the pieces needed to build all those quirky behaviors are not really sane as a public API. Overall, I think the API design process should work in the opposite direction. You don't start by building internal abstractions and then promoting them to API. You start with the API, either one that is required by standards/legacy, or one that is designed to make sense for content authors. Then you design the right architecture and internal interfaces to implement that API correctly and efficiently. If the two end up resembling each other, that is a helpful coincidence, but it's likely that they will not. I think creating better abstractions to implement the legacy editing API on the one hand, and creating a better public editing API for Web content on the other, are both quite difficult problems. If you assume that they must be solved with a single solution, that's probably overconstraining the problem space.
On Aug 4, 2010 4:30:01 PM PDT, Darin Adler <darin@apple.com> wrote:
On Aug 4, 2010, at 3:48 PM, Ryosuke Niwa wrote:
I think the kind of crashes Ojan is talking about are ones caused by DOM mutation events. <snip> It’s possible we’ll address this by changing how DOM mutation events work.
We need to change how DOM mutation events work regardless of this proposal IMO. So, lets keep that a separate discussion.
If mutation events tend to break editing, one simple solution is to turn then off within the scope of editing operations and send a single mutation event at the end. It's not clear if that kind of solution would be appropriate to expose to Web content, though; you can't do the RAII idiom in JavaScript so there could be too much risk of staying stuck in the "mutation events deferred" state. On the other hand, a dynamic-wind-style solution might be appropriate. This is one tiny example of how the same abstractions might not be right internally and externally. Regards, Maciej
On Thu, Aug 5, 2010 at 1:59 AM, Maciej Stachowiak <mjs@apple.com> wrote:
On Aug 4, 2010 4:30:01 PM PDT, Darin Adler <darin@apple.com> wrote:
On Aug 4, 2010, at 3:48 PM, Ryosuke Niwa wrote:
I think the kind of crashes Ojan is talking about are ones caused by DOM mutation events. <snip> It’s possible we’ll address this by changing how DOM mutation events work.
We need to change how DOM mutation events work regardless of this proposal IMO. So, lets keep that a separate discussion.
If mutation events tend to break editing, one simple solution is to turn then off within the scope of editing operations and send a single mutation event at the end. It's not clear if that kind of solution would be appropriate to expose to Web content, though; you can't do the RAII idiom in JavaScript so there could be too much risk of staying stuck in the "mutation events deferred" state. On the other hand, a dynamic-wind-style solution might be appropriate. This is one tiny example of how the same abstractions might not be right internally and externally.
If we don't already have it, we definitely want a RAII for turning off mutation events (or at least ASSERTing that we're not trying to fire them) for the parser. The new and old tree builders might explode if they ever fire a mutation event. Adam
On Thu, Aug 5, 2010 at 1:59 AM, Maciej Stachowiak <mjs@apple.com> wrote:
I think this carries an assumption that the right internal abstractions are necessarily also a sensible public API. I don't know if that is a good assumption.
You're right that I was making this assumption. My intuition is that the majority of the APIs we'd need internally will be the same as the ones we'd want in a public API, but I can believe that won't be true across the board. I've been very focused on this Position/Range discussion, where I do think a very similar, if not identical API makes sense. Anchoring to nodes instead of index+offset is just a better API for editing web content. I think creating better abstractions to implement the legacy editing API on
the one hand, and creating a better public editing API for Web content on the other, are both quite difficult problems. If you assume that they must be solved with a single solution, that's probably overconstraining the problem space.
Fair enough. Ojan
participants (5)
-
Adam Barth
-
Darin Adler
-
Maciej Stachowiak
-
Ojan Vafai
-
Ryosuke Niwa