Skip to content

Commit b3fa965

Browse files
authored
Merge pull request #1246 from sveltejs/omit-missing-prop-warning-for-computed
skip missing property warning for computed/global properties
2 parents 270e1d1 + 7c25eb3 commit b3fa965

File tree

5 files changed

+398
-0
lines changed

5 files changed

+398
-0
lines changed

src/generators/dom/index.ts

+3
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ export default function dom(
208208
${computations.length && `this._recompute({ ${Array.from(computationDeps).map(dep => `${dep}: 1`).join(', ')} }, this._state);`}
209209
${options.dev &&
210210
Array.from(generator.expectedProperties).map(prop => {
211+
if (globalWhitelist.has(prop)) return;
212+
if (computations.find(c => c.key === prop)) return;
213+
211214
const message = generator.components.has(prop) ?
212215
`${debugName} expected to find '${prop}' in \`data\`, but found it in \`components\` instead` :
213216
`${debugName} was created without expected data property '${prop}'`;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export default {
2+
options: {
3+
dev: true
4+
}
5+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
1+
function noop() {}
2+
3+
function assign(target) {
4+
var k,
5+
source,
6+
i = 1,
7+
len = arguments.length;
8+
for (; i < len; i++) {
9+
source = arguments[i];
10+
for (k in source) target[k] = source[k];
11+
}
12+
13+
return target;
14+
}
15+
16+
function appendNode(node, target) {
17+
target.appendChild(node);
18+
}
19+
20+
function insertNode(node, target, anchor) {
21+
target.insertBefore(node, anchor);
22+
}
23+
24+
function detachNode(node) {
25+
node.parentNode.removeChild(node);
26+
}
27+
28+
function createElement(name) {
29+
return document.createElement(name);
30+
}
31+
32+
function createText(data) {
33+
return document.createTextNode(data);
34+
}
35+
36+
function blankObject() {
37+
return Object.create(null);
38+
}
39+
40+
function destroy(detach) {
41+
this.destroy = noop;
42+
this.fire('destroy');
43+
this.set = this.get = noop;
44+
45+
if (detach !== false) this._fragment.u();
46+
this._fragment.d();
47+
this._fragment = this._state = null;
48+
}
49+
50+
function destroyDev(detach) {
51+
destroy.call(this, detach);
52+
this.destroy = function() {
53+
console.warn('Component was already destroyed');
54+
};
55+
}
56+
57+
function _differs(a, b) {
58+
return a != a ? b == b : a !== b || ((a && typeof a === 'object') || typeof a === 'function');
59+
}
60+
61+
function dispatchObservers(component, group, changed, newState, oldState) {
62+
for (var key in group) {
63+
if (!changed[key]) continue;
64+
65+
var newValue = newState[key];
66+
var oldValue = oldState[key];
67+
68+
var callbacks = group[key];
69+
if (!callbacks) continue;
70+
71+
for (var i = 0; i < callbacks.length; i += 1) {
72+
var callback = callbacks[i];
73+
if (callback.__calling) continue;
74+
75+
callback.__calling = true;
76+
callback.call(component, newValue, oldValue);
77+
callback.__calling = false;
78+
}
79+
}
80+
}
81+
82+
function fire(eventName, data) {
83+
var handlers =
84+
eventName in this._handlers && this._handlers[eventName].slice();
85+
if (!handlers) return;
86+
87+
for (var i = 0; i < handlers.length; i += 1) {
88+
handlers[i].call(this, data);
89+
}
90+
}
91+
92+
function get(key) {
93+
return key ? this._state[key] : this._state;
94+
}
95+
96+
function init(component, options) {
97+
component._observers = { pre: blankObject(), post: blankObject() };
98+
component._handlers = blankObject();
99+
component._bind = options._bind;
100+
101+
component.options = options;
102+
component.root = options.root || component;
103+
component.store = component.root.store || options.store;
104+
}
105+
106+
function observe(key, callback, options) {
107+
var group = options && options.defer
108+
? this._observers.post
109+
: this._observers.pre;
110+
111+
(group[key] || (group[key] = [])).push(callback);
112+
113+
if (!options || options.init !== false) {
114+
callback.__calling = true;
115+
callback.call(this, this._state[key]);
116+
callback.__calling = false;
117+
}
118+
119+
return {
120+
cancel: function() {
121+
var index = group[key].indexOf(callback);
122+
if (~index) group[key].splice(index, 1);
123+
}
124+
};
125+
}
126+
127+
function observeDev(key, callback, options) {
128+
var c = (key = '' + key).search(/[.[]/);
129+
if (c > -1) {
130+
var message =
131+
'The first argument to component.observe(...) must be the name of a top-level property';
132+
if (c > 0)
133+
message += ", i.e. '" + key.slice(0, c) + "' rather than '" + key + "'";
134+
135+
throw new Error(message);
136+
}
137+
138+
return observe.call(this, key, callback, options);
139+
}
140+
141+
function on(eventName, handler) {
142+
if (eventName === 'teardown') return this.on('destroy', handler);
143+
144+
var handlers = this._handlers[eventName] || (this._handlers[eventName] = []);
145+
handlers.push(handler);
146+
147+
return {
148+
cancel: function() {
149+
var index = handlers.indexOf(handler);
150+
if (~index) handlers.splice(index, 1);
151+
}
152+
};
153+
}
154+
155+
function onDev(eventName, handler) {
156+
if (eventName === 'teardown') {
157+
console.warn(
158+
"Use component.on('destroy', ...) instead of component.on('teardown', ...) which has been deprecated and will be unsupported in Svelte 2"
159+
);
160+
return this.on('destroy', handler);
161+
}
162+
163+
return on.call(this, eventName, handler);
164+
}
165+
166+
function set(newState) {
167+
this._set(assign({}, newState));
168+
if (this.root._lock) return;
169+
this.root._lock = true;
170+
callAll(this.root._beforecreate);
171+
callAll(this.root._oncreate);
172+
callAll(this.root._aftercreate);
173+
this.root._lock = false;
174+
}
175+
176+
function _set(newState) {
177+
var oldState = this._state,
178+
changed = {},
179+
dirty = false;
180+
181+
for (var key in newState) {
182+
if (this._differs(newState[key], oldState[key])) changed[key] = dirty = true;
183+
}
184+
if (!dirty) return;
185+
186+
this._state = assign({}, oldState, newState);
187+
this._recompute(changed, this._state);
188+
if (this._bind) this._bind(changed, this._state);
189+
190+
if (this._fragment) {
191+
dispatchObservers(this, this._observers.pre, changed, this._state, oldState);
192+
this._fragment.p(changed, this._state);
193+
dispatchObservers(this, this._observers.post, changed, this._state, oldState);
194+
}
195+
}
196+
197+
function setDev(newState) {
198+
if (typeof newState !== 'object') {
199+
throw new Error(
200+
this._debugName + '.set was called without an object of data key-values to update.'
201+
);
202+
}
203+
204+
this._checkReadOnly(newState);
205+
set.call(this, newState);
206+
}
207+
208+
function callAll(fns) {
209+
while (fns && fns.length) fns.shift()();
210+
}
211+
212+
function _mount(target, anchor) {
213+
this._fragment[this._fragment.i ? 'i' : 'm'](target, anchor || null);
214+
}
215+
216+
function _unmount() {
217+
if (this._fragment) this._fragment.u();
218+
}
219+
220+
var protoDev = {
221+
destroy: destroyDev,
222+
get: get,
223+
fire: fire,
224+
observe: observeDev,
225+
on: onDev,
226+
set: setDev,
227+
teardown: destroyDev,
228+
_recompute: noop,
229+
_set: _set,
230+
_mount: _mount,
231+
_unmount: _unmount,
232+
_differs: _differs
233+
};
234+
235+
/* generated by Svelte vX.Y.Z */
236+
237+
function bar(foo) {
238+
return foo * 2;
239+
}
240+
241+
function create_main_fragment(component, state) {
242+
var p, text_value = state.Math.max(0, state.foo), text, text_1, text_2;
243+
244+
return {
245+
c: function create() {
246+
p = createElement("p");
247+
text = createText(text_value);
248+
text_1 = createText("\n\t");
249+
text_2 = createText(state.bar);
250+
},
251+
252+
m: function mount(target, anchor) {
253+
insertNode(p, target, anchor);
254+
appendNode(text, p);
255+
appendNode(text_1, p);
256+
appendNode(text_2, p);
257+
},
258+
259+
p: function update(changed, state) {
260+
if ((changed.Math || changed.foo) && text_value !== (text_value = state.Math.max(0, state.foo))) {
261+
text.data = text_value;
262+
}
263+
264+
if (changed.bar) {
265+
text_2.data = state.bar;
266+
}
267+
},
268+
269+
u: function unmount() {
270+
detachNode(p);
271+
},
272+
273+
d: noop
274+
};
275+
}
276+
277+
function SvelteComponent(options) {
278+
this._debugName = '<SvelteComponent>';
279+
if (!options || (!options.target && !options.root)) throw new Error("'target' is a required option");
280+
init(this, options);
281+
this._state = assign({ Math : Math }, options.data);
282+
this._recompute({ foo: 1 }, this._state);
283+
if (!('foo' in this._state)) console.warn("<SvelteComponent> was created without expected data property 'foo'");
284+
285+
this._fragment = create_main_fragment(this, this._state);
286+
287+
if (options.target) {
288+
if (options.hydrate) throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
289+
this._fragment.c();
290+
this._mount(options.target, options.anchor);
291+
}
292+
}
293+
294+
assign(SvelteComponent.prototype, protoDev);
295+
296+
SvelteComponent.prototype._checkReadOnly = function _checkReadOnly(newState) {
297+
if ('bar' in newState && !this._updatingReadonlyProperty) throw new Error("<SvelteComponent>: Cannot set read-only property 'bar'");
298+
};
299+
300+
SvelteComponent.prototype._recompute = function _recompute(changed, state) {
301+
if (changed.foo) {
302+
if (this._differs(state.bar, (state.bar = bar(state.foo)))) changed.bar = true;
303+
}
304+
};
305+
306+
export default SvelteComponent;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/* generated by Svelte vX.Y.Z */
2+
import { appendNode, assign, createElement, createText, detachNode, init, insertNode, noop, protoDev } from "svelte/shared.js";
3+
4+
function bar(foo) {
5+
return foo * 2;
6+
}
7+
8+
function create_main_fragment(component, state) {
9+
var p, text_value = state.Math.max(0, state.foo), text, text_1, text_2;
10+
11+
return {
12+
c: function create() {
13+
p = createElement("p");
14+
text = createText(text_value);
15+
text_1 = createText("\n\t");
16+
text_2 = createText(state.bar);
17+
},
18+
19+
m: function mount(target, anchor) {
20+
insertNode(p, target, anchor);
21+
appendNode(text, p);
22+
appendNode(text_1, p);
23+
appendNode(text_2, p);
24+
},
25+
26+
p: function update(changed, state) {
27+
if ((changed.Math || changed.foo) && text_value !== (text_value = state.Math.max(0, state.foo))) {
28+
text.data = text_value;
29+
}
30+
31+
if (changed.bar) {
32+
text_2.data = state.bar;
33+
}
34+
},
35+
36+
u: function unmount() {
37+
detachNode(p);
38+
},
39+
40+
d: noop
41+
};
42+
}
43+
44+
function SvelteComponent(options) {
45+
this._debugName = '<SvelteComponent>';
46+
if (!options || (!options.target && !options.root)) throw new Error("'target' is a required option");
47+
init(this, options);
48+
this._state = assign({ Math : Math }, options.data);
49+
this._recompute({ foo: 1 }, this._state);
50+
if (!('foo' in this._state)) console.warn("<SvelteComponent> was created without expected data property 'foo'");
51+
52+
this._fragment = create_main_fragment(this, this._state);
53+
54+
if (options.target) {
55+
if (options.hydrate) throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
56+
this._fragment.c();
57+
this._mount(options.target, options.anchor);
58+
}
59+
}
60+
61+
assign(SvelteComponent.prototype, protoDev);
62+
63+
SvelteComponent.prototype._checkReadOnly = function _checkReadOnly(newState) {
64+
if ('bar' in newState && !this._updatingReadonlyProperty) throw new Error("<SvelteComponent>: Cannot set read-only property 'bar'");
65+
};
66+
67+
SvelteComponent.prototype._recompute = function _recompute(changed, state) {
68+
if (changed.foo) {
69+
if (this._differs(state.bar, (state.bar = bar(state.foo)))) changed.bar = true;
70+
}
71+
}
72+
export default SvelteComponent;

0 commit comments

Comments
 (0)