2014-01-03 13:32:13 -05:00
SpellView = require ' ./spell_view '
SpellListTabEntryView = require ' ./spell_list_tab_entry_view '
{ me } = require ' lib/auth '
module.exports = class Spell
loaded: false
view: null
entryView: null
2014-01-28 18:24:08 -05:00
constructor: (options) ->
@spellKey = options . spellKey
@pathComponents = options . pathComponents
@session = options . session
@supermodel = options . supermodel
@skipFlow = options . skipFlow
@skipProtectAPI = options . skipProtectAPI
2014-02-17 20:38:49 -05:00
@worker = options . worker
2014-01-28 18:24:08 -05:00
p = options . programmableMethod
2014-01-03 13:32:13 -05:00
@name = p . name
@source = @ session . getSourceFor ( @ spellKey ) ? p . source
@originalSource = p . source
@parameters = p . parameters
@permissions = read: p . permissions ? . read ? [ ] , readwrite: p . permissions ? . readwrite ? [ ] # teams
@thangs = { }
2014-04-18 17:59:08 -04:00
@view = new SpellView { spell: @ , session: @ session , worker: @ worker }
2014-01-03 13:32:13 -05:00
@ view . render ( ) # Get it ready and code loaded in advance
2014-01-09 17:04:46 -05:00
@tabView = new SpellListTabEntryView spell: @ , supermodel: @ supermodel
2014-01-03 13:32:13 -05:00
@ tabView . render ( )
2014-02-10 16:18:39 -05:00
@team = @ permissions . readwrite [ 0 ] ? " common "
Backbone . Mediator . publish ' tome:spell-created ' , spell: @
2014-01-03 13:32:13 -05:00
2014-02-17 20:38:49 -05:00
2014-02-11 15:10:21 -05:00
destroy: ->
@ view . destroy ( )
@ tabView . destroy ( )
2014-02-11 18:38:36 -05:00
@thangs = null
2014-02-17 20:38:49 -05:00
@worker = null
2014-02-11 16:10:59 -05:00
2014-01-03 13:32:13 -05:00
addThang: (thang) ->
2014-02-06 17:00:27 -05:00
if @ thangs [ thang . id ]
@ thangs [ thang . id ] . thang = thang
else
@ thangs [ thang . id ] = { thang: thang , aether: @ createAether ( thang ) , castAether: null }
2014-01-03 13:32:13 -05:00
2014-02-05 18:16:59 -05:00
removeThangID: (thangID) ->
delete @ thangs [ thangID ]
2014-01-03 13:32:13 -05:00
canRead: (team) ->
( team ? me . team ) in @ permissions . read or ( team ? me . team ) in @ permissions . readwrite
canWrite: (team) ->
( team ? me . team ) in @ permissions . readwrite
getSource: ->
@ view . getSource ( )
transpile: (source) ->
if source
@source = source
else
source = @ getSource ( )
2014-02-17 20:38:49 -05:00
[ pure , problems ] = [ null , null ]
2014-04-18 17:59:08 -04:00
workerMessage =
function: " lint "
spellKey: @ spellKey
source: source
@ worker . postMessage JSON . stringify ( workerMessage )
@ worker . addEventListener " message " , (e) ->
workerData = JSON . parse e . data
if workerData . function is " lint "
pure = workerData . lintMessages
2014-02-17 20:38:49 -05:00
for thangID , spellThang of @ thangs
2014-04-18 17:59:08 -04:00
2014-02-17 20:38:49 -05:00
unless pure
pure = spellThang . aether . transpile source
problems = spellThang . aether . problems
#console.log "aether transpiled", source.length, "to", pure.length, "for", thangID, @spellKey
else
spellThang.aether.pure = pure
spellThang.aether.problems = problems
#console.log "aether reused transpilation for", thangID, @spellKey
null
2014-01-03 13:32:13 -05:00
hasChanged: (newSource=null, currentSource=null) ->
( newSource ? @ originalSource ) isnt ( currentSource ? @ source )
2014-04-22 11:54:35 -04:00
hasChangedSignificantly: (newSource=null, currentSource=null, cb) ->
2014-01-03 13:32:13 -05:00
for thangID , spellThang of @ thangs
aether = spellThang . aether
break
unless aether
console . error @ toString ( ) , " couldn ' t find a spellThang with aether of " , @ thangs
return false
2014-04-22 11:54:35 -04:00
workerMessage =
function: " hasChangedSignificantly "
a: ( newSource ? @ originalSource )
spellKey: @ spellKey
b: ( currentSource ? @ source )
careAboutLineNumbers: true
careAboutLint: true
@ worker . addEventListener " message " , (e) =>
workerData = JSON . parse e . data
if workerData . function is " hasChangedSignificantly "
@ worker . removeEventListener ( " message " , arguments . callee , false )
cb ( workerData . hasChanged )
@ worker . postMessage JSON . stringify ( workerMessage )
2014-01-03 13:32:13 -05:00
createAether: (thang) ->
2014-03-28 09:42:08 -04:00
aceConfig = me . get ( ' aceConfig ' ) ? { }
2014-01-03 13:32:13 -05:00
aetherOptions =
problems:
jshint_W040: { level: " ignore " }
2014-02-03 16:58:25 -05:00
jshint_W030: { level: " ignore " } # aether_NoEffect instead
2014-04-14 14:18:02 -04:00
jshint_W038: { level: " ignore " } # eliminates hoisting problems
jshint_W091: { level: " ignore " } # eliminates more hoisting problems
jshint_E043: { level: " ignore " } # https://github.com/codecombat/codecombat/issues/813 -- since we can't actually tell JSHint to really ignore things
jshint_Unknown: { level: " ignore " } # E043 also triggers Unknown, so ignore that, too
2014-01-03 13:32:13 -05:00
aether_MissingThis: { level: ( if thang . requiresThis then ' error ' else ' warning ' ) }
2014-03-16 21:14:04 -04:00
language: aceConfig . language ? ' javascript '
2014-01-03 13:32:13 -05:00
functionName: @ name
functionParameters: @ parameters
yieldConditionally: thang . plan ?
requiresThis: thang . requiresThis
2014-01-29 11:38:37 -05:00
# TODO: Gridmancer doesn't currently work with protectAPI, so hack it off
2014-01-31 17:51:06 -05:00
protectAPI: not ( @ skipProtectAPI or window . currentView ? . level . get ( ' name ' ) . match ( " Gridmancer " ) ) and @ permissions . readwrite . length > 0 # If anyone can write to this method, we must protect it.
includeFlow: not @ skipFlow and @ canRead ( )
2014-01-21 12:03:04 -05:00
#callIndex: 0
2014-01-19 12:14:42 -05:00
#timelessVariables: ['i']
#statementIndex: 9001
2014-01-24 16:46:51 -05:00
if not ( me . team in @ permissions . readwrite ) or window . currentView ? . sessionID is " 52bfb88099264e565d001349 " # temp fix for debugger explosion bug
2014-01-21 12:03:04 -05:00
#console.log "Turning off includeFlow for", @spellKey
aetherOptions.includeFlow = false
2014-02-22 15:01:05 -05:00
#console.log "creating aether with options", aetherOptions
2014-01-03 13:32:13 -05:00
aether = new Aether aetherOptions
2014-04-18 17:59:08 -04:00
workerMessage =
function: " createAether "
spellKey: @ spellKey
options: aetherOptions
@ worker . postMessage JSON . stringify workerMessage
2014-01-03 13:32:13 -05:00
aether
2014-03-16 21:14:04 -04:00
updateLanguageAether: ->
2014-03-28 09:42:08 -04:00
aceConfig = me . get ( ' aceConfig ' ) ? { }
2014-04-18 17:59:08 -04:00
newLanguage = ( aceConfig . language ? ' javascript ' )
2014-03-16 21:14:04 -04:00
for thangId , spellThang of @ thangs
2014-04-18 17:59:08 -04:00
spellThang . aether ? . setLanguage newLanguage
2014-03-16 21:14:04 -04:00
spellThang.castAether = null
2014-04-18 17:59:08 -04:00
workerMessage =
function: " updateLanguageAether "
newLanguage: newLanguage
@ worker . postMessage JSON . stringify workerMessage
2014-03-16 21:14:04 -04:00
@ transpile ( )
2014-01-03 13:32:13 -05:00
toString: ->
" <Spell: #{ @ spellKey } > "