Skip to content

Commit b80f714

Browse files
author
hartsantler
committed
improved webworker support
1 parent bdcc3b9 commit b80f714

8 files changed

Lines changed: 230 additions & 128 deletions

File tree

pythonjs/python_to_pythonjs.py

Lines changed: 60 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ def __init__(self, source=None, module=None, module_path=None, dart=False, coffe
135135
self._use_threading = False
136136
self._use_sleep = False
137137
self._webworker_functions = dict()
138+
self._with_webworker = False
138139

139140
self._source = source.splitlines()
140141
self._classes = dict() ## class name : [method names]
@@ -1672,7 +1673,9 @@ def visit_Call(self, node):
16721673

16731674
name = self.visit(node.func)
16741675
if self._use_threading and isinstance(node.func, ast.Attribute) and isinstance(node.func.value, Name) and node.func.value.id == 'threading':
1675-
if node.func.attr == 'start_new_thread':
1676+
if node.func.attr == 'start_new_thread' or node.func.attr == '_start_new_thread':
1677+
return '__start_new_thread( %s, %s )' %(self.visit(node.args[0]), self.visit(node.args[1]))
1678+
elif node.func.attr == 'start_webworker':
16761679
return '__start_new_thread( %s, %s )' %(self.visit(node.args[0]), self.visit(node.args[1]))
16771680
else:
16781681
raise SyntaxError(node.func.attr)
@@ -2120,7 +2123,6 @@ def visit_FunctionDef(self, node):
21202123
log('function: %s'%node.name)
21212124

21222125
is_worker_entry = False
2123-
threaded = False
21242126
property_decorator = None
21252127
decorators = []
21262128
with_js_decorators = []
@@ -2130,6 +2132,11 @@ def visit_FunctionDef(self, node):
21302132
fastdef = False
21312133
javascript = False
21322134
inline = False
2135+
threaded = self._with_webworker
2136+
jsfile = None
2137+
2138+
2139+
## deprecated?
21332140
self._cached_property = None
21342141
self._func_typedefs = {}
21352142

@@ -2147,25 +2154,6 @@ def visit_FunctionDef(self, node):
21472154
threaded = True
21482155
assert len(decorator.args) == 1
21492156
jsfile = decorator.args[0].s
2150-
writer_main.write('%s = "%s"' %(node.name, jsfile))
2151-
self._webworker_functions[ node.name ] = jsfile
2152-
2153-
writer = get_webworker_writer( jsfile )
2154-
if writer.output.len == 0:
2155-
is_worker_entry = True
2156-
## TODO: two-way list and dict sync
2157-
writer.write('__wargs__ = []')
2158-
writer.write('def onmessage(e):')
2159-
writer.push()
2160-
writer.write( 'print("worker got message from parent")' )
2161-
writer.write( 'print(e.data)' )
2162-
writer.write( 'if e.data.type=="execute": %s.apply(self, e.data.args); self.postMessage({"type":"terminate"})' %node.name )
2163-
writer.write( 'elif e.data.type=="append": __wargs__[ e.data.argindex ].push( e.data.value )' )
2164-
2165-
writer.write( 'print(__wargs__)' )
2166-
2167-
writer.pull()
2168-
writer.write('self.onmessage = onmessage' )
21692157

21702158

21712159
elif self._with_dart:
@@ -2230,6 +2218,30 @@ def visit_FunctionDef(self, node):
22302218
else:
22312219
decorators.append( decorator )
22322220

2221+
2222+
if threaded:
2223+
if not jsfile: jsfile = 'worker.js'
2224+
writer_main.write('%s = "%s"' %(node.name, jsfile))
2225+
self._webworker_functions[ node.name ] = jsfile
2226+
2227+
writer = get_webworker_writer( jsfile )
2228+
if writer.output.len == 0:
2229+
is_worker_entry = True
2230+
## TODO: two-way list and dict sync
2231+
writer.write('__wargs__ = []')
2232+
writer.write('def onmessage(e):')
2233+
writer.push()
2234+
writer.write( 'print("worker got message from parent")' )
2235+
writer.write( 'print(e.data)' )
2236+
writer.write( 'if e.data.type=="execute": %s.apply(self, e.data.args); self.postMessage({"type":"terminate"})' %node.name )
2237+
writer.write( 'elif e.data.type=="append": __wargs__[ e.data.argindex ].push( e.data.value )' )
2238+
2239+
writer.write( 'print(__wargs__)' )
2240+
2241+
writer.pull()
2242+
writer.write('self.onmessage = onmessage' )
2243+
2244+
22332245
if self._with_dart:
22342246
## dart supports optional positional params [x=1, y=2], or optional named {x:1, y:2}
22352247
## but not both at the same time.
@@ -2435,8 +2447,7 @@ def visit_FunctionDef(self, node):
24352447
## if sleep() is called or a new webworker is started, the following function body must be wrapped in
24362448
## a closure callback and called later by setTimeout
24372449
timeouts = []
2438-
continues = []
2439-
after_while = False
2450+
#continues = []
24402451
for b in node.body:
24412452

24422453
if self._use_threading and isinstance(b, ast.Assign) and isinstance(b.value, ast.Call):
@@ -2447,12 +2458,16 @@ def visit_FunctionDef(self, node):
24472458
writer.write('def __callback%s():' %len(timeouts))
24482459
writer.push()
24492460
## workerjs for nodejs requires at least 100ms to initalize onmessage/postMessage
2450-
timeouts.append(100)
2461+
timeouts.append(0.2)
2462+
continue
2463+
elif b.value.func.attr == 'start_webworker':
2464+
self.visit(b)
2465+
writer.write('__run__ = True')
2466+
writer.write('def __callback%s():' %len(timeouts))
2467+
writer.push()
2468+
## workerjs for nodejs requires at least 100ms to initalize onmessage/postMessage
2469+
timeouts.append(0.2)
24512470
continue
2452-
2453-
elif after_while:
2454-
after_while = False
2455-
24562471

24572472
elif self._use_sleep:
24582473
c = b
@@ -2474,16 +2489,6 @@ def visit_FunctionDef(self, node):
24742489
if isinstance(bb, ast.Call) and isinstance(bb.func, ast.Name) and bb.func.id == 'sleep':
24752490
has_sleep = float(self.visit(bb.args[0]))
24762491

2477-
#timeouts.append( self.visit(bb.args[0]) )
2478-
#continues.append( 'if %s: __run__ = True' %self.visit(b.test)) ## recursive
2479-
#continues.append( 'else: __run__ = False')
2480-
continue
2481-
2482-
else:
2483-
#e = self.visit(bb)
2484-
#if e: writer.write( e )
2485-
pass
2486-
24872492
if has_sleep > 0.0:
24882493

24892494
#writer.write('__run_while__ = True')
@@ -2505,18 +2510,20 @@ def visit_FunctionDef(self, node):
25052510
writer.write( 'if %s: __run_while__ = True' %self.visit(b.test))
25062511
writer.write( 'else: __run_while__ = False')
25072512

2508-
writer.write('if __run_while__: setTimeout(__while, %s)' %has_sleep)
2509-
writer.write('elif __continue__: setTimeout(__callback%s, 50)' %len(timeouts))
2513+
writer.write('if __run_while__: setTimeout(__while, %s)' %(has_sleep))
2514+
writer.write('elif __continue__: setTimeout(__callback%s, 0)' %len(timeouts))
25102515

25112516
writer.pull()
25122517

2513-
writer.write('setTimeout(__while, 1)')
2518+
writer.write('setTimeout(__while, 0)')
25142519
writer.write('__run__ = True')
25152520
writer.write('def __callback%s():' %len(timeouts))
25162521
writer.push()
25172522
timeouts.append(None)
25182523
continue
25192524

2525+
else:
2526+
self.visit(b)
25202527

25212528
continue
25222529

@@ -2526,19 +2533,13 @@ def visit_FunctionDef(self, node):
25262533

25272534
i = len(timeouts)-1
25282535
while timeouts:
2529-
j = i
2530-
#if continues:
2531-
# continue_else = continues.pop()
2532-
# loop_if = continues.pop()
2533-
# writer.write( loop_if )
2534-
# writer.write( continue_else )
2535-
# j -= 1
2536-
25372536
writer.pull()
25382537
ms = timeouts.pop()
25392538
if ms is not None:
2540-
writer.write('if __run__: setTimeout(__callback%s, %s)' %(j, ms))
2541-
writer.write('elif __continue__: setTimeout(__callback%s, %s)' %(j+1, ms))
2539+
ms = float(ms)
2540+
ms *= 1000
2541+
writer.write('if __run__: setTimeout(__callback%s, %s)' %(i, ms))
2542+
writer.write('elif __continue__: setTimeout(__callback%s, %s)' %(i+1, ms))
25422543
i -= 1
25432544

25442545
if self._return_type: ## check if a return type was caught
@@ -2905,7 +2906,14 @@ def visit_While(self, node):
29052906
writer.pull()
29062907

29072908
def visit_With(self, node):
2908-
if isinstance( node.context_expr, Name ) and node.context_expr.id == 'inline':
2909+
if isinstance( node.context_expr, Name ) and node.context_expr.id == 'webworker':
2910+
self._with_webworker = True
2911+
for b in node.body:
2912+
a = self.visit(b)
2913+
if a: writer.write(a)
2914+
self._with_webworker = False
2915+
2916+
elif isinstance( node.context_expr, Name ) and node.context_expr.id == 'inline':
29092917
writer.write('with inline:')
29102918
writer.push()
29112919
for b in node.body:

0 commit comments

Comments
 (0)