dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.05k stars 1.55k forks source link

Dart scripts not executing in HTML imports. #21797

Closed DartBot closed 6 years ago

DartBot commented 9 years ago

This issue was originally filed by @si-robertson


When a Dart script is included in a HTML import the script fails to execute. Moving the script into the main HTML document results in normal behaviour, i.e. the script is executed as expected.

HTML document...      <head>     <link rel="import" href="test.htm">   </head>

HTML import document...       <script src="test.dart" type="application/dart"></script>

Dart script...

  void main() {     print("Hello")   }

Dartium : 38.0.2125.0 Reference : http://w3c.github.io/webcomponents/spec/imports/

eukreign commented 9 years ago

This one is a bit of a show stopper. I just stumbled on it as well.

DartBot commented 9 years ago

This comment was originally written by m.raese...@gmail.com


Same to me.

anders-sandholm commented 9 years ago

Added this to the 1.9 milestone. Removed Priority-Unassigned label. Added Priority-Critical, Area-Dartium, Triaged labels.

vsmenon commented 9 years ago

Note, this is actually currently intended behavior. The script in your HTML import is loaded into the page's isolate, but not executed. That behavior is there to support polymer (which registers custom elements included in imports).

The real underlying issue is deciding to what to do when we have multiple Dart scripts on the same HTML page. E.g.,

eukreign commented 9 years ago

What is the work around for now? Is there a minimal amount of code that could be added to the main page to get the dart code in the import to run? How do I get a handle to the isolate from the main page and run it?

My thoughts on your questions:

Since Dart is static once compiled, isn't the question of isolate or not isolate kind of moot? I mean, if you have to support async loading of code in the browser or just importing code much later, this would have to be in an isolate anyways? Correct?

I think it would have to be an isolate per each <link rel="import" ...>. Otherwise how would you "merge" multiple link tags if they load at different times (or if someone creates a link tag programatically later during application execution).

Seems like isolate per tag is really the only way to do this, even though having to now communicate between isolates is annoying. Overtime there will probably be better tools to make this easier.

Anyways, is there some way to get importing working right now? I looked through Polymer code but couldn't figure it out.

A sans-Polymer example of achieving the HTML imports would be awesome. Polymer is great but if I'm targeting only Dartium/HTML5 compatible browser I'd like to just use the browser standard APIs without Polymer APIs/shims.

DartBot commented 9 years ago

This comment was originally written by @si-robertson


@vsm - Ultimately this is a discussion the Dart team need to have.

That being said, I would head down the second path you suggested, load each Dart script into the same isolate. The Dart VM will have to ignore the fact that multiple main() definitions will probably exist and call them in the order it receives them. Relative URLs would be relative to the imported HTML document URL, that's how JavaScript deals with things.

What I wouldn't do tho is say "we can't support this because it would break our polymer library" because that will really annoy a lot of developers. Either support Dart scripts in HTML imports or don't :)

eukreign commented 9 years ago

Regarding knowing which isolate the custom element should execute in...

In JavaScript the file being link'ed to has access to "document" which is the main/root DOM and also "document.currentScript" which is the local DOM of the imported document. This is exposed in the dart:html as well:

https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/dart:html.Document#id_currentScript

I don't know how the internals of custom elements in Dart are implemented but I would think that they should execute in their own isolate but all share the same DOM in addition to having the DOM of their individual pages (document.currentScript).

I guess one problem you'll end up with is bloat if each isolate has its own copy of any framework code, etc. But that's a problem for us programmers to deal with.

sigmundch commented 9 years ago

The way we work around this limitation in Polymer is that we introduced a notion of a loader/initializer that walks your HTML imports, finds the script tags, and invokes methods annotated with @­initMethod within those scripts.

This initialization logic assumes that all html imports are available at the time you execute main. It preserves the order of the imports, but it doesn't guarantee synchronous execution of each main (in Javascript the document parsing is blocked until the script is executed).

These restrictions are important, because to compile to dart2js we need to do the same process in a transformer, compile the code to a new HTML file that has no html imports and include all the initialization calls in a bootstrap script.

To use this today, you can simply:  - include an html import to polymer.html (a transitive import would do)  - in every script you have in an HTML import: annotate methods you want to run with @­initMethod (imported from package:polymer/polymer.dart)  - in the script tag that occurs in your main document write a main that invokes initPolymer() (also in polymer.dart)

This should work in Dartium. Additionally, to make this work after the code is compiled to JS:  - you also need to add the polymer transformer in your pubspec and list your entrypont file (see https://www.dartlang.org/polymer/#building)

We plan to move that logic out of polymer so it can be used independently, but for now, I think that's the easiest way to work around this limitation.

sigmundch commented 9 years ago

Forgot to mention that the restrictions imply that you can't inject HTML imports dynamically, because we wouldn't be able to compile that code with dart2js at least in our current system.

eukreign commented 9 years ago

Any updates on this?

DartBot commented 9 years ago

This comment was originally written by @Emasoft


I guess one problem you'll end up with is bloat if each isolate has its own copy of any framework code, etc. But that's a problem for us programmers to deal with.

This would be a huge problem for me, and I'm not even using polymer. I have a page with more than 15 html imported modules, and if each of those allocates its own copy of the Dart framework and libraries the page is gonna be SLOW and BLOATED. I'll be forced to drop Dart and going back to use javascript only to get decent performances. If this is true, then the issue is not with us programmers but that Dart is just not up to date with the new web standards. This is very serious, please fix this.

kevmoo commented 9 years ago

Set owner to @dgrove.

DartBot commented 9 years ago

This comment was originally written by kurotensh...@autistici.org


I think that my issue (https://code.google.com/p/dart/issues/detail?id=22439) is linked to this.

But only in Dart2JS, in the non-polymer part.

DartBot commented 9 years ago

This comment was originally written by @Emasoft


I just discovered that this affects also SVG files. If you load an SVG file with a javacript code in it, it is executed. But if you load an SVG file with a Dart script in it, it is not. Please fix this.

vsmenon commented 9 years ago

Removed this from the 1.9 milestone. Added this to the 1.10 milestone. Removed Priority-Critical label. Added Priority-Medium label.

kasperl commented 9 years ago

I assume this isn't a high priority issue (not marked as such) so I'm removing the explicit milestone label.


Removed this from the 1.10 milestone.

jakemac53 commented 9 years ago

It is worth noting that the logic polymer uses to get around this has been abstracted out and is now usable with just the web_components package and no framework, so its much lighter weight. Call initWebComponents from your main, and any methods marked up with @­initMethod will be ran from the dart files in your html imports (and other Initializers as well, such as @­CustomElement and @­HtmlImport). Note that you will also need to add the web_components transformer to your pubspec.

jakemac53 commented 9 years ago

There is also no need to include the web_components polyfills as long as you are using the transformer, all html imports will be inlined.