Skip to content

Commit ac2f98b

Browse files
committed
3.4.1
1 parent 8d9f523 commit ac2f98b

File tree

4 files changed

+5881
-0
lines changed

4 files changed

+5881
-0
lines changed

dist/amd/can-view-scope.js

+290
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
/*[email protected]#can-view-scope*/
2+
define([
3+
'require',
4+
'exports',
5+
'module',
6+
'can-stache-key',
7+
'can-observation',
8+
'./template-context',
9+
'./compute_data',
10+
'can-util/js/assign',
11+
'can-util/js/each',
12+
'can-namespace',
13+
'can-reflect',
14+
'can-log/dev'
15+
], function (require, exports, module) {
16+
var observeReader = require('can-stache-key');
17+
var Observation = require('can-observation');
18+
var TemplateContext = require('./template-context');
19+
var makeComputeData = require('./compute_data');
20+
var assign = require('can-util/js/assign');
21+
var each = require('can-util/js/each');
22+
var namespace = require('can-namespace');
23+
var canReflect = require('can-reflect');
24+
var canLog = require('can-log/dev');
25+
function Scope(context, parent, meta) {
26+
this._context = context;
27+
this._parent = parent;
28+
this._meta = meta || {};
29+
this.__cache = {};
30+
}
31+
assign(Scope, {
32+
read: observeReader.read,
33+
Refs: TemplateContext,
34+
refsScope: function () {
35+
return new Scope(new TemplateContext());
36+
},
37+
keyInfo: function (attr) {
38+
var info = {};
39+
info.isDotSlash = attr.substr(0, 2) === './';
40+
info.isThisDot = attr.substr(0, 5) === 'this.';
41+
info.isThisAt = attr.substr(0, 5) === 'this@';
42+
info.isInCurrentContext = info.isDotSlash || info.isThisDot || info.isThisAt;
43+
info.isInParentContext = attr.substr(0, 3) === '../';
44+
info.isCurrentContext = attr === '.' || attr === 'this';
45+
info.isParentContext = attr === '..';
46+
info.isTemplateContext = attr === 'scope';
47+
info.isInLegacyRefsScope = attr.substr(0, 1) === '*';
48+
info.isInTemplateContext = info.isTemplateContext || info.isInLegacyRefsScope || attr.substr(0, 6) === 'scope.';
49+
info.isContextBased = info.isInCurrentContext || info.isInParentContext || info.isCurrentContext || info.isParentContext || info.isInTemplateContext;
50+
return info;
51+
}
52+
});
53+
assign(Scope.prototype, {
54+
add: function (context, meta) {
55+
if (context !== this._context) {
56+
return new this.constructor(context, this, meta);
57+
} else {
58+
return this;
59+
}
60+
},
61+
read: function (attr, options) {
62+
if (attr === '%root') {
63+
return { value: this.getRoot() };
64+
}
65+
if (attr === '%scope') {
66+
return { value: this };
67+
}
68+
if (attr === './') {
69+
attr = '.';
70+
}
71+
var keyInfo = Scope.keyInfo(attr);
72+
if (keyInfo.isContextBased && this._meta.notContext) {
73+
return this._parent.read(attr, options);
74+
}
75+
var currentScopeOnly, parent;
76+
if (keyInfo.isInCurrentContext) {
77+
currentScopeOnly = true;
78+
attr = keyInfo.isDotSlash ? attr.substr(2) : attr.substr(5);
79+
} else if (keyInfo.isInParentContext || keyInfo.isParentContext) {
80+
parent = this._parent;
81+
while (parent._meta.notContext) {
82+
parent = parent._parent;
83+
}
84+
if (keyInfo.isParentContext) {
85+
return observeReader.read(parent._context, [], options);
86+
}
87+
return parent.read(attr.substr(3) || '.', options);
88+
} else if (keyInfo.isCurrentContext) {
89+
return observeReader.read(this._context, [], options);
90+
} else if (keyInfo.isInTemplateContext) {
91+
parent = this.getTemplateContext();
92+
if (keyInfo.isTemplateContext) {
93+
return { value: parent };
94+
}
95+
return { value: canReflect.getKeyValue(parent._context, attr) };
96+
}
97+
return this._read(observeReader.reads(attr), options, currentScopeOnly);
98+
},
99+
_read: function (keyReads, options, currentScopeOnly) {
100+
var currentScope = this, currentContext, undefinedObserves = [], currentObserve, currentReads, setObserveDepth = -1, currentSetReads, currentSetObserve, readOptions = assign({
101+
foundObservable: function (observe, nameIndex) {
102+
currentObserve = observe;
103+
currentReads = keyReads.slice(nameIndex);
104+
},
105+
earlyExit: function (parentValue, nameIndex) {
106+
if (nameIndex > setObserveDepth || nameIndex === setObserveDepth && (typeof parentValue === 'object' && keyReads[nameIndex].key in parentValue)) {
107+
currentSetObserve = currentObserve;
108+
currentSetReads = currentReads;
109+
setObserveDepth = nameIndex;
110+
}
111+
}
112+
}, options);
113+
while (currentScope) {
114+
currentContext = currentScope._context;
115+
if (currentContext !== null && (typeof currentContext === 'object' || typeof currentContext === 'function')) {
116+
var getObserves = Observation.trap();
117+
var data = observeReader.read(currentContext, keyReads, readOptions);
118+
var observes = getObserves();
119+
if (data.value !== undefined) {
120+
Observation.addAll(observes);
121+
return {
122+
scope: currentScope,
123+
rootObserve: currentObserve,
124+
value: data.value,
125+
reads: currentReads
126+
};
127+
} else {
128+
undefinedObserves.push.apply(undefinedObserves, observes);
129+
}
130+
}
131+
if (currentScopeOnly) {
132+
currentScope = null;
133+
} else {
134+
currentScope = currentScope._parent;
135+
}
136+
}
137+
Observation.addAll(undefinedObserves);
138+
return {
139+
setRoot: currentSetObserve,
140+
reads: currentSetReads,
141+
value: undefined
142+
};
143+
},
144+
get: function (key, options) {
145+
options = assign({ isArgument: true }, options);
146+
var res = this.read(key, options);
147+
return res.value;
148+
},
149+
peek: Observation.ignore(function (key, options) {
150+
return this.get(key, options);
151+
}),
152+
peak: Observation.ignore(function (key, options) {
153+
return this.peek(key, options);
154+
}),
155+
getScope: function (tester) {
156+
var scope = this;
157+
while (scope) {
158+
if (tester(scope)) {
159+
return scope;
160+
}
161+
scope = scope._parent;
162+
}
163+
},
164+
getContext: function (tester) {
165+
var res = this.getScope(tester);
166+
return res && res._context;
167+
},
168+
getRefs: function () {
169+
return this.getTemplateContext();
170+
},
171+
getTemplateContext: function () {
172+
var lastScope;
173+
var templateContext = this.getScope(function (scope) {
174+
lastScope = scope;
175+
return scope._context instanceof TemplateContext;
176+
});
177+
if (!templateContext) {
178+
templateContext = new Scope(new TemplateContext());
179+
lastScope._parent = templateContext;
180+
}
181+
return templateContext;
182+
},
183+
getRoot: function () {
184+
var cur = this, child = this;
185+
while (cur._parent) {
186+
child = cur;
187+
cur = cur._parent;
188+
}
189+
if (cur._context instanceof Scope.Refs) {
190+
cur = child;
191+
}
192+
return cur._context;
193+
},
194+
set: function (key, value, options) {
195+
options = options || {};
196+
var keyInfo = Scope.keyInfo(key), parent;
197+
if (keyInfo.isCurrentContext) {
198+
return canReflect.setValue(this._context, value);
199+
} else if (keyInfo.isInParentContext || keyInfo.isParentContext) {
200+
parent = this._parent;
201+
while (parent._meta.notContext) {
202+
parent = parent._parent;
203+
}
204+
if (keyInfo.isParentContext) {
205+
return canReflect.setValue(parent._context, value);
206+
}
207+
return parent.set(key.substr(3) || '.', value, options);
208+
} else if (keyInfo.isInTemplateContext) {
209+
parent = this.getTemplateContext();
210+
return canReflect.setKeyValue(parent._context, key, value);
211+
}
212+
var dotIndex = key.lastIndexOf('.'), slashIndex = key.lastIndexOf('/'), contextPath, propName;
213+
if (slashIndex > dotIndex) {
214+
contextPath = key.substring(0, slashIndex);
215+
propName = key.substring(slashIndex + 1, key.length);
216+
} else {
217+
if (dotIndex !== -1) {
218+
contextPath = key.substring(0, dotIndex);
219+
propName = key.substring(dotIndex + 1, key.length);
220+
} else {
221+
contextPath = '.';
222+
propName = key;
223+
}
224+
}
225+
var context = this.read(contextPath, options).value;
226+
if (context === undefined) {
227+
return;
228+
}
229+
if (!canReflect.isObservableLike(context) && canReflect.isObservableLike(context[propName])) {
230+
if (canReflect.isMapLike(context[propName])) {
231+
canLog.warn('can-view-scope: Merging data into "' + propName + '" because its parent is non-observable');
232+
canReflect.updateDeep(context[propName], value);
233+
} else if (canReflect.isValueLike(context[propName])) {
234+
canReflect.setValue(context[propName], value);
235+
} else {
236+
observeReader.write(context, propName, value, options);
237+
}
238+
} else {
239+
observeReader.write(context, propName, value, options);
240+
}
241+
},
242+
attr: Observation.ignore(function (key, value, options) {
243+
canLog.warn('can-view-scope::attr is deprecated, please use peek, get or set');
244+
options = assign({ isArgument: true }, options);
245+
if (arguments.length === 2) {
246+
return this.set(key, value, options);
247+
} else {
248+
return this.get(key, options);
249+
}
250+
}),
251+
computeData: function (key, options) {
252+
return makeComputeData(this, key, options);
253+
},
254+
compute: function (key, options) {
255+
return this.computeData(key, options).compute;
256+
},
257+
cloneFromRef: function () {
258+
var contexts = [];
259+
var scope = this, context, parent;
260+
while (scope) {
261+
context = scope._context;
262+
if (context instanceof Scope.Refs) {
263+
parent = scope._parent;
264+
break;
265+
}
266+
contexts.unshift(context);
267+
scope = scope._parent;
268+
}
269+
if (parent) {
270+
each(contexts, function (context) {
271+
parent = parent.add(context);
272+
});
273+
return parent;
274+
} else {
275+
return this;
276+
}
277+
}
278+
});
279+
function Options(data, parent, meta) {
280+
if (!data.helpers && !data.partials && !data.tags) {
281+
data = { helpers: data };
282+
}
283+
Scope.call(this, data, parent, meta);
284+
}
285+
Options.prototype = new Scope();
286+
Options.prototype.constructor = Options;
287+
Scope.Options = Options;
288+
namespace.view = namespace.view || {};
289+
module.exports = namespace.view.Scope = Scope;
290+
});

0 commit comments

Comments
 (0)