@@ -792,6 +792,10 @@ def getAdjacentClassScopes (self, inMethod = False):
792
792
reversedClassScopes .append (scope )
793
793
return reversed (reversedClassScopes )
794
794
795
+ def emitSemiColon (self , index , blank = True ):
796
+ if self .noskipCodeGeneration and self .conditionalCodeGeneration and index :
797
+ self .emit ('; ' if blank else ';' )
798
+
795
799
def emitComma (self , index , blank = True ):
796
800
if self .noskipCodeGeneration and self .conditionalCodeGeneration and index :
797
801
self .emit (', ' if blank else ',' )
@@ -1914,7 +1918,7 @@ def visit_ClassDef (self, node):
1914
1918
self .emit ('export var {} = ' .format (self .filterId (node .name )))
1915
1919
self .allOwnNames .add (node .name )
1916
1920
elif type (self .getScope () .node ) == ast .ClassDef :
1917
- self .emit ('\n {}: ' .format (self .filterId (node .name )))
1921
+ self .emit ('\n var {0} = cls.{0} = ' .format (self .filterId (node .name )))
1918
1922
else :
1919
1923
self .emit ('var {} =' .format (self .filterId (node .name )))
1920
1924
@@ -1963,11 +1967,12 @@ def visit_ClassDef (self, node):
1963
1967
)
1964
1968
else :
1965
1969
self .emit ('object' )
1966
- self .emit ('], {{' )
1970
+ self .emit ('], (() => {{' ) # class scope start
1967
1971
self .inscope (node )
1968
1972
1969
1973
self .indent ()
1970
- self .emit ('\n __module__: __name__,' )
1974
+ self .emit ('\n let cls = {{}};' )
1975
+ self .emit ('\n cls.__module__ = __name__;' )
1971
1976
1972
1977
# LHS plays a role in a.o. __repr__ in a dataclass
1973
1978
inlineAssigns = [] # LHS is simple name, class var assignment generates initialisation of field in object literal
@@ -1994,7 +1999,7 @@ def visit_ClassDef (self, node):
1994
1999
if self .isCommentString (statement ):
1995
2000
pass
1996
2001
elif type (statement ) in (ast .FunctionDef , ast .AsyncFunctionDef , ast .ClassDef ):
1997
- self .emitComma (index , False )
2002
+ self .emitSemiColon (index , False )
1998
2003
self .visit (statement )
1999
2004
index += 1
2000
2005
@@ -2007,8 +2012,8 @@ def visit_ClassDef (self, node):
2007
2012
else :
2008
2013
# Simple class var assignment, can be generated in-line as initialisation field of a JavaScript object literal
2009
2014
inlineAssigns .append (statement )
2010
- self .emitComma (index , False )
2011
- self .emit ('\n {}: ' , self .filterId (statement .targets [0 ] .id ))
2015
+ self .emitSemiColon (index , False )
2016
+ self .emit ('\n var {0} = cls.{0} = ' , self .filterId (statement .targets [0 ] .id ))
2012
2017
self .visit (statement .value )
2013
2018
self .adaptLineNrString (statement )
2014
2019
index += 1
@@ -2032,18 +2037,24 @@ def visit_ClassDef (self, node):
2032
2037
initAssigns .append (statement )
2033
2038
reprAssigns .append (statement )
2034
2039
compareAssigns .append (statement )
2035
- self .emitComma (index , False )
2036
- self .emit ('\n {}: ' , self .filterId (statement .target .id ))
2037
- self .visit (statement .value )
2040
+ self .emitSemiColon (index , False )
2041
+ if statement .value is None :
2042
+ self .emit ('\n var {0} = cls.{0}' , self .filterId (statement .target .id ))
2043
+ else :
2044
+ self .emit ('\n var {0} = cls.{0} = ' , self .filterId (statement .target .id ))
2045
+ self .visit (statement .value )
2038
2046
self .adaptLineNrString (statement )
2039
2047
index += 1
2040
2048
elif type (statement .target ) == ast .Name :
2041
2049
try :
2042
2050
# Simple class var assignment
2043
2051
inlineAssigns .append (statement )
2044
- self .emitComma (index , False )
2045
- self .emit ('\n {}: ' , self .filterId (statement .target .id ))
2046
- self .visit (statement .value )
2052
+ self .emitSemiColon (index , False )
2053
+ if statement .value is None :
2054
+ self .emit ('\n var {0} = cls.{0}' , self .filterId (statement .target .id ))
2055
+ else :
2056
+ self .emit ('\n var {0} = cls.{0} = ' , self .filterId (statement .target .id ))
2057
+ self .visit (statement .value )
2047
2058
self .adaptLineNrString (statement )
2048
2059
index += 1
2049
2060
except :
@@ -2052,12 +2063,21 @@ def visit_ClassDef (self, node):
2052
2063
# LHS is attribute or array element, we can't use it for representation or comparison
2053
2064
delayedAssigns .append (statement )
2054
2065
2055
- elif self .getPragmaFromExpr (statement ):
2056
- # It's a pragma
2057
- self .visit (statement )
2066
+ elif type (statement ) == ast .Expr :
2067
+ if self .getPragmaFromExpr (statement ):
2068
+ # It's a pragma
2069
+ self .visit (statement )
2070
+ else :
2071
+ # It's a class scoped expression
2072
+ self .emitSemiColon (index , False )
2073
+ self .emit ('\n ' )
2074
+ self .visit (statement )
2075
+
2076
+ self .emitSemiColon (index , False )
2077
+ self .emit ('\n return cls;' )
2058
2078
self .dedent ()
2059
2079
2060
- self .emit ('\n }}' )
2080
+ self .emit ('\n }})()' ) # class scope end
2061
2081
2062
2082
if node .keywords :
2063
2083
if node .keywords [0 ] .arg == 'metaclass' :
@@ -2162,7 +2182,7 @@ def visit_ClassDef (self, node):
2162
2182
returns = None ,
2163
2183
docstring = None
2164
2184
))
2165
- self .emit (', ' )
2185
+ self .emit ('; ' )
2166
2186
self .allowKeywordArgs = originalAllowKeywordArgs
2167
2187
2168
2188
# Generate __repr__
@@ -2210,7 +2230,7 @@ def visit_ClassDef (self, node):
2210
2230
returns = None ,
2211
2231
docstring = None
2212
2232
))
2213
- self .emit (', ' )
2233
+ self .emit ('; ' )
2214
2234
2215
2235
# Generate comparators !!! TODO: Add check that self and other are of same class
2216
2236
comparatorNames = []
@@ -2266,7 +2286,7 @@ def visit_ClassDef (self, node):
2266
2286
decorator_list = []
2267
2287
))
2268
2288
returns = None ,
2269
- self .emit (', ' )
2289
+ self .emit ('; ' )
2270
2290
2271
2291
# After inserting at init hoist location, jump forward as much as we jumped back
2272
2292
# Simply going back to the original fragment index won't work, since fragments were prepended
@@ -2675,9 +2695,9 @@ def pushPropertyAccessor(functionName):
2675
2695
message = '\n \t decorators are not supported with jscall\n '
2676
2696
)
2677
2697
2678
- self .emit ('{}: ' , self .filterId (nodeName ))
2698
+ self .emit ('{} = ' , self .filterId (nodeName ))
2679
2699
else :
2680
- self .emit ( 'get {} () {{return {} (this, ' , self .filterId (nodeName ), getter )
2700
+ self .emit ( '__def__(cls, function {} () {{ return {} (this, ' , self .filterId (nodeName ), getter )
2681
2701
elif isGlobal :
2682
2702
if type (node .parentNode ) == ast .Module and not nodeName in self .allOwnNames :
2683
2703
self .emit ('export ' )
@@ -2705,12 +2725,12 @@ def pushPropertyAccessor(functionName):
2705
2725
else :
2706
2726
if isMethod :
2707
2727
if jsCall :
2708
- self .emit ('{}: function' , self .filterId (nodeName ), 'async ' if anAsync else '' )
2728
+ self .emit ('{} = function' , self .filterId (nodeName ), 'async ' if anAsync else '' )
2709
2729
else :
2710
2730
if isStaticMethod :
2711
- self .emit ('get {} () {{return {}function' , self .filterId (nodeName ), 'async ' if anAsync else '' )
2731
+ self .emit ('__def__(cls, function {} () {{ return {}function' , self .filterId (nodeName ), 'async ' if anAsync else '' )
2712
2732
else :
2713
- self .emit ('get {} () {{return {} (this, {}function' , self .filterId (nodeName ), getter , 'async ' if anAsync else '' )
2733
+ self .emit ('__def__(cls, function {} () {{ return {} (this, {}function' , self .filterId (nodeName ), getter , 'async ' if anAsync else '' )
2714
2734
elif isGlobal :
2715
2735
if type (node .parentNode ) == ast .Module and not nodeName in self .allOwnNames :
2716
2736
self .emit ('export ' )
@@ -2759,18 +2779,19 @@ def pushPropertyAccessor(functionName):
2759
2779
if isMethod :
2760
2780
if not jsCall :
2761
2781
if isStaticMethod :
2762
- self .emit (';}}' )
2782
+ self .emit (';}}) ' )
2763
2783
else :
2764
2784
if self .allowMemoizeCalls :
2765
2785
self .emit (', \' {}\' ' , nodeName ) # Name will be used as attribute name to add bound function to instance
2766
2786
2767
- self .emit (');}}' )
2787
+ self .emit (');}}) ' )
2768
2788
2769
2789
if nodeName == '__iter__' :
2770
- self .emit (', \n [Symbol.iterator] () {{return this .__iter__ ()}} ' )
2790
+ self .emit ('; \n cls [Symbol.iterator] = () => cls .__iter__() ' )
2771
2791
2772
2792
if nodeName == '__next__' :
2773
- self .emit (',\n next: __jsUsePyNext__' ) # ??? Shouldn't this be a property, to allow bound method pointers
2793
+ self .emit (';\n cls.next = __jsUsePyNext__' ) # ??? Shouldn't this be a property, to allow bound
2794
+ # method pointers
2774
2795
2775
2796
if isGlobal :
2776
2797
self .allOwnNames .add (nodeName )
0 commit comments