Permalink
Browse files

Use Acorn when requested (bug 939915)

  • Loading branch information...
1 parent 9ce687a commit 4901889f02b43ca3f97c8b791864af446ecc83e0 @mattbasta committed Nov 19, 2013
View
@@ -2,5 +2,5 @@ language: python
python:
- "2.6"
- "2.7"
-install: "pip install -r requirements.txt --use-mirrors"
-script: nosetests
+install: "pip install -r requirements.txt --use-mirrors && npm install acorn"
+script: nosetests
View
@@ -53,6 +53,19 @@ in a custom path, you can define it as `$SPIDERMONKEY_INSTALLATION` in
your environment.
+#### Acorn
+
+If you pass the `--acorn` command line flag, the validator will use Acorn
+instead of Spidermonkey to parse JavaScript. This requires Node and Acorn to
+be installed. You can install Acorn with the following:
+
+```bash
+npm install acorn
+```
+
+Acorn will also be used if no Spidermonkey installation is found.
+
+
## Running
Run the validator as follows:
@@ -170,7 +183,7 @@ The same rule applies for the end of a file and for files with only one line.
## Testing
-Unit tests can be run with
+Unit tests can be run with
```bash
nosetests
View
@@ -41,6 +41,10 @@ def main():
help="The amount of time before validation is "
"terminated with a timeout exception.",
default="60")
+ parser.add_argument("--acorn",
+ const=True
+ help="Uses Acorn instead of Spidermonkey for JS "
+ "parsing. Requirees Node and Acorn.")
args = parser.parse_args()
@@ -53,17 +57,18 @@ def main():
if "://" in args.package:
error_bundle = validate_app(
requests.get(args.package).content, listed=not args.unlisted,
- format=None, url=args.package)
+ format=None, url=args.package, acorn=args.acorn)
elif args.package.endswith(".webapp"):
with open(args.package) as f:
error_bundle = validate_app(
- f.read(), listed=not args.unlisted, format=None)
+ f.read(), listed=not args.unlisted, format=None,
+ acorn=args.acorn)
else:
error_bundle = validate_packaged_app(
args.package, listed=not args.unlisted, format=None,
- timeout=timeout)
+ timeout=timeout, acorn=args.acorn)
# Print the output of the tests based on the requested format.
if args.output == "text":
@@ -9,7 +9,7 @@
JS_ESCAPE = re.compile("\\\\+[ux]", re.I)
-def get_tree(code, err=None, filename=None):
+def get_tree(code, err=None, filename=None, shell_noop=None):
"""Retrieve the parse tree for a JS snippet."""
if not code:
@@ -1,16 +1,13 @@
import javascript.traverser as traverser
-from javascript.spidermonkey import get_tree
+import javascript.acorn as acorn
+import javascript.spidermonkey as spidermonkey
from appvalidator.constants import SPIDERMONKEY_INSTALLATION
from ..contextgenerator import ContextGenerator
def test_js_file(err, filename, data, line=0, context=None):
"Tests a JS file by parsing and analyzing its tokens"
- if (SPIDERMONKEY_INSTALLATION is None or
- err.get_resource("SPIDERMONKEY") is None): # Default value is False
- return
-
# Don't even try to run files bigger than 1MB.
if len(data) > 1024 * 1024:
err.warning(
@@ -27,10 +24,15 @@ def test_js_file(err, filename, data, line=0, context=None):
err.set_tier(3)
tree = None
+
+ get_tree = spidermonkey.get_tree
+ spidermonkey_path = (err and err.get_resource("SPIDERMONKEY") or
+ SPIDERMONKEY_INSTALLATION)
+ if err.get_resource("acorn") or not spidermonkey_path:
+ get_tree = acorn.get_tree
+
try:
- tree = get_tree(data, err, filename,
- err and err.get_resource("SPIDERMONKEY") or
- SPIDERMONKEY_INSTALLATION)
+ tree = get_tree(data, err, filename, spidermonkey_path)
except RuntimeError as exc:
warning ="JS: Unknown runtime error"
if "out of memory" in str(exc):
View
@@ -8,7 +8,7 @@
def validate_app(data, listed=True, market_urls=None, url=None,
- format="json"):
+ format="json", acorn=False):
"""
A handy function for validating apps.
@@ -32,6 +32,7 @@ def validate_app(data, listed=True, market_urls=None, url=None,
bundle = ErrorBundle(listed=listed)
bundle.save_resource("market_urls", market_urls)
bundle.save_resource("manifest_url", url)
+ bundle.save_resource("acorn", acorn)
webapp.detect_webapp_string(bundle, data)
submain.test_inner_package(bundle, None)
@@ -40,7 +41,7 @@ def validate_app(data, listed=True, market_urls=None, url=None,
def validate_packaged_app(path, listed=True, format="json", market_urls=None,
- timeout=None, spidermonkey=False):
+ timeout=None, spidermonkey=False, acorn=False):
"""
A handy function for validating apps.
@@ -64,6 +65,7 @@ def validate_packaged_app(path, listed=True, format="json", market_urls=None,
"""
bundle = ErrorBundle(listed=listed, spidermonkey=spidermonkey)
bundle.save_resource("packaged", True)
+ bundle.save_resource("acorn", acorn)
# Set the market URLs.
bundle.save_resource("market_urls", market_urls)
View
@@ -18,9 +18,6 @@
def uses_js(func):
- if SPIDERMONKEY_INSTALLATION is None:
- raise SkipTest("Not running JS tests.")
-
if func:
try:
setattr(func, "js", True)
@@ -32,6 +29,13 @@ def uses_js(func):
return func
+def skip_on_acorn(func):
+ """Skips a test when the test is run under Acorn."""
+ if not SPIDERMONKEY_INSTALLATION:
+ raise SkipTest()
+ return func
+
+
class TestCase(helper.TestCase):
"""A TestCase object with specialized functions for JS testing."""
@@ -1,4 +1,4 @@
-from js_helper import TestCase
+from js_helper import skip_on_acorn, TestCase
class TestOverwrite(TestCase):
@@ -53,6 +53,7 @@ def test(self, script):
yield test, self, 'Number.prototype["test"] = "foo"'
yield test, self, 'x = Number.prototype; x.test = "foo"'
+ @skip_on_acorn
def test_reduced_overwrite_messages(self):
"""
Test that there are no messages for overwrites that occur in local
@@ -70,6 +71,7 @@ def test_reduced_overwrite_messages(self):
""")
self.assert_silent()
+ @skip_on_acorn
def test_reduced_overwrite_messages_block(self):
"""
Test that there are no messages for overwrites that occur in block
View
@@ -1,4 +1,4 @@
-from js_helper import must_assert, errors, silent, TestCase
+from js_helper import must_assert, errors, silent, skip_on_acorn, TestCase
class TestScope(TestCase):
@@ -27,6 +27,7 @@ def test_local_scope_lazy(self):
}
""")
+ @skip_on_acorn
@silent
@must_assert
def test_block_scope(self):
@@ -61,6 +62,7 @@ def test_function_scope(self):
}
""")
+ @skip_on_acorn
@silent
@must_assert
def test_function_scope_block(self):
View
@@ -1,13 +1,14 @@
from nose.tools import eq_
-from js_helper import TestCase
+from js_helper import skip_on_acorn, TestCase
from appvalidator.testcases.javascript.utils import get_as_num, get_as_str
from appvalidator.testcases.javascript.jstypes import JSLiteral
class TestSyntax(TestCase):
+ @skip_on_acorn
def test_array_destructuring(self):
"""
Make sure that multi-level and prototype array destructuring don't cause
@@ -1,6 +1,6 @@
from nose.tools import eq_
-from js_helper import TestCase
+from js_helper import skip_on_acorn, TestCase
class TestAssignments(TestCase):
@@ -16,6 +16,7 @@ def test_multiple_assignments(self):
self.assert_var_eq("y", 2)
self.assert_var_eq("z", 3)
+ @skip_on_acorn
def test_arraypattern_assignment(self):
"""Tests that array patterns can be used to assign variables."""
@@ -27,6 +28,7 @@ def test_arraypattern_assignment(self):
self.assert_var_eq("y", 2)
self.assert_var_eq("z", 3)
+ @skip_on_acorn
def test_objectpattern_assignment(self):
"""Tests that ObjectPatterns are respected."""
@@ -39,6 +41,7 @@ def test_objectpattern_assignment(self):
self.assert_var_eq("y", 4)
self.assert_var_eq("z", 5)
+ @skip_on_acorn
def test_objectpattern_nested(self):
"""Test that nested ObjectPattern assignments are respected."""

0 comments on commit 4901889

Please sign in to comment.