UNPKG

2.11 kBJavaScriptView Raw
1import { computedQueue, computedI, computedNotify } from "./computed.js";
2import {
3 isObject, isFunction,
4 hasOwnProperty, defineProperty,
5 HINT_OBSERVE, HINT_DEPENDS, defineHint,
6 MESSAGE_NOT_OBJECT, throwError
7} from "./util.js";
8
9/**
10 * Generates a property descriptor for a reactive property
11 * @param value Initial property value
12 * @returns Property descriptor object
13 */
14function reactiveProperty(value) {
15 if (isObject(value)) reactiveObserve(value);
16
17 // List of computed functions that depend on this property
18 var depends = [];
19 /**
20 * Remove a computed function from this reactive property
21 * @param func Computed function to remove
22 */
23 function dependsRemove(func) {
24 var i = depends.lastIndexOf(func);
25 if (i >= 0) depends.splice(i, 1);
26 }
27
28 return {
29 get: function() {
30 // Add the current executing computed function to this reactive property's dependencies
31 var func = computedQueue[computedI];
32 if (func) {
33 var i = depends.lastIndexOf(func);
34 if (i < 0) {
35 // Add them to our dependencies
36 depends.push(func);
37 // Add us to their dependants
38 func[HINT_DEPENDS].push(dependsRemove);
39 }
40 }
41
42 return value;
43 },
44 set: function(newValue) {
45 if (isObject(newValue)) reactiveObserve(newValue);
46 value = newValue;
47
48 // Notify all dependencies
49 for (var i = 0; i < depends.length; i++) {
50 computedNotify(depends[i]);
51 }
52 }
53 };
54}
55
56/**
57 * Observes an object by making all of its enumerable properties reactive
58 * @param object Object to observe
59 */
60function reactiveObserve(object) {
61 if (hasOwnProperty(object, HINT_OBSERVE)) return;
62 defineHint(object, HINT_OBSERVE);
63
64 for (var key in object) {
65 if (hasOwnProperty(object, key)) {
66 try {
67 defineProperty(object, key, reactiveProperty(object[key]));
68 } catch (err) {}
69 }
70 }
71}
72
73/** See lib/patella.d.ts */
74export function observe(object) {
75 if (!isObject(object) && !isFunction(object)) {
76 throwError(MESSAGE_NOT_OBJECT);
77 }
78
79 reactiveObserve(object);
80 return object;
81}