Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dart2js: compiled html apps are not forward compatible: new browsers can break deployed apps #13285

Closed
jmesserly opened this issue Sep 12, 2013 · 20 comments
Assignees
Labels
library-html P1 A high priority bug; for example, a single project is unusable or has many test failures type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) web-dart2js

Comments

@jmesserly
Copy link

dart2js compiled apps are not safe to be deployed long term. Browsers can break Dart apps in ways that would not break an application written purely in JavaScript.

dart2js+html's dynamic dispatch works roughly like:

  1. find the target object's JS type name (see getFunctionForTypeNameOf in native_helper.dart)
  2. map JS type name to corresponding Dart type
  3. apply Dart semantics for that method call

Some type names like "Node" and "HTMLElement" are specified and likely to be safe to use for the foreseeable future.

However, many other type names can and do get changed by browsers between major releases. For example, Firefox renamed the type that backs ".attributes" to MozNamedAttrMap, and this broke all use of HTML attributes.
(http://code.google.com/p/dart/issues/detail?id=11879). According to Pete this happened twice with IE11 as well. I think we have seen similar issues in Blink rolls.

How do we solve this for Dart 1.0? We must have a way to deploy apps that is not going to need recompilation whenever a browser vendor releases a new version...

Other scary facts about our current dispatch:

  • it relies on User Agent sniffing
  • both IE and Firefox have ad hoc rename tables (see typeNameInFirefox, typeNameInIE)
  • everything falls back to Object.prototype.toString. From the perspective of HTML/DOM standards, the behavior here is unspecified. Typical JavaScript programs don't depend on it except for debugging.
@dgrove
Copy link
Contributor

dgrove commented Sep 12, 2013

cc @kasperl.

@blois
Copy link
Contributor

blois commented Sep 12, 2013

Recent IE 11 issue was bug #­12744- MouseEvent went to MSPointerEvent in IE11 Preview, then PointerEvent in RTM.

Additionally, there are cases such as FireFox's window.location where it's just a JS object and we haven't figured out any good way of determining the type. We handle this with a hack where we wrap it into a Dart wrapper which implements Location, but this is expensive and even relies on a runtime exception to detect (though this could probably be improved).

Blink has been discussing shifting more implementation into JS (such as promises), I'm not sure how our type detection will handle this.

@peter-ahe-google
Copy link
Contributor

My guess is that for each of these problematic objects, we have to look at how the vendor documents they can be recognized. For pointer events, I guess we have to see if there is a "pointerType" property (and the object is an instance of Event?)

@blois
Copy link
Contributor

blois commented Sep 13, 2013

That would probably work for the IE MouseEvent->PointerEvent change, PointerEvent is just a new subclass of MouseEvent.

For the Firefox NamedNodeMap->MozNamedAttrMap change, the NamedNodeMap type no longer exists.

The list of all of the 'name differences' that we've hit so far can be found at:
https://code.google.com/p/dart/source/browse/branches/bleeding_edge/dart/tools/dom/scripts/generator.py#­89

@kasperl
Copy link

kasperl commented Sep 17, 2013

At some point we talked about allowing our "type name" code to be updated separately from compiled apps (as a separate .js file downloaded from somewhere independent of the individual apps). Not sure if anyone thought more about that.

@kasperl
Copy link

kasperl commented Sep 18, 2013

Added this to the M7 milestone.

@blois
Copy link
Contributor

blois commented Sep 23, 2013

Is that the dartExperimentalFixupGetTag function?

It might be helpful to also provide a way to pro-actively mark the type of objects-
// To work around the FF location bug:
window.dartTypeInstance(window.location, 'Location');

// To add a type to a polyfill class:
window.dartTypePrototype(JsMutationRecord.prototype, 'MutationRecord');

Hosting the patching code on a third-party server is what would be needed for zero-maintenance of these, but it seems quite undesirable to rely on external patching to keep an existing app running. Better than the current state though.

@jmesserly
Copy link
Author

Shipping a separate type name map sounds intriguing. I think the challenge would be ensuring it is updated fast enough, perhaps by having someone track pre-release versions of the popular web browsers. It would be bad if, for example: Firefox rolls out a new version and a popular web site is down for a few hours while we release an updated JS file :)

@rakudrama
Copy link
Member

I am going to take on some of the pre-emptive patching.
I'll try to get some of it done by M7, but it is unlikely to be completed before M7.


Set owner to @rakudrama.

@kasperl
Copy link

kasperl commented Sep 25, 2013

Removed Priority-Critical label.
Added Priority-High label.

@kasperl
Copy link

kasperl commented Sep 25, 2013

Changed the title to: "dart2js: compiled html apps are not forward compatible: new browsers can break deployed apps".

@rakudrama
Copy link
Member

Marked this as blocking #9654.

@kasperl
Copy link

kasperl commented Oct 2, 2013

Removed this from the M7 milestone.
Added this to the M8 milestone.

@rakudrama
Copy link
Member

I have implemented the following:
A global dartNativeDispatchHooksTransformer that can be set to a function or array of functions that can replace or augment these methods:
getTag, getUnknownTag, prototypeOfTag

I have not yet implemented the idea of discriminating functions that can be patched.
I don't think this provides any functionality that is not already possible by adding code to getTag.
The discriminating logic can be added under an 'if' in getTag.
It is not clear that the extra complexity and code size (2-3k unminified) pays its way.
It is a matter of efficiency, since the discriminator can identify the subclass without the overhead of calling the more general getTag.

@kasperl
Copy link

kasperl commented Jun 4, 2014

Removed this from the M8 milestone.
Added this to the 1.6 milestone.

@DartBot
Copy link

DartBot commented Jun 19, 2014

This comment was originally written by @bp74


Currently i'm working on my library (StageXL) to make it compatible with CocoonJS. Things work pretty good on Android and not so good on the iPhone. The main reason is that some types are not compatible with Dart. I use dart:js to work around the incompatible TouchEvent type, but it's painful to do the same for the ImageElement, AudioElement, etc (which are only incompatible on the iPhone but not on Android).

Those types in CocoonJS are perfectly compatible in JavaScript and even if Dart will never officially support JavaScript for CocoonJS it would be very helpful if i could register those types on my own and from that point on Dart would be able to map them to the right Dart types.

@blois
Copy link
Contributor

blois commented Jun 19, 2014

#­16- an example of providing type mappings for dart2js can be found at https://code.google.com/p/dart/source/browse/branches/bleeding_edge/dart/pkg/web_components/lib/dart_support.js#­25

This example is used to map JS polyfills to Dart types.

@DartBot
Copy link

DartBot commented Jun 21, 2014

This comment was originally written by @bp74


#­17- Thanks the code works fine and would be really useful if CocoonJS would not use generic types like ImageElement = Object, AudioElement = Object, TouchEvent = Event, etc. I'm in contact with Ludei and let's hope they can change this behavior.

Sorry if this is a little bit off topic, but i thought it is a similar problem.

@jmesserly jmesserly added Type-Defect P1 A high priority bug; for example, a single project is unusable or has many test failures web-dart2js library-html labels Jun 21, 2014
@jmesserly jmesserly added this to the 1.11 milestone Jun 21, 2014
@sigmundch sigmundch removed this from the 1.11 milestone Jun 23, 2015
@kasperpeulen
Copy link

How is the process on this issue going, it is marked as high, but it has no milestone.

This issue has never been a problem for me, but someone in this reddit posts, claims that he had to wait for a new firefox update to make his dart app work again in firefox after a dart update:
https://www.reddit.com/r/javascript/comments/3tvgrq/fiber_launched_this_week_as_googles_first_angular/

@kevmoo kevmoo added type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) and removed accepted labels Feb 29, 2016
@kevmoo kevmoo removed the Type-Defect label Mar 1, 2016
@jmesserly
Copy link
Author

IDK how you're feeling about this @rakudrama but I'm inclined to close this as stale, I think we're in a good place now and browsers are a lot more sane these days generally. Feel free to reopen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
library-html P1 A high priority bug; for example, a single project is unusable or has many test failures type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) web-dart2js
Projects
None yet
Development

No branches or pull requests

10 participants