Skip to content

Commit 2ad2a93

Browse files
committed
Added Scripting Stuff for Host
1 parent 274c920 commit 2ad2a93

13 files changed

Lines changed: 577 additions & 65 deletions

File tree

src/scripting/Host.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,9 @@ var CCLScripting = function(workerUrl){
230230
this.resetWorker = function(){
231231
try{
232232
worker.terminate();
233-
}catch(e){}
233+
} catch(e) {
234+
235+
}
234236
worker = scripter.getWorker();
235237
if(!worker){
236238
throw new Error("SANDBOX: Worker pool exhausted.");

src/scripting/api/Display/Bitmap.ts

Lines changed: 105 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,42 @@
33

44
module Display {
55

6+
class DirtyArea {
7+
private _xBegin:number = null;
8+
private _yBegin:number = null;
9+
private _xEnd:number = null;
10+
private _yEnd:number = null;
11+
12+
public expand(x:number, y:number) {
13+
this._xBegin = this._xBegin === null ? x : Math.min(this._xBegin, x);
14+
this._xEnd = this._xEnd === null ? x : Math.max(this._xEnd, x);
15+
this._yBegin = this._yBegin === null ? y :Math.min(this._yBegin, y);
16+
this._yEnd = this._xEnd === null ? y :Math.max(this._yEnd, y);
17+
}
18+
19+
public asRect():Rectangle {
20+
if (this.isEmpty()) {
21+
return new Rectangle(0, 0, 0, 0);
22+
}
23+
return new Rectangle(this._xBegin,
24+
this._yBegin,
25+
this._xEnd - this._xBegin,
26+
this._yEnd - this._yBegin);
27+
}
28+
29+
public isEmpty():boolean {
30+
return this._xBegin === null || this._yBegin === null ||
31+
this._xEnd === null || this._yEnd === null;
32+
}
33+
34+
public reset():void {
35+
this._xBegin = null;
36+
this._xEnd = null;
37+
this._yBegin = null;
38+
this._yEnd = null;
39+
}
40+
}
41+
642
/**
743
* Bitmap AS3 Polyfill class
844
* Note: This is NOT equivalent to the Bitmap library class of the same name!
@@ -71,16 +107,21 @@ module Display {
71107
* @author Jim Chen
72108
*/
73109
export class BitmapData {
110+
private _id:string;
74111
private _rect:Rectangle;
112+
private _locked:boolean = false;
113+
private _dirtyArea:DirtyArea;
75114
private _transparent:boolean;
76115
private _fillColor:number;
77116
private _byteArray:Array<number>;
78117

79118
constructor(width:number,
80119
height:number,
81120
transparent:boolean = true,
82-
fillColor:number = 0xffffffff) {
121+
fillColor:number = 0xffffffff,
122+
id:string = Runtime.generateId()) {
83123

124+
this._id = id;
84125
this._rect = new Rectangle(0, 0, width, height);
85126
this._transparent = transparent;
86127
this._fillColor = fillColor;
@@ -94,6 +135,50 @@ module Display {
94135
}
95136
}
96137

138+
private _updateBox(changeRect:Rectangle = null):void {
139+
if (this._dirtyArea.isEmpty()) {
140+
// Don't update anything if nothing was changed
141+
return;
142+
}
143+
if (this._locked) {
144+
// Don't send updates if this is locked
145+
return;
146+
}
147+
var change:Rectangle = changeRect === null ? this._dirtyArea.asRect() :
148+
changeRect;
149+
150+
// Make sure we're not out-of-bounds
151+
if (!this._rect.containsRect(change)) {
152+
__trace('', 'err');
153+
throw new Error('Rectangle provided was not within image bounds.');
154+
}
155+
// Extract the values
156+
var region:Array<number> = [];
157+
for (var i = 0; i < change.height; i++) {
158+
for (var j = 0; j < change.width; j++) {
159+
region.push(this._byteArray[(change.y + i) * this._rect.width +
160+
change.x + j]);
161+
}
162+
}
163+
164+
__pchannel('Runtime:CallMethod', {
165+
'id': this.getId(),
166+
'name': 'updateBox',
167+
'value': {
168+
'box': change.serialize(),
169+
'values': values
170+
},
171+
});
172+
}
173+
174+
private _call(method:string, arguments:any):void {
175+
__pchannel('Runtime:CallMethod', {
176+
'id': this.getId(),
177+
'name': name,
178+
'value': arguments,
179+
});
180+
}
181+
97182
get height():number {
98183
return this._rect.height;
99184
}
@@ -162,6 +247,7 @@ module Display {
162247
color = color & 0xffffffff;
163248
}
164249
this._byteArray[y * this._rect.width + x] = color;
250+
this._dirtyArea.expand(x, y);
165251
}
166252

167253
public setPixels(rect:Rectangle, input:Array<number>):void {
@@ -177,10 +263,28 @@ module Display {
177263
for (var j = 0; j < rect.height; j++) {
178264
this._byteArray[(rect.y + j) * this.width + (rect.x + i)] =
179265
input[j * rect.width + i];
266+
this._dirtyArea.expand(i, j);
180267
}
181268
}
182269
}
183270

271+
public lock():void {
272+
this._locked = true;
273+
}
274+
275+
public unlock(changeRect:Rectangle = null):void {
276+
this._locked = false;
277+
if (changeRect == null) {
278+
this._updateBox();
279+
} else {
280+
this._updateBox(changeRect);
281+
}
282+
}
283+
284+
public getId():string {
285+
return this._id;
286+
}
287+
184288
public serialize():Object {
185289
return {
186290
'class':'BitmapData'

src/scripting/api/Player/Player.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,12 @@ module Player{
156156
}
157157

158158
export function keyTrigger(callback:Function, timeout:number):void{
159-
159+
if (!Runtime.hasObject('__player')) {
160+
__trace('Your environment does not support key triggers.', 'warn');
161+
return;
162+
}
163+
var player:Runtime.Listenable = <Runtime.Listenable>
164+
Runtime.getObject('__player');
160165
}
161166

162167
export function setMask(mask:any):void{

src/scripting/api/Runtime.d.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,19 @@ declare module Runtime {
5454
function privilegedCode(): void;
5555
}
5656
declare module Runtime {
57+
interface Listenable {
58+
addEventListener(
59+
event:string,
60+
listener:Function,
61+
useCapture:boolean,
62+
priority:number):void;
63+
removeEventListener(
64+
event:string,
65+
listener:Function,
66+
useCapture:boolean
67+
):void;
68+
hasEventListener(event:string):boolean;
69+
}
5770
interface RegisterableObject {
5871
getId():string;
5972
dispatchEvent(event:string, data?:any):void;
@@ -70,9 +83,9 @@ declare module Runtime {
7083
/**
7184
* Gets the object registered by id
7285
* @param objectId - objectid of object
73-
* @returns {any} - object or undefined if not found
86+
* @returns {RegisterableObject} - object or undefined if not found
7487
*/
75-
function getObject(objectId: string): any;
88+
function getObject(objectId: string): RegisterableObject;
7689
/**
7790
* Registers an object to allow two way communication between the API
7891
* and the host.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/**
2+
* Crypto-like wrappers that have no actual guarantees of safety.
3+
* These are just around to provide common interfaces since the sandbox may be
4+
* running in different environments.
5+
*
6+
* If safety is required, please use something else.
7+
*/
8+
module Runtime.NotCrypto {
9+
class Rc4 {
10+
private _s:number[] = [];
11+
constructor (key:number[]) {
12+
for (var i = 0; i < 256; i++) {
13+
this._s[i] = i;
14+
}
15+
var j = 0;
16+
for (var i = 0; i < 256; i++) {
17+
j = j + this._s[i] + key[i % key.length] % 256;
18+
var m = this._s[i];
19+
this._s[i] = this._s[j];
20+
this._s[j] = m;
21+
}
22+
}
23+
}
24+
25+
/**
26+
* (UNSAFE) Random value generator.
27+
* @param {number} bits - number of bits of randomness requested
28+
* @returns {number} a number within requested number of bits
29+
*/
30+
export function random(bits:number = 16):number {
31+
// Use Math.random for this if it exists
32+
if (Math && Math.random) {
33+
var value:number = 0;
34+
for (var i = 0; i < bits; i++) {
35+
value = (value << 1) + (Math.random() < 0.5 ? 0 : 1);
36+
}
37+
return value;
38+
} else {
39+
return Runtime.NotCrypto.fallbackRandom([Date.now() % 1024]);
40+
}
41+
}
42+
43+
/**
44+
* Generates a some randomness
45+
*/
46+
export function fallbackRandom(seed:number[], bits:number = 16):number {
47+
return ;
48+
}
49+
50+
/**
51+
* Transforms an integer to a hex value.
52+
* @param {number} value - value to transform
53+
* @param {number} length - how many hex digits to use. 0 means no prefixed 0s
54+
* @return {string} hex value
55+
*/
56+
export function toHex(value:number, length:number = 0):string {
57+
if (length <= 0) {
58+
return value.toString(16);
59+
}
60+
var base:string = value.toString(16);
61+
while (base.length < length) {
62+
base = '0' + base;
63+
}
64+
return base;
65+
}
66+
}

src/scripting/api/Runtime/Runtime.ts

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ module Runtime {
4747
private _listeners:{[name:string]: Array<Function>} = {};
4848

4949
constructor(name:string) {
50+
if (name.slice(0, 2) !== '__') {
51+
throw new Error('MetaObject names must start with two underscores.');
52+
}
5053
this._name = name;
5154
}
5255

@@ -103,6 +106,7 @@ module Runtime {
103106
}
104107

105108
/** Variables **/
109+
// objCount is uniformly increasing to make object names unique
106110
var objCount:number = 0;
107111
var _registeredObjects:ObjectRegistry = {
108112
'__self': new MetaObject('__self'),
@@ -149,9 +153,9 @@ module Runtime {
149153
/**
150154
* Gets the object registered by id
151155
* @param {string} objectId - objectid of object
152-
* @returns {any} - object or undefined if not found
156+
* @returns {RegisterableObject} - object or undefined if not found
153157
*/
154-
export function getObject(objectId:string):any{
158+
export function getObject(objectId:string):RegisterableObject{
155159
return _registeredObjects[objectId];
156160
}
157161

@@ -162,25 +166,26 @@ module Runtime {
162166
*/
163167
export function registerObject(object:RegisterableObject):void{
164168
if (!object.getId) {
165-
__trace("Attempted to register unnamed object", "warn");
169+
__trace('Cannot register object without getId method.','warn');
166170
return;
167171
}
168172
if (!Runtime.hasObject(object.getId())) {
169173
_registeredObjects[object.getId()] = object;
170-
__pchannel("Runtime:RegisterObject", {
171-
"id": object.getId(),
172-
"data": object.serialize()
174+
__pchannel('Runtime:RegisterObject', {
175+
'id': object.getId(),
176+
'data': object.serialize()
173177
});
174178
__schannel("object::(" + object.getId() + ")", (payload:any) => {
175-
if (payload.hasOwnProperty("type") &&
176-
payload.type === "event") {
179+
if (payload.hasOwnProperty('type') &&
180+
payload.type === 'event') {
177181
_dispatchEvent(object.getId(), payload.event, payload.data);
178182
}
179183
});
180184
objCount++;
181185
return;
182186
} else {
183-
__trace('Attempted to re-register object or id collision', 'warn');
187+
__trace('Attempted to re-register object or id collision @ ' +
188+
object.getId(), 'warn');
184189
return;
185190
}
186191
}
@@ -194,33 +199,39 @@ module Runtime {
194199
*/
195200
export function deregisterObject(objectId:string):void {
196201
if (Runtime.hasObject(objectId)) {
197-
if (objectId.substr(0,2) === "__") {
198-
__trace("Runtime.deregisterObject cannot de-register a MetaObject","warn");
202+
if (objectId.substr(0,2) === '__') {
203+
__trace('Runtime.deregisterObject cannot de-register a MetaObject',
204+
'warn');
199205
return;
200206
}
201-
__pchannel("Runtime:DeregisterObject", {
202-
"id": objectId
207+
__pchannel('Runtime:DeregisterObject', {
208+
'id': objectId
203209
});
204210
if (typeof _registeredObjects[objectId].unload === "function") {
205211
// Gracefully unload first
206212
_registeredObjects[objectId].unload();
207213
}
208214
_registeredObjects[objectId] = null;
209215
delete _registeredObjects[objectId];
210-
objCount--;
211216
}
212217
}
213218

219+
function _getId(type:string = 'obj', container:string = 'rt'):string {
220+
var randomSeed:number = Math.random()
221+
var randomSegment:string = '';
222+
return;
223+
}
224+
214225
/**
215226
* Generates an objectid that isn't registered
216227
* @param {string} type - object type
217228
* @returns {string} - objectid that has not been registered
218229
*/
219230
export function generateId(type:string = "obj"):string {
220-
var id:string = type + ":" + (new Date()).getTime() + "|" +
221-
Math.round(Math.random() * 4096) + ":" + objCount;
231+
var id:string = [type, ':', Date.now(), '|',
232+
Math.round(Math.random() * 4096), ':', objCount].join();
222233
while (Runtime.hasObject(id)) {
223-
id = type + ":" + (new Date()).getTime() + "|" +
234+
id = type + ":" + Date.now() + "|" +
224235
Math.round(Math.random() * 4096) + ":" + objCount;
225236
}
226237
return id;
@@ -254,7 +265,7 @@ module Runtime {
254265
}
255266

256267
/**
257-
* Invoke termination of script
268+
* Invoke termination of script from outside the sandbox
258269
*/
259270
export function crash():void {
260271
__trace("Runtime.crash() : Manual crash", "fatal");

0 commit comments

Comments
 (0)