11var CCLScripting = function ( workerUrl ) {
22 this . version = 1.0 ;
33 this . workerUrl = workerUrl ;
4+ this . logger = new function ( ) {
5+ this . log = function ( m ) {
6+ console . log ( m ) ;
7+ } ;
8+ this . error = function ( m ) {
9+ console . error ( m ) ;
10+ } ;
11+ this . warn = function ( m ) {
12+ console . warn ( m ) ;
13+ } ;
14+ } ;
415 this . getWorker = function ( ) {
516 return new Worker ( this . workerUrl ) ;
617 } ;
7- this . getScriptingContext ( stage ) {
8- return new this . ScriptingContext ( stage ) ;
18+ this . getScriptingContext = function ( stage ) {
19+ return new this . ScriptingContext ( this , stage ) ;
20+ } ;
21+ this . getSandbox = function ( stage , player ) {
22+ return new this . BridgedSandbox ( this , stage , player ) ;
923 } ;
1024} ;
1125
@@ -15,27 +29,78 @@ var CCLScripting = function(workerUrl){
1529 return ;
1630 }
1731
18- CCLScripting . prototype . ScriptingContext = function ( stage ) {
32+ CCLScripting . prototype . ScriptingContext = function ( scripter , stage ) {
1933 // Here in the Scripting Context we also have a objects
34+ var objects = { } ;
35+ this . registerObject = function ( objectId , serialized ) {
36+ if ( typeof this . Unpack [ serialized [ "class" ] ] === "function" ) {
37+ objects [ objectId ] = new this . Unpack [ serialized [ "class" ] ] ( stage ,
38+ serialized ) ;
39+ } else {
40+ scripter . logger . error ( "Cannot unpack class \"" +
41+ serialized [ "class" ] + "\". No valid unpacker found" ) ;
42+ return ;
43+ }
44+ } ;
2045
21- } ;
22-
23- CCLScripting . prototype . BridgedSandbox = function ( stage ) {
24- var worker = this . getWorker ( ) ;
25- var context = this . getScriptingContext ( stage ) ;
26- var channels = {
27- "::worker:state" :{
28- "max" :0 ,
29- "listeners" :[ ]
46+ this . deregisterObject = function ( objectId ) {
47+ delete objects [ objectId ] ;
48+ } ;
49+
50+ this . callMethod = function ( objectId , methodName , params ) {
51+ if ( ! objects [ objectId ] ) {
52+ scripter . logger . error ( "Object not found." ) ;
53+ return ;
54+ }
55+ if ( ! objects [ objectId ] [ methodName ] ) {
56+ scripter . logger . error ( "Method \"" + methodName
57+ + "\" not defined for object of type " +
58+ objects [ objectId ] . getClass ( ) + "." ) ;
59+ return ;
3060 }
61+ try {
62+ objects [ objectId ] [ methodName ] ( params ) ;
63+ } catch ( e ) {
64+ if ( e . stack ) {
65+ scripter . logger . error ( e . stack ) ;
66+ } else {
67+ scripter . logger . error ( e . toString ( ) ) ;
68+ } ;
69+ }
70+ } ;
71+
72+ this . clear = function ( ) {
73+
3174 } ;
75+ } ;
76+
77+ CCLScripting . prototype . ScriptingContext . prototype . Unpack = { } ;
78+
79+ CCLScripting . prototype . BridgedSandbox = function ( scripter , stage , player ) {
80+ var worker = scripter . getWorker ( ) ;
81+ var context = scripter . getScriptingContext ( stage ) ;
82+ var playerAbst = player ;
83+ var channels = { } ;
3284 var isRunning = false ;
85+ var sandbox = this ;
3386
3487 if ( ! worker ) {
3588 throw new Error ( "SANDBOX: Worker pool exhausted." ) ;
3689 }
3790
38- var addListener = function ( channel , listener ) {
91+ this . getLogger = function ( ) {
92+ return scripter . logger ;
93+ } ;
94+
95+ this . getPlayer = function ( ) {
96+ return playerAbst ;
97+ } ;
98+
99+ this . getContext = function ( ) {
100+ return context ;
101+ } ;
102+
103+ this . addListener = function ( channel , listener ) {
39104 if ( ! channels [ channel ] ) {
40105 channels [ channel ] = {
41106 "max" :0 ,
@@ -57,40 +122,160 @@ var CCLScripting = function(workerUrl){
57122 try {
58123 channels [ msg . channel ] . listeners [ i ] ( msg . payload ) ;
59124 } catch ( e ) {
60- __trace ( e , 'err' ) ;
125+ scripter . logger . error ( e ) ;
61126 }
62127 }
63128 } else {
64- console . log ( "Message for channel: " + msg . channel +
65- " but channel not existant." ) ;
129+ scripter . logger . warn ( "Message for channel \" " + msg . channel +
130+ "\" but channel not existant." ) ;
66131 }
67132 } ;
68133
69- worker . onmessage = function ( event ) {
134+ var WorkerHook = function ( event ) {
70135 try {
71136 var resp = JSON . parse ( event . data ) ;
72137 } catch ( e ) {
73138 console . log ( e ) ;
74139 return ;
75140 }
76- if ( ! isRunning ) {
77- if ( resp . channel === "::worker:state" ) {
78- if ( resp . payload === "running" && resp . auth === "worker" ) {
79- isRunning = true ;
141+ if ( resp . channel === "" ) {
142+ switch ( resp . mode ) {
143+ case "log" :
144+ default :{
145+ scripter . logger . log ( resp . obj ) ;
146+ break ;
80147 }
81- }
148+ case "warn" :{
149+ scripter . logger . warn ( resp . obj ) ;
150+ break ;
151+ }
152+ case "err" :{
153+ scripter . logger . error ( resp . obj ) ;
154+ break ;
155+ }
156+ case "fatal" :{
157+ scripter . logger . error ( resp . obj ) ;
158+ sandbox . resetWorker ( ) ;
159+ return ;
160+ }
161+ } ;
82162 return ;
163+ }
164+ if ( resp . channel . substring ( 0 , 8 ) === "::worker" ) {
165+ var RN = resp . channel . substring ( 8 ) ;
166+ switch ( RN ) {
167+ case ":state" :{
168+ if ( resp . payload === "running" && resp . auth === "worker" ) {
169+ isRunning = true ;
170+ channels = { } ;
171+ sandbox . init ( ) ;
172+ }
173+ break ;
174+ }
175+ default :{
176+ console . log ( resp ) ;
177+ break ;
178+ }
179+ }
83180 } else {
84181 dispatchMessage ( resp ) ;
85182 }
86183 } ;
87184
185+ this . resetWorker = function ( ) {
186+ try {
187+ worker . terminate ( ) ;
188+ } catch ( e ) { }
189+ worker = scripter . getWorker ( ) ;
190+ if ( ! worker ) {
191+ throw new Error ( "SANDBOX: Worker pool exhausted." ) ;
192+ }
193+ worker . addEventListener ( "message" , WorkerHook ) ;
194+ } ;
195+
196+ worker . addEventListener ( "message" , WorkerHook ) ;
197+
88198 this . eval = function ( code ) {
89199 // Pushes the code to be evaluated on the Worker
200+ if ( ! isRunning ) {
201+ throw new Error ( "Worker offline" ) ;
202+ }
90203 worker . postMessage ( JSON . stringify ( {
91204 "channel" :"::eval" ,
92205 "payload" :code
93206 } ) ) ;
94207 } ;
208+
209+ this . send = function ( channel , payload ) {
210+ // Low level send
211+ worker . postMessage ( JSON . stringify ( {
212+ "channel" :channel ,
213+ "payload" :payload
214+ } ) ) ;
215+ } ;
216+ } ;
217+ CCLScripting . prototype . BridgedSandbox . prototype . init = function ( ) {
218+ var self = this ;
219+ this . addListener ( "Runtime::alert" , function ( msg ) {
220+ alert ( msg ) ;
221+ } ) ;
222+ this . addListener ( "Runtime::clear" , function ( ) {
223+ self . getContext ( ) . clear ( ) ;
224+ } ) ;
225+ this . addListener ( "Player::action" , function ( msg ) {
226+ try {
227+ switch ( msg . action ) {
228+ default :return ;
229+ case "play" : self . getPlayer ( ) . play ( ) ; break ;
230+ case "pause" : self . getPlayer ( ) . pause ( ) ; break ;
231+ case "seek" : self . getPlayer ( ) . seek ( msg . offset ) ; break ;
232+ case "jump" : self . getPlayer ( ) . jump ( msg . params ) ; break ;
233+ }
234+ } catch ( e ) {
235+ if ( e . stack ) {
236+ self . getLogger ( ) . error ( e . stack ) ;
237+ } else {
238+ self . getLogger ( ) . error ( e . toString ( ) ) ;
239+ }
240+ }
241+ } ) ;
242+ this . addListener ( "Runtime:RegisterObject" , function ( pl ) {
243+ self . getContext ( ) . registerObject ( pl . id , pl . data ) ;
244+ } ) ;
245+ this . addListener ( "Runtime:DeregisterObject" , function ( pl ) {
246+ self . getContext ( ) . deregisterObject ( pl . id ) ;
247+ } ) ;
248+ this . addListener ( "Runtime:InvokeMethod" , function ( pl ) {
249+ self . getContext ( ) . callMethod ( pl . id , pl . method , pl . params ) ;
250+ } ) ;
251+ } ;
252+
253+ // Define some unpackers
254+ var ScriptingContext = CCLScripting . prototype . ScriptingContext ;
255+ ScriptingContext . prototype . Unpack . Comment = function ( stage , data ) {
256+ this . DOM = document . createElement ( "div" ) ;
257+
258+ this . DOM . appendChild ( document . createTextNode ( data . text ) ) ;
259+
260+ this . setFilters = function ( params ) {
261+ for ( var i = 0 ; i < params [ 0 ] . length ; i ++ ) {
262+ var filter = params [ 0 ] [ i ] ;
263+ if ( filter . type === "blur" ) {
264+ this . DOM . style . color = "transparent" ;
265+ this . DOM . style . textShadow = [ - filter . params . blurX + "px" ,
266+ - filter . params . blurY + "px" , Math . max (
267+ filter . params . blurX , filter . params . blurY ) +
268+ "px" ] . join ( " " ) ;
269+ } else if ( filter . type === "glow" ) {
270+ this . DOM . style . textShadow = [ - filter . params . blurX + "px" ,
271+ - filter . params . blurY + "px" , Math . max (
272+ filter . params . blurX , filter . params . blurY ) +
273+ "px" , "#" + filter . params . color . toString ( 16 ) ] . join ( " " ) ;
274+ }
275+ } ;
276+ } ;
277+
278+ // Hook child
279+ stage . appendChild ( this . DOM ) ;
95280 } ;
96281} ) ( ) ;
0 commit comments