annotate pydertron.py @ 21:cb73bb169b67

Added html docs.
author Atul Varma <varmaa@toolness.com>
date Thu, 10 Sep 2009 16:37:33 -0700
parents d382ca63d43f
children 915fdf283ac5
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
18
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
1 # ***** BEGIN LICENSE BLOCK *****
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
2 # Version: MPL 1.1/GPL 2.0/LGPL 2.1
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
3 #
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
4 # The contents of this file are subject to the Mozilla Public License Version
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
5 # 1.1 (the "License"); you may not use this file except in compliance with
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
6 # the License. You may obtain a copy of the License at
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
7 # http://www.mozilla.org/MPL/
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
8 #
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
9 # Software distributed under the License is distributed on an "AS IS" basis,
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
10 # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
11 # for the specific language governing rights and limitations under the
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
12 # License.
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
13 #
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
14 # The Original Code is Pydertron.
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
15 #
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
16 # The Initial Developer of the Original Code is Mozilla.
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
17 # Portions created by the Initial Developer are Copyright (C) 2007
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
18 # the Initial Developer. All Rights Reserved.
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
19 #
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
20 # Contributor(s):
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
21 # Atul Varma <atul@mozilla.com>
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
22 #
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
23 # Alternatively, the contents of this file may be used under the terms of
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
24 # either the GNU General Public License Version 2 or later (the "GPL"), or
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
25 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
26 # in which case the provisions of the GPL or the LGPL are applicable instead
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
27 # of those above. If you wish to allow use of your version of this file only
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
28 # under the terms of either the GPL or the LGPL, and not to allow others to
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
29 # use your version of this file under the terms of the MPL, indicate your
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
30 # decision by deleting the provisions above and replace them with the notice
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
31 # and other provisions required by the GPL or the LGPL. If you do not delete
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
32 # the provisions above, a recipient may use your version of this file under
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
33 # the terms of any one of the MPL, the GPL or the LGPL.
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
34 #
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
35 # ***** END LICENSE BLOCK *****
9fe3f115f951 Added license blocks.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
36
16
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
37 """
21
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
38 Pydertron is a high-level wrapper for `Pydermonkey`__ that
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
39 provides convenient, secure object wrapping between JS and Python
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
40 space.
20
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
41
21
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
42 The ``JsSandbox`` class encapsulates a JavaScript runtime, context, global
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
43 object, and a simple `SecurableModule`__ implementation that complies
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
44 with the `CommonJS`__ standard. It also provides a high-level bridge between
20
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
45 Python and JavaScript so that you don't need to deal with any of the
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
46 low-level details of the Pydermonkey API.
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
47
21
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
48 __ http://code.google.com/p/pydermonkey
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
49 __ http://wiki.commonjs.org/wiki/CommonJS/Modules/SecurableModules
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
50 __ http://wiki.commonjs.org/wiki/CommonJS
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
51
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
52 For instance, here we'll create a ``JsSandbox`` whose module root
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
53 points to the ``monkeys`` SecurableModule compliance test over HTTP:
20
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
54
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
55 >>> url = ("http://interoperablejs.googlecode.com/svn/trunk/"
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
56 ... "compliance/monkeys/")
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
57 >>> sandbox = JsSandbox(HttpFileSystem(url))
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
58
21
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
59 This compliance test requires a global ``sys`` object that contains one
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
60 method, ``print()``, that takes two arguments. First, we'll create the
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
61 ``print()`` function and prepare it for exposure to JS code:
20
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
62
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
63 >>> @jsexposed
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
64 ... def jsprint(message, label):
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
65 ... print message, label
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
66
21
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
67 Note the use of the ``@jsexposed`` decorator: all this does is set
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
68 the function's ``__jsexposed__`` attribute to ``True``. This is
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
69 done for security purposes: only Python callables satisfying this
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
70 criteria will be exposed to JavaScript code, to ensure that
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
71 untrusted JS can't accidentally gain access to privileged Python
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
72 functionality.
20
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
73
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
74 Creating a JS object can be done like this:
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
75
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
76 >>> system = sandbox.new_object()
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
77
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
78 We can now access and set properties on this object via either
21
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
79 item or attribute lookup, just like in JavaScript. Because
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
80 ``print`` is a reserved word in Python, though, we'll use item
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
81 lookup to set the property here:
20
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
82
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
83 >>> system['print'] = jsprint
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
84
21
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
85 Now we tell the sandbox that we want the ``sys`` object to be a
20
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
86 global:
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
87
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
88 >>> sandbox.set_globals(sys = system)
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
89
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
90 And finally, we execute the compliance test by running a one-line
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
91 script that imports the 'program' module, like so:
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
92
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
93 >>> sandbox.run_script("require('program');")
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
94 PASS monkeys permitted pass
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
95 DONE info
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
96 0
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
97
21
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
98 Note the ``0`` in the last line: this is the return value of
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
99 ``sandbox.run_script()``, which returns ``0`` on success, and
cb73bb169b67 Added html docs.
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
100 ``-1`` if an exception was raised. For instance, the output of bad
20
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
101 code looks like this:
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
102
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
103 >>> sandbox.run_script("(function foo() { bar(); })();",
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
104 ... stderr=sys.stdout)
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
105 Traceback (most recent call last):
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
106 File "<string>", line 1, in <module>
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
107 File "<string>", line 1, in foo
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
108 ReferenceError: bar is not defined
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
109 -1
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
110
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
111 Note that the traceback displayed is actually referring to
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
112 JavaScript code: one of Pydertron's helpful conveniences is that
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
113 it makes debugging JS code as much like debugging Python code as
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
114 possible.
16
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
115 """
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
116
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
117 import sys
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
118 import threading
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
119 import traceback
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
120 import weakref
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
121 import types
7
2117265e4dfe Fixed some threading issues.
Atul Varma <varmaa@toolness.com>
parents: 6
diff changeset
122 import atexit
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
123
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
124 import pydermonkey
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
125
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
126 class ContextWatchdogThread(threading.Thread):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
127 """
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
128 Watches active JS contexts and triggers their operation callbacks
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
129 at a regular interval.
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
130 """
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
131
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
132 # Default interval, in seconds, that the operation callbacks are
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
133 # triggered at.
8
fb0b161542b1 Improved performance of watchdog thread.
Atul Varma <varmaa@toolness.com>
parents: 7
diff changeset
134 DEFAULT_INTERVAL = 0.25
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
135
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
136 def __init__(self, interval=DEFAULT_INTERVAL):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
137 threading.Thread.__init__(self)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
138 self._lock = threading.Lock()
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
139 self._stop = threading.Event()
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
140 self._contexts = []
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
141 self.interval = interval
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
142
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
143 def add_context(self, cx):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
144 self._lock.acquire()
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
145 try:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
146 self._contexts.append(weakref.ref(cx))
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
147 finally:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
148 self._lock.release()
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
149
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
150 def join(self):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
151 self._stop.set()
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
152 threading.Thread.join(self)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
153
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
154 def run(self):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
155 while not self._stop.isSet():
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
156 new_list = []
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
157 self._lock.acquire()
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
158 try:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
159 for weakcx in self._contexts:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
160 cx = weakcx()
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
161 if cx:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
162 new_list.append(weakcx)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
163 cx.trigger_operation_callback()
7
2117265e4dfe Fixed some threading issues.
Atul Varma <varmaa@toolness.com>
parents: 6
diff changeset
164 del cx
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
165 self._contexts = new_list
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
166 finally:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
167 self._lock.release()
8
fb0b161542b1 Improved performance of watchdog thread.
Atul Varma <varmaa@toolness.com>
parents: 7
diff changeset
168 self._stop.wait(self.interval)
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
169
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
170 # Create a global watchdog.
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
171 watchdog = ContextWatchdogThread()
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
172 watchdog.start()
7
2117265e4dfe Fixed some threading issues.
Atul Varma <varmaa@toolness.com>
parents: 6
diff changeset
173 atexit.register(watchdog.join)
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
174
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
175 class InternalError(BaseException):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
176 """
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
177 Represents an error in a JS-wrapped Python function that wasn't
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
178 expected to happen; because it's derived from BaseException, it
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
179 unrolls the whole JS/Python stack so that the error can be
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
180 reported to the outermost calling code.
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
181 """
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
182
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
183 def __init__(self):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
184 BaseException.__init__(self)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
185 self.exc_info = sys.exc_info()
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
186
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
187 class SafeJsObjectWrapper(object):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
188 """
16
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
189 Securely wraps a JS object to behave like any normal Python
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
190 object. Like JS objects, though, accessing undefined object
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
191 results merely in pydermonkey.undefined.
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
192
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
193 Object properties may be accessed either via attribute or
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
194 item-based lookup.
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
195 """
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
196
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
197 __slots__ = ['_jsobject', '_sandbox', '_this']
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
198
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
199 def __init__(self, sandbox, jsobject, this):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
200 if not isinstance(jsobject, pydermonkey.Object):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
201 raise TypeError("Cannot wrap '%s' object" %
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
202 type(jsobject).__name__)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
203 object.__setattr__(self, '_sandbox', sandbox)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
204 object.__setattr__(self, '_jsobject', jsobject)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
205 object.__setattr__(self, '_this', this)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
206
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
207 @property
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
208 def wrapped_jsobject(self):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
209 return self._jsobject
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
210
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
211 def _wrap_to_python(self, jsvalue):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
212 return self._sandbox.wrap_jsobject(jsvalue, self._jsobject)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
213
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
214 def _wrap_to_js(self, value):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
215 return self._sandbox.wrap_pyobject(value)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
216
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
217 def __eq__(self, other):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
218 if isinstance(other, SafeJsObjectWrapper):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
219 return self._jsobject == other._jsobject
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
220 else:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
221 return False
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
222
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
223 def __str__(self):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
224 return self.toString()
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
225
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
226 def __unicode__(self):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
227 return self.toString()
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
228
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
229 def __setitem__(self, item, value):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
230 self.__setattr__(item, value)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
231
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
232 def __setattr__(self, name, value):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
233 cx = self._sandbox.cx
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
234 jsobject = self._jsobject
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
235
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
236 cx.define_property(jsobject, name,
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
237 self._wrap_to_js(value))
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
238
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
239 def __getitem__(self, item):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
240 return self.__getattr__(item)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
241
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
242 def __getattr__(self, name):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
243 cx = self._sandbox.cx
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
244 jsobject = self._jsobject
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
245
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
246 return self._wrap_to_python(cx.get_property(jsobject, name))
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
247
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
248 def __contains__(self, item):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
249 cx = self._sandbox.cx
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
250 jsobject = self._jsobject
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
251
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
252 return cx.has_property(jsobject, item)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
253
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
254 def __iter__(self):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
255 cx = self._sandbox.cx
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
256 jsobject = self._jsobject
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
257
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
258 properties = cx.enumerate(jsobject)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
259 for property in properties:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
260 yield property
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
261
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
262 class SafeJsFunctionWrapper(SafeJsObjectWrapper):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
263 """
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
264 Securely wraps a JS function to behave like any normal Python object.
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
265 """
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
266
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
267 def __init__(self, sandbox, jsfunction, this):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
268 if not isinstance(jsfunction, pydermonkey.Function):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
269 raise TypeError("Cannot wrap '%s' object" %
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
270 type(jsobject).__name__)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
271 SafeJsObjectWrapper.__init__(self, sandbox, jsfunction, this)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
272
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
273 def __call__(self, *args):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
274 cx = self._sandbox.cx
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
275 jsobject = self._jsobject
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
276 this = self._this
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
277
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
278 arglist = []
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
279 for arg in args:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
280 arglist.append(self._wrap_to_js(arg))
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
281
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
282 obj = cx.call_function(this, jsobject, tuple(arglist))
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
283 return self._wrap_to_python(obj)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
284
11
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
285 def format_stack(js_stack, open=open):
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
286 """
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
287 Returns a formatted Python-esque stack traceback of the given
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
288 JS stack.
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
289 """
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
290
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
291 STACK_LINE =" File \"%(filename)s\", line %(lineno)d, in %(name)s"
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
292
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
293 lines = []
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
294 while js_stack:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
295 script = js_stack['script']
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
296 function = js_stack['function']
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
297 if script:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
298 frameinfo = dict(filename = script.filename,
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
299 lineno = js_stack['lineno'],
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
300 name = '<module>')
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
301 elif function and not function.is_python:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
302 frameinfo = dict(filename = function.filename,
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
303 lineno = js_stack['lineno'],
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
304 name = function.name)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
305 else:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
306 frameinfo = None
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
307 if frameinfo:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
308 lines.insert(0, STACK_LINE % frameinfo)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
309 try:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
310 filelines = open(frameinfo['filename']).readlines()
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
311 line = filelines[frameinfo['lineno'] - 1].strip()
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
312 lines.insert(1, " %s" % line)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
313 except Exception:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
314 pass
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
315 js_stack = js_stack['caller']
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
316 lines.insert(0, "Traceback (most recent call last):")
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
317 return '\n'.join(lines)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
318
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
319 def jsexposed(name=None, on=None):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
320 """
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
321 Decorator used to expose the decorated function or method to
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
322 untrusted JS.
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
323
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
324 'name' is an optional alternative name for the function.
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
325
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
326 'on' is an optional SafeJsObjectWrapper that the function can be
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
327 automatically attached as a property to.
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
328 """
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
329
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
330 if callable(name):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
331 func = name
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
332 func.__jsexposed__ = True
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
333 return func
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
334
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
335 def make_exposed(func):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
336 if name:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
337 func.__name__ = name
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
338 func.__jsexposed__ = True
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
339 if on:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
340 on[func.__name__] = func
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
341 return func
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
342 return make_exposed
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
343
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
344 class JsExposedObject(object):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
345 """
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
346 Trivial base/mixin class for any Python classes that choose to
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
347 expose themselves to JS code.
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
348 """
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
349
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
350 pass
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
351
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
352 class JsSandbox(object):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
353 """
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
354 A JS runtime and associated functionality capable of securely
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
355 loading and executing scripts.
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
356 """
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
357
19
2dc43c316df9 Added opcb parameter
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
358 def __init__(self, fs, watchdog=watchdog, opcb=None):
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
359 rt = pydermonkey.Runtime()
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
360 cx = rt.new_context()
2
b6f9d743a2b5 Refined require() implementation.
Atul Varma <varmaa@toolness.com>
parents: 1
diff changeset
361 root_proto = cx.new_object()
b6f9d743a2b5 Refined require() implementation.
Atul Varma <varmaa@toolness.com>
parents: 1
diff changeset
362 cx.init_standard_classes(root_proto)
b6f9d743a2b5 Refined require() implementation.
Atul Varma <varmaa@toolness.com>
parents: 1
diff changeset
363 root = cx.new_object(None, root_proto)
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
364
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
365 cx.set_operation_callback(self._opcb)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
366 cx.set_throw_hook(self._throwhook)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
367 watchdog.add_context(cx)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
368
11
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
369 self.fs = fs
19
2dc43c316df9 Added opcb parameter
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
370 self.opcb = opcb
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
371 self.rt = rt
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
372 self.cx = cx
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
373 self.curr_exc = None
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
374 self.py_stack = None
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
375 self.js_stack = None
11
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
376 self.__modules = {}
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
377 self.__py_to_js = {}
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
378 self.__type_protos = {}
11
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
379 self.__globals = {}
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
380 self.__root_proto = root_proto
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
381 self.root = self.wrap_jsobject(root, root)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
382
11
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
383 def set_globals(self, **globals):
16
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
384 """
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
385 Sets the global properties for the root object and all global
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
386 scopes (e.g., SecurableModules). This should be called before
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
387 any scripts are executed.
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
388 """
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
389
11
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
390 self.__globals.update(globals)
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
391 self._install_globals(self.root)
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
392
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
393 def finish(self):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
394 """
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
395 Cleans up all resources used by the sandbox, breaking any reference
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
396 cycles created due to issue #2 in pydermonkey:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
397
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
398 http://code.google.com/p/pydermonkey/issues/detail?id=2
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
399 """
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
400
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
401 for jsobj in self.__py_to_js.values():
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
402 self.cx.clear_object_private(jsobj)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
403 del self.__py_to_js
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
404 del self.__type_protos
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
405 del self.curr_exc
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
406 del self.py_stack
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
407 del self.js_stack
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
408 del self.cx
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
409 del self.rt
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
410
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
411 def _opcb(self, cx):
19
2dc43c316df9 Added opcb parameter
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
412 # Note that if a keyboard interrupt was triggered,
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
413 # it'll get raised here automatically.
19
2dc43c316df9 Added opcb parameter
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
414 if self.opcb:
2dc43c316df9 Added opcb parameter
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
415 self.opcb()
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
416
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
417 def _throwhook(self, cx):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
418 curr_exc = cx.get_pending_exception()
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
419 if self.curr_exc != curr_exc:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
420 self.curr_exc = curr_exc
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
421 self.py_stack = traceback.extract_stack()
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
422 self.js_stack = cx.get_stack()
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
423
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
424 def __wrap_pycallable(self, func, pyproto=None):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
425 if func in self.__py_to_js:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
426 return self.__py_to_js[func]
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
427
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
428 if hasattr(func, '__name__'):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
429 name = func.__name__
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
430 else:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
431 name = ""
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
432
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
433 if pyproto:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
434 def wrapper(func_cx, this, args):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
435 try:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
436 arglist = []
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
437 for arg in args:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
438 arglist.append(self.wrap_jsobject(arg))
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
439 instance = func_cx.get_object_private(this)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
440 if instance is None or not isinstance(instance, pyproto):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
441 raise pydermonkey.error("Method type mismatch")
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
442
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
443 # TODO: Fill in extra required params with
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
444 # pymonkey.undefined? or automatically throw an
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
445 # exception to calling js code?
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
446 return self.wrap_pyobject(func(instance, *arglist))
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
447 except pydermonkey.error:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
448 raise
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
449 except Exception:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
450 raise InternalError()
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
451 else:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
452 def wrapper(func_cx, this, args):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
453 try:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
454 arglist = []
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
455 for arg in args:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
456 arglist.append(self.wrap_jsobject(arg))
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
457
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
458 # TODO: Fill in extra required params with
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
459 # pymonkey.undefined? or automatically throw an
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
460 # exception to calling js code?
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
461 return self.wrap_pyobject(func(*arglist))
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
462 except pydermonkey.error:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
463 raise
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
464 except Exception:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
465 raise InternalError()
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
466 wrapper.wrapped_pyobject = func
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
467 wrapper.__name__ = name
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
468
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
469 jsfunc = self.cx.new_function(wrapper, name)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
470 self.__py_to_js[func] = jsfunc
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
471
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
472 return jsfunc
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
473
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
474 def __wrap_pyinstance(self, value):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
475 pyproto = type(value)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
476 if pyproto not in self.__type_protos:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
477 jsproto = self.cx.new_object()
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
478 if hasattr(pyproto, '__jsprops__'):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
479 define_getter = self.cx.get_property(jsproto,
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
480 '__defineGetter__')
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
481 define_setter = self.cx.get_property(jsproto,
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
482 '__defineSetter__')
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
483 for name in pyproto.__jsprops__:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
484 prop = getattr(pyproto, name)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
485 if not type(prop) == property:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
486 raise TypeError("Expected attribute '%s' to "
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
487 "be a property" % name)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
488 getter = None
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
489 setter = None
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
490 if prop.fget:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
491 getter = self.__wrap_pycallable(prop.fget,
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
492 pyproto)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
493 if prop.fset:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
494 setter = self.__wrap_pycallable(prop.fset,
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
495 pyproto)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
496 if getter:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
497 self.cx.call_function(jsproto,
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
498 define_getter,
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
499 (name, getter))
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
500 if setter:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
501 self.cx.call_function(jsproto,
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
502 define_setter,
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
503 (name, setter,))
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
504 for name in dir(pyproto):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
505 attr = getattr(pyproto, name)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
506 if (isinstance(attr, types.UnboundMethodType) and
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
507 hasattr(attr, '__jsexposed__') and
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
508 attr.__jsexposed__):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
509 jsmethod = self.__wrap_pycallable(attr, pyproto)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
510 self.cx.define_property(jsproto, name, jsmethod)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
511 self.__type_protos[pyproto] = jsproto
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
512 return self.cx.new_object(value, self.__type_protos[pyproto])
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
513
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
514 def wrap_pyobject(self, value):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
515 """
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
516 Wraps the given Python object for export to untrusted JS.
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
517
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
518 If the Python object isn't of a type that can be exposed to JS,
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
519 a TypeError is raised.
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
520 """
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
521
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
522 if (isinstance(value, (int, basestring, float, bool)) or
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
523 value is pydermonkey.undefined or
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
524 value is None):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
525 return value
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
526 if isinstance(value, SafeJsObjectWrapper):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
527 # It's already wrapped, just unwrap it.
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
528 return value.wrapped_jsobject
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
529 elif callable(value):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
530 if not (hasattr(value, '__jsexposed__') and
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
531 value.__jsexposed__):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
532 raise ValueError("Callable isn't configured for exposure "
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
533 "to untrusted JS code")
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
534 return self.__wrap_pycallable(value)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
535 elif isinstance(value, JsExposedObject):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
536 return self.__wrap_pyinstance(value)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
537 else:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
538 raise TypeError("Can't expose objects of type '%s' to JS." %
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
539 type(value).__name__)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
540
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
541 def wrap_jsobject(self, jsvalue, this=None):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
542 """
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
543 Wraps the given pydermonkey.Object for import to trusted
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
544 Python code. If the type is just a primitive, it's simply
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
545 returned, since no wrapping is needed.
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
546 """
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
547
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
548 if this is None:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
549 this = self.root.wrapped_jsobject
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
550 if isinstance(jsvalue, pydermonkey.Function):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
551 if jsvalue.is_python:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
552 # It's a Python function, just unwrap it.
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
553 return self.cx.get_object_private(jsvalue).wrapped_pyobject
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
554 return SafeJsFunctionWrapper(self, jsvalue, this)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
555 elif isinstance(jsvalue, pydermonkey.Object):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
556 # It's a wrapped Python object instance, just unwrap it.
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
557 instance = self.cx.get_object_private(jsvalue)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
558 if instance:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
559 if not isinstance(instance, JsExposedObject):
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
560 raise AssertionError("Object private is not of type "
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
561 "JsExposedObject")
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
562 return instance
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
563 else:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
564 return SafeJsObjectWrapper(self, jsvalue, this)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
565 else:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
566 # It's a primitive value.
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
567 return jsvalue
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
568
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
569 def new_array(self, *contents):
16
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
570 """
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
571 Creates a new JavaScript array with the given contents and
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
572 returns a wrapper for it.
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
573 """
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
574
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
575 array = self.wrap_jsobject(self.cx.new_array_object())
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
576 for item in contents:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
577 array.push(item)
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
578 return array
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
579
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
580 def new_object(self, **contents):
16
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
581 """
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
582 Creates a new JavaScript object with the given properties and
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
583 returns a wrapper for it.
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
584 """
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
585
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
586 obj = self.wrap_jsobject(self.cx.new_object())
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
587 for name in contents:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
588 obj[name] = contents[name]
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
589 return obj
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
590
11
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
591 def get_calling_script(self):
16
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
592 """
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
593 Returns the filename of the current stack's most recent
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
594 JavaScript caller.
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
595 """
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
596
11
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
597 frame = self.cx.get_stack()['caller']
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
598 curr_script = None
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
599 while frame and curr_script is None:
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
600 if frame['function'] and frame['function'].filename:
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
601 curr_script = frame['function'].filename
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
602 elif frame['script']:
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
603 curr_script = frame['script'].filename
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
604 frame = frame['caller']
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
605
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
606 if curr_script is None:
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
607 raise RuntimeError("Can't find calling script")
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
608 return curr_script
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
609
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
610 def _install_globals(self, object):
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
611 for name in self.__globals:
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
612 object[name] = self.__globals[name]
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
613 object['require'] = self._require
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
614
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
615 @jsexposed(name='require')
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
616 def _require(self, path):
16
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
617 """
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
618 Implementation for the global require() function, implemented
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
619 as per the CommonJS SecurableModule specification:
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
620
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
621 http://wiki.commonjs.org/wiki/CommonJS/Modules/SecurableModules
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
622 """
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
623
11
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
624 filename = self.fs.find_module(self.get_calling_script(), path)
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
625 if not filename:
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
626 raise pydermonkey.error('Module not found: %s' % path)
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
627 if not filename in self.__modules:
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
628 cx = self.cx
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
629 module = cx.new_object(None, self.__root_proto)
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
630 cx.init_standard_classes(module)
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
631 exports = cx.new_object()
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
632 cx.define_property(module, 'exports', exports)
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
633 self._install_globals(self.wrap_jsobject(module))
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
634 self.__modules[filename] = self.wrap_jsobject(exports)
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
635 contents = self.fs.open(filename).read()
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
636 cx.evaluate_script(module, contents, filename, 1)
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
637 return self.__modules[filename]
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
638
6
97adec8c8127 Now passing all CommonJS SecurableModule compliance tests.
Atul Varma <varmaa@toolness.com>
parents: 5
diff changeset
639 def run_script(self, contents, filename='<string>', lineno=1,
20
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
640 callback=None, stderr=None):
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
641 """
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
642 Runs the given JS script, returning 0 on success, -1 on failure.
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
643 """
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
644
20
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
645 if stderr is None:
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
646 stderr = sys.stderr
d382ca63d43f Added docs with doctests.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
647
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
648 retval = -1
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
649 cx = self.cx
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
650 try:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
651 result = cx.evaluate_script(self.root.wrapped_jsobject,
6
97adec8c8127 Now passing all CommonJS SecurableModule compliance tests.
Atul Varma <varmaa@toolness.com>
parents: 5
diff changeset
652 contents, filename, lineno)
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
653 if callback:
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
654 callback(self.wrap_jsobject(result))
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
655 retval = 0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
656 except pydermonkey.error, e:
11
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
657 params = dict(
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
658 stack_trace = format_stack(self.js_stack, self.fs.open),
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
659 error = e.args[1]
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
660 )
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
661 stderr.write("%(stack_trace)s\n%(error)s\n" % params)
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
662 except InternalError, e:
11
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
663 stderr.write("An internal error occurred.\n")
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
664 traceback.print_tb(e.exc_info[2], None, stderr)
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
665 stderr.write("%s\n" % e.exc_info[1])
0
a5b09b685df4 Origination
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
666 return retval
1
ab09b8a10876 Added trivial half-baked implementation of securable modules.
Atul Varma <varmaa@toolness.com>
parents: 0
diff changeset
667
14
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
668 class HttpFileSystem(object):
16
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
669 """
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
670 File system through which all resources are loaded over HTTP.
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
671 """
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
672
14
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
673 def __init__(self, base_url):
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
674 self.base_url = base_url
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
675
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
676 def find_module(self, curr_url, path):
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
677 import urlparse
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
678
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
679 if path.startswith("."):
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
680 base_url = curr_url
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
681 else:
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
682 base_url = self.base_url
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
683
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
684 url = "%s.js" % urlparse.urljoin(base_url, path)
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
685 if not url.startswith(self.base_url):
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
686 return None
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
687 return url
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
688
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
689 def open(self, url):
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
690 import urllib
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
691
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
692 return urllib.urlopen(url)
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
693
16
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
694 class LocalFileSystem(object):
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
695 """
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
696 File system through which all resources are loaded over the local
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
697 filesystem.
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
698 """
9426f9fa6dc0 Added docs.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
699
11
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
700 def __init__(self, root_dir):
3
14d8d73774d7 Refactored securable module loader.
Atul Varma <varmaa@toolness.com>
parents: 2
diff changeset
701 self.root_dir = root_dir
2
b6f9d743a2b5 Refined require() implementation.
Atul Varma <varmaa@toolness.com>
parents: 1
diff changeset
702
11
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
703 def find_module(self, curr_script, path):
14
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
704 import os
16fe9c63aedb Added HttpFileSystem
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
705
11
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
706 if path.startswith("."):
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
707 base_dir = os.path.dirname(curr_script)
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
708 else:
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
709 base_dir = self.root_dir
2
b6f9d743a2b5 Refined require() implementation.
Atul Varma <varmaa@toolness.com>
parents: 1
diff changeset
710
11
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
711 ospath = path.replace('/', os.path.sep)
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
712 filename = os.path.join(base_dir, "%s.js" % ospath)
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
713 filename = os.path.normpath(filename)
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
714 if (filename.startswith(self.root_dir) and
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
715 (os.path.exists(filename) and
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
716 not os.path.isdir(filename))):
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
717 return filename
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
718 else:
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
719 return None
3
14d8d73774d7 Refactored securable module loader.
Atul Varma <varmaa@toolness.com>
parents: 2
diff changeset
720
11
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
721 def open(self, filename):
665f69f61716 Some refactorings
Atul Varma <varmaa@toolness.com>
parents: 9
diff changeset
722 return open(filename, 'r')