@@ -2,21 +2,63 @@ define(["require", "exports"], function(require, exports) {
2
2
var isNodeJs = ( typeof window == 'undefined' && typeof global != 'undefined' ) ;
3
3
var globalNamespace = isNodeJs ? global : window ;
4
4
5
+ if ( ! isNodeJs ) {
6
+ if ( ! Function . prototype . bind ) {
7
+ Function . prototype . bind = function ( oThis ) {
8
+ if ( typeof this !== "function" ) {
9
+ throw new TypeError ( "Function.prototype.bind - what is trying to be bound is not callable" ) ;
10
+ }
11
+
12
+ var aArgs = Array . prototype . slice . call ( arguments , 1 ) , fToBind = this , fNOP = function ( ) {
13
+ } , fBound = function ( ) {
14
+ return fToBind . apply ( this instanceof fNOP && oThis ? this : oThis , aArgs . concat ( Array . prototype . slice . call ( arguments ) ) ) ;
15
+ } ;
16
+
17
+ fNOP . prototype = this . prototype ;
18
+ fBound . prototype = new fNOP ( ) ;
19
+
20
+ return fBound ;
21
+ } ;
22
+ }
23
+ }
24
+
5
25
//TODO Support DestinationAccount['de' + 'posit'](amount)
6
26
//
7
27
//DestinationAccount['de' + 'posit'](amount) could be rewritten to:
8
28
//__context.__$DestinationAccount['de' + 'posit'].call(__context.DestinationAccount, amount)
9
29
//
10
30
//would be better to give a nice error message if role method not found:
11
- //DCI.getRoleMethod(__context, 'DestinationAccount', 'de' + 'posit').call(__context.DestinationAccount, amount)
12
- function getRoleMethod ( context , roleName , methodName ) {
13
- var roleMethod = context [ '__$' + roleName ] [ methodName ] ;
14
- if ( ! roleMethod ) {
15
- throw new Error ( 'Method "' + methodName + '" not found on role "' + roleName + '"' ) ;
31
+ //DCI.getRoleMember(__context, __context.DestinationAccount, 'DestinationAccount', 'de' + 'posit').call(__context.DestinationAccount, amount)
32
+ //Gets a member on a role player - can be either a role method or a method or property of the role player object
33
+ function getRoleMember ( context , player , roleName , memberName ) {
34
+ if ( player != context [ roleName ] ) {
35
+ //If we're here, it's because the programmer used `this` inside a closure inside a role method.
36
+ //So either `this` refers to some other object besides the current role, or the programmer used `this`
37
+ //inside a closure when they should have used `self`.
38
+ //
39
+ //In other words this code would also be reached if `this` is equal to `undefined`, `global`, or `window`.)
40
+ //...for example, if the SourceAccount.transferOut() method in the Transfer Money example contained the following code:
41
+ // [1,2,3].forEach(function() {
42
+ // this.withdraw(); //`this` is actually equal to `window` or `global` here! (or `undefined` in strict mode)
43
+ // });
44
+ //
45
+ //Because we need to account for the first case (`this` refers to some other object besides the current role),
46
+ //which is perfectly valid, we simply return the property on `this` just as would happen normally in Javascript.
47
+ return player [ memberName ] ;
48
+ }
49
+
50
+ var roleMethod = context [ '__$' + roleName ] [ memberName ] ;
51
+ if ( roleMethod ) {
52
+ //bind the role player as `this` on the specified role method
53
+ return roleMethod . bind ( player ) ;
54
+ } else {
55
+ if ( ! ( memberName in player ) ) {
56
+ throw new Error ( 'Method or property "' + memberName + '" not found on role "' + roleName + '" nor on its current role player.' ) ;
57
+ }
58
+ return player [ memberName ] ;
16
59
}
17
- return roleMethod ;
18
60
}
19
- exports . getRoleMethod = getRoleMethod ;
61
+ exports . getRoleMember = getRoleMember ;
20
62
21
63
//This function is for handling calls beginning with `this`; it calls a method on the current role player,
22
64
//which could be either a role method or a method on the data object.
0 commit comments