From 068a10b2db3c18d1510e15d680bee4e43f966d3d Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 30 Sep 2013 13:02:05 -0700 Subject: [PATCH] Extract deserializer management into class --- spec/deserializer-manager-spec.coffee | 33 ++++++++++++++++++++ spec/window-spec.coffee | 32 ------------------- src/atom.coffee | 2 ++ src/deserializer-manager.coffee | 38 ++++++++++++++++++++++ src/window.coffee | 45 +++++++-------------------- 5 files changed, 84 insertions(+), 66 deletions(-) create mode 100644 spec/deserializer-manager-spec.coffee create mode 100644 src/deserializer-manager.coffee diff --git a/spec/deserializer-manager-spec.coffee b/spec/deserializer-manager-spec.coffee new file mode 100644 index 000000000..84bc4b9d0 --- /dev/null +++ b/spec/deserializer-manager-spec.coffee @@ -0,0 +1,33 @@ +DeserializerManager = require '../src/deserializer-manager' + +describe ".deserialize(state)", -> + deserializer = null + + class Foo + @deserialize: ({name}) -> new Foo(name) + constructor: (@name) -> + + beforeEach -> + deserializer = new DeserializerManager() + deserializer.registerDeserializer(Foo) + + it "calls deserialize on the deserializer for the given state object, or returns undefined if one can't be found", -> + spyOn(console, 'warn') + object = deserializer.deserialize({ deserializer: 'Foo', name: 'Bar' }) + expect(object.name).toBe 'Bar' + expect(deserializer.deserialize({ deserializer: 'Bogus' })).toBeUndefined() + + describe "when the deserializer has a version", -> + beforeEach -> + Foo.version = 2 + + describe "when the deserialized state has a matching version", -> + it "attempts to deserialize the state", -> + object = deserializer.deserialize({ deserializer: 'Foo', version: 2, name: 'Bar' }) + expect(object.name).toBe 'Bar' + + describe "when the deserialized state has a non-matching version", -> + it "returns undefined", -> + expect(deserializer.deserialize({ deserializer: 'Foo', version: 3, name: 'Bar' })).toBeUndefined() + expect(deserializer.deserialize({ deserializer: 'Foo', version: 1, name: 'Bar' })).toBeUndefined() + expect(deserializer.deserialize({ deserializer: 'Foo', name: 'Bar' })).toBeUndefined() diff --git a/spec/window-spec.coffee b/spec/window-spec.coffee index fe00aa17b..187ddcfcf 100644 --- a/spec/window-spec.coffee +++ b/spec/window-spec.coffee @@ -96,38 +96,6 @@ describe "Window", -> expect(buffer.subscriptionCount()).toBe 0 - describe ".deserialize(state)", -> - class Foo - @deserialize: ({name}) -> new Foo(name) - constructor: (@name) -> - - beforeEach -> - registerDeserializer(Foo) - - afterEach -> - unregisterDeserializer(Foo) - - it "calls deserialize on the deserializer for the given state object, or returns undefined if one can't be found", -> - spyOn(console, 'warn') - object = deserialize({ deserializer: 'Foo', name: 'Bar' }) - expect(object.name).toBe 'Bar' - expect(deserialize({ deserializer: 'Bogus' })).toBeUndefined() - - describe "when the deserializer has a version", -> - beforeEach -> - Foo.version = 2 - - describe "when the deserialized state has a matching version", -> - it "attempts to deserialize the state", -> - object = deserialize({ deserializer: 'Foo', version: 2, name: 'Bar' }) - expect(object.name).toBe 'Bar' - - describe "when the deserialized state has a non-matching version", -> - it "returns undefined", -> - expect(deserialize({ deserializer: 'Foo', version: 3, name: 'Bar' })).toBeUndefined() - expect(deserialize({ deserializer: 'Foo', version: 1, name: 'Bar' })).toBeUndefined() - expect(deserialize({ deserializer: 'Foo', name: 'Bar' })).toBeUndefined() - describe "drag and drop", -> buildDragEvent = (type, files) -> dataTransfer = diff --git a/src/atom.coffee b/src/atom.coffee index 1668b2451..74459a619 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -10,6 +10,7 @@ path = require 'path' dialog = remote.require 'dialog' app = remote.require 'app' {Document} = require 'telepath' +DeserializerManager = require './deserializer-manager' Subscriber = require './subscriber' # Public: Atom global for dealing with packages, themes, menus, and the window. @@ -21,6 +22,7 @@ class Atom constructor: -> @rootViewParentSelector = 'body' + @deserializers = new DeserializerManager() initialize: -> @unsubscribe() diff --git a/src/deserializer-manager.coffee b/src/deserializer-manager.coffee new file mode 100644 index 000000000..8fd3bec19 --- /dev/null +++ b/src/deserializer-manager.coffee @@ -0,0 +1,38 @@ +{Document} = require 'telepath' + +module.exports = +class DeserializerManager + constructor: -> + @deserializers = {} + @deferredDeserializers = {} + + registerDeserializer: (klasses...) -> + @deserializers[klass.name] = klass for klass in klasses + + registerDeferredDeserializer: (name, fn) -> + @deferredDeserializers[name] = fn + + unregisterDeserializer: (klasses...) -> + delete @deserializers[klass.name] for klass in klasses + + deserialize: (state, params) -> + return unless state? + + if deserializer = @getDeserializer(state) + stateVersion = state.get?('version') ? state.version + return if deserializer.version? and deserializer.version isnt stateVersion + if (state instanceof Document) and not deserializer.acceptsDocuments + state = state.toObject() + deserializer.deserialize(state, params) + else + console.warn "No deserializer found for", state + + getDeserializer: (state) -> + return unless state? + + name = state.get?('deserializer') ? state.deserializer + if @deferredDeserializers[name] + @deferredDeserializers[name]() + delete @deferredDeserializers[name] + + @deserializers[name] diff --git a/src/window.coffee b/src/window.coffee index 323b8bf3e..738431186 100644 --- a/src/window.coffee +++ b/src/window.coffee @@ -7,9 +7,6 @@ remote = require 'remote' ipc = require 'ipc' WindowEventHandler = require './window-event-handler' -deserializers = {} -deferredDeserializers = {} - ### Internal ### windowEventHandler = null @@ -116,37 +113,17 @@ window.onerror = -> atom.openDevTools() window.registerDeserializers = (args...) -> - registerDeserializer(arg) for arg in args - -window.registerDeserializer = (klass) -> - deserializers[klass.name] = klass - -window.registerDeferredDeserializer = (name, fn) -> - deferredDeserializers[name] = fn - -window.unregisterDeserializer = (klass) -> - delete deserializers[klass.name] - -window.deserialize = (state, params) -> - return unless state? - if deserializer = getDeserializer(state) - stateVersion = state.get?('version') ? state.version - return if deserializer.version? and deserializer.version isnt stateVersion - if (state instanceof telepath.Document) and not deserializer.acceptsDocuments - state = state.toObject() - deserializer.deserialize(state, params) - else - console.warn "No deserializer found for", state - -window.getDeserializer = (state) -> - return unless state? - - name = state.get?('deserializer') ? state.deserializer - if deferredDeserializers[name] - deferredDeserializers[name]() - delete deferredDeserializers[name] - - deserializers[name] + atom.deserializers.registerDeserializer(args...) +window.registerDeserializer = (args...) -> + atom.deserializers.registerDeserializer(args...) +window.registerDeferredDeserializer = (args...) -> + atom.deserializers.registerDeferredDeserializer(args...) +window.unregisterDeserializer = (args...) -> + atom.deserializers.unregisterDeserializer(args...) +window.deserialize = (args...) -> + atom.deserializers.deserialize(args...) +window.getDeserializer = (args...) -> + atom.deserializer.getDeserializer(args...) window.requireWithGlobals = (id, globals={}) -> existingGlobals = {}