Skip to content
This repository has been archived by the owner on Sep 20, 2019. It is now read-only.

Script imported from template tag does not evaluate #151

Closed
molst opened this issue Jan 14, 2015 · 13 comments
Closed

Script imported from template tag does not evaluate #151

molst opened this issue Jan 14, 2015 · 13 comments

Comments

@molst
Copy link

molst commented Jan 14, 2015

A script imported from a template tag, cloned and appended into the main document does not get evaluated in Firefox and IE11. It works in Safari and Chrome.

Switching the template to a div seems to work better, but gives a type error "wrapper is undefined" in webcomponents.js.

This repo demonstrates the problem.

(use version 0.5.2 of webcomponents.js)

@addyosmani
Copy link
Member

In FF I'm currently seeing this using your repro:

screen shot 2015-02-13 at 12 59 03

Are you still seeing broken behaviour on imported/cloned template content with 0.5.4?

@molst
Copy link
Author

molst commented Feb 14, 2015

Unfortunately, that does not confirm the test case OK. Sorry for the not very obvious message. I've updated the repo with clearer messages and use of webcomponents 0.5.4 and am still seeing the problem. It should say "Component SCRIPT loaded. Test case OK!" when it works.

@garlicnation
Copy link
Contributor

From @ebidel in Polymer/polymer#1197:
Test: http://jsbin.com/qegitukowe/1/edit?html,output

The import used in the demo contains a <template> with a <script> in it.

Expected: In Chrome, when you click that page it updates the <template ref>
with "content2" and alerts 10.
Actual: In FF (polyfill), the template content is updated but the alert never happens (e.g. the script doesn't execute).

This may have something to do with template being in another document and the polyfill using .innerHTML.

@garlicnation
Copy link
Contributor

@atotic

@atotic
Copy link

atotic commented Feb 26, 2015

Looking into it. Looks like importNode is flubbered on FF.

@garlicnation
Copy link
Contributor

Some of @atotic's notes:

Looked into FF source again. If you look at nsNodeUtils::CloneAndAdopt, there is a hasHadScriptHandlingObject variable. That var explains cloned nodes not getting executed. You get to CloneAndAdopt from importNode...

http://lxr.mozilla.org/mozilla-central/source/dom/base/nsNodeUtils.cpp#344

https://github.com/atotic/web-component-polyfill-test

all browsers refuse to execute a clonedNode
but Chrome executes importedNode
FF does not

@garlicnation
Copy link
Contributor

@garlicnation
Copy link
Contributor

The fix is to manually recreate a template node before attaching it to the document. There are a couple potentially appropriate locations for this:

In the Polymer source in template stamping code, after calling importNode and before calling attach.
In the CustomElements polyfill, by wrapping document.importNode.

@atotic
Copy link

atotic commented Mar 4, 2015

We do not have to recreate the entire template, just the script elements. After import, I loop though all script nodes, create clone with create element, insert the clone, and remove originals. Sample code is in my test case branch.

Aleks
-- sent from my phone

On Mar 4, 2015, at 3:40 PM, AJ Ortega notifications@github.com wrote:

The fix is to manually recreate a template node before attaching it to the document. There are a couple potentially appropriate locations for this:

In the Polymer source in template stamping code, after calling importNode and before calling attach.
In the CustomElements polyfill, by wrapping document.importNode.


Reply to this email directly or view it on GitHub.

@garlicnation
Copy link
Contributor

@atotic is right, I misworded things.

Here's his example workaround:

function swapScript(script) {
  if (script.nodeName != 'SCRIPT')
    throw new Error("swapScript requires script");
  var clone = document.createElement('script');
  clone.appendChild( document.createTextNode(script.textContent));
  script.parentNode.insertBefore(clone, script);
  script.parentNode.removeChild(script);
};

var templateClone = document.importNode(importLink.import.content, true);
  var scripts = templateClone.querySelectorAll('script');
  for (var i=0; i<scripts.length; i++)
    swapScript(scripts[i]);
  document.body.appendChild(templateClone);

@molst
Copy link
Author

molst commented Mar 9, 2015

Thanks for the workaround. I've verified it to work in FF and IE11. Cheers!

@garlicnation
Copy link
Contributor

The costs of querySelectorAll on every importNode is too high to pay in the polyfill when it's so easy to work around. I'm going to close this bug with a known workaround unless there's significant clamor to add the feature.

It's possible to override document.importNode to globally work around this issue.

@dnbard
Copy link

dnbard commented Jul 22, 2015

Hello, thanks for the snippet.
Don't you think that such valuable workaround should be described somewhere at the main page ?
Like here?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants