diff --git a/app/lib/AsyncCloner.coffee b/app/lib/AsyncCloner.coffee new file mode 100644 index 000000000..7050d3452 --- /dev/null +++ b/app/lib/AsyncCloner.coffee @@ -0,0 +1,82 @@ +#CocoClass = require 'lib/CocoClass' +# +#module.exports = class AsyncCloner extends CocoClass +# constructor: (@source, @depth=2) -> +# # passing in a depth of 0 will just _.clone the first layer, and will result in 1 indexList +# super() +# @indexLists = [] +# @initClone() +# +# initClone: () -> +# @target = AsyncCloner.cloneToDepth(@source, @depth) +# @indexLists = [_.keys(@target)] if _.isObject @target +# +# @cloneToDepth: (value, depth) -> +# value = _.clone(value) +# return value unless depth and _.isObject value +# value[key] = @cloneToDepth(value[key], depth-1) for key in _.keys value +# value +# +# clone: -> +# while @indexLists.length +# #console.log 'Clone loop:', JSON.stringify @indexLists +# @moveIndexForward() # fills or empties the index so @indexLists.length === @depth + 1 +# break if @done() +# @cloneOne() +# @moveIndexForwardOne() +# break if @done() or @timeToSleep() +# +# moveIndexForward: -> +# while @indexLists.length +# nextValue = @getNextValue() +# if _.isObject(nextValue) +# if @indexLists.length <= @depth +# # push a new list if it's a collection +# @indexLists.push _.keys(nextValue) +# continue +# else +# break # we done, the next value needs to be deep cloned +# #console.log 'Skipping:', @getNextPath() +# @moveIndexForwardOne() # move past this value otherwise +# #console.log '\tMoved index forward', JSON.stringify @indexLists +# +# getNextValue: -> +# value = @target +# value = value[indexList[0]] for indexList in @indexLists +# value +# +# getNextParent: -> +# parent = @target +# parent = parent[indexList[0]] for indexList in @indexLists[...-1] +# parent +# +# getNextPath: -> +# (indexList[0] for indexList in @indexLists when indexList.length).join '.' +# +# moveIndexForwardOne: -> +# @indexLists[@indexLists.length-1].shift() # move the index forward one +# # if we reached the end of an index list, trim down through all finished lists +# while @indexLists.length and not @indexLists[@indexLists.length-1].length +# @indexLists.pop() +# @indexLists[@indexLists.length-1].shift() if @indexLists.length +# +# cloneOne: -> +# if @indexLists.length isnt @depth + 1 +# throw new Error('Cloner is in an invalid state!') +# parent = @getNextParent() +# key = @indexLists[@indexLists.length-1][0] +# parent[key] = _.cloneDeep parent[key] +# #console.log 'Deep Cloned:', @getNextPath() +# +# done: -> not @indexLists.length +# +# timeToSleep: -> false + + +### + Overall, the loop is: + Fill indexes if we need to to the depth we've cloned + Clone that one, popping it off the list. + If the last list is now empty, pop that list and every subsequent list if needed. + Check for doneness, or timeout. +### \ No newline at end of file diff --git a/app/lib/LevelBus.coffee b/app/lib/LevelBus.coffee index 18985716b..3f852471d 100644 --- a/app/lib/LevelBus.coffee +++ b/app/lib/LevelBus.coffee @@ -178,7 +178,7 @@ module.exports = class LevelBus extends Bus return unless @onPoint() state = @session.get('state') state.thangs ?= {} - methods = _.cloneDeep(e.methods) + methods = $.extend(true, {}, (e.methods)) delete method.metrics.statements for methodName, method of methods state.thangs[e.thangID] = { methods: methods } @session.set('state', state) diff --git a/app/lib/scripts/ScriptManager.coffee b/app/lib/scripts/ScriptManager.coffee index 004f7d854..e879466f0 100644 --- a/app/lib/scripts/ScriptManager.coffee +++ b/app/lib/scripts/ScriptManager.coffee @@ -64,7 +64,7 @@ module.exports = ScriptManager = class ScriptManager extends CocoClass @triggered = [] @ended = [] @noteGroupQueue = [] - @scripts = _.cloneDeep(@originalScripts) + @scripts = $.extend(true, {}, @originalScripts) addScriptSubscriptions: -> idNum = 0 diff --git a/app/lib/sprites/SpriteParser.coffee b/app/lib/sprites/SpriteParser.coffee index 15fe749cd..ce5b08f4b 100644 --- a/app/lib/sprites/SpriteParser.coffee +++ b/app/lib/sprites/SpriteParser.coffee @@ -1,7 +1,7 @@ module.exports = class SpriteParser constructor: (@thangTypeModel) -> # Create a new ThangType, or work with one we've been building - @thangType = _.cloneDeep(@thangTypeModel.attributes.raw) + @thangType = $.extend(true, {}, @thangTypeModel.attributes.raw) @thangType ?= {} @thangType.shapes ?= {} @thangType.containers ?= {} diff --git a/app/lib/surface/CocoSprite.coffee b/app/lib/surface/CocoSprite.coffee index 9fe0b45a1..74df2cc0e 100644 --- a/app/lib/surface/CocoSprite.coffee +++ b/app/lib/surface/CocoSprite.coffee @@ -56,7 +56,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass constructor: (@thangType, options) -> super() - @options = _.extend(_.cloneDeep(@options), options) + @options = _.extend($.extend(true, {}, @options), options) @setThang @options.thang console.error @toString(), "has no ThangType!" unless @thangType @actionQueue = [] diff --git a/app/lib/surface/WizardSprite.coffee b/app/lib/surface/WizardSprite.coffee index 702f79ce4..9a50abc0f 100644 --- a/app/lib/surface/WizardSprite.coffee +++ b/app/lib/surface/WizardSprite.coffee @@ -30,7 +30,7 @@ module.exports = class WizardSprite extends IndieSprite constructor: (thangType, options) -> if options?.isSelf - options.colorConfig = _.cloneDeep(me.get('wizard')?.colorConfig) or {} + options.colorConfig = $.extend(true, {}, me.get('wizard')?.colorConfig) or {} super thangType, options @isSelf = options.isSelf @targetPos = @thang.pos @@ -67,7 +67,7 @@ module.exports = class WizardSprite extends IndieSprite @setNameLabel me.displayName() if @displayObject.visible # not if we hid the wiz newColorConfig = me.get('wizard')?.colorConfig or {} shouldUpdate = not _.isEqual(newColorConfig, @options.colorConfig) - @options.colorConfig = _.cloneDeep(newColorConfig) + @options.colorConfig = $.extend(true, {}, newColorConfig) if shouldUpdate @setupSprite() @playAction(@currentAction) diff --git a/app/lib/world/GoalManager.coffee b/app/lib/world/GoalManager.coffee index b017482b8..d524a0386 100644 --- a/app/lib/world/GoalManager.coffee +++ b/app/lib/world/GoalManager.coffee @@ -90,7 +90,7 @@ module.exports = class GoalManager extends CocoClass # IMPLEMENTATION DETAILS addGoal: (goal) -> - goal = _.cloneDeep(goal) + goal = $.extend(true, {}, goal) goal.id = @nextGoalID++ if not goal.id return if @goalStates[goal.id]? @goals.push(goal) diff --git a/app/models/ThangType.coffee b/app/models/ThangType.coffee index bfd501adf..4373c768c 100644 --- a/app/models/ThangType.coffee +++ b/app/models/ThangType.coffee @@ -30,7 +30,7 @@ module.exports = class ThangType extends CocoModel return @actions or @buildActions() buildActions: -> - @actions = _.cloneDeep(@get('actions') or {}) + @actions = $.extend(true, {}, @get('actions') or {}) for name, action of @actions action.name = name for relatedName, relatedAction of action.relatedActions ? {} diff --git a/app/views/account/wizard_settings_view.coffee b/app/views/account/wizard_settings_view.coffee index 78f9cee6a..9a5e20e9c 100644 --- a/app/views/account/wizard_settings_view.coffee +++ b/app/views/account/wizard_settings_view.coffee @@ -69,7 +69,7 @@ module.exports = class WizardSettingsView extends CocoView colorGroup.find('.minicolors-swatch').toggle Boolean(enabled) updateColorSettings: (colorGroup) => - wizardSettings = _.cloneDeep(me.get('wizard')) or {} + wizardSettings = $.extend(true, {}, me.get('wizard')) or {} wizardSettings.colorConfig ?= {} colorName = colorGroup.data('name') wizardSettings.colorConfig[colorName] ?= {} diff --git a/app/views/editor/components/main.coffee b/app/views/editor/components/main.coffee index fdcc55a6e..573ff054c 100644 --- a/app/views/editor/components/main.coffee +++ b/app/views/editor/components/main.coffee @@ -68,7 +68,7 @@ module.exports = class ThangComponentEditView extends CocoView treemaOptions = supermodel: @supermodel schema: { type: 'array', items: LevelComponent.schema.attributes } - data: (_.cloneDeep(c) for c in components) + data: ($.extend(true, {}, c) for c in components) callbacks: {select: @onSelectAddableComponent, enter: @onAddComponentEnterPressed } readOnly: true noSortable: true @@ -155,7 +155,7 @@ module.exports = class ThangComponentEditView extends CocoView reportChanges: -> - @callback?(_.cloneDeep(@extantComponentsTreema.data)) + @callback?($.extend(true, {}, @extantComponentsTreema.data)) class ThangComponentsArrayNode extends TreemaArrayNode valueClass: 'treema-thang-components-array' diff --git a/app/views/editor/level/fork_view.coffee b/app/views/editor/level/fork_view.coffee index f807df6c7..9f8ffb229 100644 --- a/app/views/editor/level/fork_view.coffee +++ b/app/views/editor/level/fork_view.coffee @@ -25,7 +25,7 @@ module.exports = class LevelForkView extends View forkLevel: -> @showLoading() forms.clearFormAlerts(@$el) - newLevel = new Level(_.cloneDeep(@level.attributes)) + newLevel = new Level($.extend(true, {}, @level.attributes)) newLevel.unset '_id' newLevel.unset 'version' newLevel.unset 'creator' diff --git a/app/views/editor/level/scripts_tab_view.coffee b/app/views/editor/level/scripts_tab_view.coffee index f0088ad21..57192d31f 100644 --- a/app/views/editor/level/scripts_tab_view.coffee +++ b/app/views/editor/level/scripts_tab_view.coffee @@ -21,7 +21,7 @@ module.exports = class ScriptsTabView extends View onLevelLoaded: (e) -> @level = e.level @dimensions = @level.dimensions() - scripts = _.cloneDeep(@level.get('scripts') ? []) + scripts = $.extend(true, {}, @level.get('scripts') ? []) scripts = _.cloneDeep defaultScripts unless scripts.length treemaOptions = schema: Level.schema.get('properties').scripts diff --git a/app/views/editor/level/system/add.coffee b/app/views/editor/level/system/add.coffee index 3afd6e35c..4ea54e3ec 100644 --- a/app/views/editor/level/system/add.coffee +++ b/app/views/editor/level/system/add.coffee @@ -61,7 +61,7 @@ module.exports = class LevelSystemAddView extends View levelSystem = original: s.get('original') ? id majorVersion: s.get('version').major ? 0 - config: _.cloneDeep(s.get('configSchema').default ? {}) + config: $.extend(true, {}, s.get('configSchema').default ? {}) @extantSystems.push levelSystem Backbone.Mediator.publish 'level-system-added', system: levelSystem @renderAvailableSystems() diff --git a/app/views/editor/level/systems_tab_view.coffee b/app/views/editor/level/systems_tab_view.coffee index a4b481754..00e175b7b 100644 --- a/app/views/editor/level/systems_tab_view.coffee +++ b/app/views/editor/level/systems_tab_view.coffee @@ -54,7 +54,7 @@ module.exports = class SystemsTabView extends View @buildSystemsTreema() buildSystemsTreema: -> - systems = _.cloneDeep(@level.get('systems') ? []) + systems = $.extend(true, {}, @level.get('systems') ? []) unless systems.length systems = @buildDefaultSystems() insertedDefaults = true diff --git a/app/views/editor/thang/edit.coffee b/app/views/editor/thang/edit.coffee index 23fa7f38d..a8a67ff39 100644 --- a/app/views/editor/thang/edit.coffee +++ b/app/views/editor/thang/edit.coffee @@ -40,7 +40,7 @@ module.exports = class ThangTypeEditView extends View constructor: (options, @thangTypeID) -> super options - @mockThang = _.cloneDeep(@mockThang) + @mockThang = $.extend(true, {}, @mockThang) @thangType = new ThangType(_id: @thangTypeID) @thangType.saveBackups = true @thangType.fetch() @@ -320,7 +320,7 @@ module.exports = class ThangTypeEditView extends View @treema.set('/', @getThangData()) getThangData: -> - data = _.cloneDeep(@thangType.attributes) + data = $.extend(true, {}, @thangType.attributes) data = _.pick data, (value, key) => not (key in ['components']) buildTreema: -> diff --git a/app/views/play/level/modal/docs_modal.coffee b/app/views/play/level/modal/docs_modal.coffee index 42aa98319..43ecfb070 100644 --- a/app/views/play/level/modal/docs_modal.coffee +++ b/app/views/play/level/modal/docs_modal.coffee @@ -25,7 +25,7 @@ module.exports = class DocsModal extends View @docs = specific.concat(general) marked.setOptions {gfm: true, sanitize: false, smartLists: true, breaks: false} - @docs = _.cloneDeep(@docs) + @docs = $.extend(true, {}, @docs) doc.html = marked(utils.i18n doc, 'body') for doc in @docs doc.name = (utils.i18n doc, 'name') for doc in @docs doc.slug = _.string.slugify(doc.name) for doc in @docs diff --git a/app/views/play/level_view.coffee b/app/views/play/level_view.coffee index 68bca74d8..aaa718703 100644 --- a/app/views/play/level_view.coffee +++ b/app/views/play/level_view.coffee @@ -167,7 +167,7 @@ module.exports = class PlayLevelView extends View @insertSubviews ladderGame: (@level.get('type') is "ladder") @initVolume() @session.on 'change:multiplayer', @onMultiplayerChanged, @ - @originalSessionState = _.cloneDeep(@session.get('state')) + @originalSessionState = $.extend(true, {}, @session.get('state')) @register() @controlBar.setBus(@bus) @surface.showLevel() diff --git a/app/views/play/spectate_view.coffee b/app/views/play/spectate_view.coffee index d3c79b7ae..283c7dc57 100644 --- a/app/views/play/spectate_view.coffee +++ b/app/views/play/spectate_view.coffee @@ -160,7 +160,7 @@ module.exports = class SpectateLevelView extends View @insertSubviews ladderGame: @otherSession? @initVolume() - @originalSessionState = _.cloneDeep(@session.get('state')) + @originalSessionState = $.extend(true, {}, @session.get('state')) @register() @controlBar.setBus(@bus) @surface.showLevel()