HighDots Forums  

Re: How to make injected js execute?

Javascript JavaScript language (comp.lang.javascript)


Discuss Re: How to make injected js execute? in the Javascript forum.



Reply
 
Thread Tools Display Modes
  #1  
Old   
Jon Maz
 
Posts: n/a

Default Re: How to make injected js execute? - 08-20-2007 , 05:20 AM






Hi Peter,

Thanks for that - I had no idea this would be a complex issue. A couple of
observations:

1. for (possibly demented) reasons of my own it's actually an arbitrary mix
of js and html that I want to inject into the page, so of the 5 methods
offered in the other thread:

* Change Source- attempts to change the .src property of a script element.
* Change innerHMTL - inserts a script string via innerHTML.
* createElement - uses createElement to create a script block with a .src
attribute.
* Change .text - changes the .text property of a script element.
* createTextNode - creates the text part of a script element using
createTextNode

.... I think only the .innerHTML one is an option for me.

2. A lot of the thread you referred me to is about IE, whereas my observed
issue affects Firefox too.

My fingers are still crossed that there's an answer to this for me, but hope
is ebbing away fast...

Cheers,

JON



Reply With Quote
  #2  
Old   
Peter Michaux
 
Posts: n/a

Default Re: How to make injected js execute? - 08-20-2007 , 11:55 AM






On Aug 20, 2:20 am, "Jon Maz" <jon... (AT) surfeu (DOT) deno.spam> wrote:
Quote:
1. for (possibly demented) reasons of my own it's actually an arbitrary mix
of js and html that I want to inject into the page, so of the 5 methods
offered in the other thread:

* Change Source- attempts to change the .src property of a script element.
* Change innerHMTL - inserts a script string via innerHTML.
* createElement - uses createElement to create a script block with a .src
attribute.
* Change .text - changes the .text property of a script element.
* createTextNode - creates the text part of a script element using
createTextNode

... I think only the .innerHTML one is an option for me.

2. A lot of the thread you referred me to is about IE, whereas my observed
issue affects Firefox too.

My fingers are still crossed that there's an answer to this for me, but hope
is ebbing away fast...

I wrote a library that does what you want to do...sort of.

<URL: http://forkjavascript.org/mutate/docs>

What my script does it scan through the HTML that is about to be
inserted and pluck out all the script bits. It inserts the other HTML
and then process the JavaScript bits. Instead of dynamic script
insertion, as Randy has investigated, I just eval() the script bits.
This is more cross-browser but has scope implications.

If you are in control of writing the JavaScript bits then you can just
write the JavaScript bits so there are no problems with using eval().
There is only one little complication and it is with naming global
variables explicitly as global properties instead. Here is the
pertinent part of the above page regarding this issue.

<blockquote>
The main issue is the scope of entities (eg. variables or functions)
defined in the evaluated script. Because the call to eval() occurs
inside a JavaScript function, entities defined in the evaluated script
may not persist after eval() returns. If you do want to define global
entities you may look at writing something like the following snip
inside the code block.

window.foo = 2; // instead of var foo = 2
</blockquote>

If you are not in charge of the script bits and want to use script
insertion you could combine my library and one of the solutions posted
in the other c.l.j thread about script insertion.

Peter



Reply With Quote
  #3  
Old   
Dr J R Stockton
 
Posts: n/a

Default Re: How to make injected js execute? - 08-20-2007 , 02:40 PM



In comp.lang.javascript message <1187625350.498917.232880 (AT) i38g2000prf (DOT) go
oglegroups.com>, Mon, 20 Aug 2007 15:55:50, Peter Michaux
<petermichaux (AT) gmail (DOT) com> posted:

Quote:
If you are in control of writing the JavaScript bits then you can just
write the JavaScript bits so there are no problems with using eval().
There is only one little complication and it is with naming global
variables explicitly as global properties instead. Here is the
pertinent part of the above page regarding this issue.
Do you see any future problem in
<URL:http://www.merlyn.demon.co.uk/estrdate.htm#TT>?

One enters code in the blue bit just above heading "Testing and Timing"
(the textarea is preloaded with a function body, but Javascript does not
know that on loading, so use DEFINE & UNDEFINE), and executes it (check
the checkbox) in the next blue bit.

It's OK in IE6, FF2, Opera9 (though FF has a visible layout flaw).

--
(c) John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v6.05 IE 6.
Web <URL:http://www.merlyn.demon.co.uk/> - w. FAQish topics, links, acronyms
PAS EXE etc : <URL:http://www.merlyn.demon.co.uk/programs/> - see 00index.htm
Dates - miscdate.htm moredate.htm js-dates.htm pas-time.htm critdate.htm etc.


Reply With Quote
  #4  
Old   
Thomas M. Farrelly
 
Posts: n/a

Default Re: How to make injected js execute? - 08-20-2007 , 05:20 PM



On Mon, 20 Aug 2007 15:55:50 +0000, Peter Michaux wrote:

Quote:
On Aug 20, 2:20 am, "Jon Maz" <jon... (AT) surfeu (DOT) deno.spam> wrote:
[...]
blockquote
The main issue is the scope of entities (eg. variables or functions)
defined in the evaluated script. Because the call to eval() occurs
inside a JavaScript function, entities defined in the evaluated script
may not persist after eval() returns. If you do want to define global
entities you may look at writing something like the following snip
inside the code block.

if window is the root scope ( do not remember if it is, but I recall there
beeing a way to reference it. ) I would write

eval( "function() {"
+ THE_CODE_FROM_THE_SCRIPT_TAG +
"}" ).apply( window, [] ) ;

to get correct scope. This should fix your scope. In tin-tags, I do:

eval( "function() {"
+ THE_CODE_FROM_THE_SCRIPT_TAG +
"}" ).apply(
{ tag:THE_ACTUAL_TAG, ... }, []
) ;

Something like that, anyways. Because it's is a good thing to not effect
global scope by everything you do.

If you want to look at it, it is at tin-tags.org ( beta, FF only ) :-)

Quote:
window.foo = 2; // instead of var foo = 2
/blockquote

If you are not in charge of the script bits and want to use script
insertion you could combine my library and one of the solutions posted
in the other c.l.j thread about script insertion.

Peter
cheers Thomas


Reply With Quote
  #5  
Old   
Peter Michaux
 
Posts: n/a

Default Re: How to make injected js execute? - 08-20-2007 , 06:27 PM



On Aug 20, 2:20 pm, "Thomas M. Farrelly" <tho... (AT) metatools (DOT) org> wrote:
Quote:
On Mon, 20 Aug 2007 15:55:50 +0000, Peter Michaux wrote:
On Aug 20, 2:20 am, "Jon Maz" <jon... (AT) surfeu (DOT) deno.spam> wrote:
[...]
blockquote
The main issue is the scope of entities (eg. variables or functions)
defined in the evaluated script. Because the call to eval() occurs
inside a JavaScript function, entities defined in the evaluated script
may not persist after eval() returns. If you do want to define global
entities you may look at writing something like the following snip
inside the code block.

if window is the root scope ( do not remember if it is, but I recall there
beeing a way to reference it. ) I would write

eval( "function() {"
+ THE_CODE_FROM_THE_SCRIPT_TAG +
"}" ).apply( window, [] ) ;

to get correct scope.
A function's apply() will set the scope the "this" keyword when the
function runs. There is more to the script insertion problem then just
resolving "this". Here is an example where the script to be inserted
is "var foo=1;"

var foo=4;
eval( "function() {var foo=1;}" ).apply( window, [] ) ;
alert(foo);

In this case the alert says "4" but successful script insertion, as
has been defined and discussed, would result in an alert of "1". The
goal is to have the script run in the global scope completely.

Peter



Reply With Quote
  #6  
Old   
Richard Cornford
 
Posts: n/a

Default Re: How to make injected js execute? - 08-20-2007 , 07:02 PM



Thomas M. Farrelly wrote:
Quote:
On Mon, 20 Aug 2007 15:55:50 +0000, Peter Michaux wrote:
[...]
blockquote
The main issue is the scope of entities (eg. variables or
functions) defined in the evaluated script. Because the
call to eval() occurs inside a JavaScript function, entities
defined in the evaluated script may not persist after eval()
returns.
This statement is, of course, false. Because the eval execution context
uses the variable object from the execution context in which it is
executed any functions or variables it declares must persist after it
finishes executing. They persist for precisely as long as that Variable
object persists.

Quote:
If you do want to define global entities you may look at
writing something like the following snip inside the
code block.


if window is the root scope ( do not remember if it is, but
I recall there beeing a way to reference it. ) I would write

eval( "function() {"
+ THE_CODE_FROM_THE_SCRIPT_TAG +
"}" ).apply( window, [] ) ;

to get correct scope.
I take it then that you have no idea what scope is in javascript or how
it works.

But why use - Function.prototype.apply - and create a new Array each
time to pass a zero length arguments list when you could use -
Function.prototype.call - and leave the arguments to the function call
out entirely?

Quote:
This should fix your scope.
snip

It will not, as it does not even come close to addressing the issue.

Richard.



Reply With Quote
  #7  
Old   
Peter Michaux
 
Posts: n/a

Default Re: How to make injected js execute? - 08-20-2007 , 07:38 PM



On Aug 20, 4:02 pm, "Richard Cornford" <Rich... (AT) litotes (DOT) demon.co.uk>
wrote:
Quote:
Thomas M. Farrelly wrote:
On Mon, 20 Aug 2007 15:55:50 +0000, Peter Michaux wrote:
[...]
blockquote
The main issue is the scope of entities (eg. variables or
functions) defined in the evaluated script. Because the
call to eval() occurs inside a JavaScript function, entities
defined in the evaluated script may not persist after eval()
returns.

This statement is, of course, false. Because the eval execution context
uses the variable object from the execution context in which it is
executed any functions or variables it declares must persist after it
finishes executing. They persist for precisely as long as that Variable
object persists.
I meant to write "may not persist after the function containing the
eval() returns"

Peter



Reply With Quote
  #8  
Old   
Randy Webb
 
Posts: n/a

Default Re: How to make injected js execute? - 08-20-2007 , 08:22 PM



Peter Michaux said the following on 8/20/2007 11:55 AM:
Quote:
On Aug 20, 2:20 am, "Jon Maz" <jon... (AT) surfeu (DOT) deno.spam> wrote:
1. for (possibly demented) reasons of my own it's actually an arbitrary mix
of js and html that I want to inject into the page, so of the 5 methods
offered in the other thread:

* Change Source- attempts to change the .src property of a script element.
* Change innerHMTL - inserts a script string via innerHTML.
* createElement - uses createElement to create a script block with a .src
attribute.
* Change .text - changes the .text property of a script element.
* createTextNode - creates the text part of a script element using
createTextNode

... I think only the .innerHTML one is an option for me.

2. A lot of the thread you referred me to is about IE, whereas my observed
issue affects Firefox too.

My fingers are still crossed that there's an answer to this for me, but hope
is ebbing away fast...


I wrote a library that does what you want to do...sort of.

URL: http://forkjavascript.org/mutate/docs

What my script does it scan through the HTML that is about to be
inserted and pluck out all the script bits. It inserts the other HTML
and then process the JavaScript bits. Instead of dynamic script
insertion, as Randy has investigated, I just eval() the script bits.
This is more cross-browser but has scope implications.
I have a script somewhere that lets you simply insert it via innerHTML
and then reads the script blocks back out and executes them. Is that
what yours does? (I haven't looked at it).

Quote:
If you are in control of writing the JavaScript bits then you can just
write the JavaScript bits so there are no problems with using eval().
There is only one little complication and it is with naming global
variables explicitly as global properties instead. Here is the
pertinent part of the above page regarding this issue.
The other problem that can come up is if your scripts contain a
document.write statement :-)

Quote:
blockquote
The main issue is the scope of entities (eg. variables or functions)
defined in the evaluated script. Because the call to eval() occurs
inside a JavaScript function, entities defined in the evaluated script
may not persist after eval() returns. If you do want to define global
entities you may look at writing something like the following snip
inside the code block.

window.foo = 2; // instead of var foo = 2
/blockquote

If you are not in charge of the script bits and want to use script
insertion you could combine my library and one of the solutions posted
in the other c.l.j thread about script insertion.
I have yet to see a solution that handles document.write but I have an
idea in mind for it.

--
Randy
Chance Favors The Prepared Mind
comp.lang.javascript FAQ - http://jibbering.com/faq/index.html
Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/


Reply With Quote
  #9  
Old   
Peter Michaux
 
Posts: n/a

Default Re: How to make injected js execute? - 08-20-2007 , 08:43 PM



On Aug 20, 5:22 pm, Randy Webb <HikksNotAtH... (AT) aol (DOT) com> wrote:
Quote:
Peter Michaux said the following on 8/20/2007 11:55 AM:
URL:http://forkjavascript.org/mutate/docs

What my script does it scan through the HTML that is about to be
inserted and pluck out all the script bits. It inserts the other HTML
and then process the JavaScript bits. Instead of dynamic script
insertion, as Randy has investigated, I just eval() the script bits.
This is more cross-browser but has scope implications.

I have a script somewhere that lets you simply insert it via innerHTML
and then reads the script blocks back out and executes them. Is that
what yours does? (I haven't looked at it).
I extract the scripts from the HTML before inserting the HTML into the
page. That way if some browser starts to automatically evaluate
scripts when they are inserted by innerHTML I'm not screwed. There
already is one old browser out there that does this: NN6? Then after
inserting the HTML, I eval() the script bits in order. There are pros
and cons for just about every decisions in dealing with this stuff. I
find the system I built easy to use.

There is a bit more too it then that. My script takes into account
problems with inserting table rows or tbody elements by "parsing" the
html first in the appropriate surrounding element. There are
assumptions about a well formed html fragment. blah blah blah. That
script was actually a fun project.


Quote:
If you are not in charge of the script bits and want to use script
insertion you could combine my library and one of the solutions posted
in the other c.l.j thread about script insertion.

I have yet to see a solution that handles document.write but I have an
idea in mind for it.
You are obsessed! Just curious but when is it that you are wanting to
do script insertion with totally random scripts you haven't written
yourself or written by a coworker? Just academic interest?

Peter



Reply With Quote
  #10  
Old   
Randy Webb
 
Posts: n/a

Default Re: How to make injected js execute? - 08-20-2007 , 08:46 PM



Jon Maz said the following on 8/20/2007 5:20 AM:
Quote:
Hi Peter,

Thanks for that - I had no idea this would be a complex issue. A couple of
observations:

1. for (possibly demented) reasons of my own it's actually an arbitrary mix
of js and html that I want to inject into the page, so of the 5 methods
offered in the other thread:

* Change Source- attempts to change the .src property of a script element.
* Change innerHMTL - inserts a script string via innerHTML.
* createElement - uses createElement to create a script block with a .src
attribute.
* Change .text - changes the .text property of a script element.
* createTextNode - creates the text part of a script element using
createTextNode

... I think only the .innerHTML one is an option for me.
The thread that Peter sent you to isn't the best thread for what you are
trying to do. There is another one in the archives if I can find it.

<URL:
http://groups.google.com/group/comp.lang.javascript/search?group=comp.lang.javascript&q=loadHTMLFragme nt>

The name of the function that was last written for what you are doing is
named loadHTMLFragment and looks like this:

function loadHTMLFragment(elemId, HTMLFragment)
{
if (document &&
document.getElementById &&
document.getElementById(elemId) &&
document.createElement &&
document.appendChild &&
document.getElementsByTagName)
{
var el = document.getElementById(elemId);
el.innerHTML = "&nbsp;" + HTMLFragment;
//The &nbsp; is a hack to cause IE to process the
//script elements if the first node in the
//HTMLFragment is a script element.

var d =el.getElementsByTagName('script');
var t = d.length;
for (var x=0;x<t;x++)
{
var newScript = document.createElement('script');
newScript.type = "text/javascript";
newScript.text = d[x].text;
el.appendChild(newScript);
}
for (var y=0;y<t;y++)
{
el.removeChild(el.getElementsByTagName("script")[y]);
}
}
}

The comment you see about IE is because there is a bug in IE where if
the first element in the innerHTML is a script element then it won't
execute that script block for you for some odd ball reason. The simplest
solution was to blanket insert a blank space and avoid the issue all
together.

It still has issues with potential scope issues, and with document.write
issues. If any of your script blocks have a document.write in it then it
will fubar your page by replacing it. I have some ideas on ways around
it but haven't fooled with it in a few months. Maybe this will push me
to get around to it. The basic idea is to scan the script blocks, find
document.write lines and try to figure out how to go about inserting
whatever it was trying to write. Even that has issues with it.

Quote:
2. A lot of the thread you referred me to is about IE, whereas my observed
issue affects Firefox too.
Your issue affects any browser other than NS6.1x, NS6.2x, iCab3.0.3 Mac,
IE5.2 Mac as they are the only ones that will execute scripts inserted
via innerHTML (unless there is one that I don't know about). If you find
a browser other than those above that will execute scripts inserted via
innerHTML, please let me know.

Quote:
My fingers are still crossed that there's an answer to this for me, but hope
is ebbing away fast...
There is an answer, and your hope can ebb higher. Search the archives
for - script insertion randy webb - and you can find more information
about what you are trying to do than I care to sit and type out again.

The biggest thing is whether you control (in any manner) the HTML/Script
you are inserting into your page. If you do, and plan it properly,
script insertion becomes almost trivial.

--
Randy
Chance Favors The Prepared Mind
comp.lang.javascript FAQ - http://jibbering.com/faq/index.html
Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/


Reply With Quote
Reply




Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Powered by vBulletin Version 3.5.4
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.