@samitouri / QOS-React-2 / commits / 0c346ceea8

Re-added transferrables (after 'shutdown' evt fix) and guard against a tree mutation race

Brian Vaughn committed Feb 21, 2019 at 14:56 UTC 0c346ceea8650219b1dbb43d7bb0ebbe5732b318
4 files changed +39 -31
src/backend/agent.js
+1 -3
@@ -194,9 +194,7 @@ export default class Agent extends EventEmitter {
194
195 // TODO The chrome.runtime does not currently support transferables; it forces JSON serialization.
196 // The Store has a fallback in place that parses the message as JSON if the type isn't an array.
197 - // Sometimes using transferrables also cause Chrome or Firefox to throw "ArrayBuffer at index 0 is already neutered".
198 - // this._bridge.send('operations', operations, [operations.buffer]);
199 - this._bridge.send('operations', operations);
197 + this._bridge.send('operations', operations, [operations.buffer]);
198 };
199
200 _onClick = (event: MouseEvent) => {
src/backend/renderer.js
+4
@@ -524,6 +524,10 @@ export function attach(
524 }
525
526 function flushPendingEvents(root: Object): void {
527 + if (pendingOperations.length === 0) {
528 + return;
529 + }
530 +
531 // Identify which renderer this update is coming from.
532 // This enables roots to be mapped to renderers,
533 // Which in turn enables fiber props, states, and hooks to be inspected.
src/devtools/views/TreeContext.js
+33 -27
@@ -223,35 +223,41 @@ function reduceSearchState(store: Store, state: State, action: Action): State {
223 });
224
225 addedElementIDs.forEach(id => {
226 - const { displayName } = ((store.getElementByID(id): any): Element);
227 -
228 - // Add this item to the search results if it matches.
229 - const regExp = createRegExp(searchText);
230 - if (displayName !== null && regExp.test(displayName)) {
231 - const newElementIndex = ((store.getIndexOfElementID(
232 - id
233 - ): any): number);
234 -
235 - let foundMatch = false;
236 - for (let index = 0; index < searchResults.length; index++) {
237 - const id = searchResults[index];
238 - if (
239 - newElementIndex <
240 - ((store.getIndexOfElementID(id): any): number)
241 - ) {
242 - foundMatch = true;
243 - searchResults = searchResults
244 - .slice(0, index)
245 - .concat(id)
246 - .concat(searchResults.slice(index));
247 - break;
226 + const element = ((store.getElementByID(id): any): Element);
227 +
228 + // It's possible that multiple tree operations will fire before this action has run.
229 + // So it's important to check for elements that may have been added and then removed.
230 + if (element !== null) {
231 + const { displayName } = element;
232 +
233 + // Add this item to the search results if it matches.
234 + const regExp = createRegExp(searchText);
235 + if (displayName !== null && regExp.test(displayName)) {
236 + const newElementIndex = ((store.getIndexOfElementID(
237 + id
238 + ): any): number);
239 +
240 + let foundMatch = false;
241 + for (let index = 0; index < searchResults.length; index++) {
242 + const id = searchResults[index];
243 + if (
244 + newElementIndex <
245 + ((store.getIndexOfElementID(id): any): number)
246 + ) {
247 + foundMatch = true;
248 + searchResults = searchResults
249 + .slice(0, index)
250 + .concat(id)
251 + .concat(searchResults.slice(index));
252 + break;
253 + }
254 + }
255 + if (!foundMatch) {
256 + searchResults = searchResults.concat(id);
257 }
249 - }
250 - if (!foundMatch) {
251 - searchResults = searchResults.concat(id);
252 - }
258
254 - searchIndex = searchIndex === null ? 0 : searchIndex;
259 + searchIndex = searchIndex === null ? 0 : searchIndex;
260 + }
261 }
262 });
263 }
src/types.js
+1 -1
@@ -3,7 +3,7 @@
3 export type Bridge = {
4 addListener(type: string, callback: Function): void,
5 removeListener(type: string, callback: Function): void,
6 - send(type: string, data?: any): void,
6 + send(event: string, payload: any, transferable?: Array<any>): void,
7 };
8
9 export type Wall = {|