diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
new file mode 100644
index 00000000..0656399b
--- /dev/null
+++ b/.github/workflows/tests.yml
@@ -0,0 +1,33 @@
+name: tests
+
+on: [push, pull_request]
+
+jobs:
+ build:
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+# disabled windows due node packages issues
+# os: [ubuntu-latest, macos-latest, windows-latest]
+ os: [ubuntu-latest, macos-latest]
+ python-version: [ '2.x', '3.x', '3.5', '3.6', '3.7', '3.8', '3.9', 'pypy-2.7', 'pypy-3.6']
+ exclude:
+ - os: windows-latest
+ python-version: '3.5'
+ - os: macos-latest
+ python-version: 'pypy-3.6'
+ name: ${{ matrix.os }} ${{ matrix.arch }}, Python ${{ matrix.python-version }}
+ steps:
+ - uses: actions/checkout@v2
+ - name: Setup python
+ uses: actions/setup-python@v2
+ with:
+ python-version: ${{ matrix.python-version }}
+ architecture: x64
+ - name: Python version
+ run: python --version
+ - name: Install packages
+ run: pip install -r requirements.txt && pip install numpy
+ - name: Simple tests
+ run: python simple_test.py
diff --git a/.gitignore b/.gitignore
index a473ab11..ab5e9100 100644
--- a/.gitignore
+++ b/.gitignore
@@ -75,6 +75,7 @@ Icon
# Files that might appear on external disk
.Spotlight-V100
.Trashes
+venv
# Directories potentially created on remote AFP share
.AppleDB
@@ -108,3 +109,11 @@ $RECYCLE.BIN/
.idea/dictionaries/
.idea/inspectionProfiles/
.idea/scopes/
+
+bench.py
+out.py
+sample.js
+package-lock.json
+js2py/node_modules
+js2py/py_node_modules/*
+!js2py/py_node_modules/__init__.py
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
old mode 100644
new mode 100755
index c89fa5fa..cb961fe8
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,12 +1,13 @@
+dist: xenial
language: python
python:
- - "2.6"
- "2.7"
- - "3.3"
- - "3.4"
- "3.5"
- "3.6"
+ - "3.7"
+ - "3.8"
+ - "3.8-dev"
# command to install dependencies!
-install: "pip install -r requirements.txt"
+install: "pip install -r requirements.txt && pip install numpy"
# command to run tests!
-script: python simple_test.py
\ No newline at end of file
+script: python simple_test.py
diff --git a/README.md b/README.md
index 74f7e53f..dc72d685 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[](https://travis-ci.org/PiotrDabkowski/Js2Py)
+[](https://travis-ci.org/PiotrDabkowski/Js2Py) [](https://pepy.tech/project/js2py)
#### Pure Python JavaScript Translator/Interpreter
@@ -16,7 +16,24 @@ Simple Example:
6
>>> add.constructor
function Function() { [python code] }
+ >>> js2py.require('underscore')
+ 'function _(obj) { [python code] }'
```
+You can also import a big number of node modules as if they were written in Python!
+For example, here we import a pure JS library [crypto-js](https://www.npmjs.com/package/crypto-js):
+
+```python
+ >>> CryptoJS = js2py.require('crypto-js')
+ >>> data = [{'id': 1}, {'id': 2}]
+ >>> JSON = js2py.eval_js('JSON')
+ >>> ciphertext = CryptoJS.AES.encrypt(JSON.stringify(data), 'secret key 123')
+ >>> bytes = CryptoJS.AES.decrypt(ciphertext.toString(), 'secret key 123')
+ >>> decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8)).to_list()
+ >>> decryptedData
+ [{u'id': 1}, {u'id': 2}]
+```
+
+
Now also supports JavaScript 6 (still experimental):
@@ -47,7 +64,12 @@ Every feature of ECMA 5.1 is implemented (except of 'with' statement):
```
Unfortunately even though Js2Py can be generally used to translate huge Js files (over 50k lines long), in rare cases you may encounter some unexpected problems (like javascript calling a function with 300 arguments - python allows only 255). These problems are very hard to fix with current translation approach. I will try to implement an interpreter in near future which will hopefully fix all the edge cases.
+#### Installation
+
+ pip install js2py
+
+
#### More advanced usage example
It is possible to access all the variables from JS scope using EvalJs. Moreover, you can use Python objects from your JavaScript code if you add them to the scope.
@@ -83,26 +105,95 @@ function bind(thisArg) { [python code] }
6
```
+You can also enable require support in JavaScript like this:
+
+```python
+>>> context = js2py.EvalJs(enable_require=True)
+>>> context.eval("require('esprima').parse('var a = 1')")
+```
+
+
+### JavaScript 'VirtualMachine' in Python
+
+As a fun experimental project I have also implemented a VM-based JavaScript
+(yes - there are 2 separate JS implementations in this repo). It is feature complete and faster than the translation based version.
+Below you can see a demo with a nice debug view (bytecode + execution sequence):
+
+```python
+>>> from js2py.internals import seval
+>>> seval.eval_js_vm("try {throw 3+3} catch (e) {console.log(e)}", debug=True)
+[LOAD_UNDEFINED(),
+ JUMP(4,),
+ LABEL(1,),
+ LOAD_UNDEFINED(),
+ POP(),
+ LOAD_NUMBER(3.0,),
+ LOAD_NUMBER(3.0,),
+ BINARY_OP('+',),
+ THROW(),
+ NOP(),
+ LABEL(2,),
+ LOAD_UNDEFINED(),
+ POP(),
+ LOAD('console',),
+ LOAD('e',),
+ LOAD_N_TUPLE(1,),
+ CALL_METHOD_DOT('log',),
+ NOP(),
+ LABEL(3,),
+ LOAD_UNDEFINED(),
+ NOP(),
+ LABEL(4,),
+ TRY_CATCH_FINALLY(1, 2, 'e', 3, False, 4)]
+
+0 LOAD_UNDEFINED()
+1 JUMP(4,)
+18 TRY_CATCH_FINALLY(1, 2, 'e', 3, False, 4)
+ ctx entry (from:2, to:9)
+ 2 LOAD_UNDEFINED()
+ 3 POP()
+ 4 LOAD_NUMBER(3.0,)
+ 5 LOAD_NUMBER(3.0,)
+ 6 BINARY_OP('+',)
+ 7 THROW()
+ ctx exit (js errors)
+ ctx entry (from:9, to:16)
+ 9 LOAD_UNDEFINED()
+ 10 POP()
+ 11 LOAD('console',)
+ 12 LOAD('e',)
+ 13 LOAD_N_TUPLE(1,)
+ 14 CALL_METHOD_DOT('log',)
+6
+ 15 NOP()
+ ctx exit (normal)
+
+```
+
+This is just a curiosity and I do not recommend using VM in practice (requires more polishing).
+
#### Limitations
-It has only 3 known limitations:
+There are 3 main limitations:
- "strict mode" is ignored
- with statement is not supported
- Indirect call to eval is treated as direct call to eval (hence always evals in local scope)
-Please let me know if you find any bugs - they will be fixed within 48 hours.
+They are generally not a big issue in practice.
+In practice more problematic are minor edge cases that unfortunately
+sometimes do happen. Please report a bug if you find one.
+
+Js2Py was able to successfully
+translate and run huge JS libraries like Babel (100k+ loc), esprima, crypto-js and more.
+You can try it yourself by importing any supported npm package via `js2py.require('your_package')`.
-#### Installation
- pip install js2py
-
-
#### Other Examples
@@ -153,26 +244,42 @@ Also, of course you can use Js2Py to parse (tree is the same as in esprima.js) a
#### Parsing:
```python
>>> js2py.parse_js('var $ = 5')
-{'body': [{'kind': 'var', 'declarations': [{'init': {'raw': None, 'type': u'Literal', 'value': 5.0}, 'type': u'VariableDeclarator', 'id': {'type': u'Identifier', 'name': u'$'}}], 'type': u'VariableDeclaration'}], 'type': u'Program'}
+{
+ "body": [
+ {
+ "declarations": [
+ {
+ "id": {
+ "name": "$",
+ "type": "Identifier"
+ },
+ "init": {
+ "raw": "5",
+ "type": "Literal",
+ "value": 5
+ },
+ "type": "VariableDeclarator"
+ }
+ ],
+ "kind": "var",
+ "type": "VariableDeclaration"
+ }
+ ],
+ "type": "Program"
+}
```
#### Translating:
```python
->>> print js2py.translate_js('var $ = 5')
-import js2py.pyjs, sys
-# Redefine builtin objects... Do you have a better idea?
-for m in sys.modules.keys():
- if m.startswith('js2py'):
- del sys.modules[m]
-del js2py.pyjs
-del js2py
+>>> print(js2py.translate_js('var $ = 5'))
from js2py.pyjs import *
# setting scope
var = Scope( JS_BUILTINS )
set_global_object(var)
+
# Code follows:
-var.registers([u'$'])
-var.put(u'$', Js(5.0))
+var.registers(['$'])
+var.put('$', Js(5.0))
```
diff --git a/bench.dockerfile b/bench.dockerfile
new file mode 100644
index 00000000..a443348c
--- /dev/null
+++ b/bench.dockerfile
@@ -0,0 +1,13 @@
+FROM python:3.11-alpine
+WORKDIR /app
+RUN pip3 install pyjsparser six
+RUN pip3 install tzlocal
+RUN apk add --update alpine-sdk
+RUN apk --no-cache --update add build-base
+RUN pip3 install numpy
+
+ADD . /app
+
+RUN ls
+#CMD ["python3", "js2py/utils/injector.py"]
+CMD ["python3", "simple_test.py"]
\ No newline at end of file
diff --git a/ev.js b/ev.js
new file mode 100644
index 00000000..86e5211f
--- /dev/null
+++ b/ev.js
@@ -0,0 +1,82 @@
+function __get_event_env__() {
+ //pyimport time;
+ var id = 0;
+ var sh = [];
+ function add_event(func, args, interval, id) {
+ var ev = [func, args, time.time()+interval/1000., id];
+ sh.push(ev);
+ }
+ function clear_event(id) {
+ var to_del = false;
+ for (var i=0; i> & ^ |'''
- if self.Class=='Undefined' or self.Class=='Null':
- raise MakeError('TypeError', 'Undefined and null dont have properties!')
+ if self.Class == 'Undefined' or self.Class == 'Null':
+ raise MakeError('TypeError',
+ 'Undefined and null don\'t have properties (tried setting property %s)' % repr(prop))
if not isinstance(prop, basestring):
- prop = prop.to_string().value
+ prop = prop.to_string().value
if NUMPY_AVAILABLE and prop.isdigit():
if self.Class == 'Int8Array':
val = Js(numpy.int8(val.to_number().value))
@@ -363,7 +388,7 @@ def put(self, prop, val, op=None): #external use!
val = Js(numpy.float32(val.to_number().value))
elif self.Class == 'Float64Array':
val = Js(numpy.float64(val.to_number().value))
- if isinstance(self.buff,numpy.ndarray):
+ if isinstance(self.buff, numpy.ndarray):
self.buff[int(prop)] = int(val.to_number().value)
#we need to set the value to the incremented one
if op is not None:
@@ -372,20 +397,30 @@ def put(self, prop, val, op=None): #external use!
return val
own_desc = self.get_own_property(prop)
if is_data_descriptor(own_desc):
- if self.Class in ['Array','Int8Array','Uint8Array','Uint8ClampedArray','Int16Array','Uint16Array','Int32Array','Uint32Array','Float32Array','Float64Array']:
- self.define_own_property(prop, {'value':val})
+ if self.Class in [
+ 'Array', 'Int8Array', 'Uint8Array', 'Uint8ClampedArray',
+ 'Int16Array', 'Uint16Array', 'Int32Array', 'Uint32Array',
+ 'Float32Array', 'Float64Array'
+ ]:
+ self.define_own_property(prop, {'value': val})
else:
self.own[prop]['value'] = val
return val
desc = self.get_property(prop)
if is_accessor_descriptor(desc):
- desc['set'].call(self, (val,))
+ desc['set'].call(self, (val, ))
else:
- new = {'value' : val,
- 'writable' : True,
- 'configurable' : True,
- 'enumerable' : True}
- if self.Class in ['Array','Int8Array','Uint8Array','Uint8ClampedArray','Int16Array','Uint16Array','Int32Array','Uint32Array','Float32Array','Float64Array']:
+ new = {
+ 'value': val,
+ 'writable': True,
+ 'configurable': True,
+ 'enumerable': True
+ }
+ if self.Class in [
+ 'Array', 'Int8Array', 'Uint8Array', 'Uint8ClampedArray',
+ 'Int16Array', 'Uint16Array', 'Int32Array', 'Uint32Array',
+ 'Float32Array', 'Float64Array'
+ ]:
self.define_own_property(prop, new)
else:
self.own[prop] = new
@@ -405,9 +440,11 @@ def delete(self, prop):
return Js(True)
return Js(False)
- def default_value(self, hint=None): # made a mistake at the very early stage and made it to prefer string... caused lots! of problems
+ def default_value(
+ self, hint=None
+ ): # made a mistake at the very early stage and made it to prefer string... caused lots! of problems
order = ('valueOf', 'toString')
- if hint=='String' or (hint is None and self.Class=='Date'):
+ if hint == 'String' or (hint is None and self.Class == 'Date'):
order = ('toString', 'valueOf')
for meth_name in order:
method = self.get(meth_name)
@@ -415,61 +452,68 @@ def default_value(self, hint=None): # made a mistake at the very early stage an
cand = method.call(self)
if cand.is_primitive():
return cand
- raise MakeError('TypeError', 'Cannot convert object to primitive value')
-
+ raise MakeError('TypeError',
+ 'Cannot convert object to primitive value')
- def define_own_property(self, prop, desc): #Internal use only. External through Object
+ def define_own_property(self, prop,
+ desc): #Internal use only. External through Object
# prop must be a Py string. Desc is either a descriptor or accessor.
#Messy method - raw translation from Ecma spec to prevent any bugs. # todo check this
current = self.get_own_property(prop)
extensible = self.extensible
- if not current: #We are creating a new property
+ if not current: #We are creating a new property
if not extensible:
return False
if is_data_descriptor(desc) or is_generic_descriptor(desc):
- DEFAULT_DATA_DESC = {'value': undefined, #undefined
- 'writable': False,
- 'enumerable': False,
- 'configurable': False}
+ DEFAULT_DATA_DESC = {
+ 'value': undefined, #undefined
+ 'writable': False,
+ 'enumerable': False,
+ 'configurable': False
+ }
DEFAULT_DATA_DESC.update(desc)
self.own[prop] = DEFAULT_DATA_DESC
else:
- DEFAULT_ACCESSOR_DESC = {'get': undefined, #undefined
- 'set': undefined, #undefined
- 'enumerable': False,
- 'configurable': False}
+ DEFAULT_ACCESSOR_DESC = {
+ 'get': undefined, #undefined
+ 'set': undefined, #undefined
+ 'enumerable': False,
+ 'configurable': False
+ }
DEFAULT_ACCESSOR_DESC.update(desc)
self.own[prop] = DEFAULT_ACCESSOR_DESC
return True
- if not desc or desc==current: #We dont need to change anything.
+ if not desc or desc == current: #We dont need to change anything.
return True
configurable = current['configurable']
if not configurable: #Prevent changing configurable or enumerable
if desc.get('configurable'):
return False
- if 'enumerable' in desc and desc['enumerable']!=current['enumerable']:
+ if 'enumerable' in desc and desc['enumerable'] != current[
+ 'enumerable']:
return False
if is_generic_descriptor(desc):
pass
- elif is_data_descriptor(current)!=is_data_descriptor(desc):
+ elif is_data_descriptor(current) != is_data_descriptor(desc):
if not configurable:
return False
if is_data_descriptor(current):
del current['value']
del current['writable']
- current['set'] = undefined #undefined
- current['get'] = undefined #undefined
+ current['set'] = undefined #undefined
+ current['get'] = undefined #undefined
else:
del current['set']
del current['get']
- current['value'] = undefined #undefined
+ current['value'] = undefined #undefined
current['writable'] = False
elif is_data_descriptor(current) and is_data_descriptor(desc):
if not configurable:
if not current['writable'] and desc.get('writable'):
return False
- if not current['writable'] and 'value' in desc and current['value']!=desc['value']:
+ if not current['writable'] and 'value' in desc and current[
+ 'value'] != desc['value']:
return False
elif is_accessor_descriptor(current) and is_accessor_descriptor(desc):
if not configurable:
@@ -482,104 +526,102 @@ def define_own_property(self, prop, desc): #Internal use only. External through
#these methods will work only for Number class
def is_infinity(self):
- assert self.Class=='Number'
- return self.value==float('inf') or self.value==-float('inf')
+ assert self.Class == 'Number'
+ return self.value == float('inf') or self.value == -float('inf')
def is_nan(self):
- assert self.Class=='Number'
- return self.value!=self.value #nan!=nan evaluates to true
+ assert self.Class == 'Number'
+ return self.value != self.value #nan!=nan evaluates to true
def is_finite(self):
return not (self.is_nan() or self.is_infinity())
+
#Type Conversions. to_type. All must return pyjs subclass instance
def to_primitive(self, hint=None):
if self.is_primitive():
return self
- if hint is None and (self.Class=='Number' or self.Class=='Boolean'): # favour number for Class== Number or Boolean default = String
+ if hint is None and (
+ self.Class == 'Number' or self.Class == 'Boolean'
+ ): # favour number for Class== Number or Boolean default = String
hint = 'Number'
return self.default_value(hint)
def to_boolean(self):
typ = Type(self)
- if typ=='Boolean': #no need to convert
+ if typ == 'Boolean': #no need to convert
return self
- elif typ=='Null' or typ=='Undefined': #they are both always false
+ elif typ == 'Null' or typ == 'Undefined': #they are both always false
return false
- elif typ=='Number' or typ=='String': #false only for 0, '' and NaN
- return Js(bool(self.value and self.value==self.value)) # test for nan (nan -> flase)
- else: #object - always true
+ elif typ == 'Number' or typ == 'String': #false only for 0, '' and NaN
+ return Js(bool(
+ self.value
+ and self.value == self.value)) # test for nan (nan -> flase)
+ else: #object - always true
return true
def to_number(self):
typ = Type(self)
- if typ=='Null': #null is 0
+ if typ == 'Null': #null is 0
return Js(0)
- elif typ=='Undefined': # undefined is NaN
+ elif typ == 'Undefined': # undefined is NaN
return NaN
- elif typ=='Boolean': # 1 for true 0 for false
+ elif typ == 'Boolean': # 1 for true 0 for false
return Js(int(self.value))
- elif typ=='Number':# or self.Class=='Number': # no need to convert
+ elif typ == 'Number': # or self.Class=='Number': # no need to convert
return self
- elif typ=='String':
- s = self.value.strip() #Strip white space
- if not s: # '' is simply 0
+ elif typ == 'String':
+ s = self.value.strip() #Strip white space
+ if not s: # '' is simply 0
return Js(0)
- if 'x' in s or 'X' in s[:3]: #hex (positive only)
- try: # try to convert
+ if 'x' in s or 'X' in s[:3]: #hex (positive only)
+ try: # try to convert
num = int(s, 16)
- except ValueError: # could not convert > NaN
+ except ValueError: # could not convert > NaN
return NaN
return Js(num)
- sign = 1 #get sign
+ sign = 1 #get sign
if s[0] in '+-':
- if s[0]=='-':
+ if s[0] == '-':
sign = -1
s = s[1:]
- if s=='Infinity': #Check for infinity keyword. 'NaN' will be NaN anyway.
- return Js(sign*float('inf'))
- try: #decimal try
- num = sign*float(s) # Converted
+ if s == 'Infinity': #Check for infinity keyword. 'NaN' will be NaN anyway.
+ return Js(sign * float('inf'))
+ try: #decimal try
+ num = sign * float(s) # Converted
except ValueError:
- return NaN # could not convert to decimal > return NaN
+ return NaN # could not convert to decimal > return NaN
return Js(num)
- else: #object - most likely it will be NaN.
+ else: #object - most likely it will be NaN.
return self.to_primitive('Number').to_number()
def to_string(self):
typ = Type(self)
- if typ=='Null':
+ if typ == 'Null':
return Js('null')
- elif typ=='Undefined':
+ elif typ == 'Undefined':
return Js('undefined')
- elif typ=='Boolean':
+ elif typ == 'Boolean':
return Js('true') if self.value else Js('false')
- elif typ=='Number': #or self.Class=='Number':
- if self.is_nan():
- return Js('NaN')
- elif self.is_infinity():
- sign = '-' if self.value<0 else ''
- return Js(sign+'Infinity')
- elif isinstance(self.value, long) or self.value.is_integer(): # dont print .0
- return Js(unicode(int(self.value)))
- return Js(unicode(self.value)) # accurate enough
- elif typ=='String':
+ elif typ == 'Number': #or self.Class=='Number':
+ return Js(unicode(js_dtoa(self.value)))
+ elif typ == 'String':
return self
- else: #object
+ else: #object
return self.to_primitive('String').to_string()
-
def to_object(self):
typ = self.TYPE
- if typ=='Null' or typ=='Undefined':
- raise MakeError('TypeError', 'undefined or null can\'t be converted to object')
- elif typ=='Boolean': # Unsure here... todo repair here
+ if typ == 'Null' or typ == 'Undefined':
+ raise MakeError('TypeError',
+ 'undefined or null can\'t be converted to object')
+ elif typ == 'Boolean': # Unsure here... todo repair here
return Boolean.create(self)
- elif typ=='Number': #?
+ elif typ == 'Number': #?
return Number.create(self)
- elif typ=='String': #?
+ elif typ == 'String': #?
return String.create(self)
- else: #object
+ else: #object
return self
def to_int32(self):
@@ -595,14 +637,15 @@ def strict_equality_comparison(self, other):
def cok(self):
"""Check object coercible"""
if self.Class in ('Undefined', 'Null'):
- raise MakeError('TypeError', 'undefined or null can\'t be converted to object')
+ raise MakeError('TypeError',
+ 'undefined or null can\'t be converted to object')
def to_int(self):
num = self.to_number()
if num.is_nan():
return 0
elif num.is_infinity():
- return 10**20 if num.value>0 else -10**20
+ return 10**20 if num.value > 0 else -10**20
return int(num.value)
def to_uint32(self):
@@ -624,44 +667,48 @@ def to_int16(self):
int16 = int(num.value) % 2**16
return int(int16 - 2**16 if int16 >= 2**15 else int16)
-
-
def same_as(self, other):
typ = Type(self)
- if typ!=other.Class:
+ if typ != other.Class:
return False
- if typ=='Undefined' or typ=='Null':
+ if typ == 'Undefined' or typ == 'Null':
return True
- if typ=='Boolean' or typ=='Number' or typ=='String':
- return self.value==other.value
- else: #object
- return self is other #Id compare.
+ if typ == 'Boolean' or typ == 'Number' or typ == 'String':
+ return self.value == other.value
+ else: #object
+ return self is other #Id compare.
#Not to be used by translation (only internal use)
def __getitem__(self, item):
- return self.get(str(item) if not isinstance(item, PyJs) else item.to_string().value)
+ return self.get(
+ str(item) if not isinstance(item, PyJs) else item.to_string().
+ value)
def __setitem__(self, item, value):
- self.put(str(item) if not isinstance(item, PyJs) else item.to_string().value, Js(value))
+ self.put(
+ str(item) if not isinstance(item, PyJs) else
+ item.to_string().value, Js(value))
def __len__(self):
try:
return self.get('length').to_uint32()
except:
- raise TypeError('This object (%s) does not have length property'%self.Class)
+ raise TypeError(
+ 'This object (%s) does not have length property' % self.Class)
+
#Oprators-------------
#Unary, other will be implemented as functions. Increments and decrements
# will be methods of Number class
- def __neg__(self): #-u
+ def __neg__(self): #-u
return Js(-self.to_number().value)
- def __pos__(self): #+u
+ def __pos__(self): #+u
return self.to_number()
- def __invert__(self): #~u
+ def __invert__(self): #~u
return Js(Js(~self.to_int32()).to_int32())
- def neg(self): # !u cant do 'not u' :(
+ def neg(self): # !u cant do 'not u' :(
return Js(not self.to_boolean().value)
def __nonzero__(self):
@@ -674,7 +721,7 @@ def typeof(self):
if self.is_callable():
return Js('function')
typ = Type(self).lower()
- if typ=='null':
+ if typ == 'null':
typ = 'object'
return Js(typ)
@@ -695,7 +742,6 @@ def __rshift__(self, other):
shiftCount = rnum & 0x1F
return Js(Js(lnum >> shiftCount).to_int32())
-
# >>>
def pyjs_bshift(self, other):
lnum = self.to_uint32()
@@ -728,47 +774,47 @@ def __or__(self, other):
def __add__(self, other):
a = self.to_primitive()
b = other.to_primitive()
- if a.TYPE=='String' or b.TYPE=='String':
- return Js(a.to_string().value+b.to_string().value)
+ if a.TYPE == 'String' or b.TYPE == 'String':
+ return Js(a.to_string().value + b.to_string().value)
a = a.to_number()
b = b.to_number()
- return Js(a.value+b.value)
+ return Js(a.value + b.value)
# -
def __sub__(self, other):
- return Js(self.to_number().value-other.to_number().value)
+ return Js(self.to_number().value - other.to_number().value)
#Multiplicative operators
# *, / and % are implemented here
# *
def __mul__(self, other):
- return Js(self.to_number().value*other.to_number().value)
+ return Js(self.to_number().value * other.to_number().value)
# /
def __div__(self, other):
a = self.to_number().value
b = other.to_number().value
if b:
- return Js(a/b)
- if not a or a!=a:
+ return Js(a / b)
+ if not a or a != a:
return NaN
- return Infinity if a>0 else -Infinity
+ return Infinity if a > 0 else -Infinity
# %
def __mod__(self, other):
a = self.to_number().value
b = other.to_number().value
- if abs(a)==float('inf') or not b:
+ if abs(a) == float('inf') or not b:
return NaN
- if abs(b)==float('inf'):
+ if abs(b) == float('inf'):
return Js(a)
- pyres = Js(a%b) #different signs in python and javascript
- #python has the same sign as b and js has the same
- #sign as a.
- if a<0 and pyres.value>0:
+ pyres = Js(a % b) #different signs in python and javascript
+ #python has the same sign as b and js has the same
+ #sign as a.
+ if a < 0 and pyres.value > 0:
pyres.value -= abs(b)
- elif a>0 and pyres.value<0:
+ elif a > 0 and pyres.value < 0:
pyres.value += abs(b)
return Js(pyres)
@@ -784,17 +830,17 @@ def abstract_relational_comparison(self, other, self_first=True):
result is PyJs type: bool or undefined'''
px = self.to_primitive('Number')
py = other.to_primitive('Number')
- if not self_first: #reverse order
+ if not self_first: #reverse order
px, py = py, px
- if not (px.Class=='String' and py.Class=='String'):
+ if not (px.Class == 'String' and py.Class == 'String'):
px, py = px.to_number(), py.to_number()
if px.is_nan() or py.is_nan():
return undefined
- return Js(px.value>>b"""
return a.pyjs_bshift(b)
@@ -980,31 +1039,35 @@ def PyJsBshift(a, b):
def PyJsComma(a, b):
return b
-class PyJsException(Exception):
- def __str__(self):
- if self.mes.Class=='Error':
- return self.mes.callprop('toString').value
- else:
- return unicode(self.mes)
-class PyJsSwitchException(Exception): pass
+from .internals.simplex import JsException as PyJsException, js_dtoa
+import pyjsparser
+pyjsparser.parser.ENABLE_JS2PY_ERRORS = lambda msg: MakeError('SyntaxError', msg)
+
+
+class PyJsSwitchException(Exception):
+ pass
PyJs.MakeError = staticmethod(MakeError)
+
def JsToPyException(js):
temp = PyJsException()
temp.mes = js
return temp
+
def PyExceptionToJs(py):
return py.mes
+
#Scope class it will hold all the variables accessible to user
class Scope(PyJs):
Class = 'global'
extensible = True
IS_CHILD_SCOPE = True
+
# todo speed up
# in order to speed up this very important class the top scope should behave differently than
# child scopes, child scope should not have this property descriptor thing because they cant be changed anyway
@@ -1018,11 +1081,16 @@ def __init__(self, scope, closure=None):
self.own = {}
for k, v in six.iteritems(scope):
# set all the global items
- self.define_own_property(k, {'value': v, 'configurable': False,
- 'writable': False, 'enumerable': False})
+ self.define_own_property(
+ k, {
+ 'value': v,
+ 'configurable': False,
+ 'writable': False,
+ 'enumerable': False
+ })
else:
# not global, less powerful but faster closure.
- self.own = scope # simple dictionary which maps name directly to js object.
+ self.own = scope # simple dictionary which maps name directly to js object.
def register(self, lval):
# registered keeps only global registered variables
@@ -1031,11 +1099,16 @@ def register(self, lval):
if lval in self.own:
self.own[lval]['configurable'] = False
else:
- self.define_own_property(lval, {'value': undefined, 'configurable': False,
- 'writable': True, 'enumerable': True})
+ self.define_own_property(
+ lval, {
+ 'value': undefined,
+ 'configurable': False,
+ 'writable': True,
+ 'enumerable': True
+ })
elif lval not in self.own:
# define in local scope since it has not been defined yet
- self.own[lval] = undefined # default value
+ self.own[lval] = undefined # default value
def registers(self, lvals):
"""register multiple variables"""
@@ -1050,8 +1123,8 @@ def put(self, lval, val, op=None):
# trying to put in local scope
# we dont know yet in which scope we should place this var
if lval in self.own:
- if op: # increment operation
- val = getattr(self.own[lval], OP_METHODS[op])(val)
+ if op: # increment operation
+ val = getattr(self.own[lval], OP_METHODS[op])(val)
self.own[lval] = val
return val
else:
@@ -1059,8 +1132,13 @@ def put(self, lval, val, op=None):
return self.prototype.put(lval, val, op)
def force_own_put(self, prop, val, configurable=False):
- if self.prototype is None: # global scope
- self.own[prop] = {'value': val, 'writable': True, 'enumerable':True, 'configurable':configurable}
+ if self.prototype is None: # global scope
+ self.own[prop] = {
+ 'value': val,
+ 'writable': True,
+ 'enumerable': True,
+ 'configurable': configurable
+ }
else:
self.own[prop] = val
@@ -1106,11 +1184,14 @@ def __repr__(self):
def to_python(self):
return to_python(self)
+
class This(Scope):
IS_CHILD_SCOPE = False
+
def get(self, prop, throw=False):
return Scope.get(self, prop, throw)
+
class JsObjectWrapper(object):
def __init__(self, obj):
self.__dict__['_obj'] = obj
@@ -1118,7 +1199,7 @@ def __init__(self, obj):
def __call__(self, *args):
args = tuple(Js(e) for e in args)
if '_prop_of' in self.__dict__:
- parent, meth = self.__dict__['_prop_of']
+ parent, meth = self.__dict__['_prop_of']
return to_python(parent._obj.callprop(meth, *args))
return to_python(self._obj(*args))
@@ -1128,6 +1209,7 @@ def __getattr__(self, item):
def PyJsInstanceInit(*args):
args = tuple(Js(e) for e in args)
return self._obj.create(*args).to_python()
+
return PyJsInstanceInit
cand = to_python(self._obj.get(str(item)))
# handling method calling... obj.meth(). Value of this in meth should be self
@@ -1148,17 +1230,25 @@ def __setitem__(self, item, value):
self._obj.put(str(item), Js(value))
def __iter__(self):
- if self._obj.Class in ['Array', 'Int8Array','Uint8Array','Uint8ClampedArray','Int16Array','Uint16Array','Int32Array','Uint32Array','Float32Array','Float64Array']:
+ if self._obj.Class in [
+ 'Array', 'Int8Array', 'Uint8Array', 'Uint8ClampedArray',
+ 'Int16Array', 'Uint16Array', 'Int32Array', 'Uint32Array',
+ 'Float32Array', 'Float64Array'
+ ]:
return iter(self.to_list())
- elif self._obj.Class=='Object':
+ elif self._obj.Class == 'Object':
return iter(self.to_dict())
else:
- raise MakeError('TypeError', '%s is not iterable in Python' % self._obj.Class)
+ raise MakeError('TypeError',
+ '%s is not iterable in Python' % self._obj.Class)
def __repr__(self):
if self._obj.is_primitive() or self._obj.is_callable():
return repr(self._obj)
- elif self._obj.Class in ('Array', 'Int8Array','Uint8Array','Uint8ClampedArray','Int16Array','Uint16Array','Int32Array','Uint32Array','Float32Array','Float64Array', 'Arguments'):
+ elif self._obj.Class in ('Array', 'Int8Array', 'Uint8Array',
+ 'Uint8ClampedArray', 'Int16Array',
+ 'Uint16Array', 'Int32Array', 'Uint32Array',
+ 'Float32Array', 'Float64Array', 'Arguments'):
return repr(self.to_list())
return repr(self.to_dict())
@@ -1177,8 +1267,10 @@ def to_dict(self):
def to_list(self):
return to_list(self.__dict__['_obj'])
+
class PyObjectWrapper(PyJs):
Class = 'PyObjectWrapper'
+
def __init__(self, obj):
self.obj = obj
@@ -1192,10 +1284,15 @@ def get(self, prop):
except:
return undefined
- def put(self, prop, val, throw=False):
+ def put(self, prop, val, op=None, throw=False):
if not isinstance(prop, basestring):
prop = prop.to_string().value
try:
+ if isinstance(op, bool):
+ raise ValueError("Op must be a string")
+ elif op is not None:
+ if op: # increment operation
+ val = getattr(self.get(prop), OP_METHODS[op])(val)
setattr(self.obj, prop, to_python(val))
except AttributeError:
raise MakeError('TypeError', 'Read only object probably...')
@@ -1208,13 +1305,12 @@ def __call__(self, *args):
except Exception as e:
message = 'your Python function failed! '
try:
- message += e.message
+ message += str(e)
except:
pass
raise MakeError('Error', message)
return py_wrap(py_res)
-
def callprop(self, prop, *args):
py_args = tuple(to_python(e) for e in args)
if not isinstance(prop, basestring):
@@ -1244,20 +1340,21 @@ def to_py(self):
def py_wrap(py):
- if isinstance(py, (FunctionType, BuiltinFunctionType, MethodType, BuiltinMethodType,
- dict, int, str, bool, float, list, tuple, long, basestring)) or py is None :
+ if isinstance(py, (FunctionType, BuiltinFunctionType, MethodType,
+ BuiltinMethodType, dict, int, str, bool, float, list,
+ tuple, long, basestring)) or py is None:
return HJs(py)
return PyObjectWrapper(py)
-
-
##############################################################################
#Define types
+
#Object
class PyJsObject(PyJs):
Class = 'Object'
+
def __init__(self, prop_descs={}, prototype=None, extensible=True):
self.prototype = prototype
self.extensible = extensible
@@ -1269,13 +1366,13 @@ def __repr__(self):
return repr(self.to_python().to_dict())
-
ObjectPrototype = PyJsObject()
#Function
class PyJsFunction(PyJs):
Class = 'Function'
+
def __init__(self, func, prototype=None, extensible=True, source=None):
cand = fix_js_args(func)
has_scope = cand is func
@@ -1283,25 +1380,46 @@ def __init__(self, func, prototype=None, extensible=True, source=None):
self.argcount = six.get_function_code(func).co_argcount - 2 - has_scope
self.code = func
self.source = source if source else '{ [python code] }'
- self.func_name = func.__name__ if not func.__name__.startswith('PyJs_anonymous') else ''
+ self.func_name = func.__name__ if not func.__name__.startswith(
+ 'PyJs_anonymous') else ''
self.extensible = extensible
self.prototype = prototype
self.own = {}
#set own property length to the number of arguments
- self.define_own_property('length', {'value': Js(self.argcount), 'writable': False,
- 'enumerable': False, 'configurable': False})
+ self.define_own_property(
+ 'length', {
+ 'value': Js(self.argcount),
+ 'writable': False,
+ 'enumerable': False,
+ 'configurable': False
+ })
if self.func_name:
- self.define_own_property('name', {'value': Js(self.func_name), 'writable': False,
- 'enumerable': False, 'configurable': True})
+ self.define_own_property(
+ 'name', {
+ 'value': Js(self.func_name),
+ 'writable': False,
+ 'enumerable': False,
+ 'configurable': True
+ })
# set own prototype
proto = Js({})
# constructor points to this function
- proto.define_own_property('constructor',{'value': self, 'writable': True,
- 'enumerable': False, 'configurable': True})
- self.define_own_property('prototype', {'value': proto, 'writable': True,
- 'enumerable': False, 'configurable': False})
+ proto.define_own_property(
+ 'constructor', {
+ 'value': self,
+ 'writable': True,
+ 'enumerable': False,
+ 'configurable': True
+ })
+ self.define_own_property(
+ 'prototype', {
+ 'value': proto,
+ 'writable': True,
+ 'enumerable': False,
+ 'configurable': False
+ })
def _set_name(self, name):
'''name is py type'''
@@ -1311,7 +1429,7 @@ def _set_name(self, name):
def construct(self, *args):
proto = self.get('prototype')
- if not proto.is_object(): # set to standard prototype
+ if not proto.is_object(): # set to standard prototype
proto = ObjectPrototype
obj = PyJsObject(prototype=proto)
cand = self.call(obj, *args)
@@ -1331,22 +1449,27 @@ def call(self, this, args=()):
(but they will be present in arguments object).
'''
if not hasattr(args, '__iter__'): #get rid of it later
- args = (args,)
- args = tuple(Js(e) for e in args) # this wont be needed later
+ args = (args, )
+ args = tuple(Js(e) for e in args) # this wont be needed later
- arguments = PyJsArguments(args, self) # tuple will be converted to arguments object.
- arglen = self.argcount #function expects this number of args.
- if len(args)>arglen:
+ arguments = PyJsArguments(
+ args, self) # tuple will be converted to arguments object.
+ arglen = self.argcount #function expects this number of args.
+ if len(args) > arglen:
args = args[0:arglen]
- elif len(args)>': '__rshift__',
- '&': '__and__',
- '^': '__xor__',
- '|': '__or__',
- '>>>': 'pyjs_bshift'}
+OP_METHODS = {
+ '*': '__mul__',
+ '/': '__div__',
+ '%': '__mod__',
+ '+': '__add__',
+ '-': '__sub__',
+ '<<': '__lshift__',
+ '>>': '__rshift__',
+ '&': '__and__',
+ '^': '__xor__',
+ '|': '__or__',
+ '>>>': 'pyjs_bshift'
+}
+
def Empty():
return Js(None)
+
#Number
class PyJsNumber(PyJs): #Note i dont implement +0 and -0. Just 0.
TYPE = 'Number'
Class = 'Number'
-
NumberPrototype = PyJsObject({}, ObjectPrototype)
NumberPrototype.Class = 'Number'
NumberPrototype.value = 0
@@ -1444,6 +1592,8 @@ class PyJsNumber(PyJs): #Note i dont implement +0 and -0. Just 0.
CHAR_BANK = {}
NUM_BANK = {}
PyJs.CHAR_BANK = CHAR_BANK
+
+
#String
# Different than implementation design in order to improve performance
#for example I dont create separate property for each character in string, it would take ages.
@@ -1451,31 +1601,36 @@ class PyJsString(PyJs):
TYPE = 'String'
Class = 'String'
extensible = False
+
def __init__(self, value=None, prototype=None):
'''Constructor for Number String and Boolean'''
if not isinstance(value, basestring):
- raise TypeError # this will be internal error
+ raise TypeError # this will be internal error
self.value = value
self.prototype = prototype
self.own = {}
- # this should be optimized because its mych slower than python str creation (about 50 times!)
+ # this should be optimized because its mych slower than python str creation (about 50 times!)
# Dont create separate properties for every index. Just
- self.own['length'] = {'value': Js(len(value)), 'writable': False,
- 'enumerable': False, 'configurable': False}
- if len(value)==1:
- CHAR_BANK[value] = self #, 'writable': False,
- # 'enumerable': True, 'configurable': False}
+ self.own['length'] = {
+ 'value': Js(len(value)),
+ 'writable': False,
+ 'enumerable': False,
+ 'configurable': False
+ }
+ if len(value) == 1:
+ CHAR_BANK[value] = self #, 'writable': False,
+ # 'enumerable': True, 'configurable': False}
def get(self, prop):
if not isinstance(prop, basestring):
- prop = prop.to_string().value
+ prop = prop.to_string().value
try:
index = int(prop)
- if index<0:
+ if index < 0:
return undefined
char = self.value[index]
if char not in CHAR_BANK:
- Js(char) # this will add char to CHAR BANK
+ Js(char) # this will add char to CHAR BANK
return CHAR_BANK[char]
except Exception:
pass
@@ -1495,11 +1650,13 @@ def __iter__(self):
CHAR_BANK[''] = Js('')
+
#Boolean
class PyJsBoolean(PyJs):
TYPE = 'Boolean'
Class = 'Boolean'
+
BooleanPrototype = PyJsObject({}, ObjectPrototype)
BooleanPrototype.Class = 'Boolean'
BooleanPrototype.value = False
@@ -1512,69 +1669,94 @@ class PyJsBoolean(PyJs):
class PyJsUndefined(PyJs):
TYPE = 'Undefined'
Class = 'Undefined'
+
def __init__(self):
pass
+
undefined = PyJsUndefined()
+
#Null
class PyJsNull(PyJs):
TYPE = 'Null'
Class = 'Null'
+
def __init__(self):
pass
+
+
null = PyJsNull()
PyJs.null = null
+
class PyJsArray(PyJs):
Class = 'Array'
+
def __init__(self, arr=[], prototype=None):
self.extensible = True
self.prototype = prototype
- self.own = {'length' : {'value': Js(0), 'writable': True,
- 'enumerable': False, 'configurable': False}}
+ self.own = {
+ 'length': {
+ 'value': Js(0),
+ 'writable': True,
+ 'enumerable': False,
+ 'configurable': False
+ }
+ }
for i, e in enumerate(arr):
- self.define_own_property(str(i), {'value': Js(e), 'writable': True,
- 'enumerable': True, 'configurable': True})
+ self.define_own_property(
+ str(i), {
+ 'value': Js(e),
+ 'writable': True,
+ 'enumerable': True,
+ 'configurable': True
+ })
+
def define_own_property(self, prop, desc):
old_len_desc = self.get_own_property('length')
- old_len = old_len_desc['value'].value # value is js type so convert to py.
- if prop=='length':
+ old_len = old_len_desc[
+ 'value'].value # value is js type so convert to py.
+ if prop == 'length':
if 'value' not in desc:
return PyJs.define_own_property(self, prop, desc)
- new_len = desc['value'].to_uint32()
- if new_len!=desc['value'].to_number().value:
+ new_len = desc['value'].to_uint32()
+ if new_len != desc['value'].to_number().value:
raise MakeError('RangeError', 'Invalid range!')
- new_desc = dict((k,v) for k,v in six.iteritems(desc))
+ new_desc = dict((k, v) for k, v in six.iteritems(desc))
new_desc['value'] = Js(new_len)
- if new_len>=old_len:
+ if new_len >= old_len:
return PyJs.define_own_property(self, prop, new_desc)
if not old_len_desc['writable']:
return False
- if 'writable' not in new_desc or new_desc['writable']==True:
+ if 'writable' not in new_desc or new_desc['writable'] == True:
new_writable = True
else:
new_writable = False
new_desc['writable'] = True
if not PyJs.define_own_property(self, prop, new_desc):
return False
- if new_len30*len(self.own):
+ if old_len > 30 * len(self.own):
for ele in self.own.keys():
- if ele.isdigit() and int(ele)>=new_len:
- if not self.delete(ele): # if failed to delete set len to current len and reject.
- new_desc['value'] = Js(old_len+1)
+ if ele.isdigit() and int(ele) >= new_len:
+ if not self.delete(
+ ele
+ ): # if failed to delete set len to current len and reject.
+ new_desc['value'] = Js(old_len + 1)
if not new_writable:
new_desc['writable'] = False
PyJs.define_own_property(self, prop, new_desc)
return False
old_len = new_len
- else: # standard method
- while new_len=old_len and not old_len_desc['writable']:
+ if index >= old_len and not old_len_desc['writable']:
return False
if not PyJs.define_own_property(self, prop, desc):
return False
- if index>=old_len:
+ if index >= old_len:
old_len_desc['value'] = Js(index + 1)
return True
else:
return PyJs.define_own_property(self, prop, desc)
def to_list(self):
- return [self.get(str(e)) for e in xrange(self.get('length').to_uint32())]
+ return [
+ self.get(str(e)) for e in xrange(self.get('length').to_uint32())
+ ]
def __repr__(self):
return repr(self.to_python().to_list())
+
class PyJsArrayBuffer(PyJs):
Class = 'ArrayBuffer'
+
def __init__(self, arr=[], prototype=None):
self.extensible = True
self.prototype = prototype
- self.own = {'length' : {'value': Js(0), 'writable': True,
- 'enumerable': False, 'configurable': False}}
+ self.own = {
+ 'length': {
+ 'value': Js(0),
+ 'writable': True,
+ 'enumerable': False,
+ 'configurable': False
+ }
+ }
for i, e in enumerate(arr):
- self.define_own_property(str(i), {'value': Js(e), 'writable': True,
- 'enumerable': True, 'configurable': True})
+ self.define_own_property(
+ str(i), {
+ 'value': Js(e),
+ 'writable': True,
+ 'enumerable': True,
+ 'configurable': True
+ })
+
def define_own_property(self, prop, desc):
old_len_desc = self.get_own_property('length')
- old_len = old_len_desc['value'].value # value is js type so convert to py.
- if prop=='length':
+ old_len = old_len_desc[
+ 'value'].value # value is js type so convert to py.
+ if prop == 'length':
if 'value' not in desc:
return PyJs.define_own_property(self, prop, desc)
- new_len = desc['value'].to_uint32()
- if new_len!=desc['value'].to_number().value:
+ new_len = desc['value'].to_uint32()
+ if new_len != desc['value'].to_number().value:
raise MakeError('RangeError', 'Invalid range!')
- new_desc = dict((k,v) for k,v in six.iteritems(desc))
+ new_desc = dict((k, v) for k, v in six.iteritems(desc))
new_desc['value'] = Js(new_len)
- if new_len>=old_len:
+ if new_len >= old_len:
return PyJs.define_own_property(self, prop, new_desc)
if not old_len_desc['writable']:
return False
- if 'writable' not in new_desc or new_desc['writable']==True:
+ if 'writable' not in new_desc or new_desc['writable'] == True:
new_writable = True
else:
new_writable = False
new_desc['writable'] = True
if not PyJs.define_own_property(self, prop, new_desc):
return False
- if new_len30*len(self.own):
+ if old_len > 30 * len(self.own):
for ele in self.own.keys():
- if ele.isdigit() and int(ele)>=new_len:
- if not self.delete(ele): # if failed to delete set len to current len and reject.
- new_desc['value'] = Js(old_len+1)
+ if ele.isdigit() and int(ele) >= new_len:
+ if not self.delete(
+ ele
+ ): # if failed to delete set len to current len and reject.
+ new_desc['value'] = Js(old_len + 1)
if not new_writable:
new_desc['writable'] = False
PyJs.define_own_property(self, prop, new_desc)
return False
old_len = new_len
- else: # standard method
- while new_len=old_len and not old_len_desc['writable']:
+ if index >= old_len and not old_len_desc['writable']:
return False
if not PyJs.define_own_property(self, prop, desc):
return False
- if index>=old_len:
+ if index >= old_len:
old_len_desc['value'] = Js(index + 1)
return True
else:
return PyJs.define_own_property(self, prop, desc)
def to_list(self):
- return [self.get(str(e)) for e in xrange(self.get('length').to_uint32())]
+ return [
+ self.get(str(e)) for e in xrange(self.get('length').to_uint32())
+ ]
def __repr__(self):
return repr(self.to_python().to_list())
+
class PyJsInt8Array(PyJs):
Class = 'Int8Array'
+
def __init__(self, arr=[], prototype=None):
self.extensible = True
self.prototype = prototype
- self.own = {'length' : {'value': Js(0), 'writable': True,
- 'enumerable': False, 'configurable': False}}
+ self.own = {
+ 'length': {
+ 'value': Js(0),
+ 'writable': True,
+ 'enumerable': False,
+ 'configurable': False
+ }
+ }
for i, e in enumerate(arr):
- self.define_own_property(str(i), {'value': Js(e), 'writable': True,
- 'enumerable': True, 'configurable': True})
+ self.define_own_property(
+ str(i), {
+ 'value': Js(e),
+ 'writable': True,
+ 'enumerable': True,
+ 'configurable': True
+ })
+
def define_own_property(self, prop, desc):
old_len_desc = self.get_own_property('length')
- old_len = old_len_desc['value'].value # value is js type so convert to py.
- if prop=='length':
+ old_len = old_len_desc[
+ 'value'].value # value is js type so convert to py.
+ if prop == 'length':
if 'value' not in desc:
return PyJs.define_own_property(self, prop, desc)
- new_len = desc['value'].to_uint32()
- if new_len!=desc['value'].to_number().value:
+ new_len = desc['value'].to_uint32()
+ if new_len != desc['value'].to_number().value:
raise MakeError('RangeError', 'Invalid range!')
- new_desc = dict((k,v) for k,v in six.iteritems(desc))
+ new_desc = dict((k, v) for k, v in six.iteritems(desc))
new_desc['value'] = Js(new_len)
- if new_len>=old_len:
+ if new_len >= old_len:
return PyJs.define_own_property(self, prop, new_desc)
if not old_len_desc['writable']:
return False
- if 'writable' not in new_desc or new_desc['writable']==True:
+ if 'writable' not in new_desc or new_desc['writable'] == True:
new_writable = True
else:
new_writable = False
new_desc['writable'] = True
if not PyJs.define_own_property(self, prop, new_desc):
return False
- if new_len30*len(self.own):
+ if old_len > 30 * len(self.own):
for ele in self.own.keys():
- if ele.isdigit() and int(ele)>=new_len:
- if not self.delete(ele): # if failed to delete set len to current len and reject.
- new_desc['value'] = Js(old_len+1)
+ if ele.isdigit() and int(ele) >= new_len:
+ if not self.delete(
+ ele
+ ): # if failed to delete set len to current len and reject.
+ new_desc['value'] = Js(old_len + 1)
if not new_writable:
new_desc['writable'] = False
PyJs.define_own_property(self, prop, new_desc)
return False
old_len = new_len
- else: # standard method
- while new_len=old_len and not old_len_desc['writable']:
+ if index >= old_len and not old_len_desc['writable']:
return False
if not PyJs.define_own_property(self, prop, desc):
return False
- if index>=old_len:
+ if index >= old_len:
old_len_desc['value'] = Js(index + 1)
return True
else:
return PyJs.define_own_property(self, prop, desc)
def to_list(self):
- return [self.get(str(e)) for e in xrange(self.get('length').to_uint32())]
+ return [
+ self.get(str(e)) for e in xrange(self.get('length').to_uint32())
+ ]
def __repr__(self):
return repr(self.to_python().to_list())
+
class PyJsUint8Array(PyJs):
Class = 'Uint8Array'
+
def __init__(self, arr=[], prototype=None):
self.extensible = True
self.prototype = prototype
- self.own = {'length' : {'value': Js(0), 'writable': True,
- 'enumerable': False, 'configurable': False}}
+ self.own = {
+ 'length': {
+ 'value': Js(0),
+ 'writable': True,
+ 'enumerable': False,
+ 'configurable': False
+ }
+ }
for i, e in enumerate(arr):
- self.define_own_property(str(i), {'value': Js(e), 'writable': True,
- 'enumerable': True, 'configurable': True})
+ self.define_own_property(
+ str(i), {
+ 'value': Js(e),
+ 'writable': True,
+ 'enumerable': True,
+ 'configurable': True
+ })
+
def define_own_property(self, prop, desc):
old_len_desc = self.get_own_property('length')
- old_len = old_len_desc['value'].value # value is js type so convert to py.
- if prop=='length':
+ old_len = old_len_desc[
+ 'value'].value # value is js type so convert to py.
+ if prop == 'length':
if 'value' not in desc:
return PyJs.define_own_property(self, prop, desc)
- new_len = desc['value'].to_uint32()
- if new_len!=desc['value'].to_number().value:
+ new_len = desc['value'].to_uint32()
+ if new_len != desc['value'].to_number().value:
raise MakeError('RangeError', 'Invalid range!')
- new_desc = dict((k,v) for k,v in six.iteritems(desc))
+ new_desc = dict((k, v) for k, v in six.iteritems(desc))
new_desc['value'] = Js(new_len)
- if new_len>=old_len:
+ if new_len >= old_len:
return PyJs.define_own_property(self, prop, new_desc)
if not old_len_desc['writable']:
return False
- if 'writable' not in new_desc or new_desc['writable']==True:
+ if 'writable' not in new_desc or new_desc['writable'] == True:
new_writable = True
else:
new_writable = False
new_desc['writable'] = True
if not PyJs.define_own_property(self, prop, new_desc):
return False
- if new_len30*len(self.own):
+ if old_len > 30 * len(self.own):
for ele in self.own.keys():
- if ele.isdigit() and int(ele)>=new_len:
- if not self.delete(ele): # if failed to delete set len to current len and reject.
- new_desc['value'] = Js(old_len+1)
+ if ele.isdigit() and int(ele) >= new_len:
+ if not self.delete(
+ ele
+ ): # if failed to delete set len to current len and reject.
+ new_desc['value'] = Js(old_len + 1)
if not new_writable:
new_desc['writable'] = False
PyJs.define_own_property(self, prop, new_desc)
return False
old_len = new_len
- else: # standard method
- while new_len=old_len and not old_len_desc['writable']:
+ if index >= old_len and not old_len_desc['writable']:
return False
if not PyJs.define_own_property(self, prop, desc):
return False
- if index>=old_len:
+ if index >= old_len:
old_len_desc['value'] = Js(index + 1)
return True
else:
return PyJs.define_own_property(self, prop, desc)
def to_list(self):
- return [self.get(str(e)) for e in xrange(self.get('length').to_uint32())]
+ return [
+ self.get(str(e)) for e in xrange(self.get('length').to_uint32())
+ ]
def __repr__(self):
return repr(self.to_python().to_list())
+
class PyJsUint8ClampedArray(PyJs):
Class = 'Uint8ClampedArray'
+
def __init__(self, arr=[], prototype=None):
self.extensible = True
self.prototype = prototype
- self.own = {'length' : {'value': Js(0), 'writable': True,
- 'enumerable': False, 'configurable': False}}
+ self.own = {
+ 'length': {
+ 'value': Js(0),
+ 'writable': True,
+ 'enumerable': False,
+ 'configurable': False
+ }
+ }
for i, e in enumerate(arr):
- self.define_own_property(str(i), {'value': Js(e), 'writable': True,
- 'enumerable': True, 'configurable': True})
+ self.define_own_property(
+ str(i), {
+ 'value': Js(e),
+ 'writable': True,
+ 'enumerable': True,
+ 'configurable': True
+ })
+
def define_own_property(self, prop, desc):
old_len_desc = self.get_own_property('length')
- old_len = old_len_desc['value'].value # value is js type so convert to py.
- if prop=='length':
+ old_len = old_len_desc[
+ 'value'].value # value is js type so convert to py.
+ if prop == 'length':
if 'value' not in desc:
return PyJs.define_own_property(self, prop, desc)
- new_len = desc['value'].to_uint32()
- if new_len!=desc['value'].to_number().value:
+ new_len = desc['value'].to_uint32()
+ if new_len != desc['value'].to_number().value:
raise MakeError('RangeError', 'Invalid range!')
- new_desc = dict((k,v) for k,v in six.iteritems(desc))
+ new_desc = dict((k, v) for k, v in six.iteritems(desc))
new_desc['value'] = Js(new_len)
- if new_len>=old_len:
+ if new_len >= old_len:
return PyJs.define_own_property(self, prop, new_desc)
if not old_len_desc['writable']:
return False
- if 'writable' not in new_desc or new_desc['writable']==True:
+ if 'writable' not in new_desc or new_desc['writable'] == True:
new_writable = True
else:
new_writable = False
new_desc['writable'] = True
if not PyJs.define_own_property(self, prop, new_desc):
return False
- if new_len30*len(self.own):
+ if old_len > 30 * len(self.own):
for ele in self.own.keys():
- if ele.isdigit() and int(ele)>=new_len:
- if not self.delete(ele): # if failed to delete set len to current len and reject.
- new_desc['value'] = Js(old_len+1)
+ if ele.isdigit() and int(ele) >= new_len:
+ if not self.delete(
+ ele
+ ): # if failed to delete set len to current len and reject.
+ new_desc['value'] = Js(old_len + 1)
if not new_writable:
new_desc['writable'] = False
PyJs.define_own_property(self, prop, new_desc)
return False
old_len = new_len
- else: # standard method
- while new_len=old_len and not old_len_desc['writable']:
+ if index >= old_len and not old_len_desc['writable']:
return False
if not PyJs.define_own_property(self, prop, desc):
return False
- if index>=old_len:
+ if index >= old_len:
old_len_desc['value'] = Js(index + 1)
return True
else:
return PyJs.define_own_property(self, prop, desc)
def to_list(self):
- return [self.get(str(e)) for e in xrange(self.get('length').to_uint32())]
+ return [
+ self.get(str(e)) for e in xrange(self.get('length').to_uint32())
+ ]
def __repr__(self):
return repr(self.to_python().to_list())
+
class PyJsInt16Array(PyJs):
Class = 'Int16Array'
+
def __init__(self, arr=[], prototype=None):
self.extensible = True
self.prototype = prototype
- self.own = {'length' : {'value': Js(0), 'writable': True,
- 'enumerable': False, 'configurable': False}}
+ self.own = {
+ 'length': {
+ 'value': Js(0),
+ 'writable': True,
+ 'enumerable': False,
+ 'configurable': False
+ }
+ }
for i, e in enumerate(arr):
- self.define_own_property(str(i), {'value': Js(e), 'writable': True,
- 'enumerable': True, 'configurable': True})
+ self.define_own_property(
+ str(i), {
+ 'value': Js(e),
+ 'writable': True,
+ 'enumerable': True,
+ 'configurable': True
+ })
+
def define_own_property(self, prop, desc):
old_len_desc = self.get_own_property('length')
- old_len = old_len_desc['value'].value # value is js type so convert to py.
- if prop=='length':
+ old_len = old_len_desc[
+ 'value'].value # value is js type so convert to py.
+ if prop == 'length':
if 'value' not in desc:
return PyJs.define_own_property(self, prop, desc)
- new_len = desc['value'].to_uint32()
- if new_len!=desc['value'].to_number().value:
+ new_len = desc['value'].to_uint32()
+ if new_len != desc['value'].to_number().value:
raise MakeError('RangeError', 'Invalid range!')
- new_desc = dict((k,v) for k,v in six.iteritems(desc))
+ new_desc = dict((k, v) for k, v in six.iteritems(desc))
new_desc['value'] = Js(new_len)
- if new_len>=old_len:
+ if new_len >= old_len:
return PyJs.define_own_property(self, prop, new_desc)
if not old_len_desc['writable']:
return False
- if 'writable' not in new_desc or new_desc['writable']==True:
+ if 'writable' not in new_desc or new_desc['writable'] == True:
new_writable = True
else:
new_writable = False
new_desc['writable'] = True
if not PyJs.define_own_property(self, prop, new_desc):
return False
- if new_len30*len(self.own):
+ if old_len > 30 * len(self.own):
for ele in self.own.keys():
- if ele.isdigit() and int(ele)>=new_len:
- if not self.delete(ele): # if failed to delete set len to current len and reject.
- new_desc['value'] = Js(old_len+1)
+ if ele.isdigit() and int(ele) >= new_len:
+ if not self.delete(
+ ele
+ ): # if failed to delete set len to current len and reject.
+ new_desc['value'] = Js(old_len + 1)
if not new_writable:
new_desc['writable'] = False
PyJs.define_own_property(self, prop, new_desc)
return False
old_len = new_len
- else: # standard method
- while new_len=old_len and not old_len_desc['writable']:
+ if index >= old_len and not old_len_desc['writable']:
return False
if not PyJs.define_own_property(self, prop, desc):
return False
- if index>=old_len:
+ if index >= old_len:
old_len_desc['value'] = Js(index + 1)
return True
else:
return PyJs.define_own_property(self, prop, desc)
def to_list(self):
- return [self.get(str(e)) for e in xrange(self.get('length').to_uint32())]
+ return [
+ self.get(str(e)) for e in xrange(self.get('length').to_uint32())
+ ]
def __repr__(self):
return repr(self.to_python().to_list())
+
class PyJsUint16Array(PyJs):
Class = 'Uint16Array'
+
def __init__(self, arr=[], prototype=None):
self.extensible = True
self.prototype = prototype
- self.own = {'length' : {'value': Js(0), 'writable': True,
- 'enumerable': False, 'configurable': False}}
+ self.own = {
+ 'length': {
+ 'value': Js(0),
+ 'writable': True,
+ 'enumerable': False,
+ 'configurable': False
+ }
+ }
for i, e in enumerate(arr):
- self.define_own_property(str(i), {'value': Js(e), 'writable': True,
- 'enumerable': True, 'configurable': True})
+ self.define_own_property(
+ str(i), {
+ 'value': Js(e),
+ 'writable': True,
+ 'enumerable': True,
+ 'configurable': True
+ })
+
def define_own_property(self, prop, desc):
old_len_desc = self.get_own_property('length')
- old_len = old_len_desc['value'].value # value is js type so convert to py.
- if prop=='length':
+ old_len = old_len_desc[
+ 'value'].value # value is js type so convert to py.
+ if prop == 'length':
if 'value' not in desc:
return PyJs.define_own_property(self, prop, desc)
- new_len = desc['value'].to_uint32()
- if new_len!=desc['value'].to_number().value:
+ new_len = desc['value'].to_uint32()
+ if new_len != desc['value'].to_number().value:
raise MakeError('RangeError', 'Invalid range!')
- new_desc = dict((k,v) for k,v in six.iteritems(desc))
+ new_desc = dict((k, v) for k, v in six.iteritems(desc))
new_desc['value'] = Js(new_len)
- if new_len>=old_len:
+ if new_len >= old_len:
return PyJs.define_own_property(self, prop, new_desc)
if not old_len_desc['writable']:
return False
- if 'writable' not in new_desc or new_desc['writable']==True:
+ if 'writable' not in new_desc or new_desc['writable'] == True:
new_writable = True
else:
new_writable = False
new_desc['writable'] = True
if not PyJs.define_own_property(self, prop, new_desc):
return False
- if new_len30*len(self.own):
+ if old_len > 30 * len(self.own):
for ele in self.own.keys():
- if ele.isdigit() and int(ele)>=new_len:
- if not self.delete(ele): # if failed to delete set len to current len and reject.
- new_desc['value'] = Js(old_len+1)
+ if ele.isdigit() and int(ele) >= new_len:
+ if not self.delete(
+ ele
+ ): # if failed to delete set len to current len and reject.
+ new_desc['value'] = Js(old_len + 1)
if not new_writable:
new_desc['writable'] = False
PyJs.define_own_property(self, prop, new_desc)
return False
old_len = new_len
- else: # standard method
- while new_len=old_len and not old_len_desc['writable']:
+ if index >= old_len and not old_len_desc['writable']:
return False
if not PyJs.define_own_property(self, prop, desc):
return False
- if index>=old_len:
+ if index >= old_len:
old_len_desc['value'] = Js(index + 1)
return True
else:
return PyJs.define_own_property(self, prop, desc)
def to_list(self):
- return [self.get(str(e)) for e in xrange(self.get('length').to_uint32())]
+ return [
+ self.get(str(e)) for e in xrange(self.get('length').to_uint32())
+ ]
def __repr__(self):
return repr(self.to_python().to_list())
+
class PyJsInt32Array(PyJs):
Class = 'Int32Array'
+
def __init__(self, arr=[], prototype=None):
self.extensible = True
self.prototype = prototype
- self.own = {'length' : {'value': Js(0), 'writable': True,
- 'enumerable': False, 'configurable': False}}
+ self.own = {
+ 'length': {
+ 'value': Js(0),
+ 'writable': True,
+ 'enumerable': False,
+ 'configurable': False
+ }
+ }
for i, e in enumerate(arr):
- self.define_own_property(str(i), {'value': Js(e), 'writable': True,
- 'enumerable': True, 'configurable': True})
+ self.define_own_property(
+ str(i), {
+ 'value': Js(e),
+ 'writable': True,
+ 'enumerable': True,
+ 'configurable': True
+ })
+
def define_own_property(self, prop, desc):
old_len_desc = self.get_own_property('length')
- old_len = old_len_desc['value'].value # value is js type so convert to py.
- if prop=='length':
+ old_len = old_len_desc[
+ 'value'].value # value is js type so convert to py.
+ if prop == 'length':
if 'value' not in desc:
return PyJs.define_own_property(self, prop, desc)
- new_len = desc['value'].to_uint32()
- if new_len!=desc['value'].to_number().value:
+ new_len = desc['value'].to_uint32()
+ if new_len != desc['value'].to_number().value:
raise MakeError('RangeError', 'Invalid range!')
- new_desc = dict((k,v) for k,v in six.iteritems(desc))
+ new_desc = dict((k, v) for k, v in six.iteritems(desc))
new_desc['value'] = Js(new_len)
- if new_len>=old_len:
+ if new_len >= old_len:
return PyJs.define_own_property(self, prop, new_desc)
if not old_len_desc['writable']:
return False
- if 'writable' not in new_desc or new_desc['writable']==True:
+ if 'writable' not in new_desc or new_desc['writable'] == True:
new_writable = True
else:
new_writable = False
new_desc['writable'] = True
if not PyJs.define_own_property(self, prop, new_desc):
return False
- if new_len30*len(self.own):
+ if old_len > 30 * len(self.own):
for ele in self.own.keys():
- if ele.isdigit() and int(ele)>=new_len:
- if not self.delete(ele): # if failed to delete set len to current len and reject.
- new_desc['value'] = Js(old_len+1)
+ if ele.isdigit() and int(ele) >= new_len:
+ if not self.delete(
+ ele
+ ): # if failed to delete set len to current len and reject.
+ new_desc['value'] = Js(old_len + 1)
if not new_writable:
new_desc['writable'] = False
PyJs.define_own_property(self, prop, new_desc)
return False
old_len = new_len
- else: # standard method
- while new_len=old_len and not old_len_desc['writable']:
+ if index >= old_len and not old_len_desc['writable']:
return False
if not PyJs.define_own_property(self, prop, desc):
return False
- if index>=old_len:
+ if index >= old_len:
old_len_desc['value'] = Js(index + 1)
return True
else:
return PyJs.define_own_property(self, prop, desc)
def to_list(self):
- return [self.get(str(e)) for e in xrange(self.get('length').to_uint32())]
+ return [
+ self.get(str(e)) for e in xrange(self.get('length').to_uint32())
+ ]
def __repr__(self):
return repr(self.to_python().to_list())
+
class PyJsUint32Array(PyJs):
Class = 'Uint32Array'
+
def __init__(self, arr=[], prototype=None):
self.extensible = True
self.prototype = prototype
- self.own = {'length' : {'value': Js(0), 'writable': True,
- 'enumerable': False, 'configurable': False}}
+ self.own = {
+ 'length': {
+ 'value': Js(0),
+ 'writable': True,
+ 'enumerable': False,
+ 'configurable': False
+ }
+ }
for i, e in enumerate(arr):
- self.define_own_property(str(i), {'value': Js(e), 'writable': True,
- 'enumerable': True, 'configurable': True})
+ self.define_own_property(
+ str(i), {
+ 'value': Js(e),
+ 'writable': True,
+ 'enumerable': True,
+ 'configurable': True
+ })
+
def define_own_property(self, prop, desc):
old_len_desc = self.get_own_property('length')
- old_len = old_len_desc['value'].value # value is js type so convert to py.
- if prop=='length':
+ old_len = old_len_desc[
+ 'value'].value # value is js type so convert to py.
+ if prop == 'length':
if 'value' not in desc:
return PyJs.define_own_property(self, prop, desc)
- new_len = desc['value'].to_uint32()
- if new_len!=desc['value'].to_number().value:
+ new_len = desc['value'].to_uint32()
+ if new_len != desc['value'].to_number().value:
raise MakeError('RangeError', 'Invalid range!')
- new_desc = dict((k,v) for k,v in six.iteritems(desc))
+ new_desc = dict((k, v) for k, v in six.iteritems(desc))
new_desc['value'] = Js(new_len)
- if new_len>=old_len:
+ if new_len >= old_len:
return PyJs.define_own_property(self, prop, new_desc)
if not old_len_desc['writable']:
return False
- if 'writable' not in new_desc or new_desc['writable']==True:
+ if 'writable' not in new_desc or new_desc['writable'] == True:
new_writable = True
else:
new_writable = False
new_desc['writable'] = True
if not PyJs.define_own_property(self, prop, new_desc):
return False
- if new_len30*len(self.own):
+ if old_len > 30 * len(self.own):
for ele in self.own.keys():
- if ele.isdigit() and int(ele)>=new_len:
- if not self.delete(ele): # if failed to delete set len to current len and reject.
- new_desc['value'] = Js(old_len+1)
+ if ele.isdigit() and int(ele) >= new_len:
+ if not self.delete(
+ ele
+ ): # if failed to delete set len to current len and reject.
+ new_desc['value'] = Js(old_len + 1)
if not new_writable:
new_desc['writable'] = False
PyJs.define_own_property(self, prop, new_desc)
return False
old_len = new_len
- else: # standard method
- while new_len=old_len and not old_len_desc['writable']:
+ if index >= old_len and not old_len_desc['writable']:
return False
if not PyJs.define_own_property(self, prop, desc):
return False
- if index>=old_len:
+ if index >= old_len:
old_len_desc['value'] = Js(index + 1)
return True
else:
return PyJs.define_own_property(self, prop, desc)
def to_list(self):
- return [self.get(str(e)) for e in xrange(self.get('length').to_uint32())]
+ return [
+ self.get(str(e)) for e in xrange(self.get('length').to_uint32())
+ ]
def __repr__(self):
return repr(self.to_python().to_list())
+
class PyJsFloat32Array(PyJs):
Class = 'Float32Array'
+
def __init__(self, arr=[], prototype=None):
self.extensible = True
self.prototype = prototype
- self.own = {'length' : {'value': Js(0), 'writable': True,
- 'enumerable': False, 'configurable': False}}
+ self.own = {
+ 'length': {
+ 'value': Js(0),
+ 'writable': True,
+ 'enumerable': False,
+ 'configurable': False
+ }
+ }
for i, e in enumerate(arr):
- self.define_own_property(str(i), {'value': Js(e), 'writable': True,
- 'enumerable': True, 'configurable': True})
+ self.define_own_property(
+ str(i), {
+ 'value': Js(e),
+ 'writable': True,
+ 'enumerable': True,
+ 'configurable': True
+ })
+
def define_own_property(self, prop, desc):
old_len_desc = self.get_own_property('length')
- old_len = old_len_desc['value'].value # value is js type so convert to py.
- if prop=='length':
+ old_len = old_len_desc[
+ 'value'].value # value is js type so convert to py.
+ if prop == 'length':
if 'value' not in desc:
return PyJs.define_own_property(self, prop, desc)
- new_len = desc['value'].to_uint32()
- if new_len!=desc['value'].to_number().value:
+ new_len = desc['value'].to_uint32()
+ if new_len != desc['value'].to_number().value:
raise MakeError('RangeError', 'Invalid range!')
- new_desc = dict((k,v) for k,v in six.iteritems(desc))
+ new_desc = dict((k, v) for k, v in six.iteritems(desc))
new_desc['value'] = Js(new_len)
- if new_len>=old_len:
+ if new_len >= old_len:
return PyJs.define_own_property(self, prop, new_desc)
if not old_len_desc['writable']:
return False
- if 'writable' not in new_desc or new_desc['writable']==True:
+ if 'writable' not in new_desc or new_desc['writable'] == True:
new_writable = True
else:
new_writable = False
new_desc['writable'] = True
if not PyJs.define_own_property(self, prop, new_desc):
return False
- if new_len30*len(self.own):
+ if old_len > 30 * len(self.own):
for ele in self.own.keys():
- if ele.isdigit() and int(ele)>=new_len:
- if not self.delete(ele): # if failed to delete set len to current len and reject.
- new_desc['value'] = Js(old_len+1)
+ if ele.isdigit() and int(ele) >= new_len:
+ if not self.delete(
+ ele
+ ): # if failed to delete set len to current len and reject.
+ new_desc['value'] = Js(old_len + 1)
if not new_writable:
new_desc['writable'] = False
PyJs.define_own_property(self, prop, new_desc)
return False
old_len = new_len
- else: # standard method
- while new_len=old_len and not old_len_desc['writable']:
+ if index >= old_len and not old_len_desc['writable']:
return False
if not PyJs.define_own_property(self, prop, desc):
return False
- if index>=old_len:
+ if index >= old_len:
old_len_desc['value'] = Js(index + 1)
return True
else:
return PyJs.define_own_property(self, prop, desc)
def to_list(self):
- return [self.get(str(e)) for e in xrange(self.get('length').to_uint32())]
+ return [
+ self.get(str(e)) for e in xrange(self.get('length').to_uint32())
+ ]
def __repr__(self):
return repr(self.to_python().to_list())
+
class PyJsFloat64Array(PyJs):
Class = 'Float64Array'
+
def __init__(self, arr=[], prototype=None):
self.extensible = True
self.prototype = prototype
- self.own = {'length' : {'value': Js(0), 'writable': True,
- 'enumerable': False, 'configurable': False}}
+ self.own = {
+ 'length': {
+ 'value': Js(0),
+ 'writable': True,
+ 'enumerable': False,
+ 'configurable': False
+ }
+ }
for i, e in enumerate(arr):
- self.define_own_property(str(i), {'value': Js(e), 'writable': True,
- 'enumerable': True, 'configurable': True})
+ self.define_own_property(
+ str(i), {
+ 'value': Js(e),
+ 'writable': True,
+ 'enumerable': True,
+ 'configurable': True
+ })
+
def define_own_property(self, prop, desc):
old_len_desc = self.get_own_property('length')
- old_len = old_len_desc['value'].value # value is js type so convert to py.
- if prop=='length':
+ old_len = old_len_desc[
+ 'value'].value # value is js type so convert to py.
+ if prop == 'length':
if 'value' not in desc:
return PyJs.define_own_property(self, prop, desc)
- new_len = desc['value'].to_uint32()
- if new_len!=desc['value'].to_number().value:
+ new_len = desc['value'].to_uint32()
+ if new_len != desc['value'].to_number().value:
raise MakeError('RangeError', 'Invalid range!')
- new_desc = dict((k,v) for k,v in six.iteritems(desc))
+ new_desc = dict((k, v) for k, v in six.iteritems(desc))
new_desc['value'] = Js(new_len)
- if new_len>=old_len:
+ if new_len >= old_len:
return PyJs.define_own_property(self, prop, new_desc)
if not old_len_desc['writable']:
return False
- if 'writable' not in new_desc or new_desc['writable']==True:
+ if 'writable' not in new_desc or new_desc['writable'] == True:
new_writable = True
else:
new_writable = False
new_desc['writable'] = True
if not PyJs.define_own_property(self, prop, new_desc):
return False
- if new_len30*len(self.own):
+ if old_len > 30 * len(self.own):
for ele in self.own.keys():
- if ele.isdigit() and int(ele)>=new_len:
- if not self.delete(ele): # if failed to delete set len to current len and reject.
- new_desc['value'] = Js(old_len+1)
+ if ele.isdigit() and int(ele) >= new_len:
+ if not self.delete(
+ ele
+ ): # if failed to delete set len to current len and reject.
+ new_desc['value'] = Js(old_len + 1)
if not new_writable:
new_desc['writable'] = False
PyJs.define_own_property(self, prop, new_desc)
return False
old_len = new_len
- else: # standard method
- while new_len=old_len and not old_len_desc['writable']:
+ if index >= old_len and not old_len_desc['writable']:
return False
if not PyJs.define_own_property(self, prop, desc):
return False
- if index>=old_len:
+ if index >= old_len:
old_len_desc['value'] = Js(index + 1)
return True
else:
return PyJs.define_own_property(self, prop, desc)
def to_list(self):
- return [self.get(str(e)) for e in xrange(self.get('length').to_uint32())]
+ return [
+ self.get(str(e)) for e in xrange(self.get('length').to_uint32())
+ ]
def __repr__(self):
return repr(self.to_python().to_list())
+
ArrayPrototype = PyJsArray([], ObjectPrototype)
ArrayBufferPrototype = PyJsArrayBuffer([], ObjectPrototype)
@@ -2371,32 +2766,46 @@ def __repr__(self):
Float64ArrayPrototype = PyJsFloat64Array([], ObjectPrototype)
+
class PyJsArguments(PyJs):
Class = 'Arguments'
+
def __init__(self, args, callee):
self.own = {}
self.extensible = True
self.prototype = ObjectPrototype
- self.define_own_property('length', {'value': Js(len(args)), 'writable': True,
- 'enumerable': False, 'configurable': True})
- self.define_own_property('callee', {'value': callee, 'writable': True,
- 'enumerable': False, 'configurable': True})
+ self.define_own_property(
+ 'length', {
+ 'value': Js(len(args)),
+ 'writable': True,
+ 'enumerable': False,
+ 'configurable': True
+ })
+ self.define_own_property(
+ 'callee', {
+ 'value': callee,
+ 'writable': True,
+ 'enumerable': False,
+ 'configurable': True
+ })
for i, e in enumerate(args):
self.put(str(i), Js(e))
def to_list(self):
- return [self.get(str(e)) for e in xrange(self.get('length').to_uint32())]
+ return [
+ self.get(str(e)) for e in xrange(self.get('length').to_uint32())
+ ]
#We can define function proto after number proto because func uses number in its init
FunctionPrototype = PyJsFunction(Empty, ObjectPrototype)
FunctionPrototype.own['name']['value'] = Js('')
-
# I will not rewrite RegExp engine from scratch. I will use re because its much faster.
# I have to only make sure that I am handling all the differences correctly.
REGEXP_DB = {}
+
class PyJsRegExp(PyJs):
Class = 'RegExp'
extensible = True
@@ -2412,10 +2821,10 @@ def __init__(self, regexp, prototype=None):
# 'lastpos': -1,
# 'matches': {}}
flags = ''
- if not regexp[-1]=='/':
+ if not regexp[-1] == '/':
#contains some flags (allowed are i, g, m
- spl = regexp.rfind('/')
- flags = set(regexp[spl+1:])
+ spl = regexp.rfind('/')
+ flags = set(regexp[spl + 1:])
self.value = regexp[1:spl]
if 'g' in flags:
self.glob = True
@@ -2430,39 +2839,67 @@ def __init__(self, regexp, prototype=None):
if self.value in REGEXP_DB:
self.pat = REGEXP_DB[regexp]
else:
- comp = 'None'
+ comp = 'None'
# we have to check whether pattern is valid.
# also this will speed up matching later
# todo critical fix patter conversion etc. ..!!!!!
# ugly hacks porting js reg exp to py reg exp works in 99% of cases ;)
- possible_fixes = [
- (u'[]', u'[\0]'),
- (u'[^]', u'[^\0]'),
- (u'nofix1791', u'nofix1791')
- ]
+ possible_fixes = [(u'[]', u'[\0]'), (u'[^]', u'[^\0]'),
+ (u'nofix1791', u'nofix1791')]
reg = self.value
for fix, rep in possible_fixes:
comp = REGEXP_CONVERTER._interpret_regexp(reg, flags)
#print 'reg -> comp', reg, '->', comp
try:
- self.pat = re.compile(comp, self.ignore_case | self.multiline)
+ self.pat = re.compile(
+ comp, self.ignore_case | self.multiline)
#print reg, '->', comp
break
except:
reg = reg.replace(fix, rep)
- # print 'Fix', fix, '->', rep, '=', reg
+ # print 'Fix', fix, '->', rep, '=', reg
else:
raise
REGEXP_DB[regexp] = self.pat
except:
#print 'Invalid pattern but fuck it', self.value, comp
- raise MakeError('SyntaxError', 'Invalid RegExp pattern: %s -> %s'% (repr(self.value), repr(comp)))
+ raise MakeError(
+ 'SyntaxError',
+ 'Invalid RegExp pattern: %s -> %s' % (repr(self.value),
+ repr(comp)))
# now set own properties:
- self.own = {'source' : {'value': Js(self.value), 'enumerable': False, 'writable': False, 'configurable': False},
- 'global' : {'value': Js(self.glob), 'enumerable': False, 'writable': False, 'configurable': False},
- 'ignoreCase' : {'value': Js(bool(self.ignore_case)), 'enumerable': False, 'writable': False, 'configurable': False},
- 'multiline' : {'value': Js(bool(self.multiline)), 'enumerable': False, 'writable': False, 'configurable': False},
- 'lastIndex' : {'value': Js(0), 'enumerable': False, 'writable': True, 'configurable': False}}
+ self.own = {
+ 'source': {
+ 'value': Js(self.value),
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ },
+ 'global': {
+ 'value': Js(self.glob),
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ },
+ 'ignoreCase': {
+ 'value': Js(bool(self.ignore_case)),
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ },
+ 'multiline': {
+ 'value': Js(bool(self.multiline)),
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ },
+ 'lastIndex': {
+ 'value': Js(0),
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': False
+ }
+ }
def match(self, string, pos):
'''string is of course py string'''
@@ -2493,15 +2930,15 @@ def match(self, string, pos):
# return self.match(string, pos)
-
def JsRegExp(source):
# Takes regexp literal!
return PyJsRegExp(source, RegExpPrototype)
+
RegExpPrototype = PyJsRegExp('/(?:)/', ObjectPrototype)
####Exceptions:
-default_attrs = {'writable':True, 'enumerable':False, 'configurable':True}
+default_attrs = {'writable': True, 'enumerable': False, 'configurable': True}
def fill_in_props(obj, props, default_desc):
@@ -2510,10 +2947,10 @@ def fill_in_props(obj, props, default_desc):
obj.define_own_property(prop, default_desc)
-
class PyJsError(PyJs):
Class = 'Error'
extensible = True
+
def __init__(self, message=None, prototype=None):
self.prototype = prototype
self.own = {}
@@ -2521,43 +2958,58 @@ def __init__(self, message=None, prototype=None):
self.put('message', Js(message).to_string())
self.own['message']['enumerable'] = False
+
ErrorPrototype = PyJsError(Js(''), ObjectPrototype)
+
+
@Js
def Error(message):
- return PyJsError(None if message.is_undefined() else message, ErrorPrototype)
+ return PyJsError(None if message.is_undefined() else message,
+ ErrorPrototype)
+
+
Error.create = Error
-err = {'name': 'Error',
- 'constructor': Error}
+err = {'name': 'Error', 'constructor': Error}
fill_in_props(ErrorPrototype, err, default_attrs)
-Error.define_own_property('prototype', {'value': ErrorPrototype,
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+Error.define_own_property(
+ 'prototype', {
+ 'value': ErrorPrototype,
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ })
+
def define_error_type(name):
TypeErrorPrototype = PyJsError(None, ErrorPrototype)
+
@Js
def TypeError(message):
- return PyJsError(None if message.is_undefined() else message, TypeErrorPrototype)
- err = {'name': name,
- 'constructor': TypeError}
+ return PyJsError(None if message.is_undefined() else message,
+ TypeErrorPrototype)
+
+ err = {'name': name, 'constructor': TypeError}
fill_in_props(TypeErrorPrototype, err, default_attrs)
- TypeError.define_own_property('prototype', {'value': TypeErrorPrototype,
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+ TypeError.define_own_property(
+ 'prototype', {
+ 'value': TypeErrorPrototype,
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ })
ERRORS[name] = TypeError
+
ERRORS = {'Error': Error}
ERROR_NAMES = ['Eval', 'Type', 'Range', 'Reference', 'Syntax', 'URI']
for e in ERROR_NAMES:
- define_error_type(e+'Error')
-
+ define_error_type(e + 'Error')
##############################################################################
# Import and fill prototypes here.
+
#this works only for data properties
def fill_prototype(prototype, Class, attrs, constructor=False):
for i in dir(Class):
@@ -2565,13 +3017,13 @@ def fill_prototype(prototype, Class, attrs, constructor=False):
if six.PY2:
if hasattr(e, '__func__'):
temp = PyJsFunction(e.__func__, FunctionPrototype)
- attrs = dict((k,v) for k,v in attrs.iteritems())
+ attrs = dict((k, v) for k, v in attrs.iteritems())
attrs['value'] = temp
prototype.define_own_property(i, attrs)
else:
if hasattr(e, '__call__') and not i.startswith('__'):
temp = PyJsFunction(e, FunctionPrototype)
- attrs = dict((k,v) for k,v in attrs.items())
+ attrs = dict((k, v) for k, v in attrs.items())
attrs['value'] = temp
prototype.define_own_property(i, attrs)
if constructor:
@@ -2579,30 +3031,37 @@ def fill_prototype(prototype, Class, attrs, constructor=False):
prototype.define_own_property('constructor', attrs)
-
-
PyJs.undefined = undefined
PyJs.Js = staticmethod(Js)
from .prototypes import jsfunction, jsobject, jsnumber, jsstring, jsboolean, jsarray, jsregexp, jserror, jsarraybuffer, jstypedarray
-
#Object proto
fill_prototype(ObjectPrototype, jsobject.ObjectPrototype, default_attrs)
+
+
#Define __proto__ accessor (this cant be done by fill_prototype since)
@Js
def __proto__():
return this.prototype if this.prototype is not None else null
+
+
getter = __proto__
+
+
@Js
def __proto__(val):
if val.is_object():
this.prototype = val
-setter = __proto__
-ObjectPrototype.define_own_property('__proto__', {'set': setter,
- 'get': getter,
- 'enumerable': False,
- 'configurable':True})
+
+
+setter = __proto__
+ObjectPrototype.define_own_property('__proto__', {
+ 'set': setter,
+ 'get': getter,
+ 'enumerable': False,
+ 'configurable': True
+})
#Function proto
fill_prototype(FunctionPrototype, jsfunction.FunctionPrototype, default_attrs)
@@ -2615,25 +3074,35 @@ def __proto__(val):
#Array proto
fill_prototype(ArrayPrototype, jsarray.ArrayPrototype, default_attrs)
# ArrayBuffer proto
-fill_prototype(ArrayBufferPrototype, jsarraybuffer.ArrayBufferPrototype, default_attrs)
+fill_prototype(ArrayBufferPrototype, jsarraybuffer.ArrayBufferPrototype,
+ default_attrs)
# Int8Array proto
-fill_prototype(Int8ArrayPrototype, jstypedarray.TypedArrayPrototype, default_attrs)
+fill_prototype(Int8ArrayPrototype, jstypedarray.TypedArrayPrototype,
+ default_attrs)
# Uint8Array proto
-fill_prototype(Uint8ArrayPrototype, jstypedarray.TypedArrayPrototype, default_attrs)
+fill_prototype(Uint8ArrayPrototype, jstypedarray.TypedArrayPrototype,
+ default_attrs)
# Uint8ClampedArray proto
-fill_prototype(Uint8ClampedArrayPrototype, jstypedarray.TypedArrayPrototype, default_attrs)
+fill_prototype(Uint8ClampedArrayPrototype, jstypedarray.TypedArrayPrototype,
+ default_attrs)
# Int16Array proto
-fill_prototype(Int16ArrayPrototype, jstypedarray.TypedArrayPrototype, default_attrs)
+fill_prototype(Int16ArrayPrototype, jstypedarray.TypedArrayPrototype,
+ default_attrs)
# Uint16Array proto
-fill_prototype(Uint16ArrayPrototype, jstypedarray.TypedArrayPrototype, default_attrs)
+fill_prototype(Uint16ArrayPrototype, jstypedarray.TypedArrayPrototype,
+ default_attrs)
# Int32Array proto
-fill_prototype(Int32ArrayPrototype, jstypedarray.TypedArrayPrototype, default_attrs)
+fill_prototype(Int32ArrayPrototype, jstypedarray.TypedArrayPrototype,
+ default_attrs)
# Uint32Array proto
-fill_prototype(Uint32ArrayPrototype, jstypedarray.TypedArrayPrototype, default_attrs)
+fill_prototype(Uint32ArrayPrototype, jstypedarray.TypedArrayPrototype,
+ default_attrs)
# Float32Array proto
-fill_prototype(Float32ArrayPrototype, jstypedarray.TypedArrayPrototype, default_attrs)
+fill_prototype(Float32ArrayPrototype, jstypedarray.TypedArrayPrototype,
+ default_attrs)
# Float64Array proto
-fill_prototype(Float64ArrayPrototype, jstypedarray.TypedArrayPrototype, default_attrs)
+fill_prototype(Float64ArrayPrototype, jstypedarray.TypedArrayPrototype,
+ default_attrs)
#Error proto
fill_prototype(ErrorPrototype, jserror.ErrorPrototype, default_attrs)
#RegExp proto
@@ -2645,6 +3114,7 @@ def __proto__(val):
#########################################################################
# Constructors
+
# String
@Js
def String(st):
@@ -2652,6 +3122,7 @@ def String(st):
return Js('')
return arguments[0].to_string()
+
@Js
def string_constructor():
temp = PyJsObject(prototype=StringPrototype)
@@ -2661,22 +3132,36 @@ def string_constructor():
temp.value = ''
else:
temp.value = arguments[0].to_string().value
- for i, ch in enumerate(temp.value): # this will make things long...
- temp.own[str(i)] = {'value': Js(ch), 'writable': False,
- 'enumerable': True, 'configurable': True}
- temp.own['length'] = {'value': Js(len(temp.value)), 'writable': False,
- 'enumerable': False, 'configurable': False}
+ for i, ch in enumerate(temp.value): # this will make things long...
+ temp.own[str(i)] = {
+ 'value': Js(ch),
+ 'writable': False,
+ 'enumerable': True,
+ 'configurable': True
+ }
+ temp.own['length'] = {
+ 'value': Js(len(temp.value)),
+ 'writable': False,
+ 'enumerable': False,
+ 'configurable': False
+ }
return temp
+
String.create = string_constructor
# RegExp
REG_EXP_FLAGS = ('g', 'i', 'm')
+
+
@Js
def RegExp(pattern, flags):
- if pattern.Class=='RegExp':
+ if pattern.Class == 'RegExp':
if not flags.is_undefined():
- raise MakeError('TypeError', 'Cannot supply flags when constructing one RegExp from another')
+ raise MakeError(
+ 'TypeError',
+ 'Cannot supply flags when constructing one RegExp from another'
+ )
# return unchanged
return pattern
#pattern is not a regexp
@@ -2691,17 +3176,23 @@ def RegExp(pattern, flags):
flags = flags.to_string().value if not flags.is_undefined() else ''
for flag in flags:
if flag not in REG_EXP_FLAGS:
- raise MakeError('SyntaxError', 'Invalid flags supplied to RegExp constructor "%s"' % flag)
- if len(set(flags))!=len(flags):
- raise MakeError('SyntaxError', 'Invalid flags supplied to RegExp constructor "%s"' % flags)
- pattern = '/%s/'%(pattern if pattern else '(?:)') + flags
+ raise MakeError(
+ 'SyntaxError',
+ 'Invalid flags supplied to RegExp constructor "%s"' % flag)
+ if len(set(flags)) != len(flags):
+ raise MakeError(
+ 'SyntaxError',
+ 'Invalid flags supplied to RegExp constructor "%s"' % flags)
+ pattern = '/%s/' % (pattern if pattern else '(?:)') + flags
return JsRegExp(pattern)
+
RegExp.create = RegExp
PyJs.RegExp = RegExp
# Number
+
@Js
def Number():
if len(arguments):
@@ -2709,6 +3200,7 @@ def Number():
else:
return Js(0)
+
@Js
def number_constructor():
temp = PyJsObject(prototype=NumberPrototype)
@@ -2720,13 +3212,17 @@ def number_constructor():
temp.value = 0
return temp
+
Number.create = number_constructor
# Boolean
+
@Js
def Boolean(value):
return value.to_boolean()
+
+
@Js
def boolean_constructor(value):
temp = PyJsObject(prototype=BooleanPrototype)
@@ -2735,11 +3231,12 @@ def boolean_constructor(value):
temp.value = value.to_boolean().value
return temp
-Boolean.create = boolean_constructor
+Boolean.create = boolean_constructor
##############################################################################
+
def appengine(code):
try:
return translator.translate_js(code.decode('utf-8'))
@@ -2747,23 +3244,20 @@ def appengine(code):
return traceback.format_exc()
-
-builtins = ('true','false','null','undefined','Infinity',
- 'NaN')
+builtins = ('true', 'false', 'null', 'undefined', 'Infinity', 'NaN')
scope = dict(zip(builtins, [eval(e) for e in builtins]))
-JS_BUILTINS = dict((k,v) for k,v in scope.items())
-
+JS_BUILTINS = dict((k, v) for k, v in scope.items())
# Fill in NUM_BANK
-for e in xrange(-2**10,2**14):
+for e in xrange(-2**10, 2**14):
NUM_BANK[e] = Js(e)
-if __name__=='__main__':
+if __name__ == '__main__':
print(ObjectPrototype.get('toString').callprop('call'))
print(FunctionPrototype.own)
- a= null-Js(49404)
+ a = null - Js(49404)
x = a.put('ser', Js('der'))
print(Js(0) or Js('p') and Js(4.0000000000050000001))
FunctionPrototype.put('Chuj', Js(409))
@@ -2774,10 +3268,9 @@ def appengine(code):
b = Js(6)
s2 = Js(4)
- o = ObjectPrototype
+ o = ObjectPrototype
o.put('x', Js(100))
var = Scope(scope)
e = code.InteractiveConsole(globals())
#e.raw_input = interactor
e.interact()
-
diff --git a/js2py/constructors/jsarray.py b/js2py/constructors/jsarray.py
index a6af010d..1550589d 100644
--- a/js2py/constructors/jsarray.py
+++ b/js2py/constructors/jsarray.py
@@ -1,38 +1,48 @@
from ..base import *
+
@Js
def Array():
- if len(arguments)==0 or len(arguments)>1:
+ if len(arguments) == 0 or len(arguments) > 1:
return arguments.to_list()
a = arguments[0]
if isinstance(a, PyJsNumber):
length = a.to_uint32()
- if length!=a.value:
+ if length != a.value:
raise MakeError('RangeError', 'Invalid array length')
temp = Js([])
temp.put('length', a)
return temp
return [a]
+
Array.create = Array
Array.own['length']['value'] = Js(1)
+
@Js
def isArray(arg):
- return arg.Class=='Array'
+ return arg.Class == 'Array'
-Array.define_own_property('isArray', {'value': isArray,
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
+Array.define_own_property('isArray', {
+ 'value': isArray,
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+})
-Array.define_own_property('prototype', {'value': ArrayPrototype,
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+Array.define_own_property(
+ 'prototype', {
+ 'value': ArrayPrototype,
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ })
-ArrayPrototype.define_own_property('constructor', {'value': Array,
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
\ No newline at end of file
+ArrayPrototype.define_own_property('constructor', {
+ 'value': Array,
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+})
diff --git a/js2py/constructors/jsarraybuffer.py b/js2py/constructors/jsarraybuffer.py
index 51468c06..6da71aab 100644
--- a/js2py/constructors/jsarraybuffer.py
+++ b/js2py/constructors/jsarraybuffer.py
@@ -14,21 +14,28 @@ def ArrayBuffer():
a = arguments[0]
if isinstance(a, PyJsNumber):
length = a.to_uint32()
- if length!=a.value:
+ if length != a.value:
raise MakeError('RangeError', 'Invalid array length')
- temp = Js(bytearray([0]*length))
+ temp = Js(bytearray([0] * length))
return temp
return Js(bytearray([0]))
+
ArrayBuffer.create = ArrayBuffer
ArrayBuffer.own['length']['value'] = Js(None)
-ArrayBuffer.define_own_property('prototype', {'value': ArrayBufferPrototype,
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+ArrayBuffer.define_own_property(
+ 'prototype', {
+ 'value': ArrayBufferPrototype,
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ })
-ArrayBufferPrototype.define_own_property('constructor', {'value': ArrayBuffer,
- 'enumerable': False,
- 'writable': False,
- 'configurable': True})
+ArrayBufferPrototype.define_own_property(
+ 'constructor', {
+ 'value': ArrayBuffer,
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': True
+ })
diff --git a/js2py/constructors/jsboolean.py b/js2py/constructors/jsboolean.py
index 124e8fc6..743b110d 100644
--- a/js2py/constructors/jsboolean.py
+++ b/js2py/constructors/jsboolean.py
@@ -1,11 +1,16 @@
from ..base import *
-BooleanPrototype.define_own_property('constructor', {'value': Boolean,
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
+BooleanPrototype.define_own_property('constructor', {
+ 'value': Boolean,
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+})
-Boolean.define_own_property('prototype', {'value': BooleanPrototype,
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
\ No newline at end of file
+Boolean.define_own_property(
+ 'prototype', {
+ 'value': BooleanPrototype,
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ })
diff --git a/js2py/constructors/jsdate.py b/js2py/constructors/jsdate.py
index 67055e2c..b6b70a81 100644
--- a/js2py/constructors/jsdate.py
+++ b/js2py/constructors/jsdate.py
@@ -1,60 +1,73 @@
from ..base import *
from .time_helpers import *
-TZ_OFFSET = (time.altzone//3600)
+TZ_OFFSET = (time.altzone // 3600)
ABS_OFFSET = abs(TZ_OFFSET)
TZ_NAME = time.tzname[1]
ISO_FORMAT = '%s-%s-%sT%s:%s:%s.%sZ'
+
+
@Js
def Date(year, month, date, hours, minutes, seconds, ms):
return now().to_string()
+
Date.Class = 'Date'
+
def now():
- return PyJsDate(int(time.time()*1000), prototype=DatePrototype)
+ return PyJsDate(int(time.time() * 1000), prototype=DatePrototype)
@Js
-def UTC(year, month, date, hours, minutes, seconds, ms): # todo complete this
+def UTC(year, month, date, hours, minutes, seconds, ms): # todo complete this
args = arguments
y = args[0].to_number()
m = args[1].to_number()
l = len(args)
- dt = args[2].to_number() if l>2 else Js(1)
- h = args[3].to_number() if l>3 else Js(0)
- mi = args[4].to_number() if l>4 else Js(0)
- sec = args[5].to_number() if l>5 else Js(0)
- mili = args[6].to_number() if l>6 else Js(0)
- if not y.is_nan() and 0<=y.value<=99:
+ dt = args[2].to_number() if l > 2 else Js(1)
+ h = args[3].to_number() if l > 3 else Js(0)
+ mi = args[4].to_number() if l > 4 else Js(0)
+ sec = args[5].to_number() if l > 5 else Js(0)
+ mili = args[6].to_number() if l > 6 else Js(0)
+ if not y.is_nan() and 0 <= y.value <= 99:
y = y + Js(1900)
- t = TimeClip(MakeDate(MakeDay(y, m, dt), MakeTime(h, mi, sec, mili)))
- return PyJsDate(t, prototype=DatePrototype)
+ return TimeClip(MakeDate(MakeDay(y, m, dt), MakeTime(h, mi, sec, mili)))
+
@Js
def parse(string):
- return PyJsDate(TimeClip(parse_date(string.to_string().value)), prototype=DatePrototype)
+ return PyJsDate(
+ TimeClip(parse_date(string.to_string().value)),
+ prototype=DatePrototype)
+Date.define_own_property('now', {
+ 'value': Js(now),
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+})
-Date.define_own_property('now', {'value': Js(now),
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
+Date.define_own_property('parse', {
+ 'value': parse,
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+})
-Date.define_own_property('parse', {'value': parse,
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
+Date.define_own_property('UTC', {
+ 'value': UTC,
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+})
-Date.define_own_property('UTC', {'value': UTC,
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
class PyJsDate(PyJs):
Class = 'Date'
extensible = True
+
def __init__(self, value, prototype=None):
self.value = value
self.own = {}
@@ -62,10 +75,12 @@ def __init__(self, value, prototype=None):
# todo fix this problematic datetime part
def to_local_dt(self):
- return datetime.datetime.utcfromtimestamp(UTCToLocal(self.value)//1000)
+ return datetime.datetime(1970, 1, 1) + datetime.timedelta(
+ seconds=UTCToLocal(self.value) // 1000)
def to_utc_dt(self):
- return datetime.datetime.utcfromtimestamp(self.value//1000)
+ return datetime.datetime(1970, 1, 1) + datetime.timedelta(
+ seconds=self.value // 1000)
def local_strftime(self, pattern):
if self.value is NaN:
@@ -73,11 +88,16 @@ def local_strftime(self, pattern):
try:
dt = self.to_local_dt()
except:
- raise MakeError('TypeError', 'unsupported date range. Will fix in future versions')
+ raise MakeError(
+ 'TypeError',
+ 'unsupported date range. Will fix in future versions')
try:
return dt.strftime(pattern)
except:
- raise MakeError('TypeError', 'Could not generate date string from this date (limitations of python.datetime)')
+ raise MakeError(
+ 'TypeError',
+ 'Could not generate date string from this date (limitations of python.datetime)'
+ )
def utc_strftime(self, pattern):
if self.value is NaN:
@@ -85,28 +105,59 @@ def utc_strftime(self, pattern):
try:
dt = self.to_utc_dt()
except:
- raise MakeError('TypeError', 'unsupported date range. Will fix in future versions')
+ raise MakeError(
+ 'TypeError',
+ 'unsupported date range. Will fix in future versions')
try:
return dt.strftime(pattern)
except:
- raise MakeError('TypeError', 'Could not generate date string from this date (limitations of python.datetime)')
-
-
-
-
-def parse_date(py_string): # todo support all date string formats
- try:
- dt = datetime.datetime.strptime(py_string, "%Y-%m-%dT%H:%M:%S.%fZ")
- return MakeDate(MakeDay(Js(dt.year), Js(dt.month-1), Js(dt.day)), MakeTime(Js(dt.hour), Js(dt.minute), Js(dt.second), Js(dt.microsecond//1000)))
- except:
- raise MakeError('TypeError', 'Could not parse date %s - unsupported date format. Currently only supported format is RFC3339 utc. Sorry!' % py_string)
-
+ raise MakeError(
+ 'TypeError',
+ 'Could not generate date string from this date (limitations of python.datetime)'
+ )
+
+
+def parse_date(py_string): # todo support all date string formats
+ date_formats = (
+ "%Y-%m-%d",
+ "%m/%d/%Y",
+ "%b %d %Y",
+ )
+ # Supports these hour formats and with or hour.
+ hour_formats = (
+ "T%H:%M:%S.%f",
+ "T%H:%M:%S",
+ ) + ('',)
+ # Supports with or without Z indicator.
+ z_formats = ("Z",) + ('',)
+ supported_formats = [
+ d + t + z
+ for d in date_formats
+ for t in hour_formats
+ for z in z_formats
+ ]
+ for date_format in supported_formats:
+ try:
+ dt = datetime.datetime.strptime(py_string, date_format)
+ except ValueError:
+ continue
+ else:
+ return MakeDate(
+ MakeDay(Js(dt.year), Js(dt.month - 1), Js(dt.day)),
+ MakeTime(
+ Js(dt.hour), Js(dt.minute), Js(dt.second),
+ Js(dt.microsecond // 1000)))
+
+ raise MakeError(
+ 'TypeError',
+ 'Could not parse date %s - unsupported date format. Currently only supported formats are RFC3339 utc, ISO Date, Short Date, and Long Date. Sorry!'
+ % py_string)
def date_constructor(*args):
- if len(args)>=2:
+ if len(args) >= 2:
return date_constructor2(*args)
- elif len(args)==1:
+ elif len(args) == 1:
return date_constructor1(args[0])
else:
return date_constructor0()
@@ -118,7 +169,7 @@ def date_constructor0():
def date_constructor1(value):
v = value.to_primitive()
- if v._type()=='String':
+ if v._type() == 'String':
v = parse_date(v.value)
else:
v = v.to_int()
@@ -129,22 +180,25 @@ def date_constructor2(*args):
y = args[0].to_number()
m = args[1].to_number()
l = len(args)
- dt = args[2].to_number() if l>2 else Js(1)
- h = args[3].to_number() if l>3 else Js(0)
- mi = args[4].to_number() if l>4 else Js(0)
- sec = args[5].to_number() if l>5 else Js(0)
- mili = args[6].to_number() if l>6 else Js(0)
- if not y.is_nan() and 0<=y.value<=99:
+ dt = args[2].to_number() if l > 2 else Js(1)
+ h = args[3].to_number() if l > 3 else Js(0)
+ mi = args[4].to_number() if l > 4 else Js(0)
+ sec = args[5].to_number() if l > 5 else Js(0)
+ mili = args[6].to_number() if l > 6 else Js(0)
+ if not y.is_nan() and 0 <= y.value <= 99:
y = y + Js(1900)
- t = TimeClip(LocalToUTC(MakeDate(MakeDay(y, m, dt), MakeTime(h, mi, sec, mili))))
+ t = TimeClip(
+ LocalToUTC(MakeDate(MakeDay(y, m, dt), MakeTime(h, mi, sec, mili))))
return PyJsDate(t, prototype=DatePrototype)
+
Date.create = date_constructor
DatePrototype = PyJsDate(float('nan'), prototype=ObjectPrototype)
+
def check_date(obj):
- if obj.Class!='Date':
+ if obj.Class != 'Date':
raise MakeError('TypeError', 'this is not a Date object')
@@ -153,8 +207,10 @@ def toString():
check_date(this)
if this.value is NaN:
return 'Invalid Date'
- offset = (UTCToLocal(this.value) - this.value)//msPerHour
- return this.local_strftime('%a %b %d %Y %H:%M:%S GMT') + '%s00 (%s)' % (pad(offset, 2, True), GetTimeZoneName(this.value))
+ offset = (UTCToLocal(this.value) - this.value) // msPerHour
+ return this.local_strftime(
+ '%a %b %d %Y %H:%M:%S GMT') + '%s00 (%s)' % (pad(
+ offset, 2, True), GetTimeZoneName(this.value))
def toDateString():
check_date(this)
@@ -284,8 +340,7 @@ def getTimezoneOffset():
check_date(this)
if this.value is NaN:
return NaN
- return (this.value - UTCToLocal(this.value))//60000
-
+ return (this.value - UTCToLocal(this.value)) // 60000
def setTime(time):
check_date(this)
@@ -295,7 +350,8 @@ def setTime(time):
def setMilliseconds(ms):
check_date(this)
t = UTCToLocal(this.value)
- tim = MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms.to_int())
+ tim = MakeTime(
+ Js(HourFromTime(t)), Js(MinFromTime(t)), Js(SecFromTime(t)), ms)
u = TimeClip(LocalToUTC(MakeDate(Day(t), tim)))
this.value = u
return u
@@ -303,12 +359,165 @@ def setMilliseconds(ms):
def setUTCMilliseconds(ms):
check_date(this)
t = this.value
- tim = MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms.to_int())
+ tim = MakeTime(
+ Js(HourFromTime(t)), Js(MinFromTime(t)), Js(SecFromTime(t)), ms)
u = TimeClip(MakeDate(Day(t), tim))
this.value = u
return u
- # todo Complete all setters!
+ def setSeconds(sec, ms=None):
+ check_date(this)
+ t = UTCToLocal(this.value)
+ s = sec.to_number()
+ if not ms is None: milli = Js(msFromTime(t))
+ else: milli = ms.to_number()
+ date = MakeDate(
+ Day(t), MakeTime(Js(HourFromTime(t)), Js(MinFromTime(t)), s, milli))
+ u = TimeClip(LocalToUTC(date))
+ this.value = u
+ return u
+
+ def setUTCSeconds(sec, ms=None):
+ check_date(this)
+ t = this.value
+ s = sec.to_number()
+ if not ms is None: milli = Js(msFromTime(t))
+ else: milli = ms.to_number()
+ date = MakeDate(
+ Day(t), MakeTime(Js(HourFromTime(t)), Js(MinFromTime(t)), s, milli))
+ v = TimeClip(date)
+ this.value = v
+ return v
+
+ def setMinutes(min, sec=None, ms=None):
+ check_date(this)
+ t = UTCToLocal(this.value)
+ m = min.to_number()
+ if not sec is None: s = Js(SecFromTime(t))
+ else: s = sec.to_number()
+ if not ms is None: milli = Js(msFromTime(t))
+ else: milli = ms.to_number()
+ date = MakeDate(Day(t), MakeTime(Js(HourFromTime(t)), m, s, milli))
+ u = TimeClip(LocalToUTC(date))
+ this.value = u
+ return u
+
+ def setUTCMinutes(min, sec=None, ms=None):
+ check_date(this)
+ t = this.value
+ m = min.to_number()
+ if not sec is None: s = Js(SecFromTime(t))
+ else: s = sec.to_number()
+ if not ms is None: milli = Js(msFromTime(t))
+ else: milli = ms.to_number()
+ date = MakeDate(Day(t), MakeTime(Js(HourFromTime(t)), m, s, milli))
+ v = TimeClip(date)
+ this.value = v
+ return v
+
+ def setHours(hour, min=None, sec=None, ms=None):
+ check_date(this)
+ t = UTCToLocal(this.value)
+ h = hour.to_number()
+ if not min is None: m = Js(MinFromTime(t))
+ else: m = min.to_number()
+ if not sec is None: s = Js(SecFromTime(t))
+ else: s = sec.to_number()
+ if not ms is None: milli = Js(msFromTime(t))
+ else: milli = ms.to_number()
+ date = MakeDate(Day(t), MakeTime(h, m, s, milli))
+ u = TimeClip(LocalToUTC(date))
+ this.value = u
+ return u
+
+ def setUTCHours(hour, min=None, sec=None, ms=None):
+ check_date(this)
+ t = this.value
+ h = hour.to_number()
+ if not min is None: m = Js(MinFromTime(t))
+ else: m = min.to_number()
+ if not sec is None: s = Js(SecFromTime(t))
+ else: s = sec.to_number()
+ if not ms is None: milli = Js(msFromTime(t))
+ else: milli = ms.to_number()
+ date = MakeDate(Day(t), MakeTime(h, m, s, milli))
+ v = TimeClip(date)
+ this.value = v
+ return v
+
+ def setDate(date):
+ check_date(this)
+ t = UTCToLocal(this.value)
+ dt = date.to_number()
+ newDate = MakeDate(
+ MakeDay(Js(YearFromTime(t)), Js(MonthFromTime(t)), dt), TimeWithinDay(t))
+ u = TimeClip(LocalToUTC(newDate))
+ this.value = u
+ return u
+
+ def setUTCDate(date):
+ check_date(this)
+ t = this.value
+ dt = date.to_number()
+ newDate = MakeDate(
+ MakeDay(Js(YearFromTime(t)), Js(MonthFromTime(t)), dt), TimeWithinDay(t))
+ v = TimeClip(newDate)
+ this.value = v
+ return v
+
+ def setMonth(month, date=None):
+ check_date(this)
+ t = UTCToLocal(this.value)
+ m = month.to_number()
+ if not date is None: dt = Js(DateFromTime(t))
+ else: dt = date.to_number()
+ newDate = MakeDate(
+ MakeDay(Js(YearFromTime(t)), m, dt), TimeWithinDay(t))
+ u = TimeClip(LocalToUTC(newDate))
+ this.value = u
+ return u
+
+ def setUTCMonth(month, date=None):
+ check_date(this)
+ t = this.value
+ m = month.to_number()
+ if not date is None: dt = Js(DateFromTime(t))
+ else: dt = date.to_number()
+ newDate = MakeDate(
+ MakeDay(Js(YearFromTime(t)), m, dt), TimeWithinDay(t))
+ v = TimeClip(newDate)
+ this.value = v
+ return v
+
+ def setFullYear(year, month=None, date=None):
+ check_date(this)
+ if not this.value is NaN: t = UTCToLocal(this.value)
+ else: t = 0
+ y = year.to_number()
+ if not month is None: m = Js(MonthFromTime(t))
+ else: m = month.to_number()
+ if not date is None: dt = Js(DateFromTime(t))
+ else: dt = date.to_number()
+ newDate = MakeDate(
+ MakeDay(y, m, dt), TimeWithinDay(t))
+ u = TimeClip(LocalToUTC(newDate))
+ this.value = u
+ return u
+
+ def setUTCFullYear(year, month=None, date=None):
+ check_date(this)
+ if not this.value is NaN: t = UTCToLocal(this.value)
+ else: t = 0
+ y = year.to_number()
+ if not month is None: m = Js(MonthFromTime(t))
+ else: m = month.to_number()
+ if not date is None: dt = Js(DateFromTime(t))
+ else: dt = date.to_number()
+ newDate = MakeDate(
+ MakeDay(y, m, dt), TimeWithinDay(t))
+ v = TimeClip(newDate)
+ this.value = v
+ return v
def toUTCString():
check_date(this)
@@ -318,13 +527,17 @@ def toISOString():
check_date(this)
t = this.value
year = YearFromTime(t)
- month, day, hour, minute, second, milli = pad(MonthFromTime(t)+1), pad(DateFromTime(t)), pad(HourFromTime(t)), pad(MinFromTime(t)), pad(SecFromTime(t)), pad(msFromTime(t))
- return ISO_FORMAT % (unicode(year) if 0<=year<=9999 else pad(year, 6, True), month, day, hour, minute, second, milli)
+ month, day, hour, minute, second, milli = pad(
+ MonthFromTime(t) + 1), pad(DateFromTime(t)), pad(
+ HourFromTime(t)), pad(MinFromTime(t)), pad(
+ SecFromTime(t)), pad(msFromTime(t))
+ return ISO_FORMAT % (unicode(year) if 0 <= year <= 9999 else pad(
+ year, 6, True), month, day, hour, minute, second, milli)
def toJSON(key):
o = this.to_object()
tv = o.to_primitive('Number')
- if tv.Class=='Number' and not tv.is_finite():
+ if tv.Class == 'Number' and not tv.is_finite():
return this.null
toISO = o.get('toISOString')
if not toISO.is_callable():
@@ -335,34 +548,29 @@ def toJSON(key):
def pad(num, n=2, sign=False):
'''returns n digit string representation of the num'''
s = unicode(abs(num))
- if len(s)=0:
- return '+'+s
+ if num >= 0:
+ return '+' + s
else:
- return '-'+s
-
-
-
-
-
-
-
-
+ return '-' + s
fill_prototype(DatePrototype, DateProto, default_attrs)
-
-
-Date.define_own_property('prototype', {'value': DatePrototype,
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
-
-DatePrototype.define_own_property('constructor', {'value': Date,
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
\ No newline at end of file
+Date.define_own_property(
+ 'prototype', {
+ 'value': DatePrototype,
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ })
+
+DatePrototype.define_own_property('constructor', {
+ 'value': Date,
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+})
diff --git a/js2py/constructors/jsfloat32array.py b/js2py/constructors/jsfloat32array.py
index 95e2662e..3a121916 100644
--- a/js2py/constructors/jsfloat32array.py
+++ b/js2py/constructors/jsfloat32array.py
@@ -9,39 +9,48 @@
@Js
def Float32Array():
- TypedArray = (PyJsInt8Array,PyJsUint8Array,PyJsUint8ClampedArray,PyJsInt16Array,PyJsUint16Array,PyJsInt32Array,PyJsUint32Array,PyJsFloat32Array,PyJsFloat64Array)
+ TypedArray = (PyJsInt8Array, PyJsUint8Array, PyJsUint8ClampedArray,
+ PyJsInt16Array, PyJsUint16Array, PyJsInt32Array,
+ PyJsUint32Array, PyJsFloat32Array, PyJsFloat64Array)
a = arguments[0]
- if isinstance(a, PyJsNumber): # length
+ if isinstance(a, PyJsNumber): # length
length = a.to_uint32()
- if length!=a.value:
+ if length != a.value:
raise MakeError('RangeError', 'Invalid array length')
temp = Js(numpy.full(length, 0, dtype=numpy.float32))
temp.put('length', a)
return temp
- elif isinstance(a, PyJsString): # object (string)
+ elif isinstance(a, PyJsString): # object (string)
temp = Js(numpy.array(list(a.value), dtype=numpy.float32))
temp.put('length', Js(len(list(a.value))))
return temp
- elif isinstance(a, PyJsArray) or isinstance(a,TypedArray) or isinstance(a,PyJsArrayBuffer): # object (Array, TypedArray)
+ elif isinstance(a, PyJsArray) or isinstance(a, TypedArray) or isinstance(
+ a, PyJsArrayBuffer): # object (Array, TypedArray)
array = a.to_list()
- array = [(int(item.value) if item.value != None else 0) for item in array]
+ array = [(int(item.value) if item.value != None else 0)
+ for item in array]
temp = Js(numpy.array(array, dtype=numpy.float32))
temp.put('length', Js(len(array)))
return temp
- elif isinstance(a,PyObjectWrapper): # object (ArrayBuffer, etc)
+ elif isinstance(a, PyObjectWrapper): # object (ArrayBuffer, etc)
if len(a.obj) % 4 != 0:
- raise MakeError('RangeError', 'Byte length of Float32Array should be a multiple of 4')
+ raise MakeError(
+ 'RangeError',
+ 'Byte length of Float32Array should be a multiple of 4')
if len(arguments) > 1:
offset = int(arguments[1].value)
if offset % 4 != 0:
- raise MakeError('RangeError', 'Start offset of Float32Array should be a multiple of 4')
+ raise MakeError(
+ 'RangeError',
+ 'Start offset of Float32Array should be a multiple of 4')
else:
offset = 0
if len(arguments) > 2:
length = int(arguments[2].value)
else:
- length = int((len(a.obj)-offset)/4)
- array = numpy.frombuffer(a.obj, dtype=numpy.float32, count=length, offset=offset)
+ length = int((len(a.obj) - offset) / 4)
+ array = numpy.frombuffer(
+ a.obj, dtype=numpy.float32, count=length, offset=offset)
temp = Js(array)
temp.put('length', Js(length))
temp.buff = array
@@ -50,20 +59,29 @@ def Float32Array():
temp.put('length', Js(0))
return temp
+
Float32Array.create = Float32Array
Float32Array.own['length']['value'] = Js(3)
-Float32Array.define_own_property('prototype', {'value': Float32ArrayPrototype,
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+Float32Array.define_own_property(
+ 'prototype', {
+ 'value': Float32ArrayPrototype,
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ })
-Float32ArrayPrototype.define_own_property('constructor', {'value': Float32Array,
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
+Float32ArrayPrototype.define_own_property(
+ 'constructor', {
+ 'value': Float32Array,
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+ })
-Float32ArrayPrototype.define_own_property('BYTES_PER_ELEMENT', {'value': Js(4),
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+Float32ArrayPrototype.define_own_property('BYTES_PER_ELEMENT', {
+ 'value': Js(4),
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+})
diff --git a/js2py/constructors/jsfloat64array.py b/js2py/constructors/jsfloat64array.py
index 3e5a816a..9ea5f052 100644
--- a/js2py/constructors/jsfloat64array.py
+++ b/js2py/constructors/jsfloat64array.py
@@ -9,39 +9,48 @@
@Js
def Float64Array():
- TypedArray = (PyJsInt8Array,PyJsUint8Array,PyJsUint8ClampedArray,PyJsInt16Array,PyJsUint16Array,PyJsInt32Array,PyJsUint32Array,PyJsFloat32Array,PyJsFloat64Array)
+ TypedArray = (PyJsInt8Array, PyJsUint8Array, PyJsUint8ClampedArray,
+ PyJsInt16Array, PyJsUint16Array, PyJsInt32Array,
+ PyJsUint32Array, PyJsFloat32Array, PyJsFloat64Array)
a = arguments[0]
- if isinstance(a, PyJsNumber): # length
+ if isinstance(a, PyJsNumber): # length
length = a.to_uint32()
- if length!=a.value:
+ if length != a.value:
raise MakeError('RangeError', 'Invalid array length')
temp = Js(numpy.full(length, 0, dtype=numpy.float64))
temp.put('length', a)
return temp
- elif isinstance(a, PyJsString): # object (string)
+ elif isinstance(a, PyJsString): # object (string)
temp = Js(numpy.array(list(a.value), dtype=numpy.float64))
temp.put('length', Js(len(list(a.value))))
return temp
- elif isinstance(a, PyJsArray) or isinstance(a,TypedArray) or isinstance(a,PyJsArrayBuffer): # object (Array, TypedArray)
+ elif isinstance(a, PyJsArray) or isinstance(a, TypedArray) or isinstance(
+ a, PyJsArrayBuffer): # object (Array, TypedArray)
array = a.to_list()
- array = [(int(item.value) if item.value != None else 0) for item in array]
+ array = [(int(item.value) if item.value != None else 0)
+ for item in array]
temp = Js(numpy.array(array, dtype=numpy.float64))
temp.put('length', Js(len(array)))
return temp
- elif isinstance(a,PyObjectWrapper): # object (ArrayBuffer, etc)
+ elif isinstance(a, PyObjectWrapper): # object (ArrayBuffer, etc)
if len(a.obj) % 8 != 0:
- raise MakeError('RangeError', 'Byte length of Float64Array should be a multiple of 8')
+ raise MakeError(
+ 'RangeError',
+ 'Byte length of Float64Array should be a multiple of 8')
if len(arguments) > 1:
offset = int(arguments[1].value)
if offset % 8 != 0:
- raise MakeError('RangeError', 'Start offset of Float64Array should be a multiple of 8')
+ raise MakeError(
+ 'RangeError',
+ 'Start offset of Float64Array should be a multiple of 8')
else:
offset = 0
if len(arguments) > 2:
length = int(arguments[2].value)
else:
- length = int((len(a.obj)-offset)/8)
- array = numpy.frombuffer(a.obj, dtype=numpy.float64, count=length, offset=offset)
+ length = int((len(a.obj) - offset) / 8)
+ array = numpy.frombuffer(
+ a.obj, dtype=numpy.float64, count=length, offset=offset)
temp = Js(array)
temp.put('length', Js(length))
temp.buff = array
@@ -50,20 +59,29 @@ def Float64Array():
temp.put('length', Js(0))
return temp
+
Float64Array.create = Float64Array
Float64Array.own['length']['value'] = Js(3)
-Float64Array.define_own_property('prototype', {'value': Float64ArrayPrototype,
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+Float64Array.define_own_property(
+ 'prototype', {
+ 'value': Float64ArrayPrototype,
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ })
-Float64ArrayPrototype.define_own_property('constructor', {'value': Float64Array,
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
+Float64ArrayPrototype.define_own_property(
+ 'constructor', {
+ 'value': Float64Array,
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+ })
-Float64ArrayPrototype.define_own_property('BYTES_PER_ELEMENT', {'value': Js(8),
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+Float64ArrayPrototype.define_own_property('BYTES_PER_ELEMENT', {
+ 'value': Js(8),
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+})
diff --git a/js2py/constructors/jsfunction.py b/js2py/constructors/jsfunction.py
index 9a8c4b25..c4ace2c3 100644
--- a/js2py/constructors/jsfunction.py
+++ b/js2py/constructors/jsfunction.py
@@ -17,18 +17,19 @@ def Function():
# translate this function to js inline function
js_func = '(function (%s) {%s})' % (','.join(args), body)
# now translate js inline to python function
- py_func = translate_js(js_func, '')
+ py_func = translate_js(js_func, '')
# add set func scope to global scope
# a but messy solution but works :)
globals()['var'] = PyJs.GlobalObject
# define py function and return it
temp = executor(py_func, globals())
- temp.source = '{%s}'%body
+ temp.source = '{%s}' % body
temp.func_name = 'anonymous'
return temp
+
def executor(f, glob):
- exec(f, globals())
+ exec (f, globals())
return globals()['PyJs_anonymous_0_']
@@ -37,13 +38,15 @@ def executor(f, glob):
#set constructor property inside FunctionPrototype
-fill_in_props(FunctionPrototype, {'constructor':Function}, default_attrs)
+fill_in_props(FunctionPrototype, {'constructor': Function}, default_attrs)
#attach prototype to Function constructor
-Function.define_own_property('prototype', {'value': FunctionPrototype,
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+Function.define_own_property(
+ 'prototype', {
+ 'value': FunctionPrototype,
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ })
#Fix Function length (its 0 and should be 1)
Function.own['length']['value'] = Js(1)
-
diff --git a/js2py/constructors/jsint16array.py b/js2py/constructors/jsint16array.py
index 8641690d..c2864105 100644
--- a/js2py/constructors/jsint16array.py
+++ b/js2py/constructors/jsint16array.py
@@ -6,41 +6,51 @@
except:
pass
+
@Js
def Int16Array():
- TypedArray = (PyJsInt8Array,PyJsUint8Array,PyJsUint8ClampedArray,PyJsInt16Array,PyJsUint16Array,PyJsInt32Array,PyJsUint32Array,PyJsFloat32Array,PyJsFloat64Array)
+ TypedArray = (PyJsInt8Array, PyJsUint8Array, PyJsUint8ClampedArray,
+ PyJsInt16Array, PyJsUint16Array, PyJsInt32Array,
+ PyJsUint32Array, PyJsFloat32Array, PyJsFloat64Array)
a = arguments[0]
- if isinstance(a, PyJsNumber): # length
+ if isinstance(a, PyJsNumber): # length
length = a.to_uint32()
- if length!=a.value:
+ if length != a.value:
raise MakeError('RangeError', 'Invalid array length')
temp = Js(numpy.full(length, 0, dtype=numpy.int16))
temp.put('length', a)
return temp
- elif isinstance(a, PyJsString): # object (string)
+ elif isinstance(a, PyJsString): # object (string)
temp = Js(numpy.array(list(a.value), dtype=numpy.int16))
temp.put('length', Js(len(list(a.value))))
return temp
- elif isinstance(a, PyJsArray) or isinstance(a,TypedArray) or isinstance(a,PyJsArrayBuffer): # object (Array, TypedArray)
+ elif isinstance(a, PyJsArray) or isinstance(a, TypedArray) or isinstance(
+ a, PyJsArrayBuffer): # object (Array, TypedArray)
array = a.to_list()
- array = [(int(item.value) if item.value != None else 0) for item in array]
+ array = [(int(item.value) if item.value != None else 0)
+ for item in array]
temp = Js(numpy.array(array, dtype=numpy.int16))
temp.put('length', Js(len(array)))
return temp
- elif isinstance(a,PyObjectWrapper): # object (ArrayBuffer, etc)
+ elif isinstance(a, PyObjectWrapper): # object (ArrayBuffer, etc)
if len(a.obj) % 2 != 0:
- raise MakeError('RangeError', 'Byte length of Int16Array should be a multiple of 2')
+ raise MakeError(
+ 'RangeError',
+ 'Byte length of Int16Array should be a multiple of 2')
if len(arguments) > 1:
offset = int(arguments[1].value)
if offset % 2 != 0:
- raise MakeError('RangeError', 'Start offset of Int16Array should be a multiple of 2')
+ raise MakeError(
+ 'RangeError',
+ 'Start offset of Int16Array should be a multiple of 2')
else:
offset = 0
if len(arguments) > 2:
length = int(arguments[2].value)
else:
- length = int((len(a.obj)-offset)/2)
- array = numpy.frombuffer(a.obj, dtype=numpy.int16, count=length, offset=offset)
+ length = int((len(a.obj) - offset) / 2)
+ array = numpy.frombuffer(
+ a.obj, dtype=numpy.int16, count=length, offset=offset)
temp = Js(array)
temp.put('length', Js(length))
temp.buff = array
@@ -49,20 +59,29 @@ def Int16Array():
temp.put('length', Js(0))
return temp
+
Int16Array.create = Int16Array
Int16Array.own['length']['value'] = Js(3)
-Int16Array.define_own_property('prototype', {'value': Int16ArrayPrototype,
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+Int16Array.define_own_property(
+ 'prototype', {
+ 'value': Int16ArrayPrototype,
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ })
-Int16ArrayPrototype.define_own_property('constructor', {'value': Int16Array,
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
+Int16ArrayPrototype.define_own_property(
+ 'constructor', {
+ 'value': Int16Array,
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+ })
-Int16ArrayPrototype.define_own_property('BYTES_PER_ELEMENT', {'value': Js(2),
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+Int16ArrayPrototype.define_own_property('BYTES_PER_ELEMENT', {
+ 'value': Js(2),
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+})
diff --git a/js2py/constructors/jsint32array.py b/js2py/constructors/jsint32array.py
index 3f50ded1..2e8c4e84 100644
--- a/js2py/constructors/jsint32array.py
+++ b/js2py/constructors/jsint32array.py
@@ -9,39 +9,48 @@
@Js
def Int32Array():
- TypedArray = (PyJsInt8Array,PyJsUint8Array,PyJsUint8ClampedArray,PyJsInt16Array,PyJsUint16Array,PyJsInt32Array,PyJsUint32Array,PyJsFloat32Array,PyJsFloat64Array)
+ TypedArray = (PyJsInt8Array, PyJsUint8Array, PyJsUint8ClampedArray,
+ PyJsInt16Array, PyJsUint16Array, PyJsInt32Array,
+ PyJsUint32Array, PyJsFloat32Array, PyJsFloat64Array)
a = arguments[0]
- if isinstance(a, PyJsNumber): # length
+ if isinstance(a, PyJsNumber): # length
length = a.to_uint32()
- if length!=a.value:
+ if length != a.value:
raise MakeError('RangeError', 'Invalid array length')
temp = Js(numpy.full(length, 0, dtype=numpy.int32))
temp.put('length', a)
return temp
- elif isinstance(a, PyJsString): # object (string)
+ elif isinstance(a, PyJsString): # object (string)
temp = Js(numpy.array(list(a.value), dtype=numpy.int32))
temp.put('length', Js(len(list(a.value))))
return temp
- elif isinstance(a, PyJsArray) or isinstance(a,TypedArray) or isinstance(a,PyJsArrayBuffer): # object (Array, TypedArray)
+ elif isinstance(a, PyJsArray) or isinstance(a, TypedArray) or isinstance(
+ a, PyJsArrayBuffer): # object (Array, TypedArray)
array = a.to_list()
- array = [(int(item.value) if item.value != None else 0) for item in array]
+ array = [(int(item.value) if item.value != None else 0)
+ for item in array]
temp = Js(numpy.array(array, dtype=numpy.int32))
temp.put('length', Js(len(array)))
return temp
- elif isinstance(a,PyObjectWrapper): # object (ArrayBuffer, etc)
+ elif isinstance(a, PyObjectWrapper): # object (ArrayBuffer, etc)
if len(a.obj) % 4 != 0:
- raise MakeError('RangeError', 'Byte length of Int32Array should be a multiple of 4')
+ raise MakeError(
+ 'RangeError',
+ 'Byte length of Int32Array should be a multiple of 4')
if len(arguments) > 1:
offset = int(arguments[1].value)
if offset % 4 != 0:
- raise MakeError('RangeError', 'Start offset of Int32Array should be a multiple of 4')
+ raise MakeError(
+ 'RangeError',
+ 'Start offset of Int32Array should be a multiple of 4')
else:
offset = 0
if len(arguments) > 2:
length = int(arguments[2].value)
else:
- length = int((len(a.obj)-offset)/4)
- array = numpy.frombuffer(a.obj, dtype=numpy.int32, count=length, offset=offset)
+ length = int((len(a.obj) - offset) / 4)
+ array = numpy.frombuffer(
+ a.obj, dtype=numpy.int32, count=length, offset=offset)
temp = Js(array)
temp.put('length', Js(length))
temp.buff = array
@@ -50,20 +59,29 @@ def Int32Array():
temp.put('length', Js(0))
return temp
+
Int32Array.create = Int32Array
Int32Array.own['length']['value'] = Js(3)
-Int32Array.define_own_property('prototype', {'value': Int32ArrayPrototype,
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+Int32Array.define_own_property(
+ 'prototype', {
+ 'value': Int32ArrayPrototype,
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ })
-Int32ArrayPrototype.define_own_property('constructor', {'value': Int32Array,
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
+Int32ArrayPrototype.define_own_property(
+ 'constructor', {
+ 'value': Int32Array,
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+ })
-Int32ArrayPrototype.define_own_property('BYTES_PER_ELEMENT', {'value': Js(4),
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+Int32ArrayPrototype.define_own_property('BYTES_PER_ELEMENT', {
+ 'value': Js(4),
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+})
diff --git a/js2py/constructors/jsint8array.py b/js2py/constructors/jsint8array.py
index 68adc468..3396afea 100644
--- a/js2py/constructors/jsint8array.py
+++ b/js2py/constructors/jsint8array.py
@@ -6,28 +6,33 @@
except:
pass
+
@Js
def Int8Array():
- TypedArray = (PyJsInt8Array,PyJsUint8Array,PyJsUint8ClampedArray,PyJsInt16Array,PyJsUint16Array,PyJsInt32Array,PyJsUint32Array,PyJsFloat32Array,PyJsFloat64Array)
+ TypedArray = (PyJsInt8Array, PyJsUint8Array, PyJsUint8ClampedArray,
+ PyJsInt16Array, PyJsUint16Array, PyJsInt32Array,
+ PyJsUint32Array, PyJsFloat32Array, PyJsFloat64Array)
a = arguments[0]
- if isinstance(a, PyJsNumber): # length
+ if isinstance(a, PyJsNumber): # length
length = a.to_uint32()
- if length!=a.value:
+ if length != a.value:
raise MakeError('RangeError', 'Invalid array length')
temp = Js(numpy.full(length, 0, dtype=numpy.int8))
temp.put('length', a)
return temp
- elif isinstance(a, PyJsString): # object (string)
+ elif isinstance(a, PyJsString): # object (string)
temp = Js(numpy.array(list(a.value), dtype=numpy.int8))
temp.put('length', Js(len(list(a.value))))
return temp
- elif isinstance(a, PyJsArray) or isinstance(a,TypedArray) or isinstance(a,PyJsArrayBuffer): # object (Array, TypedArray)
+ elif isinstance(a, PyJsArray) or isinstance(a, TypedArray) or isinstance(
+ a, PyJsArrayBuffer): # object (Array, TypedArray)
array = a.to_list()
- array = [(int(item.value) if item.value != None else 0) for item in array]
+ array = [(int(item.value) if item.value != None else 0)
+ for item in array]
temp = Js(numpy.array(array, dtype=numpy.int8))
temp.put('length', Js(len(array)))
return temp
- elif isinstance(a,PyObjectWrapper): # object (ArrayBuffer, etc)
+ elif isinstance(a, PyObjectWrapper): # object (ArrayBuffer, etc)
if len(arguments) > 1:
offset = int(arguments[1].value)
else:
@@ -35,8 +40,9 @@ def Int8Array():
if len(arguments) > 2:
length = int(arguments[2].value)
else:
- length = int(len(a.obj)-offset)
- array = numpy.frombuffer(a.obj, dtype=numpy.int8, count=length, offset=offset)
+ length = int(len(a.obj) - offset)
+ array = numpy.frombuffer(
+ a.obj, dtype=numpy.int8, count=length, offset=offset)
temp = Js(array)
temp.put('length', Js(length))
temp.buff = array
@@ -45,20 +51,29 @@ def Int8Array():
temp.put('length', Js(0))
return temp
+
Int8Array.create = Int8Array
Int8Array.own['length']['value'] = Js(3)
-Int8Array.define_own_property('prototype', {'value': Int8ArrayPrototype,
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+Int8Array.define_own_property(
+ 'prototype', {
+ 'value': Int8ArrayPrototype,
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ })
-Int8ArrayPrototype.define_own_property('constructor', {'value': Int8Array,
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
+Int8ArrayPrototype.define_own_property(
+ 'constructor', {
+ 'value': Int8Array,
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+ })
-Int8ArrayPrototype.define_own_property('BYTES_PER_ELEMENT', {'value': Js(1),
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+Int8ArrayPrototype.define_own_property('BYTES_PER_ELEMENT', {
+ 'value': Js(1),
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+})
diff --git a/js2py/constructors/jsmath.py b/js2py/constructors/jsmath.py
index 8774527a..06751a3b 100644
--- a/js2py/constructors/jsmath.py
+++ b/js2py/constructors/jsmath.py
@@ -5,31 +5,37 @@
Math = PyJsObject(prototype=ObjectPrototype)
Math.Class = 'Math'
-CONSTANTS = {'E': 2.7182818284590452354,
- 'LN10': 2.302585092994046,
- 'LN2': 0.6931471805599453,
- 'LOG2E': 1.4426950408889634,
- 'LOG10E': 0.4342944819032518,
- 'PI': 3.1415926535897932,
- 'SQRT1_2': 0.7071067811865476,
- 'SQRT2': 1.4142135623730951}
+CONSTANTS = {
+ 'E': 2.7182818284590452354,
+ 'LN10': 2.302585092994046,
+ 'LN2': 0.6931471805599453,
+ 'LOG2E': 1.4426950408889634,
+ 'LOG10E': 0.4342944819032518,
+ 'PI': 3.1415926535897932,
+ 'SQRT1_2': 0.7071067811865476,
+ 'SQRT2': 1.4142135623730951
+}
for constant, value in CONSTANTS.items():
- Math.define_own_property(constant, {'value': Js(value),
- 'writable': False,
- 'enumerable': False,
- 'configurable': False})
+ Math.define_own_property(
+ constant, {
+ 'value': Js(value),
+ 'writable': False,
+ 'enumerable': False,
+ 'configurable': False
+ })
+
class MathFunctions:
def abs(x):
a = x.to_number().value
- if a!=a: # it must be a nan
+ if a != a: # it must be a nan
return NaN
return abs(a)
def acos(x):
a = x.to_number().value
- if a!=a: # it must be a nan
+ if a != a: # it must be a nan
return NaN
try:
return math.acos(a)
@@ -38,7 +44,7 @@ def acos(x):
def asin(x):
a = x.to_number().value
- if a!=a: # it must be a nan
+ if a != a: # it must be a nan
return NaN
try:
return math.asin(a)
@@ -47,56 +53,56 @@ def asin(x):
def atan(x):
a = x.to_number().value
- if a!=a: # it must be a nan
+ if a != a: # it must be a nan
return NaN
return math.atan(a)
def atan2(y, x):
a = x.to_number().value
b = y.to_number().value
- if a!=a or b!=b: # it must be a nan
+ if a != a or b != b: # it must be a nan
return NaN
return math.atan2(b, a)
def ceil(x):
a = x.to_number().value
- if a!=a: # it must be a nan
+ if a != a: # it must be a nan
return NaN
return math.ceil(a)
def floor(x):
a = x.to_number().value
- if a!=a: # it must be a nan
+ if a != a: # it must be a nan
return NaN
return math.floor(a)
def round(x):
a = x.to_number().value
- if a!=a: # it must be a nan
+ if a != a: # it must be a nan
return NaN
return round(a)
def sin(x):
a = x.to_number().value
- if a!=a: # it must be a nan
+ if a != a: # it must be a nan
return NaN
return math.sin(a)
def cos(x):
a = x.to_number().value
- if a!=a: # it must be a nan
+ if a != a: # it must be a nan
return NaN
- return math.cos(a)
+ return math.cos(a)
def tan(x):
a = x.to_number().value
- if a!=a: # it must be a nan
+ if a != a: # it must be a nan
return NaN
return math.tan(a)
def log(x):
a = x.to_number().value
- if a!=a: # it must be a nan
+ if a != a: # it must be a nan
return NaN
try:
return math.log(a)
@@ -105,14 +111,14 @@ def log(x):
def exp(x):
a = x.to_number().value
- if a!=a: # it must be a nan
+ if a != a: # it must be a nan
return NaN
return math.exp(a)
def pow(x, y):
a = x.to_number().value
b = y.to_number().value
- if a!=a or b!=b: # it must be a nan
+ if a != a or b != b: # it must be a nan
return NaN
try:
return a**b
@@ -121,7 +127,7 @@ def pow(x, y):
def sqrt(x):
a = x.to_number().value
- if a!=a: # it must be a nan
+ if a != a: # it must be a nan
return NaN
try:
return a**0.5
@@ -132,7 +138,7 @@ def min():
if not len(arguments):
return Infinity
lis = tuple(e.to_number().value for e in arguments.to_list())
- if any(e!=e for e in lis): # we dont want NaNs
+ if any(e != e for e in lis): # we dont want NaNs
return NaN
return min(*lis)
@@ -140,7 +146,7 @@ def max():
if not len(arguments):
return -Infinity
lis = tuple(e.to_number().value for e in arguments.to_list())
- if any(e!=e for e in lis): # we dont want NaNs
+ if any(e != e for e in lis): # we dont want NaNs
return NaN
return max(*lis)
@@ -148,4 +154,4 @@ def random():
return random.random()
-fill_prototype(Math, MathFunctions, default_attrs)
\ No newline at end of file
+fill_prototype(Math, MathFunctions, default_attrs)
diff --git a/js2py/constructors/jsnumber.py b/js2py/constructors/jsnumber.py
index 9acb43a0..9ba7c7c7 100644
--- a/js2py/constructors/jsnumber.py
+++ b/js2py/constructors/jsnumber.py
@@ -1,18 +1,23 @@
from ..base import *
+CONSTS = {
+ 'prototype': NumberPrototype,
+ 'MAX_VALUE': 1.7976931348623157e308,
+ 'MIN_VALUE': 5.0e-324,
+ 'NaN': NaN,
+ 'NEGATIVE_INFINITY': float('-inf'),
+ 'POSITIVE_INFINITY': float('inf')
+}
-CONSTS = {'prototype': NumberPrototype,
- 'MAX_VALUE':1.7976931348623157e308,
- 'MIN_VALUE': 5.0e-324,
- 'NaN': NaN,
- 'NEGATIVE_INFINITY': float('-inf'),
- 'POSITIVE_INFINITY': float('inf')}
+fill_in_props(Number, CONSTS, {
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+})
-fill_in_props(Number, CONSTS, {'enumerable': False,
- 'writable': False,
- 'configurable': False})
-
-NumberPrototype.define_own_property('constructor', {'value': Number,
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
\ No newline at end of file
+NumberPrototype.define_own_property('constructor', {
+ 'value': Number,
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+})
diff --git a/js2py/constructors/jsobject.py b/js2py/constructors/jsobject.py
index 5169fe1a..c4e0ada3 100644
--- a/js2py/constructors/jsobject.py
+++ b/js2py/constructors/jsobject.py
@@ -3,6 +3,7 @@
#todo Double check everything is OK
+
@Js
def Object():
val = arguments.get('0')
@@ -15,13 +16,14 @@ def Object():
def object_constructor():
if len(arguments):
val = arguments.get('0')
- if val.TYPE=='Object':
+ if val.TYPE == 'Object':
#Implementation dependent, but my will simply return :)
return val
elif val.TYPE in ('Number', 'String', 'Boolean'):
return val.to_object()
return PyJsObject(prototype=ObjectPrototype)
+
Object.create = object_constructor
Object.own['length']['value'] = Js(1)
@@ -29,24 +31,32 @@ def object_constructor():
class ObjectMethods:
def getPrototypeOf(obj):
if not obj.is_object():
- raise MakeError('TypeError', 'Object.getPrototypeOf called on non-object')
+ raise MakeError('TypeError',
+ 'Object.getPrototypeOf called on non-object')
return null if obj.prototype is None else obj.prototype
- def getOwnPropertyDescriptor (obj, prop):
+ def getOwnPropertyDescriptor(obj, prop):
if not obj.is_object():
- raise MakeError('TypeError', 'Object.getOwnPropertyDescriptor called on non-object')
- return obj.own.get(prop.to_string().value) # will return undefined if we dont have this prop
+ raise MakeError(
+ 'TypeError',
+ 'Object.getOwnPropertyDescriptor called on non-object')
+ return obj.own.get(
+ prop.to_string().
+ value) # will return undefined if we dont have this prop
def getOwnPropertyNames(obj):
if not obj.is_object():
- raise MakeError('TypeError', 'Object.getOwnPropertyDescriptor called on non-object')
+ raise MakeError(
+ 'TypeError',
+ 'Object.getOwnPropertyDescriptor called on non-object')
return obj.own.keys()
def create(obj):
if not (obj.is_object() or obj.is_null()):
- raise MakeError('TypeError', 'Object prototype may only be an Object or null')
+ raise MakeError('TypeError',
+ 'Object prototype may only be an Object or null')
temp = PyJsObject(prototype=(None if obj.is_null() else obj))
- if len(arguments)>1 and not arguments[1].is_undefined():
+ if len(arguments) > 1 and not arguments[1].is_undefined():
if six.PY2:
ObjectMethods.defineProperties.__func__(temp, arguments[1])
else:
@@ -55,7 +65,8 @@ def create(obj):
def defineProperty(obj, prop, attrs):
if not obj.is_object():
- raise MakeError('TypeError', 'Object.defineProperty called on non-object')
+ raise MakeError('TypeError',
+ 'Object.defineProperty called on non-object')
name = prop.to_string().value
if not obj.define_own_property(name, ToPropertyDescriptor(attrs)):
raise MakeError('TypeError', 'Cannot redefine property: %s' % name)
@@ -63,12 +74,15 @@ def defineProperty(obj, prop, attrs):
def defineProperties(obj, properties):
if not obj.is_object():
- raise MakeError('TypeError', 'Object.defineProperties called on non-object')
+ raise MakeError('TypeError',
+ 'Object.defineProperties called on non-object')
props = properties.to_object()
for name in props:
desc = ToPropertyDescriptor(props.get(name.value))
if not obj.define_own_property(name.value, desc):
- raise MakeError('TypeError', 'Failed to define own property: %s'%name.value)
+ raise MakeError(
+ 'TypeError',
+ 'Failed to define own property: %s' % name.value)
return obj
def seal(obj):
@@ -91,13 +105,15 @@ def freeze(obj):
def preventExtensions(obj):
if not obj.is_object():
- raise MakeError('TypeError', 'Object.preventExtensions on non-object')
+ raise MakeError('TypeError',
+ 'Object.preventExtensions on non-object')
obj.extensible = False
return obj
def isSealed(obj):
if not obj.is_object():
- raise MakeError('TypeError', 'Object.isSealed called on non-object')
+ raise MakeError('TypeError',
+ 'Object.isSealed called on non-object')
if obj.extensible:
return False
for desc in obj.own.values():
@@ -107,7 +123,8 @@ def isSealed(obj):
def isFrozen(obj):
if not obj.is_object():
- raise MakeError('TypeError', 'Object.isFrozen called on non-object')
+ raise MakeError('TypeError',
+ 'Object.isFrozen called on non-object')
if obj.extensible:
return False
for desc in obj.own.values():
@@ -119,32 +136,36 @@ def isFrozen(obj):
def isExtensible(obj):
if not obj.is_object():
- raise MakeError('TypeError', 'Object.isExtensible called on non-object')
+ raise MakeError('TypeError',
+ 'Object.isExtensible called on non-object')
return obj.extensible
def keys(obj):
if not obj.is_object():
raise MakeError('TypeError', 'Object.keys called on non-object')
- return [e for e,d in six.iteritems(obj.own) if d.get('enumerable')]
+ return [e for e, d in six.iteritems(obj.own) if d.get('enumerable')]
# add methods attached to Object constructor
fill_prototype(Object, ObjectMethods, default_attrs)
# add constructor to prototype
-fill_in_props(ObjectPrototype, {'constructor':Object}, default_attrs)
+fill_in_props(ObjectPrototype, {'constructor': Object}, default_attrs)
# add prototype property to the constructor.
-Object.define_own_property('prototype', {'value': ObjectPrototype,
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
-
-
+Object.define_own_property(
+ 'prototype', {
+ 'value': ObjectPrototype,
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ })
# some utility functions:
+
def ToPropertyDescriptor(obj): # page 38 (50 absolute)
- if obj.TYPE!='Object':
- raise MakeError('TypeError', 'Can\'t convert non-object to property descriptor')
+ if obj.TYPE != 'Object':
+ raise MakeError('TypeError',
+ 'Can\'t convert non-object to property descriptor')
desc = {}
if obj.has_property('enumerable'):
desc['enumerable'] = obj.get('enumerable').to_boolean().value
@@ -155,18 +176,23 @@ def ToPropertyDescriptor(obj): # page 38 (50 absolute)
if obj.has_property('writable'):
desc['writable'] = obj.get('writable').to_boolean().value
if obj.has_property('get'):
- cand = obj.get('get')
+ cand = obj.get('get')
if not (cand.is_undefined() or cand.is_callable()):
- raise MakeError('TypeError', 'Invalid getter (it has to be a function or undefined)')
+ raise MakeError(
+ 'TypeError',
+ 'Invalid getter (it has to be a function or undefined)')
desc['get'] = cand
if obj.has_property('set'):
- cand = obj.get('set')
+ cand = obj.get('set')
if not (cand.is_undefined() or cand.is_callable()):
- raise MakeError('TypeError', 'Invalid setter (it has to be a function or undefined)')
+ raise MakeError(
+ 'TypeError',
+ 'Invalid setter (it has to be a function or undefined)')
desc['set'] = cand
- if ('get' in desc or 'set' in desc) and ('value' in desc or 'writable' in desc):
- raise MakeError('TypeError', 'Invalid property. A property cannot both have accessors and be writable or have a value.')
+ if ('get' in desc or 'set' in desc) and ('value' in desc
+ or 'writable' in desc):
+ raise MakeError(
+ 'TypeError',
+ 'Invalid property. A property cannot both have accessors and be writable or have a value.'
+ )
return desc
-
-
-
diff --git a/js2py/constructors/jsregexp.py b/js2py/constructors/jsregexp.py
index 120c097d..2dfc25cb 100644
--- a/js2py/constructors/jsregexp.py
+++ b/js2py/constructors/jsregexp.py
@@ -1,11 +1,16 @@
from ..base import *
-RegExpPrototype.define_own_property('constructor', {'value': RegExp,
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
+RegExpPrototype.define_own_property('constructor', {
+ 'value': RegExp,
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+})
-RegExp.define_own_property('prototype', {'value': RegExpPrototype,
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
\ No newline at end of file
+RegExp.define_own_property(
+ 'prototype', {
+ 'value': RegExpPrototype,
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ })
diff --git a/js2py/constructors/jsstring.py b/js2py/constructors/jsstring.py
index cf9100af..0650d0f5 100644
--- a/js2py/constructors/jsstring.py
+++ b/js2py/constructors/jsstring.py
@@ -4,27 +4,37 @@
if six.PY3:
unichr = chr
+
@Js
def fromCharCode():
args = arguments.to_list()
res = u''
for e in args:
- res +=unichr(e.to_uint16())
+ res += unichr(e.to_uint16())
return this.Js(res)
+
fromCharCode.own['length']['value'] = Js(1)
-String.define_own_property('fromCharCode', {'value': fromCharCode,
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
+String.define_own_property(
+ 'fromCharCode', {
+ 'value': fromCharCode,
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+ })
-String.define_own_property('prototype', {'value': StringPrototype,
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+String.define_own_property(
+ 'prototype', {
+ 'value': StringPrototype,
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ })
-StringPrototype.define_own_property('constructor', {'value': String,
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
\ No newline at end of file
+StringPrototype.define_own_property('constructor', {
+ 'value': String,
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+})
diff --git a/js2py/constructors/jsuint16array.py b/js2py/constructors/jsuint16array.py
index efc4f67d..a61be246 100644
--- a/js2py/constructors/jsuint16array.py
+++ b/js2py/constructors/jsuint16array.py
@@ -6,41 +6,51 @@
except:
pass
+
@Js
def Uint16Array():
- TypedArray = (PyJsInt8Array,PyJsUint8Array,PyJsUint8ClampedArray,PyJsInt16Array,PyJsUint16Array,PyJsInt32Array,PyJsUint32Array,PyJsFloat32Array,PyJsFloat64Array)
+ TypedArray = (PyJsInt8Array, PyJsUint8Array, PyJsUint8ClampedArray,
+ PyJsInt16Array, PyJsUint16Array, PyJsInt32Array,
+ PyJsUint32Array, PyJsFloat32Array, PyJsFloat64Array)
a = arguments[0]
- if isinstance(a, PyJsNumber): # length
+ if isinstance(a, PyJsNumber): # length
length = a.to_uint32()
- if length!=a.value:
+ if length != a.value:
raise MakeError('RangeError', 'Invalid array length')
temp = Js(numpy.full(length, 0, dtype=numpy.uint16))
temp.put('length', a)
return temp
- elif isinstance(a, PyJsString): # object (string)
+ elif isinstance(a, PyJsString): # object (string)
temp = Js(numpy.array(list(a.value), dtype=numpy.uint16))
temp.put('length', Js(len(list(a.value))))
return temp
- elif isinstance(a, PyJsArray) or isinstance(a,TypedArray) or isinstance(a,PyJsArrayBuffer): # object (Array, TypedArray)
+ elif isinstance(a, PyJsArray) or isinstance(a, TypedArray) or isinstance(
+ a, PyJsArrayBuffer): # object (Array, TypedArray)
array = a.to_list()
- array = [(int(item.value) if item.value != None else 0) for item in array]
+ array = [(int(item.value) if item.value != None else 0)
+ for item in array]
temp = Js(numpy.array(array, dtype=numpy.uint16))
temp.put('length', Js(len(array)))
return temp
- elif isinstance(a,PyObjectWrapper): # object (ArrayBuffer, etc)
+ elif isinstance(a, PyObjectWrapper): # object (ArrayBuffer, etc)
if len(a.obj) % 2 != 0:
- raise MakeError('RangeError', 'Byte length of Uint16Array should be a multiple of 2')
+ raise MakeError(
+ 'RangeError',
+ 'Byte length of Uint16Array should be a multiple of 2')
if len(arguments) > 1:
offset = int(arguments[1].value)
if offset % 2 != 0:
- raise MakeError('RangeError', 'Start offset of Uint16Array should be a multiple of 2')
+ raise MakeError(
+ 'RangeError',
+ 'Start offset of Uint16Array should be a multiple of 2')
else:
offset = 0
if len(arguments) > 2:
length = int(arguments[2].value)
else:
- length = int((len(a.obj)-offset)/2)
- array = numpy.frombuffer(a.obj, dtype=numpy.uint16, count=length, offset=offset)
+ length = int((len(a.obj) - offset) / 2)
+ array = numpy.frombuffer(
+ a.obj, dtype=numpy.uint16, count=length, offset=offset)
temp = Js(array)
temp.put('length', Js(length))
temp.buff = array
@@ -49,20 +59,29 @@ def Uint16Array():
temp.put('length', Js(0))
return temp
+
Uint16Array.create = Uint16Array
Uint16Array.own['length']['value'] = Js(3)
-Uint16Array.define_own_property('prototype', {'value': Uint16ArrayPrototype,
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+Uint16Array.define_own_property(
+ 'prototype', {
+ 'value': Uint16ArrayPrototype,
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ })
-Uint16ArrayPrototype.define_own_property('constructor', {'value': Uint16Array,
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
+Uint16ArrayPrototype.define_own_property(
+ 'constructor', {
+ 'value': Uint16Array,
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+ })
-Uint16ArrayPrototype.define_own_property('BYTES_PER_ELEMENT', {'value': Js(2),
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+Uint16ArrayPrototype.define_own_property('BYTES_PER_ELEMENT', {
+ 'value': Js(2),
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+})
diff --git a/js2py/constructors/jsuint32array.py b/js2py/constructors/jsuint32array.py
index b9f402cf..c6f57c94 100644
--- a/js2py/constructors/jsuint32array.py
+++ b/js2py/constructors/jsuint32array.py
@@ -6,24 +6,29 @@
except:
pass
+
@Js
def Uint32Array():
- TypedArray = (PyJsInt8Array,PyJsUint8Array,PyJsUint8ClampedArray,PyJsInt16Array,PyJsUint16Array,PyJsInt32Array,PyJsUint32Array,PyJsFloat32Array,PyJsFloat64Array)
+ TypedArray = (PyJsInt8Array, PyJsUint8Array, PyJsUint8ClampedArray,
+ PyJsInt16Array, PyJsUint16Array, PyJsInt32Array,
+ PyJsUint32Array, PyJsFloat32Array, PyJsFloat64Array)
a = arguments[0]
- if isinstance(a, PyJsNumber): # length
+ if isinstance(a, PyJsNumber): # length
length = a.to_uint32()
- if length!=a.value:
+ if length != a.value:
raise MakeError('RangeError', 'Invalid array length')
temp = Js(numpy.full(length, 0, dtype=numpy.uint32))
temp.put('length', a)
return temp
- elif isinstance(a, PyJsString): # object (string)
+ elif isinstance(a, PyJsString): # object (string)
temp = Js(numpy.array(list(a.value), dtype=numpy.uint32))
temp.put('length', Js(len(list(a.value))))
return temp
- elif isinstance(a, PyJsArray) or isinstance(a,TypedArray) or isinstance(a,PyJsArrayBuffer): # object (Array, TypedArray)
+ elif isinstance(a, PyJsArray) or isinstance(a, TypedArray) or isinstance(
+ a, PyJsArrayBuffer): # object (Array, TypedArray)
array = a.to_list()
- array = [(int(item.value) if item.value != None else 0) for item in array]
+ array = [(int(item.value) if item.value != None else 0)
+ for item in array]
if len(arguments) > 1:
offset = int(arguments[1].value)
else:
@@ -31,44 +36,60 @@ def Uint32Array():
if len(arguments) > 2:
length = int(arguments[2].value)
else:
- length = len(array)-offset
- temp = Js(numpy.array(array[offset:offset+length], dtype=numpy.uint32))
+ length = len(array) - offset
+ temp = Js(
+ numpy.array(array[offset:offset + length], dtype=numpy.uint32))
temp.put('length', Js(length))
return temp
- elif isinstance(a,PyObjectWrapper): # object (ArrayBuffer, etc)
+ elif isinstance(a, PyObjectWrapper): # object (ArrayBuffer, etc)
if len(a.obj) % 4 != 0:
- raise MakeError('RangeError', 'Byte length of Uint32Array should be a multiple of 4')
+ raise MakeError(
+ 'RangeError',
+ 'Byte length of Uint32Array should be a multiple of 4')
if len(arguments) > 1:
offset = int(arguments[1].value)
if offset % 4 != 0:
- raise MakeError('RangeError', 'Start offset of Uint32Array should be a multiple of 4')
+ raise MakeError(
+ 'RangeError',
+ 'Start offset of Uint32Array should be a multiple of 4')
else:
offset = 0
if len(arguments) > 2:
length = int(arguments[2].value)
else:
- length = int((len(a.obj)-offset)/4)
- temp = Js(numpy.frombuffer(a.obj, dtype=numpy.uint32, count=length, offset=offset))
+ length = int((len(a.obj) - offset) / 4)
+ temp = Js(
+ numpy.frombuffer(
+ a.obj, dtype=numpy.uint32, count=length, offset=offset))
temp.put('length', Js(length))
return temp
temp = Js(numpy.full(0, 0, dtype=numpy.uint32))
temp.put('length', Js(0))
return temp
+
Uint32Array.create = Uint32Array
Uint32Array.own['length']['value'] = Js(3)
-Uint32Array.define_own_property('prototype', {'value': Uint32ArrayPrototype,
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+Uint32Array.define_own_property(
+ 'prototype', {
+ 'value': Uint32ArrayPrototype,
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ })
-Uint32ArrayPrototype.define_own_property('constructor', {'value': Uint32Array,
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
+Uint32ArrayPrototype.define_own_property(
+ 'constructor', {
+ 'value': Uint32Array,
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+ })
-Uint32ArrayPrototype.define_own_property('BYTES_PER_ELEMENT', {'value': Js(4),
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+Uint32ArrayPrototype.define_own_property('BYTES_PER_ELEMENT', {
+ 'value': Js(4),
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+})
diff --git a/js2py/constructors/jsuint8array.py b/js2py/constructors/jsuint8array.py
index a0f5df01..4b2199da 100644
--- a/js2py/constructors/jsuint8array.py
+++ b/js2py/constructors/jsuint8array.py
@@ -9,26 +9,30 @@
@Js
def Uint8Array():
- TypedArray = (PyJsInt8Array,PyJsUint8Array,PyJsUint8ClampedArray,PyJsInt16Array,PyJsUint16Array,PyJsInt32Array,PyJsUint32Array,PyJsFloat32Array,PyJsFloat64Array)
+ TypedArray = (PyJsInt8Array, PyJsUint8Array, PyJsUint8ClampedArray,
+ PyJsInt16Array, PyJsUint16Array, PyJsInt32Array,
+ PyJsUint32Array, PyJsFloat32Array, PyJsFloat64Array)
a = arguments[0]
- if isinstance(a, PyJsNumber): # length
+ if isinstance(a, PyJsNumber): # length
length = a.to_uint32()
- if length!=a.value:
+ if length != a.value:
raise MakeError('RangeError', 'Invalid array length')
temp = Js(numpy.full(length, 0, dtype=numpy.uint8))
temp.put('length', a)
return temp
- elif isinstance(a, PyJsString): # object (string)
+ elif isinstance(a, PyJsString): # object (string)
temp = Js(numpy.array(list(a.value), dtype=numpy.uint8))
temp.put('length', Js(len(list(a.value))))
return temp
- elif isinstance(a, PyJsArray) or isinstance(a,TypedArray) or isinstance(a,PyJsArrayBuffer): # object (Array, TypedArray)
+ elif isinstance(a, PyJsArray) or isinstance(a, TypedArray) or isinstance(
+ a, PyJsArrayBuffer): # object (Array, TypedArray)
array = a.to_list()
- array = [(int(item.value) if item.value != None else 0) for item in array]
+ array = [(int(item.value) if item.value != None else 0)
+ for item in array]
temp = Js(numpy.array(array, dtype=numpy.uint8))
temp.put('length', Js(len(array)))
return temp
- elif isinstance(a,PyObjectWrapper): # object (ArrayBuffer, etc)
+ elif isinstance(a, PyObjectWrapper): # object (ArrayBuffer, etc)
if len(arguments) > 1:
offset = int(arguments[1].value)
else:
@@ -36,8 +40,9 @@ def Uint8Array():
if len(arguments) > 2:
length = int(arguments[2].value)
else:
- length = int(len(a.obj)-offset)
- array = numpy.frombuffer(a.obj, dtype=numpy.uint8, count=length, offset=offset)
+ length = int(len(a.obj) - offset)
+ array = numpy.frombuffer(
+ a.obj, dtype=numpy.uint8, count=length, offset=offset)
temp = Js(array)
temp.put('length', Js(length))
temp.buff = array
@@ -46,20 +51,29 @@ def Uint8Array():
temp.put('length', Js(0))
return temp
+
Uint8Array.create = Uint8Array
Uint8Array.own['length']['value'] = Js(3)
-Uint8Array.define_own_property('prototype', {'value': Uint8ArrayPrototype,
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+Uint8Array.define_own_property(
+ 'prototype', {
+ 'value': Uint8ArrayPrototype,
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ })
-Uint8ArrayPrototype.define_own_property('constructor', {'value': Uint8Array,
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
+Uint8ArrayPrototype.define_own_property(
+ 'constructor', {
+ 'value': Uint8Array,
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+ })
-Uint8ArrayPrototype.define_own_property('BYTES_PER_ELEMENT', {'value': Js(1),
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+Uint8ArrayPrototype.define_own_property('BYTES_PER_ELEMENT', {
+ 'value': Js(1),
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+})
diff --git a/js2py/constructors/jsuint8clampedarray.py b/js2py/constructors/jsuint8clampedarray.py
index 973e38ef..7b5e350b 100644
--- a/js2py/constructors/jsuint8clampedarray.py
+++ b/js2py/constructors/jsuint8clampedarray.py
@@ -9,26 +9,30 @@
@Js
def Uint8ClampedArray():
- TypedArray = (PyJsInt8Array,PyJsUint8Array,PyJsUint8ClampedArray,PyJsInt16Array,PyJsUint16Array,PyJsInt32Array,PyJsUint32Array,PyJsFloat32Array,PyJsFloat64Array)
+ TypedArray = (PyJsInt8Array, PyJsUint8Array, PyJsUint8ClampedArray,
+ PyJsInt16Array, PyJsUint16Array, PyJsInt32Array,
+ PyJsUint32Array, PyJsFloat32Array, PyJsFloat64Array)
a = arguments[0]
- if isinstance(a, PyJsNumber): # length
+ if isinstance(a, PyJsNumber): # length
length = a.to_uint32()
- if length!=a.value:
+ if length != a.value:
raise MakeError('RangeError', 'Invalid array length')
temp = Js(numpy.full(length, 0, dtype=numpy.uint8), Clamped=True)
temp.put('length', a)
return temp
- elif isinstance(a, PyJsString): # object (string)
+ elif isinstance(a, PyJsString): # object (string)
temp = Js(numpy.array(list(a.value), dtype=numpy.uint8), Clamped=True)
temp.put('length', Js(len(list(a.value))))
return temp
- elif isinstance(a, PyJsArray) or isinstance(a,TypedArray) or isinstance(a,PyJsArrayBuffer): # object (Array, TypedArray)
+ elif isinstance(a, PyJsArray) or isinstance(a, TypedArray) or isinstance(
+ a, PyJsArrayBuffer): # object (Array, TypedArray)
array = a.to_list()
- array = [(int(item.value) if item.value != None else 0) for item in array]
+ array = [(int(item.value) if item.value != None else 0)
+ for item in array]
temp = Js(numpy.array(array, dtype=numpy.uint8), Clamped=True)
temp.put('length', Js(len(array)))
return temp
- elif isinstance(a,PyObjectWrapper): # object (ArrayBuffer, etc)
+ elif isinstance(a, PyObjectWrapper): # object (ArrayBuffer, etc)
if len(arguments) > 1:
offset = int(arguments[1].value)
else:
@@ -36,8 +40,9 @@ def Uint8ClampedArray():
if len(arguments) > 2:
length = int(arguments[2].value)
else:
- length = int(len(a.obj)-offset)
- array = numpy.frombuffer(a.obj, dtype=numpy.uint8, count=length, offset=offset)
+ length = int(len(a.obj) - offset)
+ array = numpy.frombuffer(
+ a.obj, dtype=numpy.uint8, count=length, offset=offset)
temp = Js(array, Clamped=True)
temp.put('length', Js(length))
temp.buff = array
@@ -46,20 +51,29 @@ def Uint8ClampedArray():
temp.put('length', Js(0))
return temp
+
Uint8ClampedArray.create = Uint8ClampedArray
Uint8ClampedArray.own['length']['value'] = Js(3)
-Uint8ClampedArray.define_own_property('prototype', {'value': Uint8ClampedArrayPrototype,
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+Uint8ClampedArray.define_own_property(
+ 'prototype', {
+ 'value': Uint8ClampedArrayPrototype,
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ })
-Uint8ClampedArrayPrototype.define_own_property('constructor', {'value': Uint8ClampedArray,
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
+Uint8ClampedArrayPrototype.define_own_property(
+ 'constructor', {
+ 'value': Uint8ClampedArray,
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+ })
-Uint8ClampedArrayPrototype.define_own_property('BYTES_PER_ELEMENT', {'value': Js(1),
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
+Uint8ClampedArrayPrototype.define_own_property('BYTES_PER_ELEMENT', {
+ 'value': Js(1),
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+})
diff --git a/js2py/constructors/time_helpers.py b/js2py/constructors/time_helpers.py
index 493ac726..f3d21f3e 100644
--- a/js2py/constructors/time_helpers.py
+++ b/js2py/constructors/time_helpers.py
@@ -6,17 +6,21 @@
try:
from tzlocal import get_localzone
LOCAL_ZONE = get_localzone()
-except: # except all problems...
- warnings.warn('Please install or fix tzlocal library (pip install tzlocal) in order to make Date object work better. Otherwise I will assume DST is in effect all the time')
+except: # except all problems...
+ warnings.warn(
+ 'Please install or fix tzlocal library (pip install tzlocal) in order to make Date object work better. Otherwise I will assume DST is in effect all the time'
+ )
+
class LOCAL_ZONE:
@staticmethod
def dst(*args):
return 1
+
from js2py.base import MakeError
CUM = (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365)
msPerDay = 86400000
-msPerYear = int(86400000*365.242)
+msPerYear = int(86400000 * 365.242)
msPerSecond = 1000
msPerMinute = 60000
msPerHour = 3600000
@@ -24,66 +28,74 @@ def dst(*args):
MinutesPerHour = 60
SecondsPerMinute = 60
NaN = float('nan')
-LocalTZA = - time.timezone * msPerSecond
-
-
-
+LocalTZA = -time.timezone * msPerSecond
def DaylightSavingTA(t):
if t is NaN:
return t
try:
- return int(LOCAL_ZONE.dst(datetime.datetime.utcfromtimestamp(t//1000)).seconds)*1000
+ return int(
+ LOCAL_ZONE.dst(datetime.datetime(1970, 1, 1) + datetime.timedelta(
+ seconds=t // 1000)).seconds) * 1000
except:
- warnings.warn('Invalid datetime date, assumed DST time, may be inaccurate...', Warning)
+ warnings.warn(
+ 'Invalid datetime date, assumed DST time, may be inaccurate...',
+ Warning)
return 1
#raise MakeError('TypeError', 'date not supported by python.datetime. I will solve it in future versions')
+
def GetTimeZoneName(t):
- return time.tzname[DaylightSavingTA(t)>0]
+ return time.tzname[DaylightSavingTA(t) > 0]
+
def LocalToUTC(t):
return t - LocalTZA - DaylightSavingTA(t - LocalTZA)
+
def UTCToLocal(t):
return t + LocalTZA + DaylightSavingTA(t)
def Day(t):
- return t//86400000
+ return t // 86400000
def TimeWithinDay(t):
- return t%86400000
+ return t % 86400000
+
def DaysInYear(y):
- if y%4:
+ if y % 4:
return 365
- elif y%100:
+ elif y % 100:
return 366
- elif y%400:
+ elif y % 400:
return 365
else:
return 366
def DayFromYear(y):
- return 365 * (y-1970) + (y-1969)//4 -(y-1901)//100 + (y-1601)//400
+ return 365 * (y - 1970) + (y - 1969) // 4 - (y - 1901) // 100 + (
+ y - 1601) // 400
+
def TimeFromYear(y):
return 86400000 * DayFromYear(y)
+
def YearFromTime(t):
- guess = 1970 - t//31556908800 # msPerYear
+ guess = 1970 - t // 31556908800 # msPerYear
gt = TimeFromYear(guess)
- if gt<=t:
- while gt<=t:
+ if gt <= t:
+ while gt <= t:
guess += 1
gt = TimeFromYear(guess)
- return guess-1
+ return guess - 1
else:
- while gt>t:
+ while gt > t:
guess -= 1
gt = TimeFromYear(guess)
return guess
@@ -92,73 +104,83 @@ def YearFromTime(t):
def DayWithinYear(t):
return Day(t) - DayFromYear(YearFromTime(t))
+
def InLeapYear(t):
y = YearFromTime(t)
- if y%4:
+ if y % 4:
return 0
- elif y%100:
+ elif y % 100:
return 1
- elif y%400:
+ elif y % 400:
return 0
else:
return 1
+
def MonthFromTime(t):
day = DayWithinYear(t)
leap = InLeapYear(t)
- if day<31:
+ if day < 31:
return 0
day -= leap
- if day<59:
+ if day < 59:
return 1
- elif day<90:
+ elif day < 90:
return 2
- elif day<120:
+ elif day < 120:
return 3
- elif day<151:
+ elif day < 151:
return 4
- elif day<181:
+ elif day < 181:
return 5
- elif day<212:
+ elif day < 212:
return 6
- elif day<243:
+ elif day < 243:
return 7
- elif day<273:
+ elif day < 273:
return 8
- elif day<304:
+ elif day < 304:
return 9
- elif day<334:
+ elif day < 334:
return 10
else:
return 11
+
def DateFromTime(t):
mon = MonthFromTime(t)
day = DayWithinYear(t)
- return day-CUM[mon] - (1 if InLeapYear(t) and mon>=2 else 0) + 1
+ return day - CUM[mon] - (1 if InLeapYear(t) and mon >= 2 else 0) + 1
+
def WeekDay(t):
# 0 == sunday
return (Day(t) + 4) % 7
+
def msFromTime(t):
return t % 1000
+
def SecFromTime(t):
- return (t//1000) % 60
+ return (t // 1000) % 60
+
def MinFromTime(t):
- return (t//60000) % 60
+ return (t // 60000) % 60
+
def HourFromTime(t):
- return (t//3600000) % 24
+ return (t // 3600000) % 24
+
-def MakeTime (hour, Min, sec, ms):
+def MakeTime(hour, Min, sec, ms):
# takes PyJs objects and returns t
- if not (hour.is_finite() and Min.is_finite() and sec.is_finite() and ms.is_finite()):
+ if not (hour.is_finite() and Min.is_finite() and sec.is_finite()
+ and ms.is_finite()):
return NaN
h, m, s, milli = hour.to_int(), Min.to_int(), sec.to_int(), ms.to_int()
- return h*3600000 + m*60000 + s*1000 + milli
+ return h * 3600000 + m * 60000 + s * 1000 + milli
def MakeDay(year, month, date):
@@ -166,19 +188,20 @@ def MakeDay(year, month, date):
if not (year.is_finite() and month.is_finite() and date.is_finite()):
return NaN
y, m, dt = year.to_int(), month.to_int(), date.to_int()
- y += m//12
+ y += m // 12
mn = m % 12
- d = DayFromYear(y) + CUM[mn] + dt - 1 + (1 if DaysInYear(y)==366 and mn>=2 else 0)
- return d # ms per day
+ d = DayFromYear(y) + CUM[mn] + dt - 1 + (1 if DaysInYear(y) == 366
+ and mn >= 2 else 0)
+ return d # ms per day
+
def MakeDate(day, time):
- return 86400000*day + time
+ return 86400000 * day + time
def TimeClip(t):
- if t!=t or abs(t)==float('inf'):
+ if t != t or abs(t) == float('inf'):
return NaN
- if abs(t) > 8.64 *10**15:
+ if abs(t) > 8.64 * 10**15:
return NaN
return int(t)
-
diff --git a/js2py/es6/__init__.py b/js2py/es6/__init__.py
index 45c4a5dc..4a58d3f0 100644
--- a/js2py/es6/__init__.py
+++ b/js2py/es6/__init__.py
@@ -2,11 +2,14 @@
babel = None
babelPresetEs2015 = None
+
def js6_to_js5(code):
global INITIALISED, babel, babelPresetEs2015
if not INITIALISED:
import signal, warnings, time
- warnings.warn('\nImporting babel.py for the first time - this can take some time. \nPlease note that currently Javascript 6 in Js2Py is unstable and slow. Use only for tiny scripts!')
+ warnings.warn(
+ '\nImporting babel.py for the first time - this can take some time. \nPlease note that currently Javascript 6 in Js2Py is unstable and slow. Use only for tiny scripts!'
+ )
from .babel import babel as _babel
babel = _babel.Object.babel
@@ -16,9 +19,14 @@ def js6_to_js5(code):
try:
babel.transform('warmup', {'presets': {}})
signal.alarm(2)
- def kill_it(a,b): raise KeyboardInterrupt('Better work next time!')
+
+ def kill_it(a, b):
+ raise KeyboardInterrupt('Better work next time!')
+
signal.signal(signal.SIGALRM, kill_it)
- babel.transform('stuckInALoop', {'presets': babelPresetEs2015}).code
+ babel.transform('stuckInALoop', {
+ 'presets': babelPresetEs2015
+ }).code
for n in range(3):
time.sleep(1)
except:
@@ -26,7 +34,8 @@ def kill_it(a,b): raise KeyboardInterrupt('Better work next time!')
INITIALISED = True
return babel.transform(code, {'presets': babelPresetEs2015}).code
-if __name__=='__main__':
+
+if __name__ == '__main__':
print(js6_to_js5('obj={}; obj.x = function() {return () => this}'))
print()
- print(js6_to_js5('const a = 1;'))
\ No newline at end of file
+ print(js6_to_js5('const a = 1;'))
diff --git a/js2py/evaljs.py b/js2py/evaljs.py
index 7839d610..f4649c4d 100644
--- a/js2py/evaljs.py
+++ b/js2py/evaljs.py
@@ -9,19 +9,26 @@
import hashlib
import codecs
-__all__ = ['EvalJs', 'translate_js', 'import_js', 'eval_js', 'translate_file', 'eval_js6', 'translate_js6', 'run_file', 'disable_pyimport', 'get_file_contents', 'write_file_contents']
+__all__ = [
+ 'EvalJs', 'translate_js', 'import_js', 'eval_js', 'translate_file',
+ 'eval_js6', 'translate_js6', 'run_file', 'disable_pyimport',
+ 'get_file_contents', 'write_file_contents'
+]
DEBUG = False
+
def disable_pyimport():
import pyjsparser.parser
pyjsparser.parser.ENABLE_PYIMPORT = False
+
def path_as_local(path):
if os.path.isabs(path):
return path
# relative to cwd
return os.path.join(os.getcwd(), path)
+
def import_js(path, lib_name, globals):
"""Imports from javascript source file.
globals is your globals()"""
@@ -46,9 +53,10 @@ def write_file_contents(path_or_file, contents):
if hasattr(path_or_file, 'write'):
path_or_file.write(contents)
else:
- with open(path_as_local(path_or_file), 'w') as f:
+ with codecs.open(path_as_local(path_or_file), "w", "utf-8") as f:
f.write(contents)
+
def translate_file(input_path, output_path):
'''
Translates input JS file to python and saves the it to the output path.
@@ -66,16 +74,13 @@ def translate_file(input_path, output_path):
py_code = translate_js(js)
lib_name = os.path.basename(output_path).split('.')[0]
- head = '__all__ = [%s]\n\n# Don\'t look below, you will not understand this Python code :) I don\'t.\n\n' % repr(lib_name)
+ head = '__all__ = [%s]\n\n# Don\'t look below, you will not understand this Python code :) I don\'t.\n\n' % repr(
+ lib_name)
tail = '\n\n# Add lib to the module scope\n%s = var.to_python()' % lib_name
out = head + py_code + tail
write_file_contents(output_path, out)
-
-
-
-
def run_file(path_or_file, context=None):
''' Context must be EvalJS object. Runs given path as a JS program. Returns (eval_value, context).
'''
@@ -87,7 +92,6 @@ def run_file(path_or_file, context=None):
return eval_value, context
-
def eval_js(js):
"""Just like javascript eval. Translates javascript to python,
executes and returns python object.
@@ -110,42 +114,60 @@ def eval_js(js):
e = EvalJs()
return e.eval(js)
+
def eval_js6(js):
+ """Just like eval_js but with experimental support for js6 via babel."""
return eval_js(js6_to_js5(js))
def translate_js6(js):
+ """Just like translate_js but with experimental support for js6 via babel."""
return translate_js(js6_to_js5(js))
-
class EvalJs(object):
"""This class supports continuous execution of javascript under same context.
- >>> js = EvalJs()
- >>> js.execute('var a = 10;function f(x) {return x*x};')
- >>> js.f(9)
+ >>> ctx = EvalJs()
+ >>> ctx.execute('var a = 10;function f(x) {return x*x};')
+ >>> ctx.f(9)
81
- >>> js.a
+ >>> ctx.a
10
context is a python dict or object that contains python variables that should be available to JavaScript
For example:
- >>> js = EvalJs({'a': 30})
- >>> js.execute('var x = a')
- >>> js.x
+ >>> ctx = EvalJs({'a': 30})
+ >>> ctx.execute('var x = a')
+ >>> ctx.x
30
+ You can enable JS require function via enable_require. With this feature enabled you can use js modules
+ from npm, for example:
+ >>> ctx = EvalJs(enable_require=True)
+ >>> ctx.execute("var esprima = require('esprima');")
+ >>> ctx.execute("esprima.parse('var a = 1')")
+
You can run interactive javascript console with console method!"""
- def __init__(self, context={}):
+
+ def __init__(self, context={}, enable_require=False):
self.__dict__['_context'] = {}
- exec(DEFAULT_HEADER, self._context)
+ exec (DEFAULT_HEADER, self._context)
self.__dict__['_var'] = self._context['var'].to_python()
+
+ if enable_require:
+ def _js_require_impl(npm_module_name):
+ from .node_import import require
+ from .base import to_python
+ return require(to_python(npm_module_name), context=self._context)
+ setattr(self._var, 'require', _js_require_impl)
+
if not isinstance(context, dict):
try:
context = context.__dict__
except:
- raise TypeError('context has to be either a dict or have __dict__ attr')
+ raise TypeError(
+ 'context has to be either a dict or have __dict__ attr')
for k, v in six.iteritems(context):
setattr(self._var, k, v)
@@ -170,13 +192,15 @@ def execute(self, js=None, use_compilation_plan=False):
try:
compiled = cache[hashkey]
except KeyError:
- code = translate_js(js, '', use_compilation_plan=use_compilation_plan)
- compiled = cache[hashkey] = compile(code, '', 'exec')
- exec(compiled, self._context)
+ code = translate_js(
+ js, '', use_compilation_plan=use_compilation_plan)
+ compiled = cache[hashkey] = compile(code, '',
+ 'exec')
+ exec (compiled, self._context)
def eval(self, expression, use_compilation_plan=False):
"""evaluates expression in current context and returns its value"""
- code = 'PyJsEvalResult = eval(%s)'%json.dumps(expression)
+ code = 'PyJsEvalResult = eval(%s)' % json.dumps(expression)
self.execute(code, use_compilation_plan=use_compilation_plan)
return self['PyJsEvalResult']
@@ -187,11 +211,15 @@ def execute_debug(self, js):
"""
code = translate_js(js, '')
# make sure you have a temp folder:
- filename = 'temp' + os.sep + '_' + hashlib.md5(code).hexdigest() + '.py'
+ filename = 'temp' + os.sep + '_' + hashlib.md5(
+ code.encode("utf-8")).hexdigest() + '.py'
try:
with open(filename, mode='w') as f:
f.write(code)
- execfile(filename, self._context)
+ with open(filename, "r") as f:
+ pyCode = compile(f.read(), filename, 'exec')
+ exec(pyCode, self._context)
+
except Exception as err:
raise err
finally:
@@ -206,10 +234,14 @@ def eval_debug(self, expression):
as opposed to the (faster) self.execute method, you can use your regular debugger
to set breakpoints and inspect the generated python code
"""
- code = 'PyJsEvalResult = eval(%s)'%json.dumps(expression)
+ code = 'PyJsEvalResult = eval(%s)' % json.dumps(expression)
self.execute_debug(code)
return self['PyJsEvalResult']
+ @property
+ def context(self):
+ return self._context
+
def __getattr__(self, var):
return getattr(self._var, var)
@@ -238,21 +270,5 @@ def console(self):
if DEBUG:
sys.stderr.write(traceback.format_exc())
else:
- sys.stderr.write('EXCEPTION: '+str(e)+'\n')
+ sys.stderr.write('EXCEPTION: ' + str(e) + '\n')
time.sleep(0.01)
-
-
-
-
-#print x
-
-
-
-if __name__=='__main__':
- #with open('C:\Users\Piotrek\Desktop\esprima.js', 'rb') as f:
- # x = f.read()
- e = EvalJs()
- e.execute('square(x)')
- #e.execute(x)
- e.console()
-
diff --git a/js2py/host/console.py b/js2py/host/console.py
index 822219ea..269eef3d 100644
--- a/js2py/host/console.py
+++ b/js2py/host/console.py
@@ -6,6 +6,10 @@ def console():
@Js
def log():
- print(arguments[0])
+ print(" ".join(repr(element) for element in arguments.to_list()))
-console.put('log', log)
\ No newline at end of file
+console.put('log', log)
+console.put('debug', log)
+console.put('info', log)
+console.put('warn', log)
+console.put('error', log)
diff --git a/js2py/host/dom/constants.py b/js2py/host/dom/constants.py
deleted file mode 100644
index b4ed209b..00000000
--- a/js2py/host/dom/constants.py
+++ /dev/null
@@ -1,47 +0,0 @@
-from js2py.base import *
-
-def _get_conts(idl):
- def is_valid(c):
- try:
- exec(c)
- return 1
- except:
- pass
- return '\n'.join(filter(is_valid, (' '.join(e.strip(' ;').split()[-3:]) for e in idl.splitlines())))
-
-
-default_attrs = {'writable':True, 'enumerable':True, 'configurable':True}
-
-
-def compose_prototype(Class, attrs=default_attrs):
- prototype = Class()
- for i in dir(Class):
- e = getattr(Class, i)
- if hasattr(e, '__func__'):
- temp = PyJsFunction(e.__func__, FunctionPrototype)
- attrs = {k:v for k,v in attrs.iteritems()}
- attrs['value'] = temp
- prototype.define_own_property(i, attrs)
- return prototype
-
-
-# Error codes
-
-INDEX_SIZE_ERR = 1
-DOMSTRING_SIZE_ERR = 2
-HIERARCHY_REQUEST_ERR = 3
-WRONG_DOCUMENT_ERR = 4
-INVALID_CHARACTER_ERR = 5
-NO_DATA_ALLOWED_ERR = 6
-NO_MODIFICATION_ALLOWED_ERR = 7
-NOT_FOUND_ERR = 8
-NOT_SUPPORTED_ERR = 9
-INUSE_ATTRIBUTE_ERR = 10
-INVALID_STATE_ERR = 11
-SYNTAX_ERR = 12
-INVALID_MODIFICATION_ERR = 13
-NAMESPACE_ERR = 14
-INVALID_ACCESS_ERR = 15
-VALIDATION_ERR = 16
-TYPE_MISMATCH_ERR = 17
-
diff --git a/js2py/host/dom/interface.py b/js2py/host/dom/interface.py
deleted file mode 100644
index 5e3e4a64..00000000
--- a/js2py/host/dom/interface.py
+++ /dev/null
@@ -1,73 +0,0 @@
-from StringIO import StringIO
-from constants import *
-from bs4 import BeautifulSoup
-from js2py.base import *
-try:
- import lxml
- def parse(source):
- return BeautifulSoup(source, 'lxml')
-except:
- def parse(source):
- return BeautifulSoup(source)
-
-
-
-
-
-
-
-x = '''
-
-
- | Shady Grove |
- Aeolian |
-
-
- | Over the River, Charlie |
- Dorian |
-
-
-
'''
-
-
-
-class DOM(PyJs):
- prototype = ObjectPrototype
- def __init__(self):
- self.own = {}
-
- def readonly(self, name, val):
- self.define_own_property(name, {'writable':False, 'enumerable':False, 'configurable':False, 'value': Js(val)})
-
-
-
-# DOMStringList
-
-class DOMStringListPrototype(DOM):
- Class = 'DOMStringListPrototype'
-
- def contains(element):
- return element.to_string().value in this._string_list
-
- def item(index):
- return this._string_list[index.to_int()] if 0<=index.to_int()36:
+ if r < 2 or r > 36:
return NaN
- if r!=16:
+ if r != 16:
strip_prefix = False
else:
r = 10
if strip_prefix:
- if len(string)>=2 and string[:2] in ('0x', '0X'):
+ if len(string) >= 2 and string[:2] in ('0x', '0X'):
string = string[2:]
r = 16
n = 0
- num = 0
- while n4: # cant be a number anymore
+ if failed > 4: # cant be a number anymore
break
length += 1
if num is None:
return NaN
- return sign*float(string[:max_len])
+ return sign * float(string[:max_len])
+
@Js
def isNaN(number):
@@ -71,6 +134,7 @@ def isNaN(number):
return true
return false
+
@Js
def isFinite(number):
num = number.to_number()
@@ -79,7 +143,34 @@ def isFinite(number):
return true
-#todo URI handling!
+# todo test them properly
+
+
+@Js
+def escape(text):
+ return quote(text.to_string().value)
+
+
+@Js
+def unescape(text):
+ return unquote(text.to_string().value)
+
+
+@Js
+def encodeURI(text):
+ return quote(text.to_string().value, safe='~@#$&()*!+=:;,.?/\'')
+
+
+@Js
+def decodeURI(text):
+ return unquote(text.to_string().value)
+@Js
+def encodeURIComponent(text):
+ return quote(text.to_string().value, safe='~()*!.\'')
+
+@Js
+def decodeURIComponent(text):
+ return unquote(text.to_string().value)
diff --git a/js2py/internals/__init__.py b/js2py/internals/__init__.py
index e69de29b..5473e711 100644
--- a/js2py/internals/__init__.py
+++ b/js2py/internals/__init__.py
@@ -0,0 +1 @@
+from .seval import eval_js_vm
\ No newline at end of file
diff --git a/js2py/internals/base.py b/js2py/internals/base.py
index 2e5fa704..938dec37 100644
--- a/js2py/internals/base.py
+++ b/js2py/internals/base.py
@@ -3,16 +3,18 @@
import datetime
-from desc import *
-from simplex import *
-from conversions import *
-import six
+from .desc import *
+from .simplex import *
+from .conversions import *
+
from pyjsparser import PyJsParser
-from itertools import izip
+import six
+if six.PY2:
+ from itertools import izip
+else:
+ izip = zip
-from conversions import *
-from simplex import *
@@ -39,17 +41,13 @@ def put_member(self, unconverted_prop, val):
return self.put(to_string(unconverted_prop), val)
def get(self, prop):
- print prop, self.TYPE, self.Class
- if self.Class == None:
- print self
- print self.own
- assert type(prop)==unicode
+ assert type(prop) == unicode
cand = self.get_property(prop)
if cand is None:
return undefined
if is_data_descriptor(cand):
return cand['value']
- if cand['get'].is_undefined():
+ if is_undefined(cand['get']):
return undefined
return cand['get'].call(self)
@@ -72,7 +70,7 @@ def put(self, prop, val, throw=False):
# takes py, returns none
if not self.can_put(prop):
if throw:
- raise TypeError()
+ raise MakeError('TypeError', 'Could not define own property')
return
own_desc = self.get_own_property(prop)
if is_data_descriptor(own_desc):
@@ -80,20 +78,24 @@ def put(self, prop, val, throw=False):
return
desc = self.get_property(prop)
if is_accessor_descriptor(desc):
- desc['set'].call(self, (val,)) # calling setter on own or inherited element
+ desc['set'].call(
+ self, (val, )) # calling setter on own or inherited element
else: # new property
- self.own[prop] = {'value': val,
- 'writable': True,
- 'configurable': True,
- 'enumerable': True}
+ self.own[prop] = {
+ 'value': val,
+ 'writable': True,
+ 'configurable': True,
+ 'enumerable': True
+ }
def can_put(self, prop): # to check
- assert type(prop) == unicode
+ assert type(prop) == unicode, type(prop)
# takes py returns py
desc = self.get_own_property(prop)
if desc: # if we have this property
if is_accessor_descriptor(desc):
- return desc['set'].is_callable() # Check if setter method is defined
+ return is_callable(
+ desc['set']) # Check if setter method is defined
else: # data desc
return desc['writable']
if self.prototype is None:
@@ -102,7 +104,7 @@ def can_put(self, prop): # to check
if inherited is None:
return self.extensible
if is_accessor_descriptor(inherited):
- return not inherited['set'].is_undefined()
+ return not is_undefined(inherited['set'])
elif self.extensible:
return inherited['writable'] # weird...
return False
@@ -122,7 +124,7 @@ def delete(self, prop, throw=False):
del self.own[prop]
return True
if throw:
- raise TypeError()
+ raise MakeError('TypeError', 'Could not define own property')
return False
def default_value(self, hint=None):
@@ -135,9 +137,12 @@ def default_value(self, hint=None):
cand = method.call(self, ())
if is_primitive(cand):
return cand
- raise MakeError('TypeError', 'Cannot convert object to primitive value')
+ raise MakeError('TypeError',
+ 'Cannot convert object to primitive value')
- def define_own_property(self, prop, desc, throw): # Internal use only. External through Object
+ def define_own_property(
+ self, prop, desc,
+ throw): # Internal use only. External through Object
assert type(prop) == unicode
# takes Py, returns Py
# prop must be a Py string. Desc is either a descriptor or accessor.
@@ -148,21 +153,26 @@ def define_own_property(self, prop, desc, throw): # Internal use only. External
if not current: # We are creating a new OWN property
if not extensible:
if throw:
- raise TypeError()
+ raise MakeError('TypeError',
+ 'Could not define own property')
return False
# extensible must be True
if is_data_descriptor(desc) or is_generic_descriptor(desc):
- DEFAULT_DATA_DESC = {'value': undefined, # undefined
- 'writable': False,
- 'enumerable': False,
- 'configurable': False}
+ DEFAULT_DATA_DESC = {
+ 'value': undefined, # undefined
+ 'writable': False,
+ 'enumerable': False,
+ 'configurable': False
+ }
DEFAULT_DATA_DESC.update(desc)
self.own[prop] = DEFAULT_DATA_DESC
else:
- DEFAULT_ACCESSOR_DESC = {'get': undefined, # undefined
- 'set': undefined, # undefined
- 'enumerable': False,
- 'configurable': False}
+ DEFAULT_ACCESSOR_DESC = {
+ 'get': undefined, # undefined
+ 'set': undefined, # undefined
+ 'enumerable': False,
+ 'configurable': False
+ }
DEFAULT_ACCESSOR_DESC.update(desc)
self.own[prop] = DEFAULT_ACCESSOR_DESC
return True
@@ -173,11 +183,14 @@ def define_own_property(self, prop, desc, throw): # Internal use only. External
if not configurable: # Prevent changing params
if desc.get('configurable'):
if throw:
- raise TypeError()
+ raise MakeError('TypeError',
+ 'Could not define own property')
return False
- if 'enumerable' in desc and desc['enumerable'] != current['enumerable']:
+ if 'enumerable' in desc and desc['enumerable'] != current[
+ 'enumerable']:
if throw:
- raise TypeError()
+ raise MakeError('TypeError',
+ 'Could not define own property')
return False
if is_generic_descriptor(desc):
pass
@@ -185,7 +198,8 @@ def define_own_property(self, prop, desc, throw): # Internal use only. External
# we want to change the current type of property
if not configurable:
if throw:
- raise TypeError()
+ raise MakeError('TypeError',
+ 'Could not define own property')
return False
if is_data_descriptor(current): # from data to setter
del current['value']
@@ -201,38 +215,47 @@ def define_own_property(self, prop, desc, throw): # Internal use only. External
if not configurable:
if not current['writable'] and desc.get('writable'):
if throw:
- raise TypeError()
+ raise MakeError('TypeError',
+ 'Could not define own property')
return False
- if not current['writable'] and 'value' in desc and current['value'] != desc['value']:
+ if not current['writable'] and 'value' in desc and current[
+ 'value'] != desc['value']:
if throw:
- raise TypeError()
+ raise MakeError('TypeError',
+ 'Could not define own property')
return False
elif is_accessor_descriptor(current) and is_accessor_descriptor(desc):
if not configurable:
if 'set' in desc and desc['set'] != current['set']:
if throw:
- raise TypeError()
+ raise MakeError('TypeError',
+ 'Could not define own property')
return False
if 'get' in desc and desc['get'] != current['get']:
if throw:
- raise TypeError()
+ raise MakeError('TypeError',
+ 'Could not define own property')
return False
current.update(desc)
return True
- def create(self, *args):
+ def create(self, args, space):
'''Generally not a constructor, raise an error'''
raise MakeError('TypeError', '%s is not a constructor' % self.Class)
-def get_member(self, prop, space): # general member getter, prop has to be unconverted prop. it is it can be any value
+def get_member(
+ self, prop, space
+): # general member getter, prop has to be unconverted prop. it is it can be any value
typ = type(self)
if typ not in PRIMITIVES: # most likely getter for object
- return self.get_member(prop) # <- object can implement this to support faster prop getting. ex array.
+ return self.get_member(
+ prop
+ ) # <- object can implement this to support faster prop getting. ex array.
elif typ == unicode: # then probably a String
- if type(prop)==float:
+ if type(prop) == float and is_finite(prop):
index = int(prop)
- if index==prop and 0 <= index < len(self):
+ if index == prop and 0 <= index < len(self):
return self[index]
s_prop = to_string(prop)
if s_prop == 'length':
@@ -250,9 +273,11 @@ def get_member(self, prop, space): # general member getter, prop has to be uncon
elif typ == bool:
return space.BooleanPrototype.get(to_string(prop))
elif typ is UNDEFINED_TYPE:
- raise MakeError('TypeError', "Cannot read property '%s' of undefined" % prop)
+ raise MakeError('TypeError',
+ "Cannot read property '%s' of undefined" % prop)
elif typ is NULL_TYPE:
- raise MakeError('TypeError', "Cannot read property '%s' of null" % prop)
+ raise MakeError('TypeError',
+ "Cannot read property '%s' of null" % prop)
else:
raise RuntimeError('Unknown type! - ' + repr(typ))
@@ -279,16 +304,19 @@ def get_member_dot(self, prop, space):
elif typ == bool:
return space.BooleanPrototype.get(prop)
elif typ in (UNDEFINED_TYPE, NULL_TYPE):
- raise MakeError('TypeError', "Cannot read property '%s' of undefined" % prop)
+ raise MakeError('TypeError',
+ "Cannot read property '%s' of undefined" % prop)
else:
raise RuntimeError('Unknown type! - ' + repr(typ))
# Object
+
class PyJsObject(PyJs):
TYPE = 'Object'
Class = 'Object'
+
def __init__(self, prototype=None):
self.prototype = prototype
self.own = {}
@@ -296,22 +324,45 @@ def __init__(self, prototype=None):
def _init(self, props, vals):
i = 0
for prop, kind in props:
- if prop in self.own: # just check... probably will not happen very often.
+ if prop in self.own: # just check... probably will not happen very often.
if is_data_descriptor(self.own[prop]):
- if kind!='i':
- raise MakeError('SyntaxError', 'Invalid object initializer! Duplicate property name "%s"' % prop)
+ if kind != 'i':
+ raise MakeError(
+ 'SyntaxError',
+ 'Invalid object initializer! Duplicate property name "%s"'
+ % prop)
else:
- if kind=='i' or (kind=='g' and 'get' in self.own[prop]) or (kind=='s' and 'set' in self.own[prop]):
- raise MakeError('SyntaxError', 'Invalid object initializer! Duplicate setter/getter of prop: "%s"' % prop)
-
- if kind == 'i': # init
- self.own[prop] = {'value': vals[i], 'writable': True, 'enumerable': True, 'configurable': True}
- elif kind == 'g': # get
- self.define_own_property(prop, {'get': vals[i], 'enumerable': True, 'configurable': True}, False)
- elif kind == 's': # get
- self.define_own_property(prop, {'get': vals[i], 'enumerable': True, 'configurable': True}, False)
+ if kind == 'i' or (kind == 'g' and 'get' in self.own[prop]
+ ) or (kind == 's'
+ and 'set' in self.own[prop]):
+ raise MakeError(
+ 'SyntaxError',
+ 'Invalid object initializer! Duplicate setter/getter of prop: "%s"'
+ % prop)
+
+ if kind == 'i': # init
+ self.own[prop] = {
+ 'value': vals[i],
+ 'writable': True,
+ 'enumerable': True,
+ 'configurable': True
+ }
+ elif kind == 'g': # get
+ self.define_own_property(prop, {
+ 'get': vals[i],
+ 'enumerable': True,
+ 'configurable': True
+ }, False)
+ elif kind == 's': # get
+ self.define_own_property(prop, {
+ 'get': vals[i],
+ 'enumerable': True,
+ 'configurable': True
+ }, False)
else:
- raise RuntimeError('Invalid property kind - %s. Expected one of i, g, s.' % repr(kind))
+ raise RuntimeError(
+ 'Invalid property kind - %s. Expected one of i, g, s.' %
+ repr(kind))
i += 1
def _set_props(self, prop_descs):
@@ -319,33 +370,43 @@ def _set_props(self, prop_descs):
self.define_own_property(prop, desc)
-
-
# Array
+
# todo Optimise Array - extremely slow due to index conversions from str to int and back etc.
# solution - make get and put methods callable with any type of prop and handle conversions from inside
# if not array then use to_string(prop). In array if prop is integer then just use it
# also consider removal of these stupid writable, enumerable etc for ints.
class PyJsArray(PyJs):
Class = 'Array'
+
def __init__(self, length, prototype=None):
self.prototype = prototype
- self.own = {'length' : {'value': float(length), 'writable': True,
- 'enumerable': False, 'configurable': False}}
+ self.own = {
+ 'length': {
+ 'value': float(length),
+ 'writable': True,
+ 'enumerable': False,
+ 'configurable': False
+ }
+ }
def _init(self, elements):
for i, ele in enumerate(elements):
if ele is None: continue
- self.own[unicode(i)] = {'value': ele, 'writable': True,
- 'enumerable': True, 'configurable': True}
+ self.own[unicode(i)] = {
+ 'value': ele,
+ 'writable': True,
+ 'enumerable': True,
+ 'configurable': True
+ }
def put(self, prop, val, throw=False):
assert type(val) != int
# takes py, returns none
if not self.can_put(prop):
if throw:
- raise TypeError()
+ raise MakeError('TypeError', 'Could not define own property')
return
own_desc = self.get_own_property(prop)
if is_data_descriptor(own_desc):
@@ -353,57 +414,66 @@ def put(self, prop, val, throw=False):
return
desc = self.get_property(prop)
if is_accessor_descriptor(desc):
- desc['set'].call(self, (val,)) # calling setter on own or inherited element
+ desc['set'].call(
+ self, (val, )) # calling setter on own or inherited element
else: # new property
- self.define_own_property(prop, {'value': val,
- 'writable': True,
- 'configurable': True,
- 'enumerable': True}, False)
-
+ self.define_own_property(
+ prop, {
+ 'value': val,
+ 'writable': True,
+ 'configurable': True,
+ 'enumerable': True
+ }, False)
def define_own_property(self, prop, desc, throw):
assert type(desc.get('value')) != int
old_len_desc = self.get_own_property('length')
old_len = old_len_desc['value'] # value is js type so convert to py.
- if prop=='length':
+ if prop == 'length':
if 'value' not in desc:
return PyJs.define_own_property(self, prop, desc, False)
- new_len = to_uint32(desc['value'])
- if new_len!=to_number(desc['value']):
+ new_len = to_uint32(desc['value'])
+ if new_len != to_number(desc['value']):
raise MakeError('RangeError', 'Invalid range!')
- new_desc = dict((k,v) for k,v in six.iteritems(desc))
+ new_desc = dict((k, v) for k, v in six.iteritems(desc))
new_desc['value'] = float(new_len)
- if new_len>=old_len:
+ if new_len >= old_len:
return PyJs.define_own_property(self, prop, new_desc, False)
if not old_len_desc['writable']:
return False
- if 'writable' not in new_desc or new_desc['writable']==True:
+ if 'writable' not in new_desc or new_desc['writable'] == True:
new_writable = True
else:
new_writable = False
new_desc['writable'] = True
if not PyJs.define_own_property(self, prop, new_desc, False):
return False
- if new_len30*len(self.own):
+ if old_len > 30 * len(self.own):
for ele in self.own.keys():
- if ele.isdigit() and int(ele)>=new_len:
- if not self.delete(ele): # if failed to delete set len to current len and reject.
- new_desc['value'] = old_len+1.
+ if ele.isdigit() and int(ele) >= new_len:
+ if not self.delete(
+ ele
+ ): # if failed to delete set len to current len and reject.
+ new_desc['value'] = old_len + 1.
if not new_writable:
new_desc['writable'] = False
- PyJs.define_own_property(self, prop, new_desc, False)
+ PyJs.define_own_property(
+ self, prop, new_desc, False)
return False
old_len = new_len
- else: # standard method
- while new_len=old_len and not old_len_desc['writable']:
+ if index >= old_len and not old_len_desc['writable']:
return False
if not PyJs.define_own_property(self, prop, desc, False):
return False
- if index>=old_len:
+ if index >= old_len:
old_len_desc['value'] = index + 1.
return True
else:
return PyJs.define_own_property(self, prop, desc, False)
def to_list(self):
- return [self.get(str(e)) for e in xrange(self.get('length').to_uint32())]
+ return [
+ self.get(str(e)) for e in xrange(self.get('length').to_uint32())
+ ]
# database with compiled patterns. Js pattern -> Py pattern.
REGEXP_DB = {}
+
class PyJsRegExp(PyJs):
Class = 'RegExp'
@@ -444,34 +517,62 @@ def __init__(self, body, flags, prototype=None):
comp = None
try:
# converting JS regexp pattern to Py pattern.
- possible_fixes = [
- (u'[]', u'[\0]'),
- (u'[^]', u'[^\0]'),
- (u'nofix1791', u'nofix1791')
- ]
+ possible_fixes = [(u'[]', u'[\0]'), (u'[^]', u'[^\0]'),
+ (u'nofix1791', u'nofix1791')]
reg = self.value
for fix, rep in possible_fixes:
comp = PyJsParser()._interpret_regexp(reg, flags)
#print 'reg -> comp', reg, '->', comp
try:
- self.pat = re.compile(comp, self.ignore_case | self.multiline)
+ self.pat = re.compile(
+ comp, self.ignore_case | self.multiline)
#print reg, '->', comp
break
except:
reg = reg.replace(fix, rep)
- # print 'Fix', fix, '->', rep, '=', reg
+ # print 'Fix', fix, '->', rep, '=', reg
else:
- raise
+ raise Exception()
REGEXP_DB[body, flags] = self.pat
except:
#print 'Invalid pattern...', self.value, comp
- raise MakeError('SyntaxError', 'Invalid RegExp pattern: %s -> %s'% (repr(self.value), repr(comp)))
+ raise MakeError(
+ 'SyntaxError',
+ 'Invalid RegExp pattern: %s -> %s' % (repr(self.value),
+ repr(comp)))
# now set own properties:
- self.own = {'source' : {'value': self.value, 'enumerable': False, 'writable': False, 'configurable': False},
- 'global' : {'value': self.glob, 'enumerable': False, 'writable': False, 'configurable': False},
- 'ignoreCase' : {'value': bool(self.ignore_case), 'enumerable': False, 'writable': False, 'configurable': False},
- 'multiline' : {'value': bool(self.multiline), 'enumerable': False, 'writable': False, 'configurable': False},
- 'lastIndex' : {'value': 0, 'enumerable': False, 'writable': True, 'configurable': False}}
+ self.own = {
+ 'source': {
+ 'value': self.value,
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ },
+ 'global': {
+ 'value': self.glob,
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ },
+ 'ignoreCase': {
+ 'value': bool(self.ignore_case),
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ },
+ 'multiline': {
+ 'value': bool(self.multiline),
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ },
+ 'lastIndex': {
+ 'value': 0.,
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': False
+ }
+ }
def match(self, string, pos):
'''string is of course a py string'''
@@ -481,6 +582,7 @@ def match(self, string, pos):
class PyJsError(PyJs):
Class = 'Error'
extensible = True
+
def __init__(self, message=None, prototype=None):
self.prototype = prototype
self.own = {}
@@ -489,10 +591,9 @@ def __init__(self, message=None, prototype=None):
self.own['message']['enumerable'] = False
-
class PyJsDate(PyJs):
Class = 'Date'
- UTCToLocal = None # todo UTC to local should be imported!
+ UTCToLocal = None # todo UTC to local should be imported!
def __init__(self, value, prototype=None):
self.value = value
@@ -501,10 +602,12 @@ def __init__(self, value, prototype=None):
# todo fix this problematic datetime part
def to_local_dt(self):
- return datetime.datetime.utcfromtimestamp(self.UTCToLocal(self.value)//1000)
+ return datetime.datetime(1970, 1, 1) + datetime.timedelta(
+ seconds=self.UTCToLocal(self.value) // 1000)
def to_utc_dt(self):
- return datetime.datetime.utcfromtimestamp(self.value//1000)
+ return datetime.datetime(1970, 1, 1) + datetime.timedelta(
+ seconds=self.value // 1000)
def local_strftime(self, pattern):
if self.value is NaN:
@@ -512,11 +615,16 @@ def local_strftime(self, pattern):
try:
dt = self.to_local_dt()
except:
- raise MakeError('TypeError', 'unsupported date range. Will fix in future versions')
+ raise MakeError(
+ 'TypeError',
+ 'unsupported date range. Will fix in future versions')
try:
return dt.strftime(pattern)
except:
- raise MakeError('TypeError', 'Could not generate date string from this date (limitations of python.datetime)')
+ raise MakeError(
+ 'TypeError',
+ 'Could not generate date string from this date (limitations of python.datetime)'
+ )
def utc_strftime(self, pattern):
if self.value is NaN:
@@ -524,11 +632,17 @@ def utc_strftime(self, pattern):
try:
dt = self.to_utc_dt()
except:
- raise MakeError('TypeError', 'unsupported date range. Will fix in future versions')
+ raise MakeError(
+ 'TypeError',
+ 'unsupported date range. Will fix in future versions')
try:
return dt.strftime(pattern)
except:
- raise MakeError('TypeError', 'Could not generate date string from this date (limitations of python.datetime)')
+ raise MakeError(
+ 'TypeError',
+ 'Could not generate date string from this date (limitations of python.datetime)'
+ )
+
# Scope class it will hold all the variables accessible to user
class Scope(PyJs):
@@ -548,13 +662,24 @@ def __init__(self, scope, space, parent=None):
"""Doc"""
self.space = space
self.prototype = parent
+ if type(scope) is not dict:
+ assert parent is not None, 'You initialised the WITH_SCOPE without a parent scope.'
+ self.own = scope
+ self.is_with_scope = True
+ else:
+ self.is_with_scope = False
if parent is None:
# global, top level scope
self.own = {}
for k, v in six.iteritems(scope):
# set all the global items
- self.define_own_property(k, {'value': v, 'configurable': False,
- 'writable': False, 'enumerable': False}, False)
+ self.define_own_property(
+ k, {
+ 'value': v,
+ 'configurable': False,
+ 'writable': False,
+ 'enumerable': False
+ }, False)
else:
# not global, less powerful but faster closure.
self.own = scope # simple dictionary which maps name directly to js object.
@@ -569,8 +694,13 @@ def register(self, var):
if var in self.own:
self.own[var]['configurable'] = False
else:
- self.define_own_property(var, {'value': undefined, 'configurable': False,
- 'writable': True, 'enumerable': True}, False)
+ self.define_own_property(
+ var, {
+ 'value': undefined,
+ 'configurable': False,
+ 'writable': True,
+ 'enumerable': True
+ }, False)
elif var not in self.own:
# define in local scope since it has not been defined yet
self.own[var] = undefined # default value
@@ -589,35 +719,48 @@ def put(self, var, val, throw=False):
if desc['writable']: # todo consider getters/setters
desc['value'] = val
else:
+ if self.is_with_scope:
+ if self.own.has_property(var):
+ return self.own.put(var, val, throw=throw)
+ else:
+ return self.prototype.put(var, val)
# trying to put in local scope
# we dont know yet in which scope we should place this var
- if var in self.own:
+ elif var in self.own:
self.own[var] = val
return val
else:
# try to put in the lower scope since we cant put in this one (var wasn't registered)
return self.prototype.put(var, val)
- def get(self, var, throw=True):
+ def get(self, var, throw=False):
if self.prototype is not None:
- # fast local scope
- cand = self.own.get(var)
+ if self.is_with_scope:
+ cand = None if not self.own.has_property(
+ var) else self.own.get(var)
+ else:
+ # fast local scope
+ cand = self.own.get(var)
if cand is None:
return self.prototype.get(var, throw)
return cand
# slow, global scope
if var not in self.own:
# try in ObjectPrototype...
- # if var in self.space.ObjectPrototype.own:
- # return self.space.ObjectPrototype.get(var)
+ if var in self.space.ObjectPrototype.own:
+ return self.space.ObjectPrototype.get(var)
if throw:
raise MakeError('ReferenceError', '%s is not defined' % var)
return undefined
- return self.own[var]['value'] # todo consider getters/setters
+ cand = self.own[var].get('value')
+ return cand if cand is not None else self.own[var]['get'].call(self)
def delete(self, var, throw=False):
if self.prototype is not None:
- if var in self.own:
+ if self.is_with_scope:
+ if self.own.has_property(var):
+ return self.own.delete(var)
+ elif var in self.own:
return False
return self.prototype.delete(var)
# we are in global scope here. Must exist and be configurable to delete
@@ -634,25 +777,40 @@ def delete(self, var, throw=False):
def get_new_arguments_obj(args, space):
obj = space.NewObject()
obj.Class = 'Arguments'
- obj.define_own_property('length', {'value': float(len(args)), 'writable': True, 'enumerable': False, 'configurable': True}, False)
+ obj.define_own_property(
+ 'length', {
+ 'value': float(len(args)),
+ 'writable': True,
+ 'enumerable': False,
+ 'configurable': True
+ }, False)
for i, e in enumerate(args):
obj.put(unicode(i), e)
return obj
-
#Function
class PyJsFunction(PyJs):
Class = 'Function'
source = '{ [native code] }'
IS_CONSTRUCTOR = True
- def __init__(self, code, ctx, params, name, space, is_declaration, definitions, prototype=None):
+ def __init__(self,
+ code,
+ ctx,
+ params,
+ name,
+ space,
+ is_declaration,
+ definitions,
+ prototype=None):
self.prototype = prototype
self.own = {}
self.code = code
- if type(self.code) == int: # just a label pointing to the beginning of the code.
+ if type(
+ self.code
+ ) == int: # just a label pointing to the beginning of the code.
self.is_native = False
else:
self.is_native = True # python function
@@ -672,35 +830,61 @@ def __init__(self, code, ctx, params, name, space, is_declaration, definitions,
self.is_declaration = is_declaration
#set own property length to the number of arguments
- self.own['length'] = {'value': len(params), 'writable': False, 'enumerable': False, 'configurable': False}
+ self.own['length'] = {
+ 'value': float(len(params)),
+ 'writable': False,
+ 'enumerable': False,
+ 'configurable': False
+ }
if name:
- self.own['name'] = {'value': name, 'writable': False, 'enumerable': False, 'configurable': True}
+ self.own['name'] = {
+ 'value': name,
+ 'writable': False,
+ 'enumerable': False,
+ 'configurable': True
+ }
if not self.is_native: # set prototype for user defined functions
# constructor points to this function
proto = space.NewObject()
- proto.own['constructor'] = {'value': self, 'writable': True, 'enumerable': False, 'configurable': True}
- self.own['prototype'] = {'value': proto, 'writable': True, 'enumerable': False, 'configurable': False}
+ proto.own['constructor'] = {
+ 'value': self,
+ 'writable': True,
+ 'enumerable': False,
+ 'configurable': True
+ }
+ self.own['prototype'] = {
+ 'value': proto,
+ 'writable': True,
+ 'enumerable': False,
+ 'configurable': False
+ }
# todo set up throwers on callee and arguments if in strict mode
-
def call(self, this, args=()):
''' Dont use this method from inside bytecode to call other bytecode. '''
if self.is_native:
- _args = SpaceTuple(args) # we have to do that unfortunately to pass all the necessary info to the funcs
+ _args = SpaceTuple(
+ args
+ ) # we have to do that unfortunately to pass all the necessary info to the funcs
_args.space = self.space
- return self.code(this, _args) # must return valid js object - undefined, null, float, unicode, bool, or PyJs
+ return self.code(
+ this, _args
+ ) # must return valid js object - undefined, null, float, unicode, bool, or PyJs
else:
- return self.space.exe._call(self, this, args) # will run inside bytecode
+ return self.space.exe._call(self, this,
+ args) # will run inside bytecode
def has_instance(self, other):
# I am not sure here so instanceof may not work lol.
if not is_object(other):
return False
proto = self.get('prototype')
- if not proto.is_object():
- raise MakeError('TypeError', 'Function has non-object prototype in instanceof check')
+ if not is_object(proto):
+ raise MakeError(
+ 'TypeError',
+ 'Function has non-object prototype in instanceof check')
while True:
other = other.prototype
if not other: # todo make sure that the condition is not None or null
@@ -719,17 +903,19 @@ def create(self, args, space):
return new
def _generate_my_context(self, this, args):
- my_ctx = Scope(dict(izip(self.params, args)), self.space, parent=self.ctx)
+ my_ctx = Scope(
+ dict(izip(self.params, args)), self.space, parent=self.ctx)
my_ctx.registers(self.definitions)
my_ctx.THIS_BINDING = this
if not self.arguments_in_params:
my_ctx.own['arguments'] = get_new_arguments_obj(args, self.space)
if not self.is_declaration and self.name and self.name not in my_ctx.own:
- my_ctx.own[self.name] = self # this should be immutable binding but come on!
+ my_ctx.own[
+ self.
+ name] = self # this should be immutable binding but come on!
return my_ctx
-
class SpaceTuple:
def __init__(self, tup):
self.tup = tup
@@ -742,4 +928,3 @@ def __getitem__(self, item):
def __iter__(self):
return iter(self.tup)
-
diff --git a/js2py/internals/byte_trans.py b/js2py/internals/byte_trans.py
index 590430e8..e32bcb1e 100644
--- a/js2py/internals/byte_trans.py
+++ b/js2py/internals/byte_trans.py
@@ -1,8 +1,8 @@
-from code import Code
-from simplex import MakeError
-from opcodes import *
-from operations import *
-from trans_utils import *
+from .code import Code
+from .simplex import MakeError
+from .opcodes import *
+from .operations import *
+from .trans_utils import *
SPECIAL_IDENTIFIERS = {'true', 'false', 'this'}
@@ -23,22 +23,20 @@ def __init__(self, exe):
self.states = []
-
def record_state(self):
- self.states.append((self.declared_continue_labels, self.declared_break_labels,
- self.implicit_breaks, self.implicit_continues,
- self.declared_vars, self.function_declaration_tape))
+ self.states.append(
+ (self.declared_continue_labels, self.declared_break_labels,
+ self.implicit_breaks, self.implicit_continues, self.declared_vars,
+ self.function_declaration_tape))
self.declared_continue_labels, self.declared_break_labels, \
self.implicit_breaks, self.implicit_continues, \
self.declared_vars, self.function_declaration_tape = {}, {}, [], [], [], []
-
def restore_state(self):
self.declared_continue_labels, self.declared_break_labels, \
self.implicit_breaks, self.implicit_continues, \
self.declared_vars, self.function_declaration_tape = self.states.pop()
-
def ArrayExpression(self, elements, **kwargs):
for e in elements:
if e is None:
@@ -46,7 +44,7 @@ def ArrayExpression(self, elements, **kwargs):
else:
self.emit(e)
self.emit('LOAD_ARRAY', len(elements))
-
+
def AssignmentExpression(self, operator, left, right, **kwargs):
operator = operator[:-1]
if left['type'] == 'MemberExpression':
@@ -61,36 +59,39 @@ def AssignmentExpression(self, operator, left, right, **kwargs):
else:
self.emit(right)
if operator:
- self.emit('STORE_MEMBER_DOT_OP', left['property']['name'], operator)
+ self.emit('STORE_MEMBER_DOT_OP', left['property']['name'],
+ operator)
else:
self.emit('STORE_MEMBER_DOT', left['property']['name'])
elif left['type'] == 'Identifier':
if left['name'] in SPECIAL_IDENTIFIERS:
- raise MakeError('SyntaxError', 'Invalid left-hand side in assignment')
+ raise MakeError('SyntaxError',
+ 'Invalid left-hand side in assignment')
self.emit(right)
if operator:
self.emit('STORE_OP', left['name'], operator)
else:
self.emit('STORE', left['name'])
else:
- raise MakeError('SyntaxError', 'Invalid left-hand side in assignment')
+ raise MakeError('SyntaxError',
+ 'Invalid left-hand side in assignment')
-
def BinaryExpression(self, operator, left, right, **kwargs):
self.emit(left)
self.emit(right)
self.emit('BINARY_OP', operator)
-
+
def BlockStatement(self, body, **kwargs):
self._emit_statement_list(body)
-
+
def BreakStatement(self, label, **kwargs):
if label is None:
self.emit('JUMP', self.implicit_breaks[-1])
else:
label = label.get('name')
if label not in self.declared_break_labels:
- raise MakeError('SyntaxError', 'Undefined label \'%s\'' % label)
+ raise MakeError('SyntaxError',
+ 'Undefined label \'%s\'' % label)
else:
self.emit('JUMP', self.declared_break_labels[label])
@@ -124,13 +125,13 @@ def CallExpression(self, callee, arguments, **kwargs):
self.emit('CALL')
else:
self.emit('CALL_NO_ARGS')
-
+
def ClassBody(self, body, **kwargs):
raise NotImplementedError('Not available in ECMA 5.1')
-
+
def ClassDeclaration(self, id, superClass, body, **kwargs):
raise NotImplementedError('Not available in ECMA 5.1')
-
+
def ClassExpression(self, id, superClass, body, **kwargs):
raise NotImplementedError('Classes not available in ECMA 5.1')
@@ -148,20 +149,21 @@ def ConditionalExpression(self, test, consequent, alternate, **kwargs):
self.emit(alternate)
# end of ?: statement
self.emit('LABEL', end)
-
+
def ContinueStatement(self, label, **kwargs):
if label is None:
self.emit('JUMP', self.implicit_continues[-1])
else:
label = label.get('name')
if label not in self.declared_continue_labels:
- raise MakeError('SyntaxError', 'Undefined label \'%s\'' % label)
+ raise MakeError('SyntaxError',
+ 'Undefined label \'%s\'' % label)
else:
self.emit('JUMP', self.declared_continue_labels[label])
-
+
def DebuggerStatement(self, **kwargs):
self.EmptyStatement(**kwargs)
-
+
def DoWhileStatement(self, body, test, **kwargs):
continue_label = self.exe.get_new_label()
break_label = self.exe.get_new_label()
@@ -181,9 +183,9 @@ def DoWhileStatement(self, body, test, **kwargs):
self.implicit_continues.pop()
self.implicit_breaks.pop()
- self.emit('JUMP', continue_label) # loop back
+ self.emit('JUMP', continue_label) # loop back
self.emit('LABEL', break_label)
-
+
def EmptyStatement(self, **kwargs):
# do nothing
pass
@@ -193,7 +195,7 @@ def ExpressionStatement(self, expression, **kwargs):
# pop the previous value and execute expression
self.emit('POP')
self.emit(expression)
-
+
def ForStatement(self, init, test, update, body, **kwargs):
continue_label = self.exe.get_new_label()
break_label = self.exe.get_new_label()
@@ -224,21 +226,63 @@ def ForStatement(self, init, test, update, body, **kwargs):
self.implicit_continues.pop()
self.implicit_breaks.pop()
- self.emit('JUMP', continue_label) # loop back
+ self.emit('JUMP', continue_label) # loop back
self.emit('LABEL', break_label)
-
+
def ForInStatement(self, left, right, body, **kwargs):
- print 'Sorry not available yet!'
-
+ # prepare the needed labels
+ body_start_label = self.exe.get_new_label()
+ continue_label = self.exe.get_new_label()
+ break_label = self.exe.get_new_label()
+
+ # prepare the name
+ if left['type'] == 'VariableDeclaration':
+ if len(left['declarations']) != 1:
+ raise MakeError(
+ 'SyntaxError',
+ ' Invalid left-hand side in for-in loop: Must have a single binding.'
+ )
+ self.emit(left)
+ name = left['declarations'][0]['id']['name']
+ elif left['type'] == 'Identifier':
+ name = left['name']
+ else:
+ raise MakeError('SyntaxError',
+ 'Invalid left-hand side in for-loop')
+
+ # prepare the iterable
+ self.emit(right)
+
+ # emit ForIn Opcode
+ self.emit('FOR_IN', name, body_start_label, continue_label,
+ break_label)
+
+ # a special continue position
+ self.emit('LABEL', continue_label)
+ self.emit('NOP')
+
+ self.emit('LABEL', body_start_label)
+ self.implicit_continues.append(continue_label)
+ self.implicit_breaks.append(break_label)
+ self.emit('LOAD_UNDEFINED')
+ self.emit(body)
+ self.implicit_continues.pop()
+ self.implicit_breaks.pop()
+ self.emit('NOP')
+ self.emit('LABEL', break_label)
+ self.emit('NOP')
+
def FunctionDeclaration(self, id, params, defaults, body, **kwargs):
if defaults:
raise NotImplementedError('Defaults not available in ECMA 5.1')
# compile function
- self.record_state() # cleans translator state and appends it to the stack so that it can be later restored
+ self.record_state(
+ ) # cleans translator state and appends it to the stack so that it can be later restored
function_start = self.exe.get_new_label()
function_declarations = self.exe.get_new_label()
- declarations_done = self.exe.get_new_label() # put jump to this place at the and of function tape!
+ declarations_done = self.exe.get_new_label(
+ ) # put jump to this place at the and of function tape!
function_end = self.exe.get_new_label()
# skip the function if encountered externally
@@ -266,7 +310,9 @@ def FunctionDeclaration(self, id, params, defaults, body, **kwargs):
name = id.get('name')
assert name is not None
self.declared_vars.append(name)
- self.function_declaration_tape.append(LOAD_FUNCTION(function_start, tuple(p['name'] for p in params), name, True, tuple(declared_vars)))
+ self.function_declaration_tape.append(
+ LOAD_FUNCTION(function_start, tuple(p['name'] for p in params),
+ name, True, tuple(declared_vars)))
self.function_declaration_tape.append(STORE(name))
self.function_declaration_tape.append(POP())
@@ -275,10 +321,12 @@ def FunctionExpression(self, id, params, defaults, body, **kwargs):
raise NotImplementedError('Defaults not available in ECMA 5.1')
# compile function
- self.record_state() # cleans translator state and appends it to the stack so that it can be later restored
+ self.record_state(
+ ) # cleans translator state and appends it to the stack so that it can be later restored
function_start = self.exe.get_new_label()
function_declarations = self.exe.get_new_label()
- declarations_done = self.exe.get_new_label() # put jump to this place at the and of function tape!
+ declarations_done = self.exe.get_new_label(
+ ) # put jump to this place at the and of function tape!
function_end = self.exe.get_new_label()
# skip the function if encountered externally
@@ -304,20 +352,20 @@ def FunctionExpression(self, id, params, defaults, body, **kwargs):
# create function object and append to stack
name = id.get('name') if id else None
- self.emit('LOAD_FUNCTION', function_start, tuple(p['name'] for p in params), name, False, tuple(declared_vars))
-
+ self.emit('LOAD_FUNCTION', function_start,
+ tuple(p['name'] for p in params), name, False,
+ tuple(declared_vars))
-
def Identifier(self, name, **kwargs):
- if name=='true':
+ if name == 'true':
self.emit('LOAD_BOOLEAN', 1)
- elif name=='false':
+ elif name == 'false':
self.emit('LOAD_BOOLEAN', 0)
- elif name=='undefined':
+ elif name == 'undefined':
self.emit('LOAD_UNDEFINED')
else:
self.emit('LOAD', name)
-
+
def IfStatement(self, test, consequent, alternate, **kwargs):
alt = self.exe.get_new_label()
end = self.exe.get_new_label()
@@ -334,10 +382,10 @@ def IfStatement(self, test, consequent, alternate, **kwargs):
# end of if statement
self.emit('LABEL', end)
-
def LabeledStatement(self, label, body, **kwargs):
label = label['name']
- if body['type'] in ('WhileStatement', 'DoWhileStatement', 'ForStatement', 'ForInStatement'):
+ if body['type'] in ('WhileStatement', 'DoWhileStatement',
+ 'ForStatement', 'ForInStatement'):
# Continue label available... Simply take labels defined by the loop.
# It is important that they request continue label first
self.declared_continue_labels[label] = self.exe._label_count + 1
@@ -353,7 +401,6 @@ def LabeledStatement(self, label, body, **kwargs):
self.emit('LABEL', lbl)
del self.declared_break_labels[label]
-
def Literal(self, value, **kwargs):
if value is None:
self.emit('LOAD_NULL')
@@ -395,7 +442,7 @@ def MemberExpression(self, computed, object, property, **kwargs):
else:
self.emit(object)
self.emit('LOAD_MEMBER_DOT', property['name'])
-
+
def NewExpression(self, callee, arguments, **kwargs):
self.emit(callee)
if arguments:
@@ -407,39 +454,43 @@ def NewExpression(self, callee, arguments, **kwargs):
else:
self.emit('NEW_NO_ARGS')
-
def ObjectExpression(self, properties, **kwargs):
data = []
for prop in properties:
self.emit(prop['value'])
if prop['computed']:
- raise NotImplementedError('ECMA 5.1 does not support computed object properties!')
+ raise NotImplementedError(
+ 'ECMA 5.1 does not support computed object properties!')
data.append((to_key(prop['key']), prop['kind'][0]))
self.emit('LOAD_OBJECT', tuple(data))
-
+
def Program(self, body, **kwargs):
+ old_tape_len = len(self.exe.tape)
self.emit('LOAD_UNDEFINED')
self.emit(body)
# add function tape !
- self.exe.tape = self.function_declaration_tape + self.exe.tape
-
+ self.exe.tape = self.exe.tape[:old_tape_len] + self.function_declaration_tape + self.exe.tape[old_tape_len:]
+
def Pyimport(self, imp, **kwargs):
- raise NotImplementedError('Not available for bytecode interpreter yet, use the Js2Py translator.')
-
- def Property(self, kind, key, computed, value, method, shorthand, **kwargs):
+ raise NotImplementedError(
+ 'Not available for bytecode interpreter yet, use the Js2Py translator.'
+ )
+
+ def Property(self, kind, key, computed, value, method, shorthand,
+ **kwargs):
raise NotImplementedError('Not available in ECMA 5.1')
-
+
def RestElement(self, argument, **kwargs):
raise NotImplementedError('Not available in ECMA 5.1')
-
+
def ReturnStatement(self, argument, **kwargs):
- self.emit('POP') # pop result of expression statements
+ self.emit('POP') # pop result of expression statements
if argument is None:
self.emit('LOAD_UNDEFINED')
else:
self.emit(argument)
self.emit('RETURN')
-
+
def SequenceExpression(self, expressions, **kwargs):
for e in expressions:
self.emit(e)
@@ -448,7 +499,7 @@ def SequenceExpression(self, expressions, **kwargs):
def SwitchCase(self, test, consequent, **kwargs):
raise NotImplementedError('Already implemented in SwitchStatement')
-
+
def SwitchStatement(self, discriminant, cases, **kwargs):
self.emit(discriminant)
labels = [self.exe.get_new_label() for case in cases]
@@ -477,16 +528,15 @@ def SwitchStatement(self, discriminant, cases, **kwargs):
self.emit('LABEL', end_of_switch)
-
def ThisExpression(self, **kwargs):
self.emit('LOAD_THIS')
-
+
def ThrowStatement(self, argument, **kwargs):
# throw with the empty stack
self.emit('POP')
self.emit(argument)
self.emit('THROW')
-
+
def TryStatement(self, block, handler, finalizer, **kwargs):
try_label = self.exe.get_new_label()
catch_label = self.exe.get_new_label()
@@ -497,17 +547,22 @@ def TryStatement(self, block, handler, finalizer, **kwargs):
# try block
self.emit('LABEL', try_label)
+ self.emit('LOAD_UNDEFINED')
self.emit(block)
- self.emit('NOP') # needed to distinguish from break/continue vs some internal jumps
+ self.emit(
+ 'NOP'
+ ) # needed to distinguish from break/continue vs some internal jumps
# catch block
self.emit('LABEL', catch_label)
+ self.emit('LOAD_UNDEFINED')
if handler:
self.emit(handler['body'])
self.emit('NOP')
# finally block
self.emit('LABEL', finally_label)
+ self.emit('LOAD_UNDEFINED')
if finalizer:
self.emit(finalizer)
self.emit('NOP')
@@ -515,17 +570,20 @@ def TryStatement(self, block, handler, finalizer, **kwargs):
self.emit('LABEL', end_label)
# give life to the code
- self.emit('TRY_CATCH_FINALLY', try_label, catch_label, handler['param']['name'] if handler else None, finally_label, bool(finalizer), end_label)
-
+ self.emit('TRY_CATCH_FINALLY', try_label, catch_label,
+ handler['param']['name'] if handler else None, finally_label,
+ bool(finalizer), end_label)
def UnaryExpression(self, operator, argument, **kwargs):
- if operator == 'typeof' and argument['type']=='Identifier': # todo fix typeof
+ if operator == 'typeof' and argument[
+ 'type'] == 'Identifier': # todo fix typeof
self.emit('TYPEOF', argument['name'])
elif operator == 'delete':
if argument['type'] == 'MemberExpression':
self.emit(argument['object'])
if argument['property']['type'] == 'Identifier':
- self.emit('LOAD_STRING', unicode(argument['property']['name']))
+ self.emit('LOAD_STRING',
+ unicode(argument['property']['name']))
else:
self.emit(argument['property'])
self.emit('DELETE_MEMBER')
@@ -537,7 +595,8 @@ def UnaryExpression(self, operator, argument, **kwargs):
self.emit(argument)
self.emit('UNARY_OP', operator)
else:
- raise MakeError('SyntaxError', 'Unknown unary operator %s' % operator)
+ raise MakeError('SyntaxError',
+ 'Unknown unary operator %s' % operator)
def UpdateExpression(self, operator, argument, prefix, **kwargs):
incr = int(operator == "++")
@@ -555,21 +614,22 @@ def UpdateExpression(self, operator, argument, prefix, **kwargs):
name = to_key(argument)
self.emit('POSTFIX', post, incr, name)
else:
- raise MakeError('SyntaxError', 'Invalid left-hand side in assignment')
+ raise MakeError('SyntaxError',
+ 'Invalid left-hand side in assignment')
-
def VariableDeclaration(self, declarations, kind, **kwargs):
if kind != 'var':
- raise NotImplementedError('Only var variable declaration is supported by ECMA 5.1')
+ raise NotImplementedError(
+ 'Only var variable declaration is supported by ECMA 5.1')
for d in declarations:
self.emit(d)
def LexicalDeclaration(self, declarations, kind, **kwargs):
raise NotImplementedError('Not supported by ECMA 5.1')
-
+
def VariableDeclarator(self, id, init, **kwargs):
name = id['name']
- if name in SPECIAL_IDENTIFIERS:
+ if name in SPECIAL_IDENTIFIERS:
raise MakeError('Invalid left-hand side in assignment')
self.declared_vars.append(name)
if init is not None:
@@ -593,13 +653,25 @@ def WhileStatement(self, test, body, **kwargs):
self.implicit_continues.pop()
self.implicit_breaks.pop()
- self.emit('JUMP', continue_label) # loop back
+ self.emit('JUMP', continue_label) # loop back
self.emit('LABEL', break_label)
-
-
def WithStatement(self, object, body, **kwargs):
- raise NotImplementedError('I am too tired to think about this crazy statement now')
+ beg_label = self.exe.get_new_label()
+ end_label = self.exe.get_new_label()
+ # scope
+ self.emit(object)
+
+ # now the body
+ self.emit('JUMP', end_label)
+ self.emit('LABEL', beg_label)
+ self.emit('LOAD_UNDEFINED')
+ self.emit(body)
+ self.emit('NOP')
+ self.emit('LABEL', end_label)
+
+ # with statement implementation
+ self.emit('WITH', beg_label, end_label)
def _emit_statement_list(self, statements):
for statement in statements:
@@ -614,8 +686,10 @@ def emit(self, what, *args):
else:
return getattr(self, what['type'])(**what)
+
import os, codecs
+
def path_as_local(path):
if os.path.isabs(path):
return path
@@ -631,11 +705,11 @@ def get_file_contents(path_or_file):
js = f.read()
return js
+
def main():
from space import Space
import fill_space
-
from pyjsparser import parse
import json
a = ByteCodeGenerator(Code())
@@ -646,7 +720,8 @@ def main():
a.exe.space = s
s.exe = a.exe
con = get_file_contents('internals/esprima.js')
- d = parse(con+(''';JSON.stringify(exports.parse(%s), 4, 4)''' % json.dumps(con)))
+ d = parse(con + (
+ ''';JSON.stringify(exports.parse(%s), 4, 4)''' % json.dumps(con)))
# d = parse('''
# function x(n) {
# log(n)
@@ -661,22 +736,18 @@ def main():
#
# }
a.emit(d)
- print a.declared_vars
- print a.exe.tape
- print len(a.exe.tape)
-
+ print(a.declared_vars)
+ print(a.exe.tape)
+ print(len(a.exe.tape))
a.exe.compile()
def log(this, args):
- print args[0]
+ print(args[0])
return 999
-
- print a.exe.run(a.exe.space.GlobalObj)
+ print(a.exe.run(a.exe.space.GlobalObj))
-if __name__=='__main__':
+if __name__ == '__main__':
main()
-
-
diff --git a/js2py/internals/code.py b/js2py/internals/code.py
index 7921543c..9af0e602 100644
--- a/js2py/internals/code.py
+++ b/js2py/internals/code.py
@@ -1,14 +1,17 @@
-from opcodes import *
-from space import *
-from base import *
+from .opcodes import *
+from .space import *
+from .base import *
+
class Code:
'''Can generate, store and run sequence of ops representing js code'''
- def __init__(self, is_strict=False):
+
+ def __init__(self, is_strict=False, debug_mode=False):
self.tape = []
self.compiled = False
self.label_locs = None
self.is_strict = is_strict
+ self.debug_mode = debug_mode
self.contexts = []
self.current_ctx = None
@@ -20,6 +23,10 @@ def __init__(self, is_strict=False):
self.GLOBAL_THIS = None
self.space = None
+ # dbg
+ self.ctx_depth = 0
+
+
def get_new_label(self):
self._label_count += 1
return self._label_count
@@ -28,10 +35,10 @@ def emit(self, op_code, *args):
''' Adds op_code with specified args to tape '''
self.tape.append(OP_CODES[op_code](*args))
- def compile(self):
+ def compile(self, start_loc=0):
''' Records locations of labels and compiles the code '''
self.label_locs = {} if self.label_locs is None else self.label_locs
- loc = 0
+ loc = start_loc
while loc < len(self.tape):
if type(self.tape[loc]) == LABEL:
self.label_locs[self.tape[loc].num] = loc
@@ -50,7 +57,7 @@ def _call(self, func, this, args):
old_curr_ctx = self.current_ctx
self.contexts = [FakeCtx()]
- self.return_locs = [len(self.tape)] # target line after return
+ self.return_locs = [len(self.tape)] # target line after return
# prepare my ctx
my_ctx = func._generate_my_context(this, args)
@@ -72,31 +79,57 @@ def execute_fragment_under_context(self, ctx, start_label, end_label):
# 0=normal, 1=return, 2=jump_outside, 3=errors
# execute_fragment_under_context returns:
# (return_value, typ, return_value/jump_loc/py_error)
- # ctx.stack must be len 1 and its always empty after the call.
+ # IMPARTANT: It is guaranteed that the length of the ctx.stack is unchanged.
'''
old_curr_ctx = self.current_ctx
+ self.ctx_depth += 1
+ old_stack_len = len(ctx.stack)
+ old_ret_len = len(self.return_locs)
+ old_ctx_len = len(self.contexts)
try:
self.current_ctx = ctx
- return self._execute_fragment_under_context(ctx, start_label, end_label)
+ return self._execute_fragment_under_context(
+ ctx, start_label, end_label)
except JsException as err:
+ if self.debug_mode:
+ self._on_fragment_exit("js errors")
+ # undo the things that were put on the stack (if any) to ensure a proper error recovery
+ del ctx.stack[old_stack_len:]
+ del self.return_locs[old_ret_len:]
+ del self.contexts[old_ctx_len :]
return undefined, 3, err
finally:
+ self.ctx_depth -= 1
self.current_ctx = old_curr_ctx
+ assert old_stack_len == len(ctx.stack)
+
+ def _get_dbg_indent(self):
+ return self.ctx_depth * ' '
+
+ def _on_fragment_exit(self, mode):
+ print(self._get_dbg_indent() + 'ctx exit (%s)' % mode)
def _execute_fragment_under_context(self, ctx, start_label, end_label):
start, end = self.label_locs[start_label], self.label_locs[end_label]
-
+ initial_len = len(ctx.stack)
loc = start
entry_level = len(self.contexts)
-
+ # for e in self.tape[start:end]:
+ # print e
+ if self.debug_mode:
+ print(self._get_dbg_indent() + 'ctx entry (from:%d, to:%d)' % (start, end))
while loc < len(self.tape):
- #print loc, self.tape[loc]
if len(self.contexts) == entry_level and loc >= end:
+ if self.debug_mode:
+ self._on_fragment_exit('normal')
assert loc == end
- assert len(ctx.stack) == 1
- return ctx.stack.pop(), 0, None # means normal return
+ delta_stack = len(ctx.stack) - initial_len
+ assert delta_stack == +1, 'Stack change must be equal to +1! got %d' % delta_stack
+ return ctx.stack.pop(), 0, None # means normal return
# execute instruction
+ if self.debug_mode:
+ print(self._get_dbg_indent() + str(loc), self.tape[loc])
status = self.tape[loc].eval(ctx)
# check status for special actions
@@ -106,16 +139,19 @@ def _execute_fragment_under_context(self, ctx, start_label, end_label):
if len(self.contexts) == entry_level:
# check if jumped outside of the fragment and break if so
if not start <= loc < end:
- assert len(ctx.stack) == 1
+ if self.debug_mode:
+ self._on_fragment_exit('jump outside loc:%d label:%d' % (loc, status))
+ delta_stack = len(ctx.stack) - initial_len
+ assert delta_stack == +1, 'Stack change must be equal to +1! got %d' % delta_stack
return ctx.stack.pop(), 2, status # jump outside
continue
- elif len(status)==2: # a call or a return!
+ elif len(status) == 2: # a call or a return!
# call: (new_ctx, func_loc_label_num)
if status[0] is not None:
# append old state to the stack
self.contexts.append(ctx)
- self.return_locs.append(loc+1)
+ self.return_locs.append(loc + 1)
# set new state
loc = self.label_locs[status[1]]
ctx = status[0]
@@ -125,8 +161,12 @@ def _execute_fragment_under_context(self, ctx, start_label, end_label):
# return: (None, None)
else:
if len(self.contexts) == entry_level:
- assert len(ctx.stack) == 1
- return undefined, 1, ctx.stack.pop() # return signal
+ if self.debug_mode:
+ self._on_fragment_exit('return')
+ delta_stack = len(ctx.stack) - initial_len
+ assert delta_stack == +1, 'Stack change must be equal to +1! got %d' % delta_stack
+ return undefined, 1, ctx.stack.pop(
+ ) # return signal
return_value = ctx.stack.pop()
ctx = self.contexts.pop()
self.current_ctx = ctx
@@ -136,6 +176,8 @@ def _execute_fragment_under_context(self, ctx, start_label, end_label):
continue
# next instruction
loc += 1
+ if self.debug_mode:
+ self._on_fragment_exit('internal error - unexpected end of tape, will crash')
assert False, 'Remember to add NOP at the end!'
def run(self, ctx, starting_loc=0):
@@ -143,7 +185,8 @@ def run(self, ctx, starting_loc=0):
self.current_ctx = ctx
while loc < len(self.tape):
# execute instruction
- #print loc, self.tape[loc]
+ if self.debug_mode:
+ print(loc, self.tape[loc])
status = self.tape[loc].eval(ctx)
# check status for special actions
@@ -152,12 +195,12 @@ def run(self, ctx, starting_loc=0):
loc = self.label_locs[status]
continue
- elif len(status)==2: # a call or a return!
+ elif len(status) == 2: # a call or a return!
# call: (new_ctx, func_loc_label_num)
if status[0] is not None:
# append old state to the stack
self.contexts.append(ctx)
- self.return_locs.append(loc+1)
+ self.return_locs.append(loc + 1)
# set new state
loc = self.label_locs[status[1]]
ctx = status[0]
@@ -178,6 +221,7 @@ def run(self, ctx, starting_loc=0):
assert len(ctx.stack) == 1, ctx.stack
return ctx.stack.pop()
+
class FakeCtx(object):
def __init__(self):
- self.stack = []
\ No newline at end of file
+ self.stack = []
diff --git a/js2py/internals/constructors/jsarray.py b/js2py/internals/constructors/jsarray.py
index 83250fa9..23364ce4 100644
--- a/js2py/internals/constructors/jsarray.py
+++ b/js2py/internals/constructors/jsarray.py
@@ -2,19 +2,21 @@
from ..func_utils import *
-
def Array(this, args):
return ArrayConstructor(args, args.space)
def ArrayConstructor(args, space):
- if len(args)==1:
+ if len(args) == 1:
l = get_arg(args, 0)
if type(l) == float:
- if to_uint32(l)==l:
+ if to_uint32(l) == l:
return space.NewArray(l)
else:
- raise MakeError('RangeError', 'Invalid length specified for Array constructor (must be uint32)')
+ raise MakeError(
+ 'RangeError',
+ 'Invalid length specified for Array constructor (must be uint32)'
+ )
else:
return space.ConstructArray([l])
else:
@@ -23,5 +25,4 @@ def ArrayConstructor(args, space):
def isArray(this, args):
x = get_arg(args, 0)
- return is_object(x) and x.Class==u'Array'
-
+ return is_object(x) and x.Class == u'Array'
diff --git a/js2py/internals/constructors/jsboolean.py b/js2py/internals/constructors/jsboolean.py
index 01c3f3b9..17025d9f 100644
--- a/js2py/internals/constructors/jsboolean.py
+++ b/js2py/internals/constructors/jsboolean.py
@@ -2,7 +2,6 @@
from ..func_utils import *
-
def Boolean(this, args):
return to_boolean(get_arg(args, 0))
diff --git a/js2py/internals/constructors/jsconsole.py b/js2py/internals/constructors/jsconsole.py
new file mode 100644
index 00000000..6840ba70
--- /dev/null
+++ b/js2py/internals/constructors/jsconsole.py
@@ -0,0 +1,11 @@
+from __future__ import unicode_literals
+
+from js2py.internals.conversions import *
+from js2py.internals.func_utils import *
+
+
+class ConsoleMethods:
+ def log(this, args):
+ x = ' '.join(to_string(e) for e in args)
+ print(x)
+ return undefined
diff --git a/js2py/internals/constructors/jsdate.py b/js2py/internals/constructors/jsdate.py
index 67055e2c..5aed830e 100644
--- a/js2py/internals/constructors/jsdate.py
+++ b/js2py/internals/constructors/jsdate.py
@@ -1,60 +1,73 @@
from ..base import *
from .time_helpers import *
-TZ_OFFSET = (time.altzone//3600)
+TZ_OFFSET = (time.altzone // 3600)
ABS_OFFSET = abs(TZ_OFFSET)
TZ_NAME = time.tzname[1]
ISO_FORMAT = '%s-%s-%sT%s:%s:%s.%sZ'
+
+
@Js
def Date(year, month, date, hours, minutes, seconds, ms):
return now().to_string()
+
Date.Class = 'Date'
+
def now():
- return PyJsDate(int(time.time()*1000), prototype=DatePrototype)
+ return PyJsDate(int(time.time() * 1000), prototype=DatePrototype)
@Js
-def UTC(year, month, date, hours, minutes, seconds, ms): # todo complete this
+def UTC(year, month, date, hours, minutes, seconds, ms): # todo complete this
args = arguments
y = args[0].to_number()
m = args[1].to_number()
l = len(args)
- dt = args[2].to_number() if l>2 else Js(1)
- h = args[3].to_number() if l>3 else Js(0)
- mi = args[4].to_number() if l>4 else Js(0)
- sec = args[5].to_number() if l>5 else Js(0)
- mili = args[6].to_number() if l>6 else Js(0)
- if not y.is_nan() and 0<=y.value<=99:
+ dt = args[2].to_number() if l > 2 else Js(1)
+ h = args[3].to_number() if l > 3 else Js(0)
+ mi = args[4].to_number() if l > 4 else Js(0)
+ sec = args[5].to_number() if l > 5 else Js(0)
+ mili = args[6].to_number() if l > 6 else Js(0)
+ if not y.is_nan() and 0 <= y.value <= 99:
y = y + Js(1900)
- t = TimeClip(MakeDate(MakeDay(y, m, dt), MakeTime(h, mi, sec, mili)))
- return PyJsDate(t, prototype=DatePrototype)
+ return TimeClip(MakeDate(MakeDay(y, m, dt), MakeTime(h, mi, sec, mili)))
+
@Js
def parse(string):
- return PyJsDate(TimeClip(parse_date(string.to_string().value)), prototype=DatePrototype)
+ return PyJsDate(
+ TimeClip(parse_date(string.to_string().value)),
+ prototype=DatePrototype)
+Date.define_own_property('now', {
+ 'value': Js(now),
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+})
-Date.define_own_property('now', {'value': Js(now),
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
+Date.define_own_property('parse', {
+ 'value': parse,
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+})
-Date.define_own_property('parse', {'value': parse,
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
+Date.define_own_property('UTC', {
+ 'value': UTC,
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+})
-Date.define_own_property('UTC', {'value': UTC,
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
class PyJsDate(PyJs):
Class = 'Date'
extensible = True
+
def __init__(self, value, prototype=None):
self.value = value
self.own = {}
@@ -62,10 +75,12 @@ def __init__(self, value, prototype=None):
# todo fix this problematic datetime part
def to_local_dt(self):
- return datetime.datetime.utcfromtimestamp(UTCToLocal(self.value)//1000)
+ return datetime.datetime(1970, 1, 1) + datetime.timedelta(
+ seconds=UTCToLocal(self.value) // 1000)
def to_utc_dt(self):
- return datetime.datetime.utcfromtimestamp(self.value//1000)
+ return datetime.datetime(1970, 1, 1) + datetime.timedelta(
+ seconds=self.value // 1000)
def local_strftime(self, pattern):
if self.value is NaN:
@@ -73,11 +88,16 @@ def local_strftime(self, pattern):
try:
dt = self.to_local_dt()
except:
- raise MakeError('TypeError', 'unsupported date range. Will fix in future versions')
+ raise MakeError(
+ 'TypeError',
+ 'unsupported date range. Will fix in future versions')
try:
return dt.strftime(pattern)
except:
- raise MakeError('TypeError', 'Could not generate date string from this date (limitations of python.datetime)')
+ raise MakeError(
+ 'TypeError',
+ 'Could not generate date string from this date (limitations of python.datetime)'
+ )
def utc_strftime(self, pattern):
if self.value is NaN:
@@ -85,28 +105,40 @@ def utc_strftime(self, pattern):
try:
dt = self.to_utc_dt()
except:
- raise MakeError('TypeError', 'unsupported date range. Will fix in future versions')
+ raise MakeError(
+ 'TypeError',
+ 'unsupported date range. Will fix in future versions')
try:
return dt.strftime(pattern)
except:
- raise MakeError('TypeError', 'Could not generate date string from this date (limitations of python.datetime)')
-
-
+ raise MakeError(
+ 'TypeError',
+ 'Could not generate date string from this date (limitations of python.datetime)'
+ )
-def parse_date(py_string): # todo support all date string formats
+def parse_date(py_string): # todo support all date string formats
try:
- dt = datetime.datetime.strptime(py_string, "%Y-%m-%dT%H:%M:%S.%fZ")
- return MakeDate(MakeDay(Js(dt.year), Js(dt.month-1), Js(dt.day)), MakeTime(Js(dt.hour), Js(dt.minute), Js(dt.second), Js(dt.microsecond//1000)))
+ try:
+ dt = datetime.datetime.strptime(py_string, "%Y-%m-%dT%H:%M:%S.%fZ")
+ except:
+ dt = datetime.datetime.strptime(py_string, "%Y-%m-%dT%H:%M:%SZ")
+ return MakeDate(
+ MakeDay(Js(dt.year), Js(dt.month - 1), Js(dt.day)),
+ MakeTime(
+ Js(dt.hour), Js(dt.minute), Js(dt.second),
+ Js(dt.microsecond // 1000)))
except:
- raise MakeError('TypeError', 'Could not parse date %s - unsupported date format. Currently only supported format is RFC3339 utc. Sorry!' % py_string)
-
+ raise MakeError(
+ 'TypeError',
+ 'Could not parse date %s - unsupported date format. Currently only supported format is RFC3339 utc. Sorry!'
+ % py_string)
def date_constructor(*args):
- if len(args)>=2:
+ if len(args) >= 2:
return date_constructor2(*args)
- elif len(args)==1:
+ elif len(args) == 1:
return date_constructor1(args[0])
else:
return date_constructor0()
@@ -118,7 +150,7 @@ def date_constructor0():
def date_constructor1(value):
v = value.to_primitive()
- if v._type()=='String':
+ if v._type() == 'String':
v = parse_date(v.value)
else:
v = v.to_int()
@@ -129,22 +161,25 @@ def date_constructor2(*args):
y = args[0].to_number()
m = args[1].to_number()
l = len(args)
- dt = args[2].to_number() if l>2 else Js(1)
- h = args[3].to_number() if l>3 else Js(0)
- mi = args[4].to_number() if l>4 else Js(0)
- sec = args[5].to_number() if l>5 else Js(0)
- mili = args[6].to_number() if l>6 else Js(0)
- if not y.is_nan() and 0<=y.value<=99:
+ dt = args[2].to_number() if l > 2 else Js(1)
+ h = args[3].to_number() if l > 3 else Js(0)
+ mi = args[4].to_number() if l > 4 else Js(0)
+ sec = args[5].to_number() if l > 5 else Js(0)
+ mili = args[6].to_number() if l > 6 else Js(0)
+ if not y.is_nan() and 0 <= y.value <= 99:
y = y + Js(1900)
- t = TimeClip(LocalToUTC(MakeDate(MakeDay(y, m, dt), MakeTime(h, mi, sec, mili))))
+ t = TimeClip(
+ LocalToUTC(MakeDate(MakeDay(y, m, dt), MakeTime(h, mi, sec, mili))))
return PyJsDate(t, prototype=DatePrototype)
+
Date.create = date_constructor
DatePrototype = PyJsDate(float('nan'), prototype=ObjectPrototype)
+
def check_date(obj):
- if obj.Class!='Date':
+ if obj.Class != 'Date':
raise MakeError('TypeError', 'this is not a Date object')
@@ -153,8 +188,10 @@ def toString():
check_date(this)
if this.value is NaN:
return 'Invalid Date'
- offset = (UTCToLocal(this.value) - this.value)//msPerHour
- return this.local_strftime('%a %b %d %Y %H:%M:%S GMT') + '%s00 (%s)' % (pad(offset, 2, True), GetTimeZoneName(this.value))
+ offset = (UTCToLocal(this.value) - this.value) // msPerHour
+ return this.local_strftime(
+ '%a %b %d %Y %H:%M:%S GMT') + '%s00 (%s)' % (pad(
+ offset, 2, True), GetTimeZoneName(this.value))
def toDateString():
check_date(this)
@@ -284,8 +321,7 @@ def getTimezoneOffset():
check_date(this)
if this.value is NaN:
return NaN
- return (this.value - UTCToLocal(this.value))//60000
-
+ return (this.value - UTCToLocal(this.value)) // 60000
def setTime(time):
check_date(this)
@@ -295,7 +331,8 @@ def setTime(time):
def setMilliseconds(ms):
check_date(this)
t = UTCToLocal(this.value)
- tim = MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms.to_int())
+ tim = MakeTime(
+ Js(HourFromTime(t)), Js(MinFromTime(t)), Js(SecFromTime(t)), ms)
u = TimeClip(LocalToUTC(MakeDate(Day(t), tim)))
this.value = u
return u
@@ -303,12 +340,165 @@ def setMilliseconds(ms):
def setUTCMilliseconds(ms):
check_date(this)
t = this.value
- tim = MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms.to_int())
+ tim = MakeTime(
+ Js(HourFromTime(t)), Js(MinFromTime(t)), Js(SecFromTime(t)), ms)
u = TimeClip(MakeDate(Day(t), tim))
this.value = u
return u
- # todo Complete all setters!
+ def setSeconds(sec, ms=None):
+ check_date(this)
+ t = UTCToLocal(this.value)
+ s = sec.to_number()
+ if not ms is None: milli = Js(msFromTime(t))
+ else: milli = ms.to_number()
+ date = MakeDate(
+ Day(t), MakeTime(Js(HourFromTime(t)), Js(MinFromTime(t)), s, milli))
+ u = TimeClip(LocalToUTC(date))
+ this.value = u
+ return u
+
+ def setUTCSeconds(sec, ms=None):
+ check_date(this)
+ t = this.value
+ s = sec.to_number()
+ if not ms is None: milli = Js(msFromTime(t))
+ else: milli = ms.to_number()
+ date = MakeDate(
+ Day(t), MakeTime(Js(HourFromTime(t)), Js(MinFromTime(t)), s, milli))
+ v = TimeClip(date)
+ this.value = v
+ return v
+
+ def setMinutes(min, sec=None, ms=None):
+ check_date(this)
+ t = UTCToLocal(this.value)
+ m = min.to_number()
+ if not sec is None: s = Js(SecFromTime(t))
+ else: s = sec.to_number()
+ if not ms is None: milli = Js(msFromTime(t))
+ else: milli = ms.to_number()
+ date = MakeDate(Day(t), MakeTime(Js(HourFromTime(t)), m, s, milli))
+ u = TimeClip(LocalToUTC(date))
+ this.value = u
+ return u
+
+ def setUTCMinutes(min, sec=None, ms=None):
+ check_date(this)
+ t = this.value
+ m = min.to_number()
+ if not sec is None: s = Js(SecFromTime(t))
+ else: s = sec.to_number()
+ if not ms is None: milli = Js(msFromTime(t))
+ else: milli = ms.to_number()
+ date = MakeDate(Day(t), MakeTime(Js(HourFromTime(t)), m, s, milli))
+ v = TimeClip(date)
+ this.value = v
+ return v
+
+ def setHours(hour, min=None, sec=None, ms=None):
+ check_date(this)
+ t = UTCToLocal(this.value)
+ h = hour.to_number()
+ if not min is None: m = Js(MinFromTime(t))
+ else: m = min.to_number()
+ if not sec is None: s = Js(SecFromTime(t))
+ else: s = sec.to_number()
+ if not ms is None: milli = Js(msFromTime(t))
+ else: milli = ms.to_number()
+ date = MakeDate(Day(t), MakeTime(h, m, s, milli))
+ u = TimeClip(LocalToUTC(date))
+ this.value = u
+ return u
+
+ def setUTCHours(hour, min=None, sec=None, ms=None):
+ check_date(this)
+ t = this.value
+ h = hour.to_number()
+ if not min is None: m = Js(MinFromTime(t))
+ else: m = min.to_number()
+ if not sec is None: s = Js(SecFromTime(t))
+ else: s = sec.to_number()
+ if not ms is None: milli = Js(msFromTime(t))
+ else: milli = ms.to_number()
+ date = MakeDate(Day(t), MakeTime(h, m, s, milli))
+ v = TimeClip(date)
+ this.value = v
+ return v
+
+ def setDate(date):
+ check_date(this)
+ t = UTCToLocal(this.value)
+ dt = date.to_number()
+ newDate = MakeDate(
+ MakeDay(Js(YearFromTime(t)), Js(MonthFromTime(t)), dt), TimeWithinDay(t))
+ u = TimeClip(LocalToUTC(newDate))
+ this.value = u
+ return u
+
+ def setUTCDate(date):
+ check_date(this)
+ t = this.value
+ dt = date.to_number()
+ newDate = MakeDate(
+ MakeDay(Js(YearFromTime(t)), Js(MonthFromTime(t)), dt), TimeWithinDay(t))
+ v = TimeClip(newDate)
+ this.value = v
+ return v
+
+ def setMonth(month, date=None):
+ check_date(this)
+ t = UTCToLocal(this.value)
+ m = month.to_number()
+ if not date is None: dt = Js(DateFromTime(t))
+ else: dt = date.to_number()
+ newDate = MakeDate(
+ MakeDay(Js(YearFromTime(t)), m, dt), TimeWithinDay(t))
+ u = TimeClip(LocalToUTC(newDate))
+ this.value = u
+ return u
+
+ def setUTCMonth(month, date=None):
+ check_date(this)
+ t = this.value
+ m = month.to_number()
+ if not date is None: dt = Js(DateFromTime(t))
+ else: dt = date.to_number()
+ newDate = MakeDate(
+ MakeDay(Js(YearFromTime(t)), m, dt), TimeWithinDay(t))
+ v = TimeClip(newDate)
+ this.value = v
+ return v
+
+ def setFullYear(year, month=None, date=None):
+ check_date(this)
+ if not this.value is NaN: t = UTCToLocal(this.value)
+ else: t = 0
+ y = year.to_number()
+ if not month is None: m = Js(MonthFromTime(t))
+ else: m = month.to_number()
+ if not date is None: dt = Js(DateFromTime(t))
+ else: dt = date.to_number()
+ newDate = MakeDate(
+ MakeDay(y, m, dt), TimeWithinDay(t))
+ u = TimeClip(LocalToUTC(newDate))
+ this.value = u
+ return u
+
+ def setUTCFullYear(year, month=None, date=None):
+ check_date(this)
+ if not this.value is NaN: t = UTCToLocal(this.value)
+ else: t = 0
+ y = year.to_number()
+ if not month is None: m = Js(MonthFromTime(t))
+ else: m = month.to_number()
+ if not date is None: dt = Js(DateFromTime(t))
+ else: dt = date.to_number()
+ newDate = MakeDate(
+ MakeDay(y, m, dt), TimeWithinDay(t))
+ v = TimeClip(newDate)
+ this.value = v
+ return v
def toUTCString():
check_date(this)
@@ -318,13 +508,17 @@ def toISOString():
check_date(this)
t = this.value
year = YearFromTime(t)
- month, day, hour, minute, second, milli = pad(MonthFromTime(t)+1), pad(DateFromTime(t)), pad(HourFromTime(t)), pad(MinFromTime(t)), pad(SecFromTime(t)), pad(msFromTime(t))
- return ISO_FORMAT % (unicode(year) if 0<=year<=9999 else pad(year, 6, True), month, day, hour, minute, second, milli)
+ month, day, hour, minute, second, milli = pad(
+ MonthFromTime(t) + 1), pad(DateFromTime(t)), pad(
+ HourFromTime(t)), pad(MinFromTime(t)), pad(
+ SecFromTime(t)), pad(msFromTime(t))
+ return ISO_FORMAT % (unicode(year) if 0 <= year <= 9999 else pad(
+ year, 6, True), month, day, hour, minute, second, milli)
def toJSON(key):
o = this.to_object()
tv = o.to_primitive('Number')
- if tv.Class=='Number' and not tv.is_finite():
+ if tv.Class == 'Number' and not tv.is_finite():
return this.null
toISO = o.get('toISOString')
if not toISO.is_callable():
@@ -335,34 +529,29 @@ def toJSON(key):
def pad(num, n=2, sign=False):
'''returns n digit string representation of the num'''
s = unicode(abs(num))
- if len(s)=0:
- return '+'+s
+ if num >= 0:
+ return '+' + s
else:
- return '-'+s
-
-
-
-
-
-
-
-
+ return '-' + s
fill_prototype(DatePrototype, DateProto, default_attrs)
-
-
-Date.define_own_property('prototype', {'value': DatePrototype,
- 'enumerable': False,
- 'writable': False,
- 'configurable': False})
-
-DatePrototype.define_own_property('constructor', {'value': Date,
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
\ No newline at end of file
+Date.define_own_property(
+ 'prototype', {
+ 'value': DatePrototype,
+ 'enumerable': False,
+ 'writable': False,
+ 'configurable': False
+ })
+
+DatePrototype.define_own_property('constructor', {
+ 'value': Date,
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+})
diff --git a/js2py/internals/constructors/jsfunction.py b/js2py/internals/constructors/jsfunction.py
index 9145d19f..738554a0 100644
--- a/js2py/internals/constructors/jsfunction.py
+++ b/js2py/internals/constructors/jsfunction.py
@@ -5,11 +5,9 @@
from ..byte_trans import ByteCodeGenerator, Code
-
-
def Function(this, args):
# convert arguments to python list of strings
- a = map(to_string, tuple(args))
+ a = list(map(to_string, tuple(args)))
_body = u';'
_args = ()
if len(a):
@@ -18,52 +16,61 @@ def Function(this, args):
return executable_function(_body, _args, args.space, global_context=True)
-# you can use this one lovely piece of function to compile and execute code on the fly! Watch out though as it may generate lots of code.
-# todo tape cleanup? we dont know which pieces are needed and which are not so rather impossible without smarter machinery
def executable_function(_body, _args, space, global_context=True):
-
func_str = u'(function (%s) { ; %s ; });' % (u', '.join(_args), _body)
- skip = space.byte_generator.exe.get_new_label()
- space.byte_generator.emit('JUMP', skip)
- space.byte_generator.emit(parse(func_str)['body'])
- space.byte_generator.emit('LABEL', skip)
- space.byte_generator.emit('NOP')
- space.byte_generator.exe.compile()
-
- ctx = space.GlobalObj if global_context else space.exe.current_ctx
- space.byte_generator.exe.tape[-1].eval(ctx)
- func = ctx.stack.pop()
- return func
+ co = executable_code(
+ code_str=func_str, space=space, global_context=global_context)
+ return co()
+# you can use this one lovely piece of function to compile and execute code on the fly! Watch out though as it may generate lots of code.
+# todo tape cleanup? we dont know which pieces are needed and which are not so rather impossible without smarter machinery something like GC,
+# a one solution would be to have a separate tape for functions
def executable_code(code_str, space, global_context=True):
+ # parse first to check if any SyntaxErrors
+ parsed = parse(code_str)
+
+ old_tape_len = len(space.byte_generator.exe.tape)
+ space.byte_generator.record_state()
start = space.byte_generator.exe.get_new_label()
skip = space.byte_generator.exe.get_new_label()
space.byte_generator.emit('JUMP', skip)
space.byte_generator.emit('LABEL', start)
- space.byte_generator.emit(parse(code_str))
+ space.byte_generator.emit(parsed)
+ space.byte_generator.emit('NOP')
space.byte_generator.emit('LABEL', skip)
space.byte_generator.emit('NOP')
- space.byte_generator.exe.compile()
+ space.byte_generator.restore_state()
+
+ space.byte_generator.exe.compile(
+ start_loc=old_tape_len
+ ) # dont read the code from the beginning, dont be stupid!
ctx = space.GlobalObj if global_context else space.exe.current_ctx
+
def ex_code():
- ret, status, token = space.byte_generator.exe.execute_fragment_under_context(ctx, start, skip)
+ ret, status, token = space.byte_generator.exe.execute_fragment_under_context(
+ ctx, start, skip)
+ # todo Clean up the tape!
+ # this is NOT a way to do that because the fragment may contain the executable code! We dont want to remove it
+ #del space.byte_generator.exe.tape[old_tape_len:]
if status == 0:
return ret
- elif status==3:
+ elif status == 3:
raise token
else:
- raise RuntimeError('Unexpected return status during JIT execution')
- return ex_code
-
+ raise RuntimeError(
+ 'Unexpected return status during JIT execution: %d' % status)
+ return ex_code
def _eval(this, args):
code_str = to_string(get_arg(args, 0))
return executable_code(code_str, args.space, global_context=True)()
+
def log(this, args):
- print ' '.join(map(to_string, args))
\ No newline at end of file
+ print(' '.join(map(to_string, args)))
+ return undefined
diff --git a/js2py/internals/constructors/jsmath.py b/js2py/internals/constructors/jsmath.py
index a6d6b459..c6fde67e 100644
--- a/js2py/internals/constructors/jsmath.py
+++ b/js2py/internals/constructors/jsmath.py
@@ -6,29 +6,31 @@
import math
import random
-CONSTANTS = {'E': 2.7182818284590452354,
- 'LN10': 2.302585092994046,
- 'LN2': 0.6931471805599453,
- 'LOG2E': 1.4426950408889634,
- 'LOG10E': 0.4342944819032518,
- 'PI': 3.1415926535897932,
- 'SQRT1_2': 0.7071067811865476,
- 'SQRT2': 1.4142135623730951}
-
-
+CONSTANTS = {
+ 'E': 2.7182818284590452354,
+ 'LN10': 2.302585092994046,
+ 'LN2': 0.6931471805599453,
+ 'LOG2E': 1.4426950408889634,
+ 'LOG10E': 0.4342944819032518,
+ 'PI': 3.1415926535897932,
+ 'SQRT1_2': 0.7071067811865476,
+ 'SQRT2': 1.4142135623730951
+}
+def is_infinity(x):
+ return x - 1e10 == x
class MathFunctions:
def abs(this, args):
x = get_arg(args, 0)
a = to_number(x)
- if a!=a: # it must be a nan
+ if a != a: # it must be a nan
return NaN
return abs(a)
def acos(this, args):
x = get_arg(args, 0)
a = to_number(x)
- if a!=a: # it must be a nan
+ if a != a: # it must be a nan
return NaN
try:
return math.acos(a)
@@ -38,7 +40,7 @@ def acos(this, args):
def asin(this, args):
x = get_arg(args, 0)
a = to_number(x)
- if a!=a: # it must be a nan
+ if a != a: # it must be a nan
return NaN
try:
return math.asin(a)
@@ -48,7 +50,7 @@ def asin(this, args):
def atan(this, args):
x = get_arg(args, 0)
a = to_number(x)
- if a!=a: # it must be a nan
+ if a != a: # it must be a nan
return NaN
return math.atan(a)
@@ -57,56 +59,56 @@ def atan2(this, args):
y = get_arg(args, 1)
a = to_number(x)
b = to_number(y)
- if a!=a or b!=b: # it must be a nan
+ if a != a or b != b: # it must be a nan
return NaN
return math.atan2(a, b)
def ceil(this, args):
x = get_arg(args, 0)
a = to_number(x)
- if a!=a: # it must be a nan
- return NaN
+ if not is_finite(x):
+ return x
return float(math.ceil(a))
def floor(this, args):
x = get_arg(args, 0)
a = to_number(x)
- if a!=a: # it must be a nan
- return NaN
+ if not is_finite(x):
+ return x
return float(math.floor(a))
def round(this, args):
x = get_arg(args, 0)
a = to_number(x)
- if a!=a: # it must be a nan
- return NaN
+ if not is_finite(x):
+ return x
return float(round(a))
def sin(this, args):
x = get_arg(args, 0)
a = to_number(x)
- if a!=a: # it must be a nan
+ if not is_finite(a): # it must be a nan
return NaN
return math.sin(a)
def cos(this, args):
x = get_arg(args, 0)
a = to_number(x)
- if a!=a: # it must be a nan
+ if not is_finite(a): # it must be a nan
return NaN
- return math.cos(a)
+ return math.cos(a)
def tan(this, args):
x = get_arg(args, 0)
a = to_number(x)
- if a!=a: # it must be a nan
+ if not is_finite(a): # it must be a nan
return NaN
return math.tan(a)
def log(this, args):
x = get_arg(args, 0)
a = to_number(x)
- if a!=a: # it must be a nan
+ if a != a: # it must be a nan
return NaN
try:
return math.log(a)
@@ -116,7 +118,7 @@ def log(this, args):
def exp(this, args):
x = get_arg(args, 0)
a = to_number(x)
- if a!=a: # it must be a nan
+ if a != a: # it must be a nan
return NaN
return math.exp(a)
@@ -125,7 +127,7 @@ def pow(this, args):
y = get_arg(args, 1)
a = to_number(x)
b = to_number(y)
- if a!=a or b!=b: # it must be a nan
+ if a != a or b != b: # it must be a nan
return NaN
try:
return a**b
@@ -135,7 +137,7 @@ def pow(this, args):
def sqrt(this, args):
x = get_arg(args, 0)
a = to_number(x)
- if a!=a: # it must be a nan
+ if a != a: # it must be a nan
return NaN
try:
return a**0.5
@@ -143,15 +145,14 @@ def sqrt(this, args):
return NaN
def min(this, args):
- if len(args)==0:
+ if len(args) == 0:
return Infinity
return min(map(to_number, tuple(args)))
def max(this, args):
- if len(args)==0:
+ if len(args) == 0:
return -Infinity
return max(map(to_number, tuple(args)))
-
def random(this, args):
return random.random()
diff --git a/js2py/internals/constructors/jsnumber.py b/js2py/internals/constructors/jsnumber.py
index c915f499..276b7cfa 100644
--- a/js2py/internals/constructors/jsnumber.py
+++ b/js2py/internals/constructors/jsnumber.py
@@ -4,7 +4,6 @@
from ..func_utils import *
-
def Number(this, args):
if len(args) == 0:
return 0.
@@ -15,16 +14,14 @@ def NumberConstructor(args, space):
temp = space.NewObject()
temp.prototype = space.NumberPrototype
temp.Class = 'Number'
- temp.value = to_number(get_arg(args, 0)) if len(args)>0 else 0.
+ temp.value = float(to_number(get_arg(args, 0)) if len(args) > 0 else 0.)
return temp
CONSTS = {
- 'MAX_VALUE':1.7976931348623157e308,
- 'MIN_VALUE': 5.0e-324,
- 'NaN': NaN,
- 'NEGATIVE_INFINITY': Infinity,
- 'POSITIVE_INFINITY': -Infinity}
-
-
-
+ 'MAX_VALUE': 1.7976931348623157e308,
+ 'MIN_VALUE': 5.0e-324,
+ 'NaN': NaN,
+ 'NEGATIVE_INFINITY': Infinity,
+ 'POSITIVE_INFINITY': -Infinity
+}
diff --git a/js2py/internals/constructors/jsobject.py b/js2py/internals/constructors/jsobject.py
index 37f046ce..06fdbbb0 100644
--- a/js2py/internals/constructors/jsobject.py
+++ b/js2py/internals/constructors/jsobject.py
@@ -7,7 +7,7 @@
def Object(this, args):
val = get_arg(args, 0)
- if val.is_null() or val.is_undefined():
+ if is_null(val) or is_undefined(val):
return args.space.NewObject()
return to_object(val, args.space)
@@ -16,48 +16,52 @@ def ObjectCreate(args, space):
if len(args):
val = get_arg(args, 0)
if is_object(val):
- #Implementation dependent, but my will simply return :)
+ # Implementation dependent, but my will simply return :)
return val
elif type(val) in (NUMBER_TYPE, STRING_TYPE, BOOLEAN_TYPE):
return to_object(val, space)
return space.NewObject()
-
class ObjectMethods:
def getPrototypeOf(this, args):
obj = get_arg(args, 0)
if not is_object(obj):
- raise MakeError('TypeError', 'Object.getPrototypeOf called on non-object')
+ raise MakeError('TypeError',
+ 'Object.getPrototypeOf called on non-object')
return null if obj.prototype is None else obj.prototype
def getOwnPropertyDescriptor(this, args):
obj = get_arg(args, 0)
prop = get_arg(args, 1)
if not is_object(obj):
- raise MakeError('TypeError', 'Object.getOwnPropertyDescriptor called on non-object')
+ raise MakeError(
+ 'TypeError',
+ 'Object.getOwnPropertyDescriptor called on non-object')
desc = obj.own.get(to_string(prop))
- return convert_to_js_type(desc)
-
+ return convert_to_js_type(desc, args.space)
def getOwnPropertyNames(this, args):
obj = get_arg(args, 0)
if not is_object(obj):
- raise MakeError('TypeError', 'Object.getOwnPropertyDescriptor called on non-object')
+ raise MakeError(
+ 'TypeError',
+ 'Object.getOwnPropertyDescriptor called on non-object')
return args.space.ConstructArray(obj.own.keys())
def create(this, args):
obj = get_arg(args, 0)
if not (is_object(obj) or is_null(obj)):
- raise MakeError('TypeError', 'Object prototype may only be an Object or null')
+ raise MakeError('TypeError',
+ 'Object prototype may only be an Object or null')
temp = args.space.NewObject()
temp.prototype = None if is_null(obj) else obj
- if len(args)>1 and not is_undefined(args[1]):
+ if len(args) > 1 and not is_undefined(args[1]):
if six.PY2:
- args.tup = (args[1],)
+ args.tup = (args[1], )
ObjectMethods.defineProperties.__func__(temp, args)
else:
- args.tup = (args[1],)
+ args.tup = (args[1], )
ObjectMethods.defineProperties(temp, args)
return temp
@@ -66,9 +70,11 @@ def defineProperty(this, args):
prop = get_arg(args, 1)
attrs = get_arg(args, 2)
if not is_object(obj):
- raise MakeError('TypeError', 'Object.defineProperty called on non-object')
+ raise MakeError('TypeError',
+ 'Object.defineProperty called on non-object')
name = to_string(prop)
- if not obj.define_own_property(name, ToPropertyDescriptor(attrs), False):
+ if not obj.define_own_property(name, ToPropertyDescriptor(attrs),
+ False):
raise MakeError('TypeError', 'Cannot redefine property: %s' % name)
return obj
@@ -76,14 +82,16 @@ def defineProperties(this, args):
obj = get_arg(args, 0)
properties = get_arg(args, 1)
if not is_object(obj):
- raise MakeError('TypeError', 'Object.defineProperties called on non-object')
+ raise MakeError('TypeError',
+ 'Object.defineProperties called on non-object')
props = to_object(properties, args.space)
for k, v in props.own.items():
if not v.get('enumerable'):
continue
desc = ToPropertyDescriptor(props.get(unicode(k)))
- if not obj.define_own_property(unicode(k), desc):
- raise MakeError('TypeError', 'Failed to define own property: %s'% k)
+ if not obj.define_own_property(unicode(k), desc, False):
+ raise MakeError('TypeError',
+ 'Failed to define own property: %s' % k)
return obj
def seal(this, args):
@@ -109,14 +117,16 @@ def freeze(this, args):
def preventExtensions(this, args):
obj = get_arg(args, 0)
if not is_object(obj):
- raise MakeError('TypeError', 'Object.preventExtensions on non-object')
+ raise MakeError('TypeError',
+ 'Object.preventExtensions on non-object')
obj.extensible = False
return obj
def isSealed(this, args):
obj = get_arg(args, 0)
if not is_object(obj):
- raise MakeError('TypeError', 'Object.isSealed called on non-object')
+ raise MakeError('TypeError',
+ 'Object.isSealed called on non-object')
if obj.extensible:
return False
for desc in obj.own.values():
@@ -127,7 +137,8 @@ def isSealed(this, args):
def isFrozen(this, args):
obj = get_arg(args, 0)
if not is_object(obj):
- raise MakeError('TypeError', 'Object.isFrozen called on non-object')
+ raise MakeError('TypeError',
+ 'Object.isFrozen called on non-object')
if obj.extensible:
return False
for desc in obj.own.values():
@@ -140,24 +151,27 @@ def isFrozen(this, args):
def isExtensible(this, args):
obj = get_arg(args, 0)
if not is_object(obj):
- raise MakeError('TypeError', 'Object.isExtensible called on non-object')
+ raise MakeError('TypeError',
+ 'Object.isExtensible called on non-object')
return obj.extensible
def keys(this, args):
obj = get_arg(args, 0)
if not is_object(obj):
raise MakeError('TypeError', 'Object.keys called on non-object')
- return args.space.ConstructArray([unicode(e) for e,d in six.iteritems(obj.own) if d.get('enumerable')])
-
-
-
+ return args.space.ConstructArray([
+ unicode(e) for e, d in six.iteritems(obj.own)
+ if d.get('enumerable')
+ ])
# some utility functions:
+
def ToPropertyDescriptor(obj): # page 38 (50 absolute)
if not is_object(obj):
- raise MakeError('TypeError', 'Can\'t convert non-object to property descriptor')
+ raise MakeError('TypeError',
+ 'Can\'t convert non-object to property descriptor')
desc = {}
if obj.has_property('enumerable'):
desc['enumerable'] = to_boolean(obj.get('enumerable'))
@@ -166,20 +180,25 @@ def ToPropertyDescriptor(obj): # page 38 (50 absolute)
if obj.has_property('value'):
desc['value'] = obj.get('value')
if obj.has_property('writable'):
- desc['writable'] =to_boolean(obj.get('writable'))
+ desc['writable'] = to_boolean(obj.get('writable'))
if obj.has_property('get'):
- cand = obj.get('get')
+ cand = obj.get('get')
if not (is_undefined(cand) or is_callable(cand)):
- raise MakeError('TypeError', 'Invalid getter (it has to be a function or undefined)')
+ raise MakeError(
+ 'TypeError',
+ 'Invalid getter (it has to be a function or undefined)')
desc['get'] = cand
if obj.has_property('set'):
- cand = obj.get('set')
+ cand = obj.get('set')
if not (is_undefined(cand) or is_callable(cand)):
- raise MakeError('TypeError', 'Invalid setter (it has to be a function or undefined)')
+ raise MakeError(
+ 'TypeError',
+ 'Invalid setter (it has to be a function or undefined)')
desc['set'] = cand
- if ('get' in desc or 'set' in desc) and ('value' in desc or 'writable' in desc):
- raise MakeError('TypeError', 'Invalid property. A property cannot both have accessors and be writable or have a value.')
+ if ('get' in desc or 'set' in desc) and ('value' in desc
+ or 'writable' in desc):
+ raise MakeError(
+ 'TypeError',
+ 'Invalid property. A property cannot both have accessors and be writable or have a value.'
+ )
return desc
-
-
-
diff --git a/js2py/internals/constructors/jsregexp.py b/js2py/internals/constructors/jsregexp.py
index 05b2c2ed..7b264fdb 100644
--- a/js2py/internals/constructors/jsregexp.py
+++ b/js2py/internals/constructors/jsregexp.py
@@ -3,15 +3,18 @@
from ..func_utils import *
from ..base import SpaceTuple
-
REG_EXP_FLAGS = ('g', 'i', 'm')
+
def RegExp(this, args):
pattern = get_arg(args, 0)
flags = get_arg(args, 1)
- if GetClass(pattern)=='RegExp':
+ if GetClass(pattern) == 'RegExp':
if not is_undefined(flags):
- raise MakeError('TypeError', 'Cannot supply flags when constructing one RegExp from another')
+ raise MakeError(
+ 'TypeError',
+ 'Cannot supply flags when constructing one RegExp from another'
+ )
# return unchanged
return pattern
#pattern is not a regexp
@@ -22,9 +25,13 @@ def RegExp(this, args):
flags = to_string(flags) if not is_undefined(flags) else u''
for flag in flags:
if flag not in REG_EXP_FLAGS:
- raise MakeError('SyntaxError', 'Invalid flags supplied to RegExp constructor "%s"' % flag)
- if len(set(flags))!=len(flags):
- raise MakeError('SyntaxError', 'Invalid flags supplied to RegExp constructor "%s"' % flags)
+ raise MakeError(
+ 'SyntaxError',
+ 'Invalid flags supplied to RegExp constructor "%s"' % flag)
+ if len(set(flags)) != len(flags):
+ raise MakeError(
+ 'SyntaxError',
+ 'Invalid flags supplied to RegExp constructor "%s"' % flags)
return args.space.NewRegExp(pattern, flags)
@@ -32,4 +39,3 @@ def RegExpCreate(args, space):
_args = SpaceTuple(args)
_args.space = space
return RegExp(undefined, _args)
-
diff --git a/js2py/internals/constructors/jsstring.py b/js2py/internals/constructors/jsstring.py
index e168bf4d..20d92a4b 100644
--- a/js2py/internals/constructors/jsstring.py
+++ b/js2py/internals/constructors/jsstring.py
@@ -1,6 +1,6 @@
from ..conversions import *
from ..func_utils import *
-
+from six import unichr
def fromCharCode(this, args):
res = u''
@@ -8,6 +8,7 @@ def fromCharCode(this, args):
res += unichr(to_uint16(e))
return res
+
def String(this, args):
if len(args) == 0:
return u''
@@ -18,5 +19,5 @@ def StringConstructor(args, space):
temp = space.NewObject()
temp.prototype = space.StringPrototype
temp.Class = 'String'
- temp.value = to_string(get_arg(args, 0)) if len(args)>0 else u''
- return temp
\ No newline at end of file
+ temp.value = to_string(get_arg(args, 0)) if len(args) > 0 else u''
+ return temp
diff --git a/js2py/internals/constructors/time_helpers.py b/js2py/internals/constructors/time_helpers.py
index aba0dd5b..2d694b58 100644
--- a/js2py/internals/constructors/time_helpers.py
+++ b/js2py/internals/constructors/time_helpers.py
@@ -8,17 +8,21 @@
try:
from tzlocal import get_localzone
LOCAL_ZONE = get_localzone()
-except: # except all problems...
- warnings.warn('Please install or fix tzlocal library (pip install tzlocal) in order to make Date object work better. Otherwise I will assume DST is in effect all the time')
+except: # except all problems...
+ warnings.warn(
+ 'Please install or fix tzlocal library (pip install tzlocal) in order to make Date object work better. Otherwise I will assume DST is in effect all the time'
+ )
+
class LOCAL_ZONE:
@staticmethod
def dst(*args):
return 1
+
from js2py.base import MakeError
CUM = (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365)
msPerDay = 86400000
-msPerYear = int(86400000*365.242)
+msPerYear = int(86400000 * 365.242)
msPerSecond = 1000
msPerMinute = 60000
msPerHour = 3600000
@@ -26,66 +30,74 @@ def dst(*args):
MinutesPerHour = 60
SecondsPerMinute = 60
NaN = float('nan')
-LocalTZA = - time.timezone * msPerSecond
-
-
-
+LocalTZA = -time.timezone * msPerSecond
def DaylightSavingTA(t):
if t is NaN:
return t
try:
- return int(LOCAL_ZONE.dst(datetime.datetime.utcfromtimestamp(t//1000)).seconds)*1000
+ return int(
+ LOCAL_ZONE.dst(datetime.datetime(1970, 1, 1) + datetime.timedelta(
+ seconds=t // 1000)).seconds) * 1000
except:
- warnings.warn('Invalid datetime date, assumed DST time, may be inaccurate...', Warning)
+ warnings.warn(
+ 'Invalid datetime date, assumed DST time, may be inaccurate...',
+ Warning)
return 1
#raise MakeError('TypeError', 'date not supported by python.datetime. I will solve it in future versions')
+
def GetTimeZoneName(t):
- return time.tzname[DaylightSavingTA(t)>0]
+ return time.tzname[DaylightSavingTA(t) > 0]
+
def LocalToUTC(t):
return t - LocalTZA - DaylightSavingTA(t - LocalTZA)
+
def UTCToLocal(t):
return t + LocalTZA + DaylightSavingTA(t)
def Day(t):
- return t//86400000
+ return t // 86400000
def TimeWithinDay(t):
- return t%86400000
+ return t % 86400000
+
def DaysInYear(y):
- if y%4:
+ if y % 4:
return 365
- elif y%100:
+ elif y % 100:
return 366
- elif y%400:
+ elif y % 400:
return 365
else:
return 366
def DayFromYear(y):
- return 365 * (y-1970) + (y-1969)//4 -(y-1901)//100 + (y-1601)//400
+ return 365 * (y - 1970) + (y - 1969) // 4 - (y - 1901) // 100 + (
+ y - 1601) // 400
+
def TimeFromYear(y):
return 86400000 * DayFromYear(y)
+
def YearFromTime(t):
- guess = 1970 - t//31556908800 # msPerYear
+ guess = 1970 - t // 31556908800 # msPerYear
gt = TimeFromYear(guess)
- if gt<=t:
- while gt<=t:
+ if gt <= t:
+ while gt <= t:
guess += 1
gt = TimeFromYear(guess)
- return guess-1
+ return guess - 1
else:
- while gt>t:
+ while gt > t:
guess -= 1
gt = TimeFromYear(guess)
return guess
@@ -94,73 +106,83 @@ def YearFromTime(t):
def DayWithinYear(t):
return Day(t) - DayFromYear(YearFromTime(t))
+
def InLeapYear(t):
y = YearFromTime(t)
- if y%4:
+ if y % 4:
return 0
- elif y%100:
+ elif y % 100:
return 1
- elif y%400:
+ elif y % 400:
return 0
else:
return 1
+
def MonthFromTime(t):
day = DayWithinYear(t)
leap = InLeapYear(t)
- if day<31:
+ if day < 31:
return 0
day -= leap
- if day<59:
+ if day < 59:
return 1
- elif day<90:
+ elif day < 90:
return 2
- elif day<120:
+ elif day < 120:
return 3
- elif day<151:
+ elif day < 151:
return 4
- elif day<181:
+ elif day < 181:
return 5
- elif day<212:
+ elif day < 212:
return 6
- elif day<243:
+ elif day < 243:
return 7
- elif day<273:
+ elif day < 273:
return 8
- elif day<304:
+ elif day < 304:
return 9
- elif day<334:
+ elif day < 334:
return 10
else:
return 11
+
def DateFromTime(t):
mon = MonthFromTime(t)
day = DayWithinYear(t)
- return day-CUM[mon] - (1 if InLeapYear(t) and mon>=2 else 0) + 1
+ return day - CUM[mon] - (1 if InLeapYear(t) and mon >= 2 else 0) + 1
+
def WeekDay(t):
# 0 == sunday
return (Day(t) + 4) % 7
+
def msFromTime(t):
return t % 1000
+
def SecFromTime(t):
- return (t//1000) % 60
+ return (t // 1000) % 60
+
def MinFromTime(t):
- return (t//60000) % 60
+ return (t // 60000) % 60
+
def HourFromTime(t):
- return (t//3600000) % 24
+ return (t // 3600000) % 24
+
-def MakeTime (hour, Min, sec, ms):
+def MakeTime(hour, Min, sec, ms):
# takes PyJs objects and returns t
- if not (hour.is_finite() and Min.is_finite() and sec.is_finite() and ms.is_finite()):
+ if not (hour.is_finite() and Min.is_finite() and sec.is_finite()
+ and ms.is_finite()):
return NaN
h, m, s, milli = hour.to_int(), Min.to_int(), sec.to_int(), ms.to_int()
- return h*3600000 + m*60000 + s*1000 + milli
+ return h * 3600000 + m * 60000 + s * 1000 + milli
def MakeDay(year, month, date):
@@ -168,19 +190,20 @@ def MakeDay(year, month, date):
if not (year.is_finite() and month.is_finite() and date.is_finite()):
return NaN
y, m, dt = year.to_int(), month.to_int(), date.to_int()
- y += m//12
+ y += m // 12
mn = m % 12
- d = DayFromYear(y) + CUM[mn] + dt - 1 + (1 if DaysInYear(y)==366 and mn>=2 else 0)
- return d # ms per day
+ d = DayFromYear(y) + CUM[mn] + dt - 1 + (1 if DaysInYear(y) == 366
+ and mn >= 2 else 0)
+ return d # ms per day
+
def MakeDate(day, time):
- return 86400000*day + time
+ return 86400000 * day + time
def TimeClip(t):
- if t!=t or abs(t)==float('inf'):
+ if t != t or abs(t) == float('inf'):
return NaN
- if abs(t) > 8.64 *10**15:
+ if abs(t) > 8.64 * 10**15:
return NaN
return int(t)
-
diff --git a/js2py/internals/conversions.py b/js2py/internals/conversions.py
index 3732a3a6..8b2c7c30 100644
--- a/js2py/internals/conversions.py
+++ b/js2py/internals/conversions.py
@@ -1,5 +1,7 @@
+from __future__ import unicode_literals
# Type Conversions. to_type. All must return PyJs subclass instance
-from simplex import *
+from .simplex import *
+
def to_primitive(self, hint=None):
if is_primitive(self):
@@ -23,6 +25,7 @@ def to_boolean(self):
else: # object - always True
return True
+
def to_number(self):
typ = Type(self)
if typ == 'Number': # or self.Class=='Number': # no need to convert
@@ -70,14 +73,7 @@ def to_string(self):
elif typ == 'Boolean':
return 'true' if self else 'false'
elif typ == 'Number': # or self.Class=='Number':
- if is_nan(self):
- return 'NaN'
- elif is_infinity(self):
- sign = '-' if self < 0 else ''
- return sign + 'Infinity'
- elif int(self)==self: # integer value!
- return unicode(int(self))
- return unicode(self) # todo make it print exactly like node.js
+ return js_dtoa(self)
else: # object
return to_string(to_primitive(self, 'String'))
@@ -87,13 +83,14 @@ def to_object(self, space):
if typ == 'Object':
return self
elif typ == 'Boolean': # Unsure ... todo check here
- return space.Boolean.create((self,), space)
+ return space.Boolean.create((self, ), space)
elif typ == 'Number': # ?
- return space.Number.create((self,), space)
+ return space.Number.create((self, ), space)
elif typ == 'String': # ?
- return space.String.create((self,), space)
+ return space.String.create((self, ), space)
elif typ == 'Null' or typ == 'Undefined':
- raise MakeError('TypeError', 'undefined or null can\'t be converted to object')
+ raise MakeError('TypeError',
+ 'undefined or null can\'t be converted to object')
else:
raise RuntimeError()
@@ -102,8 +99,8 @@ def to_int32(self):
num = to_number(self)
if is_nan(num) or is_infinity(num):
return 0
- int32 = int(num) % 2 ** 32
- return int(int32 - 2 ** 32 if int32 >= 2 ** 31 else int32)
+ int32 = int(num) % 2**32
+ return int(int32 - 2**32 if int32 >= 2**31 else int32)
def to_int(self):
@@ -111,7 +108,7 @@ def to_int(self):
if is_nan(num):
return 0
elif is_infinity(num):
- return 10 ** 20 if num > 0 else -10 ** 20
+ return 10**20 if num > 0 else -10**20
return int(num)
@@ -119,25 +116,26 @@ def to_uint32(self):
num = to_number(self)
if is_nan(num) or is_infinity(num):
return 0
- return int(num) % 2 ** 32
+ return int(num) % 2**32
def to_uint16(self):
num = to_number(self)
if is_nan(num) or is_infinity(num):
return 0
- return int(num) % 2 ** 16
+ return int(num) % 2**16
def to_int16(self):
num = to_number(self)
if is_nan(num) or is_infinity(num):
return 0
- int16 = int(num) % 2 ** 16
- return int(int16 - 2 ** 16 if int16 >= 2 ** 15 else int16)
+ int16 = int(num) % 2**16
+ return int(int16 - 2**16 if int16 >= 2**15 else int16)
def cok(self):
"""Check object coercible"""
if type(self) in (UNDEFINED_TYPE, NULL_TYPE):
- raise MakeError('TypeError', 'undefined or null can\'t be converted to object')
\ No newline at end of file
+ raise MakeError('TypeError',
+ 'undefined or null can\'t be converted to object')
diff --git a/js2py/internals/desc.py b/js2py/internals/desc.py
index 5e29b3f8..e81179c2 100644
--- a/js2py/internals/desc.py
+++ b/js2py/internals/desc.py
@@ -4,6 +4,7 @@
# Warning: value, get, set props of dest are PyJs types. Rest is Py!
+
def is_data_descriptor(desc):
return desc and ('value' in desc or 'writable' in desc)
@@ -12,8 +13,11 @@ def is_accessor_descriptor(desc):
return desc and ('get' in desc or 'set' in desc)
-def is_generic_descriptor(desc): # generic means not the data and not the setter - therefore it must be one that changes only enum and conf
- return desc and not (is_data_descriptor(desc) or is_accessor_descriptor(desc))
+def is_generic_descriptor(
+ desc
+): # generic means not the data and not the setter - therefore it must be one that changes only enum and conf
+ return desc and not (is_data_descriptor(desc)
+ or is_accessor_descriptor(desc))
def from_property_descriptor(desc, space):
@@ -21,36 +25,54 @@ def from_property_descriptor(desc, space):
return {}
obj = space.NewObject()
if is_data_descriptor(desc):
- obj.define_own_property('value', {'value': desc['value'],
- 'writable': True,
- 'enumerable': True,
- 'configurable': True}, False)
- obj.define_own_property('writable', {'value': desc['writable'],
- 'writable': True,
- 'enumerable': True,
- 'configurable': True}, False)
+ obj.define_own_property(
+ 'value', {
+ 'value': desc['value'],
+ 'writable': True,
+ 'enumerable': True,
+ 'configurable': True
+ }, False)
+ obj.define_own_property(
+ 'writable', {
+ 'value': desc['writable'],
+ 'writable': True,
+ 'enumerable': True,
+ 'configurable': True
+ }, False)
else:
- obj.define_own_property('get', {'value': desc['get'],
- 'writable': True,
- 'enumerable': True,
- 'configurable': True}, False)
- obj.define_own_property('set', {'value': desc['set'],
- 'writable': True,
- 'enumerable': True,
- 'configurable': True}, False)
- obj.define_own_property('writable', {'value': desc['writable'],
- 'writable': True,
- 'enumerable': True,
- 'configurable': True}, False)
- obj.define_own_property('enumerable', {'value': desc['enumerable'],
- 'writable': True,
- 'enumerable': True,
- 'configurable': True}, False)
+ obj.define_own_property(
+ 'get', {
+ 'value': desc['get'],
+ 'writable': True,
+ 'enumerable': True,
+ 'configurable': True
+ }, False)
+ obj.define_own_property(
+ 'set', {
+ 'value': desc['set'],
+ 'writable': True,
+ 'enumerable': True,
+ 'configurable': True
+ }, False)
+ obj.define_own_property(
+ 'writable', {
+ 'value': desc['writable'],
+ 'writable': True,
+ 'enumerable': True,
+ 'configurable': True
+ }, False)
+ obj.define_own_property(
+ 'enumerable', {
+ 'value': desc['enumerable'],
+ 'writable': True,
+ 'enumerable': True,
+ 'configurable': True
+ }, False)
return obj
def to_property_descriptor(obj):
- if obj._type()!='Object':
+ if obj._type() != 'Object':
raise TypeError()
desc = {}
for e in ('enumerable', 'configurable', 'writable'):
@@ -63,6 +85,6 @@ def to_property_descriptor(obj):
cand = obj.get(e)
if not (cand.is_callable() or cand.is_undefined()):
raise TypeError()
- if ('get' in desc or 'set' in desc) and ('value' in desc or 'writable' in desc):
+ if ('get' in desc or 'set' in desc) and ('value' in desc
+ or 'writable' in desc):
raise TypeError()
-
diff --git a/js2py/internals/esprima.js b/js2py/internals/esprima.js
deleted file mode 100644
index 15105546..00000000
--- a/js2py/internals/esprima.js
+++ /dev/null
@@ -1,5664 +0,0 @@
-/*
- Copyright (c) jQuery Foundation, Inc. and Contributors, All Rights Reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-(function (root, factory) {
-
- // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,
- // Rhino, and plain browser loading.
-
- /* istanbul ignore next */
- if (typeof define === 'function' && define.amd) {
- define(['exports'], factory);
- } else if (typeof exports !== 'undefined') {
- factory(exports);
- } else {
- factory((root.esprima = {}));
- }
-}(this, function (exports) {
-
- var Token,
- TokenName,
- FnExprTokens,
- Syntax,
- PlaceHolders,
- Messages,
- Regex,
- source,
- strict,
- index,
- lineNumber,
- lineStart,
- hasLineTerminator,
- lastIndex,
- lastLineNumber,
- lastLineStart,
- startIndex,
- startLineNumber,
- startLineStart,
- scanning,
- length,
- lookahead,
- state,
- extra,
- isBindingElement,
- isAssignmentTarget,
- firstCoverInitializedNameError;
-
- Token = {
- BooleanLiteral: 1,
- EOF: 2,
- Identifier: 3,
- Keyword: 4,
- NullLiteral: 5,
- NumericLiteral: 6,
- Punctuator: 7,
- StringLiteral: 8,
- RegularExpression: 9,
- Template: 10
- };
-
- TokenName = {};
- TokenName[Token.BooleanLiteral] = 'Boolean';
- TokenName[Token.EOF] = '';
- TokenName[Token.Identifier] = 'Identifier';
- TokenName[Token.Keyword] = 'Keyword';
- TokenName[Token.NullLiteral] = 'Null';
- TokenName[Token.NumericLiteral] = 'Numeric';
- TokenName[Token.Punctuator] = 'Punctuator';
- TokenName[Token.StringLiteral] = 'String';
- TokenName[Token.RegularExpression] = 'RegularExpression';
- TokenName[Token.Template] = 'Template';
-
- // A function following one of those tokens is an expression.
- FnExprTokens = ['(', '{', '[', 'in', 'typeof', 'instanceof', 'new',
- 'return', 'case', 'delete', 'throw', 'void',
- // assignment operators
- '=', '+=', '-=', '*=', '/=', '%=', '<<=', '>>=', '>>>=',
- '&=', '|=', '^=', ',',
- // binary/unary operators
- '+', '-', '*', '/', '%', '++', '--', '<<', '>>', '>>>', '&',
- '|', '^', '!', '~', '&&', '||', '?', ':', '===', '==', '>=',
- '<=', '<', '>', '!=', '!=='];
-
- Syntax = {
- AssignmentExpression: 'AssignmentExpression',
- AssignmentPattern: 'AssignmentPattern',
- ArrayExpression: 'ArrayExpression',
- ArrayPattern: 'ArrayPattern',
- ArrowFunctionExpression: 'ArrowFunctionExpression',
- BlockStatement: 'BlockStatement',
- BinaryExpression: 'BinaryExpression',
- BreakStatement: 'BreakStatement',
- CallExpression: 'CallExpression',
- CatchClause: 'CatchClause',
- ClassBody: 'ClassBody',
- ClassDeclaration: 'ClassDeclaration',
- ClassExpression: 'ClassExpression',
- ConditionalExpression: 'ConditionalExpression',
- ContinueStatement: 'ContinueStatement',
- DoWhileStatement: 'DoWhileStatement',
- DebuggerStatement: 'DebuggerStatement',
- EmptyStatement: 'EmptyStatement',
- ExportAllDeclaration: 'ExportAllDeclaration',
- ExportDefaultDeclaration: 'ExportDefaultDeclaration',
- ExportNamedDeclaration: 'ExportNamedDeclaration',
- ExportSpecifier: 'ExportSpecifier',
- ExpressionStatement: 'ExpressionStatement',
- ForStatement: 'ForStatement',
- ForOfStatement: 'ForOfStatement',
- ForInStatement: 'ForInStatement',
- FunctionDeclaration: 'FunctionDeclaration',
- FunctionExpression: 'FunctionExpression',
- Identifier: 'Identifier',
- IfStatement: 'IfStatement',
- ImportDeclaration: 'ImportDeclaration',
- ImportDefaultSpecifier: 'ImportDefaultSpecifier',
- ImportNamespaceSpecifier: 'ImportNamespaceSpecifier',
- ImportSpecifier: 'ImportSpecifier',
- Literal: 'Literal',
- LabeledStatement: 'LabeledStatement',
- LogicalExpression: 'LogicalExpression',
- MemberExpression: 'MemberExpression',
- MetaProperty: 'MetaProperty',
- MethodDefinition: 'MethodDefinition',
- NewExpression: 'NewExpression',
- ObjectExpression: 'ObjectExpression',
- ObjectPattern: 'ObjectPattern',
- Program: 'Program',
- Property: 'Property',
- RestElement: 'RestElement',
- ReturnStatement: 'ReturnStatement',
- SequenceExpression: 'SequenceExpression',
- SpreadElement: 'SpreadElement',
- Super: 'Super',
- SwitchCase: 'SwitchCase',
- SwitchStatement: 'SwitchStatement',
- TaggedTemplateExpression: 'TaggedTemplateExpression',
- TemplateElement: 'TemplateElement',
- TemplateLiteral: 'TemplateLiteral',
- ThisExpression: 'ThisExpression',
- ThrowStatement: 'ThrowStatement',
- TryStatement: 'TryStatement',
- UnaryExpression: 'UnaryExpression',
- UpdateExpression: 'UpdateExpression',
- VariableDeclaration: 'VariableDeclaration',
- VariableDeclarator: 'VariableDeclarator',
- WhileStatement: 'WhileStatement',
- WithStatement: 'WithStatement',
- YieldExpression: 'YieldExpression'
- };
-
- PlaceHolders = {
- ArrowParameterPlaceHolder: 'ArrowParameterPlaceHolder'
- };
-
- // Error messages should be identical to V8.
- Messages = {
- UnexpectedToken: 'Unexpected token %0',
- UnexpectedNumber: 'Unexpected number',
- UnexpectedString: 'Unexpected string',
- UnexpectedIdentifier: 'Unexpected identifier',
- UnexpectedReserved: 'Unexpected reserved word',
- UnexpectedTemplate: 'Unexpected quasi %0',
- UnexpectedEOS: 'Unexpected end of input',
- NewlineAfterThrow: 'Illegal newline after throw',
- InvalidRegExp: 'Invalid regular expression',
- UnterminatedRegExp: 'Invalid regular expression: missing /',
- InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
- InvalidLHSInForIn: 'Invalid left-hand side in for-in',
- InvalidLHSInForLoop: 'Invalid left-hand side in for-loop',
- MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
- NoCatchOrFinally: 'Missing catch or finally after try',
- UnknownLabel: 'Undefined label \'%0\'',
- Redeclaration: '%0 \'%1\' has already been declared',
- IllegalContinue: 'Illegal continue statement',
- IllegalBreak: 'Illegal break statement',
- IllegalReturn: 'Illegal return statement',
- StrictModeWith: 'Strict mode code may not include a with statement',
- StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
- StrictVarName: 'Variable name may not be eval or arguments in strict mode',
- StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode',
- StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
- StrictFunctionName: 'Function name may not be eval or arguments in strict mode',
- StrictOctalLiteral: 'Octal literals are not allowed in strict mode.',
- StrictDelete: 'Delete of an unqualified identifier in strict mode.',
- StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode',
- StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode',
- StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode',
- StrictReservedWord: 'Use of future reserved word in strict mode',
- TemplateOctalLiteral: 'Octal literals are not allowed in template strings.',
- ParameterAfterRestParameter: 'Rest parameter must be last formal parameter',
- DefaultRestParameter: 'Unexpected token =',
- ObjectPatternAsRestParameter: 'Unexpected token {',
- DuplicateProtoProperty: 'Duplicate __proto__ fields are not allowed in object literals',
- ConstructorSpecialMethod: 'Class constructor may not be an accessor',
- DuplicateConstructor: 'A class may only have one constructor',
- StaticPrototype: 'Classes may not have static property named prototype',
- MissingFromClause: 'Unexpected token',
- NoAsAfterImportNamespace: 'Unexpected token',
- InvalidModuleSpecifier: 'Unexpected token',
- IllegalImportDeclaration: 'Unexpected token',
- IllegalExportDeclaration: 'Unexpected token',
- DuplicateBinding: 'Duplicate binding %0'
- };
-
- // See also tools/generate-unicode-regex.js.
- Regex = {
- // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierStart:
- NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDE00-\uDE11\uDE13-\uDE2B\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDE00-\uDE2F\uDE44\uDE80-\uDEAA]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]/,
-
- // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierPart:
- NonAsciiIdentifierPart: /[\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDD0-\uDDDA\uDE00-\uDE11\uDE13-\uDE37\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF01-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9]|\uD806[\uDCA0-\uDCE9\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/
- };
-
- // Ensure the condition is true, otherwise throw an error.
- // This is only to have a better contract semantic, i.e. another safety net
- // to catch a logic error. The condition shall be fulfilled in normal case.
- // Do NOT use this to enforce a certain condition on any user input.
-
- function assert(condition, message) {
- /* istanbul ignore if */
- if (!condition) {
- throw new Error('ASSERT: ' + message);
- }
- }
-
- function isDecimalDigit(ch) {
- log(NaN >= 10)
- return (ch >= 0x30 && ch <= 0x39); // 0..9
- }
-
- function isHexDigit(ch) {
- return '0123456789abcdefABCDEF'.indexOf(ch) >= 0;
- }
-
- function isOctalDigit(ch) {
- return '01234567'.indexOf(ch) >= 0;
- }
-
- function octalToDecimal(ch) {
- // \0 is not octal escape sequence
- var octal = (ch !== '0'), code = '01234567'.indexOf(ch);
-
- if (index < length && isOctalDigit(source[index])) {
- octal = true;
- code = code * 8 + '01234567'.indexOf(source[index++]);
-
- // 3 digits are only allowed when string starts
- // with 0, 1, 2, 3
- if ('0123'.indexOf(ch) >= 0 &&
- index < length &&
- isOctalDigit(source[index])) {
- code = code * 8 + '01234567'.indexOf(source[index++]);
- }
- }
-
- return {
- code: code,
- octal: octal
- };
- }
-
- // ECMA-262 11.2 White Space
-
- function isWhiteSpace(ch) {
- return (ch === 0x20) || (ch === 0x09) || (ch === 0x0B) || (ch === 0x0C) || (ch === 0xA0) ||
- (ch >= 0x1680 && [0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(ch) >= 0);
- }
-
- // ECMA-262 11.3 Line Terminators
-
- function isLineTerminator(ch) {
- return (ch === 0x0A) || (ch === 0x0D) || (ch === 0x2028) || (ch === 0x2029);
- }
-
- // ECMA-262 11.6 Identifier Names and Identifiers
-
- function fromCodePoint(cp) {
- return (cp < 0x10000) ? String.fromCharCode(cp) :
- String.fromCharCode(0xD800 + ((cp - 0x10000) >> 10)) +
- String.fromCharCode(0xDC00 + ((cp - 0x10000) & 1023));
- }
-
- function isIdentifierStart(ch) {
- return (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore)
- (ch >= 0x41 && ch <= 0x5A) || // A..Z
- (ch >= 0x61 && ch <= 0x7A) || // a..z
- (ch === 0x5C) || // \ (backslash)
- ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(fromCodePoint(ch)));
- }
-
- function isIdentifierPart(ch) {
- return (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore)
- (ch >= 0x41 && ch <= 0x5A) || // A..Z
- (ch >= 0x61 && ch <= 0x7A) || // a..z
- (ch >= 0x30 && ch <= 0x39) || // 0..9
- (ch === 0x5C) || // \ (backslash)
- ((ch >= 0x80) && Regex.NonAsciiIdentifierPart.test(fromCodePoint(ch)));
- }
-
- // ECMA-262 11.6.2.2 Future Reserved Words
-
- function isFutureReservedWord(id) {
- switch (id) {
- case 'enum':
- case 'export':
- case 'import':
- case 'super':
- return true;
- default:
- return false;
- }
- }
-
- function isStrictModeReservedWord(id) {
- switch (id) {
- case 'implements':
- case 'interface':
- case 'package':
- case 'private':
- case 'protected':
- case 'public':
- case 'static':
- case 'yield':
- case 'let':
- return true;
- default:
- return false;
- }
- }
-
- function isRestrictedWord(id) {
- return id === 'eval' || id === 'arguments';
- }
-
- // ECMA-262 11.6.2.1 Keywords
-
- function isKeyword(id) {
-
- // 'const' is specialized as Keyword in V8.
- // 'yield' and 'let' are for compatibility with SpiderMonkey and ES.next.
- // Some others are from future reserved words.
-
- switch (id.length) {
- case 2:
- return (id === 'if') || (id === 'in') || (id === 'do');
- case 3:
- return (id === 'var') || (id === 'for') || (id === 'new') ||
- (id === 'try') || (id === 'let');
- case 4:
- return (id === 'this') || (id === 'else') || (id === 'case') ||
- (id === 'void') || (id === 'with') || (id === 'enum');
- case 5:
- return (id === 'while') || (id === 'break') || (id === 'catch') ||
- (id === 'throw') || (id === 'const') || (id === 'yield') ||
- (id === 'class') || (id === 'super');
- case 6:
- return (id === 'return') || (id === 'typeof') || (id === 'delete') ||
- (id === 'switch') || (id === 'export') || (id === 'import');
- case 7:
- return (id === 'default') || (id === 'finally') || (id === 'extends');
- case 8:
- return (id === 'function') || (id === 'continue') || (id === 'debugger');
- case 10:
- return (id === 'instanceof');
- default:
- return false;
- }
- }
-
- // ECMA-262 11.4 Comments
-
- function addComment(type, value, start, end, loc) {
- var comment;
-
- assert(typeof start === 'number', 'Comment must have valid position');
-
- state.lastCommentStart = start;
-
- comment = {
- type: type,
- value: value
- };
- if (extra.range) {
- comment.range = [start, end];
- }
- if (extra.loc) {
- comment.loc = loc;
- }
- extra.comments.push(comment);
- if (extra.attachComment) {
- extra.leadingComments.push(comment);
- extra.trailingComments.push(comment);
- }
- }
-
- function skipSingleLineComment(offset) {
- var start, loc, ch, comment;
-
- start = index - offset;
- loc = {
- start: {
- line: lineNumber,
- column: index - lineStart - offset
- }
- };
-
- while (index < length) {
- ch = source.charCodeAt(index);
- ++index;
- if (isLineTerminator(ch)) {
- hasLineTerminator = true;
- if (extra.comments) {
- comment = source.slice(start + offset, index - 1);
- loc.end = {
- line: lineNumber,
- column: index - lineStart - 1
- };
- addComment('Line', comment, start, index - 1, loc);
- }
- if (ch === 13 && source.charCodeAt(index) === 10) {
- ++index;
- }
- ++lineNumber;
- lineStart = index;
- return;
- }
- }
-
- if (extra.comments) {
- comment = source.slice(start + offset, index);
- loc.end = {
- line: lineNumber,
- column: index - lineStart
- };
- addComment('Line', comment, start, index, loc);
- }
- }
-
- function skipMultiLineComment() {
- var start, loc, ch, comment;
-
- if (extra.comments) {
- start = index - 2;
- loc = {
- start: {
- line: lineNumber,
- column: index - lineStart - 2
- }
- };
- }
-
- while (index < length) {
- ch = source.charCodeAt(index);
- if (isLineTerminator(ch)) {
- if (ch === 0x0D && source.charCodeAt(index + 1) === 0x0A) {
- ++index;
- }
- hasLineTerminator = true;
- ++lineNumber;
- ++index;
- lineStart = index;
- } else if (ch === 0x2A) {
- // Block comment ends with '*/'.
- if (source.charCodeAt(index + 1) === 0x2F) {
- ++index;
- ++index;
- if (extra.comments) {
- comment = source.slice(start + 2, index - 2);
- loc.end = {
- line: lineNumber,
- column: index - lineStart
- };
- addComment('Block', comment, start, index, loc);
- }
- return;
- }
- ++index;
- } else {
- ++index;
- }
- }
-
- // Ran off the end of the file - the whole thing is a comment
- if (extra.comments) {
- loc.end = {
- line: lineNumber,
- column: index - lineStart
- };
- comment = source.slice(start + 2, index);
- addComment('Block', comment, start, index, loc);
- }
- tolerateUnexpectedToken();
- }
-
- function skipComment() {
- var ch, start;
- hasLineTerminator = false;
-
- start = (index === 0);
- while (index < length) {
- ch = source.charCodeAt(index);
-
- if (isWhiteSpace(ch)) {
- ++index;
- } else if (isLineTerminator(ch)) {
- hasLineTerminator = true;
- ++index;
- if (ch === 0x0D && source.charCodeAt(index) === 0x0A) {
- ++index;
- }
- ++lineNumber;
- lineStart = index;
- start = true;
- } else if (ch === 0x2F) { // U+002F is '/'
- ch = source.charCodeAt(index + 1);
- if (ch === 0x2F) {
- ++index;
- ++index;
- skipSingleLineComment(2);
- start = true;
- } else if (ch === 0x2A) { // U+002A is '*'
- ++index;
- ++index;
- skipMultiLineComment();
- } else {
- break;
- }
- } else if (start && ch === 0x2D) { // U+002D is '-'
- // U+003E is '>'
- if ((source.charCodeAt(index + 1) === 0x2D) && (source.charCodeAt(index + 2) === 0x3E)) {
- // '-->' is a single-line comment
- index += 3;
- skipSingleLineComment(3);
- } else {
- break;
- }
- } else if (ch === 0x3C) { // U+003C is '<'
- if (source.slice(index + 1, index + 4) === '!--') {
- ++index; // `<`
- ++index; // `!`
- ++index; // `-`
- ++index; // `-`
- skipSingleLineComment(4);
- } else {
- break;
- }
- } else {
- break;
- }
- }
- }
-
- function scanHexEscape(prefix) {
- var i, len, ch, code = 0;
-
- len = (prefix === 'u') ? 4 : 2;
- for (i = 0; i < len; ++i) {
- if (index < length && isHexDigit(source[index])) {
- ch = source[index++];
- code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
- } else {
- return '';
- }
- }
- return String.fromCharCode(code);
- }
-
- function scanUnicodeCodePointEscape() {
- var ch, code;
-
- ch = source[index];
- code = 0;
-
- // At least, one hex digit is required.
- if (ch === '}') {
- throwUnexpectedToken();
- }
-
- while (index < length) {
- ch = source[index++];
- if (!isHexDigit(ch)) {
- break;
- }
- code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
- }
-
- if (code > 0x10FFFF || ch !== '}') {
- throwUnexpectedToken();
- }
-
- return fromCodePoint(code);
- }
-
- function codePointAt(i) {
- var cp, first, second;
-
- cp = source.charCodeAt(i);
- if (cp >= 0xD800 && cp <= 0xDBFF) {
- second = source.charCodeAt(i + 1);
- if (second >= 0xDC00 && second <= 0xDFFF) {
- first = cp;
- cp = (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
- }
- }
-
- return cp;
- }
-
- function getComplexIdentifier() {
- var cp, ch, id;
-
- cp = codePointAt(index);
- id = fromCodePoint(cp);
- index += id.length;
-
- // '\u' (U+005C, U+0075) denotes an escaped character.
- if (cp === 0x5C) {
- if (source.charCodeAt(index) !== 0x75) {
- throwUnexpectedToken();
- }
- ++index;
- if (source[index] === '{') {
- ++index;
- ch = scanUnicodeCodePointEscape();
- } else {
- ch = scanHexEscape('u');
- cp = ch.charCodeAt(0);
- if (!ch || ch === '\\' || !isIdentifierStart(cp)) {
- throwUnexpectedToken();
- }
- }
- id = ch;
- }
-
- while (index < length) {
- cp = codePointAt(index);
- if (!isIdentifierPart(cp)) {
- break;
- }
- ch = fromCodePoint(cp);
- id += ch;
- index += ch.length;
-
- // '\u' (U+005C, U+0075) denotes an escaped character.
- if (cp === 0x5C) {
- id = id.substr(0, id.length - 1);
- if (source.charCodeAt(index) !== 0x75) {
- throwUnexpectedToken();
- }
- ++index;
- if (source[index] === '{') {
- ++index;
- ch = scanUnicodeCodePointEscape();
- } else {
- ch = scanHexEscape('u');
- cp = ch.charCodeAt(0);
- if (!ch || ch === '\\' || !isIdentifierPart(cp)) {
- throwUnexpectedToken();
- }
- }
- id += ch;
- }
- }
-
- return id;
- }
-
- function getIdentifier() {
- var start, ch;
-
- start = index++;
- while (index < length) {
- ch = source.charCodeAt(index);
- if (ch === 0x5C) {
- // Blackslash (U+005C) marks Unicode escape sequence.
- index = start;
- return getComplexIdentifier();
- } else if (ch >= 0xD800 && ch < 0xDFFF) {
- // Need to handle surrogate pairs.
- index = start;
- return getComplexIdentifier();
- }
- if (isIdentifierPart(ch)) {
- ++index;
- } else {
- break;
- }
- }
-
- return source.slice(start, index);
- }
-
- function scanIdentifier() {
- var start, id, type;
-
- start = index;
-
- // Backslash (U+005C) starts an escaped character.
- id = (source.charCodeAt(index) === 0x5C) ? getComplexIdentifier() : getIdentifier();
-
- // There is no keyword or literal with only one character.
- // Thus, it must be an identifier.
- if (id.length === 1) {
- type = Token.Identifier;
- } else if (isKeyword(id)) {
- type = Token.Keyword;
- } else if (id === 'null') {
- type = Token.NullLiteral;
- } else if (id === 'true' || id === 'false') {
- type = Token.BooleanLiteral;
- } else {
- type = Token.Identifier;
- }
-
- return {
- type: type,
- value: id,
- lineNumber: lineNumber,
- lineStart: lineStart,
- start: start,
- end: index
- };
- }
-
-
- // ECMA-262 11.7 Punctuators
-
- function scanPunctuator() {
- var token, str;
-
- token = {
- type: Token.Punctuator,
- value: '',
- lineNumber: lineNumber,
- lineStart: lineStart,
- start: index,
- end: index
- };
-
- // Check for most common single-character punctuators.
- str = source[index];
- switch (str) {
-
- case '(':
- if (extra.tokenize) {
- extra.openParenToken = extra.tokens.length;
- }
- ++index;
- break;
-
- case '{':
- if (extra.tokenize) {
- extra.openCurlyToken = extra.tokens.length;
- }
- state.curlyStack.push('{');
- ++index;
- break;
-
- case '.':
- ++index;
- if (source[index] === '.' && source[index + 1] === '.') {
- // Spread operator: ...
- index += 2;
- str = '...';
- }
- break;
-
- case '}':
- ++index;
- state.curlyStack.pop();
- break;
- case ')':
- case ';':
- case ',':
- case '[':
- case ']':
- case ':':
- case '?':
- case '~':
- ++index;
- break;
-
- default:
- // 4-character punctuator.
- str = source.substr(index, 4);
- if (str === '>>>=') {
- index += 4;
- } else {
-
- // 3-character punctuators.
- str = str.substr(0, 3);
- if (str === '===' || str === '!==' || str === '>>>' ||
- str === '<<=' || str === '>>=') {
- index += 3;
- } else {
-
- // 2-character punctuators.
- str = str.substr(0, 2);
- if (str === '&&' || str === '||' || str === '==' || str === '!=' ||
- str === '+=' || str === '-=' || str === '*=' || str === '/=' ||
- str === '++' || str === '--' || str === '<<' || str === '>>' ||
- str === '&=' || str === '|=' || str === '^=' || str === '%=' ||
- str === '<=' || str === '>=' || str === '=>') {
- index += 2;
- } else {
-
- // 1-character punctuators.
- str = source[index];
- if ('<>=!+-*%&|^/'.indexOf(str) >= 0) {
- ++index;
- }
- }
- }
- }
- }
-
- if (index === token.start) {
- throwUnexpectedToken();
- }
-
- token.end = index;
- token.value = str;
- return token;
- }
-
- // ECMA-262 11.8.3 Numeric Literals
-
- function scanHexLiteral(start) {
- var number = '';
-
- while (index < length) {
- if (!isHexDigit(source[index])) {
- break;
- }
- number += source[index++];
- }
-
- if (number.length === 0) {
- throwUnexpectedToken();
- }
-
- if (isIdentifierStart(source.charCodeAt(index))) {
- throwUnexpectedToken();
- }
-
- return {
- type: Token.NumericLiteral,
- value: parseInt('0x' + number, 16),
- lineNumber: lineNumber,
- lineStart: lineStart,
- start: start,
- end: index
- };
- }
-
- function scanBinaryLiteral(start) {
- var ch, number;
-
- number = '';
-
- while (index < length) {
- ch = source[index];
- if (ch !== '0' && ch !== '1') {
- break;
- }
- number += source[index++];
- }
-
- if (number.length === 0) {
- // only 0b or 0B
- throwUnexpectedToken();
- }
-
- if (index < length) {
- ch = source.charCodeAt(index);
- /* istanbul ignore else */
- if (isIdentifierStart(ch) || isDecimalDigit(ch)) {
- throwUnexpectedToken();
- }
- }
-
- return {
- type: Token.NumericLiteral,
- value: parseInt(number, 2),
- lineNumber: lineNumber,
- lineStart: lineStart,
- start: start,
- end: index
- };
- }
-
- function scanOctalLiteral(prefix, start) {
- var number, octal;
-
- if (isOctalDigit(prefix)) {
- octal = true;
- number = '0' + source[index++];
- } else {
- octal = false;
- ++index;
- number = '';
- }
-
- while (index < length) {
- if (!isOctalDigit(source[index])) {
- break;
- }
- number += source[index++];
- }
-
- if (!octal && number.length === 0) {
- // only 0o or 0O
- throwUnexpectedToken();
- }
-
- if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) {
- throwUnexpectedToken();
- }
-
- return {
- type: Token.NumericLiteral,
- value: parseInt(number, 8),
- octal: octal,
- lineNumber: lineNumber,
- lineStart: lineStart,
- start: start,
- end: index
- };
- }
-
- function isImplicitOctalLiteral() {
- var i, ch;
-
- // Implicit octal, unless there is a non-octal digit.
- // (Annex B.1.1 on Numeric Literals)
- for (i = index + 1; i < length; ++i) {
- ch = source[i];
- if (ch === '8' || ch === '9') {
- return false;
- }
- if (!isOctalDigit(ch)) {
- return true;
- }
- }
-
- return true;
- }
-
- function scanNumericLiteral() {
- var number, start, ch;
-
- ch = source[index];
- assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'),
- 'Numeric literal must start with a decimal digit or a decimal point');
-
- start = index;
- number = '';
- if (ch !== '.') {
- number = source[index++];
- ch = source[index];
-
- // Hex number starts with '0x'.
- // Octal number starts with '0'.
- // Octal number in ES6 starts with '0o'.
- // Binary number in ES6 starts with '0b'.
- if (number === '0') {
- if (ch === 'x' || ch === 'X') {
- ++index;
- return scanHexLiteral(start);
- }
- if (ch === 'b' || ch === 'B') {
- ++index;
- return scanBinaryLiteral(start);
- }
- if (ch === 'o' || ch === 'O') {
- return scanOctalLiteral(ch, start);
- }
-
- if (isOctalDigit(ch)) {
- if (isImplicitOctalLiteral()) {
- return scanOctalLiteral(ch, start);
- }
- }
- }
-
- while (isDecimalDigit(source.charCodeAt(index))) {
- log(index)
- number += source[index++];
- }
- ch = source[index];
- }
-
- if (ch === '.') {
- number += source[index++];
- while (isDecimalDigit(source.charCodeAt(index))) {
- number += source[index++];
- }
- ch = source[index];
- }
-
- if (ch === 'e' || ch === 'E') {
- number += source[index++];
-
- ch = source[index];
- if (ch === '+' || ch === '-') {
- number += source[index++];
- }
- if (isDecimalDigit(source.charCodeAt(index))) {
- while (isDecimalDigit(source.charCodeAt(index))) {
- number += source[index++];
- }
- } else {
- throwUnexpectedToken();
- }
- }
-
- if (isIdentifierStart(source.charCodeAt(index))) {
- throwUnexpectedToken();
- }
-
- return {
- type: Token.NumericLiteral,
- value: parseFloat(number),
- lineNumber: lineNumber,
- lineStart: lineStart,
- start: start,
- end: index
- };
- }
-
- // ECMA-262 11.8.4 String Literals
-
- function scanStringLiteral() {
- var str = '', quote, start, ch, unescaped, octToDec, octal = false;
-
- quote = source[index];
- assert((quote === '\'' || quote === '"'),
- 'String literal must starts with a quote');
-
- start = index;
- ++index;
-
- while (index < length) {
- ch = source[index++];
-
- if (ch === quote) {
- quote = '';
- break;
- } else if (ch === '\\') {
- ch = source[index++];
- if (!ch || !isLineTerminator(ch.charCodeAt(0))) {
- switch (ch) {
- case 'u':
- case 'x':
- if (source[index] === '{') {
- ++index;
- str += scanUnicodeCodePointEscape();
- } else {
- unescaped = scanHexEscape(ch);
- if (!unescaped) {
- throw throwUnexpectedToken();
- }
- str += unescaped;
- }
- break;
- case 'n':
- str += '\n';
- break;
- case 'r':
- str += '\r';
- break;
- case 't':
- str += '\t';
- break;
- case 'b':
- str += '\b';
- break;
- case 'f':
- str += '\f';
- break;
- case 'v':
- str += '\x0B';
- break;
- case '8':
- case '9':
- str += ch;
- tolerateUnexpectedToken();
- break;
-
- default:
- if (isOctalDigit(ch)) {
- octToDec = octalToDecimal(ch);
-
- octal = octToDec.octal || octal;
- str += String.fromCharCode(octToDec.code);
- } else {
- str += ch;
- }
- break;
- }
- } else {
- ++lineNumber;
- if (ch === '\r' && source[index] === '\n') {
- ++index;
- }
- lineStart = index;
- }
- } else if (isLineTerminator(ch.charCodeAt(0))) {
- break;
- } else {
- str += ch;
- }
- }
-
- if (quote !== '') {
- throwUnexpectedToken();
- }
-
- return {
- type: Token.StringLiteral,
- value: str,
- octal: octal,
- lineNumber: startLineNumber,
- lineStart: startLineStart,
- start: start,
- end: index
- };
- }
-
- // ECMA-262 11.8.6 Template Literal Lexical Components
-
- function scanTemplate() {
- var cooked = '', ch, start, rawOffset, terminated, head, tail, restore, unescaped;
-
- terminated = false;
- tail = false;
- start = index;
- head = (source[index] === '`');
- rawOffset = 2;
-
- ++index;
-
- while (index < length) {
- ch = source[index++];
- if (ch === '`') {
- rawOffset = 1;
- tail = true;
- terminated = true;
- break;
- } else if (ch === '$') {
- if (source[index] === '{') {
- state.curlyStack.push('${');
- ++index;
- terminated = true;
- break;
- }
- cooked += ch;
- } else if (ch === '\\') {
- ch = source[index++];
- if (!isLineTerminator(ch.charCodeAt(0))) {
- switch (ch) {
- case 'n':
- cooked += '\n';
- break;
- case 'r':
- cooked += '\r';
- break;
- case 't':
- cooked += '\t';
- break;
- case 'u':
- case 'x':
- if (source[index] === '{') {
- ++index;
- cooked += scanUnicodeCodePointEscape();
- } else {
- restore = index;
- unescaped = scanHexEscape(ch);
- if (unescaped) {
- cooked += unescaped;
- } else {
- index = restore;
- cooked += ch;
- }
- }
- break;
- case 'b':
- cooked += '\b';
- break;
- case 'f':
- cooked += '\f';
- break;
- case 'v':
- cooked += '\v';
- break;
-
- default:
- if (ch === '0') {
- if (isDecimalDigit(source.charCodeAt(index))) {
- // Illegal: \01 \02 and so on
- throwError(Messages.TemplateOctalLiteral);
- }
- cooked += '\0';
- } else if (isOctalDigit(ch)) {
- // Illegal: \1 \2
- throwError(Messages.TemplateOctalLiteral);
- } else {
- cooked += ch;
- }
- break;
- }
- } else {
- ++lineNumber;
- if (ch === '\r' && source[index] === '\n') {
- ++index;
- }
- lineStart = index;
- }
- } else if (isLineTerminator(ch.charCodeAt(0))) {
- ++lineNumber;
- if (ch === '\r' && source[index] === '\n') {
- ++index;
- }
- lineStart = index;
- cooked += '\n';
- } else {
- cooked += ch;
- }
- }
-
- if (!terminated) {
- throwUnexpectedToken();
- }
-
- if (!head) {
- state.curlyStack.pop();
- }
-
- return {
- type: Token.Template,
- value: {
- cooked: cooked,
- raw: source.slice(start + 1, index - rawOffset)
- },
- head: head,
- tail: tail,
- lineNumber: lineNumber,
- lineStart: lineStart,
- start: start,
- end: index
- };
- }
-
- // ECMA-262 11.8.5 Regular Expression Literals
-
- function testRegExp(pattern, flags) {
- // The BMP character to use as a replacement for astral symbols when
- // translating an ES6 "u"-flagged pattern to an ES5-compatible
- // approximation.
- // Note: replacing with '\uFFFF' enables false positives in unlikely
- // scenarios. For example, `[\u{1044f}-\u{10440}]` is an invalid
- // pattern that would not be detected by this substitution.
- var astralSubstitute = '\uFFFF',
- tmp = pattern;
-
- if (flags.indexOf('u') >= 0) {
- tmp = tmp
- // Replace every Unicode escape sequence with the equivalent
- // BMP character or a constant ASCII code point in the case of
- // astral symbols. (See the above note on `astralSubstitute`
- // for more information.)
- .replace(/\\u\{([0-9a-fA-F]+)\}|\\u([a-fA-F0-9]{4})/g, function ($0, $1, $2) {
- var codePoint = parseInt($1 || $2, 16);
- if (codePoint > 0x10FFFF) {
- throwUnexpectedToken(null, Messages.InvalidRegExp);
- }
- if (codePoint <= 0xFFFF) {
- return String.fromCharCode(codePoint);
- }
- return astralSubstitute;
- })
- // Replace each paired surrogate with a single ASCII symbol to
- // avoid throwing on regular expressions that are only valid in
- // combination with the "u" flag.
- .replace(
- /[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
- astralSubstitute
- );
- }
-
- // First, detect invalid regular expressions.
- try {
- RegExp(tmp);
- } catch (e) {
- throwUnexpectedToken(null, Messages.InvalidRegExp);
- }
-
- // Return a regular expression object for this pattern-flag pair, or
- // `null` in case the current environment doesn't support the flags it
- // uses.
- try {
- return new RegExp(pattern, flags);
- } catch (exception) {
- return null;
- }
- }
-
- function scanRegExpBody() {
- var ch, str, classMarker, terminated, body;
-
- ch = source[index];
- assert(ch === '/', 'Regular expression literal must start with a slash');
- str = source[index++];
-
- classMarker = false;
- terminated = false;
- while (index < length) {
- ch = source[index++];
- str += ch;
- if (ch === '\\') {
- ch = source[index++];
- // ECMA-262 7.8.5
- if (isLineTerminator(ch.charCodeAt(0))) {
- throwUnexpectedToken(null, Messages.UnterminatedRegExp);
- }
- str += ch;
- } else if (isLineTerminator(ch.charCodeAt(0))) {
- throwUnexpectedToken(null, Messages.UnterminatedRegExp);
- } else if (classMarker) {
- if (ch === ']') {
- classMarker = false;
- }
- } else {
- if (ch === '/') {
- terminated = true;
- break;
- } else if (ch === '[') {
- classMarker = true;
- }
- }
- }
-
- if (!terminated) {
- throwUnexpectedToken(null, Messages.UnterminatedRegExp);
- }
-
- // Exclude leading and trailing slash.
- body = str.substr(1, str.length - 2);
- return {
- value: body,
- literal: str
- };
- }
-
- function scanRegExpFlags() {
- var ch, str, flags, restore;
-
- str = '';
- flags = '';
- while (index < length) {
- ch = source[index];
- if (!isIdentifierPart(ch.charCodeAt(0))) {
- break;
- }
-
- ++index;
- if (ch === '\\' && index < length) {
- ch = source[index];
- if (ch === 'u') {
- ++index;
- restore = index;
- ch = scanHexEscape('u');
- if (ch) {
- flags += ch;
- for (str += '\\u'; restore < index; ++restore) {
- str += source[restore];
- }
- } else {
- index = restore;
- flags += 'u';
- str += '\\u';
- }
- tolerateUnexpectedToken();
- } else {
- str += '\\';
- tolerateUnexpectedToken();
- }
- } else {
- flags += ch;
- str += ch;
- }
- }
-
- return {
- value: flags,
- literal: str
- };
- }
-
- function scanRegExp() {
- var start, body, flags, value;
- scanning = true;
-
- lookahead = null;
- skipComment();
- start = index;
-
- body = scanRegExpBody();
- flags = scanRegExpFlags();
- value = testRegExp(body.value, flags.value);
- scanning = false;
- if (extra.tokenize) {
- return {
- type: Token.RegularExpression,
- value: value,
- regex: {
- pattern: body.value,
- flags: flags.value
- },
- lineNumber: lineNumber,
- lineStart: lineStart,
- start: start,
- end: index
- };
- }
-
- return {
- literal: body.literal + flags.literal,
- value: value,
- regex: {
- pattern: body.value,
- flags: flags.value
- },
- start: start,
- end: index
- };
- }
-
- function collectRegex() {
- var pos, loc, regex, token;
-
- skipComment();
-
- pos = index;
- loc = {
- start: {
- line: lineNumber,
- column: index - lineStart
- }
- };
-
- regex = scanRegExp();
-
- loc.end = {
- line: lineNumber,
- column: index - lineStart
- };
-
- /* istanbul ignore next */
- if (!extra.tokenize) {
- // Pop the previous token, which is likely '/' or '/='
- if (extra.tokens.length > 0) {
- token = extra.tokens[extra.tokens.length - 1];
- if (token.range[0] === pos && token.type === 'Punctuator') {
- if (token.value === '/' || token.value === '/=') {
- extra.tokens.pop();
- }
- }
- }
-
- extra.tokens.push({
- type: 'RegularExpression',
- value: regex.literal,
- regex: regex.regex,
- range: [pos, index],
- loc: loc
- });
- }
-
- return regex;
- }
-
- function isIdentifierName(token) {
- return token.type === Token.Identifier ||
- token.type === Token.Keyword ||
- token.type === Token.BooleanLiteral ||
- token.type === Token.NullLiteral;
- }
-
- function advanceSlash() {
- var prevToken,
- checkToken;
- // Using the following algorithm:
- // https://github.com/mozilla/sweet.js/wiki/design
- prevToken = extra.tokens[extra.tokens.length - 1];
- if (!prevToken) {
- // Nothing before that: it cannot be a division.
- return collectRegex();
- }
- if (prevToken.type === 'Punctuator') {
- if (prevToken.value === ']') {
- return scanPunctuator();
- }
- if (prevToken.value === ')') {
- checkToken = extra.tokens[extra.openParenToken - 1];
- if (checkToken &&
- checkToken.type === 'Keyword' &&
- (checkToken.value === 'if' ||
- checkToken.value === 'while' ||
- checkToken.value === 'for' ||
- checkToken.value === 'with')) {
- return collectRegex();
- }
- return scanPunctuator();
- }
- if (prevToken.value === '}') {
- // Dividing a function by anything makes little sense,
- // but we have to check for that.
- if (extra.tokens[extra.openCurlyToken - 3] &&
- extra.tokens[extra.openCurlyToken - 3].type === 'Keyword') {
- // Anonymous function.
- checkToken = extra.tokens[extra.openCurlyToken - 4];
- if (!checkToken) {
- return scanPunctuator();
- }
- } else if (extra.tokens[extra.openCurlyToken - 4] &&
- extra.tokens[extra.openCurlyToken - 4].type === 'Keyword') {
- // Named function.
- checkToken = extra.tokens[extra.openCurlyToken - 5];
- if (!checkToken) {
- return collectRegex();
- }
- } else {
- return scanPunctuator();
- }
- // checkToken determines whether the function is
- // a declaration or an expression.
- if (FnExprTokens.indexOf(checkToken.value) >= 0) {
- // It is an expression.
- return scanPunctuator();
- }
- // It is a declaration.
- return collectRegex();
- }
- return collectRegex();
- }
- if (prevToken.type === 'Keyword' && prevToken.value !== 'this') {
- return collectRegex();
- }
- return scanPunctuator();
- }
-
- function advance() {
- var cp, token;
-
- if (index >= length) {
- return {
- type: Token.EOF,
- lineNumber: lineNumber,
- lineStart: lineStart,
- start: index,
- end: index
- };
- }
-
- cp = source.charCodeAt(index);
-
- if (isIdentifierStart(cp)) {
- token = scanIdentifier();
- if (strict && isStrictModeReservedWord(token.value)) {
- token.type = Token.Keyword;
- }
- return token;
- }
-
- // Very common: ( and ) and ;
- if (cp === 0x28 || cp === 0x29 || cp === 0x3B) {
- return scanPunctuator();
- }
-
- // String literal starts with single quote (U+0027) or double quote (U+0022).
- if (cp === 0x27 || cp === 0x22) {
- return scanStringLiteral();
- }
-
- // Dot (.) U+002E can also start a floating-point number, hence the need
- // to check the next character.
- if (cp === 0x2E) {
- if (isDecimalDigit(source.charCodeAt(index + 1))) {
- return scanNumericLiteral();
- }
- return scanPunctuator();
- }
-
- if (isDecimalDigit(cp)) {
- return scanNumericLiteral();
- }
-
- // Slash (/) U+002F can also start a regex.
- if (extra.tokenize && cp === 0x2F) {
- return advanceSlash();
- }
-
- // Template literals start with ` (U+0060) for template head
- // or } (U+007D) for template middle or template tail.
- if (cp === 0x60 || (cp === 0x7D && state.curlyStack[state.curlyStack.length - 1] === '${')) {
- return scanTemplate();
- }
-
- // Possible identifier start in a surrogate pair.
- if (cp >= 0xD800 && cp < 0xDFFF) {
- cp = codePointAt(index);
- if (isIdentifierStart(cp)) {
- return scanIdentifier();
- }
- }
-
- return scanPunctuator();
- }
-
- function collectToken() {
- var loc, token, value, entry;
-
- loc = {
- start: {
- line: lineNumber,
- column: index - lineStart
- }
- };
-
- token = advance();
- loc.end = {
- line: lineNumber,
- column: index - lineStart
- };
-
- if (token.type !== Token.EOF) {
- value = source.slice(token.start, token.end);
- entry = {
- type: TokenName[token.type],
- value: value,
- range: [token.start, token.end],
- loc: loc
- };
- if (token.regex) {
- entry.regex = {
- pattern: token.regex.pattern,
- flags: token.regex.flags
- };
- }
- extra.tokens.push(entry);
- }
-
- return token;
- }
-
- function lex() {
- var token;
- scanning = true;
-
- lastIndex = index;
- lastLineNumber = lineNumber;
- lastLineStart = lineStart;
-
- skipComment();
-
- token = lookahead;
-
- startIndex = index;
- startLineNumber = lineNumber;
- startLineStart = lineStart;
-
- lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance();
- scanning = false;
- return token;
- }
-
- function peek() {
- scanning = true;
-
- skipComment();
-
- lastIndex = index;
- lastLineNumber = lineNumber;
- lastLineStart = lineStart;
-
- startIndex = index;
- startLineNumber = lineNumber;
- startLineStart = lineStart;
-
- lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance();
- scanning = false;
- }
-
- function Position() {
- this.line = startLineNumber;
- this.column = startIndex - startLineStart;
- }
-
- function SourceLocation() {
- this.start = new Position();
- this.end = null;
- }
-
- function WrappingSourceLocation(startToken) {
- this.start = {
- line: startToken.lineNumber,
- column: startToken.start - startToken.lineStart
- };
- this.end = null;
- }
-
- function Node() {
- if (extra.range) {
- this.range = [startIndex, 0];
- }
- if (extra.loc) {
- this.loc = new SourceLocation();
- }
- }
-
- function WrappingNode(startToken) {
- if (extra.range) {
- this.range = [startToken.start, 0];
- }
- if (extra.loc) {
- this.loc = new WrappingSourceLocation(startToken);
- }
- }
-
- WrappingNode.prototype = Node.prototype = {
-
- processComment: function () {
- var lastChild,
- leadingComments,
- trailingComments,
- bottomRight = extra.bottomRightStack,
- i,
- comment,
- last = bottomRight[bottomRight.length - 1];
-
- if (this.type === Syntax.Program) {
- if (this.body.length > 0) {
- return;
- }
- }
-
- if (extra.trailingComments.length > 0) {
- trailingComments = [];
- for (i = extra.trailingComments.length - 1; i >= 0; --i) {
- comment = extra.trailingComments[i];
- if (comment.range[0] >= this.range[1]) {
- trailingComments.unshift(comment);
- extra.trailingComments.splice(i, 1);
- }
- }
- extra.trailingComments = [];
- } else {
- if (last && last.trailingComments && last.trailingComments[0].range[0] >= this.range[1]) {
- trailingComments = last.trailingComments;
- delete last.trailingComments;
- }
- }
-
- // Eating the stack.
- while (last && last.range[0] >= this.range[0]) {
- lastChild = bottomRight.pop();
- last = bottomRight[bottomRight.length - 1];
- }
-
- if (lastChild) {
- if (lastChild.leadingComments) {
- leadingComments = [];
- for (i = lastChild.leadingComments.length - 1; i >= 0; --i) {
- comment = lastChild.leadingComments[i];
- if (comment.range[1] <= this.range[0]) {
- leadingComments.unshift(comment);
- lastChild.leadingComments.splice(i, 1);
- }
- }
-
- if (!lastChild.leadingComments.length) {
- lastChild.leadingComments = undefined;
- }
- }
- } else if (extra.leadingComments.length > 0) {
- leadingComments = [];
- for (i = extra.leadingComments.length - 1; i >= 0; --i) {
- comment = extra.leadingComments[i];
- if (comment.range[1] <= this.range[0]) {
- leadingComments.unshift(comment);
- extra.leadingComments.splice(i, 1);
- }
- }
- }
-
-
- if (leadingComments && leadingComments.length > 0) {
- this.leadingComments = leadingComments;
- }
- if (trailingComments && trailingComments.length > 0) {
- this.trailingComments = trailingComments;
- }
-
- bottomRight.push(this);
- },
-
- finish: function () {
- if (extra.range) {
- this.range[1] = lastIndex;
- }
- if (extra.loc) {
- this.loc.end = {
- line: lastLineNumber,
- column: lastIndex - lastLineStart
- };
- if (extra.source) {
- this.loc.source = extra.source;
- }
- }
-
- if (extra.attachComment) {
- this.processComment();
- }
- },
-
- finishArrayExpression: function (elements) {
- this.type = Syntax.ArrayExpression;
- this.elements = elements;
- this.finish();
- return this;
- },
-
- finishArrayPattern: function (elements) {
- this.type = Syntax.ArrayPattern;
- this.elements = elements;
- this.finish();
- return this;
- },
-
- finishArrowFunctionExpression: function (params, defaults, body, expression) {
- this.type = Syntax.ArrowFunctionExpression;
- this.id = null;
- this.params = params;
- this.defaults = defaults;
- this.body = body;
- this.generator = false;
- this.expression = expression;
- this.finish();
- return this;
- },
-
- finishAssignmentExpression: function (operator, left, right) {
- this.type = Syntax.AssignmentExpression;
- this.operator = operator;
- this.left = left;
- this.right = right;
- this.finish();
- return this;
- },
-
- finishAssignmentPattern: function (left, right) {
- this.type = Syntax.AssignmentPattern;
- this.left = left;
- this.right = right;
- this.finish();
- return this;
- },
-
- finishBinaryExpression: function (operator, left, right) {
- this.type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression : Syntax.BinaryExpression;
- this.operator = operator;
- this.left = left;
- this.right = right;
- this.finish();
- return this;
- },
-
- finishBlockStatement: function (body) {
- this.type = Syntax.BlockStatement;
- this.body = body;
- this.finish();
- return this;
- },
-
- finishBreakStatement: function (label) {
- this.type = Syntax.BreakStatement;
- this.label = label;
- this.finish();
- return this;
- },
-
- finishCallExpression: function (callee, args) {
- this.type = Syntax.CallExpression;
- this.callee = callee;
- this.arguments = args;
- this.finish();
- return this;
- },
-
- finishCatchClause: function (param, body) {
- this.type = Syntax.CatchClause;
- this.param = param;
- this.body = body;
- this.finish();
- return this;
- },
-
- finishClassBody: function (body) {
- this.type = Syntax.ClassBody;
- this.body = body;
- this.finish();
- return this;
- },
-
- finishClassDeclaration: function (id, superClass, body) {
- this.type = Syntax.ClassDeclaration;
- this.id = id;
- this.superClass = superClass;
- this.body = body;
- this.finish();
- return this;
- },
-
- finishClassExpression: function (id, superClass, body) {
- this.type = Syntax.ClassExpression;
- this.id = id;
- this.superClass = superClass;
- this.body = body;
- this.finish();
- return this;
- },
-
- finishConditionalExpression: function (test, consequent, alternate) {
- this.type = Syntax.ConditionalExpression;
- this.test = test;
- this.consequent = consequent;
- this.alternate = alternate;
- this.finish();
- return this;
- },
-
- finishContinueStatement: function (label) {
- this.type = Syntax.ContinueStatement;
- this.label = label;
- this.finish();
- return this;
- },
-
- finishDebuggerStatement: function () {
- this.type = Syntax.DebuggerStatement;
- this.finish();
- return this;
- },
-
- finishDoWhileStatement: function (body, test) {
- this.type = Syntax.DoWhileStatement;
- this.body = body;
- this.test = test;
- this.finish();
- return this;
- },
-
- finishEmptyStatement: function () {
- this.type = Syntax.EmptyStatement;
- this.finish();
- return this;
- },
-
- finishExpressionStatement: function (expression) {
- this.type = Syntax.ExpressionStatement;
- this.expression = expression;
- this.finish();
- return this;
- },
-
- finishForStatement: function (init, test, update, body) {
- this.type = Syntax.ForStatement;
- this.init = init;
- this.test = test;
- this.update = update;
- this.body = body;
- this.finish();
- return this;
- },
-
- finishForOfStatement: function (left, right, body) {
- this.type = Syntax.ForOfStatement;
- this.left = left;
- this.right = right;
- this.body = body;
- this.finish();
- return this;
- },
-
- finishForInStatement: function (left, right, body) {
- this.type = Syntax.ForInStatement;
- this.left = left;
- this.right = right;
- this.body = body;
- this.each = false;
- this.finish();
- return this;
- },
-
- finishFunctionDeclaration: function (id, params, defaults, body, generator) {
- this.type = Syntax.FunctionDeclaration;
- this.id = id;
- this.params = params;
- this.defaults = defaults;
- this.body = body;
- this.generator = generator;
- this.expression = false;
- this.finish();
- return this;
- },
-
- finishFunctionExpression: function (id, params, defaults, body, generator) {
- this.type = Syntax.FunctionExpression;
- this.id = id;
- this.params = params;
- this.defaults = defaults;
- this.body = body;
- this.generator = generator;
- this.expression = false;
- this.finish();
- return this;
- },
-
- finishIdentifier: function (name) {
- this.type = Syntax.Identifier;
- this.name = name;
- this.finish();
- return this;
- },
-
- finishIfStatement: function (test, consequent, alternate) {
- this.type = Syntax.IfStatement;
- this.test = test;
- this.consequent = consequent;
- this.alternate = alternate;
- this.finish();
- return this;
- },
-
- finishLabeledStatement: function (label, body) {
- this.type = Syntax.LabeledStatement;
- this.label = label;
- this.body = body;
- this.finish();
- return this;
- },
-
- finishLiteral: function (token) {
- this.type = Syntax.Literal;
- this.value = token.value;
- this.raw = source.slice(token.start, token.end);
- if (token.regex) {
- this.regex = token.regex;
- }
- this.finish();
- return this;
- },
-
- finishMemberExpression: function (accessor, object, property) {
- this.type = Syntax.MemberExpression;
- this.computed = accessor === '[';
- this.object = object;
- this.property = property;
- this.finish();
- return this;
- },
-
- finishMetaProperty: function (meta, property) {
- this.type = Syntax.MetaProperty;
- this.meta = meta;
- this.property = property;
- this.finish();
- return this;
- },
-
- finishNewExpression: function (callee, args) {
- this.type = Syntax.NewExpression;
- this.callee = callee;
- this.arguments = args;
- this.finish();
- return this;
- },
-
- finishObjectExpression: function (properties) {
- this.type = Syntax.ObjectExpression;
- this.properties = properties;
- this.finish();
- return this;
- },
-
- finishObjectPattern: function (properties) {
- this.type = Syntax.ObjectPattern;
- this.properties = properties;
- this.finish();
- return this;
- },
-
- finishPostfixExpression: function (operator, argument) {
- this.type = Syntax.UpdateExpression;
- this.operator = operator;
- this.argument = argument;
- this.prefix = false;
- this.finish();
- return this;
- },
-
- finishProgram: function (body, sourceType) {
- this.type = Syntax.Program;
- this.body = body;
- this.sourceType = sourceType;
- this.finish();
- return this;
- },
-
- finishProperty: function (kind, key, computed, value, method, shorthand) {
- this.type = Syntax.Property;
- this.key = key;
- this.computed = computed;
- this.value = value;
- this.kind = kind;
- this.method = method;
- this.shorthand = shorthand;
- this.finish();
- return this;
- },
-
- finishRestElement: function (argument) {
- this.type = Syntax.RestElement;
- this.argument = argument;
- this.finish();
- return this;
- },
-
- finishReturnStatement: function (argument) {
- this.type = Syntax.ReturnStatement;
- this.argument = argument;
- this.finish();
- return this;
- },
-
- finishSequenceExpression: function (expressions) {
- this.type = Syntax.SequenceExpression;
- this.expressions = expressions;
- this.finish();
- return this;
- },
-
- finishSpreadElement: function (argument) {
- this.type = Syntax.SpreadElement;
- this.argument = argument;
- this.finish();
- return this;
- },
-
- finishSwitchCase: function (test, consequent) {
- this.type = Syntax.SwitchCase;
- this.test = test;
- this.consequent = consequent;
- this.finish();
- return this;
- },
-
- finishSuper: function () {
- this.type = Syntax.Super;
- this.finish();
- return this;
- },
-
- finishSwitchStatement: function (discriminant, cases) {
- this.type = Syntax.SwitchStatement;
- this.discriminant = discriminant;
- this.cases = cases;
- this.finish();
- return this;
- },
-
- finishTaggedTemplateExpression: function (tag, quasi) {
- this.type = Syntax.TaggedTemplateExpression;
- this.tag = tag;
- this.quasi = quasi;
- this.finish();
- return this;
- },
-
- finishTemplateElement: function (value, tail) {
- this.type = Syntax.TemplateElement;
- this.value = value;
- this.tail = tail;
- this.finish();
- return this;
- },
-
- finishTemplateLiteral: function (quasis, expressions) {
- this.type = Syntax.TemplateLiteral;
- this.quasis = quasis;
- this.expressions = expressions;
- this.finish();
- return this;
- },
-
- finishThisExpression: function () {
- this.type = Syntax.ThisExpression;
- this.finish();
- return this;
- },
-
- finishThrowStatement: function (argument) {
- this.type = Syntax.ThrowStatement;
- this.argument = argument;
- this.finish();
- return this;
- },
-
- finishTryStatement: function (block, handler, finalizer) {
- this.type = Syntax.TryStatement;
- this.block = block;
- this.guardedHandlers = [];
- this.handlers = handler ? [handler] : [];
- this.handler = handler;
- this.finalizer = finalizer;
- this.finish();
- return this;
- },
-
- finishUnaryExpression: function (operator, argument) {
- this.type = (operator === '++' || operator === '--') ? Syntax.UpdateExpression : Syntax.UnaryExpression;
- this.operator = operator;
- this.argument = argument;
- this.prefix = true;
- this.finish();
- return this;
- },
-
- finishVariableDeclaration: function (declarations) {
- this.type = Syntax.VariableDeclaration;
- this.declarations = declarations;
- this.kind = 'var';
- this.finish();
- return this;
- },
-
- finishLexicalDeclaration: function (declarations, kind) {
- this.type = Syntax.VariableDeclaration;
- this.declarations = declarations;
- this.kind = kind;
- this.finish();
- return this;
- },
-
- finishVariableDeclarator: function (id, init) {
- this.type = Syntax.VariableDeclarator;
- this.id = id;
- this.init = init;
- this.finish();
- return this;
- },
-
- finishWhileStatement: function (test, body) {
- this.type = Syntax.WhileStatement;
- this.test = test;
- this.body = body;
- this.finish();
- return this;
- },
-
- finishWithStatement: function (object, body) {
- this.type = Syntax.WithStatement;
- this.object = object;
- this.body = body;
- this.finish();
- return this;
- },
-
- finishExportSpecifier: function (local, exported) {
- this.type = Syntax.ExportSpecifier;
- this.exported = exported || local;
- this.local = local;
- this.finish();
- return this;
- },
-
- finishImportDefaultSpecifier: function (local) {
- this.type = Syntax.ImportDefaultSpecifier;
- this.local = local;
- this.finish();
- return this;
- },
-
- finishImportNamespaceSpecifier: function (local) {
- this.type = Syntax.ImportNamespaceSpecifier;
- this.local = local;
- this.finish();
- return this;
- },
-
- finishExportNamedDeclaration: function (declaration, specifiers, src) {
- this.type = Syntax.ExportNamedDeclaration;
- this.declaration = declaration;
- this.specifiers = specifiers;
- this.source = src;
- this.finish();
- return this;
- },
-
- finishExportDefaultDeclaration: function (declaration) {
- this.type = Syntax.ExportDefaultDeclaration;
- this.declaration = declaration;
- this.finish();
- return this;
- },
-
- finishExportAllDeclaration: function (src) {
- this.type = Syntax.ExportAllDeclaration;
- this.source = src;
- this.finish();
- return this;
- },
-
- finishImportSpecifier: function (local, imported) {
- this.type = Syntax.ImportSpecifier;
- this.local = local || imported;
- this.imported = imported;
- this.finish();
- return this;
- },
-
- finishImportDeclaration: function (specifiers, src) {
- this.type = Syntax.ImportDeclaration;
- this.specifiers = specifiers;
- this.source = src;
- this.finish();
- return this;
- },
-
- finishYieldExpression: function (argument, delegate) {
- this.type = Syntax.YieldExpression;
- this.argument = argument;
- this.delegate = delegate;
- this.finish();
- return this;
- }
- };
-
-
- function recordError(error) {
- var e, existing;
-
- for (e = 0; e < extra.errors.length; e++) {
- existing = extra.errors[e];
- // Prevent duplicated error.
- /* istanbul ignore next */
- if (existing.index === error.index && existing.message === error.message) {
- return;
- }
- }
-
- extra.errors.push(error);
- }
-
- function constructError(msg, column) {
- var error = new Error(msg);
- try {
- throw error;
- } catch (base) {
- /* istanbul ignore else */
- if (Object.create && Object.defineProperty) {
- error = Object.create(base);
- Object.defineProperty(error, 'column', { value: column });
- }
- } finally {
- return error;
- }
- }
-
- function createError(line, pos, description) {
- var msg, column, error;
-
- msg = 'Line ' + line + ': ' + description;
- column = pos - (scanning ? lineStart : lastLineStart) + 1;
- error = constructError(msg, column);
- error.lineNumber = line;
- error.description = description;
- error.index = pos;
- return error;
- }
-
- // Throw an exception
-
- function throwError(messageFormat) {
- var args, msg;
-
- args = Array.prototype.slice.call(arguments, 1);
- msg = messageFormat.replace(/%(\d)/g,
- function (whole, idx) {
- assert(idx < args.length, 'Message reference must be in range');
- return args[idx];
- }
- );
-
- throw createError(lastLineNumber, lastIndex, msg);
- }
-
- function tolerateError(messageFormat) {
- var args, msg, error;
- log(JSON.stringify(arguments))
- args = Array.prototype.slice.call(arguments, 1);
- log('here')
- log(args)
- /* istanbul ignore next */
- msg = messageFormat.replace(/%(\d)/g,
- function (whole, idx) {
- assert(idx < args.length, 'Message reference must be in range');
- return args[idx];
- }
- );
-
- error = createError(lineNumber, lastIndex, msg);
- if (extra.errors) {
- recordError(error);
- } else {
- throw error;
- }
- }
-
- // Throw an exception because of the token.
-
- function unexpectedTokenError(token, message) {
- var value, msg = message || Messages.UnexpectedToken;
-
- if (token) {
- if (!message) {
- msg = (token.type === Token.EOF) ? Messages.UnexpectedEOS :
- (token.type === Token.Identifier) ? Messages.UnexpectedIdentifier :
- (token.type === Token.NumericLiteral) ? Messages.UnexpectedNumber :
- (token.type === Token.StringLiteral) ? Messages.UnexpectedString :
- (token.type === Token.Template) ? Messages.UnexpectedTemplate :
- Messages.UnexpectedToken;
-
- if (token.type === Token.Keyword) {
- if (isFutureReservedWord(token.value)) {
- msg = Messages.UnexpectedReserved;
- } else if (strict && isStrictModeReservedWord(token.value)) {
- msg = Messages.StrictReservedWord;
- }
- }
- }
-
- value = (token.type === Token.Template) ? token.value.raw : token.value;
- } else {
- value = 'ILLEGAL';
- }
-
- msg = msg.replace('%0', value);
-
- return (token && typeof token.lineNumber === 'number') ?
- createError(token.lineNumber, token.start, msg) :
- createError(scanning ? lineNumber : lastLineNumber, scanning ? index : lastIndex, msg);
- }
-
- function throwUnexpectedToken(token, message) {
- throw unexpectedTokenError(token, message);
- }
-
- function tolerateUnexpectedToken(token, message) {
- var error = unexpectedTokenError(token, message);
- if (extra.errors) {
- recordError(error);
- } else {
- throw error;
- }
- }
-
- // Expect the next token to match the specified punctuator.
- // If not, an exception will be thrown.
-
- function expect(value) {
- var token = lex();
- if (token.type !== Token.Punctuator || token.value !== value) {
- throwUnexpectedToken(token);
- }
- }
-
- /**
- * @name expectCommaSeparator
- * @description Quietly expect a comma when in tolerant mode, otherwise delegates
- * to expect(value)
- * @since 2.0
- */
- function expectCommaSeparator() {
- var token;
-
- if (extra.errors) {
- token = lookahead;
- if (token.type === Token.Punctuator && token.value === ',') {
- lex();
- } else if (token.type === Token.Punctuator && token.value === ';') {
- lex();
- tolerateUnexpectedToken(token);
- } else {
- tolerateUnexpectedToken(token, Messages.UnexpectedToken);
- }
- } else {
- expect(',');
- }
- }
-
- // Expect the next token to match the specified keyword.
- // If not, an exception will be thrown.
-
- function expectKeyword(keyword) {
- var token = lex();
- if (token.type !== Token.Keyword || token.value !== keyword) {
- throwUnexpectedToken(token);
- }
- }
-
- // Return true if the next token matches the specified punctuator.
-
- function match(value) {
- return lookahead.type === Token.Punctuator && lookahead.value === value;
- }
-
- // Return true if the next token matches the specified keyword
-
- function matchKeyword(keyword) {
- return lookahead.type === Token.Keyword && lookahead.value === keyword;
- }
-
- // Return true if the next token matches the specified contextual keyword
- // (where an identifier is sometimes a keyword depending on the context)
-
- function matchContextualKeyword(keyword) {
- return lookahead.type === Token.Identifier && lookahead.value === keyword;
- }
-
- // Return true if the next token is an assignment operator
-
- function matchAssign() {
- var op;
-
- if (lookahead.type !== Token.Punctuator) {
- return false;
- }
- op = lookahead.value;
- return op === '=' ||
- op === '*=' ||
- op === '/=' ||
- op === '%=' ||
- op === '+=' ||
- op === '-=' ||
- op === '<<=' ||
- op === '>>=' ||
- op === '>>>=' ||
- op === '&=' ||
- op === '^=' ||
- op === '|=';
- }
-
- function consumeSemicolon() {
- // Catch the very common case first: immediately a semicolon (U+003B).
- if (source.charCodeAt(startIndex) === 0x3B || match(';')) {
- lex();
- return;
- }
-
- if (hasLineTerminator) {
- return;
- }
-
- // FIXME(ikarienator): this is seemingly an issue in the previous location info convention.
- lastIndex = startIndex;
- lastLineNumber = startLineNumber;
- lastLineStart = startLineStart;
-
- if (lookahead.type !== Token.EOF && !match('}')) {
- throwUnexpectedToken(lookahead);
- }
- }
-
- // Cover grammar support.
- //
- // When an assignment expression position starts with an left parenthesis, the determination of the type
- // of the syntax is to be deferred arbitrarily long until the end of the parentheses pair (plus a lookahead)
- // or the first comma. This situation also defers the determination of all the expressions nested in the pair.
- //
- // There are three productions that can be parsed in a parentheses pair that needs to be determined
- // after the outermost pair is closed. They are:
- //
- // 1. AssignmentExpression
- // 2. BindingElements
- // 3. AssignmentTargets
- //
- // In order to avoid exponential backtracking, we use two flags to denote if the production can be
- // binding element or assignment target.
- //
- // The three productions have the relationship:
- //
- // BindingElements ⊆ AssignmentTargets ⊆ AssignmentExpression
- //
- // with a single exception that CoverInitializedName when used directly in an Expression, generates
- // an early error. Therefore, we need the third state, firstCoverInitializedNameError, to track the
- // first usage of CoverInitializedName and report it when we reached the end of the parentheses pair.
- //
- // isolateCoverGrammar function runs the given parser function with a new cover grammar context, and it does not
- // effect the current flags. This means the production the parser parses is only used as an expression. Therefore
- // the CoverInitializedName check is conducted.
- //
- // inheritCoverGrammar function runs the given parse function with a new cover grammar context, and it propagates
- // the flags outside of the parser. This means the production the parser parses is used as a part of a potential
- // pattern. The CoverInitializedName check is deferred.
- function isolateCoverGrammar(parser) {
- var oldIsBindingElement = isBindingElement,
- oldIsAssignmentTarget = isAssignmentTarget,
- oldFirstCoverInitializedNameError = firstCoverInitializedNameError,
- result;
- isBindingElement = true;
- isAssignmentTarget = true;
- firstCoverInitializedNameError = null;
- result = parser();
- if (firstCoverInitializedNameError !== null) {
- throwUnexpectedToken(firstCoverInitializedNameError);
- }
- isBindingElement = oldIsBindingElement;
- isAssignmentTarget = oldIsAssignmentTarget;
- firstCoverInitializedNameError = oldFirstCoverInitializedNameError;
- return result;
- }
-
- function inheritCoverGrammar(parser) {
- var oldIsBindingElement = isBindingElement,
- oldIsAssignmentTarget = isAssignmentTarget,
- oldFirstCoverInitializedNameError = firstCoverInitializedNameError,
- result;
- isBindingElement = true;
- isAssignmentTarget = true;
- firstCoverInitializedNameError = null;
- result = parser();
- isBindingElement = isBindingElement && oldIsBindingElement;
- isAssignmentTarget = isAssignmentTarget && oldIsAssignmentTarget;
- firstCoverInitializedNameError = oldFirstCoverInitializedNameError || firstCoverInitializedNameError;
- return result;
- }
-
- // ECMA-262 13.3.3 Destructuring Binding Patterns
-
- function parseArrayPattern(params, kind) {
- var node = new Node(), elements = [], rest, restNode;
- expect('[');
-
- while (!match(']')) {
- if (match(',')) {
- lex();
- elements.push(null);
- } else {
- if (match('...')) {
- restNode = new Node();
- lex();
- params.push(lookahead);
- rest = parseVariableIdentifier(params, kind);
- elements.push(restNode.finishRestElement(rest));
- break;
- } else {
- elements.push(parsePatternWithDefault(params, kind));
- }
- if (!match(']')) {
- expect(',');
- }
- }
-
- }
-
- expect(']');
-
- return node.finishArrayPattern(elements);
- }
-
- function parsePropertyPattern(params, kind) {
- var node = new Node(), key, keyToken, computed = match('['), init;
- if (lookahead.type === Token.Identifier) {
- keyToken = lookahead;
- key = parseVariableIdentifier();
- if (match('=')) {
- params.push(keyToken);
- lex();
- init = parseAssignmentExpression();
-
- return node.finishProperty(
- 'init', key, false,
- new WrappingNode(keyToken).finishAssignmentPattern(key, init), false, false);
- } else if (!match(':')) {
- params.push(keyToken);
- return node.finishProperty('init', key, false, key, false, true);
- }
- } else {
- key = parseObjectPropertyKey(params, kind);
- }
- expect(':');
- init = parsePatternWithDefault(params, kind);
- return node.finishProperty('init', key, computed, init, false, false);
- }
-
- function parseObjectPattern(params, kind) {
- var node = new Node(), properties = [];
-
- expect('{');
-
- while (!match('}')) {
- properties.push(parsePropertyPattern(params, kind));
- if (!match('}')) {
- expect(',');
- }
- }
-
- lex();
-
- return node.finishObjectPattern(properties);
- }
-
- function parsePattern(params, kind) {
- if (match('[')) {
- return parseArrayPattern(params, kind);
- } else if (match('{')) {
- return parseObjectPattern(params, kind);
- }
- params.push(lookahead);
- return parseVariableIdentifier(kind);
- }
-
- function parsePatternWithDefault(params, kind) {
- var startToken = lookahead, pattern, previousAllowYield, right;
- pattern = parsePattern(params, kind);
- if (match('=')) {
- lex();
- previousAllowYield = state.allowYield;
- state.allowYield = true;
- right = isolateCoverGrammar(parseAssignmentExpression);
- state.allowYield = previousAllowYield;
- pattern = new WrappingNode(startToken).finishAssignmentPattern(pattern, right);
- }
- return pattern;
- }
-
- // ECMA-262 12.2.5 Array Initializer
-
- function parseArrayInitializer() {
- var elements = [], node = new Node(), restSpread;
-
- expect('[');
-
- while (!match(']')) {
- if (match(',')) {
- lex();
- elements.push(null);
- } else if (match('...')) {
- restSpread = new Node();
- lex();
- restSpread.finishSpreadElement(inheritCoverGrammar(parseAssignmentExpression));
-
- if (!match(']')) {
- isAssignmentTarget = isBindingElement = false;
- expect(',');
- }
- elements.push(restSpread);
- } else {
- elements.push(inheritCoverGrammar(parseAssignmentExpression));
-
- if (!match(']')) {
- expect(',');
- }
- }
- }
-
- lex();
-
- return node.finishArrayExpression(elements);
- }
-
- // ECMA-262 12.2.6 Object Initializer
-
- function parsePropertyFunction(node, paramInfo, isGenerator) {
- var previousStrict, body;
-
- isAssignmentTarget = isBindingElement = false;
-
- previousStrict = strict;
- body = isolateCoverGrammar(parseFunctionSourceElements);
-
- if (strict && paramInfo.firstRestricted) {
- tolerateUnexpectedToken(paramInfo.firstRestricted, paramInfo.message);
- }
- if (strict && paramInfo.stricted) {
- tolerateUnexpectedToken(paramInfo.stricted, paramInfo.message);
- }
-
- strict = previousStrict;
- return node.finishFunctionExpression(null, paramInfo.params, paramInfo.defaults, body, isGenerator);
- }
-
- function parsePropertyMethodFunction() {
- var params, method, node = new Node(),
- previousAllowYield = state.allowYield;
-
- state.allowYield = false;
- params = parseParams();
- state.allowYield = previousAllowYield;
-
- state.allowYield = false;
- method = parsePropertyFunction(node, params, false);
- state.allowYield = previousAllowYield;
-
- return method;
- }
-
- function parseObjectPropertyKey() {
- var token, node = new Node(), expr;
-
- token = lex();
-
- // Note: This function is called only from parseObjectProperty(), where
- // EOF and Punctuator tokens are already filtered out.
-
- switch (token.type) {
- case Token.StringLiteral:
- case Token.NumericLiteral:
- if (strict && token.octal) {
- tolerateUnexpectedToken(token, Messages.StrictOctalLiteral);
- }
- return node.finishLiteral(token);
- case Token.Identifier:
- case Token.BooleanLiteral:
- case Token.NullLiteral:
- case Token.Keyword:
- return node.finishIdentifier(token.value);
- case Token.Punctuator:
- if (token.value === '[') {
- expr = isolateCoverGrammar(parseAssignmentExpression);
- expect(']');
- return expr;
- }
- break;
- }
- throwUnexpectedToken(token);
- }
-
- function lookaheadPropertyName() {
- switch (lookahead.type) {
- case Token.Identifier:
- case Token.StringLiteral:
- case Token.BooleanLiteral:
- case Token.NullLiteral:
- case Token.NumericLiteral:
- case Token.Keyword:
- return true;
- case Token.Punctuator:
- return lookahead.value === '[';
- }
- return false;
- }
-
- // This function is to try to parse a MethodDefinition as defined in 14.3. But in the case of object literals,
- // it might be called at a position where there is in fact a short hand identifier pattern or a data property.
- // This can only be determined after we consumed up to the left parentheses.
- //
- // In order to avoid back tracking, it returns `null` if the position is not a MethodDefinition and the caller
- // is responsible to visit other options.
- function tryParseMethodDefinition(token, key, computed, node) {
- var value, options, methodNode, params,
- previousAllowYield = state.allowYield;
-
- if (token.type === Token.Identifier) {
- // check for `get` and `set`;
-
- if (token.value === 'get' && lookaheadPropertyName()) {
- computed = match('[');
- key = parseObjectPropertyKey();
- methodNode = new Node();
- expect('(');
- expect(')');
-
- state.allowYield = false;
- value = parsePropertyFunction(methodNode, {
- params: [],
- defaults: [],
- stricted: null,
- firstRestricted: null,
- message: null
- }, false);
- state.allowYield = previousAllowYield;
-
- return node.finishProperty('get', key, computed, value, false, false);
- } else if (token.value === 'set' && lookaheadPropertyName()) {
- computed = match('[');
- key = parseObjectPropertyKey();
- methodNode = new Node();
- expect('(');
-
- options = {
- params: [],
- defaultCount: 0,
- defaults: [],
- firstRestricted: null,
- paramSet: {}
- };
- if (match(')')) {
- tolerateUnexpectedToken(lookahead);
- } else {
- state.allowYield = false;
- parseParam(options);
- state.allowYield = previousAllowYield;
- if (options.defaultCount === 0) {
- options.defaults = [];
- }
- }
- expect(')');
-
- state.allowYield = false;
- value = parsePropertyFunction(methodNode, options, false);
- state.allowYield = previousAllowYield;
-
- return node.finishProperty('set', key, computed, value, false, false);
- }
- } else if (token.type === Token.Punctuator && token.value === '*' && lookaheadPropertyName()) {
- computed = match('[');
- key = parseObjectPropertyKey();
- methodNode = new Node();
-
- state.allowYield = true;
- params = parseParams();
- state.allowYield = previousAllowYield;
-
- state.allowYield = false;
- value = parsePropertyFunction(methodNode, params, true);
- state.allowYield = previousAllowYield;
-
- return node.finishProperty('init', key, computed, value, true, false);
- }
-
- if (key && match('(')) {
- value = parsePropertyMethodFunction();
- return node.finishProperty('init', key, computed, value, true, false);
- }
-
- // Not a MethodDefinition.
- return null;
- }
-
- function parseObjectProperty(hasProto) {
- var token = lookahead, node = new Node(), computed, key, maybeMethod, proto, value;
-
- computed = match('[');
- if (match('*')) {
- lex();
- } else {
- key = parseObjectPropertyKey();
- }
- maybeMethod = tryParseMethodDefinition(token, key, computed, node);
- if (maybeMethod) {
- return maybeMethod;
- }
-
- if (!key) {
- throwUnexpectedToken(lookahead);
- }
-
- // Check for duplicated __proto__
- if (!computed) {
- proto = (key.type === Syntax.Identifier && key.name === '__proto__') ||
- (key.type === Syntax.Literal && key.value === '__proto__');
- if (hasProto.value && proto) {
- tolerateError(Messages.DuplicateProtoProperty);
- }
- hasProto.value |= proto;
- }
-
- if (match(':')) {
- lex();
- value = inheritCoverGrammar(parseAssignmentExpression);
- return node.finishProperty('init', key, computed, value, false, false);
- }
-
- if (token.type === Token.Identifier) {
- if (match('=')) {
- firstCoverInitializedNameError = lookahead;
- lex();
- value = isolateCoverGrammar(parseAssignmentExpression);
- return node.finishProperty('init', key, computed,
- new WrappingNode(token).finishAssignmentPattern(key, value), false, true);
- }
- return node.finishProperty('init', key, computed, key, false, true);
- }
-
- throwUnexpectedToken(lookahead);
- }
-
- function parseObjectInitializer() {
- var properties = [], hasProto = {value: false}, node = new Node();
-
- expect('{');
-
- while (!match('}')) {
- properties.push(parseObjectProperty(hasProto));
-
- if (!match('}')) {
- expectCommaSeparator();
- }
- }
-
- expect('}');
-
- return node.finishObjectExpression(properties);
- }
-
- function reinterpretExpressionAsPattern(expr) {
- var i;
- switch (expr.type) {
- case Syntax.Identifier:
- case Syntax.MemberExpression:
- case Syntax.RestElement:
- case Syntax.AssignmentPattern:
- break;
- case Syntax.SpreadElement:
- expr.type = Syntax.RestElement;
- reinterpretExpressionAsPattern(expr.argument);
- break;
- case Syntax.ArrayExpression:
- expr.type = Syntax.ArrayPattern;
- for (i = 0; i < expr.elements.length; i++) {
- if (expr.elements[i] !== null) {
- reinterpretExpressionAsPattern(expr.elements[i]);
- }
- }
- break;
- case Syntax.ObjectExpression:
- expr.type = Syntax.ObjectPattern;
- for (i = 0; i < expr.properties.length; i++) {
- reinterpretExpressionAsPattern(expr.properties[i].value);
- }
- break;
- case Syntax.AssignmentExpression:
- expr.type = Syntax.AssignmentPattern;
- reinterpretExpressionAsPattern(expr.left);
- break;
- default:
- // Allow other node type for tolerant parsing.
- break;
- }
- }
-
- // ECMA-262 12.2.9 Template Literals
-
- function parseTemplateElement(option) {
- var node, token;
-
- if (lookahead.type !== Token.Template || (option.head && !lookahead.head)) {
- throwUnexpectedToken();
- }
-
- node = new Node();
- token = lex();
-
- return node.finishTemplateElement({ raw: token.value.raw, cooked: token.value.cooked }, token.tail);
- }
-
- function parseTemplateLiteral() {
- var quasi, quasis, expressions, node = new Node();
-
- quasi = parseTemplateElement({ head: true });
- quasis = [quasi];
- expressions = [];
-
- while (!quasi.tail) {
- expressions.push(parseExpression());
- quasi = parseTemplateElement({ head: false });
- quasis.push(quasi);
- }
-
- return node.finishTemplateLiteral(quasis, expressions);
- }
-
- // ECMA-262 12.2.10 The Grouping Operator
-
- function parseGroupExpression() {
- var expr, expressions, startToken, i, params = [];
-
- expect('(');
-
- if (match(')')) {
- lex();
- if (!match('=>')) {
- expect('=>');
- }
- return {
- type: PlaceHolders.ArrowParameterPlaceHolder,
- params: [],
- rawParams: []
- };
- }
-
- startToken = lookahead;
- if (match('...')) {
- expr = parseRestElement(params);
- expect(')');
- if (!match('=>')) {
- expect('=>');
- }
- return {
- type: PlaceHolders.ArrowParameterPlaceHolder,
- params: [expr]
- };
- }
-
- isBindingElement = true;
- expr = inheritCoverGrammar(parseAssignmentExpression);
-
- if (match(',')) {
- isAssignmentTarget = false;
- expressions = [expr];
-
- while (startIndex < length) {
- if (!match(',')) {
- break;
- }
- lex();
-
- if (match('...')) {
- if (!isBindingElement) {
- throwUnexpectedToken(lookahead);
- }
- expressions.push(parseRestElement(params));
- expect(')');
- if (!match('=>')) {
- expect('=>');
- }
- isBindingElement = false;
- for (i = 0; i < expressions.length; i++) {
- reinterpretExpressionAsPattern(expressions[i]);
- }
- return {
- type: PlaceHolders.ArrowParameterPlaceHolder,
- params: expressions
- };
- }
-
- expressions.push(inheritCoverGrammar(parseAssignmentExpression));
- }
-
- expr = new WrappingNode(startToken).finishSequenceExpression(expressions);
- }
-
-
- expect(')');
-
- if (match('=>')) {
- if (expr.type === Syntax.Identifier && expr.name === 'yield') {
- return {
- type: PlaceHolders.ArrowParameterPlaceHolder,
- params: [expr]
- };
- }
-
- if (!isBindingElement) {
- throwUnexpectedToken(lookahead);
- }
-
- if (expr.type === Syntax.SequenceExpression) {
- for (i = 0; i < expr.expressions.length; i++) {
- reinterpretExpressionAsPattern(expr.expressions[i]);
- }
- } else {
- reinterpretExpressionAsPattern(expr);
- }
-
- expr = {
- type: PlaceHolders.ArrowParameterPlaceHolder,
- params: expr.type === Syntax.SequenceExpression ? expr.expressions : [expr]
- };
- }
- isBindingElement = false;
- return expr;
- }
-
-
- // ECMA-262 12.2 Primary Expressions
-
- function parsePrimaryExpression() {
- var type, token, expr, node;
-
- if (match('(')) {
- isBindingElement = false;
- return inheritCoverGrammar(parseGroupExpression);
- }
-
- if (match('[')) {
- return inheritCoverGrammar(parseArrayInitializer);
- }
-
- if (match('{')) {
- return inheritCoverGrammar(parseObjectInitializer);
- }
-
- type = lookahead.type;
- node = new Node();
-
- if (type === Token.Identifier) {
- if (state.sourceType === 'module' && lookahead.value === 'await') {
- tolerateUnexpectedToken(lookahead);
- }
- expr = node.finishIdentifier(lex().value);
- } else if (type === Token.StringLiteral || type === Token.NumericLiteral) {
- isAssignmentTarget = isBindingElement = false;
- if (strict && lookahead.octal) {
- tolerateUnexpectedToken(lookahead, Messages.StrictOctalLiteral);
- }
- expr = node.finishLiteral(lex());
- } else if (type === Token.Keyword) {
- if (!strict && state.allowYield && matchKeyword('yield')) {
- return parseNonComputedProperty();
- }
- isAssignmentTarget = isBindingElement = false;
- if (matchKeyword('function')) {
- return parseFunctionExpression();
- }
- if (matchKeyword('this')) {
- lex();
- return node.finishThisExpression();
- }
- if (matchKeyword('class')) {
- return parseClassExpression();
- }
- throwUnexpectedToken(lex());
- } else if (type === Token.BooleanLiteral) {
- isAssignmentTarget = isBindingElement = false;
- token = lex();
- token.value = (token.value === 'true');
- expr = node.finishLiteral(token);
- } else if (type === Token.NullLiteral) {
- isAssignmentTarget = isBindingElement = false;
- token = lex();
- token.value = null;
- expr = node.finishLiteral(token);
- } else if (match('/') || match('/=')) {
- isAssignmentTarget = isBindingElement = false;
- index = startIndex;
-
- if (typeof extra.tokens !== 'undefined') {
- token = collectRegex();
- } else {
- token = scanRegExp();
- }
- lex();
- expr = node.finishLiteral(token);
- } else if (type === Token.Template) {
- expr = parseTemplateLiteral();
- } else {
- throwUnexpectedToken(lex());
- }
-
- return expr;
- }
-
- // ECMA-262 12.3 Left-Hand-Side Expressions
-
- function parseArguments() {
- var args = [], expr;
-
- expect('(');
-
- if (!match(')')) {
- while (startIndex < length) {
- if (match('...')) {
- expr = new Node();
- lex();
- expr.finishSpreadElement(isolateCoverGrammar(parseAssignmentExpression));
- } else {
- expr = isolateCoverGrammar(parseAssignmentExpression);
- }
- args.push(expr);
- if (match(')')) {
- break;
- }
- expectCommaSeparator();
- }
- }
-
- expect(')');
-
- return args;
- }
-
- function parseNonComputedProperty() {
- var token, node = new Node();
-
- token = lex();
-
- if (!isIdentifierName(token)) {
- throwUnexpectedToken(token);
- }
-
- return node.finishIdentifier(token.value);
- }
-
- function parseNonComputedMember() {
- expect('.');
-
- return parseNonComputedProperty();
- }
-
- function parseComputedMember() {
- var expr;
-
- expect('[');
-
- expr = isolateCoverGrammar(parseExpression);
-
- expect(']');
-
- return expr;
- }
-
- // ECMA-262 12.3.3 The new Operator
-
- function parseNewExpression() {
- var callee, args, node = new Node();
-
- expectKeyword('new');
-
- if (match('.')) {
- lex();
- if (lookahead.type === Token.Identifier && lookahead.value === 'target') {
- if (state.inFunctionBody) {
- lex();
- return node.finishMetaProperty('new', 'target');
- }
- }
- throwUnexpectedToken(lookahead);
- }
-
- callee = isolateCoverGrammar(parseLeftHandSideExpression);
- args = match('(') ? parseArguments() : [];
-
- isAssignmentTarget = isBindingElement = false;
-
- return node.finishNewExpression(callee, args);
- }
-
- // ECMA-262 12.3.4 Function Calls
-
- function parseLeftHandSideExpressionAllowCall() {
- var quasi, expr, args, property, startToken, previousAllowIn = state.allowIn;
-
- startToken = lookahead;
- state.allowIn = true;
-
- if (matchKeyword('super') && state.inFunctionBody) {
- expr = new Node();
- lex();
- expr = expr.finishSuper();
- if (!match('(') && !match('.') && !match('[')) {
- throwUnexpectedToken(lookahead);
- }
- } else {
- expr = inheritCoverGrammar(matchKeyword('new') ? parseNewExpression : parsePrimaryExpression);
- }
-
- for (;;) {
- if (match('.')) {
- isBindingElement = false;
- isAssignmentTarget = true;
- property = parseNonComputedMember();
- expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property);
- } else if (match('(')) {
- isBindingElement = false;
- isAssignmentTarget = false;
- args = parseArguments();
- expr = new WrappingNode(startToken).finishCallExpression(expr, args);
- } else if (match('[')) {
- isBindingElement = false;
- isAssignmentTarget = true;
- property = parseComputedMember();
- expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property);
- } else if (lookahead.type === Token.Template && lookahead.head) {
- quasi = parseTemplateLiteral();
- expr = new WrappingNode(startToken).finishTaggedTemplateExpression(expr, quasi);
- } else {
- break;
- }
- }
- state.allowIn = previousAllowIn;
-
- return expr;
- }
-
- // ECMA-262 12.3 Left-Hand-Side Expressions
-
- function parseLeftHandSideExpression() {
- var quasi, expr, property, startToken;
- assert(state.allowIn, 'callee of new expression always allow in keyword.');
-
- startToken = lookahead;
-
- if (matchKeyword('super') && state.inFunctionBody) {
- expr = new Node();
- lex();
- expr = expr.finishSuper();
- if (!match('[') && !match('.')) {
- throwUnexpectedToken(lookahead);
- }
- } else {
- expr = inheritCoverGrammar(matchKeyword('new') ? parseNewExpression : parsePrimaryExpression);
- }
-
- for (;;) {
- if (match('[')) {
- isBindingElement = false;
- isAssignmentTarget = true;
- property = parseComputedMember();
- expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property);
- } else if (match('.')) {
- isBindingElement = false;
- isAssignmentTarget = true;
- property = parseNonComputedMember();
- expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property);
- } else if (lookahead.type === Token.Template && lookahead.head) {
- quasi = parseTemplateLiteral();
- expr = new WrappingNode(startToken).finishTaggedTemplateExpression(expr, quasi);
- } else {
- break;
- }
- }
- return expr;
- }
-
- // ECMA-262 12.4 Postfix Expressions
-
- function parsePostfixExpression() {
- var expr, token, startToken = lookahead;
-
- expr = inheritCoverGrammar(parseLeftHandSideExpressionAllowCall);
-
- if (!hasLineTerminator && lookahead.type === Token.Punctuator) {
- if (match('++') || match('--')) {
- // ECMA-262 11.3.1, 11.3.2
- if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
- tolerateError(Messages.StrictLHSPostfix);
- }
-
- if (!isAssignmentTarget) {
- tolerateError(Messages.InvalidLHSInAssignment);
- }
-
- isAssignmentTarget = isBindingElement = false;
-
- token = lex();
- expr = new WrappingNode(startToken).finishPostfixExpression(token.value, expr);
- }
- }
-
- return expr;
- }
-
- // ECMA-262 12.5 Unary Operators
-
- function parseUnaryExpression() {
- var token, expr, startToken;
-
- if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) {
- expr = parsePostfixExpression();
- } else if (match('++') || match('--')) {
- startToken = lookahead;
- token = lex();
- expr = inheritCoverGrammar(parseUnaryExpression);
- // ECMA-262 11.4.4, 11.4.5
- if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
- tolerateError(Messages.StrictLHSPrefix);
- }
-
- if (!isAssignmentTarget) {
- tolerateError(Messages.InvalidLHSInAssignment);
- }
- expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
- isAssignmentTarget = isBindingElement = false;
- } else if (match('+') || match('-') || match('~') || match('!')) {
- startToken = lookahead;
- token = lex();
- expr = inheritCoverGrammar(parseUnaryExpression);
- expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
- isAssignmentTarget = isBindingElement = false;
- } else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
- startToken = lookahead;
- token = lex();
- expr = inheritCoverGrammar(parseUnaryExpression);
- expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
- if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) {
- tolerateError(Messages.StrictDelete);
- }
- isAssignmentTarget = isBindingElement = false;
- } else {
- expr = parsePostfixExpression();
- }
-
- return expr;
- }
-
- function binaryPrecedence(token, allowIn) {
- var prec = 0;
-
- if (token.type !== Token.Punctuator && token.type !== Token.Keyword) {
- return 0;
- }
-
- switch (token.value) {
- case '||':
- prec = 1;
- break;
-
- case '&&':
- prec = 2;
- break;
-
- case '|':
- prec = 3;
- break;
-
- case '^':
- prec = 4;
- break;
-
- case '&':
- prec = 5;
- break;
-
- case '==':
- case '!=':
- case '===':
- case '!==':
- prec = 6;
- break;
-
- case '<':
- case '>':
- case '<=':
- case '>=':
- case 'instanceof':
- prec = 7;
- break;
-
- case 'in':
- prec = allowIn ? 7 : 0;
- break;
-
- case '<<':
- case '>>':
- case '>>>':
- prec = 8;
- break;
-
- case '+':
- case '-':
- prec = 9;
- break;
-
- case '*':
- case '/':
- case '%':
- prec = 11;
- break;
-
- default:
- break;
- }
-
- return prec;
- }
-
- // ECMA-262 12.6 Multiplicative Operators
- // ECMA-262 12.7 Additive Operators
- // ECMA-262 12.8 Bitwise Shift Operators
- // ECMA-262 12.9 Relational Operators
- // ECMA-262 12.10 Equality Operators
- // ECMA-262 12.11 Binary Bitwise Operators
- // ECMA-262 12.12 Binary Logical Operators
-
- function parseBinaryExpression() {
- var marker, markers, expr, token, prec, stack, right, operator, left, i;
-
- marker = lookahead;
- left = inheritCoverGrammar(parseUnaryExpression);
-
- token = lookahead;
- prec = binaryPrecedence(token, state.allowIn);
- if (prec === 0) {
- return left;
- }
- isAssignmentTarget = isBindingElement = false;
- token.prec = prec;
- lex();
-
- markers = [marker, lookahead];
- right = isolateCoverGrammar(parseUnaryExpression);
-
- stack = [left, token, right];
-
- while ((prec = binaryPrecedence(lookahead, state.allowIn)) > 0) {
-
- // Reduce: make a binary expression from the three topmost entries.
- while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) {
- right = stack.pop();
- operator = stack.pop().value;
- left = stack.pop();
- markers.pop();
- expr = new WrappingNode(markers[markers.length - 1]).finishBinaryExpression(operator, left, right);
- stack.push(expr);
- }
-
- // Shift.
- token = lex();
- token.prec = prec;
- stack.push(token);
- markers.push(lookahead);
- expr = isolateCoverGrammar(parseUnaryExpression);
- stack.push(expr);
- }
-
- // Final reduce to clean-up the stack.
- i = stack.length - 1;
- expr = stack[i];
- markers.pop();
- while (i > 1) {
- expr = new WrappingNode(markers.pop()).finishBinaryExpression(stack[i - 1].value, stack[i - 2], expr);
- i -= 2;
- }
-
- return expr;
- }
-
-
- // ECMA-262 12.13 Conditional Operator
-
- function parseConditionalExpression() {
- var expr, previousAllowIn, consequent, alternate, startToken;
-
- startToken = lookahead;
-
- expr = inheritCoverGrammar(parseBinaryExpression);
- if (match('?')) {
- lex();
- previousAllowIn = state.allowIn;
- state.allowIn = true;
- consequent = isolateCoverGrammar(parseAssignmentExpression);
- state.allowIn = previousAllowIn;
- expect(':');
- alternate = isolateCoverGrammar(parseAssignmentExpression);
-
- expr = new WrappingNode(startToken).finishConditionalExpression(expr, consequent, alternate);
- isAssignmentTarget = isBindingElement = false;
- }
-
- return expr;
- }
-
- // ECMA-262 14.2 Arrow Function Definitions
-
- function parseConciseBody() {
- if (match('{')) {
- return parseFunctionSourceElements();
- }
- return isolateCoverGrammar(parseAssignmentExpression);
- }
-
- function checkPatternParam(options, param) {
- var i;
- switch (param.type) {
- case Syntax.Identifier:
- validateParam(options, param, param.name);
- break;
- case Syntax.RestElement:
- checkPatternParam(options, param.argument);
- break;
- case Syntax.AssignmentPattern:
- checkPatternParam(options, param.left);
- break;
- case Syntax.ArrayPattern:
- for (i = 0; i < param.elements.length; i++) {
- if (param.elements[i] !== null) {
- checkPatternParam(options, param.elements[i]);
- }
- }
- break;
- case Syntax.YieldExpression:
- break;
- default:
- assert(param.type === Syntax.ObjectPattern, 'Invalid type');
- for (i = 0; i < param.properties.length; i++) {
- checkPatternParam(options, param.properties[i].value);
- }
- break;
- }
- }
- function reinterpretAsCoverFormalsList(expr) {
- var i, len, param, params, defaults, defaultCount, options, token;
-
- defaults = [];
- defaultCount = 0;
- params = [expr];
-
- switch (expr.type) {
- case Syntax.Identifier:
- break;
- case PlaceHolders.ArrowParameterPlaceHolder:
- params = expr.params;
- break;
- default:
- return null;
- }
-
- options = {
- paramSet: {}
- };
-
- for (i = 0, len = params.length; i < len; i += 1) {
- param = params[i];
- switch (param.type) {
- case Syntax.AssignmentPattern:
- params[i] = param.left;
- if (param.right.type === Syntax.YieldExpression) {
- if (param.right.argument) {
- throwUnexpectedToken(lookahead);
- }
- param.right.type = Syntax.Identifier;
- param.right.name = 'yield';
- delete param.right.argument;
- delete param.right.delegate;
- }
- defaults.push(param.right);
- ++defaultCount;
- checkPatternParam(options, param.left);
- break;
- default:
- checkPatternParam(options, param);
- params[i] = param;
- defaults.push(null);
- break;
- }
- }
-
- if (strict || !state.allowYield) {
- for (i = 0, len = params.length; i < len; i += 1) {
- param = params[i];
- if (param.type === Syntax.YieldExpression) {
- throwUnexpectedToken(lookahead);
- }
- }
- }
-
- if (options.message === Messages.StrictParamDupe) {
- token = strict ? options.stricted : options.firstRestricted;
- throwUnexpectedToken(token, options.message);
- }
-
- if (defaultCount === 0) {
- defaults = [];
- }
-
- return {
- params: params,
- defaults: defaults,
- stricted: options.stricted,
- firstRestricted: options.firstRestricted,
- message: options.message
- };
- }
-
- function parseArrowFunctionExpression(options, node) {
- var previousStrict, previousAllowYield, body;
-
- if (hasLineTerminator) {
- tolerateUnexpectedToken(lookahead);
- }
- expect('=>');
-
- previousStrict = strict;
- previousAllowYield = state.allowYield;
- state.allowYield = true;
-
- body = parseConciseBody();
-
- if (strict && options.firstRestricted) {
- throwUnexpectedToken(options.firstRestricted, options.message);
- }
- if (strict && options.stricted) {
- tolerateUnexpectedToken(options.stricted, options.message);
- }
-
- strict = previousStrict;
- state.allowYield = previousAllowYield;
-
- return node.finishArrowFunctionExpression(options.params, options.defaults, body, body.type !== Syntax.BlockStatement);
- }
-
- // ECMA-262 14.4 Yield expression
-
- function parseYieldExpression() {
- var argument, expr, delegate, previousAllowYield;
-
- argument = null;
- expr = new Node();
-
- expectKeyword('yield');
-
- if (!hasLineTerminator) {
- previousAllowYield = state.allowYield;
- state.allowYield = false;
- delegate = match('*');
- if (delegate) {
- lex();
- argument = parseAssignmentExpression();
- } else {
- if (!match(';') && !match('}') && !match(')') && lookahead.type !== Token.EOF) {
- argument = parseAssignmentExpression();
- }
- }
- state.allowYield = previousAllowYield;
- }
-
- return expr.finishYieldExpression(argument, delegate);
- }
-
- // ECMA-262 12.14 Assignment Operators
-
- function parseAssignmentExpression() {
- var token, expr, right, list, startToken;
-
- startToken = lookahead;
- token = lookahead;
-
- if (!state.allowYield && matchKeyword('yield')) {
- return parseYieldExpression();
- }
-
- expr = parseConditionalExpression();
-
- if (expr.type === PlaceHolders.ArrowParameterPlaceHolder || match('=>')) {
- isAssignmentTarget = isBindingElement = false;
- list = reinterpretAsCoverFormalsList(expr);
-
- if (list) {
- firstCoverInitializedNameError = null;
- return parseArrowFunctionExpression(list, new WrappingNode(startToken));
- }
-
- return expr;
- }
-
- if (matchAssign()) {
- if (!isAssignmentTarget) {
- tolerateError(Messages.InvalidLHSInAssignment);
- }
-
- // ECMA-262 12.1.1
- if (strict && expr.type === Syntax.Identifier) {
- if (isRestrictedWord(expr.name)) {
- tolerateUnexpectedToken(token, Messages.StrictLHSAssignment);
- }
- if (isStrictModeReservedWord(expr.name)) {
- tolerateUnexpectedToken(token, Messages.StrictReservedWord);
- }
- }
-
- if (!match('=')) {
- isAssignmentTarget = isBindingElement = false;
- } else {
- reinterpretExpressionAsPattern(expr);
- }
-
- token = lex();
- right = isolateCoverGrammar(parseAssignmentExpression);
- expr = new WrappingNode(startToken).finishAssignmentExpression(token.value, expr, right);
- firstCoverInitializedNameError = null;
- }
-
- return expr;
- }
-
- // ECMA-262 12.15 Comma Operator
-
- function parseExpression() {
- var expr, startToken = lookahead, expressions;
-
- expr = isolateCoverGrammar(parseAssignmentExpression);
-
- if (match(',')) {
- expressions = [expr];
-
- while (startIndex < length) {
- if (!match(',')) {
- break;
- }
- lex();
- expressions.push(isolateCoverGrammar(parseAssignmentExpression));
- }
-
- expr = new WrappingNode(startToken).finishSequenceExpression(expressions);
- }
-
- return expr;
- }
-
- // ECMA-262 13.2 Block
-
- function parseStatementListItem() {
- if (lookahead.type === Token.Keyword) {
- switch (lookahead.value) {
- case 'export':
- if (state.sourceType !== 'module') {
- tolerateUnexpectedToken(lookahead, Messages.IllegalExportDeclaration);
- }
- return parseExportDeclaration();
- case 'import':
- if (state.sourceType !== 'module') {
- tolerateUnexpectedToken(lookahead, Messages.IllegalImportDeclaration);
- }
- return parseImportDeclaration();
- case 'const':
- case 'let':
- return parseLexicalDeclaration({inFor: false});
- case 'function':
- return parseFunctionDeclaration(new Node());
- case 'class':
- return parseClassDeclaration();
- }
- }
-
- return parseStatement();
- }
-
- function parseStatementList() {
- var list = [];
- while (startIndex < length) {
- if (match('}')) {
- break;
- }
- list.push(parseStatementListItem());
- }
-
- return list;
- }
-
- function parseBlock() {
- var block, node = new Node();
-
- expect('{');
-
- block = parseStatementList();
-
- expect('}');
-
- return node.finishBlockStatement(block);
- }
-
- // ECMA-262 13.3.2 Variable Statement
-
- function parseVariableIdentifier(kind) {
- var token, node = new Node();
-
- token = lex();
-
- if (token.type === Token.Keyword && token.value === 'yield') {
- if (strict) {
- tolerateUnexpectedToken(token, Messages.StrictReservedWord);
- } if (!state.allowYield) {
- throwUnexpectedToken(token);
- }
- } else if (token.type !== Token.Identifier) {
- if (strict && token.type === Token.Keyword && isStrictModeReservedWord(token.value)) {
- tolerateUnexpectedToken(token, Messages.StrictReservedWord);
- } else {
- if (strict || token.value !== 'let' || kind !== 'var') {
- throwUnexpectedToken(token);
- }
- }
- } else if (state.sourceType === 'module' && token.type === Token.Identifier && token.value === 'await') {
- tolerateUnexpectedToken(token);
- }
-
- return node.finishIdentifier(token.value);
- }
-
- function parseVariableDeclaration(options) {
- var init = null, id, node = new Node(), params = [];
-
- id = parsePattern(params, 'var');
-
- // ECMA-262 12.2.1
- if (strict && isRestrictedWord(id.name)) {
- tolerateError(Messages.StrictVarName);
- }
-
- if (match('=')) {
- lex();
- init = isolateCoverGrammar(parseAssignmentExpression);
- } else if (id.type !== Syntax.Identifier && !options.inFor) {
- expect('=');
- }
-
- return node.finishVariableDeclarator(id, init);
- }
-
- function parseVariableDeclarationList(options) {
- var list = [];
-
- do {
- list.push(parseVariableDeclaration({ inFor: options.inFor }));
- if (!match(',')) {
- break;
- }
- lex();
- } while (startIndex < length);
-
- return list;
- }
-
- function parseVariableStatement(node) {
- var declarations;
-
- expectKeyword('var');
-
- declarations = parseVariableDeclarationList({ inFor: false });
-
- consumeSemicolon();
-
- return node.finishVariableDeclaration(declarations);
- }
-
- // ECMA-262 13.3.1 Let and Const Declarations
-
- function parseLexicalBinding(kind, options) {
- var init = null, id, node = new Node(), params = [];
-
- id = parsePattern(params, kind);
-
- // ECMA-262 12.2.1
- if (strict && id.type === Syntax.Identifier && isRestrictedWord(id.name)) {
- tolerateError(Messages.StrictVarName);
- }
-
- if (kind === 'const') {
- if (!matchKeyword('in') && !matchContextualKeyword('of')) {
- expect('=');
- init = isolateCoverGrammar(parseAssignmentExpression);
- }
- } else if ((!options.inFor && id.type !== Syntax.Identifier) || match('=')) {
- expect('=');
- init = isolateCoverGrammar(parseAssignmentExpression);
- }
-
- return node.finishVariableDeclarator(id, init);
- }
-
- function parseBindingList(kind, options) {
- var list = [];
-
- do {
- list.push(parseLexicalBinding(kind, options));
- if (!match(',')) {
- break;
- }
- lex();
- } while (startIndex < length);
-
- return list;
- }
-
- function parseLexicalDeclaration(options) {
- var kind, declarations, node = new Node();
-
- kind = lex().value;
- assert(kind === 'let' || kind === 'const', 'Lexical declaration must be either let or const');
-
- declarations = parseBindingList(kind, options);
-
- consumeSemicolon();
-
- return node.finishLexicalDeclaration(declarations, kind);
- }
-
- function parseRestElement(params) {
- var param, node = new Node();
-
- lex();
-
- if (match('{')) {
- throwError(Messages.ObjectPatternAsRestParameter);
- }
-
- params.push(lookahead);
-
- param = parseVariableIdentifier();
-
- if (match('=')) {
- throwError(Messages.DefaultRestParameter);
- }
-
- if (!match(')')) {
- throwError(Messages.ParameterAfterRestParameter);
- }
-
- return node.finishRestElement(param);
- }
-
- // ECMA-262 13.4 Empty Statement
-
- function parseEmptyStatement(node) {
- expect(';');
- return node.finishEmptyStatement();
- }
-
- // ECMA-262 12.4 Expression Statement
-
- function parseExpressionStatement(node) {
- var expr = parseExpression();
- consumeSemicolon();
- return node.finishExpressionStatement(expr);
- }
-
- // ECMA-262 13.6 If statement
-
- function parseIfStatement(node) {
- var test, consequent, alternate;
-
- expectKeyword('if');
-
- expect('(');
-
- test = parseExpression();
-
- expect(')');
-
- consequent = parseStatement();
-
- if (matchKeyword('else')) {
- lex();
- alternate = parseStatement();
- } else {
- alternate = null;
- }
-
- return node.finishIfStatement(test, consequent, alternate);
- }
-
- // ECMA-262 13.7 Iteration Statements
-
- function parseDoWhileStatement(node) {
- var body, test, oldInIteration;
-
- expectKeyword('do');
-
- oldInIteration = state.inIteration;
- state.inIteration = true;
-
- body = parseStatement();
-
- state.inIteration = oldInIteration;
-
- expectKeyword('while');
-
- expect('(');
-
- test = parseExpression();
-
- expect(')');
-
- if (match(';')) {
- lex();
- }
-
- return node.finishDoWhileStatement(body, test);
- }
-
- function parseWhileStatement(node) {
- var test, body, oldInIteration;
-
- expectKeyword('while');
-
- expect('(');
-
- test = parseExpression();
-
- expect(')');
-
- oldInIteration = state.inIteration;
- state.inIteration = true;
-
- body = parseStatement();
-
- state.inIteration = oldInIteration;
-
- return node.finishWhileStatement(test, body);
- }
-
- function parseForStatement(node) {
- var init, forIn, initSeq, initStartToken, test, update, left, right, kind, declarations,
- body, oldInIteration, previousAllowIn = state.allowIn;
-
- init = test = update = null;
- forIn = true;
-
- expectKeyword('for');
-
- expect('(');
-
- if (match(';')) {
- lex();
- } else {
- if (matchKeyword('var')) {
- init = new Node();
- lex();
-
- state.allowIn = false;
- declarations = parseVariableDeclarationList({ inFor: true });
- state.allowIn = previousAllowIn;
-
- if (declarations.length === 1 && matchKeyword('in')) {
- init = init.finishVariableDeclaration(declarations);
- lex();
- left = init;
- right = parseExpression();
- init = null;
- } else if (declarations.length === 1 && declarations[0].init === null && matchContextualKeyword('of')) {
- init = init.finishVariableDeclaration(declarations);
- lex();
- left = init;
- right = parseAssignmentExpression();
- init = null;
- forIn = false;
- } else {
- init = init.finishVariableDeclaration(declarations);
- expect(';');
- }
- } else if (matchKeyword('const') || matchKeyword('let')) {
- init = new Node();
- kind = lex().value;
-
- state.allowIn = false;
- declarations = parseBindingList(kind, {inFor: true});
- state.allowIn = previousAllowIn;
-
- if (declarations.length === 1 && declarations[0].init === null && matchKeyword('in')) {
- init = init.finishLexicalDeclaration(declarations, kind);
- lex();
- left = init;
- right = parseExpression();
- init = null;
- } else if (declarations.length === 1 && declarations[0].init === null && matchContextualKeyword('of')) {
- init = init.finishLexicalDeclaration(declarations, kind);
- lex();
- left = init;
- right = parseAssignmentExpression();
- init = null;
- forIn = false;
- } else {
- consumeSemicolon();
- init = init.finishLexicalDeclaration(declarations, kind);
- }
- } else {
- initStartToken = lookahead;
- state.allowIn = false;
- init = inheritCoverGrammar(parseAssignmentExpression);
- state.allowIn = previousAllowIn;
-
- if (matchKeyword('in')) {
- if (!isAssignmentTarget) {
- tolerateError(Messages.InvalidLHSInForIn);
- }
-
- lex();
- reinterpretExpressionAsPattern(init);
- left = init;
- right = parseExpression();
- init = null;
- } else if (matchContextualKeyword('of')) {
- if (!isAssignmentTarget) {
- tolerateError(Messages.InvalidLHSInForLoop);
- }
-
- lex();
- reinterpretExpressionAsPattern(init);
- left = init;
- right = parseAssignmentExpression();
- init = null;
- forIn = false;
- } else {
- if (match(',')) {
- initSeq = [init];
- while (match(',')) {
- lex();
- initSeq.push(isolateCoverGrammar(parseAssignmentExpression));
- }
- init = new WrappingNode(initStartToken).finishSequenceExpression(initSeq);
- }
- expect(';');
- }
- }
- }
-
- if (typeof left === 'undefined') {
-
- if (!match(';')) {
- test = parseExpression();
- }
- expect(';');
-
- if (!match(')')) {
- update = parseExpression();
- }
- }
-
- expect(')');
-
- oldInIteration = state.inIteration;
- state.inIteration = true;
-
- body = isolateCoverGrammar(parseStatement);
-
- state.inIteration = oldInIteration;
-
- return (typeof left === 'undefined') ?
- node.finishForStatement(init, test, update, body) :
- forIn ? node.finishForInStatement(left, right, body) :
- node.finishForOfStatement(left, right, body);
- }
-
- // ECMA-262 13.8 The continue statement
-
- function parseContinueStatement(node) {
- var label = null, key;
-
- expectKeyword('continue');
-
- // Optimize the most common form: 'continue;'.
- if (source.charCodeAt(startIndex) === 0x3B) {
- lex();
-
- if (!state.inIteration) {
- throwError(Messages.IllegalContinue);
- }
-
- return node.finishContinueStatement(null);
- }
-
- if (hasLineTerminator) {
- if (!state.inIteration) {
- throwError(Messages.IllegalContinue);
- }
-
- return node.finishContinueStatement(null);
- }
-
- if (lookahead.type === Token.Identifier) {
- label = parseVariableIdentifier();
-
- key = '$' + label.name;
- if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
- throwError(Messages.UnknownLabel, label.name);
- }
- }
-
- consumeSemicolon();
-
- if (label === null && !state.inIteration) {
- throwError(Messages.IllegalContinue);
- }
-
- return node.finishContinueStatement(label);
- }
-
- // ECMA-262 13.9 The break statement
-
- function parseBreakStatement(node) {
- var label = null, key;
-
- expectKeyword('break');
-
- // Catch the very common case first: immediately a semicolon (U+003B).
- if (source.charCodeAt(lastIndex) === 0x3B) {
- lex();
-
- if (!(state.inIteration || state.inSwitch)) {
- throwError(Messages.IllegalBreak);
- }
-
- return node.finishBreakStatement(null);
- }
-
- if (hasLineTerminator) {
- if (!(state.inIteration || state.inSwitch)) {
- throwError(Messages.IllegalBreak);
- }
-
- return node.finishBreakStatement(null);
- }
-
- if (lookahead.type === Token.Identifier) {
- label = parseVariableIdentifier();
-
- key = '$' + label.name;
- if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
- throwError(Messages.UnknownLabel, label.name);
- }
- }
-
- consumeSemicolon();
-
- if (label === null && !(state.inIteration || state.inSwitch)) {
- throwError(Messages.IllegalBreak);
- }
-
- return node.finishBreakStatement(label);
- }
-
- // ECMA-262 13.10 The return statement
-
- function parseReturnStatement(node) {
- var argument = null;
-
- expectKeyword('return');
-
- if (!state.inFunctionBody) {
- tolerateError(Messages.IllegalReturn);
- }
-
- // 'return' followed by a space and an identifier is very common.
- if (source.charCodeAt(lastIndex) === 0x20) {
- if (isIdentifierStart(source.charCodeAt(lastIndex + 1))) {
- argument = parseExpression();
- consumeSemicolon();
- return node.finishReturnStatement(argument);
- }
- }
-
- if (hasLineTerminator) {
- // HACK
- return node.finishReturnStatement(null);
- }
-
- if (!match(';')) {
- if (!match('}') && lookahead.type !== Token.EOF) {
- argument = parseExpression();
- }
- }
-
- consumeSemicolon();
-
- return node.finishReturnStatement(argument);
- }
-
- // ECMA-262 13.11 The with statement
-
- function parseWithStatement(node) {
- var object, body;
-
- if (strict) {
- tolerateError(Messages.StrictModeWith);
- }
-
- expectKeyword('with');
-
- expect('(');
-
- object = parseExpression();
-
- expect(')');
-
- body = parseStatement();
-
- return node.finishWithStatement(object, body);
- }
-
- // ECMA-262 13.12 The switch statement
-
- function parseSwitchCase() {
- var test, consequent = [], statement, node = new Node();
-
- if (matchKeyword('default')) {
- lex();
- test = null;
- } else {
- expectKeyword('case');
- test = parseExpression();
- }
- expect(':');
-
- while (startIndex < length) {
- if (match('}') || matchKeyword('default') || matchKeyword('case')) {
- break;
- }
- statement = parseStatementListItem();
- consequent.push(statement);
- }
-
- return node.finishSwitchCase(test, consequent);
- }
-
- function parseSwitchStatement(node) {
- var discriminant, cases, clause, oldInSwitch, defaultFound;
-
- expectKeyword('switch');
-
- expect('(');
-
- discriminant = parseExpression();
-
- expect(')');
-
- expect('{');
-
- cases = [];
-
- if (match('}')) {
- lex();
- return node.finishSwitchStatement(discriminant, cases);
- }
-
- oldInSwitch = state.inSwitch;
- state.inSwitch = true;
- defaultFound = false;
-
- while (startIndex < length) {
- if (match('}')) {
- break;
- }
- clause = parseSwitchCase();
- if (clause.test === null) {
- if (defaultFound) {
- throwError(Messages.MultipleDefaultsInSwitch);
- }
- defaultFound = true;
- }
- cases.push(clause);
- }
-
- state.inSwitch = oldInSwitch;
-
- expect('}');
-
- return node.finishSwitchStatement(discriminant, cases);
- }
-
- // ECMA-262 13.14 The throw statement
-
- function parseThrowStatement(node) {
- var argument;
-
- expectKeyword('throw');
-
- if (hasLineTerminator) {
- throwError(Messages.NewlineAfterThrow);
- }
-
- argument = parseExpression();
-
- consumeSemicolon();
-
- return node.finishThrowStatement(argument);
- }
-
- // ECMA-262 13.15 The try statement
-
- function parseCatchClause() {
- var param, params = [], paramMap = {}, key, i, body, node = new Node();
-
- expectKeyword('catch');
-
- expect('(');
- if (match(')')) {
- throwUnexpectedToken(lookahead);
- }
-
- param = parsePattern(params);
- log(JSON.stringify(param))
- for (i = 0; i < params.length; i++) {
- key = '$' + params[i].value;
- if (Object.prototype.hasOwnProperty.call(paramMap, key)) {
- tolerateError(Messages.DuplicateBinding, params[i].value);
- }
- paramMap[key] = true;
- }
-
- // ECMA-262 12.14.1
- if (strict && isRestrictedWord(param.name)) {
- tolerateError(Messages.StrictCatchVariable);
- }
-
- expect(')');
- body = parseBlock();
- return node.finishCatchClause(param, body);
- }
-
- function parseTryStatement(node) {
- var block, handler = null, finalizer = null;
-
- expectKeyword('try');
-
- block = parseBlock();
-
- if (matchKeyword('catch')) {
- handler = parseCatchClause();
- }
-
- if (matchKeyword('finally')) {
- lex();
- finalizer = parseBlock();
- }
-
- if (!handler && !finalizer) {
- throwError(Messages.NoCatchOrFinally);
- }
-
- return node.finishTryStatement(block, handler, finalizer);
- }
-
- // ECMA-262 13.16 The debugger statement
-
- function parseDebuggerStatement(node) {
- expectKeyword('debugger');
-
- consumeSemicolon();
-
- return node.finishDebuggerStatement();
- }
-
- // 13 Statements
-
- function parseStatement() {
- var type = lookahead.type,
- expr,
- labeledBody,
- key,
- node;
-
- if (type === Token.EOF) {
- throwUnexpectedToken(lookahead);
- }
-
- if (type === Token.Punctuator && lookahead.value === '{') {
- return parseBlock();
- }
- isAssignmentTarget = isBindingElement = true;
- node = new Node();
-
- if (type === Token.Punctuator) {
- switch (lookahead.value) {
- case ';':
- return parseEmptyStatement(node);
- case '(':
- return parseExpressionStatement(node);
- default:
- break;
- }
- } else if (type === Token.Keyword) {
- switch (lookahead.value) {
- case 'break':
- return parseBreakStatement(node);
- case 'continue':
- return parseContinueStatement(node);
- case 'debugger':
- return parseDebuggerStatement(node);
- case 'do':
- return parseDoWhileStatement(node);
- case 'for':
- return parseForStatement(node);
- case 'function':
- return parseFunctionDeclaration(node);
- case 'if':
- return parseIfStatement(node);
- case 'return':
- return parseReturnStatement(node);
- case 'switch':
- return parseSwitchStatement(node);
- case 'throw':
- return parseThrowStatement(node);
- case 'try':
- return parseTryStatement(node);
- case 'var':
- return parseVariableStatement(node);
- case 'while':
- return parseWhileStatement(node);
- case 'with':
- return parseWithStatement(node);
- default:
- break;
- }
- }
-
- expr = parseExpression();
-
- // ECMA-262 12.12 Labelled Statements
- if ((expr.type === Syntax.Identifier) && match(':')) {
- lex();
-
- key = '$' + expr.name;
- if (Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
- throwError(Messages.Redeclaration, 'Label', expr.name);
- }
-
- state.labelSet[key] = true;
- labeledBody = parseStatement();
- delete state.labelSet[key];
- return node.finishLabeledStatement(expr, labeledBody);
- }
-
- consumeSemicolon();
-
- return node.finishExpressionStatement(expr);
- }
-
- // ECMA-262 14.1 Function Definition
-
- function parseFunctionSourceElements() {
- var statement, body = [], token, directive, firstRestricted,
- oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody, oldParenthesisCount,
- node = new Node();
-
- expect('{');
-
- while (startIndex < length) {
- if (lookahead.type !== Token.StringLiteral) {
- break;
- }
- token = lookahead;
-
- statement = parseStatementListItem();
- body.push(statement);
- if (statement.expression.type !== Syntax.Literal) {
- // this is not directive
- break;
- }
- directive = source.slice(token.start + 1, token.end - 1);
- if (directive === 'use strict') {
- strict = true;
- if (firstRestricted) {
- tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral);
- }
- } else {
- if (!firstRestricted && token.octal) {
- firstRestricted = token;
- }
- }
- }
-
- oldLabelSet = state.labelSet;
- oldInIteration = state.inIteration;
- oldInSwitch = state.inSwitch;
- oldInFunctionBody = state.inFunctionBody;
- oldParenthesisCount = state.parenthesizedCount;
-
- state.labelSet = {};
- state.inIteration = false;
- state.inSwitch = false;
- state.inFunctionBody = true;
- state.parenthesizedCount = 0;
-
- while (startIndex < length) {
- if (match('}')) {
- break;
- }
- body.push(parseStatementListItem());
- }
-
- expect('}');
-
- state.labelSet = oldLabelSet;
- state.inIteration = oldInIteration;
- state.inSwitch = oldInSwitch;
- state.inFunctionBody = oldInFunctionBody;
- state.parenthesizedCount = oldParenthesisCount;
-
- return node.finishBlockStatement(body);
- }
-
- function validateParam(options, param, name) {
- var key = '$' + name;
- if (strict) {
- if (isRestrictedWord(name)) {
- options.stricted = param;
- options.message = Messages.StrictParamName;
- }
- if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) {
- options.stricted = param;
- options.message = Messages.StrictParamDupe;
- }
- } else if (!options.firstRestricted) {
- if (isRestrictedWord(name)) {
- options.firstRestricted = param;
- options.message = Messages.StrictParamName;
- } else if (isStrictModeReservedWord(name)) {
- options.firstRestricted = param;
- options.message = Messages.StrictReservedWord;
- } else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) {
- options.stricted = param;
- options.message = Messages.StrictParamDupe;
- }
- }
- options.paramSet[key] = true;
- }
-
- function parseParam(options) {
- var token, param, params = [], i, def;
-
- token = lookahead;
- if (token.value === '...') {
- param = parseRestElement(params);
- validateParam(options, param.argument, param.argument.name);
- options.params.push(param);
- options.defaults.push(null);
- return false;
- }
-
- param = parsePatternWithDefault(params);
- for (i = 0; i < params.length; i++) {
- validateParam(options, params[i], params[i].value);
- }
-
- if (param.type === Syntax.AssignmentPattern) {
- def = param.right;
- param = param.left;
- ++options.defaultCount;
- }
-
- options.params.push(param);
- options.defaults.push(def);
-
- return !match(')');
- }
-
- function parseParams(firstRestricted) {
- var options;
-
- options = {
- params: [],
- defaultCount: 0,
- defaults: [],
- firstRestricted: firstRestricted
- };
-
- expect('(');
-
- if (!match(')')) {
- options.paramSet = {};
- while (startIndex < length) {
- if (!parseParam(options)) {
- break;
- }
- expect(',');
- }
- }
-
- expect(')');
-
- if (options.defaultCount === 0) {
- options.defaults = [];
- }
-
- return {
- params: options.params,
- defaults: options.defaults,
- stricted: options.stricted,
- firstRestricted: options.firstRestricted,
- message: options.message
- };
- }
-
- function parseFunctionDeclaration(node, identifierIsOptional) {
- var id = null, params = [], defaults = [], body, token, stricted, tmp, firstRestricted, message, previousStrict,
- isGenerator, previousAllowYield;
-
- previousAllowYield = state.allowYield;
-
- expectKeyword('function');
-
- isGenerator = match('*');
- if (isGenerator) {
- lex();
- }
-
- if (!identifierIsOptional || !match('(')) {
- token = lookahead;
- id = parseVariableIdentifier();
- if (strict) {
- if (isRestrictedWord(token.value)) {
- tolerateUnexpectedToken(token, Messages.StrictFunctionName);
- }
- } else {
- if (isRestrictedWord(token.value)) {
- firstRestricted = token;
- message = Messages.StrictFunctionName;
- } else if (isStrictModeReservedWord(token.value)) {
- firstRestricted = token;
- message = Messages.StrictReservedWord;
- }
- }
- }
-
- state.allowYield = !isGenerator;
- tmp = parseParams(firstRestricted);
- params = tmp.params;
- defaults = tmp.defaults;
- stricted = tmp.stricted;
- firstRestricted = tmp.firstRestricted;
- if (tmp.message) {
- message = tmp.message;
- }
-
-
- previousStrict = strict;
- body = parseFunctionSourceElements();
- if (strict && firstRestricted) {
- throwUnexpectedToken(firstRestricted, message);
- }
- if (strict && stricted) {
- tolerateUnexpectedToken(stricted, message);
- }
-
- strict = previousStrict;
- state.allowYield = previousAllowYield;
-
- return node.finishFunctionDeclaration(id, params, defaults, body, isGenerator);
- }
-
- function parseFunctionExpression() {
- var token, id = null, stricted, firstRestricted, message, tmp,
- params = [], defaults = [], body, previousStrict, node = new Node(),
- isGenerator, previousAllowYield;
-
- previousAllowYield = state.allowYield;
-
- expectKeyword('function');
-
- isGenerator = match('*');
- if (isGenerator) {
- lex();
- }
-
- state.allowYield = !isGenerator;
- if (!match('(')) {
- token = lookahead;
- id = (!strict && !isGenerator && matchKeyword('yield')) ? parseNonComputedProperty() : parseVariableIdentifier();
- if (strict) {
- if (isRestrictedWord(token.value)) {
- tolerateUnexpectedToken(token, Messages.StrictFunctionName);
- }
- } else {
- if (isRestrictedWord(token.value)) {
- firstRestricted = token;
- message = Messages.StrictFunctionName;
- } else if (isStrictModeReservedWord(token.value)) {
- firstRestricted = token;
- message = Messages.StrictReservedWord;
- }
- }
- }
-
- tmp = parseParams(firstRestricted);
- params = tmp.params;
- defaults = tmp.defaults;
- stricted = tmp.stricted;
- firstRestricted = tmp.firstRestricted;
- if (tmp.message) {
- message = tmp.message;
- }
-
- previousStrict = strict;
- body = parseFunctionSourceElements();
- if (strict && firstRestricted) {
- throwUnexpectedToken(firstRestricted, message);
- }
- if (strict && stricted) {
- tolerateUnexpectedToken(stricted, message);
- }
- strict = previousStrict;
- state.allowYield = previousAllowYield;
-
- return node.finishFunctionExpression(id, params, defaults, body, isGenerator);
- }
-
- // ECMA-262 14.5 Class Definitions
-
- function parseClassBody() {
- var classBody, token, isStatic, hasConstructor = false, body, method, computed, key;
-
- classBody = new Node();
-
- expect('{');
- body = [];
- while (!match('}')) {
- if (match(';')) {
- lex();
- } else {
- method = new Node();
- token = lookahead;
- isStatic = false;
- computed = match('[');
- if (match('*')) {
- lex();
- } else {
- key = parseObjectPropertyKey();
- if (key.name === 'static' && (lookaheadPropertyName() || match('*'))) {
- token = lookahead;
- isStatic = true;
- computed = match('[');
- if (match('*')) {
- lex();
- } else {
- key = parseObjectPropertyKey();
- }
- }
- }
- method = tryParseMethodDefinition(token, key, computed, method);
- if (method) {
- method['static'] = isStatic; // jscs:ignore requireDotNotation
- if (method.kind === 'init') {
- method.kind = 'method';
- }
- if (!isStatic) {
- if (!method.computed && (method.key.name || method.key.value.toString()) === 'constructor') {
- if (method.kind !== 'method' || !method.method || method.value.generator) {
- throwUnexpectedToken(token, Messages.ConstructorSpecialMethod);
- }
- if (hasConstructor) {
- throwUnexpectedToken(token, Messages.DuplicateConstructor);
- } else {
- hasConstructor = true;
- }
- method.kind = 'constructor';
- }
- } else {
- if (!method.computed && (method.key.name || method.key.value.toString()) === 'prototype') {
- throwUnexpectedToken(token, Messages.StaticPrototype);
- }
- }
- method.type = Syntax.MethodDefinition;
- delete method.method;
- delete method.shorthand;
- body.push(method);
- } else {
- throwUnexpectedToken(lookahead);
- }
- }
- }
- lex();
- return classBody.finishClassBody(body);
- }
-
- function parseClassDeclaration(identifierIsOptional) {
- var id = null, superClass = null, classNode = new Node(), classBody, previousStrict = strict;
- strict = true;
-
- expectKeyword('class');
-
- if (!identifierIsOptional || lookahead.type === Token.Identifier) {
- id = parseVariableIdentifier();
- }
-
- if (matchKeyword('extends')) {
- lex();
- superClass = isolateCoverGrammar(parseLeftHandSideExpressionAllowCall);
- }
- classBody = parseClassBody();
- strict = previousStrict;
-
- return classNode.finishClassDeclaration(id, superClass, classBody);
- }
-
- function parseClassExpression() {
- var id = null, superClass = null, classNode = new Node(), classBody, previousStrict = strict;
- strict = true;
-
- expectKeyword('class');
-
- if (lookahead.type === Token.Identifier) {
- id = parseVariableIdentifier();
- }
-
- if (matchKeyword('extends')) {
- lex();
- superClass = isolateCoverGrammar(parseLeftHandSideExpressionAllowCall);
- }
- classBody = parseClassBody();
- strict = previousStrict;
-
- return classNode.finishClassExpression(id, superClass, classBody);
- }
-
- // ECMA-262 15.2 Modules
-
- function parseModuleSpecifier() {
- var node = new Node();
-
- if (lookahead.type !== Token.StringLiteral) {
- throwError(Messages.InvalidModuleSpecifier);
- }
- return node.finishLiteral(lex());
- }
-
- // ECMA-262 15.2.3 Exports
-
- function parseExportSpecifier() {
- var exported, local, node = new Node(), def;
- if (matchKeyword('default')) {
- // export {default} from 'something';
- def = new Node();
- lex();
- local = def.finishIdentifier('default');
- } else {
- local = parseVariableIdentifier();
- }
- if (matchContextualKeyword('as')) {
- lex();
- exported = parseNonComputedProperty();
- }
- return node.finishExportSpecifier(local, exported);
- }
-
- function parseExportNamedDeclaration(node) {
- var declaration = null,
- isExportFromIdentifier,
- src = null, specifiers = [];
-
- // non-default export
- if (lookahead.type === Token.Keyword) {
- // covers:
- // export var f = 1;
- switch (lookahead.value) {
- case 'let':
- case 'const':
- case 'var':
- case 'class':
- case 'function':
- declaration = parseStatementListItem();
- return node.finishExportNamedDeclaration(declaration, specifiers, null);
- }
- }
-
- expect('{');
- while (!match('}')) {
- isExportFromIdentifier = isExportFromIdentifier || matchKeyword('default');
- specifiers.push(parseExportSpecifier());
- if (!match('}')) {
- expect(',');
- if (match('}')) {
- break;
- }
- }
- }
- expect('}');
-
- if (matchContextualKeyword('from')) {
- // covering:
- // export {default} from 'foo';
- // export {foo} from 'foo';
- lex();
- src = parseModuleSpecifier();
- consumeSemicolon();
- } else if (isExportFromIdentifier) {
- // covering:
- // export {default}; // missing fromClause
- throwError(lookahead.value ?
- Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
- } else {
- // cover
- // export {foo};
- consumeSemicolon();
- }
- return node.finishExportNamedDeclaration(declaration, specifiers, src);
- }
-
- function parseExportDefaultDeclaration(node) {
- var declaration = null,
- expression = null;
-
- // covers:
- // export default ...
- expectKeyword('default');
-
- if (matchKeyword('function')) {
- // covers:
- // export default function foo () {}
- // export default function () {}
- declaration = parseFunctionDeclaration(new Node(), true);
- return node.finishExportDefaultDeclaration(declaration);
- }
- if (matchKeyword('class')) {
- declaration = parseClassDeclaration(true);
- return node.finishExportDefaultDeclaration(declaration);
- }
-
- if (matchContextualKeyword('from')) {
- throwError(Messages.UnexpectedToken, lookahead.value);
- }
-
- // covers:
- // export default {};
- // export default [];
- // export default (1 + 2);
- if (match('{')) {
- expression = parseObjectInitializer();
- } else if (match('[')) {
- expression = parseArrayInitializer();
- } else {
- expression = parseAssignmentExpression();
- }
- consumeSemicolon();
- return node.finishExportDefaultDeclaration(expression);
- }
-
- function parseExportAllDeclaration(node) {
- var src;
-
- // covers:
- // export * from 'foo';
- expect('*');
- if (!matchContextualKeyword('from')) {
- throwError(lookahead.value ?
- Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
- }
- lex();
- src = parseModuleSpecifier();
- consumeSemicolon();
-
- return node.finishExportAllDeclaration(src);
- }
-
- function parseExportDeclaration() {
- var node = new Node();
- if (state.inFunctionBody) {
- throwError(Messages.IllegalExportDeclaration);
- }
-
- expectKeyword('export');
-
- if (matchKeyword('default')) {
- return parseExportDefaultDeclaration(node);
- }
- if (match('*')) {
- return parseExportAllDeclaration(node);
- }
- return parseExportNamedDeclaration(node);
- }
-
- // ECMA-262 15.2.2 Imports
-
- function parseImportSpecifier() {
- // import {} ...;
- var local, imported, node = new Node();
-
- imported = parseNonComputedProperty();
- if (matchContextualKeyword('as')) {
- lex();
- local = parseVariableIdentifier();
- }
-
- return node.finishImportSpecifier(local, imported);
- }
-
- function parseNamedImports() {
- var specifiers = [];
- // {foo, bar as bas}
- expect('{');
- while (!match('}')) {
- specifiers.push(parseImportSpecifier());
- if (!match('}')) {
- expect(',');
- if (match('}')) {
- break;
- }
- }
- }
- expect('}');
- return specifiers;
- }
-
- function parseImportDefaultSpecifier() {
- // import ...;
- var local, node = new Node();
-
- local = parseNonComputedProperty();
-
- return node.finishImportDefaultSpecifier(local);
- }
-
- function parseImportNamespaceSpecifier() {
- // import <* as foo> ...;
- var local, node = new Node();
-
- expect('*');
- if (!matchContextualKeyword('as')) {
- throwError(Messages.NoAsAfterImportNamespace);
- }
- lex();
- local = parseNonComputedProperty();
-
- return node.finishImportNamespaceSpecifier(local);
- }
-
- function parseImportDeclaration() {
- var specifiers = [], src, node = new Node();
-
- if (state.inFunctionBody) {
- throwError(Messages.IllegalImportDeclaration);
- }
-
- expectKeyword('import');
-
- if (lookahead.type === Token.StringLiteral) {
- // import 'foo';
- src = parseModuleSpecifier();
- } else {
-
- if (match('{')) {
- // import {bar}
- specifiers = specifiers.concat(parseNamedImports());
- } else if (match('*')) {
- // import * as foo
- specifiers.push(parseImportNamespaceSpecifier());
- } else if (isIdentifierName(lookahead) && !matchKeyword('default')) {
- // import foo
- specifiers.push(parseImportDefaultSpecifier());
- if (match(',')) {
- lex();
- if (match('*')) {
- // import foo, * as foo
- specifiers.push(parseImportNamespaceSpecifier());
- } else if (match('{')) {
- // import foo, {bar}
- specifiers = specifiers.concat(parseNamedImports());
- } else {
- throwUnexpectedToken(lookahead);
- }
- }
- } else {
- throwUnexpectedToken(lex());
- }
-
- if (!matchContextualKeyword('from')) {
- throwError(lookahead.value ?
- Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
- }
- lex();
- src = parseModuleSpecifier();
- }
-
- consumeSemicolon();
- return node.finishImportDeclaration(specifiers, src);
- }
-
- // ECMA-262 15.1 Scripts
-
- function parseScriptBody() {
- var statement, body = [], token, directive, firstRestricted;
-
- while (startIndex < length) {
- token = lookahead;
- if (token.type !== Token.StringLiteral) {
- break;
- }
-
- statement = parseStatementListItem();
- body.push(statement);
- if (statement.expression.type !== Syntax.Literal) {
- // this is not directive
- break;
- }
- directive = source.slice(token.start + 1, token.end - 1);
- if (directive === 'use strict') {
- strict = true;
- if (firstRestricted) {
- tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral);
- }
- } else {
- if (!firstRestricted && token.octal) {
- firstRestricted = token;
- }
- }
- }
-
- while (startIndex < length) {
- statement = parseStatementListItem();
- /* istanbul ignore if */
- if (typeof statement === 'undefined') {
- break;
- }
- body.push(statement);
- }
- return body;
- }
-
- function parseProgram() {
- var body, node;
-
- peek();
- node = new Node();
-
- body = parseScriptBody();
- return node.finishProgram(body, state.sourceType);
- }
-
- function filterTokenLocation() {
- var i, entry, token, tokens = [];
-
- for (i = 0; i < extra.tokens.length; ++i) {
- entry = extra.tokens[i];
- token = {
- type: entry.type,
- value: entry.value
- };
- if (entry.regex) {
- token.regex = {
- pattern: entry.regex.pattern,
- flags: entry.regex.flags
- };
- }
- if (extra.range) {
- token.range = entry.range;
- }
- if (extra.loc) {
- token.loc = entry.loc;
- }
- tokens.push(token);
- }
-
- extra.tokens = tokens;
- }
-
- function tokenize(code, options) {
- var toString,
- tokens;
-
- toString = String;
- if (typeof code !== 'string' && !(code instanceof String)) {
- code = toString(code);
- }
-
- source = code;
- index = 0;
- lineNumber = (source.length > 0) ? 1 : 0;
- lineStart = 0;
- startIndex = index;
- startLineNumber = lineNumber;
- startLineStart = lineStart;
- length = source.length;
- lookahead = null;
- state = {
- allowIn: true,
- allowYield: true,
- labelSet: {},
- inFunctionBody: false,
- inIteration: false,
- inSwitch: false,
- lastCommentStart: -1,
- curlyStack: []
- };
-
- extra = {};
-
- // Options matching.
- options = options || {};
-
- // Of course we collect tokens here.
- options.tokens = true;
- extra.tokens = [];
- extra.tokenize = true;
- // The following two fields are necessary to compute the Regex tokens.
- extra.openParenToken = -1;
- extra.openCurlyToken = -1;
-
- extra.range = (typeof options.range === 'boolean') && options.range;
- extra.loc = (typeof options.loc === 'boolean') && options.loc;
-
- if (typeof options.comment === 'boolean' && options.comment) {
- extra.comments = [];
- }
- if (typeof options.tolerant === 'boolean' && options.tolerant) {
- extra.errors = [];
- }
-
- try {
- peek();
- if (lookahead.type === Token.EOF) {
- return extra.tokens;
- }
-
- lex();
- while (lookahead.type !== Token.EOF) {
- try {
- lex();
- } catch (lexError) {
- if (extra.errors) {
- recordError(lexError);
- // We have to break on the first error
- // to avoid infinite loops.
- break;
- } else {
- throw lexError;
- }
- }
- }
-
- filterTokenLocation();
- tokens = extra.tokens;
- if (typeof extra.comments !== 'undefined') {
- tokens.comments = extra.comments;
- }
- if (typeof extra.errors !== 'undefined') {
- tokens.errors = extra.errors;
- }
- } catch (e) {
- throw e;
- } finally {
- extra = {};
- }
- return tokens;
- }
-
- function parse(code, options) {
- var program, toString;
-
- toString = String;
- if (typeof code !== 'string' && !(code instanceof String)) {
- code = toString(code);
- }
-
- source = code;
- index = 0;
- lineNumber = (source.length > 0) ? 1 : 0;
- lineStart = 0;
- startIndex = index;
- startLineNumber = lineNumber;
- startLineStart = lineStart;
- length = source.length;
- lookahead = null;
- state = {
- allowIn: true,
- allowYield: true,
- labelSet: {},
- inFunctionBody: false,
- inIteration: false,
- inSwitch: false,
- lastCommentStart: -1,
- curlyStack: [],
- sourceType: 'script'
- };
- strict = false;
-
- extra = {};
- if (typeof options !== 'undefined') {
- extra.range = (typeof options.range === 'boolean') && options.range;
- extra.loc = (typeof options.loc === 'boolean') && options.loc;
- extra.attachComment = (typeof options.attachComment === 'boolean') && options.attachComment;
-
- if (extra.loc && options.source !== null && options.source !== undefined) {
- extra.source = toString(options.source);
- }
-
- if (typeof options.tokens === 'boolean' && options.tokens) {
- extra.tokens = [];
- }
- if (typeof options.comment === 'boolean' && options.comment) {
- extra.comments = [];
- }
- if (typeof options.tolerant === 'boolean' && options.tolerant) {
- extra.errors = [];
- }
- if (extra.attachComment) {
- extra.range = true;
- extra.comments = [];
- extra.bottomRightStack = [];
- extra.trailingComments = [];
- extra.leadingComments = [];
- }
- if (options.sourceType === 'module') {
- // very restrictive condition for now
- state.sourceType = options.sourceType;
- strict = true;
- }
- }
-
- try {
- program = parseProgram();
- if (typeof extra.comments !== 'undefined') {
- program.comments = extra.comments;
- }
- if (typeof extra.tokens !== 'undefined') {
- filterTokenLocation();
- program.tokens = extra.tokens;
- }
- if (typeof extra.errors !== 'undefined') {
- program.errors = extra.errors;
- }
- } catch (e) {
- throw e;
- } finally {
- extra = {};
- }
-
- return program;
- }
-
- // Sync with *.json manifests.
- exports.version = '2.6.0';
-
- exports.tokenize = tokenize;
-
- exports.parse = parse;
-
- // Deep copy.
- /* istanbul ignore next */
- exports.Syntax = (function () {
- var name, types = {};
-
- if (typeof Object.create === 'function') {
- types = Object.create(null);
- }
-
- for (name in Syntax) {
- if (Syntax.hasOwnProperty(name)) {
- types[name] = Syntax[name];
- }
- }
-
- if (typeof Object.freeze === 'function') {
- Object.freeze(types);
- }
-
- return types;
- }());
-
-}));
-/* vim: set sw=4 ts=4 et tw=80 : */
diff --git a/js2py/internals/fill_space.py b/js2py/internals/fill_space.py
index 76c32d97..329c8b28 100644
--- a/js2py/internals/fill_space.py
+++ b/js2py/internals/fill_space.py
@@ -1,27 +1,23 @@
-from base import Scope
-from func_utils import *
-from conversions import *
+from __future__ import unicode_literals
+
+from .base import Scope
+from .func_utils import *
+from .conversions import *
import six
-from prototypes.jsboolean import BooleanPrototype
-from prototypes.jserror import ErrorPrototype
-from prototypes.jsfunction import FunctionPrototype
-from prototypes.jsnumber import NumberPrototype
-from prototypes.jsobject import ObjectPrototype
-from prototypes.jsregexp import RegExpPrototype
-from prototypes.jsstring import StringPrototype
-from prototypes.jsarray import ArrayPrototype
-import prototypes.jsjson as jsjson
-import prototypes.jsutils as jsutils
-
-
-from constructors import jsnumber
-from constructors import jsstring
-from constructors import jsarray
-from constructors import jsboolean
-from constructors import jsregexp
-from constructors import jsmath
-from constructors import jsobject
-from constructors import jsfunction
+from .prototypes.jsboolean import BooleanPrototype
+from .prototypes.jserror import ErrorPrototype
+from .prototypes.jsfunction import FunctionPrototype
+from .prototypes.jsnumber import NumberPrototype
+from .prototypes.jsobject import ObjectPrototype
+from .prototypes.jsregexp import RegExpPrototype
+from .prototypes.jsstring import StringPrototype
+from .prototypes.jsarray import ArrayPrototype
+from .prototypes import jsjson
+from .prototypes import jsutils
+
+from .constructors import jsnumber, jsstring, jsarray, jsboolean, jsregexp, jsmath, jsobject, jsfunction, jsconsole
+
+
def fill_proto(proto, proto_class, space):
for i in dir(proto_class):
@@ -36,7 +32,7 @@ def fill_proto(proto, proto_class, space):
meth = e
else:
continue
- meth_name = meth.__name__.strip('_') # RexExp._exec -> RegExp.exec
+ meth_name = meth.__name__.strip('_') # RexExp._exec -> RegExp.exec
js_meth = space.NewFunction(meth, space.ctx, (), meth_name, False, ())
set_non_enumerable(proto, meth_name, js_meth)
return proto
@@ -45,26 +41,36 @@ def fill_proto(proto, proto_class, space):
def easy_func(f, space):
return space.NewFunction(f, space.ctx, (), f.__name__, False, ())
+
def Empty(this, args):
return undefined
+
def set_non_enumerable(obj, name, prop):
- obj.define_own_property(unicode(name), {'value': prop,
- 'writable': True,
- 'enumerable': False,
- 'configurable': True}, True)
+ obj.define_own_property(
+ unicode(name), {
+ 'value': prop,
+ 'writable': True,
+ 'enumerable': False,
+ 'configurable': True
+ }, True)
def set_protected(obj, name, prop):
- obj.define_own_property(unicode(name), {'value': prop,
- 'writable': False,
- 'enumerable': False,
- 'configurable': False}, True)
+ obj.define_own_property(
+ unicode(name), {
+ 'value': prop,
+ 'writable': False,
+ 'enumerable': False,
+ 'configurable': False
+ }, True)
def fill_space(space, byte_generator):
# set global scope
global_scope = Scope({}, space, parent=None)
+ global_scope.THIS_BINDING = global_scope
+ global_scope.registers(byte_generator.declared_vars)
space.GlobalObj = global_scope
space.byte_generator = byte_generator
@@ -72,22 +78,22 @@ def fill_space(space, byte_generator):
# first init all protos, later take care of constructors and details
# Function must be first obviously, we have to use a small trick to do that...
- function_proto = space.NewFunction(Empty, space.ctx, (), 'Empty', False, ())
- space.FunctionPrototype = function_proto # this will fill the prototypes of the methods!
+ function_proto = space.NewFunction(Empty, space.ctx, (), 'Empty', False,
+ ())
+ space.FunctionPrototype = function_proto # this will fill the prototypes of the methods!
fill_proto(function_proto, FunctionPrototype, space)
# Object next
- object_proto = space.NewObject() # no proto
+ object_proto = space.NewObject() # no proto
fill_proto(object_proto, ObjectPrototype, space)
space.ObjectPrototype = object_proto
function_proto.prototype = object_proto
-
# Number
number_proto = space.NewObject()
number_proto.prototype = object_proto
fill_proto(number_proto, NumberPrototype, space)
- number_proto.value = 0
+ number_proto.value = 0.
number_proto.Class = 'Number'
space.NumberPrototype = number_proto
@@ -125,7 +131,7 @@ def fill_space(space, byte_generator):
isFinite = easy_func(jsutils.isFinite, space)
# Error
- error_proto= space.NewError(u'Error', u'')
+ error_proto = space.NewError(u'Error', u'')
error_proto.prototype = object_proto
error_proto.put(u'name', u'Error')
fill_proto(error_proto, ErrorPrototype, space)
@@ -139,9 +145,14 @@ def creator(this, args):
else:
msg = u''
return space.NewError(typ, msg)
+
j = easy_func(creator, space)
j.name = unicode(typ)
- j.prototype = space.ERROR_TYPES[typ]
+
+ set_protected(j, 'prototype', space.ERROR_TYPES[typ])
+
+ set_non_enumerable(space.ERROR_TYPES[typ], 'constructor', j)
+
def new_create(args, space):
message = get_arg(args, 0)
if not is_undefined(message):
@@ -149,24 +160,21 @@ def new_create(args, space):
else:
msg = u''
return space.NewError(typ, msg)
+
j.create = new_create
return j
-
# fill remaining error types
error_constructors = {}
- for err_type_name in (
- u'Error',
- u'EvalError',
- u'RangeError',
- u'ReferenceError',
- u'SyntaxError',
- u'TypeError',
- u'URIError'):
+ for err_type_name in (u'Error', u'EvalError', u'RangeError',
+ u'ReferenceError', u'SyntaxError', u'TypeError',
+ u'URIError'):
extra_err = space.NewError(u'Error', u'')
extra_err.put(u'name', err_type_name)
- setattr(space, err_type_name+u'Prototype', extra_err)
- error_constructors[err_type_name] = construct_constructor(err_type_name)
+ setattr(space, err_type_name + u'Prototype', extra_err)
+ error_constructors[err_type_name] = construct_constructor(
+ err_type_name)
+
assert space.TypeErrorPrototype is not None
# RegExp
@@ -175,11 +183,8 @@ def new_create(args, space):
fill_proto(regexp_proto, RegExpPrototype, space)
space.RegExpPrototype = regexp_proto
-
-
# Json
-
# now all these boring constructors...
# Number
@@ -199,7 +204,8 @@ def new_create(args, space):
set_non_enumerable(string_proto, 'constructor', string)
set_protected(string, 'prototype', string_proto)
# string has an extra function
- set_non_enumerable(string, 'fromCharCode', easy_func(jsstring.fromCharCode, space))
+ set_non_enumerable(string, 'fromCharCode',
+ easy_func(jsstring.fromCharCode, space))
# Boolean
boolean = easy_func(jsboolean.Boolean, space)
@@ -239,31 +245,33 @@ def new_create(args, space):
math = space.NewObject()
math.Class = 'Math'
fill_proto(math, jsmath.MathFunctions, space)
- for k,v in jsmath.CONSTANTS.items():
+ for k, v in jsmath.CONSTANTS.items():
set_protected(math, k, v)
-
+ console = space.NewObject()
+ fill_proto(console, jsconsole.ConsoleMethods, space)
# set global object
builtins = {
- 'String': string,
- 'Number': number,
- 'Boolean': boolean,
- 'RegExp': regexp,
- 'exports': convert_to_js_type({}, space),
- 'Math': math,
- #'Date',
- 'Object': _object,
- 'Function': function,
- 'JSON': json,
- 'Array': array,
- 'parseFloat': parseFloat,
- 'parseInt': parseInt,
- 'isFinite': isFinite,
- 'isNaN': isNaN,
- 'eval': easy_func(jsfunction._eval, space),
- 'log': easy_func(jsfunction.log, space),
- }
+ 'String': string,
+ 'Number': number,
+ 'Boolean': boolean,
+ 'RegExp': regexp,
+ 'exports': convert_to_js_type({}, space),
+ 'Math': math,
+ #'Date',
+ 'Object': _object,
+ 'Function': function,
+ 'JSON': json,
+ 'Array': array,
+ 'parseFloat': parseFloat,
+ 'parseInt': parseInt,
+ 'isFinite': isFinite,
+ 'isNaN': isNaN,
+ 'eval': easy_func(jsfunction._eval, space),
+ 'console': console,
+ 'log': console.get(u'log'),
+ }
builtins.update(error_constructors)
@@ -271,5 +279,3 @@ def new_create(args, space):
set_protected(global_scope, 'Infinity', Infinity)
for k, v in builtins.items():
set_non_enumerable(global_scope, k, v)
-
-
diff --git a/js2py/internals/func_utils.py b/js2py/internals/func_utils.py
index bf22cfa7..58dfef9e 100644
--- a/js2py/internals/func_utils.py
+++ b/js2py/internals/func_utils.py
@@ -1,5 +1,5 @@
-from simplex import *
-from conversions import *
+from .simplex import *
+from .conversions import *
import six
if six.PY3:
@@ -8,6 +8,7 @@
xrange = range
unicode = str
+
def get_arg(arguments, n):
if len(arguments) <= n:
return undefined
@@ -28,14 +29,21 @@ def convert_to_js_type(e, space=None):
return unicode(t)
elif t in (list, tuple):
if space is None:
- raise MakeError('TypeError', 'Actually an internal error, could not convert to js type because space not specified')
+ raise MakeError(
+ 'TypeError',
+ 'Actually an internal error, could not convert to js type because space not specified'
+ )
return space.ConstructArray(ensure_js_types(e, space=space))
- elif t==dict:
+ elif t == dict:
if space is None:
- raise MakeError('TypeError', 'Actually an internal error, could not convert to js type because space not specified')
+ raise MakeError(
+ 'TypeError',
+ 'Actually an internal error, could not convert to js type because space not specified'
+ )
new = {}
- for k,v in e.items():
- new[to_string(convert_to_js_type(k))] = convert_to_js_type(v)
+ for k, v in e.items():
+ new[to_string(convert_to_js_type(k, space))] = convert_to_js_type(
+ v, space)
return space.ConstructObject(new)
else:
raise MakeError('TypeError', 'Could not convert to js type!')
@@ -50,16 +58,16 @@ def is_js_type(e):
return False
-
# todo optimise these 2!
def js_array_to_tuple(arr):
length = to_uint32(arr.get(u'length'))
return tuple(arr.get(unicode(e)) for e in xrange(length))
+
def js_array_to_list(arr):
length = to_uint32(arr.get(u'length'))
return [arr.get(unicode(e)) for e in xrange(length)]
def js_arr_length(arr):
- return to_uint32(arr.get(u'length'))
\ No newline at end of file
+ return to_uint32(arr.get(u'length'))
diff --git a/js2py/internals/opcodes.py b/js2py/internals/opcodes.py
index cdd58a3e..2f6c65f5 100644
--- a/js2py/internals/opcodes.py
+++ b/js2py/internals/opcodes.py
@@ -1,19 +1,24 @@
-from operations import *
-from base import get_member, get_member_dot, PyJsFunction, Scope
+from .operations import *
+from .base import get_member, get_member_dot, PyJsFunction, Scope
+
class OP_CODE(object):
_params = []
+
# def eval(self, ctx):
# raise
def __repr__(self):
- return self.__class__.__name__ + str(tuple([getattr(self, e) for e in self._params]))
+ return self.__class__.__name__ + str(
+ tuple([getattr(self, e) for e in self._params]))
# --------------------- UNARY ----------------------
+
class UNARY_OP(OP_CODE):
_params = ['operator']
+
def __init__(self, operator):
self.operator = operator
@@ -24,20 +29,23 @@ def eval(self, ctx):
# special unary operations
+
class TYPEOF(OP_CODE):
_params = ['identifier']
+
def __init__(self, identifier):
self.identifier = identifier
def eval(self, ctx):
# typeof something_undefined does not throw reference error
- val = ctx.get(self.identifier, False) # <= this makes it slightly different!
+ val = ctx.get(self.identifier,
+ False) # <= this makes it slightly different!
ctx.stack.append(typeof_uop(val))
-
class POSTFIX(OP_CODE):
_params = ['cb', 'ca', 'identifier']
+
def __init__(self, post, incr, identifier):
self.identifier = identifier
self.cb = 1 if incr else -1
@@ -66,6 +74,7 @@ def eval(self, ctx):
ctx.stack.append(target + self.ca)
+
class POSTFIX_MEMBER_DOT(OP_CODE):
_params = ['cb', 'ca', 'prop']
@@ -77,7 +86,8 @@ def __init__(self, post, incr, prop):
def eval(self, ctx):
left = ctx.stack.pop()
- target = to_number(get_member_dot(left, self.prop, ctx.space)) + self.cb
+ target = to_number(get_member_dot(left, self.prop,
+ ctx.space)) + self.cb
if type(left) not in PRIMITIVES:
left.put(self.prop, target)
@@ -103,8 +113,10 @@ def eval(self, ctx):
# --------------------- BITWISE ----------------------
+
class BINARY_OP(OP_CODE):
_params = ['operator']
+
def __init__(self, operator):
self.operator = operator
@@ -113,15 +125,17 @@ def eval(self, ctx):
left = ctx.stack.pop()
ctx.stack.append(BINARY_OPERATIONS[self.operator](left, right))
-# &&, || and conditional are implemented in bytecode
+# &&, || and conditional are implemented in bytecode
# --------------------- JUMPS ----------------------
+
# simple label that will be removed from code after compilation. labels ID will be translated
# to source code position.
class LABEL(OP_CODE):
_params = ['num']
+
def __init__(self, num):
self.num = num
@@ -129,15 +143,19 @@ def __init__(self, num):
# I implemented interpreter in the way that when an integer is returned by eval operation the execution will jump
# to the location of the label (it is loc = label_locations[label])
+
class BASE_JUMP(OP_CODE):
_params = ['label']
+
def __init__(self, label):
self.label = label
+
class JUMP(BASE_JUMP):
def eval(self, ctx):
return self.label
+
class JUMP_IF_TRUE(BASE_JUMP):
def eval(self, ctx):
val = ctx.stack.pop()
@@ -153,46 +171,56 @@ def eval(self, ctx):
ctx.stack.pop()
return self.label
+
class JUMP_IF_TRUE_WITHOUT_POP(BASE_JUMP):
def eval(self, ctx):
val = ctx.stack[-1]
if to_boolean(val):
return self.label
+
class JUMP_IF_FALSE(BASE_JUMP):
def eval(self, ctx):
val = ctx.stack.pop()
if not to_boolean(val):
return self.label
+
class JUMP_IF_FALSE_WITHOUT_POP(BASE_JUMP):
def eval(self, ctx):
val = ctx.stack[-1]
if not to_boolean(val):
return self.label
+
class POP(OP_CODE):
def eval(self, ctx):
+ # todo remove this check later
+ assert len(ctx.stack), 'Popped from empty stack!'
del ctx.stack[-1]
+
# class REDUCE(OP_CODE):
# def eval(self, ctx):
# assert len(ctx.stack)==2
# ctx.stack[0] = ctx.stack[1]
# del ctx.stack[1]
-
# --------------- LOADING --------------
class LOAD_NONE(OP_CODE): # be careful with this :)
_params = []
+
def eval(self, ctx):
ctx.stack.append(None)
-class LOAD_N_TUPLE(OP_CODE): # loads the tuple composed of n last elements on stack. elements are popped.
+class LOAD_N_TUPLE(
+ OP_CODE
+): # loads the tuple composed of n last elements on stack. elements are popped.
_params = ['n']
+
def __init__(self, n):
self.n = n
@@ -214,6 +242,7 @@ def eval(self, ctx):
class LOAD_BOOLEAN(OP_CODE):
_params = ['val']
+
def __init__(self, val):
assert val in (0, 1)
self.val = bool(val)
@@ -224,6 +253,7 @@ def eval(self, ctx):
class LOAD_STRING(OP_CODE):
_params = ['val']
+
def __init__(self, val):
assert isinstance(val, basestring)
self.val = unicode(val)
@@ -234,6 +264,7 @@ def eval(self, ctx):
class LOAD_NUMBER(OP_CODE):
_params = ['val']
+
def __init__(self, val):
assert isinstance(val, (float, int, long))
self.val = float(val)
@@ -244,6 +275,7 @@ def eval(self, ctx):
class LOAD_REGEXP(OP_CODE):
_params = ['body', 'flags']
+
def __init__(self, body, flags):
self.body = body
self.flags = flags
@@ -255,20 +287,26 @@ def eval(self, ctx):
class LOAD_FUNCTION(OP_CODE):
_params = ['start', 'params', 'name', 'is_declaration', 'definitions']
+
def __init__(self, start, params, name, is_declaration, definitions):
assert type(start) == int
self.start = start # its an ID of label pointing to the beginning of the function bytecode
self.params = params
self.name = name
self.is_declaration = bool(is_declaration)
- self.definitions = tuple(set(definitions+params))
+ self.definitions = tuple(set(definitions + params))
def eval(self, ctx):
- ctx.stack.append(ctx.space.NewFunction(self.start, ctx, self.params, self.name, self.is_declaration, self.definitions))
+ ctx.stack.append(
+ ctx.space.NewFunction(self.start, ctx, self.params, self.name,
+ self.is_declaration, self.definitions))
class LOAD_OBJECT(OP_CODE):
- _params = ['props'] # props are py string pairs (prop_name, kind): kind can be either i, g or s. (init, get, set)
+ _params = [
+ 'props'
+ ] # props are py string pairs (prop_name, kind): kind can be either i, g or s. (init, get, set)
+
def __init__(self, props):
self.num = len(props)
self.props = props
@@ -284,6 +322,7 @@ def eval(self, ctx):
class LOAD_ARRAY(OP_CODE):
_params = ['num']
+
def __init__(self, num):
self.num = num
@@ -300,7 +339,7 @@ def eval(self, ctx):
ctx.stack.append(ctx.THIS_BINDING)
-class LOAD(OP_CODE): # todo check!
+class LOAD(OP_CODE): # todo check!
_params = ['identifier']
def __init__(self, identifier):
@@ -308,7 +347,7 @@ def __init__(self, identifier):
# 11.1.2
def eval(self, ctx):
- ctx.stack.append(ctx.get(self.identifier))
+ ctx.stack.append(ctx.get(self.identifier, throw=True))
class LOAD_MEMBER(OP_CODE):
@@ -320,6 +359,7 @@ def eval(self, ctx):
class LOAD_MEMBER_DOT(OP_CODE):
_params = ['prop']
+
def __init__(self, prop):
self.prop = prop
@@ -328,12 +368,12 @@ def eval(self, ctx):
ctx.stack.append(get_member_dot(obj, self.prop, ctx.space))
-
# --------------- STORING --------------
class STORE(OP_CODE):
_params = ['identifier']
+
def __init__(self, identifier):
self.identifier = identifier
@@ -352,9 +392,11 @@ def eval(self, ctx):
if typ in PRIMITIVES:
prop = to_string(name)
if typ == NULL_TYPE:
- raise MakeError('TypeError', "Cannot set property '%s' of null" % prop)
+ raise MakeError('TypeError',
+ "Cannot set property '%s' of null" % prop)
elif typ == UNDEFINED_TYPE:
- raise MakeError('TypeError', "Cannot set property '%s' of undefined" % prop)
+ raise MakeError('TypeError',
+ "Cannot set property '%s' of undefined" % prop)
# just ignore...
else:
left.put_member(name, value)
@@ -364,6 +406,7 @@ def eval(self, ctx):
class STORE_MEMBER_DOT(OP_CODE):
_params = ['prop']
+
def __init__(self, prop):
self.prop = prop
@@ -374,9 +417,12 @@ def eval(self, ctx):
typ = type(left)
if typ in PRIMITIVES:
if typ == NULL_TYPE:
- raise MakeError('TypeError', "Cannot set property '%s' of null" % self.prop)
+ raise MakeError('TypeError',
+ "Cannot set property '%s' of null" % self.prop)
elif typ == UNDEFINED_TYPE:
- raise MakeError('TypeError', "Cannot set property '%s' of undefined" % self.prop)
+ raise MakeError(
+ 'TypeError',
+ "Cannot set property '%s' of undefined" % self.prop)
# just ignore...
else:
left.put(self.prop, value)
@@ -399,6 +445,7 @@ def eval(self, ctx):
class STORE_MEMBER_OP(OP_CODE):
_params = ['op']
+
def __init__(self, op):
self.op = op
@@ -410,18 +457,25 @@ def eval(self, ctx):
typ = type(left)
if typ in PRIMITIVES:
if typ is NULL_TYPE:
- raise MakeError('TypeError', "Cannot set property '%s' of null" % to_string(name))
+ raise MakeError(
+ 'TypeError',
+ "Cannot set property '%s' of null" % to_string(name))
elif typ is UNDEFINED_TYPE:
- raise MakeError('TypeError', "Cannot set property '%s' of undefined" % to_string(name))
- ctx.stack.append(BINARY_OPERATIONS[self.op](value, get_member(left, name, ctx.space)))
+ raise MakeError(
+ 'TypeError',
+ "Cannot set property '%s' of undefined" % to_string(name))
+ ctx.stack.append(BINARY_OPERATIONS[self.op](get_member(
+ left, name, ctx.space), value))
return
else:
- ctx.stack.append(BINARY_OPERATIONS[self.op](value, get_member(left, name, ctx.space)))
+ ctx.stack.append(BINARY_OPERATIONS[self.op](get_member(
+ left, name, ctx.space), value))
left.put_member(name, ctx.stack[-1])
class STORE_MEMBER_DOT_OP(OP_CODE):
_params = ['prop', 'op']
+
def __init__(self, prop, op):
self.prop = prop
self.op = op
@@ -433,27 +487,32 @@ def eval(self, ctx):
typ = type(left)
if typ in PRIMITIVES:
if typ == NULL_TYPE:
- raise MakeError('TypeError', "Cannot set property '%s' of null" % self.prop)
+ raise MakeError('TypeError',
+ "Cannot set property '%s' of null" % self.prop)
elif typ == UNDEFINED_TYPE:
- raise MakeError('TypeError', "Cannot set property '%s' of undefined" % self.prop)
- ctx.stack.append(BINARY_OPERATIONS[self.op](value, get_member_dot(left, self.prop, ctx.space)))
+ raise MakeError(
+ 'TypeError',
+ "Cannot set property '%s' of undefined" % self.prop)
+ ctx.stack.append(BINARY_OPERATIONS[self.op](get_member_dot(
+ left, self.prop, ctx.space), value))
return
else:
- ctx.stack.append(BINARY_OPERATIONS[self.op](value, get_member_dot(left, self.prop, ctx.space)))
+ ctx.stack.append(BINARY_OPERATIONS[self.op](get_member_dot(
+ left, self.prop, ctx.space), value))
left.put(self.prop, ctx.stack[-1])
# --------------- CALLS --------------
+
def bytecode_call(ctx, func, this, args):
if type(func) is not PyJsFunction:
- raise MakeError('TypeError', "%s is not a function" % Type(func) )
- if func.is_native: # call to built-in function or method
+ raise MakeError('TypeError', "%s is not a function" % Type(func))
+ if func.is_native: # call to built-in function or method
ctx.stack.append(func.call(this, args))
return None
# therefore not native. we have to return (new_context, function_label) to instruct interpreter to call
- print func.name
return func._generate_my_context(this, args), func.code
@@ -478,6 +537,7 @@ def eval(self, ctx):
class CALL_METHOD_DOT(OP_CODE):
_params = ['prop']
+
def __init__(self, prop):
self.prop = prop
@@ -509,6 +569,7 @@ def eval(self, ctx):
class CALL_METHOD_DOT_NO_ARGS(OP_CODE):
_params = ['prop']
+
def __init__(self, prop):
self.prop = prop
@@ -524,8 +585,11 @@ class NOP(OP_CODE):
def eval(self, ctx):
pass
+
class RETURN(OP_CODE):
- def eval(self, ctx): # remember to load the return value on stack before using RETURN op.
+ def eval(
+ self, ctx
+ ): # remember to load the return value on stack before using RETURN op.
return (None, None)
@@ -533,16 +597,20 @@ class NEW(OP_CODE):
def eval(self, ctx):
args = ctx.stack.pop()
constructor = ctx.stack.pop()
- if type(constructor) in PRIMITIVES or not hasattr(constructor, 'create'):
- raise MakeError('TypeError', '%s is not a constructor' % Type(constructor))
+ if type(constructor) in PRIMITIVES or not hasattr(
+ constructor, 'create'):
+ raise MakeError('TypeError',
+ '%s is not a constructor' % Type(constructor))
ctx.stack.append(constructor.create(args, space=ctx.space))
class NEW_NO_ARGS(OP_CODE):
def eval(self, ctx):
constructor = ctx.stack.pop()
- if type(constructor) in PRIMITIVES or not hasattr(constructor, 'create'):
- raise MakeError('TypeError', '%s is not a constructor' % Type(constructor))
+ if type(constructor) in PRIMITIVES or not hasattr(
+ constructor, 'create'):
+ raise MakeError('TypeError',
+ '%s is not a constructor' % Type(constructor))
ctx.stack.append(constructor.create((), space=ctx.space))
@@ -554,11 +622,14 @@ def eval(self, ctx):
raise MakeError(None, None, ctx.stack.pop())
-
-
class TRY_CATCH_FINALLY(OP_CODE):
- _params = ['try_label', 'catch_label', 'catch_variable', 'finally_label', 'finally_present', 'end_label']
- def __init__(self, try_label, catch_label, catch_variable, finally_label, finally_present, end_label):
+ _params = [
+ 'try_label', 'catch_label', 'catch_variable', 'finally_label',
+ 'finally_present', 'end_label'
+ ]
+
+ def __init__(self, try_label, catch_label, catch_variable, finally_label,
+ finally_present, end_label):
self.try_label = try_label
self.catch_label = catch_label
self.catch_variable = catch_variable
@@ -572,40 +643,47 @@ def eval(self, ctx):
# execute_fragment_under_context returns:
# (return_value, typ, jump_loc/error)
+ ctx.stack.pop()
+
# execute try statement
- try_status = ctx.space.exe.execute_fragment_under_context(ctx, self.try_label, self.catch_label)
+ try_status = ctx.space.exe.execute_fragment_under_context(
+ ctx, self.try_label, self.catch_label)
- # check if errors
errors = try_status[1] == 3
# catch
if errors and self.catch_variable is not None:
# generate catch block context...
- catch_context = Scope({self.catch_variable: try_status[2].get_thrown_value(ctx.space)}, ctx.space, ctx)
- catch_context.stack.append(undefined)
- catch_status = ctx.space.exe.execute_fragment_under_context(catch_context, self.catch_label, self.finally_label)
+ catch_context = Scope({
+ self.catch_variable:
+ try_status[2].get_thrown_value(ctx.space)
+ }, ctx.space, ctx)
+ catch_context.THIS_BINDING = ctx.THIS_BINDING
+ catch_status = ctx.space.exe.execute_fragment_under_context(
+ catch_context, self.catch_label, self.finally_label)
else:
catch_status = None
# finally
if self.finally_present:
- ctx.stack.append(undefined) # (ctx.stack is empty after try call)
- finally_status = ctx.space.exe.execute_fragment_under_context(ctx, self.finally_label, self.end_label)
+ finally_status = ctx.space.exe.execute_fragment_under_context(
+ ctx, self.finally_label, self.end_label)
else:
finally_status = None
# now return controls
other_status = catch_status or try_status
- if finally_status is None or (finally_status[1]==0 and other_status[1]!=0):
+ if finally_status is None or (finally_status[1] == 0
+ and other_status[1] != 0):
winning_status = other_status
else:
winning_status = finally_status
val, typ, spec = winning_status
- if typ == 0: # normal
+ if typ == 0: # normal
ctx.stack.append(val)
return
- elif typ == 1: # return
+ elif typ == 1: # return
ctx.stack.append(spec)
return None, None # send return signal
elif typ == 2: # jump outside
@@ -613,25 +691,106 @@ def eval(self, ctx):
return spec
elif typ == 3:
# throw is made with empty stack as usual
-
raise spec
else:
raise RuntimeError('Invalid return code')
+# ------------ WITH + ITERATORS ----------
+class WITH(OP_CODE):
+ _params = ['beg_label', 'end_label']
+ def __init__(self, beg_label, end_label):
+ self.beg_label = beg_label
+ self.end_label = end_label
+ def eval(self, ctx):
+ obj = to_object(ctx.stack.pop(), ctx.space)
+ with_context = Scope(
+ obj, ctx.space, ctx) # todo actually use the obj to modify the ctx
+ with_context.THIS_BINDING = ctx.THIS_BINDING
+ status = ctx.space.exe.execute_fragment_under_context(
+ with_context, self.beg_label, self.end_label)
+ val, typ, spec = status
+ if typ != 3: # exception
+ ctx.stack.pop()
+ if typ == 0: # normal
+ ctx.stack.append(val)
+ return
+ elif typ == 1: # return
+ ctx.stack.append(spec)
+ return None, None # send return signal
+ elif typ == 2: # jump outside
+ ctx.stack.append(val)
+ return spec
+ elif typ == 3: # exception
+ # throw is made with empty stack as usual
+ raise spec
+ else:
+ raise RuntimeError('Invalid return code')
+class FOR_IN(OP_CODE):
+ _params = ['name', 'body_start_label', 'continue_label', 'break_label']
+ def __init__(self, name, body_start_label, continue_label, break_label):
+ self.name = name
+ self.body_start_label = body_start_label
+ self.continue_label = continue_label
+ self.break_label = break_label
-# ------------ WITH + ITERATORS ----------
+ def eval(self, ctx):
+ iterable = ctx.stack.pop()
+ if is_null(iterable) or is_undefined(iterable):
+ ctx.stack.pop()
+ ctx.stack.append(undefined)
+ return self.break_label
+
+ obj = to_object(iterable, ctx.space)
+
+ for e in sorted(obj.own):
+ if not obj.own[e]['enumerable']:
+ continue
+
+ ctx.put(
+ self.name, e
+ ) # JS would have been so much nicer if this was ctx.space.put(self.name, obj.get(e))
+
+ # evaluate the body
+ status = ctx.space.exe.execute_fragment_under_context(
+ ctx, self.body_start_label, self.break_label)
+
+ val, typ, spec = status
+
+ if typ != 3: # exception
+ ctx.stack.pop()
+
+ if typ == 0: # normal
+ ctx.stack.append(val)
+ continue
+ elif typ == 1: # return
+ ctx.stack.append(spec)
+ return None, None # send return signal
+ elif typ == 2: # jump outside
+ # now have to figure out whether this is a continue or something else...
+ ctx.stack.append(val)
+ if spec == self.continue_label:
+ # just a continue, perform next iteration as normal
+ continue
+ return spec # break or smth, go there and finish the iteration
+ elif typ == 3: # exception
+ # throw is made with empty stack as usual
+ raise spec
+ else:
+ raise RuntimeError('Invalid return code')
+
+ return self.break_label
# all opcodes...
@@ -639,7 +798,7 @@ def eval(self, ctx):
g = ''
for g in globals():
try:
- if not issubclass(globals()[g], OP_CODE) or g is 'OP_CODE':
+ if not issubclass(globals()[g], OP_CODE) or g == 'OP_CODE':
continue
except:
continue
diff --git a/js2py/internals/operations.py b/js2py/internals/operations.py
index 03bd5c39..35b90179 100644
--- a/js2py/internals/operations.py
+++ b/js2py/internals/operations.py
@@ -1,23 +1,26 @@
from __future__ import unicode_literals
-from simplex import *
-from conversions import *
-
+from .simplex import *
+from .conversions import *
# ------------------------------------------------------------------------------
# Unary operations
+
# -x
def minus_uop(self):
return -to_number(self)
+
# +x
def plus_uop(self): # +u
return to_number(self)
+
# !x
def logical_negation_uop(self): # !u cant do 'not u' :(
return not to_boolean(self)
+
# typeof x
def typeof_uop(self):
if is_callable(self):
@@ -27,10 +30,12 @@ def typeof_uop(self):
typ = u'object' # absolutely idiotic...
return typ
+
# ~u
def bit_invert_uop(self):
return float(to_int32(float(~to_int32(self))))
+
# void
def void_op(self):
return undefined
@@ -42,7 +47,8 @@ def void_op(self):
'!': logical_negation_uop,
'~': bit_invert_uop,
'void': void_op,
- 'typeof': typeof_uop, # this one only for member expressions! for identifiers its slightly different...
+ 'typeof':
+ typeof_uop, # this one only for member expressions! for identifiers its slightly different...
}
# ------------------------------------------------------------------------------
@@ -52,7 +58,6 @@ def void_op(self):
# <<, >>, &, ^, |, ~
-
# <<
def bit_lshift_op(self, other):
lnum = to_int32(self)
@@ -60,6 +65,7 @@ def bit_lshift_op(self, other):
shiftCount = rnum & 0x1F
return float(to_int32(float(lnum << shiftCount)))
+
# >>
def bit_rshift_op(self, other):
lnum = to_int32(self)
@@ -67,6 +73,7 @@ def bit_rshift_op(self, other):
shiftCount = rnum & 0x1F
return float(to_int32(float(lnum >> shiftCount)))
+
# >>>
def bit_bshift_op(self, other):
lnum = to_uint32(self)
@@ -74,27 +81,32 @@ def bit_bshift_op(self, other):
shiftCount = rnum & 0x1F
return float(to_uint32(float(lnum >> shiftCount)))
+
# &
def bit_and_op(self, other):
lnum = to_int32(self)
rnum = to_int32(other)
return float(to_int32(float(lnum & rnum)))
+
# ^
def bit_xor_op(self, other):
lnum = to_int32(self)
rnum = to_int32(other)
return float(to_int32(float(lnum ^ rnum)))
+
# |
def bit_or_op(self, other):
lnum = to_int32(self)
rnum = to_int32(other)
return float(to_int32(float(lnum | rnum)))
+
# Additive operators
# + and - are implemented here
+
# +
def add_op(self, other):
if type(self) is float and type(other) is float:
@@ -108,17 +120,21 @@ def add_op(self, other):
return to_string(a) + to_string(b)
return to_number(a) + to_number(b)
+
# -
def sub_op(self, other):
return to_number(self) - to_number(other)
+
# Multiplicative operators
# *, / and % are implemented here
+
# *
def mul_op(self, other):
return to_number(self) * to_number(other)
+
# /
def div_op(self, other):
a = to_number(self)
@@ -129,6 +145,7 @@ def div_op(self, other):
return NaN
return Infinity if a > 0 else -Infinity
+
# %
def mod_op(self, other):
a = to_number(self)
@@ -147,10 +164,10 @@ def mod_op(self, other):
return float(pyres)
-
# Comparisons
# <, <=, !=, ==, >=, > are implemented here.
-def abstract_relational_comparison(self, other, self_first=True): # todo speed up!
+def abstract_relational_comparison(self, other,
+ self_first=True): # todo speed up!
''' self=
def greater_eq_op(self, other):
res = abstract_relational_comparison(self, other, True)
@@ -192,6 +212,7 @@ def greater_eq_op(self, other):
return False
return not res
+
# >
def greater_op(self, other):
res = abstract_relational_comparison(self, other, False)
@@ -202,6 +223,7 @@ def greater_op(self, other):
# equality
+
def abstract_equality_op(self, other):
''' returns the result of JS == compare.
result is PyJs type: bool'''
@@ -212,7 +234,8 @@ def abstract_equality_op(self, other):
if tx == 'Number' or tx == 'String' or tx == 'Boolean':
return self == other
return self is other # Object
- elif (tx == 'Undefined' and ty == 'Null') or (ty == 'Undefined' and tx == 'Null'):
+ elif (tx == 'Undefined' and ty == 'Null') or (ty == 'Undefined'
+ and tx == 'Null'):
return True
elif tx == 'Number' and ty == 'String':
return abstract_equality_op(self, to_number(other))
@@ -229,6 +252,7 @@ def abstract_equality_op(self, other):
else:
return False
+
def abstract_inequality_op(self, other):
return not abstract_equality_op(self, other)
@@ -248,6 +272,7 @@ def strict_equality_op(self, other):
def strict_inequality_op(self, other):
return not strict_equality_op(self, other)
+
def instanceof_op(self, other):
'''checks if self is instance of other'''
if not hasattr(other, 'has_instance'):
@@ -255,28 +280,27 @@ def instanceof_op(self, other):
return other.has_instance(self)
-def contains_op(self, other):
- '''checks if self contains other'''
- if not self.is_object():
- raise MakeError('TypeError', "You can\'t use 'in' operator to search in non-objects")
- return self.has_property(to_string(other).value)
+def in_op(self, other):
+ '''checks if self is in other'''
+ if not is_object(other):
+ raise MakeError(
+ 'TypeError',
+ "You can\'t use 'in' operator to search in non-objects")
+ return other.has_property(to_string(self))
BINARY_OPERATIONS = {
'+': add_op,
'-': sub_op,
-
'*': mul_op,
'/': div_op,
'%': mod_op,
-
'<<': bit_lshift_op,
'>>': bit_rshift_op,
'>>>': bit_bshift_op,
'|': bit_or_op,
'&': bit_and_op,
'^': bit_xor_op,
-
'==': abstract_equality_op,
'!=': abstract_inequality_op,
'===': strict_equality_op,
@@ -285,7 +309,6 @@ def contains_op(self, other):
'<=': less_eq_op,
'>': greater_op,
'>=': greater_eq_op,
-
+ 'in': in_op,
'instanceof': instanceof_op,
}
-
diff --git a/js2py/internals/prototypes/jsarray.py b/js2py/internals/prototypes/jsarray.py
index 1c72cb5a..ace774ec 100644
--- a/js2py/internals/prototypes/jsarray.py
+++ b/js2py/internals/prototypes/jsarray.py
@@ -9,9 +9,9 @@
xrange = range
import functools
-
ARR_STACK = set({})
+
class ArrayPrototype:
def toString(this, args):
arr = to_object(this, args.space)
@@ -22,20 +22,23 @@ def toString(this, args):
def toLocaleString(this, args):
array = to_object(this, args.space)
- arr_len = to_uint32(array.get('length'))
+ arr_len = js_arr_length(array)
# separator is simply a comma ','
if not arr_len:
return ''
res = []
for i in xrange(arr_len):
- element = array[str(i)]
+ element = array.get(unicode(i))
if is_undefined(element) or is_null(element):
res.append('')
else:
cand = to_object(element, args.space)
str_func = cand.get('toLocaleString')
if not is_callable(str_func):
- raise MakeError('TypeError', 'toLocaleString method of item at index %d is not callable'%i)
+ raise MakeError(
+ 'TypeError',
+ 'toLocaleString method of item at index %d is not callable'
+ % i)
res.append(to_string(str_func.call(cand, ())))
return ','.join(res)
@@ -45,13 +48,13 @@ def concat(this, args):
items.extend(tuple(args))
A = []
for E in items:
- if GetClass(E)=='Array':
+ if GetClass(E) == 'Array':
k = 0
e_len = js_arr_length(E)
- while k (arr_len - actual_delete_count + items_len):
- array.delete(unicode(k-1))
+ array.delete(unicode(k - 1))
k -= 1
# 13
- elif items_len>actual_delete_count:
+ elif items_len > actual_delete_count:
k = arr_len - actual_delete_count
- while k>actual_start:
+ while k > actual_start:
fr = unicode(k + actual_delete_count - 1)
to = unicode(k + items_len - 1)
if array.has_property(fr):
@@ -222,7 +236,7 @@ def splice(this, args):
E = items.pop(0)
array.put(unicode(k), E)
k += 1
- array.put('length', this.Js(arr_len - actual_delete_count + items_len))
+ array.put('length', float(arr_len - actual_delete_count + items_len))
return A
def unshift(this, args):
@@ -242,7 +256,7 @@ def unshift(this, args):
for j, e in enumerate(items):
array.put(unicode(j), e)
array.put('length', float(arr_len + argCount))
- return arr_len + argCount
+ return float(arr_len + argCount)
def indexOf(this, args):
array = to_object(this, args.space)
@@ -250,7 +264,7 @@ def indexOf(this, args):
arr_len = js_arr_length(array)
if arr_len == 0:
return -1.
- if len(args)>1:
+ if len(args) > 1:
n = to_int(args[1])
else:
n = 0
@@ -281,7 +295,7 @@ def lastIndexOf(this, args):
else:
n = arr_len - 1
if n >= 0:
- k = min(n, arr_len-1)
+ k = min(n, arr_len - 1)
else:
k = arr_len - abs(n)
while k >= 0:
@@ -292,36 +306,35 @@ def lastIndexOf(this, args):
k -= 1
return -1.
-
def every(this, args):
array = to_object(this, args.space)
callbackfn = get_arg(args, 0)
- arr_len = array.get('length').to_uint32()
- if not callbackfn.is_callable():
- raise this.MakeError('TypeError', 'callbackfn must be a function')
- T = arguments[1]
+ arr_len = js_arr_length(array)
+ if not is_callable(callbackfn):
+ raise MakeError('TypeError', 'callbackfn must be a function')
+ T = get_arg(args, 1)
k = 0
- while k1: # initial value present
- accumulator = arguments[1]
+ accumulator = undefined
+ if len(args) > 1: # initial value present
+ accumulator = args[1]
else:
kPresent = False
- while not kPresent and k1: # initial value present
- accumulator = arguments[1]
+ accumulator = undefined
+
+ if len(args) > 1: # initial value present
+ accumulator = args[1]
else:
kPresent = False
- while not kPresent and k>=0:
+ while not kPresent and k >= 0:
kPresent = array.has_property(unicode(k))
if kPresent:
accumulator = array.get(unicode(k))
k -= 1
if not kPresent:
- raise this.MakeError('TypeError', 'Reduce of empty array with no initial value')
- while k>=0:
+ raise MakeError('TypeError',
+ 'Reduce of empty array with no initial value')
+ while k >= 0:
if array.has_property(unicode(k)):
kValue = array.get(unicode(k))
- accumulator = callbackfn.call(this.undefined, (accumulator, kValue, this.Js(k), array))
+ accumulator = callbackfn.call(
+ undefined, (accumulator, kValue, float(k), array))
k -= 1
return accumulator
@@ -455,12 +482,8 @@ def sort_compare(a, b, comp):
res = comp.call(undefined, (a, b))
return to_int(res)
x, y = to_string(a), to_string(b)
- if xy:
+ elif x > y:
return 1
return 0
-
-
-
-
diff --git a/js2py/internals/prototypes/jsboolean.py b/js2py/internals/prototypes/jsboolean.py
index f0d4681f..9aff9d2e 100644
--- a/js2py/internals/prototypes/jsboolean.py
+++ b/js2py/internals/prototypes/jsboolean.py
@@ -3,21 +3,20 @@
from ..conversions import *
from ..func_utils import *
+
class BooleanPrototype:
def toString(this, args):
- if GetClass(this)!='Boolean':
- raise MakeError('TypeError', 'Boolean.prototype.toString is not generic')
+ if GetClass(this) != 'Boolean':
+ raise MakeError('TypeError',
+ 'Boolean.prototype.toString is not generic')
if is_object(this):
this = this.value
return u'true' if this else u'false'
def valueOf(this, args):
- if GetClass(this)!='Boolean':
- raise MakeError('TypeError', 'Boolean.prototype.valueOf is not generic')
+ if GetClass(this) != 'Boolean':
+ raise MakeError('TypeError',
+ 'Boolean.prototype.valueOf is not generic')
if is_object(this):
this = this.value
return this
-
-
-
-
diff --git a/js2py/internals/prototypes/jserror.py b/js2py/internals/prototypes/jserror.py
index 6a7dfc9d..c58dec49 100644
--- a/js2py/internals/prototypes/jserror.py
+++ b/js2py/internals/prototypes/jserror.py
@@ -2,10 +2,12 @@
from ..conversions import *
from ..func_utils import *
+
class ErrorPrototype:
def toString(this, args):
- if Type(this)!='Object':
- raise MakeError('TypeError', 'Error.prototype.toString called on non-object')
+ if Type(this) != 'Object':
+ raise MakeError('TypeError',
+ 'Error.prototype.toString called on non-object')
name = this.get('name')
name = u'Error' if is_undefined(name) else to_string(name)
msg = this.get('message')
diff --git a/js2py/internals/prototypes/jsfunction.py b/js2py/internals/prototypes/jsfunction.py
index fe92014c..06ec6801 100644
--- a/js2py/internals/prototypes/jsfunction.py
+++ b/js2py/internals/prototypes/jsfunction.py
@@ -11,44 +11,51 @@
xrange = range
unicode = str
-
# todo fix apply and bind
-class FunctionPrototype:
+
+class FunctionPrototype:
def toString(this, args):
if not is_callable(this):
- raise MakeError('TypeError', 'Function.prototype.toString is not generic')
+ raise MakeError('TypeError',
+ 'Function.prototype.toString is not generic')
args = u', '.join(map(unicode, this.params))
- return u'function %s(%s) { [native code] }' % (this.name if this.name else u'', args)
-
+ return u'function %s(%s) { [native code] }' % (this.name if this.name
+ else u'', args)
+
def call(this, args):
if not is_callable(this):
- raise MakeError('TypeError', 'Function.prototype.call is not generic')
+ raise MakeError('TypeError',
+ 'Function.prototype.call is not generic')
_this = get_arg(args, 0)
_args = tuple(args)[1:]
return this.call(_this, _args)
-
+
def apply(this, args):
if not is_callable(this):
- raise MakeError('TypeError', 'Function.prototype.apply is not generic')
+ raise MakeError('TypeError',
+ 'Function.prototype.apply is not generic')
_args = get_arg(args, 1)
if not is_object(_args):
- raise MakeError('TypeError', 'argList argument to Function.prototype.apply must an Object')
+ raise MakeError(
+ 'TypeError',
+ 'argList argument to Function.prototype.apply must an Object')
_this = get_arg(args, 0)
return this.call(_this, js_array_to_tuple(_args))
def bind(this, args):
if not is_callable(this):
- raise MakeError('TypeError', 'Function.prototype.bind is not generic')
+ raise MakeError('TypeError',
+ 'Function.prototype.bind is not generic')
bound_this = get_arg(args, 0)
bound_args = tuple(args)[1:]
+
def bound(dummy_this, extra_args):
return this.call(bound_this, bound_args + tuple(extra_args))
+
js_bound = args.space.NewFunction(bound, this.ctx, (), u'', False, ())
- js_bound.put(u'length', float(max(len(this.params) - len(bound_args), 0.)))
+ js_bound.put(u'length',
+ float(max(len(this.params) - len(bound_args), 0.)))
js_bound.put(u'name', u'boundFunc')
return js_bound
-
-
-
diff --git a/js2py/internals/prototypes/jsjson.py b/js2py/internals/prototypes/jsjson.py
index 62aa0457..87dc5f38 100644
--- a/js2py/internals/prototypes/jsjson.py
+++ b/js2py/internals/prototypes/jsjson.py
@@ -20,7 +20,9 @@ def parse(this, args):
try:
unfiltered = json.loads(s)
except:
- raise MakeError('SyntaxError', 'JSON.parse could not parse JSON string - Invalid syntax')
+ raise MakeError(
+ 'SyntaxError',
+ 'JSON.parse could not parse JSON string - Invalid syntax')
unfiltered = to_js(unfiltered, args.space)
if is_callable(reviver):
root = args.space.ConstructObject({'': unfiltered})
@@ -31,42 +33,44 @@ def parse(this, args):
def stringify(this, args):
global indent
- value, replacer, space = get_arg(args, 0), get_arg(args, 1), get_arg(args, 2)
+ value, replacer, space = get_arg(args, 0), get_arg(args, 1), get_arg(
+ args, 2)
stack = set([])
indent = ''
property_list = replacer_function = undefined
if is_object(replacer):
if is_callable(replacer):
replacer_function = replacer
- elif replacer.Class=='Array':
+ elif replacer.Class == 'Array':
property_list = []
for e in replacer:
v = replacer[e]
item = undefined
typ = Type(v)
- if typ=='Number':
+ if typ == 'Number':
item = to_string(v)
- elif typ=='String':
+ elif typ == 'String':
item = v
- elif typ=='Object':
+ elif typ == 'Object':
if GetClass(v) in ('String', 'Number'):
item = to_string(v)
if not is_undefined(item) and item not in property_list:
property_list.append(item)
if is_object(space):
- if GetClass(space)=='Number':
+ if GetClass(space) == 'Number':
space = to_number(space)
- elif GetClass(space)=='String':
+ elif GetClass(space) == 'String':
space = to_string(space)
- if Type(space)=='Number':
- space =min(10, to_int(space))
- gap = max(int(space), 0)* ' '
- elif Type(space)=='String':
+ if Type(space) == 'Number':
+ space = min(10, to_int(space))
+ gap = max(int(space), 0) * ' '
+ elif Type(space) == 'String':
gap = space[:10]
else:
gap = ''
- return Str('', args.space.ConstructObject({'':value}), replacer_function, property_list, gap, stack, space)
-
+ return Str('', args.space.ConstructObject({
+ '': value
+ }), replacer_function, property_list, gap, stack, space)
def Str(key, holder, replacer_function, property_list, gap, stack, space):
@@ -74,37 +78,38 @@ def Str(key, holder, replacer_function, property_list, gap, stack, space):
if is_object(value):
to_json = value.get('toJSON')
if is_callable(to_json):
- value = to_json.call(value, (key,))
+ value = to_json.call(value, (key, ))
if not is_undefined(replacer_function):
value = replacer_function.call(holder, (key, value))
if is_object(value):
- if value.Class=='String':
+ if value.Class == 'String':
value = to_string(value)
- elif value.Class=='Number':
+ elif value.Class == 'Number':
value = to_number(value)
- elif value.Class=='Boolean':
+ elif value.Class == 'Boolean':
value = to_boolean(value)
typ = Type(value)
if is_null(value):
return 'null'
- elif typ=='Boolean':
+ elif typ == 'Boolean':
return 'true' if value else 'false'
- elif typ=='String':
+ elif typ == 'String':
return Quote(value)
- elif typ=='Number':
+ elif typ == 'Number':
if not is_infinity(value):
return to_string(value)
return 'null'
if is_object(value) and not is_callable(value):
- if value.Class=='Array':
- return ja(value, stack, gap, property_list, replacer_function, space)
+ if value.Class == 'Array':
+ return ja(value, stack, gap, property_list, replacer_function,
+ space)
else:
- return jo(value, stack, gap, property_list, replacer_function, space)
+ return jo(value, stack, gap, property_list, replacer_function,
+ space)
return undefined
-
def jo(value, stack, gap, property_list, replacer_function, space):
global indent
if value in stack:
@@ -115,12 +120,15 @@ def jo(value, stack, gap, property_list, replacer_function, space):
if not is_undefined(property_list):
k = property_list
else:
- k = [unicode(e) for e,d in value.own.items() if d.get('enumerable')]
+ k = [unicode(e) for e, d in value.own.items() if d.get('enumerable')]
partial = []
for p in k:
- str_p = Str(p, value, replacer_function, property_list, gap, stack, space)
+ str_p = Str(p, value, replacer_function, property_list, gap, stack,
+ space)
if not is_undefined(str_p):
- member = json.dumps(p) + ':' + (' ' if gap else '') + str_p # todo not sure here - what space character?
+ member = json.dumps(p) + ':' + (
+ ' ' if gap else
+ '') + str_p # todo not sure here - what space character?
partial.append(member)
if not partial:
final = '{}'
@@ -128,9 +136,9 @@ def jo(value, stack, gap, property_list, replacer_function, space):
if not gap:
final = '{%s}' % ','.join(partial)
else:
- sep = ',\n'+indent
+ sep = ',\n' + indent
properties = sep.join(partial)
- final = '{\n'+indent+properties+'\n'+stepback+'}'
+ final = '{\n' + indent + properties + '\n' + stepback + '}'
stack.remove(value)
indent = stepback
return final
@@ -147,7 +155,8 @@ def ja(value, stack, gap, property_list, replacer_function, space):
length = js_arr_length(value)
for index in xrange(length):
index = unicode(index)
- str_index = Str(index, value, replacer_function, property_list, gap, stack, space)
+ str_index = Str(index, value, replacer_function, property_list, gap,
+ stack, space)
if is_undefined(str_index):
partial.append('null')
else:
@@ -158,17 +167,14 @@ def ja(value, stack, gap, property_list, replacer_function, space):
if not gap:
final = '[%s]' % ','.join(partial)
else:
- sep = ',\n'+indent
+ sep = ',\n' + indent
properties = sep.join(partial)
- final = '[\n'+indent +properties+'\n'+stepback+']'
+ final = '[\n' + indent + properties + '\n' + stepback + ']'
stack.remove(value)
indent = stepback
return final
-
-
-
def Quote(string):
return json.dumps(string)
@@ -179,7 +185,7 @@ def to_js(d, _args_space):
def walk(holder, name, reviver):
val = holder.get(name)
- if GetClass(val)=='Array':
+ if GetClass(val) == 'Array':
for i in xrange(js_arr_length(val)):
i = unicode(i)
new_element = walk(val, i, reviver)
@@ -188,15 +194,12 @@ def walk(holder, name, reviver):
else:
new_element.put(i, new_element)
elif is_object(val):
- for key in [unicode(e) for e,d in val.own.items() if d.get('enumerable')]:
+ for key in [
+ unicode(e) for e, d in val.own.items() if d.get('enumerable')
+ ]:
new_element = walk(val, key, reviver)
if is_undefined(new_element):
val.delete(key)
else:
val.put(key, new_element)
return reviver.call(holder, (name, val))
-
-
-
-
-
diff --git a/js2py/internals/prototypes/jsnumber.py b/js2py/internals/prototypes/jsnumber.py
index 8943873e..d099eabd 100644
--- a/js2py/internals/prototypes/jsnumber.py
+++ b/js2py/internals/prototypes/jsnumber.py
@@ -9,38 +9,75 @@
xrange = range
unicode = str
-
-RADIX_SYMBOLS = {0: '0', 1: '1', 2: '2', 3: '3', 4: '4', 5: '5', 6: '6', 7: '7', 8: '8', 9: '9',
- 10: 'a', 11: 'b', 12: 'c', 13: 'd', 14: 'e', 15: 'f', 16: 'g', 17: 'h', 18: 'i', 19: 'j', 20: 'k',
- 21: 'l', 22: 'm', 23: 'n', 24: 'o', 25: 'p', 26: 'q', 27: 'r', 28: 's', 29: 't', 30: 'u', 31: 'v',
- 32: 'w', 33: 'x', 34: 'y', 35: 'z'}
+RADIX_SYMBOLS = {
+ 0: '0',
+ 1: '1',
+ 2: '2',
+ 3: '3',
+ 4: '4',
+ 5: '5',
+ 6: '6',
+ 7: '7',
+ 8: '8',
+ 9: '9',
+ 10: 'a',
+ 11: 'b',
+ 12: 'c',
+ 13: 'd',
+ 14: 'e',
+ 15: 'f',
+ 16: 'g',
+ 17: 'h',
+ 18: 'i',
+ 19: 'j',
+ 20: 'k',
+ 21: 'l',
+ 22: 'm',
+ 23: 'n',
+ 24: 'o',
+ 25: 'p',
+ 26: 'q',
+ 27: 'r',
+ 28: 's',
+ 29: 't',
+ 30: 'u',
+ 31: 'v',
+ 32: 'w',
+ 33: 'x',
+ 34: 'y',
+ 35: 'z'
+}
def to_str_rep(num):
if is_nan(num):
return 'NaN'
elif is_infinity(num):
- sign = '-' if num<0 else ''
- return sign+'Infinity'
- elif int(num)==num: # dont print .0
+ sign = '-' if num < 0 else ''
+ return sign + 'Infinity'
+ elif int(num) == num: # dont print .0
return unicode(int(num))
- return unicode(num) # todo: Make it 100% consistent with Node
+ return unicode(num) # todo: Make it 100% consistent with Node
class NumberPrototype:
def toString(this, args):
- if GetClass(this)!='Number':
- raise MakeError('TypeError', 'Number.prototype.valueOf is not generic')
- if type(this)!= unicode:
+ if GetClass(this) != 'Number':
+ raise MakeError('TypeError',
+ 'Number.prototype.valueOf is not generic')
+ if type(this) != float:
this = this.value
radix = get_arg(args, 0)
if is_undefined(radix):
return to_str_rep(this)
- r = radix.to_int()
- if r==10:
+ r = to_int(radix)
+ if r == 10:
return to_str_rep(this)
- if r not in xrange(2, 37) or radix!=r:
- raise MakeError('RangeError', 'Number.prototype.toString() radix argument must be an integer between 2 and 36')
+ if r not in xrange(2, 37) or radix != r:
+ raise MakeError(
+ 'RangeError',
+ 'Number.prototype.toString() radix argument must be an integer between 2 and 36'
+ )
num = to_int(this)
if num < 0:
num = -num
@@ -55,61 +92,72 @@ def toString(this, args):
return sign + (res if res else '0')
def valueOf(this, args):
- if GetClass(this)!='Number':
- raise MakeError('TypeError', 'Number.prototype.valueOf is not generic')
- if type(this)!= unicode:
+ if GetClass(this) != 'Number':
+ raise MakeError('TypeError',
+ 'Number.prototype.valueOf is not generic')
+ if type(this) != float:
this = this.value
return this
- def toFixed (this, args):
- if GetClass(this)!='Number':
- raise MakeError('TypeError', 'Number.prototype.toFixed called on incompatible receiver')
- if type(this)!= unicode:
+ def toFixed(this, args):
+ if GetClass(this) != 'Number':
+ raise MakeError(
+ 'TypeError',
+ 'Number.prototype.toFixed called on incompatible receiver')
+ if type(this) != float:
this = this.value
fractionDigits = get_arg(args, 0)
- digs = fractionDigits.to_int()
- if digs<0 or digs>20:
- raise MakeError('RangeError', 'toFixed() digits argument must be between 0 and 20')
+ digs = to_int(fractionDigits)
+ if digs < 0 or digs > 20:
+ raise MakeError(
+ 'RangeError',
+ 'toFixed() digits argument must be between 0 and 20')
elif is_infinity(this):
- return 'Infinity' if this>0 else '-Infinity'
+ return 'Infinity' if this > 0 else '-Infinity'
elif is_nan(this):
return 'NaN'
- return format(this, '-.%df'%digs)
-
+ return format(this, '-.%df' % digs)
def toExponential(this, args):
- if GetClass(this)!='Number':
- raise MakeError('TypeError', 'Number.prototype.toExponential called on incompatible receiver')
- if type(this)!= unicode:
+ if GetClass(this) != 'Number':
+ raise MakeError(
+ 'TypeError',
+ 'Number.prototype.toExponential called on incompatible receiver'
+ )
+ if type(this) != float:
this = this.value
fractionDigits = get_arg(args, 0)
digs = to_int(fractionDigits)
- if digs<0 or digs>20:
- raise MakeError('RangeError', 'toFixed() digits argument must be between 0 and 20')
+ if digs < 0 or digs > 20:
+ raise MakeError(
+ 'RangeError',
+ 'toFixed() digits argument must be between 0 and 20')
elif is_infinity(this):
- return 'Infinity' if this>0 else '-Infinity'
+ return 'Infinity' if this > 0 else '-Infinity'
elif is_nan(this):
return 'NaN'
- return format(this, '-.%de'%digs)
+ return format(this, '-.%de' % digs)
- def toPrecision (this, args):
- if GetClass(this)!='Number':
- raise MakeError('TypeError', 'Number.prototype.toPrecision called on incompatible receiver')
- if type(this)!= unicode:
+ def toPrecision(this, args):
+ if GetClass(this) != 'Number':
+ raise MakeError(
+ 'TypeError',
+ 'Number.prototype.toPrecision called on incompatible receiver')
+ if type(this) != float:
this = this.value
precision = get_arg(args, 0)
if is_undefined(precision):
return to_string(this)
- prec = precision.to_int()
+ prec = to_int(precision)
if is_nan(this):
return 'NaN'
elif is_infinity(this):
- return 'Infinity' if this>0 else '-Infinity'
+ return 'Infinity' if this > 0 else '-Infinity'
digs = prec - len(str(int(this)))
- if digs>=0:
- return format(this, '-.%df'%digs)
+ if digs >= 0:
+ return format(this, '-.%df' % digs)
else:
- return format(this, '-.%df'%(prec-1))
+ return format(this, '-.%df' % (prec - 1))
-NumberPrototype.toLocaleString = NumberPrototype.toString
+NumberPrototype.toLocaleString = NumberPrototype.toString
diff --git a/js2py/internals/prototypes/jsobject.py b/js2py/internals/prototypes/jsobject.py
index b7af780f..cdda6bab 100644
--- a/js2py/internals/prototypes/jsobject.py
+++ b/js2py/internals/prototypes/jsobject.py
@@ -5,11 +5,11 @@
class ObjectPrototype:
def toString(this, args):
- if type(this)==UNDEFINED_TYPE:
+ if type(this) == UNDEFINED_TYPE:
return u'[object Undefined]'
- elif type(this)==NULL_TYPE:
+ elif type(this) == NULL_TYPE:
return u'[object Null]'
- return u'[object %s]'% GetClass(to_object(this, args.space))
+ return u'[object %s]' % GetClass(to_object(this, args.space))
def valueOf(this, args):
return to_object(this, args.space)
@@ -46,9 +46,3 @@ def propertyIsEnumerable(this, args):
o = to_object(this, args.space)
cand = o.own.get(to_string(prop))
return cand is not None and cand.get('enumerable')
-
-
-
-
-
-
diff --git a/js2py/internals/prototypes/jsregexp.py b/js2py/internals/prototypes/jsregexp.py
index dd814577..54aba327 100644
--- a/js2py/internals/prototypes/jsregexp.py
+++ b/js2py/internals/prototypes/jsregexp.py
@@ -3,6 +3,7 @@
from ..conversions import *
from ..func_utils import *
+
class RegExpPrototype:
def toString(this, args):
flags = u''
@@ -19,22 +20,22 @@ def toString(this, args):
v = this.value if this.value else u'(?:)'
except:
v = u'(?:)'
- return u'/%s/'%v + flags
+ return u'/%s/' % v + flags
def test(this, args):
string = get_arg(args, 0)
return RegExpExec(this, string, args.space) is not null
- def _exec(this, args): # will be changed to exec in base.py. cant name it exec here...
+ def _exec(
+ this, args
+ ): # will be changed to exec in base.py. cant name it exec here...
string = get_arg(args, 0)
return RegExpExec(this, string, args.space)
-
-
def RegExpExec(this, string, space):
- if GetClass(this)!='RegExp':
- raise this.MakeError('TypeError', 'RegExp.prototype.exec is not generic!')
+ if GetClass(this) != 'RegExp':
+ raise MakeError('TypeError', 'RegExp.prototype.exec is not generic!')
string = to_string(string)
length = len(string)
i = to_int(this.get('lastIndex')) if this.glob else 0
@@ -45,11 +46,11 @@ def RegExpExec(this, string, space):
return null
matched = this.match(string, i)
i += 1
- start, end = matched.span()#[0]+i-1, matched.span()[1]+i-1
+ start, end = matched.span() #[0]+i-1, matched.span()[1]+i-1
if this.glob:
this.put('lastIndex', float(end))
- arr = convert_to_js_type([matched.group()]+list(matched.groups()), space=space)
+ arr = convert_to_js_type(
+ [matched.group()] + list(matched.groups()), space=space)
arr.put('index', float(start))
arr.put('input', unicode(string))
return arr
-
diff --git a/js2py/internals/prototypes/jsstring.py b/js2py/internals/prototypes/jsstring.py
index d3f37d0b..e8473af8 100644
--- a/js2py/internals/prototypes/jsstring.py
+++ b/js2py/internals/prototypes/jsstring.py
@@ -4,68 +4,77 @@
import re
from ..conversions import *
from ..func_utils import *
-from jsregexp import RegExpExec
+from .jsregexp import RegExpExec
DIGS = set(u'0123456789')
WHITE = u"\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF"
+
def replacement_template(rep, source, span, npar):
"""Takes the replacement template and some info about the match and returns filled template
"""
n = 0
res = ''
- while n < len(rep)-1:
+ while n < len(rep) - 1:
char = rep[n]
- if char=='$':
- if rep[n+1]=='$':
+ if char == '$':
+ if rep[n + 1] == '$':
res += '$'
n += 2
continue
- elif rep[n+1]=='`':
+ elif rep[n + 1] == '&':
+ # replace with matched string
+ res += source[span[0]:span[1]]
+ n += 2
+ continue
+ elif rep[n + 1] == '`':
# replace with string that is BEFORE match
res += source[:span[0]]
n += 2
continue
- elif rep[n+1]=='\'':
+ elif rep[n + 1] == '\'':
# replace with string that is AFTER match
res += source[span[1]:]
n += 2
continue
- elif rep[n+1] in DIGS:
- dig = rep[n+1]
- if n+2len(npar):
- res += '$'+dig
+ if not num or num > len(npar):
+ res += '$' + dig
else:
# None - undefined has to be replaced with ''
- res += npar[num-1] if npar[num-1] else ''
+ res += npar[num - 1] if npar[num - 1] else ''
n += 1 + len(dig)
continue
res += char
n += 1
- if nthat:
+ elif s > that:
return 1.
return 0.
@@ -119,21 +128,22 @@ def match(this, args):
cok(this)
s = to_string(this)
regexp = get_arg(args, 0)
- r = args.space.NewRegExp(regexp, '') if GetClass(regexp)!='RegExp' else regexp
+ r = args.space.NewRegExp(
+ regexp, '') if GetClass(regexp) != 'RegExp' else regexp
if not r.glob:
return RegExpExec(r, s, space=args.space)
- r.put('lastIndex', this.Js(0))
+ r.put('lastIndex', float(0))
found = []
previous_last_index = 0
last_match = True
while last_match:
result = RegExpExec(r, s, space=args.space)
if is_null(result):
- last_match=False
+ last_match = False
else:
this_index = r.get('lastIndex')
- if this_index==previous_last_index:
- r.put('lastIndex', float(this_index+1))
+ if this_index == previous_last_index:
+ r.put('lastIndex', float(this_index + 1))
previous_last_index += 1
else:
previous_last_index = this_index
@@ -143,7 +153,6 @@ def match(this, args):
return null
return args.space.ConstructArray(found)
-
def replace(this, args):
# VERY COMPLICATED. to check again.
cok(this)
@@ -163,15 +172,19 @@ def replace(this, args):
res += s[last:e.span()[0]]
if func:
# prepare arguments for custom func (replaceValue)
- call_args = (e.group(),) + e.groups() + (e.span()[1], s)
+ call_args = (e.group(), ) + e.groups() + (e.span()[1], s)
# convert all types to JS before Js bytecode call...
- res += to_string(replaceValue.call(this, ensure_js_types(call_args, space=args.space)))
+ res += to_string(
+ replaceValue.call(
+ this, ensure_js_types(call_args,
+ space=args.space)))
else:
- res += replacement_template(replaceValue, s, e.span(), e.groups())
+ res += replacement_template(replaceValue, s, e.span(),
+ e.groups())
last = e.span()[1]
res += s[last:]
return res
- elif GetClass(searchValue)=='RegExp':
+ elif GetClass(searchValue) == 'RegExp':
e = re.search(searchValue.pat, s)
if e is None:
return s
@@ -180,16 +193,19 @@ def replace(this, args):
match = e.group()
else:
match = to_string(searchValue)
- ind = s.find(match)
- if ind==-1:
+ ind = s.find(match)
+ if ind == -1:
return s
span = ind, ind + len(match)
pars = ()
res = s[:span[0]]
if func:
- call_args = (match,) + pars + (span[1], s)
+ call_args = (match, ) + pars + (span[1], s)
# convert all types to JS before Js bytecode call...
- res += to_string(replaceValue.call(this, ensure_js_types(call_args, space=args.space)))
+ res += to_string(
+ replaceValue.call(this,
+ ensure_js_types(call_args,
+ space=args.space)))
else:
res += replacement_template(replaceValue, s, span, pars)
res += s[span[1]:]
@@ -199,7 +215,7 @@ def search(this, args):
cok(this)
string = to_string(this)
regexp = get_arg(args, 0)
- if GetClass(regexp)=='RegExp':
+ if GetClass(regexp) == 'RegExp':
rx = regexp
else:
rx = args.space.NewRegExp(regexp, '')
@@ -219,47 +235,46 @@ def slice(this, args):
#To = max(length+end, 0) if end<0 else min(length, end)
return s[start:end]
-
def split(this, args):
# its a bit different from re.split!
cok(this)
s = to_string(this)
separator = get_arg(args, 0)
limit = get_arg(args, 1)
- lim = 2**32-1 if is_undefined(limit) else to_uint32(limit)
+ lim = 2**32 - 1 if is_undefined(limit) else to_uint32(limit)
if not lim:
return args.space.ConstructArray([])
if is_undefined(separator):
return args.space.ConstructArray([s])
len_s = len(s)
res = []
- R = separator if GetClass(separator)=='RegExp' else to_string(separator)
+ R = separator if GetClass(separator) == 'RegExp' else to_string(
+ separator)
if not len_s:
if SplitMatch(s, 0, R) is None:
return args.space.ConstructArray([s])
return args.space.ConstructArray([])
p = q = 0
- while q!=len_s:
+ while q != len_s:
e, cap = SplitMatch(s, q, R)
- if e is None or e==p:
+ if e is None or e == p:
q += 1
continue
res.append(s[p:q])
p = q = e
- if len(res)==lim:
+ if len(res) == lim:
return args.space.ConstructArray(res)
for element in cap:
res.append(element)
- if len(res)==lim:
+ if len(res) == lim:
return args.space.ConstructArray(res)
res.append(s[p:])
return args.space.ConstructArray(res)
-
- def substring (this, args):
+ def substring(this, args):
cok(this)
s = to_string(this)
- start = get_arg(args, 0)
+ start = to_int(get_arg(args, 0))
length = len(s)
end = get_arg(args, 1)
end = length if is_undefined(end) else to_int(end)
@@ -271,15 +286,15 @@ def substr(this, args):
cok(this)
#I hate this function and its description in specification
r1 = to_string(this)
- r2 = to_int(get_arg(args ,0))
- length = get_arg(args ,1)
- r3 = 10**20 if is_undefined(length) else to_int(length)
+ r2 = to_int(get_arg(args, 0))
+ length = get_arg(args, 1)
+ r3 = 10**20 if is_undefined(length) else to_int(length)
r4 = len(r1)
- r5 = r2 if r2>=0 else max(0, r2+r4)
- r6 = min(max(r3 ,0), r4 - r5)
- if r6<=0:
+ r5 = r2 if r2 >= 0 else max(0, r2 + r4)
+ r6 = min(max(r3, 0), r4 - r5)
+ if r6 <= 0:
return ''
- return r1[r5:r5+r6]
+ return r1[r5:r5 + r6]
def toLowerCase(this, args):
cok(this)
@@ -302,15 +317,12 @@ def trim(this, args):
return to_string(this).strip(WHITE)
-
-
def SplitMatch(s, q, R):
# s is Py String to match, q is the py int match start and R is Js RegExp or String.
- if GetClass(R)=='RegExp':
+ if GetClass(R) == 'RegExp':
res = R.match(s, q)
return (None, ()) if res is None else (res.span()[1], res.groups())
# R is just a string
if s[q:].startswith(R):
- return q+len(R), ()
+ return q + len(R), ()
return None, ()
-
diff --git a/js2py/internals/prototypes/jsutils.py b/js2py/internals/prototypes/jsutils.py
index d35ddded..85f5bd44 100644
--- a/js2py/internals/prototypes/jsutils.py
+++ b/js2py/internals/prototypes/jsutils.py
@@ -2,51 +2,109 @@
from ..conversions import *
from ..func_utils import *
-
-RADIX_CHARS = {'1': 1, '0': 0, '3': 3, '2': 2, '5': 5, '4': 4, '7': 7, '6': 6, '9': 9, '8': 8, 'a': 10, 'c': 12,
- 'b': 11, 'e': 14, 'd': 13, 'g': 16, 'f': 15, 'i': 18, 'h': 17, 'k': 20, 'j': 19, 'm': 22, 'l': 21,
- 'o': 24, 'n': 23, 'q': 26, 'p': 25, 's': 28, 'r': 27, 'u': 30, 't': 29, 'w': 32, 'v': 31, 'y': 34,
- 'x': 33, 'z': 35, 'A': 10, 'C': 12, 'B': 11, 'E': 14, 'D': 13, 'G': 16, 'F': 15, 'I': 18, 'H': 17,
- 'K': 20, 'J': 19, 'M': 22, 'L': 21, 'O': 24, 'N': 23, 'Q': 26, 'P': 25, 'S': 28, 'R': 27, 'U': 30,
- 'T': 29, 'W': 32, 'V': 31, 'Y': 34, 'X': 33, 'Z': 35}
+RADIX_CHARS = {
+ '1': 1,
+ '0': 0,
+ '3': 3,
+ '2': 2,
+ '5': 5,
+ '4': 4,
+ '7': 7,
+ '6': 6,
+ '9': 9,
+ '8': 8,
+ 'a': 10,
+ 'c': 12,
+ 'b': 11,
+ 'e': 14,
+ 'd': 13,
+ 'g': 16,
+ 'f': 15,
+ 'i': 18,
+ 'h': 17,
+ 'k': 20,
+ 'j': 19,
+ 'm': 22,
+ 'l': 21,
+ 'o': 24,
+ 'n': 23,
+ 'q': 26,
+ 'p': 25,
+ 's': 28,
+ 'r': 27,
+ 'u': 30,
+ 't': 29,
+ 'w': 32,
+ 'v': 31,
+ 'y': 34,
+ 'x': 33,
+ 'z': 35,
+ 'A': 10,
+ 'C': 12,
+ 'B': 11,
+ 'E': 14,
+ 'D': 13,
+ 'G': 16,
+ 'F': 15,
+ 'I': 18,
+ 'H': 17,
+ 'K': 20,
+ 'J': 19,
+ 'M': 22,
+ 'L': 21,
+ 'O': 24,
+ 'N': 23,
+ 'Q': 26,
+ 'P': 25,
+ 'S': 28,
+ 'R': 27,
+ 'U': 30,
+ 'T': 29,
+ 'W': 32,
+ 'V': 31,
+ 'Y': 34,
+ 'X': 33,
+ 'Z': 35
+}
# parseFloat
# parseInt
# isFinite
# isNaN
+
def parseInt(this, args):
string, radix = get_arg(args, 0), get_arg(args, 1)
string = to_string(string).lstrip()
sign = 1
if string and string[0] in ('+', '-'):
- if string[0]=='-':
+ if string[0] == '-':
sign = -1
string = string[1:]
r = to_int32(radix)
strip_prefix = True
if r:
- if r<2 or r>36:
+ if r < 2 or r > 36:
return NaN
- if r!=16:
+ if r != 16:
strip_prefix = False
else:
r = 10
if strip_prefix:
- if len(string)>=2 and string[:2] in ('0x', '0X'):
+ if len(string) >= 2 and string[:2] in ('0x', '0X'):
string = string[2:]
r = 16
n = 0
- num = 0
- while n4: # cant be a number anymore
+ if failed > 4: # cant be a number anymore
break
length += 1
if num is None:
return NaN
- return sign*float(string[:max_len])
+ return sign * float(string[:max_len])
def isNaN(this, args):
@@ -88,4 +146,4 @@ def isFinite(this, args):
num = to_number(number)
if is_nan(num) or is_infinity(num):
return False
- return True
\ No newline at end of file
+ return True
diff --git a/js2py/internals/seval.py b/js2py/internals/seval.py
new file mode 100644
index 00000000..cd8ea50f
--- /dev/null
+++ b/js2py/internals/seval.py
@@ -0,0 +1,33 @@
+import pyjsparser
+from .space import Space
+from . import fill_space
+from .byte_trans import ByteCodeGenerator
+from .code import Code
+from .simplex import *
+
+
+pyjsparser.parser.ENABLE_JS2PY_ERRORS = lambda msg: MakeError(u'SyntaxError', unicode(msg))
+
+def get_js_bytecode(js):
+ a = ByteCodeGenerator(Code())
+ d = pyjsparser.parse(js)
+ a.emit(d)
+ return a.exe.tape
+
+def eval_js_vm(js, debug=False):
+ a = ByteCodeGenerator(Code(debug_mode=debug))
+ s = Space()
+ a.exe.space = s
+ s.exe = a.exe
+
+ d = pyjsparser.parse(js)
+
+ a.emit(d)
+ fill_space.fill_space(s, a)
+ if debug:
+ from pprint import pprint
+ pprint(a.exe.tape)
+ print()
+ a.exe.compile()
+
+ return a.exe.run(a.exe.space.GlobalObj)
diff --git a/js2py/internals/simplex.py b/js2py/internals/simplex.py
index 8260e6a8..4cd247eb 100644
--- a/js2py/internals/simplex.py
+++ b/js2py/internals/simplex.py
@@ -1,15 +1,26 @@
from __future__ import unicode_literals
+import six
+if six.PY3:
+ basestring = str
+ long = int
+ xrange = range
+ unicode = str
#Undefined
class PyJsUndefined(object):
TYPE = 'Undefined'
Class = 'Undefined'
+
+
undefined = PyJsUndefined()
+
#Null
class PyJsNull(object):
TYPE = 'Null'
Class = 'Null'
+
+
null = PyJsNull()
Infinity = float('inf')
@@ -17,12 +28,13 @@ class PyJsNull(object):
UNDEFINED_TYPE = PyJsUndefined
NULL_TYPE = PyJsNull
-STRING_TYPE = unicode
+STRING_TYPE = unicode if six.PY2 else str
NUMBER_TYPE = float
BOOLEAN_TYPE = bool
# exactly 5 simplexes!
-PRIMITIVES = frozenset([UNDEFINED_TYPE, NULL_TYPE, STRING_TYPE, NUMBER_TYPE, BOOLEAN_TYPE])
+PRIMITIVES = frozenset(
+ [UNDEFINED_TYPE, NULL_TYPE, STRING_TYPE, NUMBER_TYPE, BOOLEAN_TYPE])
TYPE_NAMES = {
UNDEFINED_TYPE: 'Undefined',
@@ -32,10 +44,12 @@ class PyJsNull(object):
BOOLEAN_TYPE: 'Boolean',
}
+
def Type(x):
# Any -> Str
return TYPE_NAMES.get(type(x), 'Object')
+
def GetClass(x):
# Any -> Str
cand = TYPE_NAMES.get(type(x))
@@ -43,58 +57,104 @@ def GetClass(x):
return x.Class
return cand
+
def is_undefined(self):
return self is undefined
+
def is_null(self):
return self is null
+
def is_primitive(self):
return type(self) in PRIMITIVES
+
def is_object(self):
return not is_primitive(self)
+
def is_callable(self):
return hasattr(self, 'call')
+
def is_infinity(self):
- return self == float('inf') or self == -float('inf')
+ return self == Infinity or self == -Infinity
+
def is_nan(self):
return self != self # nan!=nan evaluates to True
+
def is_finite(self):
return not (is_nan(self) or is_infinity(self))
class JsException(Exception):
- def __init__(self, typ, message, throw=None):
- assert throw is None or (typ is None and message is None), (throw, typ, message)
- self.typ = typ
- self.message = message
- self.throw = throw
+ def __init__(self, typ=None, message=None, throw=None):
+ if typ is None and message is None and throw is None:
+ # it means its the trasnlator based error (old format), do nothing
+ self._translator_based = True
+ else:
+ assert throw is None or (typ is None
+ and message is None), (throw, typ,
+ message)
+ self._translator_based = False
+ self.typ = typ
+ self.message = message
+ self.throw = throw
def get_thrown_value(self, space):
- if self.throw:
+ if self.throw is not None:
return self.throw
else:
return space.NewError(self.typ, self.message)
def __str__(self):
- if self.throw is not None:
- from conversions import to_string
- return to_string(self.throw)
+ if self._translator_based:
+ if self.mes.Class == 'Error':
+ return self.mes.callprop('toString').value
+ else:
+ return self.mes.to_string().value
else:
- return self.typ+': '+self.message
-
+ if self.throw is not None:
+ from .conversions import to_string
+ return to_string(self.throw)
+ else:
+ return self.typ + ': ' + self.message
def MakeError(typ, message=u'no info', throw=None):
- return JsException(typ, unicode(message) if message is not None else message, throw)
+ return JsException(typ,
+ unicode(message) if message is not None else message,
+ throw)
+
def value_from_js_exception(js_exception, space):
if js_exception.throw is not None:
return js_exception.throw
else:
return space.NewError(js_exception.typ, js_exception.message)
+
+
+def js_dtoa(number):
+ if is_nan(number):
+ return u'NaN'
+ elif is_infinity(number):
+ if number > 0:
+ return u'Infinity'
+ return u'-Infinity'
+ elif number == 0.:
+ return u'0'
+ elif abs(number) < 1e-6 or abs(number) >= 1e21:
+ frac, exponent = unicode(repr(float(number))).split('e')
+ # Remove leading zeros from the exponent.
+ exponent = int(exponent)
+ return frac + ('e' if exponent < 0 else 'e+') + unicode(exponent)
+ elif abs(number) < 1e-4: # python starts to return exp notation while we still want the prec
+ frac, exponent = unicode(repr(float(number))).split('e-')
+ base = u'0.' + u'0' * (int(exponent) - 1) + frac.lstrip('-').replace('.', '')
+ return base if number > 0. else u'-' + base
+ elif isinstance(number, long) or number.is_integer(): # dont print .0
+ return unicode(int(number))
+ return unicode(repr(number)) # python representation should be equivalent.
diff --git a/js2py/internals/space.py b/js2py/internals/space.py
index f6e267a3..cb2e77ae 100644
--- a/js2py/internals/space.py
+++ b/js2py/internals/space.py
@@ -1,5 +1,6 @@
-from base import *
-from simplex import *
+from .base import *
+from .simplex import *
+
class Space(object):
def __init__(self):
@@ -47,16 +48,23 @@ def ERROR_TYPES(self):
'URIError': self.URIErrorPrototype,
}
-
-
def get_global_environment(self):
return self.GlobalCtx.variable_environment()
def NewObject(self):
return PyJsObject(self.ObjectPrototype)
- def NewFunction(self, code, ctx, params, name, is_declaration, definitions):
- return PyJsFunction(code, ctx, params, name, self, is_declaration, definitions, prototype=self.FunctionPrototype)
+ def NewFunction(self, code, ctx, params, name, is_declaration,
+ definitions):
+ return PyJsFunction(
+ code,
+ ctx,
+ params,
+ name,
+ self,
+ is_declaration,
+ definitions,
+ prototype=self.FunctionPrototype)
def NewDate(self, value):
return PyJsDate(value, self.DatePrototype)
diff --git a/js2py/internals/speed.py b/js2py/internals/speed.py
index 82f9e62a..482eb7ea 100644
--- a/js2py/internals/speed.py
+++ b/js2py/internals/speed.py
@@ -1,17 +1,27 @@
+from __future__ import print_function
+
from timeit import timeit
from collections import namedtuple
from array import array
-from itertools import izip
+try:
+ #python 2 code
+ from itertools import izip as zip
+except ImportError:
+ pass
+
from collections import deque
+
class Y(object):
UUU = 88
+
def __init__(self, x):
self.x = x
def s(self, x):
return self.x + 1
+
class X(Y):
A = 10
B = 2
@@ -29,32 +39,31 @@ def s(self, x):
def __add__(self, other):
return self.x + other.x
-
def another(self):
return Y.s(self, 1)
def yet_another(self):
return self.par.s(1)
-def add(a,b):
- return a.x + b.x
-
+def add(a, b):
+ return a.x + b.x
t = []
-
Type = None
try:
- print timeit(
-"""
+ print(timeit(
+ """
t.append(4)
t.pop()
-""", "from __main__ import X,Y,namedtuple,array,t,add,Type, izip", number=1000000)
+""",
+ "from __main__ import X,Y,namedtuple,array,t,add,Type, zip",
+ number=1000000))
except:
- raise
\ No newline at end of file
+ raise
diff --git a/js2py/internals/trans_utils.py b/js2py/internals/trans_utils.py
index 3798889b..f99c0994 100644
--- a/js2py/internals/trans_utils.py
+++ b/js2py/internals/trans_utils.py
@@ -1,3 +1,10 @@
+import six
+if six.PY3:
+ basestring = str
+ long = int
+ xrange = range
+ unicode = str
+
def to_key(literal_or_identifier):
''' returns string representation of this object'''
if literal_or_identifier['type'] == 'Identifier':
@@ -25,4 +32,4 @@ def compose_regex(val):
def float_repr(f):
if int(f) == f:
return unicode(repr(int(f)))
- return unicode(repr(f))
\ No newline at end of file
+ return unicode(repr(f))
diff --git a/js2py/legecy_translators/constants.py b/js2py/legecy_translators/constants.py
index 96bb79fe..8ada25ad 100644
--- a/js2py/legecy_translators/constants.py
+++ b/js2py/legecy_translators/constants.py
@@ -1,51 +1,55 @@
+from __future__ import print_function
from string import ascii_lowercase, digits
##################################
StringName = u'PyJsConstantString%d_'
NumberName = u'PyJsConstantNumber%d_'
RegExpName = u'PyJsConstantRegExp%d_'
##################################
-ALPHAS = set(ascii_lowercase+ ascii_lowercase.upper())
+ALPHAS = set(ascii_lowercase + ascii_lowercase.upper())
NUMS = set(digits)
IDENTIFIER_START = ALPHAS.union(NUMS)
ESCAPE_CHARS = {'n', '0', 'b', 'f', 'r', 't', 'v', '"', "'", '\\'}
OCTAL = {'0', '1', '2', '3', '4', '5', '6', '7'}
HEX = set('0123456789abcdefABCDEF')
from utils import *
-IDENTIFIER_PART = IDENTIFIER_PART.union({'.'})
+IDENTIFIER_PART = IDENTIFIER_PART.union({'.'})
def _is_cancelled(source, n):
cancelled = False
k = 0
while True:
- k+=1
- if source[n-k]!='\\':
+ k += 1
+ if source[n - k] != '\\':
break
cancelled = not cancelled
return cancelled
-def _ensure_regexp(source, n): #<- this function has to be improved
+
+def _ensure_regexp(source, n): #<- this function has to be improved
'''returns True if regexp starts at n else returns False
checks whether it is not a division '''
markers = '(+~"\'=[%:?!*^|&-,;/\\'
k = 0
while True:
- k+=1
- if n-k<0:
+ k += 1
+ if n - k < 0:
return True
- char = source[n-k]
+ char = source[n - k]
if char in markers:
return True
- if char!=' ' and char!='\n':
+ if char != ' ' and char != '\n':
break
return False
+
def parse_num(source, start, charset):
"""Returns a first index>=start of chat not in charset"""
- while start max_num:
break
num = cand
@@ -278,17 +296,14 @@ def do_escape(source, n):
# we have to return in a different form because python may want to parse more...
# for example '\777' will be parsed by python as a whole while js will use only \77
return '\\' + hex(num)[1:], n + len_parsed
- return source[n+1], n+2
-
-
-
+ return source[n + 1], n + 2
#####TEST######
-if __name__=='__main__':
+if __name__ == '__main__':
test = ('''
''')
t, d = remove_constants(test)
- print t, d
\ No newline at end of file
+ print(t, d)
diff --git a/js2py/legecy_translators/exps.py b/js2py/legecy_translators/exps.py
index 5e72abca..bcd09b19 100644
--- a/js2py/legecy_translators/exps.py
+++ b/js2py/legecy_translators/exps.py
@@ -16,9 +16,12 @@
NOTES:
Strings and other literals are not present so each = means assignment
"""
+from __future__ import print_function
+
from utils import *
from jsparser import *
+
def exps_translator(js):
#Check () {} and [] nums
ass = assignment_translator(js)
@@ -29,7 +32,7 @@ def assignment_translator(js):
sep = js.split(',')
res = sep[:]
for i, e in enumerate(sep):
- if '=' not in e: # no need to convert
+ if '=' not in e: # no need to convert
continue
res[i] = bass_translator(e)
return ','.join(res)
@@ -39,11 +42,11 @@ def bass_translator(s):
# I hope that I will not have to fix any bugs here because it will be terrible
if '(' in s or '[' in s:
converted = ''
- for e in bracket_split(s, ['()','[]'], strip=False):
- if e[0]=='(':
- converted += '(' + bass_translator(e[1:-1])+')'
- elif e[0]=='[':
- converted += '[' + bass_translator(e[1:-1])+']'
+ for e in bracket_split(s, ['()', '[]'], strip=False):
+ if e[0] == '(':
+ converted += '(' + bass_translator(e[1:-1]) + ')'
+ elif e[0] == '[':
+ converted += '[' + bass_translator(e[1:-1]) + ']'
else:
converted += e
s = converted
@@ -54,26 +57,29 @@ def bass_translator(s):
res = last
for e in ass:
op = ''
- if e[-1] in OP_METHODS: #increment assign like +=
- op = ', "'+e[-1]+'"'
+ if e[-1] in OP_METHODS: #increment assign like +=
+ op = ', "' + e[-1] + '"'
e = e[:-1]
- cand = e.strip('() ') # (a) = 40 is valid so we need to transform '(a) ' to 'a'
- if not is_property_accessor(cand): # it is not a property assignment
+ cand = e.strip(
+ '() ') # (a) = 40 is valid so we need to transform '(a) ' to 'a'
+ if not is_property_accessor(cand): # it is not a property assignment
if not is_lval(cand) or is_internal(cand):
raise SyntaxError('Invalid left-hand side in assignment')
- res = 'var.put(%s, %s%s)'%(cand.__repr__(), res, op)
- elif cand[-1]==']': # property assignment via []
+ res = 'var.put(%s, %s%s)' % (cand.__repr__(), res, op)
+ elif cand[-1] == ']': # property assignment via []
c = list(bracket_split(cand, ['[]'], strip=False))
- meth, prop = ''.join(c[:-1]).strip(), c[-1][1:-1].strip() #this does not have to be a string so dont remove
- #() because it can be a call
- res = '%s.put(%s, %s%s)'%(meth, prop, res, op)
+ meth, prop = ''.join(c[:-1]).strip(), c[-1][1:-1].strip(
+ ) #this does not have to be a string so dont remove
+ #() because it can be a call
+ res = '%s.put(%s, %s%s)' % (meth, prop, res, op)
else: # Prop set via '.'
c = cand.rfind('.')
- meth, prop = cand[:c].strip(), cand[c+1:].strip('() ')
+ meth, prop = cand[:c].strip(), cand[c + 1:].strip('() ')
if not is_lval(prop):
raise SyntaxError('Invalid left-hand side in assignment')
- res = '%s.put(%s, %s%s)'%(meth, prop.__repr__(), res, op)
+ res = '%s.put(%s, %s%s)' % (meth, prop.__repr__(), res, op)
return res
-if __name__=='__main__':
- print bass_translator('3.ddsd = 40')
\ No newline at end of file
+
+if __name__ == '__main__':
+ print(bass_translator('3.ddsd = 40'))
diff --git a/js2py/legecy_translators/flow.py b/js2py/legecy_translators/flow.py
index 523859cb..60d99aa3 100644
--- a/js2py/legecy_translators/flow.py
+++ b/js2py/legecy_translators/flow.py
@@ -9,31 +9,34 @@
FOR iter
CONTINUE, BREAK, RETURN, LABEL, THROW, TRY, SWITCH
"""
+from __future__ import print_function
+
from utils import *
from jsparser import *
from nodevisitor import exp_translator
import random
-
TO_REGISTER = []
CONTINUE_LABEL = 'JS_CONTINUE_LABEL_%s'
BREAK_LABEL = 'JS_BREAK_LABEL_%s'
-
PREPARE = '''HOLDER = var.own.get(NAME)\nvar.force_own_put(NAME, PyExceptionToJs(PyJsTempException))\n'''
RESTORE = '''if HOLDER is not None:\n var.own[NAME] = HOLDER\nelse:\n del var.own[NAME]\ndel HOLDER\n'''
TRY_CATCH = '''%stry:\nBLOCKfinally:\n%s''' % (PREPARE, indent(RESTORE))
+
def get_continue_label(label):
- return CONTINUE_LABEL%label.encode('hex')
+ return CONTINUE_LABEL % label.encode('hex')
+
def get_break_label(label):
- return BREAK_LABEL%label.encode('hex')
+ return BREAK_LABEL % label.encode('hex')
-def pass_until(source, start, tokens=(';',)):
+
+def pass_until(source, start, tokens=(';', )):
while start < len(source) and source[start] not in tokens:
- start+=1
- return start+1
+ start += 1
+ return start + 1
def do_bracket_exp(source, start, throw=True):
@@ -47,12 +50,12 @@ def do_bracket_exp(source, start, throw=True):
def do_if(source, start):
- start += 2 # pass this if
+ start += 2 # pass this if
bra, start = do_bracket_exp(source, start, throw=True)
statement, start = do_statement(source, start)
if statement is None:
raise SyntaxError('Invalid if statement')
- translated = 'if %s:\n'%bra+indent(statement)
+ translated = 'if %s:\n' % bra + indent(statement)
elseif = except_keyword(source, start, 'else')
is_elseif = False
@@ -66,7 +69,7 @@ def do_if(source, start):
if is_elseif:
translated += 'el' + elseif
else:
- translated += 'else:\n'+ indent(elseif)
+ translated += 'else:\n' + indent(elseif)
return translated, start
@@ -75,39 +78,40 @@ def do_statement(source, start):
also this do_ type function passes white space"""
start = pass_white(source, start)
# start is the fist position after initial start that is not a white space or \n
- if not start < len(source): #if finished parsing return None
+ if not start < len(source): #if finished parsing return None
return None, start
if any(startswith_keyword(source[start:], e) for e in {'case', 'default'}):
return None, start
rest = source[start:]
- for key, meth in KEYWORD_METHODS.iteritems(): # check for statements that are uniquely defined by their keywords
+ for key, meth in KEYWORD_METHODS.iteritems(
+ ): # check for statements that are uniquely defined by their keywords
if rest.startswith(key):
# has to startwith this keyword and the next letter after keyword must be either EOF or not in IDENTIFIER_PART
- if len(key)==len(rest) or rest[len(key)] not in IDENTIFIER_PART:
+ if len(key) == len(rest) or rest[len(key)] not in IDENTIFIER_PART:
return meth(source, start)
- if rest[0] == '{': #Block
+ if rest[0] == '{': #Block
return do_block(source, start)
# Now only label and expression left
cand = parse_identifier(source, start, False)
- if cand is not None: # it can mean that its a label
+ if cand is not None: # it can mean that its a label
label, cand_start = cand
cand_start = pass_white(source, cand_start)
- if source[cand_start]==':':
+ if source[cand_start] == ':':
return do_label(source, start)
return do_expression(source, start)
def do_while(source, start):
- start += 5 # pass while
+ start += 5 # pass while
bra, start = do_bracket_exp(source, start, throw=True)
statement, start = do_statement(source, start)
if statement is None:
raise SyntaxError('Missing statement to execute in while loop!')
- return 'while %s:\n'%bra + indent(statement), start
+ return 'while %s:\n' % bra + indent(statement), start
def do_dowhile(source, start):
- start += 2 # pass do
+ start += 2 # pass do
statement, start = do_statement(source, start)
if statement is None:
raise SyntaxError('Missing statement to execute in do while loop!')
@@ -116,7 +120,7 @@ def do_dowhile(source, start):
raise SyntaxError('Missing while keyword in do-while loop')
bra, start = do_bracket_exp(source, start, throw=True)
statement += 'if not %s:\n' % bra + indent('break\n')
- return 'while 1:\n' + indent(statement), start
+ return 'while 1:\n' + indent(statement), start
def do_block(source, start):
@@ -126,25 +130,28 @@ def do_block(source, start):
if bra is None:
raise SyntaxError('Missing block ( {code} )')
code = ''
- bra = bra[1:-1]+';'
+ bra = bra[1:-1] + ';'
bra_pos = 0
- while bra_pos=len(rev):
+ if rpos >= len(rev):
raise
if filter(lambda x: x not in SPACE, rev[lpos:rpos]):
- break
+ break
end = start + len(rev) - rpos + 1
-
def do_var(source, start):
#todo auto ; insertion
- start += 3 #pass var
- end = pass_until(source, start, tokens=(';',))
- defs = argsplit(source[start:end-1]) # defs is the list of defined vars with optional initializer
+ start += 3 #pass var
+ end = pass_until(source, start, tokens=(';', ))
+ defs = argsplit(
+ source[start:end - 1]
+ ) # defs is the list of defined vars with optional initializer
code = ''
for de in defs:
var, var_end = parse_identifier(de, 0, True)
TO_REGISTER.append(var)
var_end = pass_white(de, var_end)
- if var_end>': '__rshift__',
- '&': '__and__',
- '^': '__xor__',
- '|': '__or__'}
+OP_METHODS = {
+ '*': '__mul__',
+ '/': '__div__',
+ '%': '__mod__',
+ '+': '__add__',
+ '-': '__sub__',
+ '<<': '__lshift__',
+ '>>': '__rshift__',
+ '&': '__and__',
+ '^': '__xor__',
+ '|': '__or__'
+}
+
def dbg(source):
try:
- with open('C:\Users\Piotrek\Desktop\dbg.py','w') as f:
+ with open(r'C:\Users\Piotrek\Desktop\dbg.py', 'w') as f:
f.write(source)
except:
pass
def indent(lines, ind=4):
- return ind*' '+lines.replace('\n', '\n'+ind*' ').rstrip(' ')
+ return ind * ' ' + lines.replace('\n', '\n' + ind * ' ').rstrip(' ')
def inject_before_lval(source, lval, code):
- if source.count(lval)>1:
+ if source.count(lval) > 1:
dbg(source)
- print
- print lval
+ print()
+ print(lval)
raise RuntimeError('To many lvals (%s)' % lval)
elif not source.count(lval):
dbg(source)
- print
- print lval
+ print()
+ print(lval)
assert lval not in source
raise RuntimeError('No lval found "%s"' % lval)
end = source.index(lval)
inj = source.rfind('\n', 0, end)
ind = inj
- while source[ind+1]==' ':
- ind+=1
+ while source[ind + 1] == ' ':
+ ind += 1
ind -= inj
- return source[:inj+1]+ indent(code, ind) + source[inj+1:]
+ return source[:inj + 1] + indent(code, ind) + source[inj + 1:]
-def bracket_split(source, brackets=('()','{}','[]'), strip=False):
+def bracket_split(source, brackets=('()', '{}', '[]'), strip=False):
"""DOES NOT RETURN EMPTY STRINGS (can only return empty bracket content if strip=True)"""
starts = [e[0] for e in brackets]
in_bracket = 0
n = 0
last = 0
- while n len(source):
+ if kl + start > len(source):
return None
- if source[start:start+kl] != keyword:
+ if source[start:start + kl] != keyword:
return None
- if kl+starttext_len:
+ if s + n > text_len:
continue
- if validitate and not validitate(e, text[:n], text[n+s:]):
+ if validitate and not validitate(e, text[:n], text[n + s:]):
continue
- if any(text[n+s:].startswith(e) for e in not_after): #Cant end with end before
- n+=1
+ if any(text[n + s:].startswith(e)
+ for e in not_after): #Cant end with end before
+ n += 1
break
- if e==text[n:n+s]:
- yield text[last:n] if not translate else translate(text[last:n])
+ if e == text[n:n + s]:
+ yield text[last:n] if not translate else translate(
+ text[last:n])
yield e
- n+=s
+ n += s
last = n
break
else:
- n+=1
+ n += 1
yield text[last:n] if not translate else translate(text[last:n])
+
def split_at_single(text, sep, not_before=[], not_after=[]):
"""Works like text.split(sep) but separated fragments
cant end with not_before or start with not_after"""
n = 0
- lt, s= len(text), len(sep)
+ lt, s = len(text), len(sep)
last = 0
- while nlt:
- if sep==text[n:n+s]:
+ while n < lt:
+ if not s + n > lt:
+ if sep == text[n:n + s]:
if any(text[last:n].endswith(e) for e in not_before):
pass
- elif any(text[n+s:].startswith(e) for e in not_after):
+ elif any(text[n + s:].startswith(e) for e in not_after):
pass
else:
yield text[last:n]
- last = n+s
- n += s-1
- n+=1
- yield text[last:]
\ No newline at end of file
+ last = n + s
+ n += s - 1
+ n += 1
+ yield text[last:]
diff --git a/js2py/legecy_translators/nodevisitor.py b/js2py/legecy_translators/nodevisitor.py
index c642a2fb..5e20654b 100644
--- a/js2py/legecy_translators/nodevisitor.py
+++ b/js2py/legecy_translators/nodevisitor.py
@@ -1,3 +1,5 @@
+from __future__ import print_function
+
from jsparser import *
from utils import *
import re
@@ -6,43 +8,46 @@
#Note all white space sent to this module must be ' ' so no '\n'
REPL = {}
-
#PROBLEMS
# <<=, >>=, >>>=
# they are unusual so I will not fix that now. a++ +b works fine and a+++++b (a++ + ++b) does not work even in V8
ASSIGNMENT_MATCH = '(?)=(?!=)'
+
def unary_validitator(keyword, before, after):
if keyword[-1] in IDENTIFIER_PART:
if not after or after[0] in IDENTIFIER_PART:
return False
- if before and before[-1] in IDENTIFIER_PART: # I am not sure here...
+ if before and before[-1] in IDENTIFIER_PART: # I am not sure here...
return False
return True
+
def comb_validitator(keyword, before, after):
- if keyword=='instanceof' or keyword=='in':
+ if keyword == 'instanceof' or keyword == 'in':
if before and before[-1] in IDENTIFIER_PART:
return False
elif after and after[0] in IDENTIFIER_PART:
return False
return True
+
def bracket_replace(code):
new = ''
- for e in bracket_split(code, ['()','[]'], False):
- if e[0]=='[':
- name = '#PYJSREPL'+str(len(REPL))+'{'
- new+= name
+ for e in bracket_split(code, ['()', '[]'], False):
+ if e[0] == '[':
+ name = '#PYJSREPL' + str(len(REPL)) + '{'
+ new += name
REPL[name] = e
- elif e[0]=='(': # can be a function call
- name = '@PYJSREPL'+str(len(REPL))+'}'
- new+= name
+ elif e[0] == '(': # can be a function call
+ name = '@PYJSREPL' + str(len(REPL)) + '}'
+ new += name
REPL[name] = e
else:
- new+=e
+ new += e
return new
+
class NodeVisitor:
def __init__(self, code):
self.code = code
@@ -76,8 +81,8 @@ def translate(self):
return ''
new = bracket_replace(self.code)
#Check comma operator:
- cand = new.split(',') #every comma in new must be an operator
- if len(cand)>1: #LR
+ cand = new.split(',') #every comma in new must be an operator
+ if len(cand) > 1: #LR
return self.lr(cand, js_comma)
#Check = operator:
# dont split at != or !== or == or === or <= or >=
@@ -94,34 +99,36 @@ def translate(self):
else:
break
actual_tenary = new[tenary_start:]
- spl = ''.join(split_at_any(new, [':', '?'], translate=trans))
+ spl = ''.join(split_at_any(new, [':', '?'], translate=trans))
tenary_translation = transform_crap(spl)
assignment = new[:tenary_start] + ' PyJsConstantTENARY'
- return trans(assignment).replace('PyJsConstantTENARY', tenary_translation)
- cand = list(split_at_single(new, '=', ['!', '=','<','>'], ['=']))
- if len(cand)>1: # RL
+ return trans(assignment).replace('PyJsConstantTENARY',
+ tenary_translation)
+ cand = list(split_at_single(new, '=', ['!', '=', '<', '>'], ['=']))
+ if len(cand) > 1: # RL
it = reversed(cand)
- res = trans(it.next())
+ res = trans(it.next())
for e in it:
e = e.strip()
if not e:
raise SyntaxError('Missing left-hand in assignment!')
op = ''
if e[-2:] in OP_METHODS:
- op = ','+e[-2:].__repr__()
+ op = ',' + e[-2:].__repr__()
e = e[:-2]
elif e[-1:] in OP_METHODS:
- op = ','+e[-1].__repr__()
+ op = ',' + e[-1].__repr__()
e = e[:-1]
e = trans(e)
#Now replace last get method with put and change args
c = list(bracket_split(e, ['()']))
- beg, arglist = ''.join(c[:-1]).strip(), c[-1].strip() #strips just to make sure... I will remove it later
- if beg[-4:]!='.get':
+ beg, arglist = ''.join(c[:-1]).strip(), c[-1].strip(
+ ) #strips just to make sure... I will remove it later
+ if beg[-4:] != '.get':
raise SyntaxError('Invalid left-hand side in assignment')
- beg = beg[0:-3]+'put'
- arglist = arglist[0:-1]+', '+res+op+')'
- res = beg+arglist
+ beg = beg[0:-3] + 'put'
+ arglist = arglist[0:-1] + ', ' + res + op + ')'
+ res = beg + arglist
return res
#Now check remaining 2 arg operators that are not handled by python
#They all have Left to Right (LR) associativity
@@ -134,27 +141,36 @@ def translate(self):
cand = list(split_add_ops(new))
else:
#dont translate. cant start or end on dangerous op.
- cand = list(split_at_any(new, typ.keys(), False, dangerous, dangerous,validitate=comb_validitator))
- if not len(cand)>1:
+ cand = list(
+ split_at_any(
+ new,
+ typ.keys(),
+ False,
+ dangerous,
+ dangerous,
+ validitate=comb_validitator))
+ if not len(cand) > 1:
continue
n = 1
res = trans(cand[0])
if not res:
raise SyntaxError("Missing operand!")
- while n1: #contains unary operators
- if '++' in cand or '--' in cand: #it cant contain both ++ and --
+ cand = list(
+ split_at_any(
+ new, UNARY.keys(), False, validitate=unary_validitator))
+ if len(cand) > 1: #contains unary operators
+ if '++' in cand or '--' in cand: #it cant contain both ++ and --
if '--' in cand:
op = '--'
meths = js_post_dec, js_pre_dec
@@ -162,43 +178,46 @@ def translate(self):
op = '++'
meths = js_post_inc, js_pre_inc
pos = cand.index(op)
- if cand[pos-1].strip(): # post increment
- a = cand[pos-1]
+ if cand[pos - 1].strip(): # post increment
+ a = cand[pos - 1]
meth = meths[0]
- elif cand[pos+1].strip(): #pre increment
- a = cand[pos+1]
+ elif cand[pos + 1].strip(): #pre increment
+ a = cand[pos + 1]
meth = meths[1]
else:
raise SyntaxError('Invalid use of ++ operator')
- if cand[pos+2:]:
+ if cand[pos + 2:]:
raise SyntaxError('Too many operands')
operand = meth(trans(a))
- cand = cand[:pos-1]
+ cand = cand[:pos - 1]
# now last cand should be operand and every other odd element should be empty
else:
operand = trans(cand[-1])
del cand[-1]
for i, e in enumerate(reversed(cand)):
- if i%2:
+ if i % 2:
if e.strip():
raise SyntaxError('Too many operands')
else:
operand = UNARY[e](operand)
return operand
#Replace brackets
- if new[0]=='@' or new[0]=='#':
- if len(list(bracket_split(new, ('#{','@}')))) ==1: # we have only one bracket, otherwise pseudobracket like @@....
+ if new[0] == '@' or new[0] == '#':
+ if len(
+ list(bracket_split(new, ('#{', '@}')))
+ ) == 1: # we have only one bracket, otherwise pseudobracket like @@....
assert new in REPL
- if new[0]=='#':
- raise SyntaxError('[] cant be used as brackets! Use () instead.')
- return '('+trans(REPL[new][1:-1])+')'
+ if new[0] == '#':
+ raise SyntaxError(
+ '[] cant be used as brackets! Use () instead.')
+ return '(' + trans(REPL[new][1:-1]) + ')'
#Replace function calls and prop getters
# 'now' must be a reference like: a or b.c.d but it can have also calls or getters ( for example a["b"](3))
#From here @@ means a function call and ## means get operation (note they dont have to present)
- it = bracket_split(new, ('#{','@}'))
+ it = bracket_split(new, ('#{', '@}'))
res = []
for e in it:
- if e[0]!='#' and e[0]!='@':
+ if e[0] != '#' and e[0] != '@':
res += [x.strip() for x in e.split('.')]
else:
res += [e.strip()]
@@ -207,174 +226,210 @@ def translate(self):
if is_internal(res[0]):
out = res[0]
elif res[0][0] in {'#', '@'}:
- out = '('+trans(REPL[res[0]][1:-1])+')'
- elif is_valid_lval(res[0]) or res[0] in {'this', 'false', 'true', 'null'}:
- out = 'var.get('+res[0].__repr__()+')'
+ out = '(' + trans(REPL[res[0]][1:-1]) + ')'
+ elif is_valid_lval(
+ res[0]) or res[0] in {'this', 'false', 'true', 'null'}:
+ out = 'var.get(' + res[0].__repr__() + ')'
else:
if is_reserved(res[0]):
- raise SyntaxError('Unexpected reserved word: "%s"'%res[0])
- raise SyntaxError('Invalid identifier: "%s"'%res[0])
- if len(res)==1:
+ raise SyntaxError('Unexpected reserved word: "%s"' % res[0])
+ raise SyntaxError('Invalid identifier: "%s"' % res[0])
+ if len(res) == 1:
return out
n = 1
- while n='+b+')'
+ return '(' + a + '>=' + b + ')'
+
def js_gt(a, b):
- return '('+a+'>'+b+')'
+ return '(' + a + '>' + b + ')'
+
def js_in(a, b):
- return b+'.contains('+a+')'
+ return b + '.contains(' + a + ')'
+
def js_instanceof(a, b):
- return a+'.instanceof('+b+')'
+ return a + '.instanceof(' + b + ')'
+
def js_lshift(a, b):
- return '('+a+'<<'+b+')'
+ return '(' + a + '<<' + b + ')'
+
def js_rshift(a, b):
- return '('+a+'>>'+b+')'
+ return '(' + a + '>>' + b + ')'
+
def js_shit(a, b):
- return 'PyJsBshift('+a+','+b+')'
+ return 'PyJsBshift(' + a + ',' + b + ')'
+
+
+def js_add(
+ a,
+ b): # To simplify later process of converting unary operators + and ++
+ return '(%s+%s)' % (a, b)
-def js_add(a, b): # To simplify later process of converting unary operators + and ++
- return '(%s+%s)'%(a, b)
def js_sub(a, b): # To simplify
- return '(%s-%s)'%(a, b)
+ return '(%s-%s)' % (a, b)
+
def js_mul(a, b):
- return '('+a+'*'+b+')'
+ return '(' + a + '*' + b + ')'
+
def js_div(a, b):
- return '('+a+'/'+b+')'
+ return '(' + a + '/' + b + ')'
+
def js_mod(a, b):
- return '('+a+'%'+b+')'
+ return '(' + a + '%' + b + ')'
+
def js_typeof(a):
- cand = list(bracket_split(a, ('()',)))
- if len(cand)==2 and cand[0]=='var.get':
- return cand[0]+cand[1][:-1]+',throw=False).typeof()'
- return a+'.typeof()'
+ cand = list(bracket_split(a, ('()', )))
+ if len(cand) == 2 and cand[0] == 'var.get':
+ return cand[0] + cand[1][:-1] + ',throw=False).typeof()'
+ return a + '.typeof()'
+
def js_void(a):
- return '('+a+')'
+ return '(' + a + ')'
+
def js_new(a):
- cands = list(bracket_split(a, ('()',)))
+ cands = list(bracket_split(a, ('()', )))
lim = len(cands)
if lim < 2:
return a + '.create()'
n = 0
while n < lim:
c = cands[n]
- if c[0]=='(':
- if cands[n-1].endswith('.get') and n+1>=lim: # last get operation.
+ if c[0] == '(':
+ if cands[n - 1].endswith(
+ '.get') and n + 1 >= lim: # last get operation.
return a + '.create()'
- elif cands[n-1][0]=='(':
- return ''.join(cands[:n])+'.create' + c + ''.join(cands[n+1:])
- elif cands[n-1]=='.callprop':
- beg = ''.join(cands[:n-1])
- args = argsplit(c[1:-1],',')
- prop = args[0]
- new_args = ','.join(args[1:])
- create = '.get(%s).create(%s)' % (prop, new_args)
- return beg + create + ''.join(cands[n+1:])
- n+=1
+ elif cands[n - 1][0] == '(':
+ return ''.join(cands[:n]) + '.create' + c + ''.join(
+ cands[n + 1:])
+ elif cands[n - 1] == '.callprop':
+ beg = ''.join(cands[:n - 1])
+ args = argsplit(c[1:-1], ',')
+ prop = args[0]
+ new_args = ','.join(args[1:])
+ create = '.get(%s).create(%s)' % (prop, new_args)
+ return beg + create + ''.join(cands[n + 1:])
+ n += 1
return a + '.create()'
-
-
-
def js_delete(a):
#replace last get with delete.
c = list(bracket_split(a, ['()']))
- beg, arglist = ''.join(c[:-1]).strip(), c[-1].strip() #strips just to make sure... I will remove it later
- if beg[-4:]!='.get':
+ beg, arglist = ''.join(c[:-1]).strip(), c[-1].strip(
+ ) #strips just to make sure... I will remove it later
+ if beg[-4:] != '.get':
raise SyntaxError('Invalid delete operation')
- return beg[:-3]+'delete'+arglist
+ return beg[:-3] + 'delete' + arglist
+
def js_neg(a):
- return '(-'+a+')'
+ return '(-' + a + ')'
+
def js_pos(a):
- return '(+'+a+')'
+ return '(+' + a + ')'
+
def js_inv(a):
- return '(~'+a+')'
+ return '(~' + a + ')'
+
def js_not(a):
- return a+'.neg()'
+ return a + '.neg()'
+
def postfix(a, inc, post):
- bra = list(bracket_split(a, ('()',)))
+ bra = list(bracket_split(a, ('()', )))
meth = bra[-2]
if not meth.endswith('get'):
raise SyntaxError('Invalid ++ or -- operation.')
@@ -383,15 +438,19 @@ def postfix(a, inc, post):
res = ''.join(bra)
return res if not post else '(%s%sJs(1))' % (res, '-' if inc else '+')
+
def js_pre_inc(a):
return postfix(a, True, False)
+
def js_post_inc(a):
return postfix(a, True, True)
+
def js_pre_dec(a):
return postfix(a, False, False)
+
def js_post_dec(a):
return postfix(a, False, True)
@@ -402,65 +461,67 @@ def js_post_dec(a):
BXOR = {'^': js_bxor}
BAND = {'&': js_band}
-EQS = {'===': js_strict_eq,
- '!==': js_strict_neq,
- '==': js_abstract_eq, # we need == and != too. Read a note above method
- '!=': js_abstract_neq}
+EQS = {
+ '===': js_strict_eq,
+ '!==': js_strict_neq,
+ '==': js_abstract_eq, # we need == and != too. Read a note above method
+ '!=': js_abstract_neq
+}
#Since JS does not have chained comparisons we need to implement all cmp methods.
-COMPS = {'<': js_lt,
- '<=': js_le,
- '>=': js_ge,
- '>': js_gt,
- 'instanceof': js_instanceof, #todo change to validitate
- 'in': js_in}
-
-BSHIFTS = {'<<': js_lshift,
- '>>': js_rshift,
- '>>>': js_shit}
+COMPS = {
+ '<': js_lt,
+ '<=': js_le,
+ '>=': js_ge,
+ '>': js_gt,
+ 'instanceof': js_instanceof, #todo change to validitate
+ 'in': js_in
+}
-ADDS = {'+': js_add,
- '-': js_sub}
+BSHIFTS = {'<<': js_lshift, '>>': js_rshift, '>>>': js_shit}
-MULTS = {'*': js_mul,
- '/': js_div,
- '%': js_mod}
+ADDS = {'+': js_add, '-': js_sub}
+MULTS = {'*': js_mul, '/': js_div, '%': js_mod}
#Note they dont contain ++ and -- methods because they both have 2 different methods
# correct method will be found automatically in translate function
-UNARY = {'typeof': js_typeof,
- 'void': js_void,
- 'new': js_new,
- 'delete': js_delete,
- '!': js_not,
- '-': js_neg,
- '+': js_pos,
- '~': js_inv,
- '++': None,
- '--': None
- }
-
-
-def transform_crap(code): #needs some more tests
+UNARY = {
+ 'typeof': js_typeof,
+ 'void': js_void,
+ 'new': js_new,
+ 'delete': js_delete,
+ '!': js_not,
+ '-': js_neg,
+ '+': js_pos,
+ '~': js_inv,
+ '++': None,
+ '--': None
+}
+
+
+def transform_crap(code): #needs some more tests
"""Transforms this ?: crap into if else python syntax"""
ind = code.rfind('?')
- if ind==-1:
+ if ind == -1:
return code
sep = code.find(':', ind)
- if sep==-1:
+ if sep == -1:
raise SyntaxError('Invalid ?: syntax (probably missing ":" )')
- beg = max(code.rfind(':', 0, ind), code.find('?', 0, ind))+1
- end = code.find(':',sep+1)
- end = len(code) if end==-1 else end
- formula = '('+code[ind+1:sep]+' if '+code[beg:ind]+' else '+code[sep+1:end]+')'
- return transform_crap(code[:beg]+formula+code[end:])
+ beg = max(code.rfind(':', 0, ind), code.find('?', 0, ind)) + 1
+ end = code.find(':', sep + 1)
+ end = len(code) if end == -1 else end
+ formula = '(' + code[ind + 1:sep] + ' if ' + code[
+ beg:ind] + ' else ' + code[sep + 1:end] + ')'
+ return transform_crap(code[:beg] + formula + code[end:])
from code import InteractiveConsole
#e = InteractiveConsole(globals()).interact()
import traceback
+
+
def trans(code):
return NodeVisitor(code.strip()).translate().strip()
@@ -469,9 +530,12 @@ def trans(code):
def trans_args(code):
new = bracket_replace(code.strip()[1:-1])
args = ','.join(trans(e) for e in new.split(','))
- return '(%s)'%args
+ return '(%s)' % args
+
EXP = 0
+
+
def exp_translator(code):
global REPL, EXP
EXP += 1
@@ -490,11 +554,11 @@ def exp_translator(code):
#raw_input('\n\npress enter')
raise
-if __name__=='__main__':
+
+if __name__ == '__main__':
#print 'Here', trans('(eee ) . ii [ PyJsMarker ] [ jkj ] ( j , j ) .
# jiji (h , ji , i)(non )( )()()()')
for e in xrange(3):
- print exp_translator('jk = kk.ik++')
+ print(exp_translator('jk = kk.ik++'))
#First line translated with PyJs: PyJsStrictEq(PyJsAdd((Js(100)*Js(50)),Js(30)), Js("5030")), yay!
- print exp_translator('delete a.f')
-
+ print(exp_translator('delete a.f'))
diff --git a/js2py/legecy_translators/nparser.py b/js2py/legecy_translators/nparser.py
index 8cd4d2bd..a9c97c9a 100644
--- a/js2py/legecy_translators/nparser.py
+++ b/js2py/legecy_translators/nparser.py
@@ -33,6 +33,8 @@
# -*- coding: latin-1 -*-
from __future__ import print_function
import re
+
+
def typeof(t):
if t is None: return 'undefined'
elif isinstance(t, bool): return 'boolean'
@@ -41,343 +43,398 @@ def typeof(t):
elif hasattr(t, '__call__'): return 'function'
else: return 'object'
+
def list_indexOf(l, v):
try:
return l.index(v)
except:
return -1
+
parseFloat = float
parseInt = int
+
class jsdict(object):
def __init__(self, d):
self.__dict__.update(d)
+
def __getitem__(self, name):
if name in self.__dict__:
- return self.__dict__[name]
+ return self.__dict__[name]
else:
- return None
+ return None
+
def __setitem__(self, name, value):
self.__dict__[name] = value
return value
+
def __getattr__(self, name):
try:
return getattr(self, name)
except:
return None
+
def __setattr__(self, name, value):
self[name] = value
return value
+
def __contains__(self, name):
return name in self.__dict__
+
def __repr__(self):
return str(self.__dict__)
+
class RegExp(object):
def __init__(self, pattern, flags=''):
self.flags = flags
pyflags = 0 | re.M if 'm' in flags else 0 | re.I if 'i' in flags else 0
self.source = pattern
self.pattern = re.compile(pattern, pyflags)
+
def test(self, s):
return self.pattern.search(s) is not None
-console = jsdict({"log":print})
+
+console = jsdict({"log": print})
+
def __temp__42(object=None, body=None):
return jsdict({
-"type": Syntax.WithStatement,
-"object": object,
-"body": body,
-})
+ "type": Syntax.WithStatement,
+ "object": object,
+ "body": body,
+ })
+
def __temp__41(test=None, body=None):
return jsdict({
-"type": Syntax.WhileStatement,
-"test": test,
-"body": body,
-})
+ "type": Syntax.WhileStatement,
+ "test": test,
+ "body": body,
+ })
+
def __temp__40(id=None, init=None):
return jsdict({
-"type": Syntax.VariableDeclarator,
-"id": id,
-"init": init,
-})
+ "type": Syntax.VariableDeclarator,
+ "id": id,
+ "init": init,
+ })
+
def __temp__39(declarations=None, kind=None):
return jsdict({
-"type": Syntax.VariableDeclaration,
-"declarations": declarations,
-"kind": kind,
-})
+ "type": Syntax.VariableDeclaration,
+ "declarations": declarations,
+ "kind": kind,
+ })
+
def __temp__38(operator=None, argument=None):
if (operator == "++") or (operator == "--"):
return jsdict({
-"type": Syntax.UpdateExpression,
-"operator": operator,
-"argument": argument,
-"prefix": True,
-})
+ "type": Syntax.UpdateExpression,
+ "operator": operator,
+ "argument": argument,
+ "prefix": True,
+ })
return jsdict({
-"type": Syntax.UnaryExpression,
-"operator": operator,
-"argument": argument,
-"prefix": True,
-})
+ "type": Syntax.UnaryExpression,
+ "operator": operator,
+ "argument": argument,
+ "prefix": True,
+ })
-def __temp__37(block=None, guardedHandlers=None, handlers=None, finalizer=None):
+
+def __temp__37(block=None, guardedHandlers=None, handlers=None,
+ finalizer=None):
return jsdict({
-"type": Syntax.TryStatement,
-"block": block,
-"guardedHandlers": guardedHandlers,
-"handlers": handlers,
-"finalizer": finalizer,
-})
+ "type": Syntax.TryStatement,
+ "block": block,
+ "guardedHandlers": guardedHandlers,
+ "handlers": handlers,
+ "finalizer": finalizer,
+ })
+
def __temp__36(argument=None):
return jsdict({
-"type": Syntax.ThrowStatement,
-"argument": argument,
-})
+ "type": Syntax.ThrowStatement,
+ "argument": argument,
+ })
+
def __temp__35():
return jsdict({
-"type": Syntax.ThisExpression,
-})
+ "type": Syntax.ThisExpression,
+ })
+
def __temp__34(discriminant=None, cases=None):
return jsdict({
-"type": Syntax.SwitchStatement,
-"discriminant": discriminant,
-"cases": cases,
-})
+ "type": Syntax.SwitchStatement,
+ "discriminant": discriminant,
+ "cases": cases,
+ })
+
def __temp__33(test=None, consequent=None):
return jsdict({
-"type": Syntax.SwitchCase,
-"test": test,
-"consequent": consequent,
-})
+ "type": Syntax.SwitchCase,
+ "test": test,
+ "consequent": consequent,
+ })
+
def __temp__32(expressions=None):
return jsdict({
-"type": Syntax.SequenceExpression,
-"expressions": expressions,
-})
+ "type": Syntax.SequenceExpression,
+ "expressions": expressions,
+ })
+
def __temp__31(argument=None):
return jsdict({
-"type": Syntax.ReturnStatement,
-"argument": argument,
-})
+ "type": Syntax.ReturnStatement,
+ "argument": argument,
+ })
+
def __temp__30(kind=None, key=None, value=None):
return jsdict({
-"type": Syntax.Property,
-"key": key,
-"value": value,
-"kind": kind,
-})
+ "type": Syntax.Property,
+ "key": key,
+ "value": value,
+ "kind": kind,
+ })
+
def __temp__29(body=None):
return jsdict({
-"type": Syntax.Program,
-"body": body,
-})
+ "type": Syntax.Program,
+ "body": body,
+ })
+
def __temp__28(operator=None, argument=None):
return jsdict({
-"type": Syntax.UpdateExpression,
-"operator": operator,
-"argument": argument,
-"prefix": False,
-})
+ "type": Syntax.UpdateExpression,
+ "operator": operator,
+ "argument": argument,
+ "prefix": False,
+ })
+
def __temp__27(properties=None):
return jsdict({
-"type": Syntax.ObjectExpression,
-"properties": properties,
-})
+ "type": Syntax.ObjectExpression,
+ "properties": properties,
+ })
+
def __temp__26(callee=None, args=None):
return jsdict({
-"type": Syntax.NewExpression,
-"callee": callee,
-"arguments": args,
-})
+ "type": Syntax.NewExpression,
+ "callee": callee,
+ "arguments": args,
+ })
+
def __temp__25(accessor=None, object=None, property=None):
return jsdict({
-"type": Syntax.MemberExpression,
-"computed": accessor == "[",
-"object": object,
-"property": property,
-})
+ "type": Syntax.MemberExpression,
+ "computed": accessor == "[",
+ "object": object,
+ "property": property,
+ })
+
def __temp__24(token=None):
return jsdict({
-"type": Syntax.Literal,
-"value": token.value,
-"raw": source[token.range[0]:token.range[1]],
-})
+ "type": Syntax.Literal,
+ "value": token.value,
+ "raw": source[token.range[0]:token.range[1]],
+ })
+
def __temp__23(label=None, body=None):
return jsdict({
-"type": Syntax.LabeledStatement,
-"label": label,
-"body": body,
-})
+ "type": Syntax.LabeledStatement,
+ "label": label,
+ "body": body,
+ })
+
def __temp__22(test=None, consequent=None, alternate=None):
return jsdict({
-"type": Syntax.IfStatement,
-"test": test,
-"consequent": consequent,
-"alternate": alternate,
-})
+ "type": Syntax.IfStatement,
+ "test": test,
+ "consequent": consequent,
+ "alternate": alternate,
+ })
+
def __temp__21(name=None):
return jsdict({
-"type": Syntax.Identifier,
-"name": name,
-})
+ "type": Syntax.Identifier,
+ "name": name,
+ })
+
def __temp__20(id=None, params=None, defaults=None, body=None):
return jsdict({
-"type": Syntax.FunctionExpression,
-"id": id,
-"params": params,
-"defaults": defaults,
-"body": body,
-"rest": None,
-"generator": False,
-"expression": False,
-})
+ "type": Syntax.FunctionExpression,
+ "id": id,
+ "params": params,
+ "defaults": defaults,
+ "body": body,
+ "rest": None,
+ "generator": False,
+ "expression": False,
+ })
+
def __temp__19(id=None, params=None, defaults=None, body=None):
return jsdict({
-"type": Syntax.FunctionDeclaration,
-"id": id,
-"params": params,
-"defaults": defaults,
-"body": body,
-"rest": None,
-"generator": False,
-"expression": False,
-})
+ "type": Syntax.FunctionDeclaration,
+ "id": id,
+ "params": params,
+ "defaults": defaults,
+ "body": body,
+ "rest": None,
+ "generator": False,
+ "expression": False,
+ })
+
def __temp__18(left=None, right=None, body=None):
return jsdict({
-"type": Syntax.ForInStatement,
-"left": left,
-"right": right,
-"body": body,
-"each": False,
-})
+ "type": Syntax.ForInStatement,
+ "left": left,
+ "right": right,
+ "body": body,
+ "each": False,
+ })
+
def __temp__17(init=None, test=None, update=None, body=None):
return jsdict({
-"type": Syntax.ForStatement,
-"init": init,
-"test": test,
-"update": update,
-"body": body,
-})
+ "type": Syntax.ForStatement,
+ "init": init,
+ "test": test,
+ "update": update,
+ "body": body,
+ })
+
def __temp__16(expression=None):
return jsdict({
-"type": Syntax.ExpressionStatement,
-"expression": expression,
-})
+ "type": Syntax.ExpressionStatement,
+ "expression": expression,
+ })
+
def __temp__15():
return jsdict({
-"type": Syntax.EmptyStatement,
-})
+ "type": Syntax.EmptyStatement,
+ })
+
def __temp__14(body=None, test=None):
return jsdict({
-"type": Syntax.DoWhileStatement,
-"body": body,
-"test": test,
-})
+ "type": Syntax.DoWhileStatement,
+ "body": body,
+ "test": test,
+ })
+
def __temp__13():
return jsdict({
-"type": Syntax.DebuggerStatement,
-})
+ "type": Syntax.DebuggerStatement,
+ })
+
def __temp__12(label=None):
return jsdict({
-"type": Syntax.ContinueStatement,
-"label": label,
-})
+ "type": Syntax.ContinueStatement,
+ "label": label,
+ })
+
def __temp__11(test=None, consequent=None, alternate=None):
return jsdict({
-"type": Syntax.ConditionalExpression,
-"test": test,
-"consequent": consequent,
-"alternate": alternate,
-})
+ "type": Syntax.ConditionalExpression,
+ "test": test,
+ "consequent": consequent,
+ "alternate": alternate,
+ })
+
def __temp__10(param=None, body=None):
return jsdict({
-"type": Syntax.CatchClause,
-"param": param,
-"body": body,
-})
+ "type": Syntax.CatchClause,
+ "param": param,
+ "body": body,
+ })
+
def __temp__9(callee=None, args=None):
return jsdict({
-"type": Syntax.CallExpression,
-"callee": callee,
-"arguments": args,
-})
+ "type": Syntax.CallExpression,
+ "callee": callee,
+ "arguments": args,
+ })
+
def __temp__8(label=None):
return jsdict({
-"type": Syntax.BreakStatement,
-"label": label,
-})
+ "type": Syntax.BreakStatement,
+ "label": label,
+ })
+
def __temp__7(body=None):
return jsdict({
-"type": Syntax.BlockStatement,
-"body": body,
-})
+ "type": Syntax.BlockStatement,
+ "body": body,
+ })
+
def __temp__6(operator=None, left=None, right=None):
- type = (Syntax.LogicalExpression if (operator == "||") or (operator == "&&") else Syntax.BinaryExpression)
+ type = (Syntax.LogicalExpression if (operator == "||") or
+ (operator == "&&") else Syntax.BinaryExpression)
return jsdict({
-"type": type,
-"operator": operator,
-"left": left,
-"right": right,
-})
+ "type": type,
+ "operator": operator,
+ "left": left,
+ "right": right,
+ })
+
def __temp__5(operator=None, left=None, right=None):
return jsdict({
-"type": Syntax.AssignmentExpression,
-"operator": operator,
-"left": left,
-"right": right,
-})
+ "type": Syntax.AssignmentExpression,
+ "operator": operator,
+ "left": left,
+ "right": right,
+ })
+
def __temp__4(elements=None):
return jsdict({
-"type": Syntax.ArrayExpression,
-"elements": elements,
-})
+ "type": Syntax.ArrayExpression,
+ "elements": elements,
+ })
+
def __temp__3(node=None):
if extra.source:
node.loc.source = extra.source
return node
+
def __temp__2(node=None):
if node.range or node.loc:
if extra.loc:
@@ -389,23 +446,27 @@ def __temp__2(node=None):
SyntaxTreeDelegate.markEnd(node)
return node
+
def __temp__1(node=None):
if extra.range:
node.range = [state.markerStack.pop(), index]
if extra.loc:
node.loc = jsdict({
-"start": jsdict({
-"line": state.markerStack.pop(),
-"column": state.markerStack.pop(),
-}),
-"end": jsdict({
-"line": lineNumber,
-"column": index - lineStart,
-}),
-})
+ "start":
+ jsdict({
+ "line": state.markerStack.pop(),
+ "column": state.markerStack.pop(),
+ }),
+ "end":
+ jsdict({
+ "line": lineNumber,
+ "column": index - lineStart,
+ }),
+ })
SyntaxTreeDelegate.postProcess(node)
return node
+
def __temp__0():
if extra.loc:
state.markerStack.append(index - lineStart)
@@ -413,6 +474,7 @@ def __temp__0():
if extra.range:
state.markerStack.append(index)
+
Token = None
TokenName = None
FnExprTokens = None
@@ -432,18 +494,17 @@ def __temp__0():
state = None
extra = None
Token = jsdict({
-"BooleanLiteral": 1,
-"EOF": 2,
-"Identifier": 3,
-"Keyword": 4,
-"NullLiteral": 5,
-"NumericLiteral": 6,
-"Punctuator": 7,
-"StringLiteral": 8,
-"RegularExpression": 9,
-})
-TokenName = jsdict({
-})
+ "BooleanLiteral": 1,
+ "EOF": 2,
+ "Identifier": 3,
+ "Keyword": 4,
+ "NullLiteral": 5,
+ "NumericLiteral": 6,
+ "Punctuator": 7,
+ "StringLiteral": 8,
+ "RegularExpression": 9,
+})
+TokenName = jsdict({})
TokenName[Token.BooleanLiteral] = "Boolean"
TokenName[Token.EOF] = ""
TokenName[Token.Identifier] = "Identifier"
@@ -453,137 +514,216 @@ def __temp__0():
TokenName[Token.Punctuator] = "Punctuator"
TokenName[Token.StringLiteral] = "String"
TokenName[Token.RegularExpression] = "RegularExpression"
-FnExprTokens = ["(", "{", "[", "in", "typeof", "instanceof", "new", "return", "case", "delete", "throw", "void", "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", "&=", "|=", "^=", ",", "+", "-", "*", "/", "%", "++", "--", "<<", ">>", ">>>", "&", "|", "^", "!", "~", "&&", "||", "?", ":", "===", "==", ">=", "<=", "<", ">", "!=", "!=="]
+FnExprTokens = [
+ "(", "{", "[", "in", "typeof", "instanceof", "new", "return", "case",
+ "delete", "throw", "void", "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=",
+ ">>>=", "&=", "|=", "^=", ",", "+", "-", "*", "/", "%", "++", "--", "<<",
+ ">>", ">>>", "&", "|", "^", "!", "~", "&&", "||", "?", ":", "===", "==",
+ ">=", "<=", "<", ">", "!=", "!=="
+]
Syntax = jsdict({
-"AssignmentExpression": "AssignmentExpression",
-"ArrayExpression": "ArrayExpression",
-"BlockStatement": "BlockStatement",
-"BinaryExpression": "BinaryExpression",
-"BreakStatement": "BreakStatement",
-"CallExpression": "CallExpression",
-"CatchClause": "CatchClause",
-"ConditionalExpression": "ConditionalExpression",
-"ContinueStatement": "ContinueStatement",
-"DoWhileStatement": "DoWhileStatement",
-"DebuggerStatement": "DebuggerStatement",
-"EmptyStatement": "EmptyStatement",
-"ExpressionStatement": "ExpressionStatement",
-"ForStatement": "ForStatement",
-"ForInStatement": "ForInStatement",
-"FunctionDeclaration": "FunctionDeclaration",
-"FunctionExpression": "FunctionExpression",
-"Identifier": "Identifier",
-"IfStatement": "IfStatement",
-"Literal": "Literal",
-"LabeledStatement": "LabeledStatement",
-"LogicalExpression": "LogicalExpression",
-"MemberExpression": "MemberExpression",
-"NewExpression": "NewExpression",
-"ObjectExpression": "ObjectExpression",
-"Program": "Program",
-"Property": "Property",
-"ReturnStatement": "ReturnStatement",
-"SequenceExpression": "SequenceExpression",
-"SwitchStatement": "SwitchStatement",
-"SwitchCase": "SwitchCase",
-"ThisExpression": "ThisExpression",
-"ThrowStatement": "ThrowStatement",
-"TryStatement": "TryStatement",
-"UnaryExpression": "UnaryExpression",
-"UpdateExpression": "UpdateExpression",
-"VariableDeclaration": "VariableDeclaration",
-"VariableDeclarator": "VariableDeclarator",
-"WhileStatement": "WhileStatement",
-"WithStatement": "WithStatement",
+ "AssignmentExpression": "AssignmentExpression",
+ "ArrayExpression": "ArrayExpression",
+ "BlockStatement": "BlockStatement",
+ "BinaryExpression": "BinaryExpression",
+ "BreakStatement": "BreakStatement",
+ "CallExpression": "CallExpression",
+ "CatchClause": "CatchClause",
+ "ConditionalExpression": "ConditionalExpression",
+ "ContinueStatement": "ContinueStatement",
+ "DoWhileStatement": "DoWhileStatement",
+ "DebuggerStatement": "DebuggerStatement",
+ "EmptyStatement": "EmptyStatement",
+ "ExpressionStatement": "ExpressionStatement",
+ "ForStatement": "ForStatement",
+ "ForInStatement": "ForInStatement",
+ "FunctionDeclaration": "FunctionDeclaration",
+ "FunctionExpression": "FunctionExpression",
+ "Identifier": "Identifier",
+ "IfStatement": "IfStatement",
+ "Literal": "Literal",
+ "LabeledStatement": "LabeledStatement",
+ "LogicalExpression": "LogicalExpression",
+ "MemberExpression": "MemberExpression",
+ "NewExpression": "NewExpression",
+ "ObjectExpression": "ObjectExpression",
+ "Program": "Program",
+ "Property": "Property",
+ "ReturnStatement": "ReturnStatement",
+ "SequenceExpression": "SequenceExpression",
+ "SwitchStatement": "SwitchStatement",
+ "SwitchCase": "SwitchCase",
+ "ThisExpression": "ThisExpression",
+ "ThrowStatement": "ThrowStatement",
+ "TryStatement": "TryStatement",
+ "UnaryExpression": "UnaryExpression",
+ "UpdateExpression": "UpdateExpression",
+ "VariableDeclaration": "VariableDeclaration",
+ "VariableDeclarator": "VariableDeclarator",
+ "WhileStatement": "WhileStatement",
+ "WithStatement": "WithStatement",
})
PropertyKind = jsdict({
-"Data": 1,
-"Get": 2,
-"Set": 4,
+ "Data": 1,
+ "Get": 2,
+ "Set": 4,
})
Messages = jsdict({
-"UnexpectedToken": "Unexpected token %0",
-"UnexpectedNumber": "Unexpected number",
-"UnexpectedString": "Unexpected string",
-"UnexpectedIdentifier": "Unexpected identifier",
-"UnexpectedReserved": "Unexpected reserved word",
-"UnexpectedEOS": "Unexpected end of input",
-"NewlineAfterThrow": "Illegal newline after throw",
-"InvalidRegExp": "Invalid regular expression",
-"UnterminatedRegExp": "Invalid regular expression: missing /",
-"InvalidLHSInAssignment": "Invalid left-hand side in assignment",
-"InvalidLHSInForIn": "Invalid left-hand side in for-in",
-"MultipleDefaultsInSwitch": "More than one default clause in switch statement",
-"NoCatchOrFinally": "Missing catch or finally after try",
-"UnknownLabel": "Undefined label '%0'",
-"Redeclaration": "%0 '%1' has already been declared",
-"IllegalContinue": "Illegal continue statement",
-"IllegalBreak": "Illegal break statement",
-"IllegalReturn": "Illegal return statement",
-"StrictModeWith": "Strict mode code may not include a with statement",
-"StrictCatchVariable": "Catch variable may not be eval or arguments in strict mode",
-"StrictVarName": "Variable name may not be eval or arguments in strict mode",
-"StrictParamName": "Parameter name eval or arguments is not allowed in strict mode",
-"StrictParamDupe": "Strict mode function may not have duplicate parameter names",
-"StrictFunctionName": "Function name may not be eval or arguments in strict mode",
-"StrictOctalLiteral": "Octal literals are not allowed in strict mode.",
-"StrictDelete": "Delete of an unqualified identifier in strict mode.",
-"StrictDuplicateProperty": "Duplicate data property in object literal not allowed in strict mode",
-"AccessorDataProperty": "Object literal may not have data and accessor property with the same name",
-"AccessorGetSet": "Object literal may not have multiple get/set accessors with the same name",
-"StrictLHSAssignment": "Assignment to eval or arguments is not allowed in strict mode",
-"StrictLHSPostfix": "Postfix increment/decrement may not have eval or arguments operand in strict mode",
-"StrictLHSPrefix": "Prefix increment/decrement may not have eval or arguments operand in strict mode",
-"StrictReservedWord": "Use of future reserved word in strict mode",
+ "UnexpectedToken":
+ "Unexpected token %0",
+ "UnexpectedNumber":
+ "Unexpected number",
+ "UnexpectedString":
+ "Unexpected string",
+ "UnexpectedIdentifier":
+ "Unexpected identifier",
+ "UnexpectedReserved":
+ "Unexpected reserved word",
+ "UnexpectedEOS":
+ "Unexpected end of input",
+ "NewlineAfterThrow":
+ "Illegal newline after throw",
+ "InvalidRegExp":
+ "Invalid regular expression",
+ "UnterminatedRegExp":
+ "Invalid regular expression: missing /",
+ "InvalidLHSInAssignment":
+ "Invalid left-hand side in assignment",
+ "InvalidLHSInForIn":
+ "Invalid left-hand side in for-in",
+ "MultipleDefaultsInSwitch":
+ "More than one default clause in switch statement",
+ "NoCatchOrFinally":
+ "Missing catch or finally after try",
+ "UnknownLabel":
+ "Undefined label '%0'",
+ "Redeclaration":
+ "%0 '%1' has already been declared",
+ "IllegalContinue":
+ "Illegal continue statement",
+ "IllegalBreak":
+ "Illegal break statement",
+ "IllegalReturn":
+ "Illegal return statement",
+ "StrictModeWith":
+ "Strict mode code may not include a with statement",
+ "StrictCatchVariable":
+ "Catch variable may not be eval or arguments in strict mode",
+ "StrictVarName":
+ "Variable name may not be eval or arguments in strict mode",
+ "StrictParamName":
+ "Parameter name eval or arguments is not allowed in strict mode",
+ "StrictParamDupe":
+ "Strict mode function may not have duplicate parameter names",
+ "StrictFunctionName":
+ "Function name may not be eval or arguments in strict mode",
+ "StrictOctalLiteral":
+ "Octal literals are not allowed in strict mode.",
+ "StrictDelete":
+ "Delete of an unqualified identifier in strict mode.",
+ "StrictDuplicateProperty":
+ "Duplicate data property in object literal not allowed in strict mode",
+ "AccessorDataProperty":
+ "Object literal may not have data and accessor property with the same name",
+ "AccessorGetSet":
+ "Object literal may not have multiple get/set accessors with the same name",
+ "StrictLHSAssignment":
+ "Assignment to eval or arguments is not allowed in strict mode",
+ "StrictLHSPostfix":
+ "Postfix increment/decrement may not have eval or arguments operand in strict mode",
+ "StrictLHSPrefix":
+ "Prefix increment/decrement may not have eval or arguments operand in strict mode",
+ "StrictReservedWord":
+ "Use of future reserved word in strict mode",
})
Regex = jsdict({
-"NonAsciiIdentifierStart": RegExp(u"[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]"),
-"NonAsciiIdentifierPart": RegExp(u"[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]"),
+ "NonAsciiIdentifierStart":
+ RegExp(
+ u"[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]"
+ ),
+ "NonAsciiIdentifierPart":
+ RegExp(
+ u"[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]"
+ ),
})
+
+
def assert__py__(condition=None, message=None):
if not condition:
raise RuntimeError("ASSERT: " + message)
+
def isDecimalDigit(ch=None):
return (ch >= 48) and (ch <= 57)
+
def isHexDigit(ch=None):
return "0123456789abcdefABCDEF".find(ch) >= 0
+
def isOctalDigit(ch=None):
return "01234567".find(ch) >= 0
+
def isWhiteSpace(ch=None):
- return (((((ch == 32) or (ch == 9)) or (ch == 11)) or (ch == 12)) or (ch == 160)) or ((ch >= 5760) and (u"\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\ufeff".find(unichr(ch)) > 0))
+ return (
+ ((((ch == 32) or (ch == 9)) or (ch == 11)) or
+ (ch == 12)) or (ch == 160)
+ ) or ((ch >= 5760) and (
+ u"\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\ufeff"
+ .find(unichr(ch)) > 0))
+
def isLineTerminator(ch=None):
return (((ch == 10) or (ch == 13)) or (ch == 8232)) or (ch == 8233)
+
def isIdentifierStart(ch=None):
- return (((((ch == 36) or (ch == 95)) or ((ch >= 65) and (ch <= 90))) or ((ch >= 97) and (ch <= 122))) or (ch == 92)) or ((ch >= 128) and Regex.NonAsciiIdentifierStart.test(unichr(ch)))
+ return (((((ch == 36) or (ch == 95)) or ((ch >= 65) and (ch <= 90))) or
+ ((ch >= 97) and (ch <= 122))) or
+ (ch == 92)) or ((ch >= 128)
+ and Regex.NonAsciiIdentifierStart.test(unichr(ch)))
+
def isIdentifierPart(ch=None):
- return ((((((ch == 36) or (ch == 95)) or ((ch >= 65) and (ch <= 90))) or ((ch >= 97) and (ch <= 122))) or ((ch >= 48) and (ch <= 57))) or (ch == 92)) or ((ch >= 128) and Regex.NonAsciiIdentifierPart.test(unichr(ch)))
+ return ((((((ch == 36) or (ch == 95)) or ((ch >= 65) and (ch <= 90))) or
+ ((ch >= 97) and (ch <= 122))) or ((ch >= 48) and (ch <= 57))) or
+ (ch == 92)) or ((ch >= 128)
+ and Regex.NonAsciiIdentifierPart.test(unichr(ch)))
+
def isFutureReservedWord(id=None):
while 1:
- if (id == "super") or ((id == "import") or ((id == "extends") or ((id == "export") or ((id == "enum") or (id == "class"))))):
+ if (id == "super") or ((id == "import") or ((id == "extends") or
+ ((id == "export") or
+ ((id == "enum") or
+ (id == "class"))))):
return True
else:
return False
break
+
def isStrictModeReservedWord(id=None):
while 1:
- if (id == "let") or ((id == "yield") or ((id == "static") or ((id == "public") or ((id == "protected") or ((id == "private") or ((id == "package") or ((id == "interface") or (id == "implements")))))))):
+ if (id == "let") or ((id == "yield") or
+ ((id == "static") or
+ ((id == "public") or
+ ((id == "protected") or
+ ((id == "private") or
+ ((id == "package") or
+ ((id == "interface") or
+ (id == "implements")))))))):
return True
else:
return False
break
+
def isRestrictedWord(id=None):
return (id == "eval") or (id == "arguments")
+
def isKeyword(id=None):
if strict and isStrictModeReservedWord(id):
return True
@@ -591,39 +731,52 @@ def isKeyword(id=None):
if len(id) == 2:
return ((id == "if") or (id == "in")) or (id == "do")
elif len(id) == 3:
- return ((((id == "var") or (id == "for")) or (id == "new")) or (id == "try")) or (id == "let")
+ return ((((id == "var") or (id == "for")) or (id == "new")) or
+ (id == "try")) or (id == "let")
elif len(id) == 4:
- return (((((id == "this") or (id == "else")) or (id == "case")) or (id == "void")) or (id == "with")) or (id == "enum")
+ return (((((id == "this") or (id == "else")) or (id == "case")) or
+ (id == "void")) or (id == "with")) or (id == "enum")
elif len(id) == 5:
- return (((((((id == "while") or (id == "break")) or (id == "catch")) or (id == "throw")) or (id == "const")) or (id == "yield")) or (id == "class")) or (id == "super")
+ return (((((((id == "while") or (id == "break")) or
+ (id == "catch")) or (id == "throw")) or
+ (id == "const")) or (id == "yield")) or
+ (id == "class")) or (id == "super")
elif len(id) == 6:
- return (((((id == "return") or (id == "typeof")) or (id == "delete")) or (id == "switch")) or (id == "export")) or (id == "import")
+ return (((((id == "return") or (id == "typeof")) or
+ (id == "delete")) or (id == "switch")) or
+ (id == "export")) or (id == "import")
elif len(id) == 7:
- return ((id == "default") or (id == "finally")) or (id == "extends")
+ return ((id == "default") or
+ (id == "finally")) or (id == "extends")
elif len(id) == 8:
- return ((id == "function") or (id == "continue")) or (id == "debugger")
+ return ((id == "function") or
+ (id == "continue")) or (id == "debugger")
elif len(id) == 10:
return id == "instanceof"
else:
return False
break
+
def addComment(type=None, value=None, start=None, end=None, loc=None):
comment = None
- assert__py__(('undefined' if not 'start' in locals() else typeof(start)) == "number", "Comment must have valid position")
+ assert__py__(('undefined'
+ if not 'start' in locals() else typeof(start)) == "number",
+ "Comment must have valid position")
if state.lastCommentStart >= start:
- return
+ return
state.lastCommentStart = start
comment = jsdict({
-"type": type,
-"value": value,
-})
+ "type": type,
+ "value": value,
+ })
if extra.range:
comment.range = [start, end]
if extra.loc:
comment.loc = loc
extra.comments.append(comment)
+
def skipSingleLineComment():
global index, lineNumber, lineStart
start = None
@@ -632,11 +785,12 @@ def skipSingleLineComment():
comment = None
start = index - 2
loc = jsdict({
-"start": jsdict({
-"line": lineNumber,
-"column": (index - lineStart) - 2,
-}),
-})
+ "start":
+ jsdict({
+ "line": lineNumber,
+ "column": (index - lineStart) - 2,
+ }),
+ })
while index < length:
ch = (ord(source[index]) if index < len(source) else None)
index += 1
@@ -645,25 +799,27 @@ def skipSingleLineComment():
if extra.comments:
comment = source[(start + 2):(index - 1)]
loc.end = jsdict({
-"line": lineNumber,
-"column": (index - lineStart) - 1,
-})
+ "line": lineNumber,
+ "column": (index - lineStart) - 1,
+ })
addComment("Line", comment, start, index - 1, loc)
- if (ch == 13) and ((ord(source[index]) if index < len(source) else None) == 10):
+ if (ch == 13) and (
+ (ord(source[index]) if index < len(source) else None) == 10):
index += 1
index
lineNumber += 1
lineNumber
lineStart = index
- return
+ return
if extra.comments:
comment = source[(start + 2):index]
loc.end = jsdict({
-"line": lineNumber,
-"column": index - lineStart,
-})
+ "line": lineNumber,
+ "column": index - lineStart,
+ })
addComment("Line", comment, start, index, loc)
+
def skipMultiLineComment():
global index, lineNumber, lineStart
start = None
@@ -673,15 +829,17 @@ def skipMultiLineComment():
if extra.comments:
start = index - 2
loc = jsdict({
-"start": jsdict({
-"line": lineNumber,
-"column": (index - lineStart) - 2,
-}),
-})
+ "start":
+ jsdict({
+ "line": lineNumber,
+ "column": (index - lineStart) - 2,
+ }),
+ })
while index < length:
ch = (ord(source[index]) if index < len(source) else None)
if isLineTerminator(ch):
- if (ch == 13) and ((ord(source[index + 1]) if (index + 1) < len(source) else None) == 10):
+ if (ch == 13) and ((ord(source[index + 1]) if
+ (index + 1) < len(source) else None) == 10):
index += 1
index
lineNumber += 1
@@ -690,10 +848,10 @@ def skipMultiLineComment():
index
lineStart = index
if index >= length:
- throwError(jsdict({
-}), Messages.UnexpectedToken, "ILLEGAL")
+ throwError(jsdict({}), Messages.UnexpectedToken, "ILLEGAL")
elif ch == 42:
- if (ord(source[index + 1]) if (index + 1) < len(source) else None) == 47:
+ if (ord(source[index + 1]) if
+ (index + 1) < len(source) else None) == 47:
index += 1
index
index += 1
@@ -701,18 +859,18 @@ def skipMultiLineComment():
if extra.comments:
comment = source[(start + 2):(index - 2)]
loc.end = jsdict({
-"line": lineNumber,
-"column": index - lineStart,
-})
+ "line": lineNumber,
+ "column": index - lineStart,
+ })
addComment("Block", comment, start, index, loc)
- return
+ return
index += 1
index
else:
index += 1
index
- throwError(jsdict({
-}), Messages.UnexpectedToken, "ILLEGAL")
+ throwError(jsdict({}), Messages.UnexpectedToken, "ILLEGAL")
+
def skipComment():
global index, lineNumber, lineStart
@@ -725,14 +883,16 @@ def skipComment():
elif isLineTerminator(ch):
index += 1
index
- if (ch == 13) and ((ord(source[index]) if index < len(source) else None) == 10):
+ if (ch == 13) and (
+ (ord(source[index]) if index < len(source) else None) == 10):
index += 1
index
lineNumber += 1
lineNumber
lineStart = index
elif ch == 47:
- ch = (ord(source[index + 1]) if (index + 1) < len(source) else None)
+ ch = (ord(source[index + 1]) if
+ (index + 1) < len(source) else None)
if ch == 47:
index += 1
index
@@ -750,6 +910,7 @@ def skipComment():
else:
break
+
def scanHexEscape(prefix=None):
global len__py__, index
i = None
@@ -770,6 +931,7 @@ def scanHexEscape(prefix=None):
i += 1
return unichr(code)
+
def getEscapedIdentifier():
global index
ch = None
@@ -780,14 +942,13 @@ def getEscapedIdentifier():
id = unichr(ch)
if ch == 92:
if (ord(source[index]) if index < len(source) else None) != 117:
- throwError(jsdict({
-}), Messages.UnexpectedToken, "ILLEGAL")
+ throwError(jsdict({}), Messages.UnexpectedToken, "ILLEGAL")
index += 1
index
ch = scanHexEscape("u")
- if ((not ch) or (ch == "\\")) or (not isIdentifierStart((ord(ch[0]) if 0 < len(ch) else None))):
- throwError(jsdict({
-}), Messages.UnexpectedToken, "ILLEGAL")
+ if ((not ch) or (ch == "\\")) or (not isIdentifierStart(
+ (ord(ch[0]) if 0 < len(ch) else None))):
+ throwError(jsdict({}), Messages.UnexpectedToken, "ILLEGAL")
id = ch
while index < length:
ch = (ord(source[index]) if index < len(source) else None)
@@ -799,17 +960,17 @@ def getEscapedIdentifier():
if ch == 92:
id = id[0:(0 + (len(id) - 1))]
if (ord(source[index]) if index < len(source) else None) != 117:
- throwError(jsdict({
-}), Messages.UnexpectedToken, "ILLEGAL")
+ throwError(jsdict({}), Messages.UnexpectedToken, "ILLEGAL")
index += 1
index
ch = scanHexEscape("u")
- if ((not ch) or (ch == "\\")) or (not isIdentifierPart((ord(ch[0]) if 0 < len(ch) else None))):
- throwError(jsdict({
-}), Messages.UnexpectedToken, "ILLEGAL")
+ if ((not ch) or (ch == "\\")) or (not isIdentifierPart(
+ (ord(ch[0]) if 0 < len(ch) else None))):
+ throwError(jsdict({}), Messages.UnexpectedToken, "ILLEGAL")
id += ch
return id
+
def getIdentifier():
global index
start = None
@@ -828,12 +989,15 @@ def getIdentifier():
break
return source[start:index]
+
def scanIdentifier():
start = None
id = None
type = None
start = index
- id = (getEscapedIdentifier() if (ord(source[index]) if index < len(source) else None) == 92 else getIdentifier())
+ id = (getEscapedIdentifier() if
+ (ord(source[index]) if index < len(source) else None) == 92 else
+ getIdentifier())
if len(id) == 1:
type = Token.Identifier
elif isKeyword(id):
@@ -845,12 +1009,13 @@ def scanIdentifier():
else:
type = Token.Identifier
return jsdict({
-"type": type,
-"value": id,
-"lineNumber": lineNumber,
-"lineStart": lineStart,
-"range": [start, index],
-})
+ "type": type,
+ "value": id,
+ "lineNumber": lineNumber,
+ "lineStart": lineStart,
+ "range": [start, index],
+ })
+
def scanPunctuator():
global index
@@ -862,7 +1027,16 @@ def scanPunctuator():
ch3 = None
ch4 = None
while 1:
- if (code == 126) or ((code == 63) or ((code == 58) or ((code == 93) or ((code == 91) or ((code == 125) or ((code == 123) or ((code == 44) or ((code == 59) or ((code == 41) or ((code == 40) or (code == 46))))))))))):
+ if (code == 126) or ((code == 63) or ((code == 58) or
+ ((code == 93) or
+ ((code == 91) or
+ ((code == 125) or
+ ((code == 123) or
+ ((code == 44) or
+ ((code == 59) or
+ ((code == 41) or
+ ((code == 40) or
+ (code == 46))))))))))):
index += 1
index
if extra.tokenize:
@@ -871,37 +1045,47 @@ def scanPunctuator():
elif code == 123:
extra.openCurlyToken = len(extra.tokens)
return jsdict({
-"type": Token.Punctuator,
-"value": unichr(code),
-"lineNumber": lineNumber,
-"lineStart": lineStart,
-"range": [start, index],
-})
+ "type": Token.Punctuator,
+ "value": unichr(code),
+ "lineNumber": lineNumber,
+ "lineStart": lineStart,
+ "range": [start, index],
+ })
else:
- code2 = (ord(source[index + 1]) if (index + 1) < len(source) else None)
+ code2 = (ord(source[index + 1]) if
+ (index + 1) < len(source) else None)
if code2 == 61:
while 1:
- if (code == 124) or ((code == 94) or ((code == 62) or ((code == 60) or ((code == 47) or ((code == 45) or ((code == 43) or ((code == 42) or ((code == 38) or (code == 37))))))))):
+ if (code == 124) or ((code == 94) or
+ ((code == 62) or
+ ((code == 60) or
+ ((code == 47) or
+ ((code == 45) or
+ ((code == 43) or
+ ((code == 42) or
+ ((code == 38) or
+ (code == 37))))))))):
index += 2
return jsdict({
-"type": Token.Punctuator,
-"value": unichr(code) + unichr(code2),
-"lineNumber": lineNumber,
-"lineStart": lineStart,
-"range": [start, index],
-})
+ "type": Token.Punctuator,
+ "value": unichr(code) + unichr(code2),
+ "lineNumber": lineNumber,
+ "lineStart": lineStart,
+ "range": [start, index],
+ })
elif (code == 61) or (code == 33):
index += 2
- if (ord(source[index]) if index < len(source) else None) == 61:
+ if (ord(source[index])
+ if index < len(source) else None) == 61:
index += 1
index
return jsdict({
-"type": Token.Punctuator,
-"value": source[start:index],
-"lineNumber": lineNumber,
-"lineStart": lineStart,
-"range": [start, index],
-})
+ "type": Token.Punctuator,
+ "value": source[start:index],
+ "lineNumber": lineNumber,
+ "lineStart": lineStart,
+ "range": [start, index],
+ })
else:
break
break
@@ -914,60 +1098,60 @@ def scanPunctuator():
if ch4 == "=":
index += 4
return jsdict({
-"type": Token.Punctuator,
-"value": ">>>=",
-"lineNumber": lineNumber,
-"lineStart": lineStart,
-"range": [start, index],
-})
+ "type": Token.Punctuator,
+ "value": ">>>=",
+ "lineNumber": lineNumber,
+ "lineStart": lineStart,
+ "range": [start, index],
+ })
if ((ch1 == ">") and (ch2 == ">")) and (ch3 == ">"):
index += 3
return jsdict({
-"type": Token.Punctuator,
-"value": ">>>",
-"lineNumber": lineNumber,
-"lineStart": lineStart,
-"range": [start, index],
-})
+ "type": Token.Punctuator,
+ "value": ">>>",
+ "lineNumber": lineNumber,
+ "lineStart": lineStart,
+ "range": [start, index],
+ })
if ((ch1 == "<") and (ch2 == "<")) and (ch3 == "="):
index += 3
return jsdict({
-"type": Token.Punctuator,
-"value": "<<=",
-"lineNumber": lineNumber,
-"lineStart": lineStart,
-"range": [start, index],
-})
+ "type": Token.Punctuator,
+ "value": "<<=",
+ "lineNumber": lineNumber,
+ "lineStart": lineStart,
+ "range": [start, index],
+ })
if ((ch1 == ">") and (ch2 == ">")) and (ch3 == "="):
index += 3
return jsdict({
-"type": Token.Punctuator,
-"value": ">>=",
-"lineNumber": lineNumber,
-"lineStart": lineStart,
-"range": [start, index],
-})
+ "type": Token.Punctuator,
+ "value": ">>=",
+ "lineNumber": lineNumber,
+ "lineStart": lineStart,
+ "range": [start, index],
+ })
if (ch1 == ch2) and ("+-<>&|".find(ch1) >= 0):
index += 2
return jsdict({
-"type": Token.Punctuator,
-"value": ch1 + ch2,
-"lineNumber": lineNumber,
-"lineStart": lineStart,
-"range": [start, index],
-})
+ "type": Token.Punctuator,
+ "value": ch1 + ch2,
+ "lineNumber": lineNumber,
+ "lineStart": lineStart,
+ "range": [start, index],
+ })
if "<>=!+-*%&|^/".find(ch1) >= 0:
index += 1
index
return jsdict({
-"type": Token.Punctuator,
-"value": ch1,
-"lineNumber": lineNumber,
-"lineStart": lineStart,
-"range": [start, index],
-})
- throwError(jsdict({
-}), Messages.UnexpectedToken, "ILLEGAL")
+ "type": Token.Punctuator,
+ "value": ch1,
+ "lineNumber": lineNumber,
+ "lineStart": lineStart,
+ "range": [start, index],
+ })
+ throwError(jsdict({}), Messages.UnexpectedToken, "ILLEGAL")
+
def scanHexLiteral(start=None):
global index
@@ -978,18 +1162,18 @@ def scanHexLiteral(start=None):
index += 1
number += source[index - 1]
if len(number) == 0:
- throwError(jsdict({
-}), Messages.UnexpectedToken, "ILLEGAL")
- if isIdentifierStart((ord(source[index]) if index < len(source) else None)):
- throwError(jsdict({
-}), Messages.UnexpectedToken, "ILLEGAL")
+ throwError(jsdict({}), Messages.UnexpectedToken, "ILLEGAL")
+ if isIdentifierStart(
+ (ord(source[index]) if index < len(source) else None)):
+ throwError(jsdict({}), Messages.UnexpectedToken, "ILLEGAL")
return jsdict({
-"type": Token.NumericLiteral,
-"value": parseInt("0x" + number, 16),
-"lineNumber": lineNumber,
-"lineStart": lineStart,
-"range": [start, index],
-})
+ "type": Token.NumericLiteral,
+ "value": parseInt("0x" + number, 16),
+ "lineNumber": lineNumber,
+ "lineStart": lineStart,
+ "range": [start, index],
+ })
+
def scanOctalLiteral(start=None):
global index
@@ -1000,17 +1184,20 @@ def scanOctalLiteral(start=None):
break
index += 1
number += source[index - 1]
- if isIdentifierStart((ord(source[index]) if index < len(source) else None)) or isDecimalDigit((ord(source[index]) if index < len(source) else None)):
- throwError(jsdict({
-}), Messages.UnexpectedToken, "ILLEGAL")
+ if isIdentifierStart(
+ (ord(source[index])
+ if index < len(source) else None)) or isDecimalDigit(
+ (ord(source[index]) if index < len(source) else None)):
+ throwError(jsdict({}), Messages.UnexpectedToken, "ILLEGAL")
return jsdict({
-"type": Token.NumericLiteral,
-"value": parseInt(number, 8),
-"octal": True,
-"lineNumber": lineNumber,
-"lineStart": lineStart,
-"range": [start, index],
-})
+ "type": Token.NumericLiteral,
+ "value": parseInt(number, 8),
+ "octal": True,
+ "lineNumber": lineNumber,
+ "lineStart": lineStart,
+ "range": [start, index],
+ })
+
def scanNumericLiteral():
global index
@@ -1018,7 +1205,9 @@ def scanNumericLiteral():
start = None
ch = None
ch = source[index]
- assert__py__(isDecimalDigit((ord(ch[0]) if 0 < len(ch) else None)) or (ch == "."), "Numeric literal must start with a decimal digit or a decimal point")
+ assert__py__(
+ isDecimalDigit((ord(ch[0]) if 0 < len(ch) else None)) or (ch == "."),
+ "Numeric literal must start with a decimal digit or a decimal point")
start = index
number = ""
if ch != ".":
@@ -1033,16 +1222,17 @@ def scanNumericLiteral():
if isOctalDigit(ch):
return scanOctalLiteral(start)
if ch and isDecimalDigit((ord(ch[0]) if 0 < len(ch) else None)):
- throwError(jsdict({
-}), Messages.UnexpectedToken, "ILLEGAL")
- while isDecimalDigit((ord(source[index]) if index < len(source) else None)):
+ throwError(jsdict({}), Messages.UnexpectedToken, "ILLEGAL")
+ while isDecimalDigit(
+ (ord(source[index]) if index < len(source) else None)):
index += 1
number += source[index - 1]
ch = source[index] if index < len(source) else None
if ch == ".":
index += 1
number += source[index - 1]
- while isDecimalDigit((ord(source[index]) if index < len(source) else None)):
+ while isDecimalDigit(
+ (ord(source[index]) if index < len(source) else None)):
index += 1
number += source[index - 1]
ch = source[index]
@@ -1053,23 +1243,25 @@ def scanNumericLiteral():
if (ch == "+") or (ch == "-"):
index += 1
number += source[index - 1]
- if isDecimalDigit((ord(source[index]) if index < len(source) else None)):
- while isDecimalDigit((ord(source[index]) if index < len(source) else None)):
+ if isDecimalDigit(
+ (ord(source[index]) if index < len(source) else None)):
+ while isDecimalDigit(
+ (ord(source[index]) if index < len(source) else None)):
index += 1
number += source[index - 1]
else:
- throwError(jsdict({
-}), Messages.UnexpectedToken, "ILLEGAL")
- if isIdentifierStart((ord(source[index]) if index < len(source) else None)):
- throwError(jsdict({
-}), Messages.UnexpectedToken, "ILLEGAL")
+ throwError(jsdict({}), Messages.UnexpectedToken, "ILLEGAL")
+ if isIdentifierStart(
+ (ord(source[index]) if index < len(source) else None)):
+ throwError(jsdict({}), Messages.UnexpectedToken, "ILLEGAL")
return jsdict({
-"type": Token.NumericLiteral,
-"value": parseFloat(number),
-"lineNumber": lineNumber,
-"lineStart": lineStart,
-"range": [start, index],
-})
+ "type": Token.NumericLiteral,
+ "value": parseFloat(number),
+ "lineNumber": lineNumber,
+ "lineStart": lineStart,
+ "range": [start, index],
+ })
+
def scanStringLiteral():
global index, lineNumber
@@ -1082,7 +1274,8 @@ def scanStringLiteral():
restore = None
octal = False
quote = source[index]
- assert__py__((quote == "'") or (quote == "\""), "String literal must starts with a quote")
+ assert__py__((quote == "'") or (quote == "\""),
+ "String literal must starts with a quote")
start = index
index += 1
index
@@ -1095,7 +1288,8 @@ def scanStringLiteral():
elif ch == "\\":
index += 1
ch = source[index - 1]
- if (not ch) or (not isLineTerminator((ord(ch[0]) if 0 < len(ch) else None))):
+ if (not ch) or (not isLineTerminator(
+ (ord(ch[0]) if 0 < len(ch) else None))):
while 1:
if ch == "n":
str += u"\x0a"
@@ -1129,13 +1323,18 @@ def scanStringLiteral():
code = "01234567".find(ch)
if code != 0:
octal = True
- if (index < length) and isOctalDigit(source[index]):
+ if (index < length) and isOctalDigit(
+ source[index]):
octal = True
index += 1
- code = (code * 8) + "01234567".find(source[index - 1])
- if (("0123".find(ch) >= 0) and (index < length)) and isOctalDigit(source[index]):
+ code = (code * 8) + "01234567".find(
+ source[index - 1])
+ if (("0123".find(ch) >= 0) and
+ (index < length)) and isOctalDigit(
+ source[index]):
index += 1
- code = (code * 8) + "01234567".find(source[index - 1])
+ code = (code * 8) + "01234567".find(
+ source[index - 1])
str += unichr(code)
else:
str += ch
@@ -1152,16 +1351,16 @@ def scanStringLiteral():
else:
str += ch
if quote != "":
- throwError(jsdict({
-}), Messages.UnexpectedToken, "ILLEGAL")
+ throwError(jsdict({}), Messages.UnexpectedToken, "ILLEGAL")
return jsdict({
-"type": Token.StringLiteral,
-"value": str,
-"octal": octal,
-"lineNumber": lineNumber,
-"lineStart": lineStart,
-"range": [start, index],
-})
+ "type": Token.StringLiteral,
+ "value": str,
+ "octal": octal,
+ "lineNumber": lineNumber,
+ "lineStart": lineStart,
+ "range": [start, index],
+ })
+
def scanRegExp():
global lookahead, index
@@ -1178,7 +1377,8 @@ def scanRegExp():
skipComment()
start = index
ch = source[index]
- assert__py__(ch == "/", "Regular expression literal must start with a slash")
+ assert__py__(ch == "/",
+ "Regular expression literal must start with a slash")
index += 1
str = source[index - 1]
while index < length:
@@ -1193,8 +1393,7 @@ def scanRegExp():
index += 1
ch = source[index - 1]
if isLineTerminator((ord(ch[0]) if 0 < len(ch) else None)):
- throwError(jsdict({
-}), Messages.UnterminatedRegExp)
+ throwError(jsdict({}), Messages.UnterminatedRegExp)
str += ch
elif ch == "/":
terminated = True
@@ -1202,11 +1401,9 @@ def scanRegExp():
elif ch == "[":
classMarker = True
elif isLineTerminator((ord(ch[0]) if 0 < len(ch) else None)):
- throwError(jsdict({
-}), Messages.UnterminatedRegExp)
+ throwError(jsdict({}), Messages.UnterminatedRegExp)
if not terminated:
- throwError(jsdict({
-}), Messages.UnterminatedRegExp)
+ throwError(jsdict({}), Messages.UnterminatedRegExp)
pattern = str[1:(1 + (len(str) - 2))]
flags = ""
while index < length:
@@ -1242,25 +1439,29 @@ def scanRegExp():
try:
value = RegExp(pattern, flags)
except Exception as e:
- throwError(jsdict({
-}), Messages.InvalidRegExp)
+ throwError(jsdict({}), Messages.InvalidRegExp)
peek()
if extra.tokenize:
return jsdict({
-"type": Token.RegularExpression,
-"value": value,
-"lineNumber": lineNumber,
-"lineStart": lineStart,
-"range": [start, index],
-})
+ "type": Token.RegularExpression,
+ "value": value,
+ "lineNumber": lineNumber,
+ "lineStart": lineStart,
+ "range": [start, index],
+ })
return jsdict({
-"literal": str,
-"value": value,
-"range": [start, index],
-})
+ "literal": str,
+ "value": value,
+ "range": [start, index],
+ })
+
def isIdentifierName(token=None):
- return (((token.type == Token.Identifier) or (token.type == Token.Keyword)) or (token.type == Token.BooleanLiteral)) or (token.type == Token.NullLiteral)
+ return (((token.type == Token.Identifier) or
+ (token.type == Token.Keyword)) or
+ (token.type == Token.BooleanLiteral)) or (
+ token.type == Token.NullLiteral)
+
def advanceSlash():
prevToken = None
@@ -1271,15 +1472,20 @@ def advanceSlash():
if prevToken.type == "Punctuator":
if prevToken.value == ")":
checkToken = extra.tokens[extra.openParenToken - 1]
- if (checkToken and (checkToken.type == "Keyword")) and ((((checkToken.value == "if") or (checkToken.value == "while")) or (checkToken.value == "for")) or (checkToken.value == "with")):
+ if (checkToken and (checkToken.type == "Keyword")) and (
+ (((checkToken.value == "if") or
+ (checkToken.value == "while")) or
+ (checkToken.value == "for")) or (checkToken.value == "with")):
return scanRegExp()
return scanPunctuator()
if prevToken.value == "}":
- if extra.tokens[extra.openCurlyToken - 3] and (extra.tokens[extra.openCurlyToken - 3].type == "Keyword"):
+ if extra.tokens[extra.openCurlyToken - 3] and (
+ extra.tokens[extra.openCurlyToken - 3].type == "Keyword"):
checkToken = extra.tokens[extra.openCurlyToken - 4]
if not checkToken:
return scanPunctuator()
- elif extra.tokens[extra.openCurlyToken - 4] and (extra.tokens[extra.openCurlyToken - 4].type == "Keyword"):
+ elif extra.tokens[extra.openCurlyToken - 4] and (
+ extra.tokens[extra.openCurlyToken - 4].type == "Keyword"):
checkToken = extra.tokens[extra.openCurlyToken - 5]
if not checkToken:
return scanRegExp()
@@ -1293,16 +1499,17 @@ def advanceSlash():
return scanRegExp()
return scanPunctuator()
+
def advance():
ch = None
skipComment()
if index >= length:
return jsdict({
-"type": Token.EOF,
-"lineNumber": lineNumber,
-"lineStart": lineStart,
-"range": [index, index],
-})
+ "type": Token.EOF,
+ "lineNumber": lineNumber,
+ "lineStart": lineStart,
+ "range": [index, index],
+ })
ch = (ord(source[index]) if index < len(source) else None)
if ((ch == 40) or (ch == 41)) or (ch == 58):
return scanPunctuator()
@@ -1311,7 +1518,8 @@ def advance():
if isIdentifierStart(ch):
return scanIdentifier()
if ch == 46:
- if isDecimalDigit((ord(source[index + 1]) if (index + 1) < len(source) else None)):
+ if isDecimalDigit((ord(source[index + 1]) if
+ (index + 1) < len(source) else None)):
return scanNumericLiteral()
return scanPunctuator()
if isDecimalDigit(ch):
@@ -1320,6 +1528,7 @@ def advance():
return advanceSlash()
return scanPunctuator()
+
def lex():
global index, lineNumber, lineStart, lookahead
token = None
@@ -1333,6 +1542,7 @@ def lex():
lineStart = token.lineStart
return token
+
def peek():
global lookahead, index, lineNumber, lineStart
pos = None
@@ -1346,52 +1556,55 @@ def peek():
lineNumber = line
lineStart = start
+
SyntaxTreeDelegate = jsdict({
-"name": "SyntaxTree",
-"markStart": __temp__0,
-"markEnd": __temp__1,
-"markEndIf": __temp__2,
-"postProcess": __temp__3,
-"createArrayExpression": __temp__4,
-"createAssignmentExpression": __temp__5,
-"createBinaryExpression": __temp__6,
-"createBlockStatement": __temp__7,
-"createBreakStatement": __temp__8,
-"createCallExpression": __temp__9,
-"createCatchClause": __temp__10,
-"createConditionalExpression": __temp__11,
-"createContinueStatement": __temp__12,
-"createDebuggerStatement": __temp__13,
-"createDoWhileStatement": __temp__14,
-"createEmptyStatement": __temp__15,
-"createExpressionStatement": __temp__16,
-"createForStatement": __temp__17,
-"createForInStatement": __temp__18,
-"createFunctionDeclaration": __temp__19,
-"createFunctionExpression": __temp__20,
-"createIdentifier": __temp__21,
-"createIfStatement": __temp__22,
-"createLabeledStatement": __temp__23,
-"createLiteral": __temp__24,
-"createMemberExpression": __temp__25,
-"createNewExpression": __temp__26,
-"createObjectExpression": __temp__27,
-"createPostfixExpression": __temp__28,
-"createProgram": __temp__29,
-"createProperty": __temp__30,
-"createReturnStatement": __temp__31,
-"createSequenceExpression": __temp__32,
-"createSwitchCase": __temp__33,
-"createSwitchStatement": __temp__34,
-"createThisExpression": __temp__35,
-"createThrowStatement": __temp__36,
-"createTryStatement": __temp__37,
-"createUnaryExpression": __temp__38,
-"createVariableDeclaration": __temp__39,
-"createVariableDeclarator": __temp__40,
-"createWhileStatement": __temp__41,
-"createWithStatement": __temp__42,
+ "name": "SyntaxTree",
+ "markStart": __temp__0,
+ "markEnd": __temp__1,
+ "markEndIf": __temp__2,
+ "postProcess": __temp__3,
+ "createArrayExpression": __temp__4,
+ "createAssignmentExpression": __temp__5,
+ "createBinaryExpression": __temp__6,
+ "createBlockStatement": __temp__7,
+ "createBreakStatement": __temp__8,
+ "createCallExpression": __temp__9,
+ "createCatchClause": __temp__10,
+ "createConditionalExpression": __temp__11,
+ "createContinueStatement": __temp__12,
+ "createDebuggerStatement": __temp__13,
+ "createDoWhileStatement": __temp__14,
+ "createEmptyStatement": __temp__15,
+ "createExpressionStatement": __temp__16,
+ "createForStatement": __temp__17,
+ "createForInStatement": __temp__18,
+ "createFunctionDeclaration": __temp__19,
+ "createFunctionExpression": __temp__20,
+ "createIdentifier": __temp__21,
+ "createIfStatement": __temp__22,
+ "createLabeledStatement": __temp__23,
+ "createLiteral": __temp__24,
+ "createMemberExpression": __temp__25,
+ "createNewExpression": __temp__26,
+ "createObjectExpression": __temp__27,
+ "createPostfixExpression": __temp__28,
+ "createProgram": __temp__29,
+ "createProperty": __temp__30,
+ "createReturnStatement": __temp__31,
+ "createSequenceExpression": __temp__32,
+ "createSwitchCase": __temp__33,
+ "createSwitchStatement": __temp__34,
+ "createThisExpression": __temp__35,
+ "createThrowStatement": __temp__36,
+ "createTryStatement": __temp__37,
+ "createUnaryExpression": __temp__38,
+ "createVariableDeclaration": __temp__39,
+ "createVariableDeclarator": __temp__40,
+ "createWhileStatement": __temp__41,
+ "createWithStatement": __temp__42,
})
+
+
def peekLineTerminator():
global index, lineNumber, lineStart
pos = None
@@ -1408,15 +1621,17 @@ def peekLineTerminator():
lineStart = start
return found
+
def throwError(token=None, messageFormat=None, a=None):
def __temp__43(whole=None, index=None):
assert__py__(index < len(args), "Message reference must be in range")
return args[index]
-
+
error = None
args = Array.prototype.slice.call(arguments, 2)
msg = messageFormat.replace(RegExp(r'%(\d)'), __temp__43)
- if ('undefined' if not ('lineNumber' in token) else typeof(token.lineNumber)) == "number":
+ if ('undefined' if not ('lineNumber' in token) else typeof(
+ token.lineNumber)) == "number":
error = RuntimeError((("Line " + token.lineNumber) + ": ") + msg)
error.index = token.range[0]
error.lineNumber = token.lineNumber
@@ -1429,6 +1644,7 @@ def __temp__43(whole=None, index=None):
error.description = msg
raise error
+
def throwErrorTolerant():
try:
throwError.apply(None, arguments)
@@ -1436,7 +1652,8 @@ def throwErrorTolerant():
if extra.errors:
extra.errors.append(e)
else:
- raise
+ raise
+
def throwUnexpected(token=None):
if token.type == Token.EOF:
@@ -1452,50 +1669,62 @@ def throwUnexpected(token=None):
throwError(token, Messages.UnexpectedReserved)
elif strict and isStrictModeReservedWord(token.value):
throwErrorTolerant(token, Messages.StrictReservedWord)
- return
+ return
throwError(token, Messages.UnexpectedToken, token.value)
throwError(token, Messages.UnexpectedToken, token.value)
+
def expect(value=None):
token = lex()
if (token.type != Token.Punctuator) or (token.value != value):
throwUnexpected(token)
+
def expectKeyword(keyword=None):
token = lex()
if (token.type != Token.Keyword) or (token.value != keyword):
throwUnexpected(token)
+
def match(value=None):
return (lookahead.type == Token.Punctuator) and (lookahead.value == value)
+
def matchKeyword(keyword=None):
return (lookahead.type == Token.Keyword) and (lookahead.value == keyword)
+
def matchAssign():
op = None
if lookahead.type != Token.Punctuator:
return False
op = lookahead.value
- return (((((((((((op == "=") or (op == "*=")) or (op == "/=")) or (op == "%=")) or (op == "+=")) or (op == "-=")) or (op == "<<=")) or (op == ">>=")) or (op == ">>>=")) or (op == "&=")) or (op == "^=")) or (op == "|=")
+ return (((((((((((op == "=") or (op == "*=")) or (op == "/=")) or
+ (op == "%=")) or (op == "+=")) or (op == "-=")) or
+ (op == "<<=")) or (op == ">>=")) or (op == ">>>=")) or
+ (op == "&=")) or (op == "^=")) or (op == "|=")
+
def consumeSemicolon():
line = None
if (ord(source[index]) if index < len(source) else None) == 59:
lex()
- return
+ return
line = lineNumber
skipComment()
if lineNumber != line:
- return
+ return
if match(";"):
lex()
- return
+ return
if (lookahead.type != Token.EOF) and (not match("}")):
throwUnexpected(lookahead)
+
def isLeftHandSide(expr=None):
- return (expr.type == Syntax.Identifier) or (expr.type == Syntax.MemberExpression)
+ return (expr.type == Syntax.Identifier) or (
+ expr.type == Syntax.MemberExpression)
+
def parseArrayInitialiser():
elements = []
@@ -1511,6 +1740,7 @@ def parseArrayInitialiser():
expect("]")
return delegate.createArrayExpression(elements)
+
def parsePropertyFunction(param=None, first=None):
global strict
previousStrict = None
@@ -1522,19 +1752,23 @@ def parsePropertyFunction(param=None, first=None):
if (first and strict) and isRestrictedWord(param[0].name):
throwErrorTolerant(first, Messages.StrictParamName)
strict = previousStrict
- return delegate.markEnd(delegate.createFunctionExpression(None, param, [], body))
+ return delegate.markEnd(
+ delegate.createFunctionExpression(None, param, [], body))
+
def parseObjectPropertyKey():
token = None
skipComment()
delegate.markStart()
token = lex()
- if (token.type == Token.StringLiteral) or (token.type == Token.NumericLiteral):
+ if (token.type == Token.StringLiteral) or (
+ token.type == Token.NumericLiteral):
if strict and token.octal:
throwErrorTolerant(token, Messages.StrictOctalLiteral)
return delegate.markEnd(delegate.createLiteral(token))
return delegate.markEnd(delegate.createIdentifier(token.value))
+
def parseObjectProperty():
token = None
key = None
@@ -1558,7 +1792,8 @@ def parseObjectProperty():
token = lookahead
if token.type != Token.Identifier:
expect(")")
- throwErrorTolerant(token, Messages.UnexpectedToken, token.value)
+ throwErrorTolerant(token, Messages.UnexpectedToken,
+ token.value)
value = parsePropertyFunction([])
else:
param = [parseVariableIdentifier()]
@@ -1576,14 +1811,14 @@ def parseObjectProperty():
value = parseAssignmentExpression()
return delegate.markEnd(delegate.createProperty("init", key, value))
+
def parseObjectInitialiser():
properties = []
property = None
name = None
key = None
kind = None
- map = jsdict({
-})
+ map = jsdict({})
toString = str
expect("{")
while not match("}"):
@@ -1592,23 +1827,23 @@ def parseObjectInitialiser():
name = property.key.name
else:
name = toString(property.key.value)
- kind = (PropertyKind.Data if property.kind == "init" else (PropertyKind.Get if property.kind == "get" else PropertyKind.Set))
+ kind = (PropertyKind.Data if property.kind == "init" else (
+ PropertyKind.Get if property.kind == "get" else PropertyKind.Set))
key = "$" + name
if key in map:
if map[key] == PropertyKind.Data:
if strict and (kind == PropertyKind.Data):
- throwErrorTolerant(jsdict({
-}), Messages.StrictDuplicateProperty)
+ throwErrorTolerant(
+ jsdict({}), Messages.StrictDuplicateProperty)
elif kind != PropertyKind.Data:
- throwErrorTolerant(jsdict({
-}), Messages.AccessorDataProperty)
+ throwErrorTolerant(
+ jsdict({}), Messages.AccessorDataProperty)
else:
if kind == PropertyKind.Data:
- throwErrorTolerant(jsdict({
-}), Messages.AccessorDataProperty)
+ throwErrorTolerant(
+ jsdict({}), Messages.AccessorDataProperty)
elif map[key] & kind:
- throwErrorTolerant(jsdict({
-}), Messages.AccessorGetSet)
+ throwErrorTolerant(jsdict({}), Messages.AccessorGetSet)
map[key] |= kind
else:
map[key] = kind
@@ -1618,6 +1853,7 @@ def parseObjectInitialiser():
expect("}")
return delegate.createObjectExpression(properties)
+
def parseGroupExpression():
expr = None
expect("(")
@@ -1625,6 +1861,7 @@ def parseGroupExpression():
expect(")")
return expr
+
def parsePrimaryExpression():
type = None
token = None
@@ -1663,6 +1900,7 @@ def parsePrimaryExpression():
return delegate.markEnd(expr)
throwUnexpected(lex())
+
def parseArguments():
args = []
expect("(")
@@ -1675,6 +1913,7 @@ def parseArguments():
expect(")")
return args
+
def parseNonComputedProperty():
token = None
delegate.markStart()
@@ -1683,10 +1922,12 @@ def parseNonComputedProperty():
throwUnexpected(token)
return delegate.markEnd(delegate.createIdentifier(token.value))
+
def parseNonComputedMember():
expect(".")
return parseNonComputedProperty()
+
def parseComputedMember():
expr = None
expect("[")
@@ -1694,6 +1935,7 @@ def parseComputedMember():
expect("]")
return expr
+
def parseNewExpression():
callee = None
args = None
@@ -1703,13 +1945,15 @@ def parseNewExpression():
args = (parseArguments() if match("(") else [])
return delegate.markEnd(delegate.createNewExpression(callee, args))
+
def parseLeftHandSideExpressionAllowCall():
marker = None
expr = None
args = None
property = None
marker = createLocationMarker()
- expr = (parseNewExpression() if matchKeyword("new") else parsePrimaryExpression())
+ expr = (parseNewExpression()
+ if matchKeyword("new") else parsePrimaryExpression())
while (match(".") or match("[")) or match("("):
if match("("):
args = parseArguments()
@@ -1725,12 +1969,14 @@ def parseLeftHandSideExpressionAllowCall():
marker.apply(expr)
return expr
+
def parseLeftHandSideExpression():
marker = None
expr = None
property = None
marker = createLocationMarker()
- expr = (parseNewExpression() if matchKeyword("new") else parsePrimaryExpression())
+ expr = (parseNewExpression()
+ if matchKeyword("new") else parsePrimaryExpression())
while match(".") or match("["):
if match("["):
property = parseComputedMember()
@@ -1743,6 +1989,7 @@ def parseLeftHandSideExpression():
marker.apply(expr)
return expr
+
def parsePostfixExpression():
expr = None
token = None
@@ -1750,47 +1997,50 @@ def parsePostfixExpression():
expr = parseLeftHandSideExpressionAllowCall()
if lookahead.type == Token.Punctuator:
if (match("++") or match("--")) and (not peekLineTerminator()):
- if (strict and (expr.type == Syntax.Identifier)) and isRestrictedWord(expr.name):
- throwErrorTolerant(jsdict({
-}), Messages.StrictLHSPostfix)
+ if (strict and
+ (expr.type == Syntax.Identifier)) and isRestrictedWord(
+ expr.name):
+ throwErrorTolerant(jsdict({}), Messages.StrictLHSPostfix)
if not isLeftHandSide(expr):
- throwError(jsdict({
-}), Messages.InvalidLHSInAssignment)
+ throwError(jsdict({}), Messages.InvalidLHSInAssignment)
token = lex()
expr = delegate.createPostfixExpression(token.value, expr)
return delegate.markEndIf(expr)
+
def parseUnaryExpression():
token = None
expr = None
delegate.markStart()
- if (lookahead.type != Token.Punctuator) and (lookahead.type != Token.Keyword):
+ if (lookahead.type != Token.Punctuator) and (lookahead.type !=
+ Token.Keyword):
expr = parsePostfixExpression()
elif match("++") or match("--"):
token = lex()
expr = parseUnaryExpression()
- if (strict and (expr.type == Syntax.Identifier)) and isRestrictedWord(expr.name):
- throwErrorTolerant(jsdict({
-}), Messages.StrictLHSPrefix)
+ if (strict and
+ (expr.type == Syntax.Identifier)) and isRestrictedWord(expr.name):
+ throwErrorTolerant(jsdict({}), Messages.StrictLHSPrefix)
if not isLeftHandSide(expr):
- throwError(jsdict({
-}), Messages.InvalidLHSInAssignment)
+ throwError(jsdict({}), Messages.InvalidLHSInAssignment)
expr = delegate.createUnaryExpression(token.value, expr)
elif ((match("+") or match("-")) or match("~")) or match("!"):
token = lex()
expr = parseUnaryExpression()
expr = delegate.createUnaryExpression(token.value, expr)
- elif (matchKeyword("delete") or matchKeyword("void")) or matchKeyword("typeof"):
+ elif (matchKeyword("delete")
+ or matchKeyword("void")) or matchKeyword("typeof"):
token = lex()
expr = parseUnaryExpression()
expr = delegate.createUnaryExpression(token.value, expr)
- if (strict and (expr.operator == "delete")) and (expr.argument.type == Syntax.Identifier):
- throwErrorTolerant(jsdict({
-}), Messages.StrictDelete)
+ if (strict and (expr.operator == "delete")) and (
+ expr.argument.type == Syntax.Identifier):
+ throwErrorTolerant(jsdict({}), Messages.StrictDelete)
else:
expr = parsePostfixExpression()
return delegate.markEndIf(expr)
+
def binaryPrecedence(token=None, allowIn=None):
prec = 0
if (token.type != Token.Punctuator) and (token.type != Token.Keyword):
@@ -1811,22 +2061,29 @@ def binaryPrecedence(token=None, allowIn=None):
elif token.value == "&":
prec = 5
break
- elif (token.value == "!==") or ((token.value == "===") or ((token.value == "!=") or (token.value == "=="))):
+ elif (token.value == "!==") or ((token.value == "===") or
+ ((token.value == "!=") or
+ (token.value == "=="))):
prec = 6
break
- elif (token.value == "instanceof") or ((token.value == ">=") or ((token.value == "<=") or ((token.value == ">") or (token.value == "<")))):
+ elif (token.value == "instanceof") or ((token.value == ">=") or
+ ((token.value == "<=") or
+ ((token.value == ">") or
+ (token.value == "<")))):
prec = 7
break
elif token.value == "in":
prec = (7 if allowIn else 0)
break
- elif (token.value == ">>>") or ((token.value == ">>") or (token.value == "<<")):
+ elif (token.value == ">>>") or ((token.value == ">>") or
+ (token.value == "<<")):
prec = 8
break
elif (token.value == "-") or (token.value == "+"):
prec = 9
break
- elif (token.value == "%") or ((token.value == "/") or (token.value == "*")):
+ elif (token.value == "%") or ((token.value == "/") or
+ (token.value == "*")):
prec = 11
break
else:
@@ -1834,6 +2091,7 @@ def binaryPrecedence(token=None, allowIn=None):
break
return prec
+
def parseBinaryExpression():
marker = None
markers = None
@@ -1885,7 +2143,8 @@ def parseBinaryExpression():
expr = stack[i]
markers.pop()
while i > 1:
- expr = delegate.createBinaryExpression(stack[i - 1].value, stack[i - 2], expr)
+ expr = delegate.createBinaryExpression(stack[i - 1].value,
+ stack[i - 2], expr)
i -= 2
marker = markers.pop()
if marker:
@@ -1893,6 +2152,7 @@ def parseBinaryExpression():
marker.apply(expr)
return expr
+
def parseConditionalExpression():
expr = None
previousAllowIn = None
@@ -1908,12 +2168,13 @@ def parseConditionalExpression():
state.allowIn = previousAllowIn
expect(":")
alternate = parseAssignmentExpression()
- expr = delegate.markEnd(delegate.createConditionalExpression(expr, consequent, alternate))
+ expr = delegate.markEnd(
+ delegate.createConditionalExpression(expr, consequent, alternate))
else:
- delegate.markEnd(jsdict({
-}))
+ delegate.markEnd(jsdict({}))
return expr
+
def parseAssignmentExpression():
token = None
left = None
@@ -1925,15 +2186,16 @@ def parseAssignmentExpression():
node = left
if matchAssign():
if not isLeftHandSide(left):
- throwError(jsdict({
-}), Messages.InvalidLHSInAssignment)
- if (strict and (left.type == Syntax.Identifier)) and isRestrictedWord(left.name):
+ throwError(jsdict({}), Messages.InvalidLHSInAssignment)
+ if (strict and
+ (left.type == Syntax.Identifier)) and isRestrictedWord(left.name):
throwErrorTolerant(token, Messages.StrictLHSAssignment)
token = lex()
right = parseAssignmentExpression()
node = delegate.createAssignmentExpression(token.value, left, right)
return delegate.markEndIf(node)
+
def parseExpression():
expr = None
delegate.markStart()
@@ -1947,6 +2209,7 @@ def parseExpression():
expr.expressions.append(parseAssignmentExpression())
return delegate.markEndIf(expr)
+
def parseStatementList():
list__py__ = []
statement = None
@@ -1954,11 +2217,13 @@ def parseStatementList():
if match("}"):
break
statement = parseSourceElement()
- if ('undefined' if not 'statement' in locals() else typeof(statement)) == "undefined":
+ if ('undefined' if not 'statement' in locals() else
+ typeof(statement)) == "undefined":
break
list__py__.append(statement)
return list__py__
+
def parseBlock():
block = None
skipComment()
@@ -1968,6 +2233,7 @@ def parseBlock():
expect("}")
return delegate.markEnd(delegate.createBlockStatement(block))
+
def parseVariableIdentifier():
token = None
skipComment()
@@ -1977,6 +2243,7 @@ def parseVariableIdentifier():
throwUnexpected(token)
return delegate.markEnd(delegate.createIdentifier(token.value))
+
def parseVariableDeclaration(kind=None):
init = None
id = None
@@ -1984,8 +2251,7 @@ def parseVariableDeclaration(kind=None):
delegate.markStart()
id = parseVariableIdentifier()
if strict and isRestrictedWord(id.name):
- throwErrorTolerant(jsdict({
-}), Messages.StrictVarName)
+ throwErrorTolerant(jsdict({}), Messages.StrictVarName)
if kind == "const":
expect("=")
init = parseAssignmentExpression()
@@ -1994,6 +2260,7 @@ def parseVariableDeclaration(kind=None):
init = parseAssignmentExpression()
return delegate.markEnd(delegate.createVariableDeclarator(id, init))
+
def parseVariableDeclarationList(kind=None):
list__py__ = []
while 1:
@@ -2005,6 +2272,7 @@ def parseVariableDeclarationList(kind=None):
break
return list__py__
+
def parseVariableStatement():
declarations = None
expectKeyword("var")
@@ -2012,6 +2280,7 @@ def parseVariableStatement():
consumeSemicolon()
return delegate.createVariableDeclaration(declarations, "var")
+
def parseConstLetDeclaration(kind=None):
declarations = None
skipComment()
@@ -2019,17 +2288,21 @@ def parseConstLetDeclaration(kind=None):
expectKeyword(kind)
declarations = parseVariableDeclarationList(kind)
consumeSemicolon()
- return delegate.markEnd(delegate.createVariableDeclaration(declarations, kind))
+ return delegate.markEnd(
+ delegate.createVariableDeclaration(declarations, kind))
+
def parseEmptyStatement():
expect(";")
return delegate.createEmptyStatement()
+
def parseExpressionStatement():
expr = parseExpression()
consumeSemicolon()
return delegate.createExpressionStatement(expr)
+
def parseIfStatement():
test = None
consequent = None
@@ -2046,6 +2319,7 @@ def parseIfStatement():
alternate = None
return delegate.createIfStatement(test, consequent, alternate)
+
def parseDoWhileStatement():
body = None
test = None
@@ -2063,6 +2337,7 @@ def parseDoWhileStatement():
lex()
return delegate.createDoWhileStatement(body, test)
+
def parseWhileStatement():
test = None
body = None
@@ -2077,13 +2352,16 @@ def parseWhileStatement():
state.inIteration = oldInIteration
return delegate.createWhileStatement(test, body)
+
def parseForVariableDeclaration():
token = None
declarations = None
delegate.markStart()
token = lex()
declarations = parseVariableDeclarationList()
- return delegate.markEnd(delegate.createVariableDeclaration(declarations, token.value))
+ return delegate.markEnd(
+ delegate.createVariableDeclaration(declarations, token.value))
+
def parseForStatement():
init = None
@@ -2116,15 +2394,16 @@ def parseForStatement():
state.allowIn = True
if matchKeyword("in"):
if not isLeftHandSide(init):
- throwError(jsdict({
-}), Messages.InvalidLHSInForIn)
+ throwError(jsdict({}), Messages.InvalidLHSInForIn)
lex()
left = init
right = parseExpression()
init = None
- if ('undefined' if not 'left' in locals() else typeof(left)) == "undefined":
+ if ('undefined'
+ if not 'left' in locals() else typeof(left)) == "undefined":
expect(";")
- if ('undefined' if not 'left' in locals() else typeof(left)) == "undefined":
+ if ('undefined'
+ if not 'left' in locals() else typeof(left)) == "undefined":
if not match(";"):
test = parseExpression()
expect(";")
@@ -2135,7 +2414,10 @@ def parseForStatement():
state.inIteration = True
body = parseStatement()
state.inIteration = oldInIteration
- return (delegate.createForStatement(init, test, update, body) if ('undefined' if not 'left' in locals() else typeof(left)) == "undefined" else delegate.createForInStatement(left, right, body))
+ return (delegate.createForStatement(init, test, update, body) if (
+ 'undefined' if not 'left' in locals() else typeof(left)) == "undefined"
+ else delegate.createForInStatement(left, right, body))
+
def parseContinueStatement():
label = None
@@ -2144,26 +2426,23 @@ def parseContinueStatement():
if (ord(source[index]) if index < len(source) else None) == 59:
lex()
if not state.inIteration:
- throwError(jsdict({
-}), Messages.IllegalContinue)
+ throwError(jsdict({}), Messages.IllegalContinue)
return delegate.createContinueStatement(None)
if peekLineTerminator():
if not state.inIteration:
- throwError(jsdict({
-}), Messages.IllegalContinue)
+ throwError(jsdict({}), Messages.IllegalContinue)
return delegate.createContinueStatement(None)
if lookahead.type == Token.Identifier:
label = parseVariableIdentifier()
key = "$" + label.name
if not (key in state.labelSet):
- throwError(jsdict({
-}), Messages.UnknownLabel, label.name)
+ throwError(jsdict({}), Messages.UnknownLabel, label.name)
consumeSemicolon()
if (label == None) and (not state.inIteration):
- throwError(jsdict({
-}), Messages.IllegalContinue)
+ throwError(jsdict({}), Messages.IllegalContinue)
return delegate.createContinueStatement(label)
+
def parseBreakStatement():
label = None
key = None
@@ -2171,34 +2450,31 @@ def parseBreakStatement():
if (ord(source[index]) if index < len(source) else None) == 59:
lex()
if not (state.inIteration or state.inSwitch):
- throwError(jsdict({
-}), Messages.IllegalBreak)
+ throwError(jsdict({}), Messages.IllegalBreak)
return delegate.createBreakStatement(None)
if peekLineTerminator():
if not (state.inIteration or state.inSwitch):
- throwError(jsdict({
-}), Messages.IllegalBreak)
+ throwError(jsdict({}), Messages.IllegalBreak)
return delegate.createBreakStatement(None)
if lookahead.type == Token.Identifier:
label = parseVariableIdentifier()
key = "$" + label.name
if not (key in state.labelSet):
- throwError(jsdict({
-}), Messages.UnknownLabel, label.name)
+ throwError(jsdict({}), Messages.UnknownLabel, label.name)
consumeSemicolon()
if (label == None) and (not (state.inIteration or state.inSwitch)):
- throwError(jsdict({
-}), Messages.IllegalBreak)
+ throwError(jsdict({}), Messages.IllegalBreak)
return delegate.createBreakStatement(label)
+
def parseReturnStatement():
argument = None
expectKeyword("return")
if not state.inFunctionBody:
- throwErrorTolerant(jsdict({
-}), Messages.IllegalReturn)
+ throwErrorTolerant(jsdict({}), Messages.IllegalReturn)
if (ord(source[index]) if index < len(source) else None) == 32:
- if isIdentifierStart((ord(source[index + 1]) if (index + 1) < len(source) else None)):
+ if isIdentifierStart((ord(source[index + 1]) if
+ (index + 1) < len(source) else None)):
argument = parseExpression()
consumeSemicolon()
return delegate.createReturnStatement(argument)
@@ -2210,12 +2486,12 @@ def parseReturnStatement():
consumeSemicolon()
return delegate.createReturnStatement(argument)
+
def parseWithStatement():
object = None
body = None
if strict:
- throwErrorTolerant(jsdict({
-}), Messages.StrictModeWith)
+ throwErrorTolerant(jsdict({}), Messages.StrictModeWith)
expectKeyword("with")
expect("(")
object = parseExpression()
@@ -2223,6 +2499,7 @@ def parseWithStatement():
body = parseStatement()
return delegate.createWithStatement(object, body)
+
def parseSwitchCase():
test = None
consequent = []
@@ -2243,6 +2520,7 @@ def parseSwitchCase():
consequent.append(statement)
return delegate.markEnd(delegate.createSwitchCase(test, consequent))
+
def parseSwitchStatement():
discriminant = None
cases = None
@@ -2267,24 +2545,24 @@ def parseSwitchStatement():
clause = parseSwitchCase()
if clause.test == None:
if defaultFound:
- throwError(jsdict({
-}), Messages.MultipleDefaultsInSwitch)
+ throwError(jsdict({}), Messages.MultipleDefaultsInSwitch)
defaultFound = True
cases.append(clause)
state.inSwitch = oldInSwitch
expect("}")
return delegate.createSwitchStatement(discriminant, cases)
+
def parseThrowStatement():
argument = None
expectKeyword("throw")
if peekLineTerminator():
- throwError(jsdict({
-}), Messages.NewlineAfterThrow)
+ throwError(jsdict({}), Messages.NewlineAfterThrow)
argument = parseExpression()
consumeSemicolon()
return delegate.createThrowStatement(argument)
+
def parseCatchClause():
param = None
body = None
@@ -2296,12 +2574,12 @@ def parseCatchClause():
throwUnexpected(lookahead)
param = parseVariableIdentifier()
if strict and isRestrictedWord(param.name):
- throwErrorTolerant(jsdict({
-}), Messages.StrictCatchVariable)
+ throwErrorTolerant(jsdict({}), Messages.StrictCatchVariable)
expect(")")
body = parseBlock()
return delegate.markEnd(delegate.createCatchClause(param, body))
+
def parseTryStatement():
block = None
handlers = []
@@ -2314,15 +2592,16 @@ def parseTryStatement():
lex()
finalizer = parseBlock()
if (len(handlers) == 0) and (not finalizer):
- throwError(jsdict({
-}), Messages.NoCatchOrFinally)
+ throwError(jsdict({}), Messages.NoCatchOrFinally)
return delegate.createTryStatement(block, [], handlers, finalizer)
+
def parseDebuggerStatement():
expectKeyword("debugger")
consumeSemicolon()
return delegate.createDebuggerStatement()
+
def parseStatement():
type = lookahead.type
expr = None
@@ -2381,15 +2660,16 @@ def parseStatement():
lex()
key = "$" + expr.name
if key in state.labelSet:
- throwError(jsdict({
-}), Messages.Redeclaration, "Label", expr.name)
+ throwError(jsdict({}), Messages.Redeclaration, "Label", expr.name)
state.labelSet[key] = True
labeledBody = parseStatement()
del state.labelSet[key]
- return delegate.markEnd(delegate.createLabeledStatement(expr, labeledBody))
+ return delegate.markEnd(
+ delegate.createLabeledStatement(expr, labeledBody))
consumeSemicolon()
return delegate.markEnd(delegate.createExpressionStatement(expr))
+
def parseFunctionSourceElements():
global strict
sourceElement = None
@@ -2416,7 +2696,8 @@ def parseFunctionSourceElements():
if directive == "use strict":
strict = True
if firstRestricted:
- throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral)
+ throwErrorTolerant(firstRestricted,
+ Messages.StrictOctalLiteral)
else:
if (not firstRestricted) and token.octal:
firstRestricted = token
@@ -2424,8 +2705,7 @@ def parseFunctionSourceElements():
oldInIteration = state.inIteration
oldInSwitch = state.inSwitch
oldInFunctionBody = state.inFunctionBody
- state.labelSet = jsdict({
-})
+ state.labelSet = jsdict({})
state.inIteration = False
state.inSwitch = False
state.inFunctionBody = True
@@ -2433,7 +2713,8 @@ def parseFunctionSourceElements():
if match("}"):
break
sourceElement = parseSourceElement()
- if ('undefined' if not 'sourceElement' in locals() else typeof(sourceElement)) == "undefined":
+ if ('undefined' if not 'sourceElement' in locals() else
+ typeof(sourceElement)) == "undefined":
break
sourceElements.append(sourceElement)
expect("}")
@@ -2443,6 +2724,7 @@ def parseFunctionSourceElements():
state.inFunctionBody = oldInFunctionBody
return delegate.markEnd(delegate.createBlockStatement(sourceElements))
+
def parseParams(firstRestricted=None):
param = None
params = []
@@ -2453,8 +2735,7 @@ def parseParams(firstRestricted=None):
message = None
expect("(")
if not match(")"):
- paramSet = jsdict({
-})
+ paramSet = jsdict({})
while index < length:
token = lookahead
param = parseVariableIdentifier()
@@ -2483,11 +2764,12 @@ def parseParams(firstRestricted=None):
expect(",")
expect(")")
return jsdict({
-"params": params,
-"stricted": stricted,
-"firstRestricted": firstRestricted,
-"message": message,
-})
+ "params": params,
+ "stricted": stricted,
+ "firstRestricted": firstRestricted,
+ "message": message,
+ })
+
def parseFunctionDeclaration():
global strict
@@ -2528,7 +2810,9 @@ def parseFunctionDeclaration():
if strict and stricted:
throwErrorTolerant(stricted, message)
strict = previousStrict
- return delegate.markEnd(delegate.createFunctionDeclaration(id, params, [], body))
+ return delegate.markEnd(
+ delegate.createFunctionDeclaration(id, params, [], body))
+
def parseFunctionExpression():
global strict
@@ -2569,7 +2853,9 @@ def parseFunctionExpression():
if strict and stricted:
throwErrorTolerant(stricted, message)
strict = previousStrict
- return delegate.markEnd(delegate.createFunctionExpression(id, params, [], body))
+ return delegate.markEnd(
+ delegate.createFunctionExpression(id, params, [], body))
+
def parseSourceElement():
if lookahead.type == Token.Keyword:
@@ -2584,6 +2870,7 @@ def parseSourceElement():
if lookahead.type != Token.EOF:
return parseStatement()
+
def parseSourceElements():
global strict
sourceElement = None
@@ -2603,17 +2890,20 @@ def parseSourceElements():
if directive == "use strict":
strict = True
if firstRestricted:
- throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral)
+ throwErrorTolerant(firstRestricted,
+ Messages.StrictOctalLiteral)
else:
if (not firstRestricted) and token.octal:
firstRestricted = token
while index < length:
sourceElement = parseSourceElement()
- if ('undefined' if not 'sourceElement' in locals() else typeof(sourceElement)) == "undefined":
+ if ('undefined' if not 'sourceElement' in locals() else
+ typeof(sourceElement)) == "undefined":
break
sourceElements.append(sourceElement)
return sourceElements
+
def parseProgram():
global strict
body = None
@@ -2624,6 +2914,7 @@ def parseProgram():
body = parseSourceElements()
return delegate.markEnd(delegate.createProgram(body))
+
def collectToken():
start = None
loc = None
@@ -2633,27 +2924,30 @@ def collectToken():
skipComment()
start = index
loc = jsdict({
-"start": jsdict({
-"line": lineNumber,
-"column": index - lineStart,
-}),
-})
+ "start":
+ jsdict({
+ "line": lineNumber,
+ "column": index - lineStart,
+ }),
+ })
token = extra.advance()
loc.end = jsdict({
-"line": lineNumber,
-"column": index - lineStart,
-})
+ "line": lineNumber,
+ "column": index - lineStart,
+ })
if token.type != Token.EOF:
range = [token.range[0], token.range[1]]
value = source[token.range[0]:token.range[1]]
- extra.tokens.append(jsdict({
-"type": TokenName[token.type],
-"value": value,
-"range": range,
-"loc": loc,
-}))
+ extra.tokens.append(
+ jsdict({
+ "type": TokenName[token.type],
+ "value": value,
+ "range": range,
+ "loc": loc,
+ }))
return token
+
def collectRegex():
pos = None
loc = None
@@ -2662,30 +2956,33 @@ def collectRegex():
skipComment()
pos = index
loc = jsdict({
-"start": jsdict({
-"line": lineNumber,
-"column": index - lineStart,
-}),
-})
+ "start":
+ jsdict({
+ "line": lineNumber,
+ "column": index - lineStart,
+ }),
+ })
regex = extra.scanRegExp()
loc.end = jsdict({
-"line": lineNumber,
-"column": index - lineStart,
-})
+ "line": lineNumber,
+ "column": index - lineStart,
+ })
if not extra.tokenize:
if len(extra.tokens) > 0:
token = extra.tokens[len(extra.tokens) - 1]
if (token.range[0] == pos) and (token.type == "Punctuator"):
if (token.value == "/") or (token.value == "/="):
extra.tokens.pop()
- extra.tokens.append(jsdict({
-"type": "RegularExpression",
-"value": regex.literal,
-"range": [pos, index],
-"loc": loc,
-}))
+ extra.tokens.append(
+ jsdict({
+ "type": "RegularExpression",
+ "value": regex.literal,
+ "range": [pos, index],
+ "loc": loc,
+ }))
return regex
+
def filterTokenLocation():
i = None
entry = None
@@ -2697,9 +2994,9 @@ def filterTokenLocation():
break
entry = extra.tokens[i]
token = jsdict({
-"type": entry.type,
-"value": entry.value,
-})
+ "type": entry.type,
+ "value": entry.value,
+ })
if extra.range:
token.range = entry.range
if extra.loc:
@@ -2708,51 +3005,60 @@ def filterTokenLocation():
i += 1
extra.tokens = tokens
+
class LocationMarker(object):
def __init__(self=None):
self.marker = [index, lineNumber, index - lineStart, 0, 0, 0]
-
+
def end(self=None):
self.marker[3] = index
self.marker[4] = lineNumber
self.marker[5] = index - lineStart
-
+
def apply(self=None, node=None):
if extra.range:
node.range = [self.marker[0], self.marker[3]]
if extra.loc:
node.loc = jsdict({
-"start": jsdict({
-"line": self.marker[1],
-"column": self.marker[2],
-}),
-"end": jsdict({
-"line": self.marker[4],
-"column": self.marker[5],
-}),
-})
+ "start":
+ jsdict({
+ "line": self.marker[1],
+ "column": self.marker[2],
+ }),
+ "end":
+ jsdict({
+ "line": self.marker[4],
+ "column": self.marker[5],
+ }),
+ })
node = delegate.postProcess(node)
-
+
+
def createLocationMarker():
if (not extra.loc) and (not extra.range):
return None
skipComment()
return LocationMarker()
+
def patch():
global advance, scanRegExp
- if ('undefined' if not ('tokens' in extra) else typeof(extra.tokens)) != "undefined":
+ if ('undefined' if not ('tokens' in extra) else typeof(
+ extra.tokens)) != "undefined":
extra.advance = advance
extra.scanRegExp = scanRegExp
advance = collectToken
scanRegExp = collectRegex
+
def unpatch():
global advance, scanRegExp
- if ('undefined' if not ('scanRegExp' in extra) else typeof(extra.scanRegExp)) == "function":
+ if ('undefined' if not ('scanRegExp' in extra) else typeof(
+ extra.scanRegExp)) == "function":
advance = extra.advance
scanRegExp = extra.scanRegExp
+
def tokenize(code, **options):
global delegate, source, index, lineNumber, lineStart, length, lookahead, state, extra
options = jsdict(options)
@@ -2760,7 +3066,8 @@ def tokenize(code, **options):
token = None
tokens = None
toString = str
- if (('undefined' if not 'code' in locals() else typeof(code)) != "string") and (not isinstance(code, str)):
+ if (('undefined' if not 'code' in locals() else typeof(code)) !=
+ "string") and (not isinstance(code, str)):
code = toString(code)
delegate = SyntaxTreeDelegate
source = code
@@ -2770,28 +3077,29 @@ def tokenize(code, **options):
length = len(source)
lookahead = None
state = jsdict({
-"allowIn": True,
-"labelSet": jsdict({
-}),
-"inFunctionBody": False,
-"inIteration": False,
-"inSwitch": False,
-"lastCommentStart": -1,
-})
- extra = jsdict({
-})
- options = options or jsdict({
-})
+ "allowIn": True,
+ "labelSet": jsdict({}),
+ "inFunctionBody": False,
+ "inIteration": False,
+ "inSwitch": False,
+ "lastCommentStart": -1,
+ })
+ extra = jsdict({})
+ options = options or jsdict({})
options.tokens = True
extra.tokens = []
extra.tokenize = True
extra.openParenToken = -1
extra.openCurlyToken = -1
- extra.range = (('undefined' if not ('range' in options) else typeof(options.range)) == "boolean") and options.range
- extra.loc = (('undefined' if not ('loc' in options) else typeof(options.loc)) == "boolean") and options.loc
- if (('undefined' if not ('comment' in options) else typeof(options.comment)) == "boolean") and options.comment:
+ extra.range = (('undefined' if not ('range' in options) else typeof(
+ options.range)) == "boolean") and options.range
+ extra.loc = (('undefined' if not ('loc' in options) else typeof(
+ options.loc)) == "boolean") and options.loc
+ if (('undefined' if not ('comment' in options) else typeof(
+ options.comment)) == "boolean") and options.comment:
extra.comments = []
- if (('undefined' if not ('tolerant' in options) else typeof(options.tolerant)) == "boolean") and options.tolerant:
+ if (('undefined' if not ('tolerant' in options) else typeof(
+ options.tolerant)) == "boolean") and options.tolerant:
extra.errors = []
if length > 0:
if (typeof(source[0])) == "undefined":
@@ -2812,28 +3120,31 @@ def tokenize(code, **options):
extra.errors.append(lexError)
break
else:
- raise
+ raise
filterTokenLocation()
tokens = extra.tokens
- if ('undefined' if not ('comments' in extra) else typeof(extra.comments)) != "undefined":
+ if ('undefined' if not ('comments' in extra) else typeof(
+ extra.comments)) != "undefined":
tokens.comments = extra.comments
- if ('undefined' if not ('errors' in extra) else typeof(extra.errors)) != "undefined":
+ if ('undefined' if not ('errors' in extra) else typeof(
+ extra.errors)) != "undefined":
tokens.errors = extra.errors
except Exception as e:
- raise
+ raise
finally:
unpatch()
- extra = jsdict({
-})
+ extra = jsdict({})
return tokens
+
def parse(code, **options):
global delegate, source, index, lineNumber, lineStart, length, lookahead, state, extra
options = jsdict(options)
program = None
toString = None
toString = str
- if (('undefined' if not 'code' in locals() else typeof(code)) != "string") and (not isinstance(code, str)):
+ if (('undefined' if not 'code' in locals() else typeof(code)) !=
+ "string") and (not isinstance(code, str)):
code = toString(code)
delegate = SyntaxTreeDelegate
source = code
@@ -2843,27 +3154,32 @@ def parse(code, **options):
length = len(source)
lookahead = None
state = jsdict({
-"allowIn": True,
-"labelSet": jsdict({
-}),
-"inFunctionBody": False,
-"inIteration": False,
-"inSwitch": False,
-"lastCommentStart": -1,
-"markerStack": [],
-})
- extra = jsdict({
-})
- if ('undefined' if not 'options' in locals() else typeof(options)) != "undefined":
- extra.range = (('undefined' if not ('range' in options) else typeof(options.range)) == "boolean") and options.range
- extra.loc = (('undefined' if not ('loc' in options) else typeof(options.loc)) == "boolean") and options.loc
- if (extra.loc and (options.source != None)) and (options.source != undefined):
+ "allowIn": True,
+ "labelSet": jsdict({}),
+ "inFunctionBody": False,
+ "inIteration": False,
+ "inSwitch": False,
+ "lastCommentStart": -1,
+ "markerStack": [],
+ })
+ extra = jsdict({})
+ if ('undefined'
+ if not 'options' in locals() else typeof(options)) != "undefined":
+ extra.range = (('undefined' if not ('range' in options) else typeof(
+ options.range)) == "boolean") and options.range
+ extra.loc = (('undefined' if not ('loc' in options) else typeof(
+ options.loc)) == "boolean") and options.loc
+ if (extra.loc and
+ (options.source != None)) and (options.source != undefined):
extra.source = toString(options.source)
- if (('undefined' if not ('tokens' in options) else typeof(options.tokens)) == "boolean") and options.tokens:
+ if (('undefined' if not ('tokens' in options) else typeof(
+ options.tokens)) == "boolean") and options.tokens:
extra.tokens = []
- if (('undefined' if not ('comment' in options) else typeof(options.comment)) == "boolean") and options.comment:
+ if (('undefined' if not ('comment' in options) else typeof(
+ options.comment)) == "boolean") and options.comment:
extra.comments = []
- if (('undefined' if not ('tolerant' in options) else typeof(options.tolerant)) == "boolean") and options.tolerant:
+ if (('undefined' if not ('tolerant' in options) else typeof(
+ options.tolerant)) == "boolean") and options.tolerant:
extra.errors = []
if length > 0:
if (typeof(source[0])) == "undefined":
@@ -2872,20 +3188,22 @@ def parse(code, **options):
patch()
try:
program = parseProgram()
- if ('undefined' if not ('comments' in extra) else typeof(extra.comments)) != "undefined":
+ if ('undefined' if not ('comments' in extra) else typeof(
+ extra.comments)) != "undefined":
program.comments = extra.comments
- if ('undefined' if not ('tokens' in extra) else typeof(extra.tokens)) != "undefined":
+ if ('undefined' if not ('tokens' in extra) else typeof(
+ extra.tokens)) != "undefined":
filterTokenLocation()
program.tokens = extra.tokens
- if ('undefined' if not ('errors' in extra) else typeof(extra.errors)) != "undefined":
+ if ('undefined' if not ('errors' in extra) else typeof(
+ extra.errors)) != "undefined":
program.errors = extra.errors
except Exception as e:
- raise
+ raise
finally:
unpatch()
- extra = jsdict({
-})
+ extra = jsdict({})
return program
-parse('var = 490 \n a=4;')
\ No newline at end of file
+parse('var = 490 \n a=4;')
diff --git a/js2py/legecy_translators/objects.py b/js2py/legecy_translators/objects.py
index a05f77bf..5cb9012a 100644
--- a/js2py/legecy_translators/objects.py
+++ b/js2py/legecy_translators/objects.py
@@ -1,17 +1,21 @@
""" This module removes all objects/arrays from JS source code and replace them with LVALS.
Also it has s function translating removed object/array to python code.
Use this module just after removing constants. Later move on to removing functions"""
+from __future__ import print_function
+
OBJECT_LVAL = 'PyJsLvalObject%d_'
ARRAY_LVAL = 'PyJsLvalArray%d_'
from utils import *
from jsparser import *
-from nodevisitor import exp_translator
+from nodevisitor import exp_translator
import functions
from flow import KEYWORD_METHODS
-def FUNC_TRANSLATOR(*a):# stupid import system in python
+
+def FUNC_TRANSLATOR(*a): # stupid import system in python
raise RuntimeError('Remember to set func translator. Thank you.')
+
def set_func_translator(ftrans):
# stupid stupid Python or Peter
global FUNC_TRANSLATOR
@@ -24,11 +28,15 @@ def is_empty_object(n, last):
return False
# seems to be but can be empty code
last = last.strip()
- markers = {')', ';',}
+ markers = {
+ ')',
+ ';',
+ }
if not last or last[-1] in markers:
return False
return True
+
# todo refine this function
def is_object(n, last):
"""n may be the inside of block or object.
@@ -38,19 +46,21 @@ def is_object(n, last):
if not n.strip():
return False
#Object contains lines of code so it cant be an object
- if len(argsplit(n, ';'))>1:
+ if len(argsplit(n, ';')) > 1:
return False
cands = argsplit(n, ',')
if not cands[-1].strip():
- return True # {xxxx,} empty after last , it must be an object
+ return True # {xxxx,} empty after last , it must be an object
for cand in cands:
cand = cand.strip()
# separate each candidate element at : in dict and check whether they are correct...
kv = argsplit(cand, ':')
- if len(kv) > 2: # set the len of kv to 2 because of this stupid : expression
- kv = kv[0],':'.join(kv[1:])
+ if len(
+ kv
+ ) > 2: # set the len of kv to 2 because of this stupid : expression
+ kv = kv[0], ':'.join(kv[1:])
- if len(kv)==2:
+ if len(kv) == 2:
# key value pair, check whether not label or ?:
k, v = kv
if not is_lval(k.strip()):
@@ -59,11 +69,12 @@ def is_object(n, last):
if v.startswith('function'):
continue
#will fail on label... {xxx: while {}}
- if v[0]=='{': # value cant be a code block
+ if v[0] == '{': # value cant be a code block
return False
for e in KEYWORD_METHODS:
# if v starts with any statement then return false
- if v.startswith(e) and len(e) 2
- print 'Unusual case ' + repr(e)
+ print('Unusual case ' + repr(e))
key = spl[0]
value = ':'.join(spl[1:])
key = key.strip()
@@ -182,54 +197,56 @@ def translate_object(obj, lval, obj_count=1, arr_count=1):
res.append('%s:%s' % (key, value))
res = '%s = Js({%s})\n' % (lval, ','.join(res)) + gsetters_after
# translate all the nested objects (including removed earlier functions)
- for nested_name, nested_info in inline.iteritems(): # functions
+ for nested_name, nested_info in inline.iteritems(): # functions
nested_block, nested_args = nested_info
new_def = FUNC_TRANSLATOR(nested_name, nested_block, nested_args)
res = new_def + res
- for lval, obj in obj_rep.iteritems(): #objects
- new_def, obj_count, arr_count = translate_object(obj, lval, obj_count, arr_count)
+ for lval, obj in obj_rep.iteritems(): #objects
+ new_def, obj_count, arr_count = translate_object(
+ obj, lval, obj_count, arr_count)
# add object definition BEFORE array definition
res = new_def + res
- for lval, obj in arr_rep.iteritems(): # arrays
- new_def, obj_count, arr_count = translate_array(obj, lval, obj_count, arr_count)
+ for lval, obj in arr_rep.iteritems(): # arrays
+ new_def, obj_count, arr_count = translate_array(
+ obj, lval, obj_count, arr_count)
# add object definition BEFORE array definition
res = new_def + res
return res, obj_count, arr_count
-
def translate_setter(lval, setter):
func = 'function' + setter[3:]
try:
_, data, _ = functions.remove_functions(func)
- if not data or len(data)>1:
+ if not data or len(data) > 1:
raise Exception()
except:
- raise SyntaxError('Could not parse setter: '+setter)
+ raise SyntaxError('Could not parse setter: ' + setter)
prop = data.keys()[0]
body, args = data[prop]
- if len(args)!=1: #setter must have exactly 1 argument
+ if len(args) != 1: #setter must have exactly 1 argument
raise SyntaxError('Invalid setter. It must take exactly 1 argument.')
# now messy part
res = FUNC_TRANSLATOR('setter', body, args)
- res += "%s.define_own_property(%s, {'set': setter})\n"%(lval, repr(prop))
+ res += "%s.define_own_property(%s, {'set': setter})\n" % (lval, repr(prop))
return res
+
def translate_getter(lval, getter):
func = 'function' + getter[3:]
try:
_, data, _ = functions.remove_functions(func)
- if not data or len(data)>1:
+ if not data or len(data) > 1:
raise Exception()
except:
- raise SyntaxError('Could not parse getter: '+getter)
+ raise SyntaxError('Could not parse getter: ' + getter)
prop = data.keys()[0]
body, args = data[prop]
- if len(args)!=0: #setter must have exactly 0 argument
+ if len(args) != 0: #setter must have exactly 0 argument
raise SyntaxError('Invalid getter. It must take exactly 0 argument.')
# now messy part
res = FUNC_TRANSLATOR('getter', body, args)
- res += "%s.define_own_property(%s, {'get': setter})\n"%(lval, repr(prop))
+ res += "%s.define_own_property(%s, {'get': setter})\n" % (lval, repr(prop))
return res
@@ -261,27 +278,25 @@ def translate_array(array, lval, obj_count=1, arr_count=1):
new_def = FUNC_TRANSLATOR(nested_name, nested_block, nested_args)
arr = new_def + arr
for lval, obj in obj_rep.iteritems():
- new_def, obj_count, arr_count = translate_object(obj, lval, obj_count, arr_count)
+ new_def, obj_count, arr_count = translate_object(
+ obj, lval, obj_count, arr_count)
# add object definition BEFORE array definition
arr = new_def + arr
for lval, obj in arr_rep.iteritems():
- new_def, obj_count, arr_count = translate_array(obj, lval, obj_count, arr_count)
+ new_def, obj_count, arr_count = translate_array(
+ obj, lval, obj_count, arr_count)
# add object definition BEFORE array definition
arr = new_def + arr
return arr, obj_count, arr_count
-
-
-
-if __name__=='__main__':
+if __name__ == '__main__':
test = 'a = {404:{494:19}}; b = 303; if () {f={:}; { }}'
-
#print remove_objects(test)
#print list(bracket_split(' {}'))
- print
- print remove_arrays('typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""], [][[5][5]])[1].toLowerCase()])')
- print is_object('', ')')
-
-
+ print()
+ print(remove_arrays(
+ 'typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""], [][[5][5]])[1].toLowerCase()])'
+ ))
+ print(is_object('', ')'))
diff --git a/js2py/legecy_translators/translator.py b/js2py/legecy_translators/translator.py
index 1994ab6e..c0ad8459 100644
--- a/js2py/legecy_translators/translator.py
+++ b/js2py/legecy_translators/translator.py
@@ -1,3 +1,5 @@
+from __future__ import print_function
+
from flow import translate_flow
from constants import remove_constants, recover_constants
from objects import remove_objects, remove_arrays, translate_object, translate_array, set_func_translator
@@ -7,7 +9,6 @@
TOP_GLOBAL = '''from js2py.pyjs import *\nvar = Scope( JS_BUILTINS )\nset_global_object(var)\n'''
-
def translate_js(js, top=TOP_GLOBAL):
"""js has to be a javascript source code.
returns equivalent python code."""
@@ -38,34 +39,39 @@ def translate_js(js, top=TOP_GLOBAL):
#print len(hoisted) , 'HH'*40
for nested_name, nested_info in hoisted.iteritems():
nested_block, nested_args = nested_info
- new_code = translate_func('PyJsLvalTempHoisted', nested_block, nested_args)
- new_code += 'PyJsLvalTempHoisted.func_name = %s\n' %repr(nested_name)
- defs += new_code +'\nvar.put(%s, PyJsLvalTempHoisted)\n' % repr(nested_name)
+ new_code = translate_func('PyJsLvalTempHoisted', nested_block,
+ nested_args)
+ new_code += 'PyJsLvalTempHoisted.func_name = %s\n' % repr(nested_name)
+ defs += new_code + '\nvar.put(%s, PyJsLvalTempHoisted)\n' % repr(
+ nested_name)
#defs += '# Everting ready!\n'
# inline functions recovery
for nested_name, nested_info in inline.iteritems():
nested_block, nested_args = nested_info
new_code = translate_func(nested_name, nested_block, nested_args)
- py_seed = inject_before_lval(py_seed, nested_name.split('@')[0], new_code)
+ py_seed = inject_before_lval(py_seed,
+ nested_name.split('@')[0], new_code)
# add hoisted definitiond - they have literals that have to be recovered
py_seed = defs + py_seed
#Recover arrays
for arr_lval, arr_code in arrays.iteritems():
- translation, obj_count, arr_count = translate_array(arr_code, arr_lval, obj_count, arr_count)
+ translation, obj_count, arr_count = translate_array(
+ arr_code, arr_lval, obj_count, arr_count)
py_seed = inject_before_lval(py_seed, arr_lval, translation)
#Recover objects
for obj_lval, obj_code in objects.iteritems():
- translation, obj_count, arr_count = translate_object(obj_code, obj_lval, obj_count, arr_count)
+ translation, obj_count, arr_count = translate_object(
+ obj_code, obj_lval, obj_count, arr_count)
py_seed = inject_before_lval(py_seed, obj_lval, translation)
-
#Recover constants
py_code = recover_constants(py_seed, constants)
return top + py_code
+
def translate_func(name, block, args):
"""Translates functions and all nested functions to Python code.
name - name of that function (global functions will be available under var while
@@ -76,12 +82,12 @@ def translate_func(name, block, args):
real_name = ''
if inline:
name, real_name = name.split('@')
- arglist = ', '.join(args) +', ' if args else ''
+ arglist = ', '.join(args) + ', ' if args else ''
code = '@Js\ndef %s(%sthis, arguments, var=var):\n' % (name, arglist)
# register local variables
- scope = "'this':this, 'arguments':arguments" #it will be a simple dictionary
+ scope = "'this':this, 'arguments':arguments" #it will be a simple dictionary
for arg in args:
- scope += ', %s:%s' %(repr(arg), arg)
+ scope += ', %s:%s' % (repr(arg), arg)
if real_name:
scope += ', %s:%s' % (repr(real_name), name)
code += indent('var = Scope({%s}, var)\n' % scope)
@@ -90,26 +96,30 @@ def translate_func(name, block, args):
#register variables declared with var and names of hoisted functions.
to_register += nested_hoisted.keys()
if to_register:
- code += indent('var.registers(%s)\n'% str(to_register))
+ code += indent('var.registers(%s)\n' % str(to_register))
for nested_name, info in nested_hoisted.iteritems():
nested_block, nested_args = info
- new_code = translate_func('PyJsLvalTempHoisted', nested_block, nested_args)
+ new_code = translate_func('PyJsLvalTempHoisted', nested_block,
+ nested_args)
# Now put definition of hoisted function on the top
code += indent(new_code)
- code += indent('PyJsLvalTempHoisted.func_name = %s\n' %repr(nested_name))
- code += indent('var.put(%s, PyJsLvalTempHoisted)\n' % repr(nested_name))
+ code += indent(
+ 'PyJsLvalTempHoisted.func_name = %s\n' % repr(nested_name))
+ code += indent(
+ 'var.put(%s, PyJsLvalTempHoisted)\n' % repr(nested_name))
for nested_name, info in nested_inline.iteritems():
nested_block, nested_args = info
new_code = translate_func(nested_name, nested_block, nested_args)
# Inject definitions of inline functions just before usage
# nested inline names have this format : LVAL_NAME@REAL_NAME
- py_code = inject_before_lval(py_code, nested_name.split('@')[0], new_code)
+ py_code = inject_before_lval(py_code,
+ nested_name.split('@')[0], new_code)
if py_code.strip():
code += indent(py_code)
return code
-set_func_translator(translate_func)
+set_func_translator(translate_func)
#print inject_before_lval(' chuj\n moj\n lval\nelse\n', 'lval', 'siema\njestem piter\n')
import time
@@ -123,7 +133,7 @@ def translate_func(name, block, args):
"""
-SANDBOX ='''
+SANDBOX = '''
import traceback
try:
%s
@@ -132,12 +142,12 @@ def translate_func(name, block, args):
print
raw_input('Press Enter to quit')
'''
-if __name__=='__main__':
+if __name__ == '__main__':
# test with jq if works then it really works :)
#with open('jq.js', 'r') as f:
- #jq = f.read()
+ #jq = f.read()
#res = translate_js(jq)
res = translate_js(t)
- dbg(SANDBOX% indent(res))
- print 'Done'
\ No newline at end of file
+ dbg(SANDBOX % indent(res))
+ print('Done')
diff --git a/js2py/legecy_translators/utils.py b/js2py/legecy_translators/utils.py
index f5bd7890..b14e13d8 100644
--- a/js2py/legecy_translators/utils.py
+++ b/js2py/legecy_translators/utils.py
@@ -2,6 +2,7 @@
import unicodedata
from collections import defaultdict
+
def is_lval(t):
"""Does not chceck whether t is not resticted or internal"""
if not t:
@@ -11,6 +12,7 @@ def is_lval(t):
return False
return all(e in IDENTIFIER_PART for e in i)
+
def is_valid_lval(t):
"""Checks whether t is valid JS identifier name (no keyword like var, function, if etc)
Also returns false on internal"""
@@ -22,21 +24,23 @@ def is_valid_lval(t):
def is_plval(t):
return t.startswith('PyJsLval')
+
def is_marker(t):
return t.startswith('PyJsMarker') or t.startswith('PyJsConstant')
+
def is_internal(t):
- return is_plval(t) or is_marker(t) or t=='var' # var is a scope var
+ return is_plval(t) or is_marker(t) or t == 'var' # var is a scope var
+
def is_property_accessor(t):
return '[' in t or '.' in t
+
def is_reserved(t):
return t in RESERVED_NAMES
-
-
#http://stackoverflow.com/questions/14245893/efficiently-list-all-characters-in-a-given-unicode-category
BOM = u'\uFEFF'
ZWJ = u'\u200D'
@@ -55,26 +59,33 @@ def is_reserved(t):
for c in map(unichr, range(sys.maxunicode + 1)):
U_CATEGORIES[unicodedata.category(c)].append(c)
-UNICODE_LETTER = set(U_CATEGORIES['Lu']+U_CATEGORIES['Ll']+
- U_CATEGORIES['Lt']+U_CATEGORIES['Lm']+
- U_CATEGORIES['Lo']+U_CATEGORIES['Nl'])
-UNICODE_COMBINING_MARK = set(U_CATEGORIES['Mn']+U_CATEGORIES['Mc'])
+UNICODE_LETTER = set(U_CATEGORIES['Lu'] + U_CATEGORIES['Ll'] +
+ U_CATEGORIES['Lt'] + U_CATEGORIES['Lm'] +
+ U_CATEGORIES['Lo'] + U_CATEGORIES['Nl'])
+UNICODE_COMBINING_MARK = set(U_CATEGORIES['Mn'] + U_CATEGORIES['Mc'])
UNICODE_DIGIT = set(U_CATEGORIES['Nd'])
UNICODE_CONNECTOR_PUNCTUATION = set(U_CATEGORIES['Pc'])
-IDENTIFIER_START = UNICODE_LETTER.union({'$','_'}) # and some fucking unicode escape sequence
-IDENTIFIER_PART = IDENTIFIER_START.union(UNICODE_COMBINING_MARK).union(UNICODE_DIGIT).union(UNICODE_CONNECTOR_PUNCTUATION).union({ZWJ, ZWNJ})
+IDENTIFIER_START = UNICODE_LETTER.union(
+ {'$', '_'}) # and some fucking unicode escape sequence
+IDENTIFIER_PART = IDENTIFIER_START.union(UNICODE_COMBINING_MARK).union(
+ UNICODE_DIGIT).union(UNICODE_CONNECTOR_PUNCTUATION).union({ZWJ, ZWNJ})
USP = U_CATEGORIES['Zs']
-KEYWORD = {'break', 'do', 'instanceof', 'typeof', 'case', 'else', 'new',
- 'var', 'catch', 'finally', 'return', 'void', 'continue', 'for',
- 'switch', 'while', 'debugger', 'function', 'this', 'with', 'default',
- 'if', 'throw', 'delete', 'in', 'try'}
-
-FUTURE_RESERVED_WORD = {'class', 'enum', 'extends', 'super', 'const', 'export', 'import'}
-RESERVED_NAMES = KEYWORD.union(FUTURE_RESERVED_WORD).union({'null', 'false', 'true'})
+KEYWORD = {
+ 'break', 'do', 'instanceof', 'typeof', 'case', 'else', 'new', 'var',
+ 'catch', 'finally', 'return', 'void', 'continue', 'for', 'switch', 'while',
+ 'debugger', 'function', 'this', 'with', 'default', 'if', 'throw', 'delete',
+ 'in', 'try'
+}
+
+FUTURE_RESERVED_WORD = {
+ 'class', 'enum', 'extends', 'super', 'const', 'export', 'import'
+}
+RESERVED_NAMES = KEYWORD.union(FUTURE_RESERVED_WORD).union(
+ {'null', 'false', 'true'})
WHITE = {TAB, VT, FF, SP, NBSP, BOM}.union(USP)
LINE_TERMINATOR = {LF, CR, LS, PS}
LLINE_TERMINATOR = list(LINE_TERMINATOR)
-x = ''.join(WHITE)+''.join(LINE_TERMINATOR)
+x = ''.join(WHITE) + ''.join(LINE_TERMINATOR)
SPACE = WHITE.union(LINE_TERMINATOR)
-LINE_TERMINATOR_SEQUENCE = LINE_TERMINATOR.union({CR+LF})
\ No newline at end of file
+LINE_TERMINATOR_SEQUENCE = LINE_TERMINATOR.union({CR + LF})
diff --git a/js2py/node_import.py b/js2py/node_import.py
new file mode 100644
index 00000000..21844314
--- /dev/null
+++ b/js2py/node_import.py
@@ -0,0 +1,167 @@
+__all__ = ['require']
+
+import subprocess, os, codecs, glob
+from .evaljs import translate_js, DEFAULT_HEADER
+from .translators.friendly_nodes import is_valid_py_name
+import six
+import tempfile
+import hashlib
+import random
+
+DID_INIT = False
+DIRNAME = tempfile.mkdtemp()
+PY_NODE_MODULES_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'py_node_modules')
+
+
+def _init():
+ global DID_INIT
+ if DID_INIT:
+ return
+ assert subprocess.call(
+ 'node -v', shell=True, cwd=DIRNAME
+ ) == 0, 'You must have node installed! run: brew install node'
+ assert subprocess.call(
+ 'cd %s;npm install babel-core babel-cli babel-preset-es2015 babel-polyfill babelify browserify browserify-shim'
+ % repr(DIRNAME),
+ shell=True,
+ cwd=DIRNAME) == 0, 'Could not link required node_modules'
+ DID_INIT = True
+
+
+ADD_TO_GLOBALS_FUNC = '''
+;function addToGlobals(name, obj) {
+ if (!Object.prototype.hasOwnProperty('_fake_exports')) {
+ Object.prototype._fake_exports = {};
+ }
+ Object.prototype._fake_exports[name] = obj;
+};
+
+'''
+# subprocess.call("""node -e 'require("browserify")'""", shell=True)
+GET_FROM_GLOBALS_FUNC = '''
+;function getFromGlobals(name) {
+ if (!Object.prototype.hasOwnProperty('_fake_exports')) {
+ throw Error("Could not find any value named "+name);
+ }
+ if (Object.prototype._fake_exports.hasOwnProperty(name)) {
+ return Object.prototype._fake_exports[name];
+ } else {
+ throw Error("Could not find any value named "+name);
+ }
+};
+
+'''
+
+
+def _get_module_py_name(module_name):
+ return module_name.replace('-', '_')
+
+
+def _get_module_var_name(module_name):
+ cand = _get_module_py_name(module_name).rpartition('/')[-1]
+ if not is_valid_py_name(cand):
+ raise ValueError(
+ "Invalid Python module name %s (generated from %s). Unsupported/invalid npm module specification?" % (
+ repr(cand), repr(module_name)))
+ return cand
+
+
+def _get_and_translate_npm_module(module_name, include_polyfill=False, update=False, maybe_version_str=""):
+ assert isinstance(module_name, str), 'module_name must be a string!'
+
+ py_name = _get_module_py_name(module_name)
+ module_filename = '%s.py' % py_name
+ var_name = _get_module_var_name(module_name)
+ if not os.path.exists(os.path.join(PY_NODE_MODULES_PATH,
+ module_filename)) or update:
+ _init()
+ module_hash = hashlib.sha1(module_name.encode("utf-8")).hexdigest()[:15]
+ version = random.randrange(10000000000000)
+ in_file_name = 'in_%s_%d.js' % (module_hash, version)
+ out_file_name = 'out_%s_%d.js' % (module_hash, version)
+ code = ADD_TO_GLOBALS_FUNC
+ if include_polyfill:
+ code += "\n;require('babel-polyfill');\n"
+ code += """
+ var module_temp_love_python = require(%s);
+ addToGlobals(%s, module_temp_love_python);
+ """ % (repr(module_name), repr(module_name))
+ with open(os.path.join(DIRNAME, in_file_name), 'wb') as f:
+ f.write(code.encode('utf-8') if six.PY3 else code)
+
+ pkg_name = module_name.partition('/')[0]
+ if maybe_version_str:
+ pkg_name += '@' + maybe_version_str
+ # make sure the module is installed
+ assert subprocess.call(
+ 'cd %s;npm install %s' % (repr(DIRNAME), pkg_name),
+ shell=True,
+ cwd=DIRNAME
+ ) == 0, 'Could not install the required module: ' + pkg_name
+
+ # convert the module
+ assert subprocess.call(
+ '''node -e "(require('browserify')('./%s').bundle(function (err,data) {if (err) {console.log(err);throw new Error(err);};fs.writeFile('%s', require('babel-core').transform(data, {'presets': require('babel-preset-es2015')}).code, ()=>{});}))"'''
+ % (in_file_name, out_file_name),
+ shell=True,
+ cwd=DIRNAME,
+ ) == 0, 'Error when converting module to the js bundle'
+
+ os.remove(os.path.join(DIRNAME, in_file_name))
+ with codecs.open(os.path.join(DIRNAME, out_file_name), "r",
+ "utf-8") as f:
+ js_code = f.read()
+ print("Bundled JS library dumped at: %s" % os.path.join(DIRNAME, out_file_name))
+ if len(js_code) < 50:
+ raise RuntimeError("Candidate JS bundle too short - likely browserify issue.")
+ js_code += GET_FROM_GLOBALS_FUNC
+ js_code += ';var %s = getFromGlobals(%s);%s' % (
+ var_name, repr(module_name), var_name)
+ print('Please wait, translating...')
+ py_code = translate_js(js_code)
+
+ dirname = os.path.dirname(
+ os.path.join(PY_NODE_MODULES_PATH, module_filename))
+ if not os.path.isdir(dirname):
+ os.makedirs(dirname)
+ with open(os.path.join(PY_NODE_MODULES_PATH, module_filename),
+ 'wb') as f:
+ f.write(py_code.encode('utf-8') if six.PY3 else py_code)
+ else:
+ with codecs.open(
+ os.path.join(PY_NODE_MODULES_PATH, module_filename), "r",
+ "utf-8") as f:
+ py_code = f.read()
+ return py_code
+
+
+def require(module_name, include_polyfill=True, update=False, context=None):
+ """
+ Installs the provided npm module, exports a js bundle via browserify, converts to ECMA 5.1 via babel and
+ finally translates the generated JS bundle to Python via Js2Py.
+ Returns a pure python object that behaves like the installed module. Nice!
+
+ :param module_name: Name of the npm module to require. For example 'esprima'. Supports specific versions via @
+ specification. Eg: 'crypto-js@3.3'.
+ :param include_polyfill: Whether the babel-polyfill should be included as part of the translation. May be needed
+ for some modules that use unsupported features of JS6 such as Map or typed arrays.
+ :param update: Whether to force update the translation. Otherwise uses a cached version if exists.
+ :param context: Optional context in which the translated module should be executed in. If provided, the
+ header (js2py imports) will be skipped as it is assumed that the context already has all the necessary imports.
+ :return: The JsObjectWrapper containing the translated module object. Can be used like a standard python object.
+ """
+ module_name, maybe_version = (module_name+"@@@").split('@')[:2]
+
+ py_code = _get_and_translate_npm_module(module_name, include_polyfill=include_polyfill, update=update,
+ maybe_version_str=maybe_version)
+ # this is a bit hacky but we need to strip the default header from the generated code...
+ if context is not None:
+ if not py_code.startswith(DEFAULT_HEADER):
+ # new header version? retranslate...
+ assert not update, "Unexpected header."
+ py_code = _get_and_translate_npm_module(module_name, include_polyfill=include_polyfill, update=True)
+ assert py_code.startswith(DEFAULT_HEADER), "Unexpected header."
+ py_code = py_code[len(DEFAULT_HEADER):]
+ context = {} if context is None else context
+ exec(py_code, context)
+ return context['var'][_get_module_var_name(module_name)].to_py()
diff --git a/js2py/prototypes/jsarray.py b/js2py/prototypes/jsarray.py
index efa4796d..d02e62b2 100644
--- a/js2py/prototypes/jsarray.py
+++ b/js2py/prototypes/jsarray.py
@@ -4,6 +4,7 @@
xrange = range
import functools
+
def to_arr(this):
"""Returns Python array from Js array"""
return [this.get(str(e)) for e in xrange(len(this))]
@@ -11,14 +12,17 @@ def to_arr(this):
ARR_STACK = set({})
+
class ArrayPrototype:
def toString():
# this function is wrong but I will leave it here fore debugging purposes.
func = this.get('join')
if not func.is_callable():
+
@this.Js
def func():
- return '[object %s]'%this.Class
+ return '[object %s]' % this.Class
+
return func.call(this, ())
def toLocaleString():
@@ -36,7 +40,10 @@ def toLocaleString():
cand = element.to_object()
str_func = element.get('toLocaleString')
if not str_func.is_callable():
- raise this.MakeError('TypeError', 'toLocaleString method of item at index %d is not callable'%i)
+ raise this.MakeError(
+ 'TypeError',
+ 'toLocaleString method of item at index %d is not callable'
+ % i)
res.append(element.callprop('toLocaleString').value)
return ','.join(res)
@@ -47,24 +54,25 @@ def concat():
items.extend(to_arr(arguments))
n = 0
for E in items:
- if E.Class=='Array':
+ if E.Class == 'Array':
k = 0
e_len = len(E)
- while k (arr_len - actual_delete_count + items_len):
- array.delete(str(k-1))
+ array.delete(str(k - 1))
k -= 1
# 13
- elif items_len>actual_delete_count:
+ elif items_len > actual_delete_count:
k = arr_len - actual_delete_count
- while k>actual_start:
+ while k > actual_start:
fr = str(k + actual_delete_count - 1)
to = str(k + items_len - 1)
if array.has_property(fr):
@@ -252,7 +263,7 @@ def indexOf(searchElement):
arr_len = array.get('length').to_uint32()
if arr_len == 0:
return -1
- if len(arguments)>1:
+ if len(arguments) > 1:
n = arguments[1].to_int()
else:
n = 0
@@ -277,12 +288,12 @@ def lastIndexOf(searchElement):
arr_len = array.get('length').to_uint32()
if arr_len == 0:
return -1
- if len(arguments)>1:
+ if len(arguments) > 1:
n = arguments[1].to_int()
else:
n = arr_len - 1
if n >= 0:
- k = min(n, arr_len-1)
+ k = min(n, arr_len - 1)
else:
k = arr_len - abs(n)
while k >= 0:
@@ -293,7 +304,6 @@ def lastIndexOf(searchElement):
k -= 1
return -1
-
def every(callbackfn):
array = this.to_object()
arr_len = array.get('length').to_uint32()
@@ -301,15 +311,15 @@ def every(callbackfn):
raise this.MakeError('TypeError', 'callbackfn must be a function')
T = arguments[1]
k = 0
- while k1: # initial value present
+ if len(arguments) > 1: # initial value present
accumulator = arguments[1]
else:
kPresent = False
- while not kPresent and k1: # initial value present
+ if len(arguments) > 1: # initial value present
accumulator = arguments[1]
else:
kPresent = False
- while not kPresent and k>=0:
+ while not kPresent and k >= 0:
kPresent = array.has_property(str(k))
if kPresent:
accumulator = array.get(str(k))
k -= 1
if not kPresent:
- raise this.MakeError('TypeError', 'Reduce of empty array with no initial value')
- while k>=0:
+ raise this.MakeError(
+ 'TypeError', 'Reduce of empty array with no initial value')
+ while k >= 0:
if array.has_property(str(k)):
kValue = array.get(str(k))
- accumulator = callbackfn.call(this.undefined, (accumulator, kValue, this.Js(k), array))
+ accumulator = callbackfn.call(
+ this.undefined, (accumulator, kValue, this.Js(k), array))
k -= 1
return accumulator
@@ -447,12 +469,8 @@ def sort_compare(a, b, comp):
res = comp.call(a.undefined, (a, b))
return res.to_int()
x, y = a.to_string(), b.to_string()
- if xy:
+ elif x > y:
return 1
return 0
-
-
-
-
diff --git a/js2py/prototypes/jsarraybuffer.py b/js2py/prototypes/jsarraybuffer.py
index 5c7cf348..7bcd00fb 100644
--- a/js2py/prototypes/jsarraybuffer.py
+++ b/js2py/prototypes/jsarraybuffer.py
@@ -6,6 +6,7 @@
xrange = range
import functools
+
def to_arr(this):
"""Returns Python array from Js array"""
return [this.get(str(e)) for e in xrange(len(this))]
@@ -13,5 +14,6 @@ def to_arr(this):
ARR_STACK = set({})
+
class ArrayBufferPrototype:
pass
diff --git a/js2py/prototypes/jsboolean.py b/js2py/prototypes/jsboolean.py
index af048953..2cacd32d 100644
--- a/js2py/prototypes/jsboolean.py
+++ b/js2py/prototypes/jsboolean.py
@@ -1,16 +1,10 @@
-
-
class BooleanPrototype:
def toString():
- if this.Class!='Boolean':
+ if this.Class != 'Boolean':
raise this.Js(TypeError)('this must be a boolean')
return 'true' if this.value else 'false'
def valueOf():
- if this.Class!='Boolean':
+ if this.Class != 'Boolean':
raise this.Js(TypeError)('this must be a boolean')
return this.value
-
-
-
-
diff --git a/js2py/prototypes/jserror.py b/js2py/prototypes/jserror.py
index 934e0fc9..c488bf15 100644
--- a/js2py/prototypes/jserror.py
+++ b/js2py/prototypes/jserror.py
@@ -1,10 +1,10 @@
-
class ErrorPrototype:
def toString():
- if this.TYPE!='Object':
- raise this.MakeError('TypeError', 'Error.prototype.toString called on non-object')
+ if this.TYPE != 'Object':
+ raise this.MakeError(
+ 'TypeError', 'Error.prototype.toString called on non-object')
name = this.get('name')
name = 'Error' if name.is_undefined() else name.to_string().value
msg = this.get('message')
msg = '' if msg.is_undefined() else msg.to_string().value
- return name + (name and msg and ': ') + msg
\ No newline at end of file
+ return name + (name and msg and ': ') + msg
diff --git a/js2py/prototypes/jsfunction.py b/js2py/prototypes/jsfunction.py
index 1b67db24..2ed417e0 100644
--- a/js2py/prototypes/jsfunction.py
+++ b/js2py/prototypes/jsfunction.py
@@ -7,47 +7,45 @@
unicode = str
-# todo fix apply and bind
-
-class FunctionPrototype:
+class FunctionPrototype:
def toString():
if not this.is_callable():
raise TypeError('toString is not generic!')
args = ', '.join(this.code.__code__.co_varnames[:this.argcount])
- return 'function %s(%s) '%(this.func_name, args)+this.source
-
+ return 'function %s(%s) ' % (this.func_name, args) + this.source
+
def call():
arguments_ = arguments
if not len(arguments):
obj = this.Js(None)
else:
obj = arguments[0]
- if len(arguments)<=1:
- args = ()
+ if len(arguments) <= 1:
+ args = ()
else:
args = tuple([arguments_[e] for e in xrange(1, len(arguments_))])
return this.call(obj, args)
-
+
def apply():
if not len(arguments):
obj = this.Js(None)
else:
obj = arguments[0]
- if len(arguments)<=1:
- args = ()
+ if len(arguments) <= 1:
+ args = ()
else:
appl = arguments[1]
args = tuple([appl[e] for e in xrange(len(appl))])
return this.call(obj, args)
def bind(thisArg):
+ arguments_ = arguments
target = this
if not target.is_callable():
- raise this.MakeError('Object must be callable in order to be used with bind method')
+ raise this.MakeError(
+ 'Object must be callable in order to be used with bind method')
if len(arguments) <= 1:
args = ()
else:
- args = tuple([arguments[e] for e in xrange(1, len(arguments))])
+ args = tuple([arguments_[e] for e in xrange(1, len(arguments_))])
return this.PyJsBoundFunction(target, thisArg, args)
-
-
diff --git a/js2py/prototypes/jsjson.py b/js2py/prototypes/jsjson.py
index e933dd86..9f7ccbb0 100644
--- a/js2py/prototypes/jsjson.py
+++ b/js2py/prototypes/jsjson.py
@@ -16,7 +16,8 @@ def parse(text):
try:
unfiltered = json.loads(s)
except:
- raise this.MakeError('SyntaxError', 'Could not parse JSON string - Invalid syntax')
+ raise this.MakeError('SyntaxError',
+ 'Could not parse JSON string - Invalid syntax')
unfiltered = to_js(this, unfiltered)
if reviver.is_callable():
root = this.Js({'': unfiltered})
@@ -33,14 +34,14 @@ def stringify(value, replacer, space):
if replacer.is_object():
if replacer.is_callable():
replacer_function = replacer
- elif replacer.Class=='Array':
+ elif replacer.Class == 'Array':
property_list = []
for e in replacer:
v = replacer[e]
item = this.undefined
- if v._type()=='Number':
+ if v._type() == 'Number':
item = v.to_string()
- elif v._type()=='String':
+ elif v._type() == 'String':
item = v
elif v.is_object():
if v.Class in ('String', 'Number'):
@@ -48,19 +49,21 @@ def stringify(value, replacer, space):
if not item.is_undefined() and item.value not in property_list:
property_list.append(item.value)
if space.is_object():
- if space.Class=='Number':
+ if space.Class == 'Number':
space = space.to_number()
- elif space.Class=='String':
+ elif space.Class == 'String':
space = space.to_string()
- if space._type()=='Number':
+ if space._type() == 'Number':
space = this.Js(min(10, space.to_int()))
- gap = max(int(space.value), 0)* ' '
- elif space._type()=='String':
+ gap = max(int(space.value), 0) * ' '
+ elif space._type() == 'String':
gap = space.value[:10]
else:
gap = ''
- return this.Js(Str('', this.Js({'':value}), replacer_function, property_list, gap, stack, space))
-
+ return this.Js(
+ Str('', this.Js({
+ '': value
+ }), replacer_function, property_list, gap, stack, space))
def Str(key, holder, replacer_function, property_list, gap, stack, space):
@@ -68,40 +71,42 @@ def Str(key, holder, replacer_function, property_list, gap, stack, space):
if value.is_object():
to_json = value.get('toJSON')
if to_json.is_callable():
- value = to_json.call(value, (key,))
+ value = to_json.call(value, (key, ))
if not replacer_function.is_undefined():
value = replacer_function.call(holder, (key, value))
if value.is_object():
- if value.Class=='String':
+ if value.Class == 'String':
value = value.to_string()
- elif value.Class=='Number':
+ elif value.Class == 'Number':
value = value.to_number()
- elif value.Class=='Boolean':
+ elif value.Class == 'Boolean':
value = value.to_boolean()
if value.is_null():
return 'null'
- elif value.Class=='Boolean':
+ elif value.Class == 'Boolean':
return 'true' if value.value else 'false'
- elif value._type()=='String':
+ elif value._type() == 'String':
return Quote(value)
- elif value._type()=='Number':
+ elif value._type() == 'Number':
if not value.is_infinity():
return value.to_string()
return 'null'
if value.is_object() and not value.is_callable():
- if value.Class=='Array':
- return ja(value, stack, gap, property_list, replacer_function, space)
+ if value.Class == 'Array':
+ return ja(value, stack, gap, property_list, replacer_function,
+ space)
else:
- return jo(value, stack, gap, property_list, replacer_function, space)
- return None # undefined
-
+ return jo(value, stack, gap, property_list, replacer_function,
+ space)
+ return None # undefined
def jo(value, stack, gap, property_list, replacer_function, space):
global indent
if value in stack:
- raise value.MakeError('TypeError', 'Converting circular structure to JSON')
+ raise value.MakeError('TypeError',
+ 'Converting circular structure to JSON')
stack.add(value)
stepback = indent
indent += gap
@@ -111,9 +116,12 @@ def jo(value, stack, gap, property_list, replacer_function, space):
k = [e.value for e in value]
partial = []
for p in k:
- str_p = value.Js(Str(p, value, replacer_function, property_list, gap, stack, space))
+ str_p = value.Js(
+ Str(p, value, replacer_function, property_list, gap, stack, space))
if not str_p.is_undefined():
- member = json.dumps(p) + ':' + (' ' if gap else '') + str_p.value # todo not sure here - what space character?
+ member = json.dumps(p) + ':' + (
+ ' ' if gap else
+ '') + str_p.value # todo not sure here - what space character?
partial.append(member)
if not partial:
final = '{}'
@@ -121,9 +129,9 @@ def jo(value, stack, gap, property_list, replacer_function, space):
if not gap:
final = '{%s}' % ','.join(partial)
else:
- sep = ',\n'+indent
+ sep = ',\n' + indent
properties = sep.join(partial)
- final = '{\n'+indent+properties+'\n'+stepback+'}'
+ final = '{\n' + indent + properties + '\n' + stepback + '}'
stack.remove(value)
indent = stepback
return final
@@ -132,7 +140,8 @@ def jo(value, stack, gap, property_list, replacer_function, space):
def ja(value, stack, gap, property_list, replacer_function, space):
global indent
if value in stack:
- raise value.MakeError('TypeError', 'Converting circular structure to JSON')
+ raise value.MakeError('TypeError',
+ 'Converting circular structure to JSON')
stack.add(value)
stepback = indent
indent += gap
@@ -140,7 +149,9 @@ def ja(value, stack, gap, property_list, replacer_function, space):
length = len(value)
for index in xrange(length):
index = str(index)
- str_index = value.Js(Str(index, value, replacer_function, property_list, gap, stack, space))
+ str_index = value.Js(
+ Str(index, value, replacer_function, property_list, gap, stack,
+ space))
if str_index.is_undefined():
partial.append('null')
else:
@@ -151,31 +162,27 @@ def ja(value, stack, gap, property_list, replacer_function, space):
if not gap:
final = '[%s]' % ','.join(partial)
else:
- sep = ',\n'+indent
+ sep = ',\n' + indent
properties = sep.join(partial)
- final = '[\n'+indent +properties+'\n'+stepback+']'
+ final = '[\n' + indent + properties + '\n' + stepback + ']'
stack.remove(value)
indent = stepback
return final
-
-
-
def Quote(string):
return string.Js(json.dumps(string.value))
def to_js(this, d):
if isinstance(d, dict):
- return this.Js(dict((k,this.Js(v)) for k, v in six.iteritems(d)))
+ return this.Js(dict((k, this.Js(v)) for k, v in six.iteritems(d)))
return this.Js(d)
-
def walk(holder, name, reviver):
val = holder.get(name)
- if val.Class=='Array':
+ if val.Class == 'Array':
for i in xrange(len(val)):
i = unicode(i)
new_element = walk(val, i, reviver)
@@ -193,18 +200,20 @@ def walk(holder, name, reviver):
return reviver.call(holder, (name, val))
-
-
-
-
JSON = Js({})
-JSON.define_own_property('parse', {'value': Js(parse),
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
-
-JSON.define_own_property('stringify', {'value': Js(stringify),
- 'enumerable': False,
- 'writable': True,
- 'configurable': True})
\ No newline at end of file
+JSON.define_own_property(
+ 'parse', {
+ 'value': Js(parse),
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+ })
+
+JSON.define_own_property(
+ 'stringify', {
+ 'value': Js(stringify),
+ 'enumerable': False,
+ 'writable': True,
+ 'configurable': True
+ })
diff --git a/js2py/prototypes/jsnumber.py b/js2py/prototypes/jsnumber.py
index d825c891..c9905ab0 100644
--- a/js2py/prototypes/jsnumber.py
+++ b/js2py/prototypes/jsnumber.py
@@ -5,35 +5,73 @@
xrange = range
unicode = str
-
-RADIX_SYMBOLS = {0: '0', 1: '1', 2: '2', 3: '3', 4: '4', 5: '5', 6: '6', 7: '7', 8: '8', 9: '9',
- 10: 'a', 11: 'b', 12: 'c', 13: 'd', 14: 'e', 15: 'f', 16: 'g', 17: 'h', 18: 'i', 19: 'j', 20: 'k',
- 21: 'l', 22: 'm', 23: 'n', 24: 'o', 25: 'p', 26: 'q', 27: 'r', 28: 's', 29: 't', 30: 'u', 31: 'v',
- 32: 'w', 33: 'x', 34: 'y', 35: 'z'}
+RADIX_SYMBOLS = {
+ 0: '0',
+ 1: '1',
+ 2: '2',
+ 3: '3',
+ 4: '4',
+ 5: '5',
+ 6: '6',
+ 7: '7',
+ 8: '8',
+ 9: '9',
+ 10: 'a',
+ 11: 'b',
+ 12: 'c',
+ 13: 'd',
+ 14: 'e',
+ 15: 'f',
+ 16: 'g',
+ 17: 'h',
+ 18: 'i',
+ 19: 'j',
+ 20: 'k',
+ 21: 'l',
+ 22: 'm',
+ 23: 'n',
+ 24: 'o',
+ 25: 'p',
+ 26: 'q',
+ 27: 'r',
+ 28: 's',
+ 29: 't',
+ 30: 'u',
+ 31: 'v',
+ 32: 'w',
+ 33: 'x',
+ 34: 'y',
+ 35: 'z'
+}
def to_str_rep(num):
if num.is_nan():
return num.Js('NaN')
elif num.is_infinity():
- sign = '-' if num.value<0 else ''
- return num.Js(sign+'Infinity')
- elif isinstance(num.value, (long, int)) or num.value.is_integer(): # dont print .0
+ sign = '-' if num.value < 0 else ''
+ return num.Js(sign + 'Infinity')
+ elif isinstance(num.value,
+ (long, int)) or num.value.is_integer(): # dont print .0
return num.Js(unicode(int(num.value)))
- return num.Js(unicode(num.value)) # accurate enough
+ return num.Js(unicode(num.value)) # accurate enough
class NumberPrototype:
def toString(radix):
- if this.Class!='Number':
- raise this.MakeError('TypeError', 'Number.prototype.valueOf is not generic')
+ if this.Class != 'Number':
+ raise this.MakeError('TypeError',
+ 'Number.prototype.valueOf is not generic')
if radix.is_undefined():
return to_str_rep(this)
r = radix.to_int()
- if r==10:
+ if r == 10:
return to_str_rep(this)
- if r not in xrange(2, 37):
- raise this.MakeError('RangeError', 'Number.prototype.toString() radix argument must be between 2 and 36')
+ if r not in xrange(2, 37):
+ raise this.MakeError(
+ 'RangeError',
+ 'Number.prototype.toString() radix argument must be between 2 and 36'
+ )
num = this.to_int()
if num < 0:
num = -num
@@ -48,53 +86,61 @@ def toString(radix):
return sign + (res if res else '0')
def valueOf():
- if this.Class!='Number':
- raise this.MakeError('TypeError', 'Number.prototype.valueOf is not generic')
+ if this.Class != 'Number':
+ raise this.MakeError('TypeError',
+ 'Number.prototype.valueOf is not generic')
return this.value
def toLocaleString():
return this.to_string()
- def toFixed (fractionDigits):
- if this.Class!='Number':
- raise this.MakeError('TypeError', 'Number.prototype.toFixed called on incompatible receiver')
+ def toFixed(fractionDigits):
+ if this.Class != 'Number':
+ raise this.MakeError(
+ 'TypeError',
+ 'Number.prototype.toFixed called on incompatible receiver')
digs = fractionDigits.to_int()
- if digs<0 or digs>20:
- raise this.MakeError('RangeError', 'toFixed() digits argument must be between 0 and 20')
+ if digs < 0 or digs > 20:
+ raise this.MakeError(
+ 'RangeError',
+ 'toFixed() digits argument must be between 0 and 20')
elif this.is_infinity():
- return 'Infinity' if this.value>0 else '-Infinity'
+ return 'Infinity' if this.value > 0 else '-Infinity'
elif this.is_nan():
return 'NaN'
- return format(this.value, '-.%df'%digs)
-
+ return format(this.value, '-.%df' % digs)
- def toExponential (fractionDigits):
- if this.Class!='Number':
- raise this.MakeError('TypeError', 'Number.prototype.toExponential called on incompatible receiver')
+ def toExponential(fractionDigits):
+ if this.Class != 'Number':
+ raise this.MakeError(
+ 'TypeError',
+ 'Number.prototype.toExponential called on incompatible receiver'
+ )
digs = fractionDigits.to_int()
- if digs<0 or digs>20:
- raise this.MakeError('RangeError', 'toFixed() digits argument must be between 0 and 20')
+ if digs < 0 or digs > 20:
+ raise this.MakeError(
+ 'RangeError',
+ 'toFixed() digits argument must be between 0 and 20')
elif this.is_infinity():
- return 'Infinity' if this.value>0 else '-Infinity'
+ return 'Infinity' if this.value > 0 else '-Infinity'
elif this.is_nan():
return 'NaN'
- return format(this.value, '-.%de'%digs)
+ return format(this.value, '-.%de' % digs)
- def toPrecision (precision):
- if this.Class!='Number':
- raise this.MakeError('TypeError', 'Number.prototype.toPrecision called on incompatible receiver')
+ def toPrecision(precision):
+ if this.Class != 'Number':
+ raise this.MakeError(
+ 'TypeError',
+ 'Number.prototype.toPrecision called on incompatible receiver')
if precision.is_undefined():
return this.to_string()
prec = precision.to_int()
if this.is_nan():
return 'NaN'
elif this.is_infinity():
- return 'Infinity' if this.value>0 else '-Infinity'
+ return 'Infinity' if this.value > 0 else '-Infinity'
digs = prec - len(str(int(this.value)))
- if digs>=0:
- return format(this.value, '-.%df'%digs)
+ if digs >= 0:
+ return format(this.value, '-.%df' % digs)
else:
- return format(this.value, '-.%df'%(prec-1))
-
-
-
+ return format(this.value, '-.%df' % (prec - 1))
diff --git a/js2py/prototypes/jsobject.py b/js2py/prototypes/jsobject.py
index 793869af..aeefe5d3 100644
--- a/js2py/prototypes/jsobject.py
+++ b/js2py/prototypes/jsobject.py
@@ -1,12 +1,10 @@
-
class ObjectPrototype:
def toString():
- return '[object %s]'%this.Class
+ return '[object %s]' % this.Class
def valueOf():
return this.to_object()
-
def toLocaleString():
return this.callprop('toString')
@@ -28,9 +26,3 @@ def isPrototypeOf(obj):
def propertyIsEnumerable(prop):
cand = this.own.get(prop.to_string().value)
return cand is not None and cand.get('enumerable')
-
-
-
-
-
-
diff --git a/js2py/prototypes/jsregexp.py b/js2py/prototypes/jsregexp.py
index c14d9fda..b23f2003 100644
--- a/js2py/prototypes/jsregexp.py
+++ b/js2py/prototypes/jsregexp.py
@@ -1,4 +1,3 @@
-
class RegExpPrototype:
def toString():
flags = u''
@@ -12,20 +11,20 @@ def toString():
except:
pass
v = this.value if this.value else '(?:)'
- return u'/%s/'%v + flags
+ return u'/%s/' % v + flags
def test(string):
return Exec(this, string) is not this.null
- def exec2(string): # will be changed to exec in base.py. cant name it exec here
+ def exec2(string
+ ): # will be changed to exec in base.py. cant name it exec here
return Exec(this, string)
-
-
def Exec(this, string):
- if this.Class!='RegExp':
- raise this.MakeError('TypeError', 'RegExp.prototype.exec is not generic!')
+ if this.Class != 'RegExp':
+ raise this.MakeError('TypeError',
+ 'RegExp.prototype.exec is not generic!')
string = string.to_string()
length = len(string)
i = this.get('lastIndex').to_int() if this.glob else 0
@@ -36,11 +35,11 @@ def Exec(this, string):
return this.null
matched = this.match(string.value, i)
i += 1
- start, end = matched.span()#[0]+i-1, matched.span()[1]+i-1
+ start, end = matched.span() #[0]+i-1, matched.span()[1]+i-1
if this.glob:
this.put('lastIndex', this.Js(end))
- arr = this.Js([this.Js(e) for e in [matched.group()]+list(matched.groups())])
+ arr = this.Js(
+ [this.Js(e) for e in [matched.group()] + list(matched.groups())])
arr.put('index', this.Js(start))
arr.put('input', string)
return arr
-
diff --git a/js2py/prototypes/jsstring.py b/js2py/prototypes/jsstring.py
index ebeed399..a313bfb9 100644
--- a/js2py/prototypes/jsstring.py
+++ b/js2py/prototypes/jsstring.py
@@ -4,69 +4,78 @@
DIGS = set('0123456789')
WHITE = u"\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF"
+
def replacement_template(rep, source, span, npar):
"""Takes the replacement template and some info about the match and returns filled template
"""
n = 0
res = ''
- while n < len(rep)-1:
+ while n < len(rep) - 1:
char = rep[n]
- if char=='$':
- if rep[n+1]=='$':
+ if char == '$':
+ if rep[n + 1] == '$':
res += '$'
n += 2
continue
- elif rep[n+1]=='`':
+ elif rep[n + 1] == '&':
+ # replace with matched string
+ res += source[span[0]:span[1]]
+ n += 2
+ continue
+ elif rep[n + 1] == '`':
# replace with string that is BEFORE match
res += source[:span[0]]
n += 2
continue
- elif rep[n+1]=='\'':
+ elif rep[n + 1] == '\'':
# replace with string that is AFTER match
res += source[span[1]:]
n += 2
continue
- elif rep[n+1] in DIGS:
- dig = rep[n+1]
- if n+2len(npar):
- res += '$'+dig
+ if not num or num > len(npar):
+ res += '$' + dig
else:
# None - undefined has to be replaced with ''
- res += npar[num-1] if npar[num-1] else ''
+ res += npar[num - 1] if npar[num - 1] else ''
n += 1 + len(dig)
continue
res += char
n += 1
- if nthat:
+ elif s > that:
return this.Js(1)
return this.Js(0)
def match(regexp):
this.cok()
s = this.to_string()
- r = this.RegExp(regexp) if regexp.Class!='RegExp' else regexp
+ r = this.RegExp(regexp) if regexp.Class != 'RegExp' else regexp
if not r.glob:
return Exec(r, s)
r.put('lastIndex', this.Js(0))
@@ -124,11 +133,11 @@ def match(regexp):
while last_match:
result = Exec(r, s)
if result.is_null():
- last_match=False
+ last_match = False
else:
this_index = r.get('lastIndex').value
- if this_index==previous_last_index:
- r.put('lastIndex', this.Js(this_index+1))
+ if this_index == previous_last_index:
+ r.put('lastIndex', this.Js(this_index + 1))
previous_last_index += 1
else:
previous_last_index = this_index
@@ -138,7 +147,6 @@ def match(regexp):
return this.null
return found
-
def replace(searchValue, replaceValue):
# VERY COMPLICATED. to check again.
this.cok()
@@ -157,16 +165,17 @@ def replace(searchValue, replaceValue):
res += s[last:e.span()[0]]
if func:
# prepare arguments for custom func (replaceValue)
- args = (e.group(),) + e.groups() + (e.span()[1], string)
+ args = (e.group(), ) + e.groups() + (e.span()[1], string)
# convert all types to JS
args = map(this.Js, args)
res += replaceValue(*args).to_string().value
else:
- res += replacement_template(replaceValue, s, e.span(), e.groups())
+ res += replacement_template(replaceValue, s, e.span(),
+ e.groups())
last = e.span()[1]
res += s[last:]
return this.Js(res)
- elif searchValue.Class=='RegExp':
+ elif searchValue.Class == 'RegExp':
e = re.search(searchValue.pat, s)
if e is None:
return string
@@ -175,14 +184,14 @@ def replace(searchValue, replaceValue):
match = e.group()
else:
match = searchValue.to_string().value
- ind = s.find(match)
- if ind==-1:
+ ind = s.find(match)
+ if ind == -1:
return string
span = ind, ind + len(match)
pars = ()
res = s[:span[0]]
if func:
- args = (match,) + pars + (span[1], string)
+ args = (match, ) + pars + (span[1], string)
# convert all types to JS
this_ = this
args = tuple([this_.Js(x) for x in args])
@@ -195,7 +204,7 @@ def replace(searchValue, replaceValue):
def search(regexp):
this.cok()
string = this.to_string()
- if regexp.Class=='RegExp':
+ if regexp.Class == 'RegExp':
rx = regexp
else:
rx = this.RegExp(regexp)
@@ -209,48 +218,46 @@ def slice(start, end):
s = this.to_string()
start = start.to_int()
length = len(s.value)
- end = length if end.is_undefined() else end.to_int()
+ end = length if end.is_undefined() else end.to_int()
#From = max(length+start, 0) if start<0 else min(length, start)
#To = max(length+end, 0) if end<0 else min(length, end)
return s.value[start:end]
-
- def split (separator, limit):
+ def split(separator, limit):
# its a bit different that re.split!
this.cok()
S = this.to_string()
s = S.value
- lim = 2**32-1 if limit.is_undefined() else limit.to_uint32()
+ lim = 2**32 - 1 if limit.is_undefined() else limit.to_uint32()
if not lim:
return []
if separator.is_undefined():
return [s]
len_s = len(s)
res = []
- R = separator if separator.Class=='RegExp' else separator.to_string()
+ R = separator if separator.Class == 'RegExp' else separator.to_string()
if not len_s:
if SplitMatch(s, 0, R) is None:
return [S]
return []
p = q = 0
- while q!=len_s:
+ while q != len_s:
e, cap = SplitMatch(s, q, R)
- if e is None or e==p:
+ if e is None or e == p:
q += 1
continue
res.append(s[p:q])
p = q = e
- if len(res)==lim:
+ if len(res) == lim:
return res
for element in cap:
res.append(this.Js(element))
- if len(res)==lim:
+ if len(res) == lim:
return res
res.append(s[p:])
return res
-
- def substring (start, end):
+ def substring(start, end):
this.cok()
s = this.to_string().value
start = start.to_int()
@@ -264,13 +271,13 @@ def substr(start, length):
#I hate this function and its description in specification
r1 = this.to_string().value
r2 = start.to_int()
- r3 = 10**20 if length.is_undefined() else length.to_int()
+ r3 = 10**20 if length.is_undefined() else length.to_int()
r4 = len(r1)
- r5 = r2 if r2>=0 else max(0, r2+r4)
- r6 = min(max(r3 ,0), r4 - r5)
- if r6<=0:
+ r5 = r2 if r2 >= 0 else max(0, r2 + r4)
+ r6 = min(max(r3, 0), r4 - r5)
+ if r6 <= 0:
return ''
- return r1[r5:r5+r6]
+ return r1[r5:r5 + r6]
def toLowerCase():
this.cok()
@@ -293,15 +300,12 @@ def trim():
return this.Js(this.to_string().value.strip(WHITE))
-
-
def SplitMatch(s, q, R):
# s is Py String to match, q is the py int match start and R is Js RegExp or String.
- if R.Class=='RegExp':
+ if R.Class == 'RegExp':
res = R.match(s, q)
return (None, ()) if res is None else (res.span()[1], res.groups())
# R is just a string
if s[q:].startswith(R.value):
- return q+len(R.value), ()
+ return q + len(R.value), ()
return None, ()
-
diff --git a/js2py/prototypes/jstypedarray.py b/js2py/prototypes/jstypedarray.py
index ba2c33a8..43285aae 100644
--- a/js2py/prototypes/jstypedarray.py
+++ b/js2py/prototypes/jstypedarray.py
@@ -10,6 +10,7 @@
xrange = range
import functools
+
def to_arr(this):
"""Returns Python array from Js array"""
return [this.get(str(e)) for e in xrange(len(this))]
@@ -17,18 +18,20 @@ def to_arr(this):
ARR_STACK = set({})
-class TypedArrayPrototype:
+class TypedArrayPrototype:
def toString():
# this function is wrong
func = this.get('join')
if not func.is_callable():
+
@this.Js
def func():
- return '[object %s]'%this.Class
+ return '[object %s]' % this.Class
+
return func.call(this, ())
- def toLocaleString(locales=None,options=None):
+ def toLocaleString(locales=None, options=None):
array = this.to_object()
arr_len = array.get("length").to_uint32()
# separator is simply a comma ','
@@ -43,7 +46,10 @@ def toLocaleString(locales=None,options=None):
cand = element.to_object()
str_func = element.get('toLocaleString')
if not str_func.is_callable():
- raise this.MakeError('TypeError', 'toLocaleString method of item at index %d is not callable'%i)
+ raise this.MakeError(
+ 'TypeError',
+ 'toLocaleString method of item at index %d is not callable'
+ % i)
res.append(element.callprop('toLocaleString').value)
return ','.join(res)
@@ -51,7 +57,8 @@ def join(separator):
ARR_STACK.add(this)
array = this.to_object()
arr_len = array.get("length").to_uint32()
- separator = ',' if separator.is_undefined() else separator.to_string().value
+ separator = ',' if separator.is_undefined() else separator.to_string(
+ ).value
elems = []
for e in xrange(arr_len):
elem = array.get(str(e))
@@ -59,13 +66,14 @@ def join(separator):
s = ''
else:
s = elem.to_string().value
- elems.append(s if not (elem.is_undefined() or elem.is_null()) else '')
- res = separator.join(elems)
+ elems.append(
+ s if not (elem.is_undefined() or elem.is_null()) else '')
+ res = separator.join(elems)
ARR_STACK.remove(this)
return res
def reverse():
- array = this.to_object() # my own algorithm
+ array = this.to_object() # my own algorithm
vals = to_arr(array)
has_props = [array.has_property(str(e)) for e in xrange(len(array))]
vals.reverse()
@@ -77,16 +85,18 @@ def reverse():
array.delete(str(i))
return array
- def slice(start, end): # todo check
+ def slice(start, end): # todo check
array = this.to_object()
arr_len = array.get("length").to_uint32()
relative_start = start.to_int()
- k = max((arr_len + relative_start), 0) if relative_start<0 else min(relative_start, arr_len)
+ k = max((arr_len + relative_start), 0) if relative_start < 0 else min(
+ relative_start, arr_len)
relative_end = arr_len if end.is_undefined() else end.to_int()
- final = max((arr_len + relative_end), 0) if relative_end<0 else min(relative_end, arr_len)
+ final = max((arr_len + relative_end), 0) if relative_end < 0 else min(
+ relative_end, arr_len)
res = []
n = 0
- while k1:
+ if len(arguments) > 1:
n = arguments[1].to_int()
else:
n = 0
@@ -146,12 +156,12 @@ def lastIndexOf(searchElement):
arr_len = array.get("length").to_uint32()
if arr_len == 0:
return -1
- if len(arguments)>1:
+ if len(arguments) > 1:
n = arguments[1].to_int()
else:
n = arr_len - 1
if n >= 0:
- k = min(n, arr_len-1)
+ k = min(n, arr_len - 1)
else:
k = arr_len - abs(n)
while k >= 0:
@@ -169,10 +179,11 @@ def every(callbackfn):
raise this.MakeError('TypeError', 'callbackfn must be a function')
T = arguments[1]
k = 0
- while k1: # initial value present
+ if len(arguments) > 1: # initial value present
accumulator = arguments[1]
else:
kPresent = False
- while not kPresent and k1: # initial value present
+ if len(arguments) > 1: # initial value present
accumulator = arguments[1]
else:
kPresent = False
- while not kPresent and k>=0:
+ while not kPresent and k >= 0:
kPresent = array.has_property(str(k))
if kPresent:
accumulator = array.get(str(k))
k -= 1
if not kPresent:
- raise this.MakeError('TypeError', 'Reduce of empty array with no initial value')
- while k>=0:
+ raise this.MakeError(
+ 'TypeError', 'Reduce of empty array with no initial value')
+ while k >= 0:
if array.has_property(str(k)):
kValue = array.get(str(k))
- accumulator = callbackfn.call(this.undefined, (accumulator, kValue, this.Js(k), array))
+ accumulator = callbackfn.call(
+ this.undefined, (accumulator, kValue, this.Js(k), array))
k -= 1
return accumulator
+
def sort_compare(a, b, comp):
if a is None:
if b is None:
@@ -313,12 +337,8 @@ def sort_compare(a, b, comp):
res = comp.call(a.undefined, (a, b))
return res.to_int()
x, y = a.to_string(), b.to_string()
- if xy:
+ elif x > y:
return 1
return 0
-
-
-
-
diff --git a/js2py/py_node_modules/__init__.py b/js2py/py_node_modules/__init__.py
new file mode 100644
index 00000000..03b73026
--- /dev/null
+++ b/js2py/py_node_modules/__init__.py
@@ -0,0 +1 @@
+"""this package contains all the npm modules translated by js2py via node import"""
\ No newline at end of file
diff --git a/js2py/pyjs.py b/js2py/pyjs.py
index db49f4f7..98e106a0 100644
--- a/js2py/pyjs.py
+++ b/js2py/pyjs.py
@@ -21,27 +21,60 @@
from .prototypes.jsjson import JSON
from .host.console import console
from .host.jseval import Eval
-from .host.jsfunctions import parseFloat, parseInt, isFinite, isNaN
+from .host.jsfunctions import parseFloat, parseInt, isFinite, \
+ isNaN, escape, unescape, encodeURI, decodeURI, encodeURIComponent, decodeURIComponent
# Now we have all the necessary items to create global environment for script
-__all__ = ['Js', 'PyJsComma', 'PyJsStrictEq', 'PyJsStrictNeq',
- 'PyJsException', 'PyJsBshift', 'Scope', 'PyExceptionToJs',
- 'JsToPyException', 'JS_BUILTINS', 'appengine', 'set_global_object',
- 'JsRegExp', 'PyJsException', 'PyExceptionToJs', 'JsToPyException', 'PyJsSwitchException']
-
+__all__ = [
+ 'Js', 'PyJsComma', 'PyJsStrictEq', 'PyJsStrictNeq', 'PyJsException',
+ 'PyJsBshift', 'Scope', 'PyExceptionToJs', 'JsToPyException', 'JS_BUILTINS',
+ 'appengine', 'set_global_object', 'JsRegExp', 'PyJsException',
+ 'PyExceptionToJs', 'JsToPyException', 'PyJsSwitchException'
+]
# these were defined in base.py
-builtins = ('true','false','null','undefined','Infinity',
- 'NaN', 'console', 'String', 'Number', 'Boolean', 'RegExp',
- 'Math', 'Date', 'Object', 'Function', 'Array',
- 'Int8Array', 'Uint8Array', 'Uint8ClampedArray',
- 'Int16Array','Uint16Array',
- 'Int32Array', 'Uint32Array',
- 'Float32Array', 'Float64Array',
- 'ArrayBuffer',
- 'parseFloat', 'parseInt', 'isFinite', 'isNaN')
- #Array, Function, JSON, Error is done later :)
- # also some built in functions like eval...
+builtins = (
+ 'true',
+ 'false',
+ 'null',
+ 'undefined',
+ 'Infinity',
+ 'NaN',
+ 'console',
+ 'String',
+ 'Number',
+ 'Boolean',
+ 'RegExp',
+ 'Math',
+ 'Date',
+ 'Object',
+ 'Function',
+ 'Array',
+ 'Int8Array',
+ 'Uint8Array',
+ 'Uint8ClampedArray',
+ 'Int16Array',
+ 'Uint16Array',
+ 'Int32Array',
+ 'Uint32Array',
+ 'Float32Array',
+ 'Float64Array',
+ 'ArrayBuffer',
+ 'parseFloat',
+ 'parseInt',
+ 'isFinite',
+ 'isNaN',
+ 'escape',
+ 'unescape',
+ 'encodeURI',
+ 'decodeURI',
+ 'encodeURIComponent',
+ 'decodeURIComponent',
+)
+
+#Array, Function, JSON, Error is done later :)
+# also some built in functions like eval...
+
def set_global_object(obj):
obj.IS_CHILD_SCOPE = False
@@ -52,7 +85,9 @@ def set_global_object(obj):
# make this available
obj.register('this')
obj.put('this', this)
-
+ # also add window and set it to be a global object for compatibility
+ obj.register('window')
+ obj.put('window', this)
scope = dict(zip(builtins, [globals()[e] for e in builtins]))
@@ -62,5 +97,4 @@ def set_global_object(obj):
#add eval
scope['eval'] = Eval
scope['JSON'] = JSON
-JS_BUILTINS = dict((k,v) for k,v in scope.items())
-
+JS_BUILTINS = dict((k, v) for k, v in scope.items())
diff --git a/js2py/test_internals.py b/js2py/test_internals.py
deleted file mode 100644
index eade6003..00000000
--- a/js2py/test_internals.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from internals import byte_trans
-
-byte_trans.main()
\ No newline at end of file
diff --git a/js2py/translators/__init__.py b/js2py/translators/__init__.py
index 48acaa1a..7a1001fd 100644
--- a/js2py/translators/__init__.py
+++ b/js2py/translators/__init__.py
@@ -18,8 +18,10 @@
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
-__all__ = ['PyJsParser', 'Node', 'WrappingNode', 'node_to_dict', 'parse', 'translate_js', 'translate', 'syntax_tree_translate',
- 'DEFAULT_HEADER']
+__all__ = [
+ 'PyJsParser', 'Node', 'WrappingNode', 'node_to_dict', 'parse',
+ 'translate_js', 'translate', 'syntax_tree_translate', 'DEFAULT_HEADER'
+]
__author__ = 'Piotr Dabkowski'
__version__ = '2.2.0'
from pyjsparser import PyJsParser
@@ -34,5 +36,3 @@ def parse(javascript_code):
Same as PyJsParser().parse For your convenience :) """
p = PyJsParser()
return p.parse(javascript_code)
-
-
diff --git a/js2py/translators/friendly_nodes.py b/js2py/translators/friendly_nodes.py
index 835cc827..370f85d8 100644
--- a/js2py/translators/friendly_nodes.py
+++ b/js2py/translators/friendly_nodes.py
@@ -10,14 +10,19 @@
REGEXP_CONVERTER = PyJsParser()
+
def to_hex(s):
- return binascii.hexlify(s.encode('utf8')).decode('utf8') # fucking python 3, I hate it so much
- # wtf was wrong with s.encode('hex') ???
+ return binascii.hexlify(s.encode('utf8')).decode(
+ 'utf8') # fucking python 3, I hate it so much
+
+
+ # wtf was wrong with s.encode('hex') ???
def indent(lines, ind=4):
- return ind*' '+lines.replace('\n', '\n'+ind*' ').rstrip(' ')
+ return ind * ' ' + lines.replace('\n', '\n' + ind * ' ').rstrip(' ')
+
def inject_before_lval(source, lval, code):
- if source.count(lval)>1:
+ if source.count(lval) > 1:
print()
print(lval)
raise RuntimeError('To many lvals (%s)' % lval)
@@ -29,39 +34,44 @@ def inject_before_lval(source, lval, code):
end = source.index(lval)
inj = source.rfind('\n', 0, end)
ind = inj
- while source[ind+1]==' ':
- ind+=1
+ while source[ind + 1] == ' ':
+ ind += 1
ind -= inj
- return source[:inj+1]+ indent(code, ind) + source[inj+1:]
+ return source[:inj + 1] + indent(code, ind) + source[inj + 1:]
def get_continue_label(label):
- return CONTINUE_LABEL%to_hex(label)
+ return CONTINUE_LABEL % to_hex(label)
+
def get_break_label(label):
- return BREAK_LABEL%to_hex(label)
+ return BREAK_LABEL % to_hex(label)
def is_valid_py_name(name):
try:
- compile(name+' = 11', 'a','exec')
+ compile(name + ' = 11', 'a', 'exec')
except:
return False
return True
+
def indent(lines, ind=4):
- return ind*' '+lines.replace('\n', '\n'+ind*' ').rstrip(' ')
+ return ind * ' ' + lines.replace('\n', '\n' + ind * ' ').rstrip(' ')
+
def compose_regex(val):
reg, flags = val
#reg = REGEXP_CONVERTER._unescape_string(reg)
return u'/%s/%s' % (reg, flags)
+
def float_repr(f):
- if int(f)==f:
+ if int(f) == f:
return repr(int(f))
return repr(f)
+
def argsplit(args, sep=','):
"""used to split JS args (it is not that simple as it seems because
sep can be inside brackets).
@@ -69,238 +79,275 @@ def argsplit(args, sep=','):
pass args *without* brackets!
Used also to parse array and object elements, and more"""
- parsed_len = 0
+ parsed_len = 0
last = 0
splits = []
for e in bracket_split(args, brackets=['()', '[]', '{}']):
if e[0] not in ('(', '[', '{'):
for i, char in enumerate(e):
- if char==sep:
- splits.append(args[last:parsed_len+i])
+ if char == sep:
+ splits.append(args[last:parsed_len + i])
last = parsed_len + i + 1
parsed_len += len(e)
splits.append(args[last:])
return splits
-def bracket_split(source, brackets=('()','{}','[]'), strip=False):
+def bracket_split(source, brackets=('()', '{}', '[]'), strip=False):
"""DOES NOT RETURN EMPTY STRINGS (can only return empty bracket content if strip=True)"""
starts = [e[0] for e in brackets]
in_bracket = 0
n = 0
last = 0
- while n='+b+')'
+ return '(' + a + '>=' + b + ')'
+
def js_gt(a, b):
- return '('+a+'>'+b+')'
+ return '(' + a + '>' + b + ')'
+
def js_in(a, b):
- return b+'.contains('+a+')'
+ return b + '.contains(' + a + ')'
+
def js_instanceof(a, b):
- return a+'.instanceof('+b+')'
+ return a + '.instanceof(' + b + ')'
+
def js_lshift(a, b):
- return '('+a+'<<'+b+')'
+ return '(' + a + '<<' + b + ')'
+
def js_rshift(a, b):
- return '('+a+'>>'+b+')'
+ return '(' + a + '>>' + b + ')'
+
def js_shit(a, b):
- return 'PyJsBshift('+a+','+b+')'
+ return 'PyJsBshift(' + a + ',' + b + ')'
+
+
+def js_add(
+ a,
+ b): # To simplify later process of converting unary operators + and ++
+ return '(%s+%s)' % (a, b)
-def js_add(a, b): # To simplify later process of converting unary operators + and ++
- return '(%s+%s)'%(a, b)
def js_sub(a, b): # To simplify
- return '(%s-%s)'%(a, b)
+ return '(%s-%s)' % (a, b)
+
def js_mul(a, b):
- return '('+a+'*'+b+')'
+ return '(' + a + '*' + b + ')'
+
def js_div(a, b):
- return '('+a+'/'+b+')'
+ return '(' + a + '/' + b + ')'
+
def js_mod(a, b):
- return '('+a+'%'+b+')'
+ return '(' + a + '%' + b + ')'
+
def js_typeof(a):
- cand = list(bracket_split(a, ('()',)))
- if len(cand)==2 and cand[0]=='var.get':
- return cand[0]+cand[1][:-1]+',throw=False).typeof()'
- return a+'.typeof()'
+ cand = list(bracket_split(a, ('()', )))
+ if len(cand) == 2 and cand[0] == 'var.get':
+ return cand[0] + cand[1][:-1] + ',throw=False).typeof()'
+ return a + '.typeof()'
+
def js_void(a):
# eval and return undefined
return 'PyJsComma(%s, Js(None))' % a
+
def js_new(a):
- cands = list(bracket_split(a, ('()',)))
+ cands = list(bracket_split(a, ('()', )))
lim = len(cands)
if lim < 2:
return a + '.create()'
n = 0
while n < lim:
c = cands[n]
- if c[0]=='(':
- if cands[n-1].endswith('.get') and n+1>=lim: # last get operation.
+ if c[0] == '(':
+ if cands[n - 1].endswith(
+ '.get') and n + 1 >= lim: # last get operation.
return a + '.create()'
- elif cands[n-1][0]=='(':
- return ''.join(cands[:n])+'.create' + c + ''.join(cands[n+1:])
- elif cands[n-1]=='.callprop':
- beg = ''.join(cands[:n-1])
- args = argsplit(c[1:-1],',')
- prop = args[0]
- new_args = ','.join(args[1:])
- create = '.get(%s).create(%s)' % (prop, new_args)
- return beg + create + ''.join(cands[n+1:])
- n+=1
+ elif cands[n - 1][0] == '(':
+ return ''.join(cands[:n]) + '.create' + c + ''.join(
+ cands[n + 1:])
+ elif cands[n - 1] == '.callprop':
+ beg = ''.join(cands[:n - 1])
+ args = argsplit(c[1:-1], ',')
+ prop = args[0]
+ new_args = ','.join(args[1:])
+ create = '.get(%s).create(%s)' % (prop, new_args)
+ return beg + create + ''.join(cands[n + 1:])
+ n += 1
return a + '.create()'
def js_delete(a):
#replace last get with delete.
c = list(bracket_split(a, ['()']))
- beg, arglist = ''.join(c[:-1]).strip(), c[-1].strip() #strips just to make sure... I will remove it later
- if beg[-4:]!='.get':
+ beg, arglist = ''.join(c[:-1]).strip(), c[-1].strip(
+ ) #strips just to make sure... I will remove it later
+ if beg[-4:] != '.get':
print(a)
raise SyntaxError('Invalid delete operation')
- return beg[:-3]+'delete'+arglist
+ return beg[:-3] + 'delete' + arglist
def js_neg(a):
- return '(-'+a+')'
+ return '(-' + a + ')'
+
def js_pos(a):
- return '(+'+a+')'
+ return '(+' + a + ')'
+
def js_inv(a):
- return '(~'+a+')'
+ return '(~' + a + ')'
+
def js_not(a):
- return a+'.neg()'
+ return a + '.neg()'
+
def js_postfix(a, inc, post):
- bra = list(bracket_split(a, ('()',)))
+ bra = list(bracket_split(a, ('()', )))
meth = bra[-2]
if not meth.endswith('get'):
raise SyntaxError('Invalid ++ or -- operation.')
bra[-2] = bra[-2][:-3] + 'put'
- bra[-1] = '(%s,Js(%s.to_number())%sJs(1))' % (bra[-1][1:-1], a, '+' if inc else '-')
+ bra[-1] = '(%s,Js(%s.to_number())%sJs(1))' % (bra[-1][1:-1], a,
+ '+' if inc else '-')
res = ''.join(bra)
return res if not post else '(%s%sJs(1))' % (res, '-' if inc else '+')
+
def js_pre_inc(a):
return js_postfix(a, True, False)
+
def js_post_inc(a):
return js_postfix(a, True, True)
+
def js_pre_dec(a):
return js_postfix(a, False, False)
+
def js_post_dec(a):
return js_postfix(a, False, True)
-
CONTINUE_LABEL = 'JS_CONTINUE_LABEL_%s'
BREAK_LABEL = 'JS_BREAK_LABEL_%s'
PREPARE = '''HOLDER = var.own.get(NAME)\nvar.force_own_put(NAME, PyExceptionToJs(PyJsTempException))\n'''
RESTORE = '''if HOLDER is not None:\n var.own[NAME] = HOLDER\nelse:\n del var.own[NAME]\ndel HOLDER\n'''
TRY_CATCH = '''%stry:\nBLOCKfinally:\n%s''' % (PREPARE, indent(RESTORE))
-
-
OR = {'||': js_or}
AND = {'&&': js_and}
BOR = {'|': js_bor}
BXOR = {'^': js_bxor}
BAND = {'&': js_band}
-EQS = {'===': js_strict_eq,
- '!==': js_strict_neq,
- '==': js_abstract_eq, # we need == and != too. Read a note above method
- '!=': js_abstract_neq}
+EQS = {
+ '===': js_strict_eq,
+ '!==': js_strict_neq,
+ '==': js_abstract_eq, # we need == and != too. Read a note above method
+ '!=': js_abstract_neq
+}
#Since JS does not have chained comparisons we need to implement all cmp methods.
-COMPS = {'<': js_lt,
- '<=': js_le,
- '>=': js_ge,
- '>': js_gt,
- 'instanceof': js_instanceof, #todo change to validitate
- 'in': js_in}
-
-BSHIFTS = {'<<': js_lshift,
- '>>': js_rshift,
- '>>>': js_shit}
-
-ADDS = {'+': js_add,
- '-': js_sub}
-
-MULTS = {'*': js_mul,
- '/': js_div,
- '%': js_mod}
+COMPS = {
+ '<': js_lt,
+ '<=': js_le,
+ '>=': js_ge,
+ '>': js_gt,
+ 'instanceof': js_instanceof, #todo change to validitate
+ 'in': js_in
+}
+
+BSHIFTS = {'<<': js_lshift, '>>': js_rshift, '>>>': js_shit}
+
+ADDS = {'+': js_add, '-': js_sub}
+
+MULTS = {'*': js_mul, '/': js_div, '%': js_mod}
BINARY = {}
BINARY.update(ADDS)
BINARY.update(MULTS)
@@ -314,14 +361,15 @@ def js_post_dec(a):
BINARY.update(OR)
#Note they dont contain ++ and -- methods because they both have 2 different methods
# correct method will be found automatically in translate function
-UNARY = {'typeof': js_typeof,
- 'void': js_void,
- 'new': js_new,
- 'delete': js_delete,
- '!': js_not,
- '-': js_neg,
- '+': js_pos,
- '~': js_inv,
- '++': None,
- '--': None
- }
\ No newline at end of file
+UNARY = {
+ 'typeof': js_typeof,
+ 'void': js_void,
+ 'new': js_new,
+ 'delete': js_delete,
+ '!': js_not,
+ '-': js_neg,
+ '+': js_pos,
+ '~': js_inv,
+ '++': None,
+ '--': None
+}
diff --git a/js2py/translators/jsregexps.py b/js2py/translators/jsregexps.py
index 7a976cc3..235d67c7 100644
--- a/js2py/translators/jsregexps.py
+++ b/js2py/translators/jsregexps.py
@@ -2,22 +2,28 @@
REGEXP_SPECIAL_SINGLE = {'\\', '^', '$', '*', '+', '?', '.'}
-NOT_PATTERN_CHARS = {'^', '$', '\\', '.', '*', '+', '?', '(', ')', '[', ']', '|'} # what about '{', '}', ???
+NOT_PATTERN_CHARS = {
+ '^', '$', '\\', '.', '*', '+', '?', '(', ')', '[', ']', '|'
+} # what about '{', '}', ???
CHAR_CLASS_ESCAPE = {'d', 'D', 's', 'S', 'w', 'W'}
CONTROL_ESCAPE_CHARS = {'f', 'n', 'r', 't', 'v'}
-CONTROL_LETTERS = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
- 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
- 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}
+CONTROL_LETTERS = {
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D',
+ 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
+ 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
+}
+
def SpecialChar(char):
- return {'type': 'SpecialChar',
- 'content': char}
+ return {'type': 'SpecialChar', 'content': char}
def isPatternCharacter(char):
return char not in NOT_PATTERN_CHARS
+
class JsRegExpParser:
def __init__(self, source, flags):
self.source = source
@@ -27,11 +33,9 @@ def __init__(self, source, flags):
self.lineNumber = 0
self.lineStart = 0
-
def parsePattern(self):
'''Perform sctring escape - for regexp literals'''
- return {'type': 'Pattern',
- 'contents': self.parseDisjunction()}
+ return {'type': 'Pattern', 'contents': self.parseDisjunction()}
def parseDisjunction(self):
alternatives = []
@@ -41,29 +45,28 @@ def parseDisjunction(self):
self.expect_character('|')
else:
break
- return {'type': 'Disjunction',
- 'contents': alternatives}
+ return {'type': 'Disjunction', 'contents': alternatives}
def isEOF(self):
- if self.index>=self.length:
+ if self.index >= self.length:
return True
return False
def expect_character(self, character):
- if self.source[self.index]!=character:
+ if self.source[self.index] != character:
self.throwUnexpected(character)
self.index += 1
def parseAlternative(self):
contents = []
- while not self.isEOF() and self.source[self.index]!='|':
+ while not self.isEOF() and self.source[self.index] != '|':
contents.append(self.parseTerm())
- return {'type': 'Alternative',
- 'contents': contents}
+ return {'type': 'Alternative', 'contents': contents}
def follows(self, chars):
for i, c in enumerate(chars):
- if self.index+i>=self.length or self.source[self.index+i] != c:
+ if self.index + i >= self.length or self.source[self.index +
+ i] != c:
return False
return True
@@ -72,9 +75,10 @@ def parseTerm(self):
if assertion:
return assertion
else:
- return {'type': 'Term',
- 'contents': self.parseAtom()} # quantifier will go inside atom!
-
+ return {
+ 'type': 'Term',
+ 'contents': self.parseAtom()
+ } # quantifier will go inside atom!
def parseAssertion(self):
if self.follows('$'):
@@ -93,24 +97,19 @@ def parseAssertion(self):
self.index += 3
dis = self.parseDisjunction()
self.expect_character(')')
- content = {'type': 'Lookached',
- 'contents': dis,
- 'negated': False}
+ content = {'type': 'Lookached', 'contents': dis, 'negated': False}
elif self.follows('(?!'):
self.index += 3
dis = self.parseDisjunction()
self.expect_character(')')
- content = {'type': 'Lookached',
- 'contents': dis,
- 'negated': True}
+ content = {'type': 'Lookached', 'contents': dis, 'negated': True}
else:
return None
- return {'type': 'Assertion',
- 'content': content}
+ return {'type': 'Assertion', 'content': content}
def parseAtom(self):
if self.follows('.'):
- content = SpecialChar('.')
+ content = SpecialChar('.')
self.index += 1
elif self.follows('\\'):
self.index += 1
@@ -133,9 +132,7 @@ def parseAtom(self):
else:
return None
quantifier = self.parseQuantifier()
- return {'type': 'Atom',
- 'content': content,
- 'quantifier': quantifier}
+ return {'type': 'Atom', 'content': content, 'quantifier': quantifier}
def parseQuantifier(self):
prefix = self.parseQuantifierPrefix()
@@ -145,9 +142,7 @@ def parseQuantifier(self):
if self.follows('?'):
self.index += 1
greedy = False
- return {'type': 'Quantifier',
- 'contents': prefix,
- 'greedy': greedy}
+ return {'type': 'Quantifier', 'contents': prefix, 'greedy': greedy}
def parseQuantifierPrefix(self):
if self.isEOF():
@@ -161,7 +156,9 @@ def parseQuantifierPrefix(self):
elif self.follows('*'):
content = '*'
self.index += 1
- elif self.follows('{'): # try matching otherwise return None and restore the state
+ elif self.follows(
+ '{'
+ ): # try matching otherwise return None and restore the state
i = self.index
self.index += 1
digs1 = self.scanDecimalDigs()
@@ -186,10 +183,9 @@ def parseQuantifierPrefix(self):
return None
return content
-
def parseAtomEscape(self):
ch = self.source[self.index]
- if isDecimalDigit(ch) and ch!=0:
+ if isDecimalDigit(ch) and ch != 0:
digs = self.scanDecimalDigs()
elif ch in CHAR_CLASS_ESCAPE:
self.index += 1
@@ -201,10 +197,9 @@ def parseCharacterEscape(self):
ch = self.source[self.index]
if ch in CONTROL_ESCAPE_CHARS:
return SpecialChar('\\' + ch)
- if ch=='c':
+ if ch == 'c':
'ok, fuck this shit.'
-
def scanDecimalDigs(self):
s = self.index
while not self.isEOF() and isDecimalDigit(self.source[self.index]):
@@ -212,8 +207,5 @@ def scanDecimalDigs(self):
return self.source[s:self.index]
-
-
-
a = JsRegExpParser('a(?=x)', '')
-print(a.parsePattern())
\ No newline at end of file
+print(a.parsePattern())
diff --git a/js2py/translators/translating_nodes.py b/js2py/translators/translating_nodes.py
index e63539a5..4e2b5760 100644
--- a/js2py/translators/translating_nodes.py
+++ b/js2py/translators/translating_nodes.py
@@ -11,39 +11,50 @@
# number of characters above which expression will be split to multiple lines in order to avoid python parser stack overflow
# still experimental so I suggest to set it to 400 in order to avoid common errors
# set it to smaller value only if you have problems with parser stack overflow
-LINE_LEN_LIMIT = 400 # 200 # or any other value - the larger the smaller probability of errors :)
+LINE_LEN_LIMIT = 400 # 200 # or any other value - the larger the smaller probability of errors :)
-class ForController:
+
+class LoopController:
def __init__(self):
- self.inside = [False]
- self.update = ''
+ self.update = [""]
+ self.label_to_update_idx = {}
+
+ def enter(self, update=""):
+ self.update.append(update)
+
+ def leave(self):
+ self.update.pop()
- def enter_for(self, update):
- self.inside.append(True)
- self.update = update
+ def get_update(self, label=None):
+ if label is None:
+ return self.update[-1]
+ if label not in self.label_to_update_idx:
+ raise SyntaxError("Undefined label %s" % label)
+ if self.label_to_update_idx[label] >= len(self.update):
+ raise SyntaxError("%s is not a iteration statement label?" % label)
+ return self.update[self.label_to_update_idx[label]]
- def leave_for(self):
- self.inside.pop()
+ def register_label(self, label):
+ if label in self.label_to_update_idx:
+ raise SyntaxError("label %s already used")
+ self.label_to_update_idx[label] = len(self.update)
- def enter_other(self):
- self.inside.append(False)
+ def deregister_label(self, label):
+ del self.label_to_update_idx[label]
- def leave_other(self):
- self.inside.pop()
- def is_inside(self):
- return self.inside[-1]
class InlineStack:
NAME = 'PyJs_%s_%d_'
+
def __init__(self):
self.reps = {}
self.names = []
def inject_inlines(self, source):
- for lval in self.names: # first in first out! Its important by the way
+ for lval in self.names: # first in first out! Its important by the way
source = inject_before_lval(source, lval, self.reps[lval])
return source
@@ -77,26 +88,25 @@ def define(self, name, code):
self.register(name)
def get_code(self):
- code = 'var.registers([%s])\n' % ', '.join(repr(e) for e in self.to_register)
+ code = 'var.registers([%s])\n' % ', '.join(
+ repr(e) for e in self.to_register)
for name, func_code in six.iteritems(self.to_define):
code += func_code
return code
-
def clean_stacks():
- global Context, inline_stack
+ global Context, inline_stack, loop_controller
Context = ContextStack()
inline_stack = InlineStack()
-
-
+ loop_controller = LoopController()
def to_key(literal_or_identifier):
''' returns string representation of this object'''
- if literal_or_identifier['type']=='Identifier':
+ if literal_or_identifier['type'] == 'Identifier':
return literal_or_identifier['name']
- elif literal_or_identifier['type']=='Literal':
+ elif literal_or_identifier['type'] == 'Literal':
k = literal_or_identifier['value']
if isinstance(k, float):
return unicode(float_repr(k))
@@ -109,6 +119,14 @@ def to_key(literal_or_identifier):
else:
return unicode(k)
+def is_iteration_statement(cand):
+ if not isinstance(cand, dict):
+ # Multiple statements.
+ return False
+ return cand.get("type", "?") in {"ForStatement", "ForInStatement", "WhileStatement", "DoWhileStatement"}
+
+
+
def trans(ele, standard=False):
"""Translates esprima syntax tree to python by delegating to appropriate translating node"""
try:
@@ -116,7 +134,8 @@ def trans(ele, standard=False):
if not node:
raise NotImplementedError('%s is not supported!' % ele['type'])
if standard:
- node = node.__dict__['standard'] if 'standard' in node.__dict__ else node
+ node = node.__dict__[
+ 'standard'] if 'standard' in node.__dict__ else node
return node(**ele)
except:
#print ele
@@ -127,46 +146,47 @@ def limited(func):
'''Decorator limiting resulting line length in order to avoid python parser stack overflow -
If expression longer than LINE_LEN_LIMIT characters then it will be moved to upper line
USE ONLY ON EXPRESSIONS!!! '''
+
def f(standard=False, **args):
- insert_pos = len(inline_stack.names) # in case line is longer than limit we will have to insert the lval at current position
- # this is because calling func will change inline_stack.
- # we cant use inline_stack.require here because we dont know whether line overflows yet
+ insert_pos = len(
+ inline_stack.names
+ ) # in case line is longer than limit we will have to insert the lval at current position
+ # this is because calling func will change inline_stack.
+ # we cant use inline_stack.require here because we dont know whether line overflows yet
res = func(**args)
- if len(res)>LINE_LEN_LIMIT:
+ if len(res) > LINE_LEN_LIMIT:
name = inline_stack.require('LONG')
inline_stack.names.pop()
inline_stack.names.insert(insert_pos, name)
res = 'def %s(var=var):\n return %s\n' % (name, res)
inline_stack.define(name, res)
- return name+'()'
+ return name + '()'
else:
return res
+
f.__dict__['standard'] = func
return f
-
-
-
-
# ==== IDENTIFIERS AND LITERALS =======
-
inf = float('inf')
def Literal(type, value, raw, regex=None):
- if regex: # regex
+ if regex: # regex
return 'JsRegExp(%s)' % repr(compose_regex(value))
elif value is None: # null
return 'var.get(u"null")'
# Todo template
# String, Bool, Float
- return 'Js(%s)' % repr(value) if value!=inf else 'Js(float("inf"))'
+ return 'Js(%s)' % repr(value) if value != inf else 'Js(float("inf"))'
+
def Identifier(type, name):
return 'var.get(%s)' % repr(name)
+
@limited
def MemberExpression(type, computed, object, property):
far_left = trans(object)
@@ -174,9 +194,9 @@ def MemberExpression(type, computed, object, property):
# may be literal which is the same in every case so we can save some time on conversion
if property['type'] == 'Literal':
prop = repr(to_key(property))
- else: # worst case
+ else: # worst case
prop = trans(property)
- else: # always the same since not computed (obj.prop accessor)
+ else: # always the same since not computed (obj.prop accessor)
prop = repr(to_key(property))
return far_left + '.get(%s)' % prop
@@ -184,26 +204,27 @@ def MemberExpression(type, computed, object, property):
def ThisExpression(type):
return 'var.get(u"this")'
+
@limited
def CallExpression(type, callee, arguments):
arguments = [trans(e) for e in arguments]
- if callee['type']=='MemberExpression':
+ if callee['type'] == 'MemberExpression':
far_left = trans(callee['object'])
if callee['computed']: # obj[prop] type accessor
# may be literal which is the same in every case so we can save some time on conversion
if callee['property']['type'] == 'Literal':
prop = repr(to_key(callee['property']))
- else: # worst case
- prop = trans(callee['property']) # its not a string literal! so no repr
- else: # always the same since not computed (obj.prop accessor)
+ else: # worst case
+ prop = trans(
+ callee['property']) # its not a string literal! so no repr
+ else: # always the same since not computed (obj.prop accessor)
prop = repr(to_key(callee['property']))
arguments.insert(0, prop)
return far_left + '.callprop(%s)' % ', '.join(arguments)
- else: # standard call
+ else: # standard call
return trans(callee) + '(%s)' % ', '.join(arguments)
-
# ========== ARRAYS ============
@@ -211,33 +232,46 @@ def ArrayExpression(type, elements): # todo fix null inside problem
return 'Js([%s])' % ', '.join(trans(e) if e else 'None' for e in elements)
-
# ========== OBJECTS =============
+
def ObjectExpression(type, properties):
- name = inline_stack.require('Object')
+ name = None
elems = []
after = ''
for p in properties:
- if p['kind']=='init':
+ if p['kind'] == 'init':
elems.append('%s:%s' % Property(**p))
- elif p['kind']=='set':
- k, setter = Property(**p) # setter is just a lval referring to that function, it will be defined in InlineStack automatically
- after += '%s.define_own_property(%s, {"set":%s, "configurable":True, "enumerable":True})\n' % (name, k, setter)
- elif p['kind']=='get':
- k, getter = Property(**p)
- after += '%s.define_own_property(%s, {"get":%s, "configurable":True, "enumerable":True})\n' % (name, k, getter)
else:
- raise RuntimeError('Unexpected object propery kind')
- obj = '%s = Js({%s})\n' % (name, ','.join(elems))
- inline_stack.define(name, obj+after)
- return name
-
+ if name is None:
+ name = inline_stack.require('Object')
+ if p['kind'] == 'set':
+ k, setter = Property(
+ **p
+ ) # setter is just a lval referring to that function, it will be defined in InlineStack automatically
+ after += '%s.define_own_property(%s, {"set":%s, "configurable":True, "enumerable":True})\n' % (
+ name, k, setter)
+ elif p['kind'] == 'get':
+ k, getter = Property(**p)
+ after += '%s.define_own_property(%s, {"get":%s, "configurable":True, "enumerable":True})\n' % (
+ name, k, getter)
+ else:
+ raise RuntimeError('Unexpected object propery kind')
+ definition = 'Js({%s})' % ','.join(elems)
+ if name is None:
+ return definition
+ body = '%s = %s\n' % (name, definition)
+ body += after
+ body += 'return %s\n' % name
+ code = 'def %s():\n%s' % (name, indent(body))
+ inline_stack.define(name, code)
+ return name + '()'
def Property(type, kind, key, computed, value, method, shorthand):
if shorthand or computed:
- raise NotImplementedError('Shorthand and Computed properties not implemented!')
+ raise NotImplementedError(
+ 'Shorthand and Computed properties not implemented!')
k = to_key(key)
if k is None:
raise SyntaxError('Invalid key in dictionary! Or bug in Js2Py')
@@ -250,72 +284,92 @@ def Property(type, kind, key, computed, value, method, shorthand):
@limited
def UnaryExpression(type, operator, argument, prefix):
- a = trans(argument, standard=True) # unary involve some complex operations so we cant use line shorteners here
- if operator=='delete':
+ a = trans(
+ argument, standard=True
+ ) # unary involve some complex operations so we cant use line shorteners here
+ if operator == 'delete':
if argument['type'] in ('Identifier', 'MemberExpression'):
# means that operation is valid
return js_delete(a)
- return 'PyJsComma(%s, Js(True))' % a # otherwise not valid, just perform expression and return true.
- elif operator=='typeof':
+ return 'PyJsComma(%s, Js(True))' % a # otherwise not valid, just perform expression and return true.
+ elif operator == 'typeof':
return js_typeof(a)
return UNARY[operator](a)
+
@limited
def BinaryExpression(type, operator, left, right):
a = trans(left)
b = trans(right)
# delegate to our friends
- return BINARY[operator](a,b)
+ return BINARY[operator](a, b)
+
@limited
def UpdateExpression(type, operator, argument, prefix):
- a = trans(argument, standard=True) # also complex operation involving parsing of the result so no line length reducing here
- return js_postfix(a, operator=='++', not prefix)
+ a = trans(
+ argument, standard=True
+ ) # also complex operation involving parsing of the result so no line length reducing here
+ return js_postfix(a, operator == '++', not prefix)
+
@limited
def AssignmentExpression(type, operator, left, right):
operator = operator[:-1]
- if left['type']=='Identifier':
+ if left['type'] == 'Identifier':
if operator:
- return 'var.put(%s, %s, %s)' % (repr(to_key(left)), trans(right), repr(operator))
+ return 'var.put(%s, %s, %s)' % (repr(to_key(left)), trans(right),
+ repr(operator))
else:
return 'var.put(%s, %s)' % (repr(to_key(left)), trans(right))
- elif left['type']=='MemberExpression':
+ elif left['type'] == 'MemberExpression':
far_left = trans(left['object'])
if left['computed']: # obj[prop] type accessor
# may be literal which is the same in every case so we can save some time on conversion
if left['property']['type'] == 'Literal':
prop = repr(to_key(left['property']))
- else: # worst case
- prop = trans(left['property']) # its not a string literal! so no repr
- else: # always the same since not computed (obj.prop accessor)
+ else: # worst case
+ prop = trans(
+ left['property']) # its not a string literal! so no repr
+ else: # always the same since not computed (obj.prop accessor)
prop = repr(to_key(left['property']))
if operator:
- return far_left + '.put(%s, %s, %s)' % (prop, trans(right), repr(operator))
+ return far_left + '.put(%s, %s, %s)' % (prop, trans(right),
+ repr(operator))
else:
return far_left + '.put(%s, %s)' % (prop, trans(right))
else:
raise SyntaxError('Invalid left hand side in assignment!')
+
+
six
+
+
@limited
def SequenceExpression(type, expressions):
return reduce(js_comma, (trans(e) for e in expressions))
+
@limited
def NewExpression(type, callee, arguments):
- return trans(callee) + '.create(%s)' % ', '.join(trans(e) for e in arguments)
+ return trans(callee) + '.create(%s)' % ', '.join(
+ trans(e) for e in arguments)
-@limited
-def ConditionalExpression(type, test, consequent, alternate): # caused plenty of problems in my home-made translator :)
- return '(%s if %s else %s)' % (trans(consequent), trans(test), trans(alternate))
+@limited
+def ConditionalExpression(
+ type, test, consequent,
+ alternate): # caused plenty of problems in my home-made translator :)
+ return '(%s if %s else %s)' % (trans(consequent), trans(test),
+ trans(alternate))
# =========== STATEMENTS =============
def BlockStatement(type, body):
- return StatementList(body) # never returns empty string! In the worst case returns pass\n
+ return StatementList(
+ body) # never returns empty string! In the worst case returns pass\n
def ExpressionStatement(type, expression):
@@ -331,12 +385,19 @@ def BreakStatement(type, label):
def ContinueStatement(type, label):
if label:
- return 'raise %s("Continued")\n' % (get_continue_label(label['name']))
+ maybe_update_expr = loop_controller.get_update(label=label['name'])
+ continue_stmt = 'raise %s("Continued")\n' % (get_continue_label(label['name']))
else:
- return 'continue\n'
+ maybe_update_expr = loop_controller.get_update()
+ continue_stmt = "continue\n"
+ if maybe_update_expr:
+ return "# continue update\n%s\n%s" % (maybe_update_expr, continue_stmt)
+ return continue_stmt
+
def ReturnStatement(type, argument):
- return 'return %s\n' % (trans(argument) if argument else "var.get('undefined')")
+ return 'return %s\n' % (trans(argument)
+ if argument else "var.get('undefined')")
def EmptyStatement(type):
@@ -348,43 +409,49 @@ def DebuggerStatement(type):
def DoWhileStatement(type, body, test):
- inside = trans(body) + 'if not %s:\n' % trans(test) + indent('break\n')
+ loop_controller.enter()
+ body_code = trans(body)
+ loop_controller.leave()
+ inside = body_code + 'if not %s:\n' % trans(test) + indent('break\n')
result = 'while 1:\n' + indent(inside)
return result
-
def ForStatement(type, init, test, update, body):
- update = indent(trans(update)) if update else ''
- init = trans(init) if init else ''
+ update = trans(update) if update else ''
+ init = trans(init) if init else ''
if not init.endswith('\n'):
init += '\n'
test = trans(test) if test else '1'
+ loop_controller.enter(update)
if not update:
- result = '#for JS loop\n%swhile %s:\n%s%s\n' % (init, test, indent(trans(body)), update)
+ result = '#for JS loop\n%swhile %s:\n%s%s\n' % (
+ init, test, indent(trans(body)), update)
else:
result = '#for JS loop\n%swhile %s:\n' % (init, test)
- body = 'try:\n%sfinally:\n %s\n' % (indent(trans(body)), update)
- result += indent(body)
+ result += indent("%s# update\n%s\n" % (trans(body), update))
+ loop_controller.leave()
return result
def ForInStatement(type, left, right, body, each):
- res = 'for PyJsTemp in %s:\n' % trans(right)
- if left['type']=="VariableDeclaration":
- addon = trans(left) # make sure variable is registered
+ res = 'for PyJsTemp in %s:\n' % trans(right)
+ if left['type'] == "VariableDeclaration":
+ addon = trans(left) # make sure variable is registered
if addon != 'pass\n':
- res = addon + res # we have to execute this expression :(
+ res = addon + res # we have to execute this expression :(
# now extract the name
try:
name = left['declarations'][0]['id']['name']
except:
raise RuntimeError('Unusual ForIn loop')
- elif left['type']=='Identifier':
+ elif left['type'] == 'Identifier':
name = left['name']
else:
raise RuntimeError('Unusual ForIn loop')
+ loop_controller.enter()
res += indent('var.put(%s, PyJsTemp)\n' % repr(name) + trans(body))
+ loop_controller.leave()
return res
@@ -400,21 +467,25 @@ def IfStatement(type, test, consequent, alternate):
def LabeledStatement(type, label, body):
# todo consider using smarter approach!
+ label_name = label['name']
+ loop_controller.register_label(label_name)
inside = trans(body)
+ loop_controller.deregister_label(label_name)
defs = ''
- if inside.startswith('while ') or inside.startswith('for ') or inside.startswith('#for'):
+ if is_iteration_statement(body) and (inside.startswith('while ') or inside.startswith(
+ 'for ') or inside.startswith('#for')):
# we have to add contine label as well...
# 3 or 1 since #for loop type has more lines before real for.
sep = 1 if not inside.startswith('#for') else 3
- cont_label = get_continue_label(label['name'])
+ cont_label = get_continue_label(label_name)
temp = inside.split('\n')
- injected = 'try:\n'+'\n'.join(temp[sep:])
- injected += 'except %s:\n pass\n'%cont_label
- inside = '\n'.join(temp[:sep])+'\n'+indent(injected)
- defs += 'class %s(Exception): pass\n'%cont_label
- break_label = get_break_label(label['name'])
- inside = 'try:\n%sexcept %s:\n pass\n'% (indent(inside), break_label)
- defs += 'class %s(Exception): pass\n'%break_label
+ injected = 'try:\n' + '\n'.join(temp[sep:])
+ injected += 'except %s:\n pass\n' % cont_label
+ inside = '\n'.join(temp[:sep]) + '\n' + indent(injected)
+ defs += 'class %s(Exception): pass\n' % cont_label
+ break_label = get_break_label(label_name)
+ inside = 'try:\n%sexcept %s:\n pass\n' % (indent(inside), break_label)
+ defs += 'class %s(Exception): pass\n' % break_label
return defs + inside
@@ -425,6 +496,7 @@ def StatementList(lis):
else:
return 'pass\n'
+
def PyimportStatement(type, imp):
lib = imp['name']
jlib = 'PyImport_%s' % lib
@@ -433,19 +505,22 @@ def PyimportStatement(type, imp):
try:
compile(code, '', 'exec')
except:
- raise SyntaxError('Invalid Python module name (%s) in pyimport statement'%lib)
+ raise SyntaxError(
+ 'Invalid Python module name (%s) in pyimport statement' % lib)
# var.pyimport will handle module conversion to PyJs object
code += 'var.pyimport(%s, %s)\n' % (repr(lib), jlib)
return code
+
def SwitchStatement(type, discriminant, cases):
#TODO there will be a problem with continue in a switch statement.... FIX IT
code = 'while 1:\n' + indent('SWITCHED = False\nCONDITION = (%s)\n')
code = code % trans(discriminant)
for case in cases:
case_code = None
- if case['test']: # case (x):
- case_code = 'if SWITCHED or PyJsStrictEq(CONDITION, %s):\n' % (trans(case['test']))
+ if case['test']: # case (x):
+ case_code = 'if SWITCHED or PyJsStrictEq(CONDITION, %s):\n' % (
+ trans(case['test']))
else: # default:
case_code = 'if True:\n'
case_code += indent('SWITCHED = True\n')
@@ -458,7 +533,8 @@ def SwitchStatement(type, discriminant, cases):
def ThrowStatement(type, argument):
- return 'PyJsTempException = JsToPyException(%s)\nraise PyJsTempException\n' % trans(argument)
+ return 'PyJsTempException = JsToPyException(%s)\nraise PyJsTempException\n' % trans(
+ argument)
def TryStatement(type, block, handler, handlers, guardedHandlers, finalizer):
@@ -466,11 +542,15 @@ def TryStatement(type, block, handler, handlers, guardedHandlers, finalizer):
# complicated catch statement...
if handler:
identifier = handler['param']['name']
- holder = 'PyJsHolder_%s_%d'%(to_hex(identifier), random.randrange(1e8))
+ holder = 'PyJsHolder_%s_%d' % (to_hex(identifier),
+ random.randrange(1e8))
identifier = repr(identifier)
result += 'except PyJsException as PyJsTempException:\n'
# fill in except ( catch ) block and remember to recover holder variable to its previous state
- result += indent(TRY_CATCH.replace('HOLDER', holder).replace('NAME', identifier).replace('BLOCK', indent(trans(handler['body']))))
+ result += indent(
+ TRY_CATCH.replace('HOLDER',
+ holder).replace('NAME', identifier).replace(
+ 'BLOCK', indent(trans(handler['body']))))
# translate finally statement if present
if finalizer:
result += 'finally:\n%s' % indent(trans(finalizer))
@@ -478,7 +558,9 @@ def TryStatement(type, block, handler, handlers, guardedHandlers, finalizer):
def LexicalDeclaration(type, declarations, kind):
- raise NotImplementedError('let and const not implemented yet but they will be soon! Check github for updates.')
+ raise NotImplementedError(
+ 'let and const not implemented yet but they will be soon! Check github for updates.'
+ )
def VariableDeclarator(type, id, init):
@@ -496,7 +578,11 @@ def VariableDeclaration(type, declarations, kind):
def WhileStatement(type, test, body):
- result = 'while %s:\n'%trans(test) + indent(trans(body))
+ test_code = trans(test)
+ loop_controller.enter()
+ body_code = trans(body)
+ loop_controller.leave()
+ result = 'while %s:\n' % test_code + indent(body_code)
return result
@@ -514,16 +600,18 @@ def Program(type, body):
return code
-
# ======== FUNCTIONS ============
-def FunctionDeclaration(type, id, params, defaults, body, generator, expression):
+
+def FunctionDeclaration(type, id, params, defaults, body, generator,
+ expression):
if generator:
raise NotImplementedError('Generators not supported')
if defaults:
raise NotImplementedError('Defaults not supported')
if not id:
- return FunctionExpression(type, id, params, defaults, body, generator, expression) + '\n'
+ return FunctionExpression(type, id, params, defaults, body, generator,
+ expression) + '\n'
JsName = id['name']
PyName = 'PyJsHoisted_%s_' % JsName
PyName = PyName if is_valid_py_name(PyName) else 'PyJsHoistedNonPyName'
@@ -545,18 +633,20 @@ def FunctionDeclaration(type, id, params, defaults, body, generator, expression)
for v in vars:
if is_valid_py_name(v):
used_vars.append(v)
- else: # invalid arg in python, for example $, replace with alternatice arg
+ else: # invalid arg in python, for example $, replace with alternatice arg
used_vars.append('PyJsArg_%s_' % to_hex(v))
header = '@Js\n'
- header+= 'def %s(%sthis, arguments, var=var):\n' % (PyName, ', '.join(used_vars) +(', ' if vars else ''))
+ header += 'def %s(%sthis, arguments, var=var):\n' % (
+ PyName, ', '.join(used_vars) + (', ' if vars else ''))
# transfer names from Py scope to Js scope
arg_map = dict(zip(vars, used_vars))
- arg_map.update({'this':'this', 'arguments':'arguments'})
- arg_conv = 'var = Scope({%s}, var)\n' % ', '.join(repr(k)+':'+v for k,v in six.iteritems(arg_map))
+ arg_map.update({'this': 'this', 'arguments': 'arguments'})
+ arg_conv = 'var = Scope({%s}, var)\n' % ', '.join(
+ repr(k) + ':' + v for k, v in six.iteritems(arg_map))
# and finally set the name of the function to its real name:
footer = '%s.func_name = %s\n' % (PyName, repr(JsName))
- footer+= 'var.put(%s, %s)\n' % (repr(JsName), PyName)
- whole_code = header + indent(arg_conv+code) + footer
+ footer += 'var.put(%s, %s)\n' % (repr(JsName), PyName)
+ whole_code = header + indent(arg_conv + code) + footer
# restore context
Context = previous_context
# define in upper context
@@ -564,7 +654,8 @@ def FunctionDeclaration(type, id, params, defaults, body, generator, expression)
return 'pass\n'
-def FunctionExpression(type, id, params, defaults, body, generator, expression):
+def FunctionExpression(type, id, params, defaults, body, generator,
+ expression):
if generator:
raise NotImplementedError('Generators not supported')
if defaults:
@@ -594,20 +685,22 @@ def FunctionExpression(type, id, params, defaults, body, generator, expression):
for v in vars:
if is_valid_py_name(v):
used_vars.append(v)
- else: # invalid arg in python, for example $, replace with alternatice arg
+ else: # invalid arg in python, for example $, replace with alternatice arg
used_vars.append('PyJsArg_%s_' % to_hex(v))
header = '@Js\n'
- header+= 'def %s(%sthis, arguments, var=var):\n' % (PyName, ', '.join(used_vars) +(', ' if vars else ''))
+ header += 'def %s(%sthis, arguments, var=var):\n' % (
+ PyName, ', '.join(used_vars) + (', ' if vars else ''))
# transfer names from Py scope to Js scope
arg_map = dict(zip(vars, used_vars))
- arg_map.update({'this':'this', 'arguments':'arguments'})
- if id: # make self available from inside...
+ arg_map.update({'this': 'this', 'arguments': 'arguments'})
+ if id: # make self available from inside...
if id['name'] not in arg_map:
arg_map[id['name']] = PyName
- arg_conv = 'var = Scope({%s}, var)\n' % ', '.join(repr(k)+':'+v for k,v in six.iteritems(arg_map))
+ arg_conv = 'var = Scope({%s}, var)\n' % ', '.join(
+ repr(k) + ':' + v for k, v in six.iteritems(arg_map))
# and finally set the name of the function to its real name:
footer = '%s._set_name(%s)\n' % (PyName, repr(JsName))
- whole_code = header + indent(arg_conv+code) + footer
+ whole_code = header + indent(arg_conv + code) + footer
# restore context
Context = previous_context
# define in upper context
@@ -620,12 +713,12 @@ def FunctionExpression(type, id, params, defaults, body, generator, expression):
clean_stacks()
-if __name__=='__main__':
+if __name__ == '__main__':
import codecs
import time
import pyjsparser
- c = None#'''`ijfdij`'''
+ c = None #'''`ijfdij`'''
if not c:
with codecs.open("esp.js", "r", "utf-8") as f:
c = f.read()
@@ -633,9 +726,8 @@ def FunctionExpression(type, id, params, defaults, body, generator, expression):
print('Started')
t = time.time()
res = trans(pyjsparser.PyJsParser().parse(c))
- dt = time.time() - t+ 0.000000001
- print('Translated everyting in', round(dt,5), 'seconds.')
- print('Thats %d characters per second' % int(len(c)/dt))
+ dt = time.time() - t + 0.000000001
+ print('Translated everyting in', round(dt, 5), 'seconds.')
+ print('Thats %d characters per second' % int(len(c) / dt))
with open('res.py', 'w') as f:
f.write(res)
-
diff --git a/js2py/translators/translator.py b/js2py/translators/translator.py
index 1b9983c1..5ec47002 100644
--- a/js2py/translators/translator.py
+++ b/js2py/translators/translator.py
@@ -5,9 +5,7 @@
import hashlib
import re
-
# Enable Js2Py exceptions and pyimport in parser
-pyjsparser.parser.ENABLE_JS2PY_ERRORS = True
pyjsparser.parser.ENABLE_PYIMPORT = True
# the re below is how we'll recognise numeric constants.
@@ -17,8 +15,7 @@
CP_NUMERIC_RE = re.compile(r'(?= (3, 11)
# Now we modify the actual bytecode
modified = []
+ drop_future_cache = False
for inst in instructions(code_obj):
+ if is_new_bytecode and inst.opname == "CACHE":
+ assert inst.arg == 0
+ if not drop_future_cache:
+ modified.extend(write_instruction(inst.opcode, inst.arg))
+ else:
+ # We need to inject NOOP to not break jumps :(
+ modified.extend(write_instruction(dis.opmap["NOP"], 0))
+
+ continue
op, arg = inst.opcode, inst.arg
# If the instruction is a LOAD_GLOBAL, we have to check to see if
# it's one of the globals that we are replacing. Either way,
# update its arg using the appropriate dict.
+ drop_future_cache = False
if inst.opcode == LOAD_GLOBAL:
- if inst.arg in names_to_varnames:
+ idx = inst.arg
+ if is_new_bytecode:
+ idx = idx // 2
+ if idx in names_to_varnames:
op = LOAD_FAST
- arg = names_to_varnames[inst.arg]
- elif inst.arg in name_translations:
- arg = name_translations[inst.arg]
+ arg = names_to_varnames[idx]
+ # Cache is not present after LOAD_FAST and needs to be removed.
+ drop_future_cache = True
+ elif idx in name_translations:
+ tgt = name_translations[idx]
+ if is_new_bytecode:
+ tgt = 2*tgt + (inst.arg % 2)
+ arg = tgt
else:
- raise ValueError("a name was lost in translation")
+ raise(ValueError("a name was lost in translation last instruction %s" % str(inst)))
# If it accesses co_varnames or co_names then update its argument.
elif inst.opcode in opcode.haslocal:
arg = varname_translations[inst.arg]
elif inst.opcode in opcode.hasname:
+ # for example STORE_GLOBAL
arg = name_translations[inst.arg]
+ elif is_new_bytecode and inst.opcode in opcode.hasfree:
+ # Python 3.11+ adds refs at the end (after locals), for whatever reason...
+ if inst.argval not in code_obj.co_varnames[:code_obj.co_argcount]: # we do not need to remap existing arguments, they are not shifted by new ones.
+ arg = inst.arg + len(new_locals)
modified.extend(write_instruction(op, arg))
if six.PY2:
code = ''.join(modified)
args = (co_argcount + new_locals_len,
- code_obj.co_nlocals + new_locals_len,
- code_obj.co_stacksize,
- code_obj.co_flags,
- code,
- code_obj.co_consts,
- names,
- varnames,
- code_obj.co_filename,
- code_obj.co_name,
- code_obj.co_firstlineno,
- code_obj.co_lnotab,
- code_obj.co_freevars,
- code_obj.co_cellvars)
+ code_obj.co_nlocals + new_locals_len, code_obj.co_stacksize,
+ code_obj.co_flags, code, code_obj.co_consts, names, varnames,
+ code_obj.co_filename, code_obj.co_name,
+ code_obj.co_firstlineno, code_obj.co_lnotab,
+ code_obj.co_freevars, code_obj.co_cellvars)
else:
code = bytes(modified)
- args = (co_argcount + new_locals_len,
- 0,
- code_obj.co_nlocals + new_locals_len,
- code_obj.co_stacksize,
- code_obj.co_flags,
- code,
- code_obj.co_consts,
- names,
- varnames,
- code_obj.co_filename,
- code_obj.co_name,
- code_obj.co_firstlineno,
- code_obj.co_lnotab,
- code_obj.co_freevars,
- code_obj.co_cellvars)
-
+ args = (co_argcount + new_locals_len, 0,
+ code_obj.co_nlocals + new_locals_len, code_obj.co_stacksize,
+ code_obj.co_flags, code, code_obj.co_consts, names, varnames,
+ code_obj.co_filename, code_obj.co_name,
+ code_obj.co_firstlineno, code_obj.co_lnotab,
+ code_obj.co_freevars, code_obj.co_cellvars)
# Done modifying codestring - make the code object
- return types.CodeType(*args)
+ if hasattr(code_obj, "replace"):
+ # Python 3.8+
+ code_obj = code_obj.replace(
+ co_argcount=co_argcount + new_locals_len,
+ co_nlocals=code_obj.co_nlocals + new_locals_len,
+ co_code=code,
+ co_names=names,
+ co_varnames=varnames)
+ return code_obj
+ else:
+ return types.CodeType(*args)
-def instructions(code_obj):
- # easy for python 3.4+
- if sys.version_info >= (3, 4):
+def instructions(code_obj, show_cache=True):
+ if sys.version_info >= (3, 11):
+ # Python 3.11 introduced "cache instructions", hidden by default.
+ for inst in dis.Bytecode(code_obj, show_caches=show_cache):
+ yield inst
+ elif sys.version_info >= (3, 4): # easy for python 3.4+
for inst in dis.Bytecode(code_obj):
yield inst
else:
@@ -145,11 +172,11 @@ def instructions(code_obj):
extended_arg = 0
while i < L:
op = code[i]
- i+= 1
+ i += 1
if op < opcode.HAVE_ARGUMENT:
yield NewInstruction(op, None)
continue
- oparg = code[i] + (code[i+1] << 8) + extended_arg
+ oparg = code[i] + (code[i + 1] << 8) + extended_arg
extended_arg = 0
i += 2
if op == opcode.EXTENDED_ARG:
@@ -157,6 +184,7 @@ def instructions(code_obj):
continue
yield NewInstruction(op, oparg)
+
def write_instruction(op, arg):
if sys.version_info < (3, 6):
if arg is None:
@@ -164,14 +192,16 @@ def write_instruction(op, arg):
elif arg <= 65536:
return [chr(op), chr(arg & 255), chr((arg >> 8) & 255)]
elif arg <= 4294967296:
- return [chr(opcode.EXTENDED_ARG),
- chr((arg >> 16) & 255),
- chr((arg >> 24) & 255),
- chr(op),
- chr(arg & 255),
- chr((arg >> 8) & 255)]
+ return [
+ chr(opcode.EXTENDED_ARG),
+ chr((arg >> 16) & 255),
+ chr((arg >> 24) & 255),
+ chr(op),
+ chr(arg & 255),
+ chr((arg >> 8) & 255)
+ ]
else:
- raise ValueError("Invalid oparg: {0} is too large".format(oparg))
+ raise ValueError("Invalid oparg: {0} is too large".format(arg))
else: # python 3.6+ uses wordcode instead of bytecode and they already supply all the EXTENDEND_ARG ops :)
if arg is None:
return [chr(op), 0]
@@ -191,6 +221,7 @@ def write_instruction(op, arg):
# raise ValueError("Invalid oparg: {0} is too large".format(oparg))
+
def check(code_obj):
old_bytecode = code_obj.co_code
insts = list(instructions(code_obj))
@@ -213,27 +244,107 @@ def check(code_obj):
while 1:
if i in pos_to_inst:
print(pos_to_inst[i])
- print(pos_to_inst[i-2])
- print(list(map(chr, old_bytecode))[i-4:i+8])
- print(bytelist[i-4:i+8])
+ print(pos_to_inst[i - 2])
+ print(list(map(chr, old_bytecode))[i - 4:i + 8])
+ print(bytelist[i - 4:i + 8])
break
- raise RuntimeError('Your python version made changes to the bytecode')
+ raise RuntimeError(
+ 'Your python version made changes to the bytecode')
+
+
+def signature(func):
+ code_obj = six.get_function_code(func)
+ return (code_obj.co_nlocals, code_obj.co_argcount, code_obj.co_nlocals, code_obj.co_stacksize,
+ code_obj.co_flags, code_obj.co_names, code_obj.co_varnames,
+ code_obj.co_filename,
+ code_obj.co_freevars, code_obj.co_cellvars)
+
check(six.get_function_code(check))
-if __name__=='__main__':
- x = 'Wrong'
- dick = 3000
- def func(a):
- print(x,y,z, a)
- print(dick)
- d = (x,)
- for e in (e for e in x):
- print(e)
- return x, y, z
- func2 =types.FunctionType(append_arguments(six.get_function_code(func), ('x', 'y', 'z')), six.get_function_globals(func), func.__name__, closure=six.get_function_closure(func))
- args = (2,2,3,4),3,4
- assert func2(1, *args) == args
+def compare_func(fake_func, gt_func):
+ print(signature(fake_func))
+ print(signature(gt_func))
+ assert signature(fake_func) == signature(gt_func)
+ fake_ins = list(instructions(six.get_function_code(fake_func), show_cache=False))
+ real_ins = list(instructions(six.get_function_code(gt_func), show_cache=False))
+ offset = 0
+ pos = 0
+ for e in fake_ins:
+ if e.opname == "NOP":
+ offset += 1 # ignore NOPs that are inserted in place of old cache.
+ else:
+ real = real_ins[pos]
+ fake = e
+ print("POS %d OFFSET: %d FAKE VS REAL" % (pos, offset))
+ print(fake)
+ print(real)
+ assert fake.opcode == real.opcode
+ if fake.opcode in dis.hasjabs or fake.opcode in dis.hasjrel:
+ pass
+ else:
+ assert fake.arg == real.arg
+ assert fake.argval == real.argval or fake.opname in ["LOAD_CONST"]
+ assert fake.is_jump_target == real.is_jump_target
+
+ pos += 1
+ assert pos == len(real_ins), (pos, len(real_ins))
+ print("DONE, looks good.")
+
+
+if __name__ == '__main__':
+ import faulthandler
+
+ faulthandler.enable()
+
+ def func(cmpfn):
+ if not this.Class in ('Array', 'Arguments'):
+ return this.to_object() # do nothing
+ arr = []
+ for i in xrange(len(this)):
+ arr.append(this.get(six.text_type(i)))
+
+ if not arr:
+ return this
+ if not cmpfn.is_callable():
+ cmpfn = None
+ cmp = lambda a, b: sort_compare(a, b, cmpfn)
+ if six.PY3:
+ key = functools.cmp_to_key(cmp)
+ arr.sort(key=key)
+ else:
+ arr.sort(cmp=cmp)
+ for i in xrange(len(arr)):
+ this.put(six.text_type(i), arr[i])
+
+ return this
+
+
+ def func_gt(cmpfn, this, arguments):
+ if not this.Class in ('Array', 'Arguments'):
+ return this.to_object() # do nothing
+ arr = []
+ for i in xrange(len(this)):
+ arr.append(this.get(six.text_type(i)))
+
+ if not arr:
+ return this
+ if not cmpfn.is_callable():
+ cmpfn = None
+ cmp = lambda a, b: sort_compare(a, b, cmpfn)
+ if six.PY3:
+ key = functools.cmp_to_key(cmp)
+ arr.sort(key=key)
+ else:
+ arr.sort(cmp=cmp)
+ for i in xrange(len(arr)):
+ this.put(six.text_type(i), arr[i])
+
+ return this
+
+
+ func2 = fix_js_args(func)
+ compare_func(func2, func_gt)
diff --git a/setup.cfg b/setup.cfg
index 224a7795..101fbf34 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,2 +1,5 @@
[metadata]
-description-file = README.md
\ No newline at end of file
+description_file = README.md
+
+[yapf]
+based_on_style = pep8
\ No newline at end of file
diff --git a/setup.py b/setup.py
index 090e00c5..b496e614 100644
--- a/setup.py
+++ b/setup.py
@@ -23,16 +23,17 @@
-# python setup.py register -r pypi
-# python setup.py sdist upload -r pypi
+# rm -rf dist build && python3 setup.py sdist bdist_wheel
+# twine upload dist/*
setup(
name='Js2Py',
- version='0.45',
+ version='0.74',
packages=['js2py', 'js2py.utils', 'js2py.prototypes', 'js2py.translators',
- 'js2py.constructors', 'js2py.host', 'js2py.es6'],
+ 'js2py.constructors', 'js2py.host', 'js2py.es6', 'js2py.internals',
+ 'js2py.internals.prototypes', 'js2py.internals.constructors', 'js2py.py_node_modules'],
url='https://github.com/PiotrDabkowski/Js2Py',
- install_requires = ['tzlocal>=1.2', 'six>=1.10', 'pyjsparser>=2.4.5'],
+ install_requires = ['tzlocal>=1.2', 'six>=1.10', 'pyjsparser>=2.5.1'],
license='MIT',
author='Piotr Dabkowski',
author_email='piodrus@gmail.com',
diff --git a/simple_test.py b/simple_test.py
index 93a1998d..9b6918f2 100644
--- a/simple_test.py
+++ b/simple_test.py
@@ -1,7 +1,37 @@
import js2py
import time
+import sys
+
+sys.setrecursionlimit(10000)
print("Testing ECMA 5...")
+
+continue_labels_test = """
+for (i=0;i<10;i++) {
+}
+a:for (i=0;i<10;i++) {
+ b:for (j=0;j<10;j++) {
+ continue a;
+ }
+}
+if (i !== 10 || j !== 0) {
+ throw Error("i: " + i + " j: " + j)
+}
+"""
+js2py.eval_js(continue_labels_test)
+
+break_labels_test = """
+a:for (i=0;i<10;i++) {
+ b:for (j=0;j<10;j++) {
+ break a;
+ }
+}
+if (i !== 0 || j !== 0) {
+ throw Error("i: " + i + " j: " + j)
+}
+"""
+js2py.eval_js(break_labels_test)
+
assert js2py.eval_js('(new Date("2008-9-03T20:56:35.450686Z")).toString()')
assert js2py.eval_js('/ser/.test("Mleko + ser to nabial")')
@@ -11,7 +41,7 @@
x, c = js2py.run_file('examples/esprima.js')
assert c.esprima.parse('var abc = 40').to_dict() == {'type': 'Program', 'body': [{'type': 'VariableDeclaration', 'kind': 'var', 'declarations': [{'id': {'type': 'Identifier', 'name': 'abc'}, 'type': 'VariableDeclarator', 'init': {'type': 'Literal', 'raw': '40', 'value': 40}}]}], 'sourceType': 'script'}
-
+assert js2py.eval_js('var x = {get y() { return this.val;}, val: 11};x.y') == 11
try:
assert js2py.eval_js('syntax error!') and 0
except js2py.PyJsException as err:
@@ -26,7 +56,93 @@
except js2py.PyJsException as err:
assert str(err).startswith('SyntaxError: ')
-print("Passed ECMA 5!\n"+30*'-')
+
+# Simple PyWrapper test
+class Foo:
+ def __init__(self, bar):
+ self.bar = bar
+ self.bar_history = []
+
+ def set_bar(self, x):
+ import copy
+ self.bar_history.append(copy.deepcopy(self))
+ self.bar = x
+
+ def get_bar(self):
+ return self.bar
+
+pyobj = Foo(5)
+context = js2py.EvalJs({'foo': pyobj})
+assert context.foo.bar == 5
+context.execute('foo.bar = 7')
+assert context.foo.bar == 7
+context.execute('foo.bar += 15.22')
+assert context.foo.bar == 22.22
+context.execute('foo.bar /= 2')
+assert context.foo.bar == 11.11
+assert pyobj.bar == 11.11
+context.execute('foo.set_bar(foo.get_bar())')
+assert context.foo.get_bar() == 11.11
+context.execute('foo.set_bar(33)')
+assert context.foo.get_bar() == 33
+assert context.eval('foo.bar_history.push(foo.bar_history[1].get_bar());foo.bar_history[foo.bar_history.length-1].get_bar()') == 11.11
+
+print("Passed ECMA 5 simple tests!\n"+30*'-')
+
+print('Now harder tests - test on huge JS libraries:')
+
+# crypto-js ( https://www.npmjs.com/package/crypto-js )
+print('Testing crypto-js')
+CryptoJS = js2py.require('crypto-js@3.1.8')
+data = [{'id': 1}, {'id': 2}]
+JSON = js2py.eval_js('JSON')
+ciphertext = CryptoJS.AES.encrypt(JSON.stringify(data), 'secret key 123')
+bytes = CryptoJS.AES.decrypt(ciphertext.toString(), 'secret key 123')
+decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8)).to_list()
+assert decryptedData == data
+
+AES = js2py.require('crypto-js/aes@3.1.8')
+ciphertext = AES.encrypt(JSON.stringify(data), 'secret key 123')
+bytes = AES.decrypt(ciphertext.toString(), 'secret key 123')
+decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8)).to_list()
+assert decryptedData == data
+
+
+# esprima ( https://www.npmjs.com/package/esprima )
+# escodegen ( https://github.com/estools/escodegen )
+print('Testing esprima & escodegen')
+esprima = js2py.require('esprima')
+escodegen = js2py.require('escodegen')
+print('now use the translated esprima to parse some js code!')
+sample_js_code = '''
+function helloWorld(a, b, c) {
+ console.log(this+a+b+c); 8; var x={hh:1,i:0};
+ if (a!=1) {
+ return x
+ } else {
+ throw error
+ }
+}
+'''
+# we can even parse esprima's own source code, but its size is too big for the travis test.
+#sample_js_code = js2py.get_file_contents('examples/esprima.js')
+parsed = esprima.parse(sample_js_code)
+print('use escodegen to get back the js code from the parsed AST')
+reconstructed = escodegen.generate(parsed)
+parsed2 = esprima.parse(sample_js_code)
+reconstructed2 = escodegen.generate(parsed)
+assert reconstructed==reconstructed2 and len(reconstructed)>=len(sample_js_code)
+
+
+# chalk ( https://github.com/chalk/chalk )
+# print('For the final test use chalk. this is interesting because it '
+# 'uses ES6 objects like Map, Therefore we have to include the polyfills!')
+# chalk = js2py.require('chalk', include_polyfill=True)
+# chalk = chalk.constructor.new({'level': 2})
+# true_text = '\x1b[34mHello \x1b[4m\x1b[44mworld\x1b[49m\x1b[24m!\x1b[39m'
+# text = chalk.blue('Hello', chalk.underline.bgBlue('world') + '!')
+# print(text)
+# assert text==true_text
print("Testing ECMA 6...")
@@ -67,3 +183,6 @@ class Shape {
''').x == 2
print("Passed ECMA 6!")
+
+from js2py.internals import seval
+assert seval.eval_js_vm("function k() {try {throw 3+8} catch (e) {console.log(e);return e}};k()", debug=True) == 11.0
\ No newline at end of file
diff --git a/test_bench.py b/test_bench.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/tests/node_eval.py b/tests/node_eval.py
new file mode 100644
index 00000000..48775d3a
--- /dev/null
+++ b/tests/node_eval.py
@@ -0,0 +1,41 @@
+import subprocess
+from tempfile import NamedTemporaryFile
+import six
+import re
+import os
+
+class NodeJsError(Exception):
+ pass
+
+def node_eval_js(code):
+ ERR_MARKER = "<<>>"
+ ERR_REGEXP = ERR_MARKER + r'([\s\S]*?)' + ERR_MARKER
+ interceptor_code = """
+ try {
+ var res = eval(%s);
+ console.log(res);
+ } catch (e) {
+ throw new Error(getErrMarker() + e + getErrMarker())
+ }
+ function getErrMarker() {
+ return %s;
+ }
+ """ % (repr(code), repr(ERR_MARKER))
+ f = NamedTemporaryFile(delete=False, suffix='.js')
+ f.write(interceptor_code.encode('utf-8') if six.PY3 else interceptor_code)
+ f.close()
+ p = subprocess.Popen(['node', f.name], stderr=subprocess.PIPE, stdout=subprocess.PIPE)
+ out, err = map(lambda x: x.decode('utf-8') if six.PY3 else x, p.communicate())
+ os.unlink(f.name)
+ if not p.returncode:
+ return out
+ # try to get clear error message
+ match = re.search(ERR_REGEXP, err)
+ if match and len(match.groups()) == 1:
+ raise NodeJsError(match.groups()[0])
+ else:
+ raise NodeJsError(err)
+
+
+if __name__ == '__main__':
+ print(node_eval_js('x = 5;x'))
\ No newline at end of file
diff --git a/tests/run_on_js2py.py b/tests/run.py
similarity index 71%
rename from tests/run_on_js2py.py
rename to tests/run.py
index 3e084761..1916dfa4 100644
--- a/tests/run_on_js2py.py
+++ b/tests/run.py
@@ -1,12 +1,43 @@
from __future__ import print_function
import js2py
from js2py.base import PyJsException, PyExceptionToJs
+from js2py.internals import seval
+from js2py.internals.simplex import JsException
import os, sys, re, traceback, threading, ctypes, time, six
from distutils.version import LooseVersion
+from node_eval import NodeJsError, node_eval_js
+import codecs
+import json
+import traceback
+
+TEST_TIMEOUT = 2
+INCLUDE_PATH = 'includes/'
+TEST_PATH = 'test_cases/language'
+FAILING = []
+
+# choose which JS runtime to test. Js2Py has 2 independent runtimes. Translation based (translator) and the vm interpreter based.
+RUNTIME_TO_TEST = 'vm'
+
+
+if RUNTIME_TO_TEST == 'translator':
+ JS_EVALUATOR = js2py.eval_js
+ PY_JS_EXCEPTION = PyJsException
+ MESSAGE_FROM_PY_JS_EXCEPTION = lambda x: PyExceptionToJs(x).get('message').to_python()
+elif RUNTIME_TO_TEST == 'vm':
+ JS_EVALUATOR = seval.eval_js_vm
+ PY_JS_EXCEPTION = PyJsException
+ MESSAGE_FROM_PY_JS_EXCEPTION = lambda x: str(x)
+elif RUNTIME_TO_TEST == 'node':
+ JS_EVALUATOR = node_eval_js
+ PY_JS_EXCEPTION = NodeJsError
+ MESSAGE_FROM_PY_JS_EXCEPTION = lambda x: str(x)
+else:
+ raise RuntimeError("Js2Py has currently only 2 runtimes available - 'translator' and the 'vm' - RUNTIME_TO_TEST must be one of these.")
+
def load(path):
- with open(path, 'r') as f:
+ with codecs.open(path, "r", "utf-8") as f:
return f.read()
def terminate_thread(thread):
@@ -14,7 +45,7 @@ def terminate_thread(thread):
:param thread: a threading.Thread instance
"""
- if not thread.isAlive():
+ if not thread.is_alive():
return
exc = ctypes.py_object(SystemExit)
@@ -29,13 +60,13 @@ def terminate_thread(thread):
raise SystemError("PyThreadState_SetAsyncExc failed")
-TEST_TIMEOUT = 10
-INCLUDE_PATH = 'includes/'
-TEST_PATH = 'test_cases/'
+
INIT = load(os.path.join(INCLUDE_PATH, 'init.js'))
+with open("node_failed.txt") as f:
+ NODE_FAILED = set(f.readlines())
-class TestCase:
+class FestCase:
description = None
includes = None
author = None
@@ -59,15 +90,17 @@ def __init__(self, path):
if self.includes:
for include in self.includes:
self.init += load(os.path.join(INCLUDE_PATH, include))
- if 'onlyStrict' in self.flags:
+ if 'onlyStrict' in self.flags or '"use strict"' in self.raw or "'use strict'" in self.raw:
self.strict_only = True
else:
self.strict_only = False
+ self.node_failed = self.es5id in NODE_FAILED
+
self.code = self.init + self.raw
def _parse_test_info(self):
- self.raw_info = re.search('/\*---(.+)---\*/', self.raw, re.DOTALL).groups()[0].strip()
+ self.raw_info = re.search(r'/\*---(.+)---\*/', self.raw, re.DOTALL).groups()[0].strip()
category = None
category_content = None
for line in self.raw_info.splitlines() + ['END:']:
@@ -75,6 +108,8 @@ def _parse_test_info(self):
if category is None:
raise RuntimeError('Could not parse test case info! %s' % self.path)
category_content += '\n' + line.lstrip()
+ elif line == 'onlyStrict':
+ self.strict_only = True
else:
if category is not None:
content = category_content.strip()
@@ -102,7 +137,7 @@ def run(self):
crashed = True
label = None
try:
- js2py.eval_js(self.code)
+ JS_EVALUATOR(self.code)
errors = False
crashed = False
@@ -115,14 +150,14 @@ def run(self):
full_error = traceback.format_exc()
label = 'NOT_IMPLEMENTED'
- except PyJsException as e:
+ except PY_JS_EXCEPTION as e:
crashed = False
full_error = traceback.format_exc()
if self.negative:
passed = True
else:
passed = False
- reason = PyExceptionToJs(e).get('message').to_python()
+ reason = MESSAGE_FROM_PY_JS_EXCEPTION(e)
label = 'FAILED'
@@ -138,7 +173,7 @@ def run(self):
except:
full_error = traceback.format_exc()
passed = False
- reason = 'UNKNOWN - URGENT, FIX NOW!'
+ reason = 'UNKNOWN - URGENT, FIX NOW!\n' + traceback.format_exc()[-2000:]+'\n\n'
label = 'CRASHED'
if not errors:
@@ -154,11 +189,16 @@ def run(self):
label = "PASSED"
reason = ''
full_error = ''
+ if not passed:
+ FAILING.append(self.es5id)
self.passed, self.label, self.reason, self.full_error = passed, label, reason, full_error
return passed, label, reason, full_error
def print_result(self):
- print(self.clear_name, self.es5id, self.label, self.reason, '\nFile "%s", line 1'%self.full_path if self.label=='CRASHED' else '')
+ #if self.label == "CRASHED": return
+ print(self.clear_name, self.es5id, self.label, self.reason, '\nFile "%s", line 1'%self.full_path if self.label!='PASSED' else '')
+
+ if self.label == "CRASHED": print(self.code) or exit()
@@ -176,19 +216,20 @@ def list_path(path, folders=False):
try:
return sorted(res, key=LooseVersion)
except:
- print('Fuck python 3!')
- return sorted(res) # python 3
+ return sorted(res) # python 3... why cant they fix this
-def test_all(path):
+def fest_all(path):
files = list_path(path)
folders = list_path(path, folders=True)
for f in files:
if not f.endswith('.js'):
continue
try:
- test = TestCase(f)
+ test = FestCase(f)
if test.strict_only:
continue
+ if test.node_failed:
+ continue
thread = threading.Thread(target=test.run)
timeout_time = time.time() + TEST_TIMEOUT
@@ -205,12 +246,14 @@ def test_all(path):
except:
print(traceback.format_exc())
print(f)
- input()
for folder in folders:
- test_all(folder)
+ fest_all(folder)
+
+fest_all(TEST_PATH)
+with open('failed.txt', 'w') as f:
+ f.write('\n'.join(filter(lambda x: x, FAILING)))
-test_all(TEST_PATH)
diff --git a/tests/test_cases/built-ins/Array/prototype/find/Array.prototype.find_callable-arrowfunction.js b/tests/test_cases/built-ins/Array/prototype/find/Array.prototype.find_callable-arrowfunction.js
deleted file mode 100755
index 4f63feb5..00000000
--- a/tests/test_cases/built-ins/Array/prototype/find/Array.prototype.find_callable-arrowfunction.js
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2014 Matthew Meyers. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-
-/*---
-description: >
- Array.prototype.find shouldn't throw a TypeError if
- IsCallable(predicate) is true; arrow functions are callable
-features: [Array#find, arrow-function]
----*/
-
-
-[].find(x => x);
-
diff --git a/tests/test_cases/built-ins/RegExp/S15.10.2.10_A2.1_T1.js b/tests/test_cases/built-ins/RegExp/S15.10.2.10_A2.1_T1.js
deleted file mode 100755
index 4fd4b446..00000000
--- a/tests/test_cases/built-ins/RegExp/S15.10.2.10_A2.1_T1.js
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2009 the Sputnik authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-
-/*---
-info: "CharacterEscape :: c ControlLetter"
-es5id: 15.10.2.10_A2.1_T1
-description: "ControlLetter :: A - Z"
-onlyStrict
----*/
-
-//CHECK#0041-005A
-var result = true;
-for (alpha = 0x0041; alpha <= 0x005A; alpha++) {
- str = String.fromCharCode(alpha % 32);
- arr = (new RegExp("\\c" + String.fromCharCode(alpha))).exec(str);
- console.log(arr)
- if ((arr === null) || (arr[0] !== str)) {
- result = false;
- }
-}
-
-if (result !== true) {
- $ERROR('#1: CharacterEscape :: c A - Z');
-}
diff --git a/tests/test_cases/built-ins/RegExp/S15.10.2.10_A2.1_T2.js b/tests/test_cases/built-ins/RegExp/S15.10.2.10_A2.1_T2.js
deleted file mode 100755
index 3e4ac6e9..00000000
--- a/tests/test_cases/built-ins/RegExp/S15.10.2.10_A2.1_T2.js
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2009 the Sputnik authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-
-/*---
-info: "CharacterEscape :: c ControlLetter"
-es5id: 15.10.2.10_A2.1_T2
-description: "ControlLetter :: a - z"
-onlyStrict
----*/
-
-//CHECK#0061-007A
-var result = true;
-for (alpha = 0x0061; alpha <= 0x007A; alpha++) {
- str = String.fromCharCode(alpha % 32);
- arr = (new RegExp("\\c" + String.fromCharCode(alpha))).exec(str);
- if ((arr === null) || (arr[0] !== str)) {
- result = false;
- }
-}
-
-if (result !== true) {
- $ERROR('#1: CharacterEscape :: c a - z');
-}
diff --git a/tests/test_cases/built-ins/RegExp/S15.10.2.9_A1_T4.js b/tests/test_cases/built-ins/RegExp/S15.10.2.9_A1_T4.js
deleted file mode 100755
index 37cfcb6d..00000000
--- a/tests/test_cases/built-ins/RegExp/S15.10.2.9_A1_T4.js
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2009 the Sputnik authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-
-/*---
-info: >
- An escape sequence of the form \ followed by a nonzero decimal number n
- matches the result of the nth set of capturing parentheses (see
- 15.10.2.11)
-es5id: 15.10.2.9_A1_T4
-description: >
- Execute /\b(\w+) \2\b/.test("do you listen the the band") and
- check results
-
- onlyStrict
----*/
-
-__executed = /\b(\w+) \2\b/.test("do you listen the the band");
-
-//CHECK#1
-if (__executed) {
- $ERROR('#1: /\\b(\\w+) \\2\\b/.test("do you listen the the band") === false');
-}
diff --git a/tests/test_cases/language/arguments-object/10.5-1-s.js b/tests/test_cases/language/arguments-object/10.5-1-s.js
deleted file mode 100755
index 8d4f6947..00000000
--- a/tests/test_cases/language/arguments-object/10.5-1-s.js
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.5-1-s
-description: Strict Mode - arguments object is immutable
-flags: [onlyStrict]
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- "use strict";
- try {
- (function fun() {
- eval("arguments = 10");
- })(30);
- return false;
- } catch (e) {
- return (e instanceof SyntaxError);
- }
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.5-1gs.js b/tests/test_cases/language/arguments-object/10.5-1gs.js
deleted file mode 100755
index b7be5487..00000000
--- a/tests/test_cases/language/arguments-object/10.5-1gs.js
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.5-1gs
-description: Strict Mode - arguments cannot be assigned to in a strict function
-negative: SyntaxError
-flags: [onlyStrict]
----*/
-
-"use strict";
-throw NotEarlyError;
-
-function f_10_5_1_gs(){
- arguments = 7;
-}
diff --git a/tests/test_cases/language/arguments-object/10.5-7-b-1-s.js b/tests/test_cases/language/arguments-object/10.5-7-b-1-s.js
deleted file mode 100755
index 6c5c1b0b..00000000
--- a/tests/test_cases/language/arguments-object/10.5-7-b-1-s.js
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.5-7-b-1-s
-description: Strict Mode - arguments object is immutable in eval'ed functions
-flags: [onlyStrict]
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- "use strict";
-
- try {
- eval("(function _10_5_7_b_1_fun() { arguments = 10;} ());");
- return false;
- } catch (e) {
- return e instanceof SyntaxError;
- }
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.5-7-b-2-s.js b/tests/test_cases/language/arguments-object/10.5-7-b-2-s.js
deleted file mode 100755
index b443416e..00000000
--- a/tests/test_cases/language/arguments-object/10.5-7-b-2-s.js
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.5-7-b-2-s
-description: Strict Mode - arguments object index assignment is allowed
-flags: [onlyStrict]
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- "use strict";
-
- function _10_5_7_b_2_fun() {
- arguments[7] = 12;
- return arguments[7] === 12;
- };
-
- return _10_5_7_b_2_fun(30);
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.5-7-b-3-s.js b/tests/test_cases/language/arguments-object/10.5-7-b-3-s.js
deleted file mode 100755
index b9fc991e..00000000
--- a/tests/test_cases/language/arguments-object/10.5-7-b-3-s.js
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.5-7-b-3-s
-description: >
- Strict Mode - Adding property to the arguments object successful
- under strict mode
-flags: [onlyStrict]
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- "use strict";
-
- function _10_5_7_b_3_fun() {
- arguments[1] = 12;
- return arguments[0] === 30 && arguments[1] === 12;
- };
-
- return _10_5_7_b_3_fun(30);
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.5-7-b-4-s.js b/tests/test_cases/language/arguments-object/10.5-7-b-4-s.js
deleted file mode 100755
index 3f9f1ec6..00000000
--- a/tests/test_cases/language/arguments-object/10.5-7-b-4-s.js
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.5-7-b-4-s
-description: >
- Strict Mode - Deleting property of the arguments object successful
- under strict mode
-flags: [onlyStrict]
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- "use strict";
-
- function _10_5_7_b_4_fun() {
- var _10_5_7_b_4_1 = arguments[0] === 30 && arguments[1] === 12;
- delete arguments[1];
- var _10_5_7_b_4_2 = arguments[0] === 30 && typeof arguments[1] === "undefined";
- return _10_5_7_b_4_1 && _10_5_7_b_4_2;
- };
- return _10_5_7_b_4_fun(30, 12);
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-10-c-ii-1-s.js b/tests/test_cases/language/arguments-object/10.6-10-c-ii-1-s.js
deleted file mode 100755
index 771355e5..00000000
--- a/tests/test_cases/language/arguments-object/10.6-10-c-ii-1-s.js
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-10-c-ii-1-s
-description: >
- arguments[i] remains same after changing actual parameters in
- strict mode
-flags: [onlyStrict]
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- function foo(a,b,c)
- {
- 'use strict';
- a = 1; b = 'str'; c = 2.1;
- return (arguments[0] === 10 && arguments[1] === 'sss' && arguments[2] === 1);
- }
- return foo(10, 'sss', 1);
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-10-c-ii-1.js b/tests/test_cases/language/arguments-object/10.6-10-c-ii-1.js
deleted file mode 100755
index c9ad44df..00000000
--- a/tests/test_cases/language/arguments-object/10.6-10-c-ii-1.js
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-10-c-ii-1
-description: arguments[i] change with actual parameters
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- function foo(a,b,c)
- {
- a = 1; b = 'str'; c = 2.1;
- if(arguments[0] === 1 && arguments[1] === 'str' && arguments[2] === 2.1)
- return true;
- }
- return foo(10,'sss',1);
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-10-c-ii-2-s.js b/tests/test_cases/language/arguments-object/10.6-10-c-ii-2-s.js
deleted file mode 100755
index b39ec15b..00000000
--- a/tests/test_cases/language/arguments-object/10.6-10-c-ii-2-s.js
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-10-c-ii-2-s
-description: arguments[i] doesn't map to actual parameters in strict mode
-flags: [onlyStrict]
-includes: [runTestCase.js]
----*/
-
-function testcase() {
-
- function foo(a,b,c)
- {
- 'use strict';
- arguments[0] = 1; arguments[1] = 'str'; arguments[2] = 2.1;
- return 10 === a && 'sss' === b && 1 === c;
- }
- return foo(10,'sss',1);
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-10-c-ii-2.js b/tests/test_cases/language/arguments-object/10.6-10-c-ii-2.js
deleted file mode 100755
index c1eee201..00000000
--- a/tests/test_cases/language/arguments-object/10.6-10-c-ii-2.js
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-10-c-ii-2
-description: arguments[i] map to actual parameter
-includes: [runTestCase.js]
----*/
-
-function testcase() {
-
- function foo(a,b,c)
- {
- arguments[0] = 1; arguments[1] = 'str'; arguments[2] = 2.1;
- if(1 === a && 'str' === b && 2.1 === c)
- return true;
- }
- return foo(10,'sss',1);
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-11-b-1.js b/tests/test_cases/language/arguments-object/10.6-11-b-1.js
deleted file mode 100755
index cd6949ce..00000000
--- a/tests/test_cases/language/arguments-object/10.6-11-b-1.js
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-11-b-1
-description: >
- Arguments Object has index property '0' as its own property, it
- shoulde be writable, enumerable, configurable and does not invoke
- the setter defined on Object.prototype[0] (Step 11.b)
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- try {
- var data = "data";
- var getFunc = function () {
- return data;
- };
-
- var setFunc = function (value) {
- data = value;
- };
-
- Object.defineProperty(Object.prototype, "0", {
- get: getFunc,
- set: setFunc,
- configurable: true
- });
-
- var argObj = (function () { return arguments })(1);
-
- var verifyValue = false;
- verifyValue = (argObj[0] === 1);
-
- var verifyEnumerable = false;
- for (var p in argObj) {
- if (p === "0" && argObj.hasOwnProperty("0")) {
- verifyEnumerable = true;
- }
- }
-
- var verifyWritable = false;
- argObj[0] = 1001;
- verifyWritable = (argObj[0] === 1001);
-
- var verifyConfigurable = false;
- delete argObj[0];
- verifyConfigurable = argObj.hasOwnProperty("0");
-
- return verifyValue && verifyWritable && verifyEnumerable && !verifyConfigurable && data === "data";
- } finally {
- delete Object.prototype[0];
- }
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-12-1.js b/tests/test_cases/language/arguments-object/10.6-12-1.js
deleted file mode 100755
index 539b49c6..00000000
--- a/tests/test_cases/language/arguments-object/10.6-12-1.js
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-12-1
-description: Accessing callee property of Arguments object is allowed
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- try
- {
- arguments.callee;
- return true;
- }
- catch (e) {
- }
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-12-2.js b/tests/test_cases/language/arguments-object/10.6-12-2.js
deleted file mode 100755
index 2376d2c4..00000000
--- a/tests/test_cases/language/arguments-object/10.6-12-2.js
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-12-2
-description: arguments.callee has correct attributes
-includes: [runTestCase.js]
----*/
-
-function testcase() {
-
- var desc = Object.getOwnPropertyDescriptor(arguments,"callee");
- if(desc.configurable === true &&
- desc.enumerable === false &&
- desc.writable === true &&
- desc.hasOwnProperty('get') == false &&
- desc.hasOwnProperty('put') == false)
- return true;
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-13-1.js b/tests/test_cases/language/arguments-object/10.6-13-1.js
deleted file mode 100755
index 3def632f..00000000
--- a/tests/test_cases/language/arguments-object/10.6-13-1.js
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-13-1
-description: Accessing caller property of Arguments object is allowed
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- try
- {
- arguments.caller;
- return true;
- }
- catch (e) {
- }
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-13-a-1.js b/tests/test_cases/language/arguments-object/10.6-13-a-1.js
deleted file mode 100755
index 9bedd01e..00000000
--- a/tests/test_cases/language/arguments-object/10.6-13-a-1.js
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-13-a-1
-description: >
- In non-strict mode, arguments object should have its own 'callee'
- property defined (Step 13.a)
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- try {
- Object.defineProperty(Object.prototype, "callee", {
- value: 1,
- writable: false,
- configurable: true
- });
-
- var argObj = (function () { return arguments })();
-
- var verifyValue = false;
- verifyValue = typeof argObj.callee === "function";
-
- var verifyWritable = false;
- argObj.callee = 1001;
- verifyWritable = (argObj.callee === 1001);
-
- var verifyEnumerable = false;
- for (var p in argObj) {
- if (p === "callee" && argObj.hasOwnProperty("callee")) {
- verifyEnumerable = true;
- }
- }
-
- var verifyConfigurable = false;
- delete argObj.callee;
- verifyConfigurable = argObj.hasOwnProperty("callee");
-
- return verifyValue && verifyWritable && !verifyEnumerable && !verifyConfigurable;
- } finally {
- delete Object.prototype.callee;
- }
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-13-a-2.js b/tests/test_cases/language/arguments-object/10.6-13-a-2.js
deleted file mode 100755
index 3cdce0d6..00000000
--- a/tests/test_cases/language/arguments-object/10.6-13-a-2.js
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-13-a-2
-description: A direct call to arguments.callee.caller should work
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- var called = false;
-
- function test1(flag) {
- if (flag!==true) {
- test2();
- } else {
- called = true;
- }
- }
-
- function test2() {
- if(arguments.callee.caller===undefined) {
- called=true; // Extension not supported - fake it
- } else {
- arguments.callee.caller(true);
- }
- }
-
- test1();
- return called;
-}
-
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-13-a-3.js b/tests/test_cases/language/arguments-object/10.6-13-a-3.js
deleted file mode 100755
index 86454f9c..00000000
--- a/tests/test_cases/language/arguments-object/10.6-13-a-3.js
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-13-a-3
-description: An indirect call to arguments.callee.caller should work
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- var called = false;
-
- function test1(flag) {
- if (flag!==true) {
- test2();
- } else {
- called = true;
- }
- }
-
- function test2() {
- if (arguments.callee.caller===undefined) {
- called = true; //Extension not supported - fake it
- } else {
- var explicit = arguments.callee.caller;
- explicit(true);
- }
- }
-
- test1();
- return called;
-}
-
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-13-b-1-s.js b/tests/test_cases/language/arguments-object/10.6-13-b-1-s.js
deleted file mode 100755
index c2666194..00000000
--- a/tests/test_cases/language/arguments-object/10.6-13-b-1-s.js
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-13-b-1-s
-description: >
- Accessing caller property of Arguments object throws TypeError in
- strict mode
-flags: [onlyStrict]
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- 'use strict';
- try
- {
- arguments.caller;
- }
- catch (e) {
- if(e instanceof TypeError)
- return true;
- }
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-13-b-2-s.js b/tests/test_cases/language/arguments-object/10.6-13-b-2-s.js
deleted file mode 100755
index 8db28513..00000000
--- a/tests/test_cases/language/arguments-object/10.6-13-b-2-s.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-13-b-2-s
-description: arguments.caller exists in strict mode
-flags: [onlyStrict]
-includes: [runTestCase.js]
----*/
-
-function testcase() {
-
- 'use strict';
- var desc = Object.getOwnPropertyDescriptor(arguments,"caller");
- return desc!== undefined;
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-13-b-3-s.js b/tests/test_cases/language/arguments-object/10.6-13-b-3-s.js
deleted file mode 100755
index c7b56413..00000000
--- a/tests/test_cases/language/arguments-object/10.6-13-b-3-s.js
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-13-b-3-s
-description: arguments.caller is non-configurable in strict mode
-flags: [onlyStrict]
-includes: [runTestCase.js]
----*/
-
-function testcase() {
-
- 'use strict';
- var desc = Object.getOwnPropertyDescriptor(arguments,"caller");
-
- return (desc.configurable === false &&
- desc.enumerable === false &&
- desc.hasOwnProperty('value') == false &&
- desc.hasOwnProperty('writable') == false &&
- desc.hasOwnProperty('get') == true &&
- desc.hasOwnProperty('set') == true);
-
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-13-c-1-s.js b/tests/test_cases/language/arguments-object/10.6-13-c-1-s.js
deleted file mode 100755
index 4f25f14a..00000000
--- a/tests/test_cases/language/arguments-object/10.6-13-c-1-s.js
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-13-c-1-s
-description: >
- Accessing callee property of Arguments object throws TypeError in
- strict mode
-flags: [onlyStrict]
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- 'use strict';
- try
- {
- arguments.callee;
- return false;
- }
- catch (e) {
- return (e instanceof TypeError);
- }
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-13-c-2-s.js b/tests/test_cases/language/arguments-object/10.6-13-c-2-s.js
deleted file mode 100755
index 125852d3..00000000
--- a/tests/test_cases/language/arguments-object/10.6-13-c-2-s.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-13-c-2-s
-description: arguments.callee is exists in strict mode
-flags: [onlyStrict]
-includes: [runTestCase.js]
----*/
-
-function testcase() {
-
- 'use strict';
- var desc = Object.getOwnPropertyDescriptor(arguments,"callee");
- return desc !== undefined;
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-13-c-3-s.js b/tests/test_cases/language/arguments-object/10.6-13-c-3-s.js
deleted file mode 100755
index 6182ad0f..00000000
--- a/tests/test_cases/language/arguments-object/10.6-13-c-3-s.js
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-13-c-3-s
-description: arguments.callee is non-configurable in strict mode
-flags: [onlyStrict]
-includes: [runTestCase.js]
----*/
-
-function testcase() {
-
- 'use strict';
- var desc = Object.getOwnPropertyDescriptor(arguments,"callee");
- return (desc.configurable === false &&
- desc.enumerable === false &&
- desc.hasOwnProperty('value') == false &&
- desc.hasOwnProperty('writable') == false &&
- desc.hasOwnProperty('get') == true &&
- desc.hasOwnProperty('set') == true);
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-14-1-s.js b/tests/test_cases/language/arguments-object/10.6-14-1-s.js
deleted file mode 100755
index f7f76465..00000000
--- a/tests/test_cases/language/arguments-object/10.6-14-1-s.js
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-14-1-s
-description: Strict Mode - 'callee' exists and 'caller' exists under strict mode
-flags: [onlyStrict]
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- "use strict";
- var argObj = function () {
- return arguments;
- } ();
- return argObj.hasOwnProperty("callee") && argObj.hasOwnProperty("caller");
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-14-b-1-s.js b/tests/test_cases/language/arguments-object/10.6-14-b-1-s.js
deleted file mode 100755
index 488b443d..00000000
--- a/tests/test_cases/language/arguments-object/10.6-14-b-1-s.js
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-14-b-1-s
-description: >
- Strict Mode - [[Enumerable]] attribute value in 'caller' is false
- under strict mode
-flags: [onlyStrict]
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- "use strict";
-
- var argObj = function () {
- return arguments;
- } ();
-
- var verifyEnumerable = false;
- for (var _10_6_14_b_1 in argObj) {
- if (argObj.hasOwnProperty(_10_6_14_b_1) && _10_6_14_b_1 === "caller") {
- verifyEnumerable = true;
- }
- }
- return !verifyEnumerable && argObj.hasOwnProperty("caller");
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-14-b-4-s.js b/tests/test_cases/language/arguments-object/10.6-14-b-4-s.js
deleted file mode 100755
index 8a8b54a7..00000000
--- a/tests/test_cases/language/arguments-object/10.6-14-b-4-s.js
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-14-b-4-s
-description: >
- Strict Mode - TypeError is thrown when accessing the [[Set]]
- attribute in 'caller' under strict mode
-flags: [onlyStrict]
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- "use strict";
-
- var argObj = function () {
- return arguments;
- } ();
-
- try {
- argObj.caller = {};
- return false;
- } catch (e) {
- return e instanceof TypeError;
- }
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-14-c-1-s.js b/tests/test_cases/language/arguments-object/10.6-14-c-1-s.js
deleted file mode 100755
index 215e95db..00000000
--- a/tests/test_cases/language/arguments-object/10.6-14-c-1-s.js
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-14-c-1-s
-description: >
- Strict Mode - [[Enumerable]] attribute value in 'callee' is false
- under strict mode
-flags: [onlyStrict]
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- "use strict";
-
- var argObj = function () {
- return arguments;
- } ();
-
- var verifyEnumerable = false;
- for (var _10_6_14_c_1 in argObj) {
- if (argObj.hasOwnProperty(_10_6_14_c_1) && _10_6_14_c_1 === "callee") {
- verifyEnumerable = true;
- }
- }
- return !verifyEnumerable && argObj.hasOwnProperty("callee");
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-14-c-4-s.js b/tests/test_cases/language/arguments-object/10.6-14-c-4-s.js
deleted file mode 100755
index 9f2baa39..00000000
--- a/tests/test_cases/language/arguments-object/10.6-14-c-4-s.js
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-14-c-4-s
-description: >
- Strict Mode - TypeError is thrown when accessing the [[Set]]
- attribute in 'callee' under strict mode
-flags: [onlyStrict]
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- "use strict";
-
- var argObj = function () {
- return arguments;
- } ();
-
- try {
- argObj.callee = {};
- return false;
- } catch (e) {
- return e instanceof TypeError;
- }
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-1gs.js b/tests/test_cases/language/arguments-object/10.6-1gs.js
deleted file mode 100755
index b4bf6b28..00000000
--- a/tests/test_cases/language/arguments-object/10.6-1gs.js
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-1gs
-description: >
- Strict Mode - arguments.callee cannot be accessed in a strict
- function, but does not throw an early error
-flags: [onlyStrict]
----*/
-
-"use strict";
-function f_10_6_1_gs(){
- return arguments.callee;
-}
diff --git a/tests/test_cases/language/arguments-object/10.6-2gs.js b/tests/test_cases/language/arguments-object/10.6-2gs.js
deleted file mode 100755
index d5782511..00000000
--- a/tests/test_cases/language/arguments-object/10.6-2gs.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-2gs
-description: >
- Strict Mode - arguments.callee cannot be accessed in a strict
- function
-negative: .
-flags: [onlyStrict]
----*/
-
-"use strict";
-function f_10_6_1_gs(){
- return arguments.callee;
-}
-f_10_6_1_gs();
diff --git a/tests/test_cases/language/arguments-object/10.6-5-1.js b/tests/test_cases/language/arguments-object/10.6-5-1.js
deleted file mode 100755
index 058a96c7..00000000
--- a/tests/test_cases/language/arguments-object/10.6-5-1.js
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-5-1
-description: >
- [[Prototype]] property of Arguments is set to Object prototype
- object
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- if(Object.getPrototypeOf(arguments) === Object.getPrototypeOf({}))
- return true;
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-6-1.js b/tests/test_cases/language/arguments-object/10.6-6-1.js
deleted file mode 100755
index 3ac99bd3..00000000
--- a/tests/test_cases/language/arguments-object/10.6-6-1.js
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-6-1
-description: "'length property of arguments object exists"
-includes: [runTestCase.js]
----*/
-
-function testcase() {
-
- var desc = Object.getOwnPropertyDescriptor(arguments,"length");
- return desc !== undefined
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-6-2.js b/tests/test_cases/language/arguments-object/10.6-6-2.js
deleted file mode 100755
index 6a1f56e4..00000000
--- a/tests/test_cases/language/arguments-object/10.6-6-2.js
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-6-2
-description: "'length' property of arguments object has correct attributes"
-includes: [runTestCase.js]
----*/
-
-function testcase() {
-
- var desc = Object.getOwnPropertyDescriptor(arguments,"length");
- if(desc.configurable === true &&
- desc.enumerable === false &&
- desc.writable === true )
- return true;
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-6-3.js b/tests/test_cases/language/arguments-object/10.6-6-3.js
deleted file mode 100755
index bd461a05..00000000
--- a/tests/test_cases/language/arguments-object/10.6-6-3.js
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-6-3
-description: >
- 'length' property of arguments object for 0 argument function
- exists
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- var arguments= undefined;
- return (function () {return arguments.length !== undefined})();
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-6-4.js b/tests/test_cases/language/arguments-object/10.6-6-4.js
deleted file mode 100755
index 1ece6916..00000000
--- a/tests/test_cases/language/arguments-object/10.6-6-4.js
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-6-4
-description: >
- 'length' property of arguments object for 0 argument function call
- is 0 even with formal parameters
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- var arguments= undefined;
- return (function (a,b,c) {return arguments.length === 0})();
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/10.6-7-1.js b/tests/test_cases/language/arguments-object/10.6-7-1.js
deleted file mode 100755
index ca2238d4..00000000
--- a/tests/test_cases/language/arguments-object/10.6-7-1.js
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2012 Ecma International. All rights reserved.
-// Ecma International makes this code available under the terms and conditions set
-// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
-// "Use Terms"). Any redistribution of this code must retain the above
-// copyright and this notice and otherwise comply with the Use Terms.
-
-/*---
-es5id: 10.6-7-1
-description: >
- Arguments Object has length as its own property and does not
- invoke the setter defined on Object.prototype.length (Step 7)
-includes: [runTestCase.js]
----*/
-
-function testcase() {
- try {
- var data = "data";
- var getFunc = function () {
- return 12;
- };
-
- var setFunc = function (value) {
- data = value;
- };
-
- Object.defineProperty(Object.prototype, "length", {
- get: getFunc,
- set: setFunc,
- configurable: true
- });
-
- var verifyValue = false;
- var argObj = (function () { return arguments })();
- verifyValue = (argObj.length === 0);
-
- var verifyWritable = false;
- argObj.length = 1001;
- verifyWritable = (argObj.length === 1001);
-
- var verifyEnumerable = false;
- for (var p in argObj) {
- if (p === "length") {
- verifyEnumerable = true;
- }
- }
-
- var verifyConfigurable = false;
- delete argObj.length;
- verifyConfigurable = argObj.hasOwnProperty("length");
-
- return verifyValue && verifyWritable && !verifyEnumerable && !verifyConfigurable && data === "data";
- } finally {
- delete Object.prototype.length;
- }
- }
-runTestCase(testcase);
diff --git a/tests/test_cases/language/arguments-object/S10.1.6_A1_T2.js b/tests/test_cases/language/arguments-object/S10.1.6_A1_T2.js
deleted file mode 100755
index 89e5ec69..00000000
--- a/tests/test_cases/language/arguments-object/S10.1.6_A1_T2.js
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2009 the Sputnik authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-
-/*---
-info: >
- The activation object is initialised with a property with name arguments
- and attributes {DontDelete}
-es5id: 10.1.6_A1_T2
-description: Checking funtion which returns property "arguments"
----*/
-
-var ARG_STRING = "value of the argument property";
-
-function f1() {
- this.constructor.prototype.arguments = ARG_STRING;
- return arguments;
-}
-
-//CHECK#1
-if ((new f1(1,2,3,4,5)).length !== 5)
- $ERROR('#1: (new f1(1,2,3,4,5)).length===5, where f1 returns "arguments" that is set to "'+ ARG_STRING + '"');
-
-//CHECK#2
-if ((new f1(1,2,3,4,5))[3] !== 4)
- $ERROR('#2: (new f1(1,2,3,4,5))[3]===4, where f1 returns "arguments" that is set to "'+ ARG_STRING + '"');
-
-//CHECK#3
-var x = new f1(1,2,3,4,5);
-if (delete x[3] !== true)
- $ERROR('#3.1: Function parameters have attribute {DontDelete}');
-
-if (x[3] === 4)
- $ERROR('#3.2: Function parameters have attribute {DontDelete}');
diff --git a/tests/test_cases/language/arguments-object/S10.1.6_A1_T3.js b/tests/test_cases/language/arguments-object/S10.1.6_A1_T3.js
deleted file mode 100755
index 4349aa4a..00000000
--- a/tests/test_cases/language/arguments-object/S10.1.6_A1_T3.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2009 the Sputnik authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-
-/*---
-info: >
- The activation object is initialised with a property with name arguments
- and attributes {DontDelete}
-es5id: 10.1.6_A1_T3
-description: Checking function which returns "this"
-flags: [noStrict]
----*/
-
-function f1() {
- if (delete arguments) {
- $ERROR("#1: Function parameters have attribute {DontDelete}" + arguments);
- }
- return arguments;
-}
-
-f1();
diff --git a/tests/test_cases/language/arguments-object/S10.6_A1.js b/tests/test_cases/language/arguments-object/S10.6_A1.js
deleted file mode 100755
index e1ff7841..00000000
--- a/tests/test_cases/language/arguments-object/S10.6_A1.js
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2009 the Sputnik authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-
-/*---
-info: >
- When control enters an execution context for function code,
- an arguments object is created and initialised
-es5id: 10.6_A1
-description: Executing function which uses arguments object
----*/
-
-//CHECK#1
-function f1(){
- return arguments;
-}
-
-try{
- var x = f1();
-}
-catch(e){
- $ERROR("#1: arguments doesn't exists");
-}
-
-//CHECK#2
-var f2 = function(){
- return arguments;
-}
-
-try{
- var x = f2();
-}
-catch(e){
- $ERROR("#2: arguments doesn't exists");
-}
diff --git a/tests/test_cases/language/arguments-object/S10.6_A2.js b/tests/test_cases/language/arguments-object/S10.6_A2.js
deleted file mode 100755
index f5b4d777..00000000
--- a/tests/test_cases/language/arguments-object/S10.6_A2.js
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2009 the Sputnik authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-
-/*---
-info: >
- The value of the internal [[Prototype]] property of the
- created arguments object is the original Object prototype object, the one
- that is the initial value of Object.prototype
-es5id: 10.6_A2
-description: Checking arguments.constructor.prototype===Object.prototype
----*/
-
-//CHECK#1
-function f1(){
- return arguments.constructor.prototype;
-}
-try{
- if(f1() !== Object.prototype){
- $ERROR('#1: arguments.constructor.prototype === Object.prototype');
- }
-}
-catch(e){
- $ERROR("#1: arguments doesn't exists");
-}
-
-//CHECK#2
-var f2 = function(){return arguments.constructor.prototype;};
-try{
- if(f2() !== Object.prototype){
- $ERROR('#2: arguments.constructor.prototype === Object.prototype');
- }
-}
-catch(e){
- $ERROR("#2: arguments doesn't exists");
-}
diff --git a/tests/test_cases/language/arguments-object/S10.6_A3_T1.js b/tests/test_cases/language/arguments-object/S10.6_A3_T1.js
deleted file mode 100755
index 8e4ad5c7..00000000
--- a/tests/test_cases/language/arguments-object/S10.6_A3_T1.js
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2009 the Sputnik authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-
-/*---
-info: >
- A property is created with name callee with property
- attributes { DontEnum } and no others
-es5id: 10.6_A3_T1
-description: Checking existence of arguments.callee property
----*/
-
-//CHECK#1
-function f1(){
- return arguments.hasOwnProperty("callee");
-}
-try{
- if(f1() !== true){
- $ERROR("#1: arguments object doesn't contains property 'callee'");
- }
-}
-catch(e){
- $ERROR("#1: arguments object doesn't exists");
-}
-
-//CHECK#2
-var f2 = function(){return arguments.hasOwnProperty("callee");};
-try{
- if(f2() !== true){
- $ERROR("#2: arguments object doesn't contains property 'callee'");
- }
-}
-catch(e){
- $ERROR("#2: arguments object doesn't exists");
-}
diff --git a/tests/test_cases/language/arguments-object/S10.6_A3_T2.js b/tests/test_cases/language/arguments-object/S10.6_A3_T2.js
deleted file mode 100755
index d06369d6..00000000
--- a/tests/test_cases/language/arguments-object/S10.6_A3_T2.js
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2009 the Sputnik authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-
-/*---
-info: >
- A property is created with name callee with property
- attributes { DontEnum } and no others
-es5id: 10.6_A3_T2
-description: Checking if enumerating the arguments.callee property fails
----*/
-
-//CHECK#1
-function f1(){
- for(var x in arguments){
- if (x === "callee"){
- return false;
- }
- }
- return true;
-}
-
-try{
- if(!f1()){
- $ERROR("#1: A property callee don't have attribute { DontEnum }");
- }
-}
-catch(e){
- $ERROR("#1: arguments object don't exists");
-}
-
-//CHECK#2
-var f2 = function(){
- for(var x in arguments){
- if (x === "callee"){
- return false;
- }
- }
- return true;
-}
-
-try{
- if(!f2()){
- $ERROR("#2: A property callee don't have attribute { DontEnum }");
- }
-}
-catch(e){
- $ERROR("#2: arguments object don't exists");
-}
diff --git a/tests/test_cases/language/arguments-object/S10.6_A3_T3.js b/tests/test_cases/language/arguments-object/S10.6_A3_T3.js
deleted file mode 100755
index 3d735cd3..00000000
--- a/tests/test_cases/language/arguments-object/S10.6_A3_T3.js
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2009 the Sputnik authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-
-/*---
-info: >
- A property is created with name callee with property
- attributes { DontEnum } and no others
-es5id: 10.6_A3_T3
-description: Checking if deleting arguments.callee property fails
-flags: [noStrict]
----*/
-
-//CHECK#1
-function f1(){
- return (delete arguments.callee);
-}
-
-try{
- if(!f1()){
- $ERROR("#1: A property callee have attribute { DontDelete }");
- }
-}
-catch(e){
- $ERROR("#1: arguments object don't exists");
-}
-
-//CHECK#2
-var f2 = function(){
- return (delete arguments.callee);
-}
-
-try{
- if(!f2()){
- $ERROR("#2: A property callee have attribute { DontDelete }");
- }
-}
-catch(e){
- $ERROR("#2: arguments object don't exists");
-}
diff --git a/tests/test_cases/language/arguments-object/S10.6_A3_T4.js b/tests/test_cases/language/arguments-object/S10.6_A3_T4.js
deleted file mode 100755
index 6be7774f..00000000
--- a/tests/test_cases/language/arguments-object/S10.6_A3_T4.js
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2009 the Sputnik authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-
-/*---
-info: >
- A property is created with name callee with property
- attributes { DontEnum } and no others
-es5id: 10.6_A3_T4
-description: Overriding arguments.callee property
-flags: [noStrict]
----*/
-
-var str = "something different";
-//CHECK#1
-function f1(){
- arguments.callee = str;
- return arguments;
-}
-
-try{
- if(f1().callee !== str){
- $ERROR("#1: A property callee have attribute { ReadOnly }");
- }
-}
-catch(e){
- $ERROR("#1: arguments object don't exists");
-}
-
-//CHECK#2
-var f2 = function(){
- arguments.callee = str;
- return arguments;
- }
-try{
- if(f2().callee !== str){
- $ERROR("#2: A property callee have attribute { ReadOnly }");
- }
-}
-catch(e){
- $ERROR("#2: arguments object don't exists");
-}
diff --git a/tests/test_cases/language/arguments-object/S10.6_A4.js b/tests/test_cases/language/arguments-object/S10.6_A4.js
deleted file mode 100755
index 0ed7598b..00000000
--- a/tests/test_cases/language/arguments-object/S10.6_A4.js
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2009 the Sputnik authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-
-/*---
-info: >
- The initial value of the created property callee is the
- Function object being executed
-es5id: 10.6_A4
-description: Checking that arguments.callee === function object
-flags: [noStrict]
----*/
-
-//CHECK#1
-function f1(){
- return arguments.callee;
-}
-
-try{
- if(f1 !== f1()){
- $ERROR('#1: arguments.callee === f1');
- }
-}
-catch(e){
- $ERROR("#1: arguments object doesn't exists");
-}
-
-//CHECK#2
-var f2 = function(){return arguments.callee;};
-
-try{
- if(f2 !== f2()){
- $ERROR('#2: arguments.callee === f2');
- }
-}
-catch(e){
- $ERROR("#1: arguments object doesn't exists");
-}
diff --git a/tests/test_cases/language/arguments-object/S10.6_A5_T1.js b/tests/test_cases/language/arguments-object/S10.6_A5_T1.js
deleted file mode 100755
index df172978..00000000
--- a/tests/test_cases/language/arguments-object/S10.6_A5_T1.js
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2009 the Sputnik authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-
-/*---
-info: >
- A property is created with name length with property
- attributes { DontEnum } and no others
-es5id: 10.6_A5_T1
-description: Checking existence of arguments.length property
----*/
-
-//CHECK#1
-function f1(){
- return arguments.hasOwnProperty("length");
-}
-try{
- if(f1() !== true){
- $ERROR("#1: arguments object doesn't contains property 'length'");
- }
-}
-catch(e){
- $ERROR("#1: arguments object doesn't exists");
-}
-
-//CHECK#2
-var f2 = function(){return arguments.hasOwnProperty("length");};
-try{
- if(f2() !== true){
- $ERROR("#2: arguments object doesn't contains property 'length'");
- }
-}
-catch(e){
- $ERROR("#2: arguments object doesn't exists");
-}
diff --git a/tests/test_cases/language/arguments-object/S10.6_A5_T2.js b/tests/test_cases/language/arguments-object/S10.6_A5_T2.js
deleted file mode 100755
index 47027610..00000000
--- a/tests/test_cases/language/arguments-object/S10.6_A5_T2.js
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2009 the Sputnik authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-
-/*---
-info: >
- A property is created with name length with property
- attributes { DontEnum } and no others
-es5id: 10.6_A5_T2
-description: Checking if enumerating the arguments.length property fails
----*/
-
-//CHECK#1
-function f1(){
- for(var x in arguments){
- if (x === "length"){
- return false;
- }
- }
- return true;
-}
-
-try{
- if(!f1()){
- $ERROR("#1: A property length don't have attribute { DontEnum }");
- }
-}
-catch(e){
- $ERROR("#1: arguments object don't exists");
-}
-
-//CHECK#2
-var f2 = function(){
- for(var x in arguments){
- if (x === "length"){
- return false;
- }
- }
- return true;
-}
-
-try{
- if(!f2()){
- $ERROR("#2: A property length don't have attribute { DontEnum }");
- }
-}
-catch(e){
- $ERROR("#2: arguments object don't exists");
-}
diff --git a/tests/test_cases/language/arguments-object/S10.6_A5_T3.js b/tests/test_cases/language/arguments-object/S10.6_A5_T3.js
deleted file mode 100755
index b2859558..00000000
--- a/tests/test_cases/language/arguments-object/S10.6_A5_T3.js
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2009 the Sputnik authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-
-/*---
-info: >
- A property is created with name length with property
- attributes { DontEnum } and no others
-es5id: 10.6_A5_T3
-description: Checking if deleting arguments.length property fails
----*/
-
-//CHECK#1
-function f1(){
- return (delete arguments.length);
-}
-
-try{
- if(!f1()){
- $ERROR("#1: A property length have attribute { DontDelete }");
- }
-}
-catch(e){
- $ERROR("#1: arguments object don't exists");
-}
-
-//CHECK#2
-var f2 = function(){
- return (delete arguments.length);
-}
-
-try{
- if(!f2()){
- $ERROR("#2: A property length have attribute { DontDelete }");
- }
-}
-catch(e){
- $ERROR("#2: arguments object don't exists");
-}
diff --git a/tests/test_cases/language/arguments-object/S10.6_A5_T4.js b/tests/test_cases/language/arguments-object/S10.6_A5_T4.js
deleted file mode 100755
index 4336f11c..00000000
--- a/tests/test_cases/language/arguments-object/S10.6_A5_T4.js
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2009 the Sputnik authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-
-/*---
-info: >
- A property is created with name length with property
- attributes { DontEnum } and no others
-es5id: 10.6_A5_T4
-description: Overriding arguments.length property
----*/
-
-var str = "something different";
-//CHECK#1
-function f1(){
- arguments.length = str;
- return arguments;
-}
-
-try{
- if(f1().length !== str){
- $ERROR("#1: A property length have attribute { ReadOnly }");
- }
-}
-catch(e){
- $ERROR("#1: arguments object don't exists");
-}
-
-//CHECK#2
-var f2 = function(){
- arguments.length = str;
- return arguments;
- };
-try{
- if(f2().length !== str){
- $ERROR("#2: A property length have attribute { ReadOnly }");
- }
-}
-catch(e){
- $ERROR("#2: arguments object don't exists");
-}
diff --git a/tests/test_cases/language/arguments-object/S10.6_A6.js b/tests/test_cases/language/arguments-object/S10.6_A6.js
deleted file mode 100755
index e0eaf30a..00000000
--- a/tests/test_cases/language/arguments-object/S10.6_A6.js
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2009 the Sputnik authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-
-/*---
-info: >
- The initial value of the created property length is the number
- of actual parameter values supplied by the caller
-es5id: 10.6_A6
-description: Create function, that returned arguments.length
----*/
-
-function f1(){
- return arguments.length;
-}
-
-//CHECK#1
-if(!(f1() === 0)){
- $ERROR('#1: argument.length === 0');
-}
-
-//CHECK#2
-if(!(f1(0) === 1)){
- $ERROR('#2: argument.length === 1');
-}
-
-//CHECK#3
-if(!(f1(0, 1) === 2)){
- $ERROR('#3: argument.length === 2');
-}
-
-//CHECK#4
-if(!(f1(0, 1, 2) === 3)){
- $ERROR('#4: argument.length === 3');
-}
-
-//CHECK#5
-if(!(f1(0, 1, 2, 3) === 4)){
- $ERROR('#5: argument.length === 4');
-}
-
-var f2 = function(){return arguments.length;};
-
-//CHECK#6
-if(!(f2() === 0)){
- $ERROR('#6: argument.length === 0');
-}
-
-//CHECK#7
-if(!(f2(0) === 1)){
- $ERROR('#7: argument.length === 1');
-}
-
-//CHECK#8
-if(!(f2(0, 1) === 2)){
- $ERROR('#8: argument.length === 2');
-}
-
-//CHECK#9
-if(!(f2(0, 1, 2) === 3)){
- $ERROR('#9: argument.length === 3');
-}
-
-//CHECK#10
-if(!(f2(0, 1, 2, 3) === 4)){
- $ERROR('#10: argument.length === 4');
-}
diff --git a/tests/test_cases/language/arguments-object/S10.6_A7.js b/tests/test_cases/language/arguments-object/S10.6_A7.js
deleted file mode 100755
index 7012e9f9..00000000
--- a/tests/test_cases/language/arguments-object/S10.6_A7.js
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2009 the Sputnik authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-
-/*---
-info: Get arguments of function
-es5id: 10.6_A7
-description: Use property arguments
----*/
-
-function f1() {
- return arguments;
-}
-
-//CHECK#1-5
-for(var i = 1; i < 5; i++){
-if (f1(1,2,3,4,5)[i] !== (i+1))
- $ERROR("#"+i+": Returning function's arguments work wrong, f1(1,2,3,4,5)["+i+"] !== "+(i+1));
-}
diff --git a/tests/test_cases/language/asi/S7.9_A5.7_T1.js b/tests/test_cases/language/asi/S7.9_A5.7_T1.js
deleted file mode 100755
index d61fc101..00000000
--- a/tests/test_cases/language/asi/S7.9_A5.7_T1.js
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2009 the Sputnik authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-
-/*---
-info: >
-
- Since LineTerminator(LT) between Postfix Increment/Decrement
- Operator(I/DO) and operand is not allowed, two IO(just as two DO
- and their combination) between two references separated by [LT]
- after automatic semicolon insertion lead to syntax error
- ES6 specifies this as `ReferenceError`
-
-es5id: 7.9_A5.7_T1
-description: Try use Variable1 \n ++ \n ++ \n Variable2 construction
-negative: ReferenceError
----*/
-
-var x=0, y=0;
-var z=
-x
-++
-++
-y
diff --git a/tests/test_cases/language/statements/function/S13.2.1_A1_T1.js b/tests/test_cases/language/statements/function/S13.2.1_A1_T1.js
index 5fb7a9a5..7ed84848 100755
--- a/tests/test_cases/language/statements/function/S13.2.1_A1_T1.js
+++ b/tests/test_cases/language/statements/function/S13.2.1_A1_T1.js
@@ -7,66 +7,3 @@ es5id: 13.2.1_A1_T1
description: Creating function calls 32 elements depth
---*/
-(function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){
- (function(){})()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
- })()
-})()