@@ -1308,6 +1308,10 @@ exports.Class = class Class extends Base
1308
1308
# Anonymous classes are only valid in expressions
1309
1309
node = new Parens node
1310
1310
1311
+ if @boundMethods .length and @parent
1312
+ @variable ?= new IdentifierLiteral o .scope .freeVariable ' _class'
1313
+ [@variable , @variableRef ] = @variable .cache o unless @variableRef ?
1314
+
1311
1315
if @variable
1312
1316
node = new Assign @variable , node, null , { @moduleDeclaration }
1313
1317
@@ -1318,9 +1322,11 @@ exports.Class = class Class extends Base
1318
1322
delete @compileNode
1319
1323
1320
1324
compileClassDeclaration : (o ) ->
1321
- @ctor ?= @ makeDefaultConstructor () if @externalCtor
1325
+ @ctor ?= @ makeDefaultConstructor () if @externalCtor or @boundMethods . length
1322
1326
@ctor ? .noReturn = true
1323
1327
1328
+ @ proxyBoundMethods () if @boundMethods .length
1329
+
1324
1330
o .indent += TAB
1325
1331
1326
1332
result = []
@@ -1356,6 +1362,7 @@ exports.Class = class Class extends Base
1356
1362
1357
1363
walkBody : ->
1358
1364
@ctor = null
1365
+ @boundMethods = []
1359
1366
executableBody = null
1360
1367
1361
1368
initializer = []
@@ -1401,6 +1408,8 @@ exports.Class = class Class extends Base
1401
1408
@ctor = method
1402
1409
else if method .isStatic and method .bound
1403
1410
method .context = @name
1411
+ else if method .bound
1412
+ @boundMethods .push method
1404
1413
1405
1414
if initializer .length isnt expressions .length
1406
1415
@body .expressions = (expression .hoist () for expression in initializer)
@@ -1438,7 +1447,7 @@ exports.Class = class Class extends Base
1438
1447
method .name = new (if methodName .shouldCache () then Index else Access) methodName
1439
1448
method .name .updateLocationDataIfMissing methodName .locationData
1440
1449
method .ctor = (if @parent then ' derived' else ' base' ) if methodName .value is ' constructor'
1441
- method .error ' Methods cannot be bound functions ' if method .bound
1450
+ method .error ' Cannot define a constructor as a bound (fat arrow) function ' if method .bound and method . ctor
1442
1451
1443
1452
method
1444
1453
@@ -1457,6 +1466,15 @@ exports.Class = class Class extends Base
1457
1466
1458
1467
ctor
1459
1468
1469
+ proxyBoundMethods : ->
1470
+ @ctor .thisAssignments = for method in @boundMethods
1471
+ method .classVariable = @variableRef if @parent
1472
+
1473
+ name = new Value (new ThisLiteral , [ method .name ])
1474
+ new Assign name, new Call (new Value (name, [new Access new PropertyName ' bind' ]), [new ThisLiteral ])
1475
+
1476
+ null
1477
+
1460
1478
exports .ExecutableClassBody = class ExecutableClassBody extends Base
1461
1479
children : [ ' class' , ' body' ]
1462
1480
@@ -1540,7 +1558,7 @@ exports.ExecutableClassBody = class ExecutableClassBody extends Base
1540
1558
@body .traverseChildren false , (node ) =>
1541
1559
if node instanceof ThisLiteral
1542
1560
node .value = @name
1543
- else if node instanceof Code and node .bound
1561
+ else if node instanceof Code and node .bound and node . isStatic
1544
1562
node .context = @name
1545
1563
1546
1564
# Make class/prototype assignments for invalid ES properties
@@ -2180,6 +2198,9 @@ exports.Code = class Code extends Base
2180
2198
wasEmpty = @body .isEmpty ()
2181
2199
@body .expressions .unshift thisAssignments... unless @ expandCtorSuper thisAssignments
2182
2200
@body .expressions .unshift exprs...
2201
+ if @isMethod and @bound and not @isStatic and @classVariable
2202
+ boundMethodCheck = new Value new Literal utility ' boundMethodCheck' , o
2203
+ @body .expressions .unshift new Call (boundMethodCheck, [new Value (new ThisLiteral ), @classVariable ])
2183
2204
@body .makeReturn () unless wasEmpty or @noReturn
2184
2205
2185
2206
# Assemble the output
@@ -3149,6 +3170,13 @@ exports.If = class If extends Base
3149
3170
3150
3171
UTILITIES =
3151
3172
modulo : -> ' function(a, b) { return (+a % (b = +b) + b) % b; }'
3173
+ boundMethodCheck : -> "
3174
+ function(instance, Constructor) {
3175
+ if (!(instance instanceof Constructor)) {
3176
+ throw new Error('Bound instance method accessed before binding');
3177
+ }
3178
+ }
3179
+ "
3152
3180
3153
3181
# Shortcuts to speed up the lookup time for native functions.
3154
3182
hasProp : -> ' {}.hasOwnProperty'
0 commit comments