Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(310)

Side by Side Diff: src/object-observe.js

Issue 11593028: Object.observe: Change semantics of deliverChangeRecords to iterate. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed comments Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | test/mjsunit/harmony/object-observe.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 throw MakeTypeError("observe_callback_frozen"); 75 throw MakeTypeError("observe_callback_frozen");
76 76
77 if (!observerInfoMap.has(callback)) { 77 if (!observerInfoMap.has(callback)) {
78 observerInfoMap.set(callback, { 78 observerInfoMap.set(callback, {
79 pendingChangeRecords: null, 79 pendingChangeRecords: null,
80 priority: observationState.observerPriority++, 80 priority: observationState.observerPriority++,
81 }); 81 });
82 } 82 }
83 83
84 var objectInfo = objectInfoMap.get(object); 84 var objectInfo = objectInfoMap.get(object);
85 if (IS_UNDEFINED(objectInfo)) { 85 if (IS_UNDEFINED(objectInfo)) objectInfo = CreateObjectInfo(object);
86 objectInfo = CreateObjectInfo(object);
87 }
88 %SetIsObserved(object, true); 86 %SetIsObserved(object, true);
89 87
90 var changeObservers = objectInfo.changeObservers; 88 var changeObservers = objectInfo.changeObservers;
91 if (changeObservers.indexOf(callback) < 0) 89 if (changeObservers.indexOf(callback) < 0) changeObservers.push(callback);
92 changeObservers.push(callback);
93 90
94 return object; 91 return object;
95 } 92 }
96 93
97 function ObjectUnobserve(object, callback) { 94 function ObjectUnobserve(object, callback) {
98 if (!IS_SPEC_OBJECT(object)) 95 if (!IS_SPEC_OBJECT(object))
99 throw MakeTypeError("observe_non_object", ["unobserve"]); 96 throw MakeTypeError("observe_non_object", ["unobserve"]);
100 if (!IS_SPEC_FUNCTION(callback)) 97 if (!IS_SPEC_FUNCTION(callback))
101 throw MakeTypeError("observe_non_function", ["unobserve"]); 98 throw MakeTypeError("observe_non_function", ["unobserve"]);
102 99
103 var objectInfo = objectInfoMap.get(object); 100 var objectInfo = objectInfoMap.get(object);
104 if (IS_UNDEFINED(objectInfo)) 101 if (IS_UNDEFINED(objectInfo))
105 return object; 102 return object;
106 103
107 var changeObservers = objectInfo.changeObservers; 104 var changeObservers = objectInfo.changeObservers;
108 var index = changeObservers.indexOf(callback); 105 var index = changeObservers.indexOf(callback);
109 if (index >= 0) { 106 if (index >= 0) {
110 changeObservers.splice(index, 1); 107 changeObservers.splice(index, 1);
111 if (changeObservers.length === 0) 108 if (changeObservers.length === 0) %SetIsObserved(object, false);
112 %SetIsObserved(object, false);
113 } 109 }
114 110
115 return object; 111 return object;
116 } 112 }
117 113
118 function EnqueueChangeRecord(changeRecord, observers) { 114 function EnqueueChangeRecord(changeRecord, observers) {
119 for (var i = 0; i < observers.length; i++) { 115 for (var i = 0; i < observers.length; i++) {
120 var observer = observers[i]; 116 var observer = observers[i];
121 var observerInfo = observerInfoMap.get(observer); 117 var observerInfo = observerInfoMap.get(observer);
122 observationState.pendingObservers[observerInfo.priority] = observer; 118 observationState.pendingObservers[observerInfo.priority] = observer;
(...skipping 11 matching lines...) Expand all
134 var changeRecord = (arguments.length < 4) ? 130 var changeRecord = (arguments.length < 4) ?
135 { type: type, object: object, name: name } : 131 { type: type, object: object, name: name } :
136 { type: type, object: object, name: name, oldValue: oldValue }; 132 { type: type, object: object, name: name, oldValue: oldValue };
137 ObjectFreeze(changeRecord); 133 ObjectFreeze(changeRecord);
138 EnqueueChangeRecord(changeRecord, objectInfo.changeObservers); 134 EnqueueChangeRecord(changeRecord, objectInfo.changeObservers);
139 } 135 }
140 136
141 var notifierPrototype = {}; 137 var notifierPrototype = {};
142 138
143 function ObjectNotifierNotify(changeRecord) { 139 function ObjectNotifierNotify(changeRecord) {
140 var target = notifierTargetMap.get(this);
144 if (!IS_SPEC_OBJECT(this)) 141 if (!IS_SPEC_OBJECT(this))
145 throw MakeTypeError("called_on_non_object", ["notify"]); 142 throw MakeTypeError("called_on_non_object", ["notify"]);
146
147 var target = notifierTargetMap.get(this);
148 if (IS_UNDEFINED(target)) 143 if (IS_UNDEFINED(target))
149 throw MakeTypeError("observe_notify_non_notifier"); 144 throw MakeTypeError("observe_notify_non_notifier");
150
151 if (!IS_STRING(changeRecord.type)) 145 if (!IS_STRING(changeRecord.type))
152 throw MakeTypeError("observe_type_non_string"); 146 throw MakeTypeError("observe_type_non_string");
153 147
154 var objectInfo = objectInfoMap.get(target); 148 var objectInfo = objectInfoMap.get(target);
155 if (IS_UNDEFINED(objectInfo)) 149 if (IS_UNDEFINED(objectInfo) || objectInfo.changeObservers.length === 0)
156 return; 150 return;
157 151
158 if (!objectInfo.changeObservers.length) 152 var newRecord = { object: target };
159 return;
160
161 var newRecord = {
162 object: target
163 };
164 for (var prop in changeRecord) { 153 for (var prop in changeRecord) {
165 if (prop === 'object') 154 if (prop === 'object') continue;
166 continue;
167
168 %DefineOrRedefineDataProperty(newRecord, prop, changeRecord[prop], 155 %DefineOrRedefineDataProperty(newRecord, prop, changeRecord[prop],
169 READ_ONLY + DONT_DELETE); 156 READ_ONLY + DONT_DELETE);
170 } 157 }
171 ObjectFreeze(newRecord); 158 ObjectFreeze(newRecord);
172 159
173 EnqueueChangeRecord(newRecord, objectInfo.changeObservers); 160 EnqueueChangeRecord(newRecord, objectInfo.changeObservers);
174 } 161 }
175 162
176 function ObjectGetNotifier(object) { 163 function ObjectGetNotifier(object) {
177 if (!IS_SPEC_OBJECT(object)) 164 if (!IS_SPEC_OBJECT(object))
178 throw MakeTypeError("observe_non_object", ["getNotifier"]); 165 throw MakeTypeError("observe_non_object", ["getNotifier"]);
179 166
180 if (ObjectIsFrozen(object)) 167 if (ObjectIsFrozen(object)) return null;
181 return null;
182 168
183 var objectInfo = objectInfoMap.get(object); 169 var objectInfo = objectInfoMap.get(object);
184 if (IS_UNDEFINED(objectInfo)) 170 if (IS_UNDEFINED(objectInfo)) objectInfo = CreateObjectInfo(object);
185 objectInfo = CreateObjectInfo(object);
186 171
187 if (IS_NULL(objectInfo.notifier)) { 172 if (IS_NULL(objectInfo.notifier)) {
188 objectInfo.notifier = { 173 objectInfo.notifier = { __proto__: notifierPrototype };
189 __proto__: notifierPrototype
190 };
191 notifierTargetMap.set(objectInfo.notifier, object); 174 notifierTargetMap.set(objectInfo.notifier, object);
192 } 175 }
193 176
194 return objectInfo.notifier; 177 return objectInfo.notifier;
195 } 178 }
196 179
197 function DeliverChangeRecordsForObserver(observer) { 180 function DeliverChangeRecordsForObserver(observer) {
198 var observerInfo = observerInfoMap.get(observer); 181 var observerInfo = observerInfoMap.get(observer);
199 if (IS_UNDEFINED(observerInfo)) 182 if (IS_UNDEFINED(observerInfo))
200 return; 183 return false;
201 184
202 var pendingChangeRecords = observerInfo.pendingChangeRecords; 185 var pendingChangeRecords = observerInfo.pendingChangeRecords;
203 if (IS_NULL(pendingChangeRecords)) 186 if (IS_NULL(pendingChangeRecords))
204 return; 187 return false;
205 188
206 observerInfo.pendingChangeRecords = null; 189 observerInfo.pendingChangeRecords = null;
207 delete observationState.pendingObservers[observerInfo.priority]; 190 delete observationState.pendingObservers[observerInfo.priority];
208 var delivered = []; 191 var delivered = [];
209 %MoveArrayContents(pendingChangeRecords, delivered); 192 %MoveArrayContents(pendingChangeRecords, delivered);
210 try { 193 try {
211 %Call(void 0, delivered, observer); 194 %Call(void 0, delivered, observer);
212 } catch (ex) {} 195 } catch (ex) {}
196 return true;
213 } 197 }
214 198
215 function ObjectDeliverChangeRecords(callback) { 199 function ObjectDeliverChangeRecords(callback) {
216 if (!IS_SPEC_FUNCTION(callback)) 200 if (!IS_SPEC_FUNCTION(callback))
217 throw MakeTypeError("observe_non_function", ["deliverChangeRecords"]); 201 throw MakeTypeError("observe_non_function", ["deliverChangeRecords"]);
218 202
219 DeliverChangeRecordsForObserver(callback); 203 while (DeliverChangeRecordsForObserver(callback)) {}
220 } 204 }
221 205
222 function DeliverChangeRecords() { 206 function DeliverChangeRecords() {
223 while (observationState.pendingObservers.length) { 207 while (observationState.pendingObservers.length) {
224 var pendingObservers = observationState.pendingObservers; 208 var pendingObservers = observationState.pendingObservers;
225 observationState.pendingObservers = new InternalArray; 209 observationState.pendingObservers = new InternalArray;
226 for (var i in pendingObservers) { 210 for (var i in pendingObservers) {
227 DeliverChangeRecordsForObserver(pendingObservers[i]); 211 DeliverChangeRecordsForObserver(pendingObservers[i]);
228 } 212 }
229 } 213 }
230 } 214 }
231 215
232 function SetupObjectObserve() { 216 function SetupObjectObserve() {
233 %CheckIsBootstrapping(); 217 %CheckIsBootstrapping();
234 InstallFunctions($Object, DONT_ENUM, $Array( 218 InstallFunctions($Object, DONT_ENUM, $Array(
235 "deliverChangeRecords", ObjectDeliverChangeRecords, 219 "deliverChangeRecords", ObjectDeliverChangeRecords,
236 "getNotifier", ObjectGetNotifier, 220 "getNotifier", ObjectGetNotifier,
237 "observe", ObjectObserve, 221 "observe", ObjectObserve,
238 "unobserve", ObjectUnobserve 222 "unobserve", ObjectUnobserve
239 )); 223 ));
240 InstallFunctions(notifierPrototype, DONT_ENUM, $Array( 224 InstallFunctions(notifierPrototype, DONT_ENUM, $Array(
241 "notify", ObjectNotifierNotify 225 "notify", ObjectNotifierNotify
242 )); 226 ));
243 } 227 }
244 228
245 SetupObjectObserve(); 229 SetupObjectObserve();
OLDNEW
« no previous file with comments | « no previous file | test/mjsunit/harmony/object-observe.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698