-
Notifications
You must be signed in to change notification settings - Fork 25
/
bindings.js
118 lines (103 loc) · 3.67 KB
/
bindings.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
var Map = require("collections/map"),
bind = require("./bind"),
compute = require("./compute"),
observe = require("./observe"),
stringify = require("./stringify");
var bindingsForObject = new Map(),
owns = Object.prototype.hasOwnProperty,
ONE_WAY = "<-",
TWO_WAY = "<->",
COMPUTE = "compute",
GET = "get",
SET = "set",
WRITABLE = "writable",
CONFIGURABLE = "configurable",
ENUMERABLE = "enumerable";
exports.count = 0;
exports.bindings = bindingsForObject;
exports.defineBindings = defineBindings;
function defineBindings(object, descriptors, commonDescriptor) {
if (descriptors) {
for (var name in descriptors) {
defineBinding(object, name, descriptors[name], commonDescriptor);
}
}
return object;
}
exports.defineBinding = defineBinding;
function defineBinding(object, name, descriptor, commonDescriptor) {
commonDescriptor = commonDescriptor || defineBinding.empty;
var bindingsForName = defineBinding.getBindings(object),
parameters, document;
if (bindingsForName.has(name)) {
throw new Error("Can't bind to already bound target, " + JSON.stringify(name));
}
else if (ONE_WAY in descriptor || TWO_WAY in descriptor || COMPUTE in descriptor) {
bindingsForName.set(name,descriptor);
descriptor.target = object;
if((parameters = descriptor.parameters || commonDescriptor.parameters))
descriptor.parameters = parameters;
if((document = descriptor.document || commonDescriptor.document))
descriptor.document = document;
descriptor.components = descriptor.components || commonDescriptor.components;
descriptor.cancel = (COMPUTE in descriptor)
? defineBinding.compute(object, name, descriptor)
: defineBinding.bind(object, name, descriptor);
exports.count++;
} else {
if (!(GET in descriptor) && !(SET in descriptor) && !(WRITABLE in descriptor)) {
descriptor.writable = true;
}
if (!(CONFIGURABLE in descriptor)) {
descriptor.configurable = true;
}
if (!(ENUMERABLE in descriptor)) {
descriptor.enumerable = true;
}
Object.defineProperty(object, name, descriptor);
}
return object;
}
defineBinding.empty = Object.empty;
defineBinding.getBindings = getBindings;
defineBinding.compute = compute;
defineBinding.bind = bind;
exports.getBindings = getBindings;
function getBindings(object) {
var value;
return bindingsForObject.get(object) || (bindingsForObject.set(object, ( value = new Map)) && value);
}
exports.getBinding = getBinding;
function getBinding(object, name) {
var bindingsForName = getBindings(object);
return bindingsForName.get(name);
}
exports.cancelBindings = cancelBindings;
function cancelBindings(object) {
var bindings = getBindings(object),
mapIter = bindings.keys();
while (name = mapIter.next().value) {
cancelBinding(object, name, bindings);
}
// for (var name in bindings) {
// cancelBinding(object, name);
// }
}
exports.cancelBinding = cancelBinding;
function cancelBinding(object, name, bindings/*private argument to call from cancelBindings*/) {
if(!bindings) {
bindings = getBindings(object);
if (!bindings.has(name)) {
throw new Error("Can't cancel non-existent binding to " + JSON.stringify(name));
}
}
var binding = bindings.get(name);
if (binding && binding.cancel) {
binding.cancel();
bindings.delete(name);
exports.count--;
if (bindings.size < 1) {
bindingsForObject.delete(object);
}
}
}