From 61ceb47182e57e9484775524f9f9c534cf348dfa Mon Sep 17 00:00:00 2001 From: Zalmoxisus Date: Sat, 15 Oct 2016 18:16:30 +0300 Subject: [PATCH] Better handling of circular references --- package.json | 2 +- src/app/api/index.js | 42 +++++++++----------------------- test/app/inject/api.spec.js | 9 ++++--- test/app/inject/enhancer.spec.js | 17 ++++++------- 4 files changed, 26 insertions(+), 44 deletions(-) diff --git a/package.json b/package.json index ec32ff0d..e6637f83 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "redux": "^3.5.2", "redux-devtools": "^3.3.1", "redux-devtools-instrument": "^1.3.2", - "remotedev-app": "^0.8.0-beta-8", + "remotedev-app": "^0.8.0-beta-12", "remotedev-slider": "^1.0.1", "remotedev-utils": "0.0.1" } diff --git a/src/app/api/index.js b/src/app/api/index.js index 7e95b7de..c58a4348 100644 --- a/src/app/api/index.js +++ b/src/app/api/index.js @@ -1,48 +1,28 @@ -import jsan from 'jsan'; +import { stringify } from 'jsan'; const listeners = {}; export const source = '@devtools-page'; -let isCircular; - -export default function stringify(obj, replacer, type) { - if (type === 2) { // Deep serialization - return jsan.stringify(obj, function(key, value) { - if (value && value.toJS) { return value.toJS(); } - return value; - }, null, true); - } - return jsan.stringify(obj, replacer); -} export function generateId(instanceId) { return instanceId || Math.random().toString(36).substr(2); } -function tryCatch(fn, args) { - try { - return fn(args); - } catch (err) { - isCircular = true; - toContentScript(args); - } -} - function post(message) { window.postMessage(message, '*'); } export function toContentScript(message, shouldStringify, serializeState, serializeAction) { - if (shouldStringify || isCircular) { - if (message.type !== 'ERROR' && message.type !== 'GET_REPORT' && message.payload) { - message.payload = stringify(message.payload, serializeState); - } - if (message.type !== 'STATE' && message.action) { - message.action = stringify(message.action, serializeAction); - } - post(message); - } else { - tryCatch(post, message); + if (message.type === 'ACTION') { + message.action = stringify(message.action, serializeAction); + message.payload = stringify(message.payload, serializeState); + } else if (message.type === 'STATE') { + const { actionsById, computedStates, committedState, ...rest } = message.payload; + message.payload = rest; + message.actionsById = stringify(actionsById, serializeAction); + message.computedStates = stringify(computedStates, serializeState); + message.committedState = stringify(committedState, serializeState); } + post(message); } export function sendMessage(action, state, shouldStringify, id, name) { diff --git a/test/app/inject/api.spec.js b/test/app/inject/api.spec.js index f21e4a77..61901ef2 100644 --- a/test/app/inject/api.spec.js +++ b/test/app/inject/api.spec.js @@ -33,7 +33,7 @@ describe('API', () => { }); expect(message).toInclude({ type: 'ACTION', - action: { action: { type: 'hi' } }, + action: '{"action":{"type":"hi"}}', payload: undefined, id: undefined, name: '', @@ -45,8 +45,8 @@ describe('API', () => { }); expect(message).toInclude({ type: 'ACTION', - action: { action: { type: 'hi' } }, - payload: { counter: 1 }, + action: '{"action":{"type":"hi"}}', + payload: '{"counter":1}', instanceId: 1, name: '', source: '@devtools-page' @@ -70,6 +70,9 @@ describe('API', () => { expect(message).toEqual({ type: 'STATE', payload: { counter: 1 }, + actionsById: undefined, + computedStates: undefined, + committedState: undefined, instanceId: 1, name: '', source: '@devtools-page' diff --git a/test/app/inject/enhancer.spec.js b/test/app/inject/enhancer.spec.js index 6d9d1a03..39f2770e 100644 --- a/test/app/inject/enhancer.spec.js +++ b/test/app/inject/enhancer.spec.js @@ -31,8 +31,8 @@ describe('Redux enhancer', () => { message = await listenMessage(); expect(message.type).toBe('STATE'); - expect(message.payload.actionsById[0].action.type).toBe('@@INIT'); - expect(message.payload.computedStates[0].state).toBe(0); + expect(message.actionsById).toInclude('{"0":{"type":"PERFORM_ACTION","action":{"type":"@@INIT"},"'); + expect(message.computedStates).toBe('[{"state":0}]'); }); it('should perform actions', async () => { @@ -41,16 +41,16 @@ describe('Redux enhancer', () => { expect(window.store.getState()).toBe(1); }); expect(message.type).toBe('ACTION'); - expect(message.action.action.type).toBe('INCREMENT'); - expect(message.payload).toBe(1); + expect(message.action).toInclude('{"type":"PERFORM_ACTION","action":{"type":"INCREMENT"},'); + expect(message.payload).toBe('1'); message = await listenMessage(() => { window.store.dispatch({ type: 'INCREMENT' }); expect(window.store.getState()).toBe(2); }); expect(message.type).toBe('ACTION'); - expect(message.action.action.type).toBe('INCREMENT'); - expect(message.payload).toBe(2); + expect(message.action).toInclude('{"type":"PERFORM_ACTION","action":{"type":"INCREMENT"},'); + expect(message.payload).toBe('2'); }); it('should dispatch actions remotely', async () => { @@ -65,8 +65,8 @@ describe('Redux enhancer', () => { message = await listenMessage(); expect(message.type).toBe('ACTION'); - expect(message.action.action.type).toBe('INCREMENT'); - expect(message.payload).toBe(3); + expect(message.action).toInclude('{"type":"PERFORM_ACTION","action":{"type":"INCREMENT"},'); + expect(message.payload).toBe('3'); }); it('should cancel (toggle) action', async () => { @@ -81,7 +81,6 @@ describe('Redux enhancer', () => { message = await listenMessage(); expect(message.type).toBe('STATE'); - expect(message.payload.computedStates[message.payload.computedStates.length - 1].state).toBe(2); expect(window.store.getState()).toBe(2); message = await listenMessage(() => {