Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.javascript > #7529 > unrolled thread
| Started by | Seni Seven <OneWhoLovesYou@humanitarian.ca.invalid> |
|---|---|
| First post | 2011-10-18 13:48 +0000 |
| Last post | 2011-10-19 20:09 +0100 |
| Articles | 6 — 5 participants |
Back to article view | Back to comp.lang.javascript
Parsing String of Named Function & Converting To Source Seni Seven <OneWhoLovesYou@humanitarian.ca.invalid> - 2011-10-18 13:48 +0000
Re: Parsing String of Named Function & Converting To Source Andreas Bergmaier <andber93@web.de> - 2011-10-18 16:03 +0200
Re: Parsing String of Named Function & Converting To Source Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2011-10-18 19:29 +0200
Re: Parsing String of Named Function & Converting To Source Lasse Reichstein Nielsen <lrn.unread@gmail.com> - 2011-10-18 18:34 +0200
Re: Parsing String of Named Function & Converting To Source Seni Seven <OneWhoLovesYou@humanitarian.ca.invalid> - 2011-10-19 08:01 +0000
Re: Parsing String of Named Function & Converting To Source Dr J R Stockton <reply1142@merlyn.demon.co.uk> - 2011-10-19 20:09 +0100
| From | Seni Seven <OneWhoLovesYou@humanitarian.ca.invalid> |
|---|---|
| Date | 2011-10-18 13:48 +0000 |
| Subject | Parsing String of Named Function & Converting To Source |
| Message-ID | <Xns9F82AB08718BBSSca@88.198.244.100> |
Suppose I have HTML markup with a SCRIPT element as shown below:
<script type="text/javascript">
function multiply(a, b) {
return a * b;
}
var i = multiply(2, 5);
document.write("The value of <i>i</i> is " + i);
</script>
All of this markup and contained script code is retrieved as a string using
Ajax.
I have an HTML parser with support for parsing the string containing the
script code.
In parsing the contained code (using JavaScript, of course), how would you
convert the contained script code from string into source?
What I have found so far (using Firebug in Firefox for development) is this:
1) Isolating the string "function multiply(a, b) { return a * b; }" and then
passing that string as an argument to eval() does not cause the definition
of the function named "multiply," it seems.
2) I can parse the function definition in a way to create the string:
"var multiply = new Function (\"a\", \"b\", \"{ return a * b; }\");"
and then use eval() on it (without error). And then when I eval() the
global level code in a debugger (Firebug in FireFox), as so
eval("var i = multiply(2, 5); document.write(\"The value " +
"of <i>i</i> is \" + i);"); // parsed code as string on one line
the value of identifier 'i' is immediately set to 10 in the debugger, but
the debugger exits with error 'multiply is not defined', which indicates
multiple levels of execution contexts, I suppose. In fact, if I just do an
eval() on the "multiply" assignment of the Function constructor, the
identifier 'multiply' is still not defined.
QUESTION: What's the solution to the goal I want to achieve?
[don't worry about the 'document.write()' call for the moment: that string
pattern gets replaced eventually with a function that injects DOM nodes into
the tree in the same way document.write() would on document loading]
For those who are curious as to why I would want to do this, there is a
basis for this. See BACKGROUND below.
BACKGROUND
I have a modular interactive chemistry calculator running entirely on the
client side.
The "modularity" is such that a main HTML document provides a base interface
and I extend functionality by reading in one JS file which specifies a
document in HTML markup--the markup is valid, but not the document--which is
read in using Ajax. The JS file also contains all the code for doing the
chemistry calculations specific for that module.
The string representing the markup obtained by Ajax retrieval is then passed
to a parsing function which is supposed to do it all: parses the HTML
markup using DOM methods to insert the DocumentFragment into the main
document tree. It also parses CSS (stylesheets and style attributes), as
well as any Javascript contained inside SCRIPT elements. Everything becomes
part of the interactive document by using DOM method calls, HTML --> element
nodes with attributes; CSS --> as stylesheets in LINK element nodes for
external stylesheets, as style property changes to DOM element nodes where
style attributes are identified; JavaScript --> converting strings into
executable source, parsing named functions from global level source (which
might be wrapped in anonymous functions and called).
So far there has been no problem with the HTML and CSS. It's the Javascript
that remains a barrier now.
Security considerations: all the module HTML documents and JS files are
delivered from the same server, the one from which the main document was
loaded. Inherent Javascript security features against accessing the file
system without user permissions are always in play.
[toc] | [next] | [standalone]
| From | Andreas Bergmaier <andber93@web.de> |
|---|---|
| Date | 2011-10-18 16:03 +0200 |
| Message-ID | <j7k0uo$uee$1@news.albasani.net> |
| In reply to | #7529 |
Seni Seven schrieb:
> Suppose I have HTML markup with a SCRIPT element as shown below:
>
> <script type="text/javascript">
> function multiply(a, b) {
> return a * b;
> }
> var i = multiply(2, 5);
> document.write("The value of<i>i</i> is " + i);
> </script>
>
> All of this markup and contained script code is retrieved as a string using
> Ajax.
>
> I have an HTML parser with support for parsing the string containing the
> script code.
>
> In parsing the contained code (using JavaScript, of course), how would you
> convert the contained script code from string into source?
>
> The string representing the markup obtained by Ajax retrieval is then passed
> to a parsing function which is supposed to do it all: parses the HTML
> markup using DOM methods to insert the DocumentFragment into the main
> document tree. It also parses CSS (stylesheets and style attributes), as
> well as any Javascript contained inside SCRIPT elements. Everything becomes
> part of the interactive document by using DOM method calls, HTML --> element
> nodes with attributes; CSS --> as stylesheets in LINK element nodes for
> external stylesheets, as style property changes to DOM element nodes where
> style attributes are identified; JavaScript --> converting strings into
> executable source, parsing named functions from global level source (which
> might be wrapped in anonymous functions and called).
Why do you try to build an (x)html parser in javascript (@PE: or one of
its dialects)?
I see two solutions to your problem:
* Use your parser to append the "script" node from the ajaxed fragment
into your document, just as style nodes and everything other. The script
then should be executed in your global environment.
* Why don't you use iframes? Then valid documents were needed (instead
of your fragments), but you wouldn't have to build a error-prone parser.
As the fragments load from the same server, you could even copy the
DOM-tree from the (hidden) iframe into your document if you need that.
Bergi
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2011-10-18 19:29 +0200 |
| Message-ID | <3072618.pbM1GnOhur@PointedEars.de> |
| In reply to | #7530 |
Andreas Bergmaier wrote: > Why do you try to build an (x)html parser Because it is an interesting problem to solve; `innerHTML' is proprietary, unreliable and undocumented by comparison. I would probably skip the XHTML part, though, because there's DOMParser. > in javascript (@PE: or one of its dialects)? There is no "javascript", so there are no "javascript dialects" :) I might comment on the rest later. PointedEars -- Danny Goodman's books are out of date and teach practices that are positively harmful for cross-browser scripting. -- Richard Cornford, cljs, <cife6q$253$1$8300dec7@news.demon.co.uk> (2004)
[toc] | [prev] | [next] | [standalone]
| From | Lasse Reichstein Nielsen <lrn.unread@gmail.com> |
|---|---|
| Date | 2011-10-18 18:34 +0200 |
| Message-ID | <8voi2r92.fsf@gmail.com> |
| In reply to | #7529 |
Seni Seven <OneWhoLovesYou@humanitarian.ca.invalid> writes:
> Suppose I have HTML markup with a SCRIPT element as shown below:
>
> <script type="text/javascript">
> function multiply(a, b) {
> return a * b;
> }
> var i = multiply(2, 5);
> document.write("The value of <i>i</i> is " + i);
Invalid HTML 4 markup. You should escape the </ inside the string.
> </script>
>
> All of this markup and contained script code is retrieved as a string using
> Ajax.
So, it's a string with the above content (newlines and all).
> I have an HTML parser with support for parsing the string containing the
> script code.
Ok.
> In parsing the contained code (using JavaScript, of course), how would you
> convert the contained script code from string into source?
What's the difference? I assume your HTML parser extracts the content
of the script element as a string.
What do you want to do with that string?
> What I have found so far (using Firebug in Firefox for development) is this:
>
> 1) Isolating the string "function multiply(a, b) { return a * b; }" and then
> passing that string as an argument to eval() does not cause the definition
> of the function named "multiply," it seems.
It probably does, but in the scope where the eval is executed, not at
the global scope.
For that, you can use, e.g.,
window.eval(sourceString);
(or any other non-direct call to eval).
> 2) I can parse the function definition in a way to create the string:
>
> "var multiply = new Function (\"a\", \"b\", \"{ return a * b; }\");"
How wasteful :) The function syntax is perfectly fine, no need to make
it more convoluted.
> and then use eval() on it (without error). And then when I eval() the
> global level code in a debugger (Firebug in FireFox), as so
>
> eval("var i = multiply(2, 5); document.write(\"The value " +
> "of <i>i</i> is \" + i);"); // parsed code as string on one line
>
>
> the value of identifier 'i' is immediately set to 10 in the debugger, but
> the debugger exits with error 'multiply is not defined', which indicates
> multiple levels of execution contexts, I suppose. In fact, if I just do an
> eval() on the "multiply" assignment of the Function constructor, the
> identifier 'multiply' is still not defined.
>
> QUESTION: What's the solution to the goal I want to achieve?
Try:
var script = document.createElement("script");
script.textContent = sourceString;
document.body.appendChild(script);
This executes the code as top-level, non-eval code (which there is no way
to do in pure Javascript).
No guarantees wrt. old browsers, but it seems to work in the current versions.
Alternatively, just use a non-direct call to eval.
var topLevelEval = eval;
topLevelEval(sourceString);
> The string representing the markup obtained by Ajax retrieval is then passed
> to a parsing function which is supposed to do it all: parses the HTML
> markup using DOM methods to insert the DocumentFragment into the main
> document tree. It also parses CSS (stylesheets and style attributes), as
> well as any Javascript contained inside SCRIPT elements. Everything becomes
> part of the interactive document by using DOM method calls, HTML --> element
Why not pass it as something easier to parse and separate into
CSS/HTML/JS, e.g., JSON?
/L
--
Lasse Reichstein Holst Nielsen
'Javascript frameworks is a disruptive technology'
[toc] | [prev] | [next] | [standalone]
| From | Seni Seven <OneWhoLovesYou@humanitarian.ca.invalid> |
|---|---|
| Date | 2011-10-19 08:01 +0000 |
| Message-ID | <Xns9F83701848613SSca@88.198.244.100> |
| In reply to | #7541 |
Lasse Reichstein Nielsen <lrn.unread@gmail.com> wrote on Tue 18 Oct 2011
07:34:17p
> Seni Seven <OneWhoLovesYou@humanitarian.ca.invalid> writes:
>
>> Suppose I have HTML markup with a SCRIPT element as shown below:
>>
>> <script type="text/javascript">
>> function multiply(a, b) {
>> return a * b;
>> }
>> var i = multiply(2, 5);
>> document.write("The value of <i>i</i> is " + i);
>
> Invalid HTML 4 markup. You should escape the </ inside the string.
Yes, my parser actually stopped on the "</i>" etago markup, of all things.
And yes, the HTML 4.1 recommendation specifies this is invalid.
Then I read one article (I believe there are others) on this subject of
CDATA content inside a SCRIPT element which first asserted that (1) it was
nonsense to have this in the recommendation and (2) that no browser
implementation actually followed this part of the recommendation: that is,
all textual content between the start and end tag of a SCRIPT element was
not effectively regarded as part of HTML markup, so I made my parser ignore
all content between the start and end tag of a SCRIPT element and process it
as script code.
But even so, I admit that I should backlash the string pattern "</"
appropriately to be in compliance with the recommendation.
>
>> </script>
>>
>> All of this markup and contained script code is retrieved as a string
>> using Ajax.
>
> So, it's a string with the above content (newlines and all).
Ajax effectively recovers data that become strings if handled by
ECMAscript/Javascript, doesn't it?
>> I have an HTML parser with support for parsing the string containing
>> the script code.
>
> Ok.
>
>> In parsing the contained code (using JavaScript, of course), how would
>> you convert the contained script code from string into source?
>
> What's the difference? I assume your HTML parser extracts the content
> of the script element as a string.
> What do you want to do with that string?
Well, normally, all script as either elements in HTML documents or loaded
from external JS files get processed during HTML document loading in the
browser. This is before the document.close() call has effectively been
invoked and completed, right?
But what do you do if you bring in ECMAscript code (as strings via Ajax)
AFTER the document.close() call has been made? You want to make function
definitions (named functions) part of the executable code in the HTML
document (object?), just as if it were made during document loading. As for
script code outside of named function definition scope, you want to parse
and execute immediately, in order of retrieval via Ajax.
>> What I have found so far (using Firebug in Firefox for development) is
>> this:
>>
>> 1) Isolating the string "function multiply(a, b) { return a * b; }" and
>> then passing that string as an argument to eval() does not cause the
>> definition of the function named "multiply," it seems.
>
> It probably does, but in the scope where the eval is executed, not at
> the global scope.
> For that, you can use, e.g.,
> window.eval(sourceString);
> (or any other non-direct call to eval).
Okay.
>> 2) I can parse the function definition in a way to create the string:
>>
>> "var multiply = new Function (\"a\", \"b\", \"{ return a * b; }\");"
>
> How wasteful :) The function syntax is perfectly fine, no need to make
> it more convoluted.
>
>> and then use eval() on it (without error). And then when I eval() the
>> global level code in a debugger (Firebug in FireFox), as so
>>
>> eval("var i = multiply(2, 5); document.write(\"The value " +
>> "of <i>i</i> is \" + i);"); // parsed code as string on one line
>>
>>
>> the value of identifier 'i' is immediately set to 10 in the debugger,
>> but the debugger exits with error 'multiply is not defined', which
>> indicates multiple levels of execution contexts, I suppose. In fact,
>> if I just do an eval() on the "multiply" assignment of the Function
>> constructor, the identifier 'multiply' is still not defined.
>>
>> QUESTION: What's the solution to the goal I want to achieve?
>
> Try:
> var script = document.createElement("script");
> script.textContent = sourceString;
> document.body.appendChild(script);
> This executes the code as top-level, non-eval code (which there is no
> way to do in pure Javascript).
> No guarantees wrt. old browsers, but it seems to work in the current
> versions.
Yes, tried, and found it works.
> Alternatively, just use a non-direct call to eval.
> var topLevelEval = eval;
> topLevelEval(sourceString);
Yes, tried, and found it works.
I am looking at search results (http://is.gd/jwhNln) to understand why
indirect calls to eval() work.
>
>> The string representing the markup obtained by Ajax retrieval is then
>> passed to a parsing function which is supposed to do it all: parses
>> the HTML markup using DOM methods to insert the DocumentFragment into
>> the main document tree. It also parses CSS (stylesheets and style
>> attributes), as well as any Javascript contained inside SCRIPT
>> elements. Everything becomes part of the interactive document by using
>> DOM method calls, HTML --> element
> Why not pass it as something easier to parse and separate into
> CSS/HTML/JS, e.g., JSON?
I will look into this most certainly and try to make it workable.
The suggestion by poster "Andreas Bergmaier" to use iframes probably is
worthy of exploring. Perhaps I made this overly complicated.
[toc] | [prev] | [next] | [standalone]
| From | Dr J R Stockton <reply1142@merlyn.demon.co.uk> |
|---|---|
| Date | 2011-10-19 20:09 +0100 |
| Message-ID | <fyJIlYLACynOFwa3@invalid.uk.co.demon.merlyn.invalid> |
| In reply to | #7541 |
In comp.lang.javascript message <8voi2r92.fsf@gmail.com>, Tue, 18 Oct
2011 18:34:17, Lasse Reichstein Nielsen <lrn.unread@gmail.com> posted:
>Seni Seven <OneWhoLovesYou@humanitarian.ca.invalid> writes:
>
>> Suppose I have HTML markup with a SCRIPT element as shown below:
>>
>> <script type="text/javascript">
>> function multiply(a, b) {
>> return a * b;
>> }
>> var i = multiply(2, 5);
>> document.write("The value of <i>i</i> is " + i);
>> </script>
>>
>> All of this markup and contained script code is retrieved as a string using
>> Ajax.
>> I have an HTML parser with support for parsing the string containing the
>> script code.
>> In parsing the contained code (using JavaScript, of course), how would you
>> convert the contained script code from string into source?
>> ...
>> the value of identifier 'i' is immediately set to 10 in the debugger, but
>> the debugger exits with error 'multiply is not defined', which indicates
>> multiple levels of execution contexts, I suppose. In fact, if I just do an
>> eval() on the "multiply" assignment of the Function constructor, the
>> identifier 'multiply' is still not defined.
>>
>> QUESTION: What's the solution to the goal I want to achieve?
I've done that, or something rather similar, in
<http://www.merlyn.demon.co.uk/js-randm.htm> - the code for inserting
Johannes Baagoe's (or other) functions. IIRC, it was necessary to be
slightly subtle about the argument to 'eval', perhaps such as something
like prepending " XXX = " to the function - see the source code of the
page.
>Try:
> var script = document.createElement("script");
> script.textContent = sourceString;
> document.body.appendChild(script);
>This executes the code as top-level, non-eval code (which there is no way
>to do in pure Javascript).
>No guarantees wrt. old browsers, but it seems to work in the current versions.
>
>Alternatively, just use a non-direct call to eval.
> var topLevelEval = eval;
> topLevelEval(sourceString);
Would any of your contribution give a worthwhile improvement in the
cited js-randm.htm, given that the latter works?
--
(c) John Stockton, nr London, UK. ?@merlyn.demon.co.uk Turnpike 6.05 WinXP.
Web <http://www.merlyn.demon.co.uk/> - FAQ-type topics, acronyms, and links.
Command-prompt MiniTrue is useful for viewing/searching/altering files. Free,
DOS/Win/UNIX now 2.0.6; see <URL:http://www.merlyn.demon.co.uk/pc-links.htm>.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.javascript
csiph-web