[javascriptlint-commit] SF.net SVN: javascriptlint:[301] trunk
Status: Beta
Brought to you by:
matthiasmiller
From: <mat...@us...> - 2010-10-03 20:18:17
|
Revision: 301 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=301&view=rev Author: matthiasmiller Date: 2010-10-03 20:18:10 +0000 (Sun, 03 Oct 2010) Log Message: ----------- Add support for content types and differing JavaScript versions. Modified Paths: -------------- trunk/javascriptlint/conf.py trunk/javascriptlint/jsparse.py trunk/javascriptlint/lint.py trunk/javascriptlint/pyspidermonkey/pyspidermonkey.c trunk/javascriptlint/util.py trunk/javascriptlint/warnings.py Added Paths: ----------- trunk/tests/control_comments/conf-version-2.js trunk/tests/control_comments/conf-version.js trunk/tests/html/e4x.html trunk/tests/html/unsupported_version.html Modified: trunk/javascriptlint/conf.py =================================================================== --- trunk/javascriptlint/conf.py 2010-04-23 21:09:57 UTC (rev 300) +++ trunk/javascriptlint/conf.py 2010-10-03 20:18:10 UTC (rev 301) @@ -2,6 +2,7 @@ import os import unittest +import util import warnings def _getwarningsconf(): @@ -80,6 +81,11 @@ #+define document +### JavaScript Version +# To change the default JavaScript version: +#+default-type text/javascript;version=1.5 +#+default-type text/javascript;e4x=1 + ### Files # Specify which files to lint # Use "+recurse" to enable recursion (disabled by default). @@ -144,6 +150,17 @@ parm = os.path.join(dir, parm) self.value.append((self._recurse.value, parm)) +class JSVersionSetting(Setting): + wants_parm = True + value = util.JSVersion.default() + def load(self, enabled, parm): + if not enabled: + raise ConfError, 'Expected +.' + + self.value = util.JSVersion.fromtype(parm) + if not self.value: + raise ConfError, 'Invalid JavaScript version: %s' % parm + class Conf: def __init__(self): recurse = BooleanSetting(False) @@ -157,6 +174,7 @@ 'define': DeclareSetting(), 'context': BooleanSetting(True), 'process': ProcessSetting(recurse), + 'default-version': JSVersionSetting(), # SpiderMonkey warnings 'no_return_value': BooleanSetting(True), 'equal_as_assign': BooleanSetting(True), Modified: trunk/javascriptlint/jsparse.py =================================================================== --- trunk/javascriptlint/jsparse.py 2010-04-23 21:09:57 UTC (rev 300) +++ trunk/javascriptlint/jsparse.py 2010-10-03 20:18:10 UTC (rev 301) @@ -7,6 +7,7 @@ import spidermonkey from spidermonkey import tok, op +from util import JSVersion _tok_names = dict(zip( [getattr(tok, prop) for prop in dir(tok)], @@ -145,6 +146,11 @@ return True +def isvalidversion(jsversion): + if jsversion is None: + return True + return spidermonkey.is_valid_version(jsversion.version) + def findpossiblecomments(script, node_positions): pos = 0 single_line_re = r"//[^\r\n]*" @@ -193,7 +199,7 @@ # this one was within a string or a regexp. pos = match.start()+1 -def parse(script, error_callback, startpos=None): +def parse(script, jsversion, error_callback, startpos=None): """ All node positions will be relative to startpos. This allows scripts to be embedded in a file (for example, HTML). """ @@ -203,7 +209,10 @@ error_callback(line, col, msg) startpos = startpos or NodePos(0,0) - return spidermonkey.parse(script, _Node, _wrapped_callback, + jsversion = jsversion or JSVersion.default() + assert isvalidversion(jsversion) + return spidermonkey.parse(script, jsversion.version, jsversion.e4x, + _Node, _wrapped_callback, startpos.line, startpos.col) def filtercomments(possible_comments, node_positions, root_node): @@ -237,8 +246,10 @@ possible_comments = findpossiblecomments(script, node_positions) return filtercomments(possible_comments, node_positions, root_node) -def is_compilable_unit(script): - return spidermonkey.is_compilable_unit(script) +def is_compilable_unit(script, jsversion): + jsversion = jsversion or JSVersion.default() + assert isvalidversion(jsversion) + return spidermonkey.is_compilable_unit(script, jsversion.version, jsversion.e4x) def _dump_node(node, depth=0): if node is None: @@ -263,12 +274,12 @@ def dump_tree(script): def error_callback(line, col, msg): print '(%i, %i): %s', (line, col, msg) - node = parse(script, error_callback) + node = parse(script, None, error_callback) _dump_node(node) class TestComments(unittest.TestCase): def _test(self, script, expected_comments): - root = parse(script, lambda line, col, msg: None) + root = parse(script, None, lambda line, col, msg: None) comments = findcomments(script, root) encountered_comments = [node.atom for node in comments] self.assertEquals(encountered_comments, list(expected_comments)) @@ -365,10 +376,11 @@ ('re = /.*', False), ('{ // missing curly', False) ) - for text, result in tests: - self.assertEquals(is_compilable_unit(text), result) + for text, expected in tests: + encountered = is_compilable_unit(text, JSVersion.default()) + self.assertEquals(encountered, expected) # NOTE: This seems like a bug. - self.assert_(is_compilable_unit("/* test")) + self.assert_(is_compilable_unit("/* test", JSVersion.default())) class TestLineOffset(unittest.TestCase): def testErrorPos(self): @@ -376,7 +388,7 @@ errors = [] def onerror(line, col, msg): errors.append((line, col, msg)) - parse(script, onerror, startpos) + parse(script, None, onerror, startpos) self.assertEquals(len(errors), 1) return errors[0] self.assertEquals(geterror(' ?', None), (0, 1, 'syntax_error')) @@ -385,7 +397,7 @@ self.assertEquals(geterror('\n ?', NodePos(1,1)), (2, 1, 'syntax_error')) def testNodePos(self): def getnodepos(script, startpos): - root = parse(script, None, startpos) + root = parse(script, None, None, startpos) self.assertEquals(root.kind, tok.LC) var, = root.kids self.assertEquals(var.kind, tok.VAR) @@ -398,7 +410,7 @@ self.assertEquals(getnodepos('\n\n var x;', NodePos(3,4)), NodePos(5,1)) def testComments(self): def testcomment(comment, startpos, expectedpos): - root = parse(comment, None, startpos) + root = parse(comment, None, None, startpos) comment, = findcomments(comment, root, startpos) self.assertEquals(comment.start_pos(), expectedpos) for comment in ('/*comment*/', '//comment'): Modified: trunk/javascriptlint/lint.py =================================================================== --- trunk/javascriptlint/lint.py 2010-04-23 21:09:57 UTC (rev 300) +++ trunk/javascriptlint/lint.py 2010-10-03 20:18:10 UTC (rev 301) @@ -63,6 +63,7 @@ 'pass': (False), 'declare': (True), 'unused': (True), + 'content-type': (True), } if control_comment.lower() in control_comments: keyword = control_comment.lower() @@ -240,19 +241,21 @@ if global_: return global_ -def _findhtmlscripts(contents): +def _findhtmlscripts(contents, default_version): starttag = None nodepos = jsparse.NodePositions(contents) for tag in htmlparse.findscripttags(contents): if tag['type'] == 'start': # Ignore nested start tags. if not starttag: - starttag = tag + jsversion = util.JSVersion.fromattr(tag['attr'], default_version) + starttag = dict(tag, jsversion=jsversion) src = tag['attr'].get('src') if src: yield { 'type': 'external', - 'src': src + 'jsversion': jsversion, + 'src': src, } elif tag['type'] == 'end': if not starttag: @@ -268,25 +271,27 @@ endoffset = nodepos.to_offset(endpos) script = contents[startoffset:endoffset] - if jsparse.is_compilable_unit(script): - starttag = None + if not jsparse.isvalidversion(starttag['jsversion']) or \ + jsparse.is_compilable_unit(script, starttag['jsversion']): if script.strip(): yield { 'type': 'inline', + 'jsversion': starttag['jsversion'], 'pos': startpos, 'contents': script, } + starttag = None else: assert False, 'Invalid internal tag type %s' % tag['type'] def lint_files(paths, lint_error, conf=conf.Conf(), printpaths=True): - def lint_file(path, kind): - def import_script(import_path): + def lint_file(path, kind, jsversion): + def import_script(import_path, jsversion): # The user can specify paths using backslashes (such as when # linting Windows scripts on a posix environment. import_path = import_path.replace('\\', os.sep) import_path = os.path.join(os.path.dirname(path), import_path) - return lint_file(import_path, 'js') + return lint_file(import_path, 'js', jsversion) def _lint_error(*args): return lint_error(normpath, *args) @@ -300,14 +305,20 @@ script_parts = [] if kind == 'js': - script_parts.append((None, contents)) + script_parts.append((None, jsversion or conf['default-version'], contents)) elif kind == 'html': - for script in _findhtmlscripts(contents): + assert jsversion is None + for script in _findhtmlscripts(contents, conf['default-version']): + # TODO: Warn about foreign languages. + if not script['jsversion']: + continue + if script['type'] == 'external': - other = import_script(script['src']) + other = import_script(script['src'], script['jsversion']) lint_cache[normpath].importscript(other) elif script['type'] == 'inline': - script_parts.append((script['pos'], script['contents'])) + script_parts.append((script['pos'], script['jsversion'], + script['contents'])) else: assert False, 'Invalid internal script type %s' % \ script['type'] @@ -321,12 +332,12 @@ for path in paths: ext = os.path.splitext(path)[1] if ext.lower() in ['.htm', '.html']: - lint_file(path, 'html') + lint_file(path, 'html', None) else: - lint_file(path, 'js') + lint_file(path, 'js', None) -def _lint_script_part(scriptpos, script, script_cache, conf, ignores, - report_native, report_lint, import_callback): +def _lint_script_part(scriptpos, jsversion, script, script_cache, conf, + ignores, report_native, report_lint, import_callback): def parse_error(row, col, msg): if not msg in ('anon_no_return_value', 'no_return_value', 'redeclared_var', 'var_hides_arg'): @@ -375,7 +386,28 @@ node_positions = jsparse.NodePositions(script, scriptpos) possible_comments = jsparse.findpossiblecomments(script, node_positions) - root = jsparse.parse(script, parse_error, scriptpos) + # Check control comments for the correct version. It may be this comment + # isn't a valid comment (for example, it might be inside a string literal) + # After parsing, validate that it's legitimate. + jsversionnode = None + for comment in possible_comments: + cc = _parse_control_comment(comment) + if cc: + node, keyword, parms = cc + if keyword == 'content-type': + ccversion = util.JSVersion.fromtype(parms) + if ccversion: + jsversion = ccversion + jsversionnode = node + else: + report(node, 'unsupported_version', version=parms) + + if not jsparse.isvalidversion(jsversion): + report_lint(jsversionnode, 'unsupported_version', scriptpos, + version=jsversion.version) + return + + root = jsparse.parse(script, jsversion, parse_error, scriptpos) if not root: # Report errors and quit. for pos, msg in parse_errors: @@ -383,6 +415,11 @@ return comments = jsparse.filtercomments(possible_comments, node_positions, root) + + if jsversionnode is not None and jsversionnode not in comments: + # TODO + report(jsversionnode, 'incorrect_version') + start_ignore = None for comment in comments: cc = _parse_control_comment(comment) @@ -461,7 +498,7 @@ # Process imports by copying global declarations into the universal scope. for path in import_paths: - script_cache.importscript(import_callback(path)) + script_cache.importscript(import_callback(path, jsversion)) for name, node in declares: declare_scope = script_cache.scope.find_scope(node) @@ -494,9 +531,9 @@ return lint_error(pos.line, pos.col, errname, errdesc) - for scriptpos, script in script_parts: + for scriptpos, jsversion, script in script_parts: ignores = [] - _lint_script_part(scriptpos, script, script_cache, conf, ignores, + _lint_script_part(scriptpos, jsversion, script, script_cache, conf, ignores, report_native, report_lint, import_callback) scope = script_cache.scope @@ -620,8 +657,55 @@ </html> """ scripts = [(x.get('src'), x.get('contents')) - for x in _findhtmlscripts(html)] + for x in _findhtmlscripts(html, util.JSVersion.default())] self.assertEquals(scripts, [ ('test.js', None), (None, "<!--\nvar s = '<script></script>';\n-->") ]) + def testJSVersion(self): + def parsetag(starttag, default_version=None): + script, = _findhtmlscripts(starttag + '/**/</script>', \ + default_version) + return script + + script = parsetag('<script>') + self.assertEquals(script['jsversion'], None) + + script = parsetag('<script language="vbscript">') + self.assertEquals(script['jsversion'], None) + + script = parsetag('<script type="text/javascript">') + self.assertEquals(script['jsversion'], util.JSVersion.default()) + + script = parsetag('<SCRIPT TYPE="TEXT/JAVASCRIPT">') + self.assertEquals(script['jsversion'], util.JSVersion.default()) + + script = parsetag('<script type="text/javascript; version = 1.6 ">') + self.assertEquals(script['jsversion'], util.JSVersion('1.6', False)) + + script = parsetag('<script type="text/javascript; version = 1.6 ">') + self.assertEquals(script['jsversion'], util.JSVersion('1.6', False)) + + script = parsetag('<SCRIPT TYPE="TEXT/JAVASCRIPT; e4x = 1 ">') + self.assertEquals(script['jsversion'], util.JSVersion('default', True)) + + script = parsetag('<script type="" language="livescript">') + self.assertEquals(script['jsversion'], util.JSVersion.default()) + + script = parsetag('<script type="" language="MOCHA">') + self.assertEquals(script['jsversion'], util.JSVersion.default()) + + script = parsetag('<script type="" language="JavaScript1.2">') + self.assertEquals(script['jsversion'], util.JSVersion('1.2', False)) + + script = parsetag('<script type="text/javascript;version=1.2" language="javascript1.4">') + self.assertEquals(script['jsversion'], util.JSVersion('1.2', False)) + + # Test setting the default version. + script = parsetag('<script>', util.JSVersion('1.2', False)) + self.assertEquals(script['jsversion'], util.JSVersion('1.2', False)) + + script = parsetag('<script type="" language="mocha">', + util.JSVersion('1.2', False)) + self.assertEquals(script['jsversion'], util.JSVersion.default()) + Modified: trunk/javascriptlint/pyspidermonkey/pyspidermonkey.c =================================================================== --- trunk/javascriptlint/pyspidermonkey/pyspidermonkey.c 2010-04-23 21:09:57 UTC (rev 300) +++ trunk/javascriptlint/pyspidermonkey/pyspidermonkey.c 2010-10-03 20:18:10 UTC (rev 301) @@ -70,6 +70,9 @@ static PyObject* is_compilable_unit(PyObject *self, PyObject *args); +static PyObject* +is_valid_version(PyObject *self, PyObject *args); + static PyMethodDef module_methods[] = { {"parse", module_parse, METH_VARARGS, "Parses \"script\" and returns a tree of \"node_class\"."}, @@ -77,6 +80,9 @@ {"is_compilable_unit", is_compilable_unit, METH_VARARGS, "Returns True if \"script\" is a compilable unit."}, + {"is_valid_version", is_valid_version, METH_VARARGS, + "Returns True if \"strversion\" is a valid version."}, + {NULL, NULL, 0, NULL} /* Sentinel */ }; @@ -398,13 +404,22 @@ /* Returns NULL on success. Otherwise, it returns an error. * If the error is blank, an exception will be set. */ -static const char* create_jscontext(void* ctx_data, +static const char* create_jscontext(const char* strversion, PyObject* is_e4x, + void* ctx_data, JSRuntime** runtime, JSContext** context, JSObject** global) { + JSVersion jsversion; + + jsversion = JS_StringToVersion(strversion); + if (jsversion == JSVERSION_UNKNOWN) { + PyErr_SetString(PyExc_ValueError, "\"version\" is invalid"); + return ""; + } + *runtime = JS_NewRuntime(8L * 1024L * 1024L); if (*runtime == NULL) - return"cannot create runtime"; + return "cannot create runtime"; *context = JS_NewContext(*runtime, 8192); if (*context == NULL) @@ -413,6 +428,11 @@ JS_SetErrorReporter(*context, error_reporter); JS_SetContextPrivate(*context, ctx_data); JS_ToggleOptions(*context, JSOPTION_STRICT); + if (is_e4x == Py_True) + JS_ToggleOptions(*context, JSOPTION_XML); + else if (is_e4x != Py_False) + return "e4x is not a boolean"; + JS_SetVersion(*context, jsversion); *global = JS_NewObject(*context, NULL, NULL, NULL); if (*global == NULL) @@ -430,6 +450,8 @@ struct { char* scriptbuf; int scriptbuflen; + const char* jsversion; + PyObject* is_e4x; PyObject* pynode; JSRuntime* runtime; @@ -446,8 +468,9 @@ error = "encountered an unknown error"; /* validate arguments */ - if (!PyArg_ParseTuple(args, "es#OOll", "utf16", &m.scriptbuf, - &m.scriptbuflen, &m.ctx_data.node_class, &m.ctx_data.error_callback, + if (!PyArg_ParseTuple(args, "es#sO!OOll", "utf16", &m.scriptbuf, + &m.scriptbuflen, &m.jsversion, &PyBool_Type, &m.is_e4x, + &m.ctx_data.node_class, &m.ctx_data.error_callback, &m.ctx_data.first_lineno, &m.ctx_data.first_index)) { return NULL; } @@ -462,7 +485,8 @@ return NULL; } - error = create_jscontext(&m.ctx_data, &m.runtime, &m.context, &m.global); + error = create_jscontext(m.jsversion, m.is_e4x, &m.ctx_data, + &m.runtime, &m.context, &m.global); if (error) goto cleanup; @@ -511,6 +535,8 @@ struct { char* scriptbuf; int scriptbuflen; + const char* jsversion; + PyObject* is_e4x; JSRuntime* runtime; JSContext* context; JSObject* global; @@ -521,10 +547,13 @@ memset(&m, 0, sizeof(m)); error = "encountered an unknown error"; - if (!PyArg_ParseTuple(args, "es#", "utf16", &m.scriptbuf, &m.scriptbuflen)) + if (!PyArg_ParseTuple(args, "es#sO!", "utf16", &m.scriptbuf, + &m.scriptbuflen, &m.jsversion, &PyBool_Type, &m.is_e4x)) { return NULL; + } - error = create_jscontext(NULL, &m.runtime, &m.context, &m.global); + error = create_jscontext(m.jsversion, m.is_e4x, NULL, + &m.runtime, &m.context, &m.global); if (error) goto cleanup; @@ -546,13 +575,22 @@ PyErr_SetString(PyExc_StandardError, error); return NULL; } - if (m.is_compilable) { - Py_INCREF(Py_True); - return Py_True; - } - else { - Py_INCREF(Py_False); - return Py_False; - } + if (m.is_compilable) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; } +static PyObject* +is_valid_version(PyObject *self, PyObject *args) { + const char* strversion = NULL; + + if (!PyArg_ParseTuple(args, "s", &strversion)) + return NULL; + + if (JS_StringToVersion(strversion) != JSVERSION_UNKNOWN) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + Modified: trunk/javascriptlint/util.py =================================================================== --- trunk/javascriptlint/util.py 2010-04-23 21:09:57 UTC (rev 300) +++ trunk/javascriptlint/util.py 2010-10-03 20:18:10 UTC (rev 301) @@ -1,4 +1,5 @@ # vim: ts=4 sw=4 expandtab +import cgi import codecs import os.path import re @@ -6,6 +7,57 @@ _identifier = re.compile('^[A-Za-z_$][A-Za-z0-9_$]*$') +_contenttypes = ( + 'text/javascript', + 'text/ecmascript', + 'application/javascript', + 'application/ecmascript', + 'application/x-javascript', +) + +class JSVersion: + def __init__(self, jsversion, is_e4x): + self.version = jsversion + self.e4x = is_e4x + + def __eq__(self, other): + return self.version == other.version and \ + self.e4x == other.e4x + + @classmethod + def default(klass): + return klass('default', False) + + @classmethod + def fromattr(klass, attr, default_version=None): + if attr.get('type'): + return klass.fromtype(attr['type']) + if attr.get('language'): + return klass.fromlanguage(attr['language']) + return default_version + + @classmethod + def fromtype(klass, type_): + typestr, typeparms = cgi.parse_header(type_) + if typestr.lower() in _contenttypes: + jsversion = typeparms.get('version', 'default') + is_e4x = typeparms.get('e4x') == '1' + return klass(jsversion, is_e4x) + return None + + @classmethod + def fromlanguage(klass, language): + if language.lower() in ('javascript', 'livescript', 'mocha'): + return klass.default() + + # Simplistic parsing of javascript/x.y + if language.lower().startswith('javascript'): + language = language[len('javascript'):] + if language.replace('.', '').isdigit(): + return klass(language, False) + + return None + def isidentifier(text): return _identifier.match(text) @@ -91,7 +143,6 @@ self.assertEquals(format_error('encode:__ERROR_MSGENC__', r'c:\my\file', 1, 2, 'name', r'a\b'), r'a\\b') - if __name__ == '__main__': unittest.main() Modified: trunk/javascriptlint/warnings.py =================================================================== --- trunk/javascriptlint/warnings.py 2010-04-23 21:09:57 UTC (rev 300) +++ trunk/javascriptlint/warnings.py 2010-10-03 20:18:10 UTC (rev 301) @@ -94,7 +94,9 @@ 'invalid_pass': 'unexpected "pass" control comment', 'want_assign_or_call': 'expected an assignment or function call', 'no_return_value': 'function {name} does not always return a value', - 'anon_no_return_value': 'anonymous function does not always return value' + 'anon_no_return_value': 'anonymous function does not always return value', + 'unsupported_version': 'JavaScript {version} is not supported', + 'incorrect_version': 'Expected /*jsl:content-type*/ control comment. The script was parsed with the wrong version.', } def format_error(errname, **errargs): @@ -511,6 +513,8 @@ # NOTE: Don't handle comma-separated statements. if child.kind in (tok.ASSIGN, tok.INC, tok.DEC, tok.DELETE, tok.COMMA): return + if child.kind == tok.YIELD: + return # Ignore function calls. if child.kind == tok.LP and child.opcode == op.CALL: return Added: trunk/tests/control_comments/conf-version-2.js =================================================================== --- trunk/tests/control_comments/conf-version-2.js (rev 0) +++ trunk/tests/control_comments/conf-version-2.js 2010-10-03 20:18:10 UTC (rev 301) @@ -0,0 +1,7 @@ +/*conf:+default-version text/javascript;version=1.7*/ +/*jsl:content-type text/javascript;version=1.6*/ + +/* Make sure that the control comment overrides the config file. */ +function default_version() { + yield true; /*warning:semi_before_stmnt*/ +} Added: trunk/tests/control_comments/conf-version.js =================================================================== --- trunk/tests/control_comments/conf-version.js (rev 0) +++ trunk/tests/control_comments/conf-version.js 2010-10-03 20:18:10 UTC (rev 301) @@ -0,0 +1,4 @@ +/*conf:+default-version text/javascript;version=1.7*/ +function default_version() { + yield true; +} Added: trunk/tests/html/e4x.html =================================================================== --- trunk/tests/html/e4x.html (rev 0) +++ trunk/tests/html/e4x.html 2010-10-03 20:18:10 UTC (rev 301) @@ -0,0 +1,28 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"> +<html> +<head> + <title>JavaScript Lint Test Page</title> + <!-- If e4x is disabled, HTML commments are treated as + comment-till-end-of-line. --> + <script type="text/javascript"> + // e4x is disabled by default, so HTML comments are single-line only. + var comment_a = <!-- + ? /*warning:syntax_error*/ + -->; + </script> + <script type="text/javascript;e4x=1"> + // Explicitly enable e4x. + var comment_c = <!-- + ? + -->; + </script> + <script type="text/javascript;version=1.6;e4x=0"> + // e4x is always enabled in 1.6+ + var comment_b = <!-- + ? + -->; + </script> +</head> +<body> +</body> +</html> Added: trunk/tests/html/unsupported_version.html =================================================================== --- trunk/tests/html/unsupported_version.html (rev 0) +++ trunk/tests/html/unsupported_version.html 2010-10-03 20:18:10 UTC (rev 301) @@ -0,0 +1,19 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"> +<html> +<head> + <title>JavaScript Lint Test Page</title> + <script type="text/javascript;version=0.1"> /*warning:unsupported_version*/ + function x() { + return 10; + } + </script> + <script language="javascript10.0"> /*warning:unsupported_version*/ + function x() { + return 10; + } + </script> +</head> +<body> +</body> +</html> + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |