browser/extensions/shumway/content/shumway.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /*
michael@0 2 * Copyright 2013 Mozilla Foundation
michael@0 3 *
michael@0 4 * Licensed under the Apache License, Version 2.0 (the "License");
michael@0 5 * you may not use this file except in compliance with the License.
michael@0 6 * You may obtain a copy of the License at
michael@0 7 *
michael@0 8 * http://www.apache.org/licenses/LICENSE-2.0
michael@0 9 *
michael@0 10 * Unless required by applicable law or agreed to in writing, software
michael@0 11 * distributed under the License is distributed on an "AS IS" BASIS,
michael@0 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
michael@0 13 * See the License for the specific language governing permissions and
michael@0 14 * limitations under the License.
michael@0 15 */
michael@0 16
michael@0 17 // This file is automatically generated
michael@0 18
michael@0 19 (function (global) {
michael@0 20 if (global.DataView)
michael@0 21 return;
michael@0 22 if (!global.ArrayBuffer)
michael@0 23 fail('ArrayBuffer not supported');
michael@0 24 if (!Object.defineProperties)
michael@0 25 fail('This module requires ECMAScript 5');
michael@0 26 var nativele = new Int8Array(new Int32Array([
michael@0 27 1
michael@0 28 ]).buffer)[0] === 1;
michael@0 29 var temp = new Uint8Array(8);
michael@0 30 global.DataView = function DataView(buffer, offset, length) {
michael@0 31 if (!(buffer instanceof ArrayBuffer))
michael@0 32 fail('Bad ArrayBuffer');
michael@0 33 offset = offset || 0;
michael@0 34 length = length || buffer.byteLength - offset;
michael@0 35 if (offset < 0 || length < 0 || offset + length > buffer.byteLength)
michael@0 36 fail('Illegal offset and/or length');
michael@0 37 Object.defineProperties(this, {
michael@0 38 buffer: {
michael@0 39 value: buffer,
michael@0 40 enumerable: false,
michael@0 41 writable: false,
michael@0 42 configurable: false
michael@0 43 },
michael@0 44 byteOffset: {
michael@0 45 value: offset,
michael@0 46 enumerable: false,
michael@0 47 writable: false,
michael@0 48 configurable: false
michael@0 49 },
michael@0 50 byteLength: {
michael@0 51 value: length,
michael@0 52 enumerable: false,
michael@0 53 writable: false,
michael@0 54 configurable: false
michael@0 55 },
michael@0 56 _bytes: {
michael@0 57 value: new Uint8Array(buffer, offset, length),
michael@0 58 enumerable: false,
michael@0 59 writable: false,
michael@0 60 configurable: false
michael@0 61 }
michael@0 62 });
michael@0 63 };
michael@0 64 global.DataView.prototype = {
michael@0 65 constructor: DataView,
michael@0 66 getInt8: function getInt8(offset) {
michael@0 67 return get(this, Int8Array, 1, offset);
michael@0 68 },
michael@0 69 getUint8: function getUint8(offset) {
michael@0 70 return get(this, Uint8Array, 1, offset);
michael@0 71 },
michael@0 72 getInt16: function getInt16(offset, le) {
michael@0 73 return get(this, Int16Array, 2, offset, le);
michael@0 74 },
michael@0 75 getUint16: function getUint16(offset, le) {
michael@0 76 return get(this, Uint16Array, 2, offset, le);
michael@0 77 },
michael@0 78 getInt32: function getInt32(offset, le) {
michael@0 79 return get(this, Int32Array, 4, offset, le);
michael@0 80 },
michael@0 81 getUint32: function getUint32(offset, le) {
michael@0 82 return get(this, Uint32Array, 4, offset, le);
michael@0 83 },
michael@0 84 getFloat32: function getFloat32(offset, le) {
michael@0 85 return get(this, Float32Array, 4, offset, le);
michael@0 86 },
michael@0 87 getFloat64: function getFloat32(offset, le) {
michael@0 88 return get(this, Float64Array, 8, offset, le);
michael@0 89 },
michael@0 90 setInt8: function setInt8(offset, value) {
michael@0 91 set(this, Int8Array, 1, offset, value);
michael@0 92 },
michael@0 93 setUint8: function setUint8(offset, value) {
michael@0 94 set(this, Uint8Array, 1, offset, value);
michael@0 95 },
michael@0 96 setInt16: function setInt16(offset, value, le) {
michael@0 97 set(this, Int16Array, 2, offset, value, le);
michael@0 98 },
michael@0 99 setUint16: function setUint16(offset, value, le) {
michael@0 100 set(this, Uint16Array, 2, offset, value, le);
michael@0 101 },
michael@0 102 setInt32: function setInt32(offset, value, le) {
michael@0 103 set(this, Int32Array, 4, offset, value, le);
michael@0 104 },
michael@0 105 setUint32: function setUint32(offset, value, le) {
michael@0 106 set(this, Uint32Array, 4, offset, value, le);
michael@0 107 },
michael@0 108 setFloat32: function setFloat32(offset, value, le) {
michael@0 109 set(this, Float32Array, 4, offset, value, le);
michael@0 110 },
michael@0 111 setFloat64: function setFloat64(offset, value, le) {
michael@0 112 set(this, Float64Array, 8, offset, value, le);
michael@0 113 }
michael@0 114 };
michael@0 115 function get(view, type, size, offset, le) {
michael@0 116 if (offset === undefined)
michael@0 117 fail('Missing required offset argument');
michael@0 118 if (offset < 0 || offset + size > view.byteLength)
michael@0 119 fail('Invalid index: ' + offset);
michael@0 120 if (size === 1 || !(!le) === nativele) {
michael@0 121 if ((view.byteOffset + offset) % size === 0)
michael@0 122 return new type(view.buffer, view.byteOffset + offset, 1)[0];
michael@0 123 else {
michael@0 124 for (var i = 0; i < size; i++)
michael@0 125 temp[i] = view._bytes[offset + i];
michael@0 126 return new type(temp.buffer)[0];
michael@0 127 }
michael@0 128 } else {
michael@0 129 for (var i = 0; i < size; i++)
michael@0 130 temp[size - i - 1] = view._bytes[offset + i];
michael@0 131 return new type(temp.buffer)[0];
michael@0 132 }
michael@0 133 }
michael@0 134 function set(view, type, size, offset, value, le) {
michael@0 135 if (offset === undefined)
michael@0 136 fail('Missing required offset argument');
michael@0 137 if (value === undefined)
michael@0 138 fail('Missing required value argument');
michael@0 139 if (offset < 0 || offset + size > view.byteLength)
michael@0 140 fail('Invalid index: ' + offset);
michael@0 141 if (size === 1 || !(!le) === nativele) {
michael@0 142 if ((view.byteOffset + offset) % size === 0) {
michael@0 143 new type(view.buffer, view.byteOffset + offset, 1)[0] = value;
michael@0 144 } else {
michael@0 145 new type(temp.buffer)[0] = value;
michael@0 146 for (var i = 0; i < size; i++)
michael@0 147 view._bytes[i + offset] = temp[i];
michael@0 148 }
michael@0 149 } else {
michael@0 150 new type(temp.buffer)[0] = value;
michael@0 151 for (var i = 0; i < size; i++)
michael@0 152 view._bytes[offset + i] = temp[size - 1 - i];
michael@0 153 }
michael@0 154 }
michael@0 155 function fail(msg) {
michael@0 156 throw new Error(msg);
michael@0 157 }
michael@0 158 }(this));
michael@0 159 ;
michael@0 160 var ByteArray = ByteArray || function (undefined) {
michael@0 161 ByteArrayClass.INITIAL_SIZE = 128;
michael@0 162 ByteArrayClass.DEFAULT_OBJECT_ENCODING = 3;
michael@0 163 function ByteArrayClass(bytes) {
michael@0 164 if (bytes instanceof ByteArray) {
michael@0 165 return bytes;
michael@0 166 }
michael@0 167 var initData = bytes || this.symbol && this.symbol.data;
michael@0 168 if (initData) {
michael@0 169 this.a = new ArrayBuffer(initData.length);
michael@0 170 this.length = initData.length;
michael@0 171 new Uint8Array(this.a).set(initData);
michael@0 172 } else {
michael@0 173 this.a = new ArrayBuffer(ByteArrayClass.INITIAL_SIZE);
michael@0 174 this.length = 0;
michael@0 175 }
michael@0 176 this.position = 0;
michael@0 177 this.cacheViews();
michael@0 178 this.nativele = new Int8Array(new Int32Array([]).buffer)[0] === 1;
michael@0 179 this.le = this.nativele;
michael@0 180 this.objectEncoding = ByteArrayClass.DEFAULT_OBJECT_ENCODING;
michael@0 181 this.bitBuffer = 0;
michael@0 182 this.bitLength = 0;
michael@0 183 }
michael@0 184 ;
michael@0 185 function throwEOFError() {
michael@0 186 runtime.throwErrorFromVM('flash.errors.EOFError', 'End of file was encountered.');
michael@0 187 }
michael@0 188 function throwRangeError() {
michael@0 189 var error = Errors.ParamRangeError;
michael@0 190 runtime.throwErrorFromVM('RangeError', getErrorMessage(error.code), error.code);
michael@0 191 }
michael@0 192 function throwCompressedDataError() {
michael@0 193 var error = Errors.CompressedDataError;
michael@0 194 runtime.throwErrorFromVM('CompressedDataError', getErrorMessage(error.code), error.code);
michael@0 195 }
michael@0 196 function checkRange(x, min, max) {
michael@0 197 if (x !== clamp(x, min, max)) {
michael@0 198 throwRangeError();
michael@0 199 }
michael@0 200 }
michael@0 201 function get(b, m, size) {
michael@0 202 if (b.position + size > b.length) {
michael@0 203 throwEOFError();
michael@0 204 }
michael@0 205 var v = b.view[m](b.position, b.le);
michael@0 206 b.position += size;
michael@0 207 return v;
michael@0 208 }
michael@0 209 function set(b, m, size, v) {
michael@0 210 var len = b.position + size;
michael@0 211 b.ensureCapacity(len);
michael@0 212 b.view[m](b.position, v, b.le);
michael@0 213 b.position = len;
michael@0 214 if (len > b.length) {
michael@0 215 b.length = len;
michael@0 216 }
michael@0 217 }
michael@0 218 var BAp = ByteArrayClass.prototype;
michael@0 219 BAp.cacheViews = function cacheViews() {
michael@0 220 var a = this.a;
michael@0 221 this.int8v = new Int8Array(a);
michael@0 222 this.uint8v = new Uint8Array(a);
michael@0 223 this.view = new DataView(a);
michael@0 224 };
michael@0 225 BAp.getBytes = function getBytes() {
michael@0 226 return new Uint8Array(this.a, 0, this.length);
michael@0 227 };
michael@0 228 BAp.ensureCapacity = function ensureCapacity(size) {
michael@0 229 var origa = this.a;
michael@0 230 if (origa.byteLength < size) {
michael@0 231 var newSize = origa.byteLength;
michael@0 232 while (newSize < size) {
michael@0 233 newSize *= 2;
michael@0 234 }
michael@0 235 var copya = new ArrayBuffer(newSize);
michael@0 236 var origv = this.int8v;
michael@0 237 this.a = copya;
michael@0 238 this.cacheViews();
michael@0 239 this.int8v.set(origv);
michael@0 240 }
michael@0 241 };
michael@0 242 BAp.clear = function clear() {
michael@0 243 this.length = 0;
michael@0 244 this.position = 0;
michael@0 245 };
michael@0 246 BAp.readBoolean = function readBoolean() {
michael@0 247 if (this.position + 1 > this.length) {
michael@0 248 throwEOFError();
michael@0 249 }
michael@0 250 return this.int8v[this.position++] !== 0;
michael@0 251 };
michael@0 252 BAp.readByte = function readByte() {
michael@0 253 if (this.position + 1 > this.length) {
michael@0 254 throwEOFError();
michael@0 255 }
michael@0 256 return this.int8v[this.position++];
michael@0 257 };
michael@0 258 BAp.readUnsignedByte = function readUnsignedByte() {
michael@0 259 if (this.position + 1 > this.length) {
michael@0 260 throwEOFError();
michael@0 261 }
michael@0 262 return this.uint8v[this.position++];
michael@0 263 };
michael@0 264 BAp.readBytes = function readBytes(bytes, offset, length) {
michael@0 265 var pos = this.position;
michael@0 266 if (!offset) {
michael@0 267 offset = 0;
michael@0 268 }
michael@0 269 if (!length) {
michael@0 270 length = this.length - pos;
michael@0 271 }
michael@0 272 if (pos + length > this.length) {
michael@0 273 throwEOFError();
michael@0 274 }
michael@0 275 if (bytes.length < offset + length) {
michael@0 276 bytes.ensureCapacity(offset + length);
michael@0 277 bytes.length = offset + length;
michael@0 278 }
michael@0 279 bytes.int8v.set(new Int8Array(this.a, pos, length), offset);
michael@0 280 this.position += length;
michael@0 281 };
michael@0 282 BAp.writeBoolean = function writeBoolean(v) {
michael@0 283 var len = this.position + 1;
michael@0 284 this.ensureCapacity(len);
michael@0 285 this.int8v[this.position++] = v ? 1 : 0;
michael@0 286 if (len > this.length) {
michael@0 287 this.length = len;
michael@0 288 }
michael@0 289 };
michael@0 290 BAp.writeByte = function writeByte(v) {
michael@0 291 var len = this.position + 1;
michael@0 292 this.ensureCapacity(len);
michael@0 293 this.int8v[this.position++] = v;
michael@0 294 if (len > this.length) {
michael@0 295 this.length = len;
michael@0 296 }
michael@0 297 };
michael@0 298 BAp.writeUnsignedByte = function writeUnsignedByte(v) {
michael@0 299 var len = this.position + 1;
michael@0 300 this.ensureCapacity(len);
michael@0 301 this.uint8v[this.position++] = v;
michael@0 302 if (len > this.length) {
michael@0 303 this.length = len;
michael@0 304 }
michael@0 305 };
michael@0 306 BAp.writeRawBytes = function writeRawBytes(bytes) {
michael@0 307 var len = this.position + bytes.length;
michael@0 308 this.ensureCapacity(len);
michael@0 309 this.int8v.set(bytes, this.position);
michael@0 310 this.position = len;
michael@0 311 if (len > this.length) {
michael@0 312 this.length = len;
michael@0 313 }
michael@0 314 };
michael@0 315 BAp.readRawBytes = function readRawBytes() {
michael@0 316 return new Int8Array(this.a, 0, this.length);
michael@0 317 };
michael@0 318 BAp.writeBytes = function writeBytes(bytes, offset, length) {
michael@0 319 if (arguments.length < 2) {
michael@0 320 offset = 0;
michael@0 321 }
michael@0 322 if (arguments.length < 3) {
michael@0 323 length = 0;
michael@0 324 }
michael@0 325 checkRange(offset, 0, bytes.length);
michael@0 326 checkRange(offset + length, 0, bytes.length);
michael@0 327 if (length === 0) {
michael@0 328 length = bytes.length - offset;
michael@0 329 }
michael@0 330 this.writeRawBytes(new Int8Array(bytes.a, offset, length));
michael@0 331 };
michael@0 332 BAp.readDouble = function readDouble() {
michael@0 333 return get(this, 'getFloat64', 8);
michael@0 334 };
michael@0 335 BAp.readFloat = function readFloat() {
michael@0 336 return get(this, 'getFloat32', 4);
michael@0 337 };
michael@0 338 BAp.readInt = function readInt() {
michael@0 339 return get(this, 'getInt32', 4);
michael@0 340 };
michael@0 341 BAp.readShort = function readShort() {
michael@0 342 return get(this, 'getInt16', 2);
michael@0 343 };
michael@0 344 BAp.readUnsignedInt = function readUnsignedInt() {
michael@0 345 return get(this, 'getUint32', 4);
michael@0 346 };
michael@0 347 BAp.readUnsignedShort = function readUnsignedShort() {
michael@0 348 return get(this, 'getUint16', 2);
michael@0 349 };
michael@0 350 BAp.writeDouble = function writeDouble(v) {
michael@0 351 set(this, 'setFloat64', 8, v);
michael@0 352 };
michael@0 353 BAp.writeFloat = function writeFloat(v) {
michael@0 354 set(this, 'setFloat32', 4, v);
michael@0 355 };
michael@0 356 BAp.writeInt = function writeInt(v) {
michael@0 357 set(this, 'setInt32', 4, v);
michael@0 358 };
michael@0 359 BAp.writeShort = function writeShort(v) {
michael@0 360 set(this, 'setInt16', 2, v);
michael@0 361 };
michael@0 362 BAp.writeUnsignedInt = function writeUnsignedInt(v) {
michael@0 363 set(this, 'setUint32', 4, v);
michael@0 364 };
michael@0 365 BAp.writeUnsignedShort = function writeUnsignedShort(v) {
michael@0 366 set(this, 'setUint16', 2, v);
michael@0 367 };
michael@0 368 var codeLengthOrder = [
michael@0 369 16,
michael@0 370 17,
michael@0 371 18,
michael@0 372 0,
michael@0 373 8,
michael@0 374 7,
michael@0 375 9,
michael@0 376 6,
michael@0 377 10,
michael@0 378 5,
michael@0 379 11,
michael@0 380 4,
michael@0 381 12,
michael@0 382 3,
michael@0 383 13,
michael@0 384 2,
michael@0 385 14,
michael@0 386 1,
michael@0 387 15
michael@0 388 ];
michael@0 389 var distanceCodes = [];
michael@0 390 var distanceExtraBits = [];
michael@0 391 for (var i = 0, j = 0, code = 1; i < 30; ++i) {
michael@0 392 distanceCodes[i] = code;
michael@0 393 code += 1 << (distanceExtraBits[i] = ~(~((j += i > 2 ? 1 : 0) / 2)));
michael@0 394 }
michael@0 395 var bitLengths = [];
michael@0 396 for (var i = 0; i < 32; ++i) {
michael@0 397 bitLengths[i] = 5;
michael@0 398 }
michael@0 399 var fixedDistanceTable = makeHuffmanTable(bitLengths);
michael@0 400 var lengthCodes = [];
michael@0 401 var lengthExtraBits = [];
michael@0 402 for (var i = 0, j = 0, code = 3; i < 29; ++i) {
michael@0 403 lengthCodes[i] = code - (i == 28 ? 1 : 0);
michael@0 404 code += 1 << (lengthExtraBits[i] = ~(~((j += i > 4 ? 1 : 0) / 4 % 6)));
michael@0 405 }
michael@0 406 for (var i = 0; i < 288; ++i) {
michael@0 407 bitLengths[i] = i < 144 || i > 279 ? 8 : i < 256 ? 9 : 7;
michael@0 408 }
michael@0 409 var fixedLiteralTable = makeHuffmanTable(bitLengths);
michael@0 410 function makeHuffmanTable(bitLengths) {
michael@0 411 var maxBits = Math.max.apply(null, bitLengths);
michael@0 412 var numLengths = bitLengths.length;
michael@0 413 var size = 1 << maxBits;
michael@0 414 var codes = new Uint32Array(size);
michael@0 415 for (var code = 0, len = 1, skip = 2; len <= maxBits; code <<= 1, ++len, skip <<= 1) {
michael@0 416 for (var val = 0; val < numLengths; ++val) {
michael@0 417 if (bitLengths[val] === len) {
michael@0 418 var lsb = 0;
michael@0 419 for (var i = 0; i < len; ++i) {
michael@0 420 lsb = lsb * 2 + (code >> i & 1);
michael@0 421 }
michael@0 422 for (var i = lsb; i < size; i += skip) {
michael@0 423 codes[i] = len << 16 | val;
michael@0 424 }
michael@0 425 ++code;
michael@0 426 }
michael@0 427 }
michael@0 428 }
michael@0 429 return {
michael@0 430 codes: codes,
michael@0 431 maxBits: maxBits
michael@0 432 };
michael@0 433 }
michael@0 434 function inflateBlock(input, output) {
michael@0 435 var header = readBits(input, 3);
michael@0 436 switch (header >> 1) {
michael@0 437 case 0:
michael@0 438 input.bitBuffer = input.bitLength = 0;
michael@0 439 var len = input.readUnsignedShort();
michael@0 440 var nlen = input.readUnsignedShort();
michael@0 441 if ((~nlen & 65535) !== len) {
michael@0 442 throwCompressedDataError();
michael@0 443 }
michael@0 444 output.writeBytes(input, input.position, len);
michael@0 445 input.position += len;
michael@0 446 break;
michael@0 447 case 1:
michael@0 448 inflate(input, output, fixedLiteralTable, fixedDistanceTable);
michael@0 449 break;
michael@0 450 case 2:
michael@0 451 var bitLengths = [];
michael@0 452 var numLiteralCodes = readBits(input, 5) + 257;
michael@0 453 var numDistanceCodes = readBits(input, 5) + 1;
michael@0 454 var numCodes = numLiteralCodes + numDistanceCodes;
michael@0 455 var numLengthCodes = readBits(input, 4) + 4;
michael@0 456 for (var i = 0; i < 19; ++i) {
michael@0 457 bitLengths[codeLengthOrder[i]] = i < numLengthCodes ? readBits(input, 3) : 0;
michael@0 458 }
michael@0 459 var codeLengthTable = makeHuffmanTable(bitLengths);
michael@0 460 bitLengths = [];
michael@0 461 var i = 0;
michael@0 462 var prev = 0;
michael@0 463 while (i < numCodes) {
michael@0 464 var j = 1;
michael@0 465 var sym = readCode(input, codeLengthTable);
michael@0 466 switch (sym) {
michael@0 467 case 16:
michael@0 468 j = readBits(input, 2) + 3;
michael@0 469 sym = prev;
michael@0 470 break;
michael@0 471 case 17:
michael@0 472 j = readBits(input, 3) + 3;
michael@0 473 sym = 0;
michael@0 474 break;
michael@0 475 case 18:
michael@0 476 j = readBits(input, 7) + 11;
michael@0 477 sym = 0;
michael@0 478 break;
michael@0 479 default:
michael@0 480 prev = sym;
michael@0 481 }
michael@0 482 while (j--) {
michael@0 483 bitLengths[i++] = sym;
michael@0 484 }
michael@0 485 }
michael@0 486 var distanceTable = makeHuffmanTable(bitLengths.splice(numLiteralCodes, numDistanceCodes));
michael@0 487 var literalTable = makeHuffmanTable(bitLengths);
michael@0 488 inflate(input, output, literalTable, distanceTable);
michael@0 489 break;
michael@0 490 default:
michael@0 491 fail('unknown block type', 'inflate');
michael@0 492 }
michael@0 493 }
michael@0 494 function readBits(input, size) {
michael@0 495 var buffer = input.bitBuffer;
michael@0 496 var bufflen = input.bitLength;
michael@0 497 while (size > bufflen) {
michael@0 498 buffer |= input.readUnsignedByte() << bufflen;
michael@0 499 bufflen += 8;
michael@0 500 }
michael@0 501 input.bitBuffer = buffer >>> size;
michael@0 502 input.bitLength = bufflen - size;
michael@0 503 return buffer & (1 << size) - 1;
michael@0 504 }
michael@0 505 function inflate(input, output, literalTable, distanceTable) {
michael@0 506 var sym;
michael@0 507 while ((sym = readCode(input, literalTable)) !== 256) {
michael@0 508 if (sym < 256) {
michael@0 509 output.writeUnsignedByte(sym);
michael@0 510 } else {
michael@0 511 sym -= 257;
michael@0 512 var len = lengthCodes[sym] + readBits(input, lengthExtraBits[sym]);
michael@0 513 sym = readCode(input, distanceTable);
michael@0 514 var distance = distanceCodes[sym] + readBits(input, distanceExtraBits[sym]);
michael@0 515 output.writeBytes(output, output.position - distance, len);
michael@0 516 }
michael@0 517 }
michael@0 518 }
michael@0 519 function readCode(input, codeTable) {
michael@0 520 var buffer = input.bitBuffer;
michael@0 521 var bitlen = input.bitLength;
michael@0 522 var maxBits = codeTable.maxBits;
michael@0 523 while (maxBits > bitlen) {
michael@0 524 buffer |= input.readUnsignedByte() << bitlen;
michael@0 525 bitlen += 8;
michael@0 526 }
michael@0 527 var code = codeTable.codes[buffer & (1 << maxBits) - 1];
michael@0 528 var len = code >> 16;
michael@0 529 if (!len) {
michael@0 530 throwCompressedDataError();
michael@0 531 }
michael@0 532 input.bitBuffer = buffer >>> len;
michael@0 533 input.bitLength = bitlen - len;
michael@0 534 return code & 65535;
michael@0 535 }
michael@0 536 function adler32(data, start, end) {
michael@0 537 var a = 1;
michael@0 538 var b = 0;
michael@0 539 for (var i = start; i < end; ++i) {
michael@0 540 a = (a + (data[i] & 255)) % 65521;
michael@0 541 b = (b + a) % 65521;
michael@0 542 }
michael@0 543 return b << 16 | a;
michael@0 544 }
michael@0 545 BAp.compress = function (algorithm) {
michael@0 546 this.position = 0;
michael@0 547 var output = new ByteArray();
michael@0 548 switch (algorithm) {
michael@0 549 case 'zlib':
michael@0 550 output.writeUnsignedByte(120);
michael@0 551 output.writeUnsignedByte(156);
michael@0 552 case 'deflate':
michael@0 553 output.le = true;
michael@0 554 var len = this.length;
michael@0 555 output.ensureCapacity(len + Math.ceil(len / 65535) * 5 + 4);
michael@0 556 while (len > 65535) {
michael@0 557 output.writeUnsignedByte(0);
michael@0 558 output.writeUnsignedShort(65535);
michael@0 559 output.writeUnsignedShort(0);
michael@0 560 output.writeBytes(this, this.position, 65535);
michael@0 561 this.position += 65535;
michael@0 562 len -= 65535;
michael@0 563 }
michael@0 564 output.writeUnsignedByte(0);
michael@0 565 output.writeUnsignedShort(len);
michael@0 566 output.writeUnsignedShort(~len & 65535);
michael@0 567 output.writeBytes(this, this.position, len);
michael@0 568 if (algorithm === 'zlib') {
michael@0 569 output.writeUnsignedInt(adler32(this.uint8v, 0, this.length));
michael@0 570 }
michael@0 571 break;
michael@0 572 default:
michael@0 573 return;
michael@0 574 }
michael@0 575 this.ensureCapacity(output.uint8v.length);
michael@0 576 this.uint8v.set(output.uint8v);
michael@0 577 this.length = output.length;
michael@0 578 this.position = 0;
michael@0 579 };
michael@0 580 BAp.uncompress = function (algorithm) {
michael@0 581 var output = new ByteArray();
michael@0 582 switch (algorithm) {
michael@0 583 case 'zlib':
michael@0 584 var header = this.readUnsignedShort();
michael@0 585 if ((header & 3840) !== 2048 || header % 31 !== 0 || header & 32) {
michael@0 586 throwCompressedDataError();
michael@0 587 }
michael@0 588 case 'deflate':
michael@0 589 var le = this.le;
michael@0 590 this.le = true;
michael@0 591 while (this.position < this.length - 6) {
michael@0 592 inflateBlock(this, output);
michael@0 593 }
michael@0 594 this.le = le;
michael@0 595 break;
michael@0 596 default:
michael@0 597 return;
michael@0 598 }
michael@0 599 this.ensureCapacity(output.uint8v.length);
michael@0 600 this.uint8v.set(output.uint8v);
michael@0 601 this.length = output.length;
michael@0 602 this.position = 0;
michael@0 603 };
michael@0 604 return ByteArrayClass;
michael@0 605 }();
michael@0 606 var Shumway;
michael@0 607 (function (Shumway) {
michael@0 608 (function (Options) {
michael@0 609 var Argument = function () {
michael@0 610 function Argument(shortName, longName, type, options) {
michael@0 611 this.shortName = shortName;
michael@0 612 this.longName = longName;
michael@0 613 this.type = type;
michael@0 614 options = options || {};
michael@0 615 this.positional = options.positional;
michael@0 616 this.parseFn = options.parse;
michael@0 617 this.value = options.defaultValue;
michael@0 618 }
michael@0 619 Argument.prototype.parse = function (value) {
michael@0 620 if (this.type === 'boolean') {
michael@0 621 true;
michael@0 622 this.value = value;
michael@0 623 } else if (this.type === 'number') {
michael@0 624 true;
michael@0 625 this.value = parseInt(value, 10);
michael@0 626 } else {
michael@0 627 this.value = value;
michael@0 628 }
michael@0 629 if (this.parseFn) {
michael@0 630 this.parseFn(this.value);
michael@0 631 }
michael@0 632 };
michael@0 633 return Argument;
michael@0 634 }();
michael@0 635 Options.Argument = Argument;
michael@0 636 var ArgumentParser = function () {
michael@0 637 function ArgumentParser() {
michael@0 638 this.args = [];
michael@0 639 }
michael@0 640 ArgumentParser.prototype.addArgument = function (shortName, longName, type, options) {
michael@0 641 var argument = new Argument(shortName, longName, type, options);
michael@0 642 this.args.push(argument);
michael@0 643 return argument;
michael@0 644 };
michael@0 645 ArgumentParser.prototype.addBoundOption = function (option) {
michael@0 646 var options = {
michael@0 647 parse: function (x) {
michael@0 648 option.value = x;
michael@0 649 }
michael@0 650 };
michael@0 651 this.args.push(new Argument(option.shortName, option.longName, option.type, options));
michael@0 652 };
michael@0 653 ArgumentParser.prototype.addBoundOptionSet = function (optionSet) {
michael@0 654 var self = this;
michael@0 655 optionSet.options.forEach(function (x) {
michael@0 656 if (x instanceof OptionSet) {
michael@0 657 self.addBoundOptionSet(x);
michael@0 658 } else {
michael@0 659 true;
michael@0 660 self.addBoundOption(x);
michael@0 661 }
michael@0 662 });
michael@0 663 };
michael@0 664 ArgumentParser.prototype.getUsage = function () {
michael@0 665 var str = '';
michael@0 666 this.args.forEach(function (x) {
michael@0 667 if (!x.positional) {
michael@0 668 str += '[-' + x.shortName + '|--' + x.longName + (x.type === 'boolean' ? '' : ' ' + x.type[0].toUpperCase()) + ']';
michael@0 669 } else {
michael@0 670 str += x.longName;
michael@0 671 }
michael@0 672 str += ' ';
michael@0 673 });
michael@0 674 return str;
michael@0 675 };
michael@0 676 ArgumentParser.prototype.parse = function (args) {
michael@0 677 var nonPositionalArgumentMap = {};
michael@0 678 var positionalArgumentList = [];
michael@0 679 this.args.forEach(function (x) {
michael@0 680 if (x.positional) {
michael@0 681 positionalArgumentList.push(x);
michael@0 682 } else {
michael@0 683 nonPositionalArgumentMap['-' + x.shortName] = x;
michael@0 684 nonPositionalArgumentMap['--' + x.longName] = x;
michael@0 685 }
michael@0 686 });
michael@0 687 var leftoverArguments = [];
michael@0 688 while (args.length) {
michael@0 689 var argString = args.shift();
michael@0 690 var argument = null, value = argString;
michael@0 691 if (argString == '--') {
michael@0 692 leftoverArguments = leftoverArguments.concat(args);
michael@0 693 break;
michael@0 694 } else if (argString.slice(0, 1) == '-' || argString.slice(0, 2) == '--') {
michael@0 695 argument = nonPositionalArgumentMap[argString];
michael@0 696 true;
michael@0 697 if (!argument) {
michael@0 698 continue;
michael@0 699 }
michael@0 700 if (argument.type !== 'boolean') {
michael@0 701 value = args.shift();
michael@0 702 true;
michael@0 703 } else {
michael@0 704 value = true;
michael@0 705 }
michael@0 706 } else if (positionalArgumentList.length) {
michael@0 707 argument = positionalArgumentList.shift();
michael@0 708 } else {
michael@0 709 leftoverArguments.push(value);
michael@0 710 }
michael@0 711 if (argument) {
michael@0 712 argument.parse(value);
michael@0 713 }
michael@0 714 }
michael@0 715 true;
michael@0 716 return leftoverArguments;
michael@0 717 };
michael@0 718 return ArgumentParser;
michael@0 719 }();
michael@0 720 Options.ArgumentParser = ArgumentParser;
michael@0 721 var OptionSet = function () {
michael@0 722 function OptionSet(name) {
michael@0 723 this.name = name;
michael@0 724 this.options = [];
michael@0 725 }
michael@0 726 OptionSet.prototype.register = function (option) {
michael@0 727 this.options.push(option);
michael@0 728 return option;
michael@0 729 };
michael@0 730 OptionSet.prototype.trace = function (writer) {
michael@0 731 writer.enter(this.name + ' {');
michael@0 732 this.options.forEach(function (option) {
michael@0 733 option.trace(writer);
michael@0 734 });
michael@0 735 writer.leave('}');
michael@0 736 };
michael@0 737 return OptionSet;
michael@0 738 }();
michael@0 739 Options.OptionSet = OptionSet;
michael@0 740 var Option = function () {
michael@0 741 function Option(shortName, longName, type, defaultValue, description) {
michael@0 742 this.longName = longName;
michael@0 743 this.shortName = shortName;
michael@0 744 this.type = type;
michael@0 745 this.defaultValue = defaultValue;
michael@0 746 this.value = defaultValue;
michael@0 747 this.description = description;
michael@0 748 }
michael@0 749 Option.prototype.parse = function (value) {
michael@0 750 this.value = value;
michael@0 751 };
michael@0 752 Option.prototype.trace = function (writer) {
michael@0 753 writer.writeLn(('-' + this.shortName + '|--' + this.longName).padRight(' ', 30) + ' = ' + this.type + ' ' + this.value + ' [' + this.defaultValue + ']' + ' (' + this.description + ')');
michael@0 754 };
michael@0 755 return Option;
michael@0 756 }();
michael@0 757 Options.Option = Option;
michael@0 758 }(Shumway.Options || (Shumway.Options = {})));
michael@0 759 var Options = Shumway.Options;
michael@0 760 }(Shumway || (Shumway = {})));
michael@0 761 if (typeof exports !== 'undefined') {
michael@0 762 exports['Shumway'] = Shumway;
michael@0 763 }
michael@0 764 var ArgumentParser = Shumway.Options.ArgumentParser;
michael@0 765 var Option = Shumway.Options.Option;
michael@0 766 var OptionSet = Shumway.Options.OptionSet;
michael@0 767 var Option = Shumway.Options.Option;
michael@0 768 var OptionSet = Shumway.Options.OptionSet;
michael@0 769 var coreOptions = new OptionSet('Core Options');
michael@0 770 var Timeline = function () {
michael@0 771 var barColor = 'rgba(255,255,255, 0.075)';
michael@0 772 var backgroundColor = 'rgb(61, 61, 61)';
michael@0 773 var backgroundColorInfo = 'rgba(0,0,0, 0.85)';
michael@0 774 var fpsLineColor = 'rgb(255,64,0)';
michael@0 775 var textColor = '#ccc';
michael@0 776 function timeline(canvas) {
michael@0 777 this.depth = 0;
michael@0 778 this.start = 0;
michael@0 779 this.index = 0;
michael@0 780 this.marks = new Shumway.CircularBuffer(Int32Array);
michael@0 781 this.times = new Shumway.CircularBuffer(Float64Array);
michael@0 782 this.frameRate = 12;
michael@0 783 this.maxFrameTime = 1000 * 2 / this.frameRate;
michael@0 784 this.refreshFrequency = 10;
michael@0 785 this.refreshCounter = 0;
michael@0 786 this.count = 0;
michael@0 787 this.kinds = createEmptyObject();
michael@0 788 this.kindCount = 0;
michael@0 789 this.canvas = canvas;
michael@0 790 this.context = canvas.getContext('2d', {
michael@0 791 original: true
michael@0 792 });
michael@0 793 this.fillStyles = [
michael@0 794 'rgb(85, 152, 213)',
michael@0 795 '#bfd8a7',
michael@0 796 '#d906d7'
michael@0 797 ];
michael@0 798 window.addEventListener('resize', this.resizeHandler.bind(this), false);
michael@0 799 this.resizeHandler();
michael@0 800 }
michael@0 801 timeline.prototype.setFrameRate = function setFrameRate(frameRate) {
michael@0 802 this.frameRate = frameRate;
michael@0 803 this.maxFrameTime = 1000 * 2 / frameRate;
michael@0 804 };
michael@0 805 timeline.prototype.refreshEvery = function refreshEvery(freq) {
michael@0 806 this.refreshFrequency = freq;
michael@0 807 this.refreshCounter = 0;
michael@0 808 };
michael@0 809 var ENTER = 3203334144 | 0;
michael@0 810 var LEAVE = 3735879680 | 0;
michael@0 811 timeline.prototype.registerKind = function getKind(name, fillStyle) {
michael@0 812 if (this.kinds[name] === undefined) {
michael@0 813 this.fillStyles[this.kindCount] = fillStyle;
michael@0 814 this.kinds[name] = this.kindCount++;
michael@0 815 } else {
michael@0 816 this.fillStyles[this.kinds[name]] = fillStyle;
michael@0 817 }
michael@0 818 };
michael@0 819 timeline.prototype.getKind = function getKind(name) {
michael@0 820 if (this.kinds[name] === undefined) {
michael@0 821 this.kinds[name] = this.kindCount++;
michael@0 822 if (this.kindCount > this.fillStyles.length) {
michael@0 823 this.fillStyles.push(randomStyle());
michael@0 824 }
michael@0 825 }
michael@0 826 return this.kinds[name];
michael@0 827 };
michael@0 828 timeline.prototype.enter = function enter(name) {
michael@0 829 this.depth++;
michael@0 830 this.marks.write(ENTER | this.getKind(name));
michael@0 831 this.times.write(performance.now());
michael@0 832 };
michael@0 833 timeline.prototype.leave = function leave(name) {
michael@0 834 this.marks.write(LEAVE | this.getKind(name));
michael@0 835 this.times.write(performance.now());
michael@0 836 this.depth--;
michael@0 837 if (this.depth === 0) {
michael@0 838 this.count++;
michael@0 839 if (++this.refreshCounter == this.refreshFrequency) {
michael@0 840 this.refreshCounter = 0;
michael@0 841 this.paint();
michael@0 842 }
michael@0 843 }
michael@0 844 };
michael@0 845 timeline.prototype.gatherFrames = function gatherFrames(maxFrames) {
michael@0 846 var stack = [];
michael@0 847 var frames = [];
michael@0 848 var times = this.times;
michael@0 849 maxFrames++;
michael@0 850 this.marks.forEachInReverse(function (mark, i) {
michael@0 851 var time = times.get(i);
michael@0 852 if ((mark & 4294901760) === ENTER) {
michael@0 853 var node = stack.pop();
michael@0 854 node.startTime = time;
michael@0 855 if (!stack.length) {
michael@0 856 if (frames.length && !frames[0].total) {
michael@0 857 frames[0].total = frames[0].startTime - time;
michael@0 858 }
michael@0 859 frames.unshift(node);
michael@0 860 } else {
michael@0 861 var top = stack.top();
michael@0 862 if (!top.children) {
michael@0 863 top.children = [
michael@0 864 node
michael@0 865 ];
michael@0 866 } else {
michael@0 867 top.children.push(node);
michael@0 868 }
michael@0 869 }
michael@0 870 } else if ((mark & 4294901760) === LEAVE) {
michael@0 871 if (frames.length > maxFrames) {
michael@0 872 return true;
michael@0 873 }
michael@0 874 stack.push({
michael@0 875 kind: mark & 65535,
michael@0 876 endTime: time
michael@0 877 });
michael@0 878 }
michael@0 879 });
michael@0 880 return frames;
michael@0 881 };
michael@0 882 timeline.prototype.resizeHandler = function resizeHandler(event) {
michael@0 883 var parent = this.canvas.parentElement;
michael@0 884 this.cw = parent.offsetWidth;
michael@0 885 this.ch = parent.offsetHeight - 1;
michael@0 886 var devicePixelRatio = window.devicePixelRatio || 1;
michael@0 887 var backingStoreRatio = this.context.webkitBackingStorePixelRatio || this.context.mozBackingStorePixelRatio || this.context.msBackingStorePixelRatio || this.context.oBackingStorePixelRatio || this.context.backingStorePixelRatio || 1;
michael@0 888 if (devicePixelRatio !== backingStoreRatio) {
michael@0 889 var ratio = devicePixelRatio / backingStoreRatio;
michael@0 890 this.canvas.width = this.cw * ratio;
michael@0 891 this.canvas.height = this.ch * ratio;
michael@0 892 this.canvas.style.width = this.cw + 'px';
michael@0 893 this.canvas.style.height = this.ch + 'px';
michael@0 894 this.context.scale(ratio, ratio);
michael@0 895 } else {
michael@0 896 this.canvas.width = this.cw;
michael@0 897 this.canvas.height = this.ch;
michael@0 898 }
michael@0 899 this.context.font = '10px Consolas, "Liberation Mono", Courier, monospace';
michael@0 900 };
michael@0 901 timeline.prototype.paint = function paint() {
michael@0 902 var w = 10;
michael@0 903 var gap = 1;
michael@0 904 var maxFrames = this.cw / (w + gap) | 0;
michael@0 905 var frames = this.gatherFrames(maxFrames);
michael@0 906 var context = this.context;
michael@0 907 var maxFrameTime = this.maxFrameTime;
michael@0 908 var fillStyles = this.fillStyles;
michael@0 909 context.clearRect(0, 0, this.cw, this.ch);
michael@0 910 var maxFrameRate = 0;
michael@0 911 var maxFrameRateCount = 0;
michael@0 912 var avgFrameRate = 0;
michael@0 913 var avgFrameRateCount = 0;
michael@0 914 var offsetW;
michael@0 915 context.save();
michael@0 916 context.translate(0, this.ch);
michael@0 917 context.scale(1, -this.ch / maxFrameTime);
michael@0 918 for (var i = 0; i < frames.length - 1; i++) {
michael@0 919 var frame = frames[i];
michael@0 920 maxFrameRate += frame.endTime - frame.startTime;
michael@0 921 maxFrameRateCount++;
michael@0 922 if (frame.total) {
michael@0 923 avgFrameRate += frame.total;
michael@0 924 avgFrameRateCount++;
michael@0 925 }
michael@0 926 offsetW = i * (w + gap);
michael@0 927 context.fillStyle = barColor;
michael@0 928 context.fillRect(offsetW, 0, w, frames[i + 1].startTime - frame.startTime);
michael@0 929 drawNode(frame, frame.startTime);
michael@0 930 }
michael@0 931 function drawNode(node, frameStartTime) {
michael@0 932 var nodeTime = node.endTime - node.startTime;
michael@0 933 var offsetH = node.startTime - frameStartTime;
michael@0 934 context.fillStyle = fillStyles[node.kind];
michael@0 935 context.fillRect(offsetW, offsetH, w, nodeTime);
michael@0 936 if (node.children) {
michael@0 937 var children = node.children;
michael@0 938 for (var i = 0, n = children.length; i < n; i++) {
michael@0 939 drawNode(children[i], frameStartTime);
michael@0 940 }
michael@0 941 }
michael@0 942 }
michael@0 943 var lineH = 1000 / this.frameRate;
michael@0 944 context.beginPath();
michael@0 945 context.lineWidth = 0.5;
michael@0 946 context.moveTo(0, lineH);
michael@0 947 context.lineTo(this.cw, lineH);
michael@0 948 context.strokeStyle = fpsLineColor;
michael@0 949 context.stroke();
michael@0 950 context.restore();
michael@0 951 context.fillStyle = backgroundColorInfo;
michael@0 952 context.fillRect(0, 0, this.cw, 20);
michael@0 953 var textOffset;
michael@0 954 var sFrameCount = this.count;
michael@0 955 var sMaxFrameRate = Math.round(1000 * maxFrameRateCount / maxFrameRate);
michael@0 956 var sAvgFrameRate = Math.round(1000 * avgFrameRateCount / avgFrameRate);
michael@0 957 var space = 5;
michael@0 958 textOffset = 5;
michael@0 959 context.fillStyle = textColor;
michael@0 960 context.fillText(sFrameCount, textOffset, 13);
michael@0 961 textOffset += context.measureText(sFrameCount).width + space;
michael@0 962 context.fillText(sMaxFrameRate, textOffset, 13);
michael@0 963 textOffset += context.measureText(sMaxFrameRate).width + space;
michael@0 964 context.fillText(sAvgFrameRate, textOffset, 13);
michael@0 965 var basicOffset = textOffset + context.measureText(sAvgFrameRate).width + space;
michael@0 966 textOffset = this.cw;
michael@0 967 for (var k in this.kinds) {
michael@0 968 context.fillStyle = this.fillStyles[this.getKind(k)];
michael@0 969 textOffset -= context.measureText(k).width + space;
michael@0 970 if (textOffset > basicOffset) {
michael@0 971 this.context.fillText(k, textOffset, 13);
michael@0 972 }
michael@0 973 }
michael@0 974 };
michael@0 975 return timeline;
michael@0 976 }();
michael@0 977 var create = Object.create;
michael@0 978 var defineProperty = Object.defineProperty;
michael@0 979 var keys = Object.keys;
michael@0 980 var isArray = Array.isArray;
michael@0 981 var fromCharCode = String.fromCharCode;
michael@0 982 var logE = Math.log;
michael@0 983 var max = Math.max;
michael@0 984 var min = Math.min;
michael@0 985 var pow = Math.pow;
michael@0 986 var push = Array.prototype.push;
michael@0 987 var slice = Array.prototype.slice;
michael@0 988 var splice = Array.prototype.splice;
michael@0 989 function fail(msg, context) {
michael@0 990 throw new Error((context ? context + ': ' : '') + msg);
michael@0 991 }
michael@0 992 function assert(cond, msg, context) {
michael@0 993 if (!cond)
michael@0 994 fail(msg, context);
michael@0 995 }
michael@0 996 function scriptProperties(namespace, props) {
michael@0 997 return props.reduce(function (o, p) {
michael@0 998 o[p] = namespace + ' ' + p;
michael@0 999 return o;
michael@0 1000 }, {});
michael@0 1001 }
michael@0 1002 function cloneObject(obj) {
michael@0 1003 var clone = Object.create(null);
michael@0 1004 for (var prop in obj)
michael@0 1005 clone[prop] = obj[prop];
michael@0 1006 return clone;
michael@0 1007 }
michael@0 1008 function sortNumeric(a, b) {
michael@0 1009 return a - b;
michael@0 1010 }
michael@0 1011 function sortByZindex(a, b) {
michael@0 1012 return a._zindex - b._zindex;
michael@0 1013 }
michael@0 1014 function rgbaObjToStr(color) {
michael@0 1015 return 'rgba(' + color.red + ',' + color.green + ',' + color.blue + ',' + color.alpha / 255 + ')';
michael@0 1016 }
michael@0 1017 function rgbIntAlphaToStr(color, alpha) {
michael@0 1018 color |= 0;
michael@0 1019 if (alpha >= 1) {
michael@0 1020 var colorStr = color.toString(16);
michael@0 1021 while (colorStr.length < 6) {
michael@0 1022 colorStr = '0' + colorStr;
michael@0 1023 }
michael@0 1024 return '#' + colorStr;
michael@0 1025 }
michael@0 1026 var red = color >> 16 & 255;
michael@0 1027 var green = color >> 8 & 255;
michael@0 1028 var blue = color & 255;
michael@0 1029 return 'rgba(' + red + ',' + green + ',' + blue + ',' + alpha + ')';
michael@0 1030 }
michael@0 1031 function argbUintToStr(argb) {
michael@0 1032 return 'rgba(' + (argb >>> 16 & 255) + ',' + (argb >>> 8 & 255) + ',' + (argb & 255) + ',' + (argb >>> 24 & 255) / 255 + ')';
michael@0 1033 }
michael@0 1034 (function functionNameSupport() {
michael@0 1035 if (eval('function t() {} t.name === \'t\'')) {
michael@0 1036 return;
michael@0 1037 }
michael@0 1038 Object.defineProperty(Function.prototype, 'name', {
michael@0 1039 get: function () {
michael@0 1040 if (this.__name) {
michael@0 1041 return this.__name;
michael@0 1042 }
michael@0 1043 var m = /function\s([^\(]+)/.exec(this.toString());
michael@0 1044 var name = m && m[1] !== 'anonymous' ? m[1] : null;
michael@0 1045 this.__name = name;
michael@0 1046 return name;
michael@0 1047 },
michael@0 1048 configurable: true,
michael@0 1049 enumerable: false
michael@0 1050 });
michael@0 1051 }());
michael@0 1052 var randomStyleCache;
michael@0 1053 var nextStyle = 0;
michael@0 1054 function randomStyle() {
michael@0 1055 if (!randomStyleCache) {
michael@0 1056 randomStyleCache = [
michael@0 1057 '#ff5e3a',
michael@0 1058 '#ff9500',
michael@0 1059 '#ffdb4c',
michael@0 1060 '#87fc70',
michael@0 1061 '#52edc7',
michael@0 1062 '#1ad6fd',
michael@0 1063 '#c644fc',
michael@0 1064 '#ef4db6',
michael@0 1065 '#4a4a4a',
michael@0 1066 '#dbddde',
michael@0 1067 '#ff3b30',
michael@0 1068 '#ff9500',
michael@0 1069 '#ffcc00',
michael@0 1070 '#4cd964',
michael@0 1071 '#34aadc',
michael@0 1072 '#007aff',
michael@0 1073 '#5856d6',
michael@0 1074 '#ff2d55',
michael@0 1075 '#8e8e93',
michael@0 1076 '#c7c7cc',
michael@0 1077 '#5ad427',
michael@0 1078 '#c86edf',
michael@0 1079 '#d1eefc',
michael@0 1080 '#e0f8d8',
michael@0 1081 '#fb2b69',
michael@0 1082 '#f7f7f7',
michael@0 1083 '#1d77ef',
michael@0 1084 '#d6cec3',
michael@0 1085 '#55efcb',
michael@0 1086 '#ff4981',
michael@0 1087 '#ffd3e0',
michael@0 1088 '#f7f7f7',
michael@0 1089 '#ff1300',
michael@0 1090 '#1f1f21',
michael@0 1091 '#bdbec2',
michael@0 1092 '#ff3a2d'
michael@0 1093 ];
michael@0 1094 }
michael@0 1095 return randomStyleCache[nextStyle++ % randomStyleCache.length];
michael@0 1096 }
michael@0 1097 (function PromiseClosure() {
michael@0 1098 var global = Function('return this')();
michael@0 1099 if (global.Promise) {
michael@0 1100 if (typeof global.Promise.all !== 'function') {
michael@0 1101 global.Promise.all = function (iterable) {
michael@0 1102 var count = 0, results = [], resolve, reject;
michael@0 1103 var promise = new global.Promise(function (resolve_, reject_) {
michael@0 1104 resolve = resolve_;
michael@0 1105 reject = reject_;
michael@0 1106 });
michael@0 1107 iterable.forEach(function (p, i) {
michael@0 1108 count++;
michael@0 1109 p.then(function (result) {
michael@0 1110 results[i] = result;
michael@0 1111 count--;
michael@0 1112 if (count === 0) {
michael@0 1113 resolve(results);
michael@0 1114 }
michael@0 1115 }, reject);
michael@0 1116 });
michael@0 1117 if (count === 0) {
michael@0 1118 resolve(results);
michael@0 1119 }
michael@0 1120 return promise;
michael@0 1121 };
michael@0 1122 }
michael@0 1123 if (typeof global.Promise.resolve !== 'function') {
michael@0 1124 global.Promise.resolve = function (x) {
michael@0 1125 return new global.Promise(function (resolve) {
michael@0 1126 resolve(x);
michael@0 1127 });
michael@0 1128 };
michael@0 1129 }
michael@0 1130 return;
michael@0 1131 }
michael@0 1132 function getDeferred(C) {
michael@0 1133 if (typeof C !== 'function') {
michael@0 1134 throw new TypeError('Invalid deferred constructor');
michael@0 1135 }
michael@0 1136 var resolver = createDeferredConstructionFunctions();
michael@0 1137 var promise = new C(resolver);
michael@0 1138 var resolve = resolver.resolve;
michael@0 1139 if (typeof resolve !== 'function') {
michael@0 1140 throw new TypeError('Invalid resolve construction function');
michael@0 1141 }
michael@0 1142 var reject = resolver.reject;
michael@0 1143 if (typeof reject !== 'function') {
michael@0 1144 throw new TypeError('Invalid reject construction function');
michael@0 1145 }
michael@0 1146 return {
michael@0 1147 promise: promise,
michael@0 1148 resolve: resolve,
michael@0 1149 reject: reject
michael@0 1150 };
michael@0 1151 }
michael@0 1152 function updateDeferredFromPotentialThenable(x, deferred) {
michael@0 1153 if (typeof x !== 'object' || x === null) {
michael@0 1154 return false;
michael@0 1155 }
michael@0 1156 try {
michael@0 1157 var then = x.then;
michael@0 1158 if (typeof then !== 'function') {
michael@0 1159 return false;
michael@0 1160 }
michael@0 1161 var thenCallResult = then.call(x, deferred.resolve, deferred.reject);
michael@0 1162 } catch (e) {
michael@0 1163 var reject = deferred.reject;
michael@0 1164 reject(e);
michael@0 1165 }
michael@0 1166 return true;
michael@0 1167 }
michael@0 1168 function isPromise(x) {
michael@0 1169 return typeof x === 'object' && x !== null && typeof x.promiseStatus !== 'undefined';
michael@0 1170 }
michael@0 1171 function rejectPromise(promise, reason) {
michael@0 1172 if (promise.promiseStatus !== 'unresolved') {
michael@0 1173 return;
michael@0 1174 }
michael@0 1175 var reactions = promise.rejectReactions;
michael@0 1176 promise.result = reason;
michael@0 1177 promise.resolveReactions = undefined;
michael@0 1178 promise.rejectReactions = undefined;
michael@0 1179 promise.promiseStatus = 'has-rejection';
michael@0 1180 triggerPromiseReactions(reactions, reason);
michael@0 1181 }
michael@0 1182 function resolvePromise(promise, resolution) {
michael@0 1183 if (promise.promiseStatus !== 'unresolved') {
michael@0 1184 return;
michael@0 1185 }
michael@0 1186 var reactions = promise.resolveReactions;
michael@0 1187 promise.result = resolution;
michael@0 1188 promise.resolveReactions = undefined;
michael@0 1189 promise.rejectReactions = undefined;
michael@0 1190 promise.promiseStatus = 'has-resolution';
michael@0 1191 triggerPromiseReactions(reactions, resolution);
michael@0 1192 }
michael@0 1193 function triggerPromiseReactions(reactions, argument) {
michael@0 1194 for (var i = 0; i < reactions.length; i++) {
michael@0 1195 queueMicrotask({
michael@0 1196 reaction: reactions[i],
michael@0 1197 argument: argument
michael@0 1198 });
michael@0 1199 }
michael@0 1200 }
michael@0 1201 function queueMicrotask(task) {
michael@0 1202 if (microtasksQueue.length === 0) {
michael@0 1203 setTimeout(handleMicrotasksQueue, 0);
michael@0 1204 }
michael@0 1205 microtasksQueue.push(task);
michael@0 1206 }
michael@0 1207 function executePromiseReaction(reaction, argument) {
michael@0 1208 var deferred = reaction.deferred;
michael@0 1209 var handler = reaction.handler;
michael@0 1210 var handlerResult, updateResult;
michael@0 1211 try {
michael@0 1212 handlerResult = handler(argument);
michael@0 1213 } catch (e) {
michael@0 1214 var reject = deferred.reject;
michael@0 1215 return reject(e);
michael@0 1216 }
michael@0 1217 if (handlerResult === deferred.promise) {
michael@0 1218 var reject = deferred.reject;
michael@0 1219 return reject(new TypeError('Self resolution'));
michael@0 1220 }
michael@0 1221 try {
michael@0 1222 updateResult = updateDeferredFromPotentialThenable(handlerResult, deferred);
michael@0 1223 if (!updateResult) {
michael@0 1224 var resolve = deferred.resolve;
michael@0 1225 return resolve(handlerResult);
michael@0 1226 }
michael@0 1227 } catch (e) {
michael@0 1228 var reject = deferred.reject;
michael@0 1229 return reject(e);
michael@0 1230 }
michael@0 1231 }
michael@0 1232 var microtasksQueue = [];
michael@0 1233 function handleMicrotasksQueue() {
michael@0 1234 while (microtasksQueue.length > 0) {
michael@0 1235 var task = microtasksQueue[0];
michael@0 1236 try {
michael@0 1237 executePromiseReaction(task.reaction, task.argument);
michael@0 1238 } catch (e) {
michael@0 1239 if (typeof Promise.onerror === 'function') {
michael@0 1240 Promise.onerror(e);
michael@0 1241 }
michael@0 1242 }
michael@0 1243 microtasksQueue.shift();
michael@0 1244 }
michael@0 1245 }
michael@0 1246 function throwerFunction(e) {
michael@0 1247 throw e;
michael@0 1248 }
michael@0 1249 function identityFunction(x) {
michael@0 1250 return x;
michael@0 1251 }
michael@0 1252 function createRejectPromiseFunction(promise) {
michael@0 1253 return function (reason) {
michael@0 1254 rejectPromise(promise, reason);
michael@0 1255 };
michael@0 1256 }
michael@0 1257 function createResolvePromiseFunction(promise) {
michael@0 1258 return function (resolution) {
michael@0 1259 resolvePromise(promise, resolution);
michael@0 1260 };
michael@0 1261 }
michael@0 1262 function createDeferredConstructionFunctions() {
michael@0 1263 var fn = function (resolve, reject) {
michael@0 1264 fn.resolve = resolve;
michael@0 1265 fn.reject = reject;
michael@0 1266 };
michael@0 1267 return fn;
michael@0 1268 }
michael@0 1269 function createPromiseResolutionHandlerFunctions(promise, fulfillmentHandler, rejectionHandler) {
michael@0 1270 return function (x) {
michael@0 1271 if (x === promise) {
michael@0 1272 return rejectionHandler(new TypeError('Self resolution'));
michael@0 1273 }
michael@0 1274 var cstr = promise.promiseConstructor;
michael@0 1275 if (isPromise(x)) {
michael@0 1276 var xConstructor = x.promiseConstructor;
michael@0 1277 if (xConstructor === cstr) {
michael@0 1278 return x.then(fulfillmentHandler, rejectionHandler);
michael@0 1279 }
michael@0 1280 }
michael@0 1281 var deferred = getDeferred(cstr);
michael@0 1282 var updateResult = updateDeferredFromPotentialThenable(x, deferred);
michael@0 1283 if (updateResult) {
michael@0 1284 var deferredPromise = deferred.promise;
michael@0 1285 return deferredPromise.then(fulfillmentHandler, rejectionHandler);
michael@0 1286 }
michael@0 1287 return fulfillmentHandler(x);
michael@0 1288 };
michael@0 1289 }
michael@0 1290 function createPromiseAllCountdownFunction(index, values, deferred, countdownHolder) {
michael@0 1291 return function (x) {
michael@0 1292 values[index] = x;
michael@0 1293 countdownHolder.countdown--;
michael@0 1294 if (countdownHolder.countdown === 0) {
michael@0 1295 deferred.resolve(values);
michael@0 1296 }
michael@0 1297 };
michael@0 1298 }
michael@0 1299 function Promise(resolver) {
michael@0 1300 if (typeof resolver !== 'function') {
michael@0 1301 throw new TypeError('resolver is not a function');
michael@0 1302 }
michael@0 1303 var promise = this;
michael@0 1304 if (typeof promise !== 'object') {
michael@0 1305 throw new TypeError('Promise to initialize is not an object');
michael@0 1306 }
michael@0 1307 promise.promiseStatus = 'unresolved';
michael@0 1308 promise.resolveReactions = [];
michael@0 1309 promise.rejectReactions = [];
michael@0 1310 promise.result = undefined;
michael@0 1311 var resolve = createResolvePromiseFunction(promise);
michael@0 1312 var reject = createRejectPromiseFunction(promise);
michael@0 1313 try {
michael@0 1314 var result = resolver(resolve, reject);
michael@0 1315 } catch (e) {
michael@0 1316 rejectPromise(promise, e);
michael@0 1317 }
michael@0 1318 promise.promiseConstructor = Promise;
michael@0 1319 return promise;
michael@0 1320 }
michael@0 1321 Promise.all = function (iterable) {
michael@0 1322 var deferred = getDeferred(this);
michael@0 1323 var values = [];
michael@0 1324 var countdownHolder = {
michael@0 1325 countdown: 0
michael@0 1326 };
michael@0 1327 var index = 0;
michael@0 1328 iterable.forEach(function (nextValue) {
michael@0 1329 var nextPromise = this.cast(nextValue);
michael@0 1330 var fn = createPromiseAllCountdownFunction(index, values, deferred, countdownHolder);
michael@0 1331 nextPromise.then(fn, deferred.reject);
michael@0 1332 index++;
michael@0 1333 countdownHolder.countdown++;
michael@0 1334 }, this);
michael@0 1335 if (index === 0) {
michael@0 1336 deferred.resolve(values);
michael@0 1337 }
michael@0 1338 return deferred.promise;
michael@0 1339 };
michael@0 1340 Promise.cast = function (x) {
michael@0 1341 if (isPromise(x)) {
michael@0 1342 return x;
michael@0 1343 }
michael@0 1344 var deferred = getDeferred(this);
michael@0 1345 deferred.resolve(x);
michael@0 1346 return deferred.promise;
michael@0 1347 };
michael@0 1348 Promise.reject = function (r) {
michael@0 1349 var deferred = getDeferred(this);
michael@0 1350 var rejectResult = deferred.reject(r);
michael@0 1351 return deferred.promise;
michael@0 1352 };
michael@0 1353 Promise.resolve = function (x) {
michael@0 1354 var deferred = getDeferred(this);
michael@0 1355 var rejectResult = deferred.resolve(x);
michael@0 1356 return deferred.promise;
michael@0 1357 };
michael@0 1358 Promise.prototype = {
michael@0 1359 'catch': function (onRejected) {
michael@0 1360 this.then(undefined, onRejected);
michael@0 1361 },
michael@0 1362 then: function (onFulfilled, onRejected) {
michael@0 1363 var promise = this;
michael@0 1364 if (!isPromise(promise)) {
michael@0 1365 throw new TypeError('this is not a Promises');
michael@0 1366 }
michael@0 1367 var cstr = promise.promiseConstructor;
michael@0 1368 var deferred = getDeferred(cstr);
michael@0 1369 var rejectionHandler = typeof onRejected === 'function' ? onRejected : throwerFunction;
michael@0 1370 var fulfillmentHandler = typeof onFulfilled === 'function' ? onFulfilled : identityFunction;
michael@0 1371 var resolutionHandler = createPromiseResolutionHandlerFunctions(promise, fulfillmentHandler, rejectionHandler);
michael@0 1372 var resolveReaction = {
michael@0 1373 deferred: deferred,
michael@0 1374 handler: resolutionHandler
michael@0 1375 };
michael@0 1376 var rejectReaction = {
michael@0 1377 deferred: deferred,
michael@0 1378 handler: rejectionHandler
michael@0 1379 };
michael@0 1380 switch (promise.promiseStatus) {
michael@0 1381 case 'unresolved':
michael@0 1382 promise.resolveReactions.push(resolveReaction);
michael@0 1383 promise.rejectReactions.push(rejectReaction);
michael@0 1384 break;
michael@0 1385 case 'has-resolution':
michael@0 1386 var resolution = promise.result;
michael@0 1387 queueMicrotask({
michael@0 1388 reaction: resolveReaction,
michael@0 1389 argument: resolution
michael@0 1390 });
michael@0 1391 break;
michael@0 1392 case 'has-rejection':
michael@0 1393 var rejection = promise.result;
michael@0 1394 queueMicrotask({
michael@0 1395 reaction: rejectReaction,
michael@0 1396 argument: rejection
michael@0 1397 });
michael@0 1398 break;
michael@0 1399 }
michael@0 1400 return deferred.promise;
michael@0 1401 }
michael@0 1402 };
michael@0 1403 global.Promise = Promise;
michael@0 1404 }());
michael@0 1405 var QuadTree = function (x, y, width, height, parent) {
michael@0 1406 this.x = x | 0;
michael@0 1407 this.y = y | 0;
michael@0 1408 this.width = width | 0;
michael@0 1409 this.height = height | 0;
michael@0 1410 if (parent) {
michael@0 1411 this.root = parent.root;
michael@0 1412 this.parent = parent;
michael@0 1413 this.level = parent.level + 1;
michael@0 1414 } else {
michael@0 1415 this.root = this;
michael@0 1416 this.parent = null;
michael@0 1417 this.level = 0;
michael@0 1418 }
michael@0 1419 this.reset();
michael@0 1420 };
michael@0 1421 QuadTree.prototype.reset = function () {
michael@0 1422 this.stuckObjects = null;
michael@0 1423 this.objects = null;
michael@0 1424 this.nodes = [];
michael@0 1425 };
michael@0 1426 QuadTree.prototype._findIndex = function (xMin, xMax, yMin, yMax) {
michael@0 1427 var midX = this.x + (this.width / 2 | 0);
michael@0 1428 var midY = this.y + (this.height / 2 | 0);
michael@0 1429 var top = yMin < midY && yMax < midY;
michael@0 1430 var bottom = yMin > midY;
michael@0 1431 if (xMin < midX && xMax < midX) {
michael@0 1432 if (top) {
michael@0 1433 return 1;
michael@0 1434 } else if (bottom) {
michael@0 1435 return 2;
michael@0 1436 }
michael@0 1437 } else if (xMin > midX) {
michael@0 1438 if (top) {
michael@0 1439 return 0;
michael@0 1440 } else if (bottom) {
michael@0 1441 return 3;
michael@0 1442 }
michael@0 1443 }
michael@0 1444 return -1;
michael@0 1445 };
michael@0 1446 QuadTree.prototype.insert = function (obj) {
michael@0 1447 var nodes = this.nodes;
michael@0 1448 if (nodes.length) {
michael@0 1449 var index = this._findIndex(obj.xMin, obj.xMax, obj.yMin, obj.yMax);
michael@0 1450 if (index > -1) {
michael@0 1451 nodes[index].insert(obj);
michael@0 1452 } else {
michael@0 1453 obj.prev = null;
michael@0 1454 if (this.stuckObjects) {
michael@0 1455 obj.next = this.stuckObjects;
michael@0 1456 this.stuckObjects.prev = obj;
michael@0 1457 } else {
michael@0 1458 obj.next = null;
michael@0 1459 }
michael@0 1460 this.stuckObjects = obj;
michael@0 1461 obj.parent = this;
michael@0 1462 }
michael@0 1463 return;
michael@0 1464 }
michael@0 1465 var numChildren = 1;
michael@0 1466 var item = this.objects;
michael@0 1467 if (!item) {
michael@0 1468 obj.prev = null;
michael@0 1469 obj.next = null;
michael@0 1470 this.objects = obj;
michael@0 1471 } else {
michael@0 1472 while (item.next) {
michael@0 1473 numChildren++;
michael@0 1474 item = item.next;
michael@0 1475 }
michael@0 1476 obj.prev = item;
michael@0 1477 obj.next = null;
michael@0 1478 item.next = obj;
michael@0 1479 }
michael@0 1480 if (numChildren > 4 && this.level < 10) {
michael@0 1481 this._subdivide();
michael@0 1482 item = this.objects;
michael@0 1483 while (item) {
michael@0 1484 var next = item.next;
michael@0 1485 this.insert(item);
michael@0 1486 item = next;
michael@0 1487 }
michael@0 1488 this.objects = null;
michael@0 1489 return;
michael@0 1490 }
michael@0 1491 obj.parent = this;
michael@0 1492 };
michael@0 1493 QuadTree.prototype.update = function (obj) {
michael@0 1494 var node = obj.parent;
michael@0 1495 if (node) {
michael@0 1496 if (obj.xMin >= node.x && obj.xMax <= node.x + node.width && obj.yMin >= node.y && obj.yMax <= node.y + node.height) {
michael@0 1497 if (node.nodes.length) {
michael@0 1498 var index = this._findIndex(obj.xMin, obj.xMax, obj.yMin, obj.yMax);
michael@0 1499 if (index > -1) {
michael@0 1500 node.remove(obj);
michael@0 1501 node = this.nodes[index];
michael@0 1502 node.insert(obj);
michael@0 1503 }
michael@0 1504 } else {
michael@0 1505 node.remove(obj);
michael@0 1506 node.insert(obj);
michael@0 1507 }
michael@0 1508 return;
michael@0 1509 }
michael@0 1510 node.remove(obj);
michael@0 1511 }
michael@0 1512 this.root.insert(obj);
michael@0 1513 };
michael@0 1514 QuadTree.prototype.remove = function (obj) {
michael@0 1515 var prev = obj.prev;
michael@0 1516 var next = obj.next;
michael@0 1517 if (prev) {
michael@0 1518 prev.next = next;
michael@0 1519 obj.prev = null;
michael@0 1520 } else {
michael@0 1521 var node = obj.parent;
michael@0 1522 if (node.objects === obj) {
michael@0 1523 node.objects = next;
michael@0 1524 } else if (node.stuckObjects === obj) {
michael@0 1525 node.stuckObjects = next;
michael@0 1526 }
michael@0 1527 }
michael@0 1528 if (next) {
michael@0 1529 next.prev = prev;
michael@0 1530 obj.next = null;
michael@0 1531 }
michael@0 1532 obj.parent = null;
michael@0 1533 };
michael@0 1534 QuadTree.prototype.retrieve = function (xMin, xMax, yMin, yMax) {
michael@0 1535 var stack = [];
michael@0 1536 var out = [];
michael@0 1537 var node = this;
michael@0 1538 do {
michael@0 1539 if (node.nodes.length) {
michael@0 1540 var index = node._findIndex(xMin, xMax, yMin, yMax);
michael@0 1541 if (index > -1) {
michael@0 1542 stack.push(node.nodes[index]);
michael@0 1543 } else {
michael@0 1544 stack.push.apply(stack, node.nodes);
michael@0 1545 }
michael@0 1546 }
michael@0 1547 var item = node.objects;
michael@0 1548 for (var i = 0; i < 2; i++) {
michael@0 1549 while (item) {
michael@0 1550 if (!(item.xMin > xMax || item.xMax < xMin || item.yMin > yMax || item.yMax < yMin)) {
michael@0 1551 out.push(item);
michael@0 1552 }
michael@0 1553 item = item.next;
michael@0 1554 }
michael@0 1555 item = node.stuckObjects;
michael@0 1556 }
michael@0 1557 node = stack.pop();
michael@0 1558 } while (node);
michael@0 1559 return out;
michael@0 1560 };
michael@0 1561 QuadTree.prototype._subdivide = function () {
michael@0 1562 var halfWidth = this.width / 2 | 0;
michael@0 1563 var halfHeight = this.height / 2 | 0;
michael@0 1564 var midX = this.x + halfWidth;
michael@0 1565 var midY = this.y + halfHeight;
michael@0 1566 this.nodes[0] = new QuadTree(midX, this.y, halfWidth, halfHeight, this);
michael@0 1567 this.nodes[1] = new QuadTree(this.x, this.y, halfWidth, halfHeight, this);
michael@0 1568 this.nodes[2] = new QuadTree(this.x, midY, halfWidth, halfHeight, this);
michael@0 1569 this.nodes[3] = new QuadTree(midX, midY, halfWidth, halfHeight, this);
michael@0 1570 };
michael@0 1571 var RegionCluster = function () {
michael@0 1572 this.regions = [];
michael@0 1573 };
michael@0 1574 RegionCluster.prototype.reset = function () {
michael@0 1575 this.regions.length = 0;
michael@0 1576 };
michael@0 1577 RegionCluster.prototype.insert = function (region) {
michael@0 1578 var regions = this.regions;
michael@0 1579 if (regions.length < 3) {
michael@0 1580 regions.push({
michael@0 1581 xMin: region.xMin,
michael@0 1582 xMax: region.xMax,
michael@0 1583 yMin: region.yMin,
michael@0 1584 yMax: region.yMax
michael@0 1585 });
michael@0 1586 return;
michael@0 1587 }
michael@0 1588 var a = region;
michael@0 1589 var b = regions[0];
michael@0 1590 var c = regions[1];
michael@0 1591 var d = regions[2];
michael@0 1592 var ab = (max(a.xMax, b.xMax) - min(a.xMin, b.xMin)) * (max(a.yMax, b.yMax) - min(a.yMin, b.yMin));
michael@0 1593 var rb = regions[0];
michael@0 1594 var ac = (max(a.xMax, c.xMax) - min(a.xMin, c.xMin)) * (max(a.yMax, c.yMax) - min(a.yMin, c.yMin));
michael@0 1595 var ad = (max(a.xMax, d.xMax) - min(a.xMin, d.xMin)) * (max(a.yMax, d.yMax) - min(a.yMin, d.yMin));
michael@0 1596 if (ac < ab) {
michael@0 1597 ab = ac;
michael@0 1598 rb = c;
michael@0 1599 }
michael@0 1600 if (ad < ab) {
michael@0 1601 ab = ad;
michael@0 1602 rb = d;
michael@0 1603 }
michael@0 1604 var bc = (max(b.xMax, c.xMax) - min(b.xMin, c.xMin)) * (max(b.yMax, c.yMax) - min(b.yMin, c.yMin));
michael@0 1605 var bd = (max(b.xMax, d.xMax) - min(b.xMin, d.xMin)) * (max(b.yMax, d.yMax) - min(b.yMin, d.yMin));
michael@0 1606 var cd = (max(c.xMax, d.xMax) - min(c.xMin, d.xMin)) * (max(c.yMax, d.yMax) - min(c.yMin, d.yMin));
michael@0 1607 if (ab < bc && ab < bd && ab < cd) {
michael@0 1608 if (a.xMin < rb.xMin) {
michael@0 1609 rb.xMin = a.xMin;
michael@0 1610 }
michael@0 1611 if (a.xMax > rb.xMax) {
michael@0 1612 rb.xMax = a.xMax;
michael@0 1613 }
michael@0 1614 if (a.yMin < rb.yMin) {
michael@0 1615 rb.yMin = a.yMin;
michael@0 1616 }
michael@0 1617 if (a.yMax > rb.yMax) {
michael@0 1618 rb.yMax = a.yMax;
michael@0 1619 }
michael@0 1620 return;
michael@0 1621 }
michael@0 1622 rb = regions[0];
michael@0 1623 var rc = regions[1];
michael@0 1624 if (bd < bc) {
michael@0 1625 bc = bd;
michael@0 1626 rc = regions[2];
michael@0 1627 }
michael@0 1628 if (cd < bc) {
michael@0 1629 rb = regions[1];
michael@0 1630 rc = regions[2];
michael@0 1631 }
michael@0 1632 if (rc.xMin < rb.xMin) {
michael@0 1633 rb.xMin = rc.xMin;
michael@0 1634 }
michael@0 1635 if (rc.xMax > rb.xMax) {
michael@0 1636 rb.xMax = rc.xMax;
michael@0 1637 }
michael@0 1638 if (rc.yMin < rb.yMin) {
michael@0 1639 rb.yMin = rc.yMin;
michael@0 1640 }
michael@0 1641 if (rc.yMax > rb.yMax) {
michael@0 1642 rb.yMax = rc.yMax;
michael@0 1643 }
michael@0 1644 rc.xMin = a.xMin;
michael@0 1645 rc.xMax = a.xMax;
michael@0 1646 rc.yMin = a.yMin;
michael@0 1647 rc.yMax = a.yMax;
michael@0 1648 };
michael@0 1649 RegionCluster.prototype.retrieve = function () {
michael@0 1650 return this.regions;
michael@0 1651 };
michael@0 1652 var EXTERNAL_INTERFACE_FEATURE = 1;
michael@0 1653 var CLIPBOARD_FEATURE = 2;
michael@0 1654 var SHAREDOBJECT_FEATURE = 3;
michael@0 1655 var VIDEO_FEATURE = 4;
michael@0 1656 var SOUND_FEATURE = 5;
michael@0 1657 var NETCONNECTION_FEATURE = 6;
michael@0 1658 if (!this.performance) {
michael@0 1659 this.performance = {};
michael@0 1660 }
michael@0 1661 if (!this.performance.now) {
michael@0 1662 this.performance.now = Date.now;
michael@0 1663 }
michael@0 1664 var SWF_TAG_CODE_CSM_TEXT_SETTINGS = 74;
michael@0 1665 var SWF_TAG_CODE_DEFINE_BINARY_DATA = 87;
michael@0 1666 var SWF_TAG_CODE_DEFINE_BITS = 6;
michael@0 1667 var SWF_TAG_CODE_DEFINE_BITS_JPEG2 = 21;
michael@0 1668 var SWF_TAG_CODE_DEFINE_BITS_JPEG3 = 35;
michael@0 1669 var SWF_TAG_CODE_DEFINE_BITS_JPEG4 = 90;
michael@0 1670 var SWF_TAG_CODE_DEFINE_BITS_LOSSLESS = 20;
michael@0 1671 var SWF_TAG_CODE_DEFINE_BITS_LOSSLESS2 = 36;
michael@0 1672 var SWF_TAG_CODE_DEFINE_BUTTON = 7;
michael@0 1673 var SWF_TAG_CODE_DEFINE_BUTTON2 = 34;
michael@0 1674 var SWF_TAG_CODE_DEFINE_BUTTON_CXFORM = 23;
michael@0 1675 var SWF_TAG_CODE_DEFINE_BUTTON_SOUND = 17;
michael@0 1676 var SWF_TAG_CODE_DEFINE_EDIT_TEXT = 37;
michael@0 1677 var SWF_TAG_CODE_DEFINE_FONT = 10;
michael@0 1678 var SWF_TAG_CODE_DEFINE_FONT2 = 48;
michael@0 1679 var SWF_TAG_CODE_DEFINE_FONT3 = 75;
michael@0 1680 var SWF_TAG_CODE_DEFINE_FONT4 = 91;
michael@0 1681 var SWF_TAG_CODE_DEFINE_FONT_ALIGN_ZONES = 73;
michael@0 1682 var SWF_TAG_CODE_DEFINE_FONT_INFO = 13;
michael@0 1683 var SWF_TAG_CODE_DEFINE_FONT_INFO2 = 62;
michael@0 1684 var SWF_TAG_CODE_DEFINE_FONT_NAME = 88;
michael@0 1685 var SWF_TAG_CODE_DEFINE_MORPH_SHAPE = 46;
michael@0 1686 var SWF_TAG_CODE_DEFINE_MORPH_SHAPE2 = 84;
michael@0 1687 var SWF_TAG_CODE_DEFINE_SCALING_GRID = 78;
michael@0 1688 var SWF_TAG_CODE_DEFINE_SCENE_AND_FRAME_LABEL_DATA = 86;
michael@0 1689 var SWF_TAG_CODE_DEFINE_SHAPE = 2;
michael@0 1690 var SWF_TAG_CODE_DEFINE_SHAPE2 = 22;
michael@0 1691 var SWF_TAG_CODE_DEFINE_SHAPE3 = 32;
michael@0 1692 var SWF_TAG_CODE_DEFINE_SHAPE4 = 83;
michael@0 1693 var SWF_TAG_CODE_DEFINE_SOUND = 14;
michael@0 1694 var SWF_TAG_CODE_DEFINE_SPRITE = 39;
michael@0 1695 var SWF_TAG_CODE_DEFINE_TEXT = 11;
michael@0 1696 var SWF_TAG_CODE_DEFINE_TEXT2 = 33;
michael@0 1697 var SWF_TAG_CODE_DEFINE_VIDEO_STREAM = 60;
michael@0 1698 var SWF_TAG_CODE_DO_ABC = 82;
michael@0 1699 var SWF_TAG_CODE_DO_ABC_ = 72;
michael@0 1700 var SWF_TAG_CODE_DO_ACTION = 12;
michael@0 1701 var SWF_TAG_CODE_DO_INIT_ACTION = 59;
michael@0 1702 var SWF_TAG_CODE_ENABLE_DEBUGGER = 58;
michael@0 1703 var SWF_TAG_CODE_ENABLE_DEBUGGER2 = 64;
michael@0 1704 var SWF_TAG_CODE_END = 0;
michael@0 1705 var SWF_TAG_CODE_EXPORT_ASSETS = 56;
michael@0 1706 var SWF_TAG_CODE_FILE_ATTRIBUTES = 69;
michael@0 1707 var SWF_TAG_CODE_FRAME_LABEL = 43;
michael@0 1708 var SWF_TAG_CODE_IMPORT_ASSETS = 57;
michael@0 1709 var SWF_TAG_CODE_IMPORT_ASSETS2 = 71;
michael@0 1710 var SWF_TAG_CODE_JPEG_TABLES = 8;
michael@0 1711 var SWF_TAG_CODE_METADATA = 77;
michael@0 1712 var SWF_TAG_CODE_PLACE_OBJECT = 4;
michael@0 1713 var SWF_TAG_CODE_PLACE_OBJECT2 = 26;
michael@0 1714 var SWF_TAG_CODE_PLACE_OBJECT3 = 70;
michael@0 1715 var SWF_TAG_CODE_PROTECT = 24;
michael@0 1716 var SWF_TAG_CODE_REMOVE_OBJECT = 5;
michael@0 1717 var SWF_TAG_CODE_REMOVE_OBJECT2 = 28;
michael@0 1718 var SWF_TAG_CODE_SCRIPT_LIMITS = 65;
michael@0 1719 var SWF_TAG_CODE_SET_BACKGROUND_COLOR = 9;
michael@0 1720 var SWF_TAG_CODE_SET_TAB_INDEX = 66;
michael@0 1721 var SWF_TAG_CODE_SHOW_FRAME = 1;
michael@0 1722 var SWF_TAG_CODE_SOUND_STREAM_BLOCK = 19;
michael@0 1723 var SWF_TAG_CODE_SOUND_STREAM_HEAD = 18;
michael@0 1724 var SWF_TAG_CODE_SOUND_STREAM_HEAD2 = 45;
michael@0 1725 var SWF_TAG_CODE_START_SOUND = 15;
michael@0 1726 var SWF_TAG_CODE_START_SOUND2 = 89;
michael@0 1727 var SWF_TAG_CODE_SYMBOL_CLASS = 76;
michael@0 1728 var SWF_TAG_CODE_VIDEO_FRAME = 61;
michael@0 1729 self.SWF = {};
michael@0 1730 var codeLengthOrder = [
michael@0 1731 16,
michael@0 1732 17,
michael@0 1733 18,
michael@0 1734 0,
michael@0 1735 8,
michael@0 1736 7,
michael@0 1737 9,
michael@0 1738 6,
michael@0 1739 10,
michael@0 1740 5,
michael@0 1741 11,
michael@0 1742 4,
michael@0 1743 12,
michael@0 1744 3,
michael@0 1745 13,
michael@0 1746 2,
michael@0 1747 14,
michael@0 1748 1,
michael@0 1749 15
michael@0 1750 ];
michael@0 1751 var distanceCodes = [];
michael@0 1752 var distanceExtraBits = [];
michael@0 1753 for (var i = 0, j = 0, code = 1; i < 30; ++i) {
michael@0 1754 distanceCodes[i] = code;
michael@0 1755 code += 1 << (distanceExtraBits[i] = ~(~((j += i > 2 ? 1 : 0) / 2)));
michael@0 1756 }
michael@0 1757 var bitLengths = [];
michael@0 1758 for (var i = 0; i < 32; ++i)
michael@0 1759 bitLengths[i] = 5;
michael@0 1760 var fixedDistanceTable = makeHuffmanTable(bitLengths);
michael@0 1761 var lengthCodes = [];
michael@0 1762 var lengthExtraBits = [];
michael@0 1763 for (var i = 0, j = 0, code = 3; i < 29; ++i) {
michael@0 1764 lengthCodes[i] = code - (i == 28 ? 1 : 0);
michael@0 1765 code += 1 << (lengthExtraBits[i] = ~(~((j += i > 4 ? 1 : 0) / 4 % 6)));
michael@0 1766 }
michael@0 1767 for (var i = 0; i < 288; ++i)
michael@0 1768 bitLengths[i] = i < 144 || i > 279 ? 8 : i < 256 ? 9 : 7;
michael@0 1769 var fixedLiteralTable = makeHuffmanTable(bitLengths);
michael@0 1770 function makeHuffmanTable(bitLengths) {
michael@0 1771 var maxBits = Math.max.apply(null, bitLengths);
michael@0 1772 var numLengths = bitLengths.length;
michael@0 1773 var size = 1 << maxBits;
michael@0 1774 var codes = new Uint32Array(size);
michael@0 1775 for (var code = 0, len = 1, skip = 2; len <= maxBits; code <<= 1, ++len, skip <<= 1) {
michael@0 1776 for (var val = 0; val < numLengths; ++val) {
michael@0 1777 if (bitLengths[val] === len) {
michael@0 1778 var lsb = 0;
michael@0 1779 for (var i = 0; i < len; ++i)
michael@0 1780 lsb = lsb * 2 + (code >> i & 1);
michael@0 1781 for (var i = lsb; i < size; i += skip)
michael@0 1782 codes[i] = len << 16 | val;
michael@0 1783 ++code;
michael@0 1784 }
michael@0 1785 }
michael@0 1786 }
michael@0 1787 return {
michael@0 1788 codes: codes,
michael@0 1789 maxBits: maxBits
michael@0 1790 };
michael@0 1791 }
michael@0 1792 function verifyDeflateHeader(bytes) {
michael@0 1793 var header = bytes[0] << 8 | bytes[1];
michael@0 1794 }
michael@0 1795 function createInflatedStream(bytes, outputLength) {
michael@0 1796 verifyDeflateHeader(bytes);
michael@0 1797 var stream = new Stream(bytes, 2);
michael@0 1798 var output = {
michael@0 1799 data: new Uint8Array(outputLength),
michael@0 1800 available: 0,
michael@0 1801 completed: false
michael@0 1802 };
michael@0 1803 var state = {
michael@0 1804 header: null,
michael@0 1805 distanceTable: null,
michael@0 1806 literalTable: null,
michael@0 1807 sym: null,
michael@0 1808 len: null,
michael@0 1809 sym2: null
michael@0 1810 };
michael@0 1811 do {
michael@0 1812 inflateBlock(stream, output, state);
michael@0 1813 } while (!output.completed && stream.pos < stream.end);
michael@0 1814 return new Stream(output.data, 0, output.available);
michael@0 1815 }
michael@0 1816 var InflateNoDataError = {};
michael@0 1817 function inflateBlock(stream, output, state) {
michael@0 1818 var header = state.header !== null ? state.header : state.header = readBits(stream.bytes, stream, 3);
michael@0 1819 switch (header >> 1) {
michael@0 1820 case 0:
michael@0 1821 stream.align();
michael@0 1822 var pos = stream.pos;
michael@0 1823 if (stream.end - pos < 4) {
michael@0 1824 throw InflateNoDataError;
michael@0 1825 }
michael@0 1826 var len = stream.getUint16(pos, true);
michael@0 1827 var nlen = stream.getUint16(pos + 2, true);
michael@0 1828 if (stream.end - pos < 4 + len) {
michael@0 1829 throw InflateNoDataError;
michael@0 1830 }
michael@0 1831 var begin = pos + 4;
michael@0 1832 var end = stream.pos = begin + len;
michael@0 1833 var sbytes = stream.bytes, dbytes = output.data;
michael@0 1834 dbytes.set(sbytes.subarray(begin, end), output.available);
michael@0 1835 output.available += len;
michael@0 1836 break;
michael@0 1837 case 1:
michael@0 1838 inflate(stream, output, fixedLiteralTable, fixedDistanceTable, state);
michael@0 1839 break;
michael@0 1840 case 2:
michael@0 1841 var distanceTable, literalTable;
michael@0 1842 if (state.distanceTable !== null) {
michael@0 1843 distanceTable = state.distanceTable;
michael@0 1844 literalTable = state.literalTable;
michael@0 1845 } else {
michael@0 1846 var sbytes = stream.bytes;
michael@0 1847 var savedBufferPos = stream.pos;
michael@0 1848 var savedBitBuffer = stream.bitBuffer;
michael@0 1849 var savedBitLength = stream.bitLength;
michael@0 1850 var bitLengths = [];
michael@0 1851 var numLiteralCodes, numDistanceCodes;
michael@0 1852 try {
michael@0 1853 numLiteralCodes = readBits(sbytes, stream, 5) + 257;
michael@0 1854 numDistanceCodes = readBits(sbytes, stream, 5) + 1;
michael@0 1855 var numCodes = numLiteralCodes + numDistanceCodes;
michael@0 1856 var numLengthCodes = readBits(sbytes, stream, 4) + 4;
michael@0 1857 for (var i = 0; i < 19; ++i)
michael@0 1858 bitLengths[codeLengthOrder[i]] = i < numLengthCodes ? readBits(sbytes, stream, 3) : 0;
michael@0 1859 var codeLengthTable = makeHuffmanTable(bitLengths);
michael@0 1860 bitLengths = [];
michael@0 1861 var i = 0;
michael@0 1862 var prev = 0;
michael@0 1863 while (i < numCodes) {
michael@0 1864 var j = 1;
michael@0 1865 var sym = readCode(sbytes, stream, codeLengthTable);
michael@0 1866 switch (sym) {
michael@0 1867 case 16:
michael@0 1868 j = readBits(sbytes, stream, 2) + 3;
michael@0 1869 sym = prev;
michael@0 1870 break;
michael@0 1871 case 17:
michael@0 1872 j = readBits(sbytes, stream, 3) + 3;
michael@0 1873 sym = 0;
michael@0 1874 break;
michael@0 1875 case 18:
michael@0 1876 j = readBits(sbytes, stream, 7) + 11;
michael@0 1877 sym = 0;
michael@0 1878 break;
michael@0 1879 default:
michael@0 1880 prev = sym;
michael@0 1881 }
michael@0 1882 while (j--)
michael@0 1883 bitLengths[i++] = sym;
michael@0 1884 }
michael@0 1885 } catch (e) {
michael@0 1886 stream.pos = savedBufferPos;
michael@0 1887 stream.bitBuffer = savedBitBuffer;
michael@0 1888 stream.bitLength = savedBitLength;
michael@0 1889 throw e;
michael@0 1890 }
michael@0 1891 distanceTable = state.distanceTable = makeHuffmanTable(bitLengths.splice(numLiteralCodes, numDistanceCodes));
michael@0 1892 literalTable = state.literalTable = makeHuffmanTable(bitLengths);
michael@0 1893 }
michael@0 1894 inflate(stream, output, literalTable, distanceTable, state);
michael@0 1895 state.distanceTable = null;
michael@0 1896 state.literalTable = null;
michael@0 1897 break;
michael@0 1898 default:
michael@0 1899 fail('unknown block type', 'inflate');
michael@0 1900 }
michael@0 1901 state.header = null;
michael@0 1902 output.completed = !(!(header & 1));
michael@0 1903 }
michael@0 1904 function readBits(bytes, stream, size) {
michael@0 1905 var bitBuffer = stream.bitBuffer;
michael@0 1906 var bitLength = stream.bitLength;
michael@0 1907 if (size > bitLength) {
michael@0 1908 var pos = stream.pos;
michael@0 1909 var end = stream.end;
michael@0 1910 do {
michael@0 1911 if (pos >= end) {
michael@0 1912 stream.pos = pos;
michael@0 1913 stream.bitBuffer = bitBuffer;
michael@0 1914 stream.bitLength = bitLength;
michael@0 1915 throw InflateNoDataError;
michael@0 1916 }
michael@0 1917 bitBuffer |= bytes[pos++] << bitLength;
michael@0 1918 bitLength += 8;
michael@0 1919 } while (size > bitLength);
michael@0 1920 stream.pos = pos;
michael@0 1921 }
michael@0 1922 stream.bitBuffer = bitBuffer >>> size;
michael@0 1923 stream.bitLength = bitLength - size;
michael@0 1924 return bitBuffer & (1 << size) - 1;
michael@0 1925 }
michael@0 1926 function inflate(stream, output, literalTable, distanceTable, state) {
michael@0 1927 var pos = output.available;
michael@0 1928 var dbytes = output.data;
michael@0 1929 var sbytes = stream.bytes;
michael@0 1930 var sym = state.sym !== null ? state.sym : readCode(sbytes, stream, literalTable);
michael@0 1931 while (sym !== 256) {
michael@0 1932 if (sym < 256) {
michael@0 1933 dbytes[pos++] = sym;
michael@0 1934 } else {
michael@0 1935 state.sym = sym;
michael@0 1936 sym -= 257;
michael@0 1937 var len = state.len !== null ? state.len : state.len = lengthCodes[sym] + readBits(sbytes, stream, lengthExtraBits[sym]);
michael@0 1938 var sym2 = state.sym2 !== null ? state.sym2 : state.sym2 = readCode(sbytes, stream, distanceTable);
michael@0 1939 var distance = distanceCodes[sym2] + readBits(sbytes, stream, distanceExtraBits[sym2]);
michael@0 1940 var i = pos - distance;
michael@0 1941 while (len--)
michael@0 1942 dbytes[pos++] = dbytes[i++];
michael@0 1943 state.sym2 = null;
michael@0 1944 state.len = null;
michael@0 1945 state.sym = null;
michael@0 1946 }
michael@0 1947 output.available = pos;
michael@0 1948 sym = readCode(sbytes, stream, literalTable);
michael@0 1949 }
michael@0 1950 }
michael@0 1951 function readCode(bytes, stream, codeTable) {
michael@0 1952 var bitBuffer = stream.bitBuffer;
michael@0 1953 var bitLength = stream.bitLength;
michael@0 1954 var maxBits = codeTable.maxBits;
michael@0 1955 if (maxBits > bitLength) {
michael@0 1956 var pos = stream.pos;
michael@0 1957 var end = stream.end;
michael@0 1958 do {
michael@0 1959 if (pos >= end) {
michael@0 1960 stream.pos = pos;
michael@0 1961 stream.bitBuffer = bitBuffer;
michael@0 1962 stream.bitLength = bitLength;
michael@0 1963 throw InflateNoDataError;
michael@0 1964 }
michael@0 1965 bitBuffer |= bytes[pos++] << bitLength;
michael@0 1966 bitLength += 8;
michael@0 1967 } while (maxBits > bitLength);
michael@0 1968 stream.pos = pos;
michael@0 1969 }
michael@0 1970 var code = codeTable.codes[bitBuffer & (1 << maxBits) - 1];
michael@0 1971 var len = code >> 16;
michael@0 1972 stream.bitBuffer = bitBuffer >>> len;
michael@0 1973 stream.bitLength = bitLength - len;
michael@0 1974 return code & 65535;
michael@0 1975 }
michael@0 1976 var StreamNoDataError = {};
michael@0 1977 var Stream = function StreamClosure() {
michael@0 1978 function Stream_align() {
michael@0 1979 this.bitBuffer = this.bitLength = 0;
michael@0 1980 }
michael@0 1981 function Stream_ensure(size) {
michael@0 1982 if (this.pos + size > this.end) {
michael@0 1983 throw StreamNoDataError;
michael@0 1984 }
michael@0 1985 }
michael@0 1986 function Stream_remaining() {
michael@0 1987 return this.end - this.pos;
michael@0 1988 }
michael@0 1989 function Stream_substream(begin, end) {
michael@0 1990 var stream = new Stream(this.bytes);
michael@0 1991 stream.pos = begin;
michael@0 1992 stream.end = end;
michael@0 1993 return stream;
michael@0 1994 }
michael@0 1995 function Stream_push(data) {
michael@0 1996 var bytes = this.bytes;
michael@0 1997 var newBytesLength = this.end + data.length;
michael@0 1998 if (newBytesLength > bytes.length) {
michael@0 1999 throw 'stream buffer overfow';
michael@0 2000 }
michael@0 2001 bytes.set(data, this.end);
michael@0 2002 this.end = newBytesLength;
michael@0 2003 }
michael@0 2004 function Stream(buffer, offset, length, maxLength) {
michael@0 2005 if (offset === undefined)
michael@0 2006 offset = 0;
michael@0 2007 if (buffer.buffer instanceof ArrayBuffer) {
michael@0 2008 offset += buffer.byteOffset;
michael@0 2009 buffer = buffer.buffer;
michael@0 2010 }
michael@0 2011 if (length === undefined)
michael@0 2012 length = buffer.byteLength - offset;
michael@0 2013 if (maxLength === undefined)
michael@0 2014 maxLength = length;
michael@0 2015 var bytes = new Uint8Array(buffer, offset, maxLength);
michael@0 2016 var stream = new DataView(buffer, offset, maxLength);
michael@0 2017 stream.bytes = bytes;
michael@0 2018 stream.pos = 0;
michael@0 2019 stream.end = length;
michael@0 2020 stream.bitBuffer = 0;
michael@0 2021 stream.bitLength = 0;
michael@0 2022 stream.align = Stream_align;
michael@0 2023 stream.ensure = Stream_ensure;
michael@0 2024 stream.remaining = Stream_remaining;
michael@0 2025 stream.substream = Stream_substream;
michael@0 2026 stream.push = Stream_push;
michael@0 2027 return stream;
michael@0 2028 }
michael@0 2029 return Stream;
michael@0 2030 }();
michael@0 2031 var FORMAT_COLORMAPPED = 3;
michael@0 2032 var FORMAT_15BPP = 4;
michael@0 2033 var FORMAT_24BPP = 5;
michael@0 2034 var FACTOR_5BBP = 255 / 31;
michael@0 2035 var crcTable = [];
michael@0 2036 for (var i = 0; i < 256; i++) {
michael@0 2037 var c = i;
michael@0 2038 for (var h = 0; h < 8; h++) {
michael@0 2039 if (c & 1)
michael@0 2040 c = 3988292384 ^ c >> 1 & 2147483647;
michael@0 2041 else
michael@0 2042 c = c >> 1 & 2147483647;
michael@0 2043 }
michael@0 2044 crcTable[i] = c;
michael@0 2045 }
michael@0 2046 function crc32(data, start, end) {
michael@0 2047 var crc = -1;
michael@0 2048 for (var i = start; i < end; i++) {
michael@0 2049 var a = (crc ^ data[i]) & 255;
michael@0 2050 var b = crcTable[a];
michael@0 2051 crc = crc >>> 8 ^ b;
michael@0 2052 }
michael@0 2053 return crc ^ -1;
michael@0 2054 }
michael@0 2055 function createPngChunk(type, data) {
michael@0 2056 var chunk = new Uint8Array(12 + data.length);
michael@0 2057 var p = 0;
michael@0 2058 var len = data.length;
michael@0 2059 chunk[p] = len >> 24 & 255;
michael@0 2060 chunk[p + 1] = len >> 16 & 255;
michael@0 2061 chunk[p + 2] = len >> 8 & 255;
michael@0 2062 chunk[p + 3] = len & 255;
michael@0 2063 chunk[p + 4] = type.charCodeAt(0) & 255;
michael@0 2064 chunk[p + 5] = type.charCodeAt(1) & 255;
michael@0 2065 chunk[p + 6] = type.charCodeAt(2) & 255;
michael@0 2066 chunk[p + 7] = type.charCodeAt(3) & 255;
michael@0 2067 if (data instanceof Uint8Array)
michael@0 2068 chunk.set(data, 8);
michael@0 2069 p = 8 + len;
michael@0 2070 var crc = crc32(chunk, 4, p);
michael@0 2071 chunk[p] = crc >> 24 & 255;
michael@0 2072 chunk[p + 1] = crc >> 16 & 255;
michael@0 2073 chunk[p + 2] = crc >> 8 & 255;
michael@0 2074 chunk[p + 3] = crc & 255;
michael@0 2075 return chunk;
michael@0 2076 }
michael@0 2077 function adler32(data, start, end) {
michael@0 2078 var a = 1;
michael@0 2079 var b = 0;
michael@0 2080 for (var i = start; i < end; ++i) {
michael@0 2081 a = (a + (data[i] & 255)) % 65521;
michael@0 2082 b = (b + a) % 65521;
michael@0 2083 }
michael@0 2084 return b << 16 | a;
michael@0 2085 }
michael@0 2086 function defineBitmap(tag) {
michael@0 2087 var width = tag.width;
michael@0 2088 var height = tag.height;
michael@0 2089 var hasAlpha = tag.hasAlpha;
michael@0 2090 var plte = '';
michael@0 2091 var trns = '';
michael@0 2092 var literals;
michael@0 2093 var bmpData = tag.bmpData;
michael@0 2094 switch (tag.format) {
michael@0 2095 case FORMAT_COLORMAPPED:
michael@0 2096 var colorType = 3;
michael@0 2097 var bytesPerLine = width + 3 & ~3;
michael@0 2098 var colorTableSize = tag.colorTableSize + 1;
michael@0 2099 var paletteSize = colorTableSize * (tag.hasAlpha ? 4 : 3);
michael@0 2100 var datalen = paletteSize + bytesPerLine * height;
michael@0 2101 var stream = createInflatedStream(bmpData, datalen);
michael@0 2102 var bytes = stream.bytes;
michael@0 2103 var pos = 0;
michael@0 2104 stream.ensure(paletteSize);
michael@0 2105 if (hasAlpha) {
michael@0 2106 var palette = new Uint8Array(paletteSize / 4 * 3);
michael@0 2107 var pp = 0;
michael@0 2108 var alphaValues = new Uint8Array(paletteSize / 4);
michael@0 2109 var pa = 0;
michael@0 2110 while (pos < paletteSize) {
michael@0 2111 palette[pp++] = bytes[pos];
michael@0 2112 palette[pp++] = bytes[pos + 1];
michael@0 2113 palette[pp++] = bytes[pos + 2];
michael@0 2114 alphaValues[pa++] = bytes[pos + 3];
michael@0 2115 pos += 4;
michael@0 2116 }
michael@0 2117 plte = createPngChunk('PLTE', palette);
michael@0 2118 trns = createPngChunk('tRNS', alphaValues);
michael@0 2119 } else {
michael@0 2120 plte = createPngChunk('PLTE', bytes.subarray(pos, pos + paletteSize));
michael@0 2121 pos += paletteSize;
michael@0 2122 }
michael@0 2123 literals = new Uint8Array(width * height + height);
michael@0 2124 var pl = 0;
michael@0 2125 while (pos < datalen) {
michael@0 2126 stream.ensure(bytesPerLine);
michael@0 2127 var begin = pos;
michael@0 2128 var end = begin + width;
michael@0 2129 pl++;
michael@0 2130 literals.set(bytes.subarray(begin, end), pl);
michael@0 2131 pl += end - begin;
michael@0 2132 stream.pos = pos += bytesPerLine;
michael@0 2133 }
michael@0 2134 break;
michael@0 2135 case FORMAT_15BPP:
michael@0 2136 var colorType = 2;
michael@0 2137 var bytesPerLine = width * 2 + 3 & ~3;
michael@0 2138 var stream = createInflatedStream(bmpData, bytesPerLine * height);
michael@0 2139 var pos = 0;
michael@0 2140 literals = new Uint8Array(width * height * 3 + height);
michael@0 2141 var pl = 0;
michael@0 2142 for (var y = 0; y < height; ++y) {
michael@0 2143 pl++;
michael@0 2144 stream.ensure(bytesPerLine);
michael@0 2145 for (var x = 0; x < width; ++x) {
michael@0 2146 var word = stream.getUint16(pos);
michael@0 2147 pos += 2;
michael@0 2148 literals[pl++] = 0 | FACTOR_5BBP * (word >> 10 & 31);
michael@0 2149 literals[pl++] = 0 | FACTOR_5BBP * (word >> 5 & 31);
michael@0 2150 literals[pl++] = 0 | FACTOR_5BBP * (word & 31);
michael@0 2151 }
michael@0 2152 stream.pos = pos += bytesPerLine;
michael@0 2153 }
michael@0 2154 break;
michael@0 2155 case FORMAT_24BPP:
michael@0 2156 var padding;
michael@0 2157 if (hasAlpha) {
michael@0 2158 var colorType = 6;
michael@0 2159 padding = 0;
michael@0 2160 literals = new Uint8Array(width * height * 4 + height);
michael@0 2161 } else {
michael@0 2162 var colorType = 2;
michael@0 2163 padding = 1;
michael@0 2164 literals = new Uint8Array(width * height * 3 + height);
michael@0 2165 }
michael@0 2166 var bytesPerLine = width * 4;
michael@0 2167 var stream = createInflatedStream(bmpData, bytesPerLine * height);
michael@0 2168 var bytes = stream.bytes;
michael@0 2169 var pos = 0;
michael@0 2170 var pl = 0;
michael@0 2171 for (var y = 0; y < height; ++y) {
michael@0 2172 stream.ensure(bytesPerLine);
michael@0 2173 pl++;
michael@0 2174 for (var x = 0; x < width; ++x) {
michael@0 2175 pos += padding;
michael@0 2176 if (hasAlpha) {
michael@0 2177 var alpha = bytes[pos];
michael@0 2178 if (alpha) {
michael@0 2179 var opacity = alpha / 255;
michael@0 2180 literals[pl++] = 0 | bytes[pos + 1] / opacity;
michael@0 2181 literals[pl++] = 0 | bytes[pos + 2] / opacity;
michael@0 2182 literals[pl++] = 0 | bytes[pos + 3] / opacity;
michael@0 2183 literals[pl++] = alpha;
michael@0 2184 } else {
michael@0 2185 pl += 4;
michael@0 2186 }
michael@0 2187 } else {
michael@0 2188 literals[pl++] = bytes[pos];
michael@0 2189 literals[pl++] = bytes[pos + 1];
michael@0 2190 literals[pl++] = bytes[pos + 2];
michael@0 2191 }
michael@0 2192 pos += 4 - padding;
michael@0 2193 }
michael@0 2194 stream.pos = pos;
michael@0 2195 }
michael@0 2196 break;
michael@0 2197 default:
michael@0 2198 fail('invalid format', 'bitmap');
michael@0 2199 }
michael@0 2200 var ihdr = new Uint8Array([
michael@0 2201 width >> 24 & 255,
michael@0 2202 width >> 16 & 255,
michael@0 2203 width >> 8 & 255,
michael@0 2204 width & 255,
michael@0 2205 height >> 24 & 255,
michael@0 2206 height >> 16 & 255,
michael@0 2207 height >> 8 & 255,
michael@0 2208 height & 255,
michael@0 2209 8,
michael@0 2210 colorType,
michael@0 2211 0,
michael@0 2212 0,
michael@0 2213 0
michael@0 2214 ]);
michael@0 2215 var len = literals.length;
michael@0 2216 var maxBlockLength = 65535;
michael@0 2217 var idat = new Uint8Array(2 + len + Math.ceil(len / maxBlockLength) * 5 + 4);
michael@0 2218 var pi = 0;
michael@0 2219 idat[pi++] = 120;
michael@0 2220 idat[pi++] = 156;
michael@0 2221 var pos = 0;
michael@0 2222 while (len > maxBlockLength) {
michael@0 2223 idat[pi++] = 0;
michael@0 2224 idat[pi++] = 255;
michael@0 2225 idat[pi++] = 255;
michael@0 2226 idat[pi++] = 0;
michael@0 2227 idat[pi++] = 0;
michael@0 2228 idat.set(literals.subarray(pos, pos + maxBlockLength), pi);
michael@0 2229 pi += maxBlockLength;
michael@0 2230 pos += maxBlockLength;
michael@0 2231 len -= maxBlockLength;
michael@0 2232 }
michael@0 2233 idat[pi++] = 1;
michael@0 2234 idat[pi++] = len & 255;
michael@0 2235 idat[pi++] = len >> 8 & 255;
michael@0 2236 idat[pi++] = ~len & 65535 & 255;
michael@0 2237 idat[pi++] = (~len & 65535) >> 8 & 255;
michael@0 2238 idat.set(literals.subarray(pos), pi);
michael@0 2239 pi += literals.length - pos;
michael@0 2240 var adler = adler32(literals, 0, literals.length);
michael@0 2241 idat[pi++] = adler >> 24 & 255;
michael@0 2242 idat[pi++] = adler >> 16 & 255;
michael@0 2243 idat[pi++] = adler >> 8 & 255;
michael@0 2244 idat[pi++] = adler & 255;
michael@0 2245 var chunks = [
michael@0 2246 new Uint8Array([
michael@0 2247 137,
michael@0 2248 80,
michael@0 2249 78,
michael@0 2250 71,
michael@0 2251 13,
michael@0 2252 10,
michael@0 2253 26,
michael@0 2254 10
michael@0 2255 ]),
michael@0 2256 createPngChunk('IHDR', ihdr),
michael@0 2257 plte,
michael@0 2258 trns,
michael@0 2259 createPngChunk('IDAT', idat),
michael@0 2260 createPngChunk('IEND', '')
michael@0 2261 ];
michael@0 2262 return {
michael@0 2263 type: 'image',
michael@0 2264 id: tag.id,
michael@0 2265 width: width,
michael@0 2266 height: height,
michael@0 2267 mimeType: 'image/png',
michael@0 2268 data: new Blob(chunks, {
michael@0 2269 type: 'image/png'
michael@0 2270 })
michael@0 2271 };
michael@0 2272 }
michael@0 2273 function defineButton(tag, dictionary) {
michael@0 2274 var characters = tag.characters;
michael@0 2275 var states = {
michael@0 2276 up: {},
michael@0 2277 over: {},
michael@0 2278 down: {},
michael@0 2279 hitTest: {}
michael@0 2280 };
michael@0 2281 var i = 0, character;
michael@0 2282 while (character = characters[i++]) {
michael@0 2283 if (character.eob)
michael@0 2284 break;
michael@0 2285 var characterItem = dictionary[character.symbolId];
michael@0 2286 var entry = {
michael@0 2287 symbolId: characterItem.id,
michael@0 2288 hasMatrix: !(!character.matrix),
michael@0 2289 matrix: character.matrix
michael@0 2290 };
michael@0 2291 if (character.stateUp)
michael@0 2292 states.up[character.depth] = entry;
michael@0 2293 if (character.stateOver)
michael@0 2294 states.over[character.depth] = entry;
michael@0 2295 if (character.stateDown)
michael@0 2296 states.down[character.depth] = entry;
michael@0 2297 if (character.stateHitTest)
michael@0 2298 states.hitTest[character.depth] = entry;
michael@0 2299 }
michael@0 2300 var button = {
michael@0 2301 type: 'button',
michael@0 2302 id: tag.id,
michael@0 2303 buttonActions: tag.buttonActions,
michael@0 2304 states: states
michael@0 2305 };
michael@0 2306 return button;
michael@0 2307 }
michael@0 2308 var nextFontId = 1;
michael@0 2309 function maxPower2(num) {
michael@0 2310 var maxPower = 0;
michael@0 2311 var val = num;
michael@0 2312 while (val >= 2) {
michael@0 2313 val /= 2;
michael@0 2314 ++maxPower;
michael@0 2315 }
michael@0 2316 return pow(2, maxPower);
michael@0 2317 }
michael@0 2318 function toString16(val) {
michael@0 2319 return fromCharCode(val >> 8 & 255, val & 255);
michael@0 2320 }
michael@0 2321 function toString32(val) {
michael@0 2322 return toString16(val >> 16) + toString16(val);
michael@0 2323 }
michael@0 2324 function defineFont(tag, dictionary) {
michael@0 2325 var tables = {};
michael@0 2326 var codes = [];
michael@0 2327 var glyphIndex = {};
michael@0 2328 var ranges = [];
michael@0 2329 var glyphs = tag.glyphs;
michael@0 2330 var glyphCount = glyphs.length;
michael@0 2331 if (tag.codes) {
michael@0 2332 codes = codes.concat(tag.codes);
michael@0 2333 for (var i = 0, code; code = codes[i]; ++i)
michael@0 2334 glyphIndex[code] = i;
michael@0 2335 codes.sort(function (a, b) {
michael@0 2336 return a - b;
michael@0 2337 });
michael@0 2338 var i = 0;
michael@0 2339 var code;
michael@0 2340 while (code = codes[i++]) {
michael@0 2341 var start = code;
michael@0 2342 var end = start;
michael@0 2343 var indices = [
michael@0 2344 i - 1
michael@0 2345 ];
michael@0 2346 while ((code = codes[i]) && end + 1 === code) {
michael@0 2347 ++end;
michael@0 2348 indices.push(i);
michael@0 2349 ++i;
michael@0 2350 }
michael@0 2351 ranges.push([
michael@0 2352 start,
michael@0 2353 end,
michael@0 2354 indices
michael@0 2355 ]);
michael@0 2356 }
michael@0 2357 } else {
michael@0 2358 var indices = [];
michael@0 2359 var UAC_OFFSET = 57344;
michael@0 2360 for (var i = 0; i < glyphCount; i++) {
michael@0 2361 var code = UAC_OFFSET + i;
michael@0 2362 codes.push(code);
michael@0 2363 glyphIndex[code] = i;
michael@0 2364 indices.push(i);
michael@0 2365 }
michael@0 2366 ranges.push([
michael@0 2367 UAC_OFFSET,
michael@0 2368 UAC_OFFSET + glyphCount - 1,
michael@0 2369 indices
michael@0 2370 ]);
michael@0 2371 }
michael@0 2372 var resolution = tag.resolution || 1;
michael@0 2373 var ascent = Math.ceil(tag.ascent / resolution) || 1024;
michael@0 2374 var descent = -Math.ceil(tag.descent / resolution) | 0;
michael@0 2375 var leading = tag.leading / resolution | 0;
michael@0 2376 tables['OS/2'] = '\0\x01\0\0' + toString16(tag.bold ? 700 : 400) + '\0\x05' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0\0\0\0\0\0\0\0\0' + '\0\0\0\0' + '\0\0\0\0' + '\0\0\0\0' + '\0\0\0\0' + 'ALF ' + toString16((tag.italic ? 1 : 0) | (tag.bold ? 32 : 0)) + toString16(codes[0]) + toString16(codes[codes.length - 1]) + toString16(ascent) + toString16(descent) + toString16(leading) + toString16(ascent) + toString16(-descent) + '\0\0\0\0' + '\0\0\0\0';
michael@0 2377 ;
michael@0 2378 var startCount = '';
michael@0 2379 var endCount = '';
michael@0 2380 var idDelta = '';
michael@0 2381 var idRangeOffset = '';
michael@0 2382 var i = 0;
michael@0 2383 var range;
michael@0 2384 while (range = ranges[i++]) {
michael@0 2385 var start = range[0];
michael@0 2386 var end = range[1];
michael@0 2387 var code = range[2][0];
michael@0 2388 startCount += toString16(start);
michael@0 2389 endCount += toString16(end);
michael@0 2390 idDelta += toString16(code - start + 1 & 65535);
michael@0 2391 idRangeOffset += toString16(0);
michael@0 2392 }
michael@0 2393 endCount += '\xff\xff';
michael@0 2394 startCount += '\xff\xff';
michael@0 2395 idDelta += '\0\x01';
michael@0 2396 idRangeOffset += '\0\0';
michael@0 2397 var segCount = ranges.length + 1;
michael@0 2398 var searchRange = maxPower2(segCount) * 2;
michael@0 2399 var rangeShift = 2 * segCount - searchRange;
michael@0 2400 var format314 = '\0\0' + toString16(segCount * 2) + toString16(searchRange) + toString16(logE(segCount) / logE(2)) + toString16(rangeShift) + endCount + '\0\0' + startCount + idDelta + idRangeOffset;
michael@0 2401 ;
michael@0 2402 tables['cmap'] = '\0\0\0\x01\0\x03\0\x01\0\0\0\f\0\x04' + toString16(format314.length + 4) + format314;
michael@0 2403 ;
michael@0 2404 var glyf = '\0\x01\0\0\0\0\0\0\0\0\0\0\0\x001\0';
michael@0 2405 var loca = '\0\0';
michael@0 2406 var offset = 16;
michael@0 2407 var maxPoints = 0;
michael@0 2408 var xMins = [];
michael@0 2409 var xMaxs = [];
michael@0 2410 var yMins = [];
michael@0 2411 var yMaxs = [];
michael@0 2412 var maxContours = 0;
michael@0 2413 var i = 0;
michael@0 2414 var code;
michael@0 2415 while (code = codes[i++]) {
michael@0 2416 var glyph = glyphs[glyphIndex[code]];
michael@0 2417 var records = glyph.records;
michael@0 2418 var numberOfContours = 1;
michael@0 2419 var endPoint = 0;
michael@0 2420 var endPtsOfContours = '';
michael@0 2421 var flags = '';
michael@0 2422 var xCoordinates = '';
michael@0 2423 var yCoordinates = '';
michael@0 2424 var x = 0;
michael@0 2425 var y = 0;
michael@0 2426 var xMin = 1024;
michael@0 2427 var xMax = -1024;
michael@0 2428 var yMin = 1024;
michael@0 2429 var yMax = -1024;
michael@0 2430 for (var j = 0, record; record = records[j]; ++j) {
michael@0 2431 if (record.type) {
michael@0 2432 if (record.isStraight) {
michael@0 2433 if (record.isGeneral) {
michael@0 2434 flags += '\x01';
michael@0 2435 var dx = record.deltaX / resolution;
michael@0 2436 var dy = -record.deltaY / resolution;
michael@0 2437 xCoordinates += toString16(dx);
michael@0 2438 yCoordinates += toString16(dy);
michael@0 2439 x += dx;
michael@0 2440 y += dy;
michael@0 2441 } else if (record.isVertical) {
michael@0 2442 flags += '\x11';
michael@0 2443 var dy = -record.deltaY / resolution;
michael@0 2444 yCoordinates += toString16(dy);
michael@0 2445 y += dy;
michael@0 2446 } else {
michael@0 2447 flags += '!';
michael@0 2448 var dx = record.deltaX / resolution;
michael@0 2449 xCoordinates += toString16(dx);
michael@0 2450 x += dx;
michael@0 2451 }
michael@0 2452 } else {
michael@0 2453 flags += '\0';
michael@0 2454 var cx = record.controlDeltaX / resolution;
michael@0 2455 var cy = -record.controlDeltaY / resolution;
michael@0 2456 xCoordinates += toString16(cx);
michael@0 2457 yCoordinates += toString16(cy);
michael@0 2458 flags += '\x01';
michael@0 2459 var dx = record.anchorDeltaX / resolution;
michael@0 2460 var dy = -record.anchorDeltaY / resolution;
michael@0 2461 xCoordinates += toString16(dx);
michael@0 2462 yCoordinates += toString16(dy);
michael@0 2463 ++endPoint;
michael@0 2464 x += cx + dx;
michael@0 2465 y += cy + dy;
michael@0 2466 }
michael@0 2467 if (x < xMin)
michael@0 2468 xMin = x;
michael@0 2469 if (x > xMax)
michael@0 2470 xMax = x;
michael@0 2471 if (y < yMin)
michael@0 2472 yMin = y;
michael@0 2473 if (y > yMax)
michael@0 2474 yMax = y;
michael@0 2475 ++endPoint;
michael@0 2476 } else {
michael@0 2477 if (record.eos)
michael@0 2478 break;
michael@0 2479 if (record.move) {
michael@0 2480 if (endPoint) {
michael@0 2481 ++numberOfContours;
michael@0 2482 endPtsOfContours += toString16(endPoint - 1);
michael@0 2483 }
michael@0 2484 flags += '\x01';
michael@0 2485 var moveX = record.moveX / resolution;
michael@0 2486 var moveY = -record.moveY / resolution;
michael@0 2487 var dx = moveX - x;
michael@0 2488 var dy = moveY - y;
michael@0 2489 xCoordinates += toString16(dx);
michael@0 2490 yCoordinates += toString16(dy);
michael@0 2491 x = moveX;
michael@0 2492 y = moveY;
michael@0 2493 if (endPoint > maxPoints)
michael@0 2494 maxPoints = endPoint;
michael@0 2495 if (x < xMin)
michael@0 2496 xMin = x;
michael@0 2497 if (x > xMax)
michael@0 2498 xMax = x;
michael@0 2499 if (y < yMin)
michael@0 2500 yMin = y;
michael@0 2501 if (y > yMax)
michael@0 2502 yMax = y;
michael@0 2503 ++endPoint;
michael@0 2504 }
michael@0 2505 }
michael@0 2506 }
michael@0 2507 endPtsOfContours += toString16((endPoint || 1) - 1);
michael@0 2508 if (!j) {
michael@0 2509 xMin = xMax = yMin = yMax = 0;
michael@0 2510 flags += '1';
michael@0 2511 }
michael@0 2512 var entry = toString16(numberOfContours) + toString16(xMin) + toString16(yMin) + toString16(xMax) + toString16(yMax) + endPtsOfContours + '\0\0' + flags + xCoordinates + yCoordinates;
michael@0 2513 ;
michael@0 2514 if (entry.length & 1)
michael@0 2515 entry += '\0';
michael@0 2516 glyf += entry;
michael@0 2517 loca += toString16(offset / 2);
michael@0 2518 offset += entry.length;
michael@0 2519 xMins.push(xMin);
michael@0 2520 xMaxs.push(xMax);
michael@0 2521 yMins.push(yMin);
michael@0 2522 yMaxs.push(yMax);
michael@0 2523 if (numberOfContours > maxContours)
michael@0 2524 maxContours = numberOfContours;
michael@0 2525 if (endPoint > maxPoints)
michael@0 2526 maxPoints = endPoint;
michael@0 2527 }
michael@0 2528 loca += toString16(offset / 2);
michael@0 2529 tables['glyf'] = glyf;
michael@0 2530 tables['head'] = '\0\x01\0\0\0\x01\0\0\0\0\0\0_\x0f<\xf5\0\v\x04\0\0\0\0\0' + toString32(Date.now()) + '\0\0\0\0' + toString32(Date.now()) + toString16(min.apply(null, xMins)) + toString16(min.apply(null, yMins)) + toString16(max.apply(null, xMaxs)) + toString16(max.apply(null, yMaxs)) + toString16((tag.italic ? 2 : 0) | (tag.bold ? 1 : 0)) + '\0\b' + '\0\x02' + '\0\0' + '\0\0';
michael@0 2531 ;
michael@0 2532 var advance = tag.advance;
michael@0 2533 tables['hhea'] = '\0\x01\0\0' + toString16(ascent) + toString16(descent) + toString16(leading) + toString16(advance ? max.apply(null, advance) : 1024) + '\0\0' + '\0\0' + '\x03\xb8' + '\0\x01' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + toString16(glyphCount + 1);
michael@0 2534 ;
michael@0 2535 var hmtx = '\0\0\0\0';
michael@0 2536 for (var i = 0; i < glyphCount; ++i)
michael@0 2537 hmtx += toString16(advance ? advance[i] / resolution : 1024) + '\0\0';
michael@0 2538 tables['hmtx'] = hmtx;
michael@0 2539 if (tag.kerning) {
michael@0 2540 var kerning = tag.kerning;
michael@0 2541 var nPairs = kerning.length;
michael@0 2542 var searchRange = maxPower2(nPairs) * 2;
michael@0 2543 var kern = '\0\0\0\x01\0\0' + toString16(14 + nPairs * 6) + '\0\x01' + toString16(nPairs) + toString16(searchRange) + toString16(logE(nPairs) / logE(2)) + toString16(2 * nPairs - searchRange);
michael@0 2544 ;
michael@0 2545 var i = 0;
michael@0 2546 var record;
michael@0 2547 while (record = kerning[i++]) {
michael@0 2548 kern += toString16(glyphIndex[record.code1]) + toString16(glyphIndex[record.code2]) + toString16(record.adjustment);
michael@0 2549 ;
michael@0 2550 }
michael@0 2551 tables['kern'] = kern;
michael@0 2552 }
michael@0 2553 tables['loca'] = loca;
michael@0 2554 tables['maxp'] = '\0\x01\0\0' + toString16(glyphCount + 1) + toString16(maxPoints) + toString16(maxContours) + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0';
michael@0 2555 ;
michael@0 2556 var uniqueId = 'swf-font-' + nextFontId++;
michael@0 2557 var fontName = tag.name || uniqueId;
michael@0 2558 var psName = fontName.replace(/ /g, '');
michael@0 2559 var strings = [
michael@0 2560 tag.copyright || 'Original licence',
michael@0 2561 fontName,
michael@0 2562 'Unknown',
michael@0 2563 uniqueId,
michael@0 2564 fontName,
michael@0 2565 '1.0',
michael@0 2566 psName,
michael@0 2567 'Unknown',
michael@0 2568 'Unknown',
michael@0 2569 'Unknown'
michael@0 2570 ];
michael@0 2571 var count = strings.length;
michael@0 2572 var name = '\0\0' + toString16(count) + toString16(count * 12 + 6);
michael@0 2573 var offset = 0;
michael@0 2574 var i = 0;
michael@0 2575 var str;
michael@0 2576 while (str = strings[i++]) {
michael@0 2577 name += '\0\x01\0\0\0\0' + toString16(i - 1) + toString16(str.length) + toString16(offset);
michael@0 2578 offset += str.length;
michael@0 2579 }
michael@0 2580 tables['name'] = name + strings.join('');
michael@0 2581 tables['post'] = '\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0';
michael@0 2582 ;
michael@0 2583 var names = keys(tables);
michael@0 2584 var numTables = names.length;
michael@0 2585 var header = '\0\x01\0\0' + toString16(numTables) + '\0\x80' + '\0\x03' + '\0 ';
michael@0 2586 ;
michael@0 2587 var data = '';
michael@0 2588 var offset = numTables * 16 + header.length;
michael@0 2589 var i = 0;
michael@0 2590 var name;
michael@0 2591 while (name = names[i++]) {
michael@0 2592 var table = tables[name];
michael@0 2593 var length = table.length;
michael@0 2594 header += name + '\0\0\0\0' + toString32(offset) + toString32(length);
michael@0 2595 ;
michael@0 2596 while (length & 3) {
michael@0 2597 table += '\0';
michael@0 2598 ++length;
michael@0 2599 }
michael@0 2600 data += table;
michael@0 2601 while (offset & 3)
michael@0 2602 ++offset;
michael@0 2603 offset += length;
michael@0 2604 }
michael@0 2605 var otf = header + data;
michael@0 2606 var unitPerEm = 1024;
michael@0 2607 var metrics = {
michael@0 2608 ascent: ascent / unitPerEm,
michael@0 2609 descent: -descent / unitPerEm,
michael@0 2610 leading: leading / unitPerEm
michael@0 2611 };
michael@0 2612 return {
michael@0 2613 type: 'font',
michael@0 2614 id: tag.id,
michael@0 2615 name: fontName,
michael@0 2616 uniqueName: psName + uniqueId,
michael@0 2617 codes: codes,
michael@0 2618 metrics: metrics,
michael@0 2619 bold: tag.bold === 1,
michael@0 2620 italic: tag.italic === 1,
michael@0 2621 data: otf
michael@0 2622 };
michael@0 2623 }
michael@0 2624 function getUint16(buff, pos) {
michael@0 2625 return buff[pos] << 8 | buff[pos + 1];
michael@0 2626 }
michael@0 2627 function parseJpegChunks(imgDef, bytes) {
michael@0 2628 var i = 0;
michael@0 2629 var n = bytes.length;
michael@0 2630 var chunks = [];
michael@0 2631 var code;
michael@0 2632 do {
michael@0 2633 var begin = i;
michael@0 2634 while (i < n && bytes[i] !== 255)
michael@0 2635 ++i;
michael@0 2636 while (i < n && bytes[i] === 255)
michael@0 2637 ++i;
michael@0 2638 code = bytes[i++];
michael@0 2639 if (code === 218) {
michael@0 2640 i = n;
michael@0 2641 } else if (code === 217) {
michael@0 2642 i += 2;
michael@0 2643 continue;
michael@0 2644 } else if (code < 208 || code > 216) {
michael@0 2645 var length = getUint16(bytes, i);
michael@0 2646 if (code >= 192 && code <= 195) {
michael@0 2647 imgDef.height = getUint16(bytes, i + 3);
michael@0 2648 imgDef.width = getUint16(bytes, i + 5);
michael@0 2649 }
michael@0 2650 i += length;
michael@0 2651 }
michael@0 2652 chunks.push(bytes.subarray(begin, i));
michael@0 2653 } while (i < n);
michael@0 2654 return chunks;
michael@0 2655 }
michael@0 2656 function defineImage(tag, dictionary) {
michael@0 2657 var img = {
michael@0 2658 type: 'image',
michael@0 2659 id: tag.id,
michael@0 2660 mimeType: tag.mimeType
michael@0 2661 };
michael@0 2662 var imgData = tag.imgData;
michael@0 2663 var chunks;
michael@0 2664 if (tag.mimeType === 'image/jpeg') {
michael@0 2665 chunks = parseJpegChunks(img, imgData);
michael@0 2666 var alphaData = tag.alphaData;
michael@0 2667 if (alphaData) {
michael@0 2668 img.mask = createInflatedStream(alphaData, img.width * img.height).bytes;
michael@0 2669 }
michael@0 2670 if (tag.incomplete) {
michael@0 2671 var tables = dictionary[0];
michael@0 2672 var header = tables.data;
michael@0 2673 if (header && header.size) {
michael@0 2674 chunks[0] = chunks[0].subarray(2);
michael@0 2675 chunks.unshift(header.slice(0, header.size - 2));
michael@0 2676 }
michael@0 2677 }
michael@0 2678 } else {
michael@0 2679 chunks = [
michael@0 2680 imgData
michael@0 2681 ];
michael@0 2682 }
michael@0 2683 img.data = new Blob(chunks, {
michael@0 2684 type: tag.mimeType
michael@0 2685 });
michael@0 2686 return img;
michael@0 2687 }
michael@0 2688 function defineLabel(tag, dictionary) {
michael@0 2689 var records = tag.records;
michael@0 2690 var m = tag.matrix;
michael@0 2691 var cmds = [
michael@0 2692 'c.save()',
michael@0 2693 'c.transform(' + [
michael@0 2694 m.a,
michael@0 2695 m.b,
michael@0 2696 m.c,
michael@0 2697 m.d,
michael@0 2698 m.tx / 20,
michael@0 2699 m.ty / 20
michael@0 2700 ].join(',') + ')',
michael@0 2701 'c.scale(0.05, 0.05)'
michael@0 2702 ];
michael@0 2703 var dependencies = [];
michael@0 2704 var x = 0;
michael@0 2705 var y = 0;
michael@0 2706 var i = 0;
michael@0 2707 var record;
michael@0 2708 var codes;
michael@0 2709 while (record = records[i++]) {
michael@0 2710 if (record.eot)
michael@0 2711 break;
michael@0 2712 if (record.hasFont) {
michael@0 2713 var font = dictionary[record.fontId];
michael@0 2714 codes = font.codes;
michael@0 2715 cmds.push('c.font="' + record.fontHeight + 'px \'' + font.uniqueName + '\'"');
michael@0 2716 dependencies.push(font.id);
michael@0 2717 }
michael@0 2718 if (record.hasColor) {
michael@0 2719 cmds.push('ct.setFillStyle(c,"' + rgbaObjToStr(record.color) + '")');
michael@0 2720 cmds.push('ct.setAlpha(c)');
michael@0 2721 } else {
michael@0 2722 cmds.push('ct.setAlpha(c,true)');
michael@0 2723 }
michael@0 2724 if (record.hasMoveX)
michael@0 2725 x = record.moveX;
michael@0 2726 if (record.hasMoveY)
michael@0 2727 y = record.moveY;
michael@0 2728 var entries = record.entries;
michael@0 2729 var j = 0;
michael@0 2730 var entry;
michael@0 2731 while (entry = entries[j++]) {
michael@0 2732 var code = codes[entry.glyphIndex];
michael@0 2733 var text = code >= 32 && code != 34 && code != 92 ? fromCharCode(code) : '\\u' + (code + 65536).toString(16).substring(1);
michael@0 2734 cmds.push('c.fillText("' + text + '",' + x + ',' + y + ')');
michael@0 2735 x += entry.advance;
michael@0 2736 }
michael@0 2737 }
michael@0 2738 cmds.push('c.restore()');
michael@0 2739 var label = {
michael@0 2740 type: 'label',
michael@0 2741 id: tag.id,
michael@0 2742 bbox: tag.bbox,
michael@0 2743 data: cmds.join('\n')
michael@0 2744 };
michael@0 2745 if (dependencies.length)
michael@0 2746 label.require = dependencies;
michael@0 2747 return label;
michael@0 2748 }
michael@0 2749 var GRAPHICS_FILL_CLIPPED_BITMAP = 65;
michael@0 2750 var GRAPHICS_FILL_FOCAL_RADIAL_GRADIENT = 19;
michael@0 2751 var GRAPHICS_FILL_LINEAR_GRADIENT = 16;
michael@0 2752 var GRAPHICS_FILL_NONSMOOTHED_CLIPPED_BITMAP = 67;
michael@0 2753 var GRAPHICS_FILL_NONSMOOTHED_REPEATING_BITMAP = 66;
michael@0 2754 var GRAPHICS_FILL_RADIAL_GRADIENT = 18;
michael@0 2755 var GRAPHICS_FILL_REPEATING_BITMAP = 64;
michael@0 2756 var GRAPHICS_FILL_SOLID = 0;
michael@0 2757 function applySegmentToStyles(segment, styles, linePaths, fillPaths, isMorph) {
michael@0 2758 if (!segment) {
michael@0 2759 return;
michael@0 2760 }
michael@0 2761 var commands = segment.commands;
michael@0 2762 var data = segment.data;
michael@0 2763 var morphData = segment.morphData;
michael@0 2764 if (morphData) {
michael@0 2765 }
michael@0 2766 var path;
michael@0 2767 var targetSegment;
michael@0 2768 var command;
michael@0 2769 var i;
michael@0 2770 if (styles.fill0) {
michael@0 2771 path = fillPaths[styles.fill0 - 1];
michael@0 2772 if (!(styles.fill1 || styles.line)) {
michael@0 2773 targetSegment = path.head();
michael@0 2774 targetSegment.commands = [];
michael@0 2775 targetSegment.data = [];
michael@0 2776 targetSegment.morphData = isMorph ? [] : null;
michael@0 2777 } else {
michael@0 2778 targetSegment = path.addSegment([], [], isMorph ? [] : null);
michael@0 2779 }
michael@0 2780 var targetCommands = targetSegment.commands;
michael@0 2781 var targetData = targetSegment.data;
michael@0 2782 var targetMorphData = targetSegment.morphData;
michael@0 2783 targetCommands.push(SHAPE_MOVE_TO);
michael@0 2784 var j = data.length - 2;
michael@0 2785 targetData.push(data[j], data[j + 1]);
michael@0 2786 if (isMorph) {
michael@0 2787 targetMorphData.push(morphData[j], morphData[j + 1]);
michael@0 2788 }
michael@0 2789 for (i = commands.length; i-- > 1; j -= 2) {
michael@0 2790 command = commands[i];
michael@0 2791 targetCommands.push(command);
michael@0 2792 targetData.push(data[j - 2], data[j - 1]);
michael@0 2793 if (isMorph) {
michael@0 2794 targetMorphData.push(morphData[j - 2], morphData[j - 1]);
michael@0 2795 }
michael@0 2796 if (command === SHAPE_CURVE_TO) {
michael@0 2797 targetData.push(data[j - 4], data[j - 3]);
michael@0 2798 if (isMorph) {
michael@0 2799 targetMorphData.push(morphData[j - 4], morphData[j - 3]);
michael@0 2800 }
michael@0 2801 j -= 2;
michael@0 2802 }
michael@0 2803 }
michael@0 2804 if (isMorph) {
michael@0 2805 }
michael@0 2806 }
michael@0 2807 if (styles.line && styles.fill1) {
michael@0 2808 path = linePaths[styles.line - 1];
michael@0 2809 path.addSegment(commands, data, morphData);
michael@0 2810 }
michael@0 2811 }
michael@0 2812 function convertRecordsToStyledPaths(records, fillPaths, linePaths, dictionary, dependencies, recordsMorph, transferables) {
michael@0 2813 var isMorph = recordsMorph !== null;
michael@0 2814 var styles = {
michael@0 2815 fill0: 0,
michael@0 2816 fill1: 0,
michael@0 2817 line: 0
michael@0 2818 };
michael@0 2819 var segment = null;
michael@0 2820 var allPaths;
michael@0 2821 var defaultPath;
michael@0 2822 var numRecords = records.length - 1;
michael@0 2823 var x = 0;
michael@0 2824 var y = 0;
michael@0 2825 var morphX = 0;
michael@0 2826 var morphY = 0;
michael@0 2827 var path;
michael@0 2828 for (var i = 0, j = 0; i < numRecords; i++) {
michael@0 2829 var record = records[i];
michael@0 2830 var morphRecord;
michael@0 2831 if (isMorph) {
michael@0 2832 morphRecord = recordsMorph[j++];
michael@0 2833 }
michael@0 2834 if (record.type === 0) {
michael@0 2835 if (segment) {
michael@0 2836 applySegmentToStyles(segment, styles, linePaths, fillPaths, isMorph);
michael@0 2837 }
michael@0 2838 if (record.hasNewStyles) {
michael@0 2839 if (!allPaths) {
michael@0 2840 allPaths = [];
michael@0 2841 }
michael@0 2842 push.apply(allPaths, fillPaths);
michael@0 2843 fillPaths = createPathsList(record.fillStyles, false, dictionary, dependencies);
michael@0 2844 push.apply(allPaths, linePaths);
michael@0 2845 linePaths = createPathsList(record.lineStyles, true, dictionary, dependencies);
michael@0 2846 if (defaultPath) {
michael@0 2847 allPaths.push(defaultPath);
michael@0 2848 defaultPath = null;
michael@0 2849 }
michael@0 2850 styles = {
michael@0 2851 fill0: 0,
michael@0 2852 fill1: 0,
michael@0 2853 line: 0
michael@0 2854 };
michael@0 2855 }
michael@0 2856 if (record.hasFillStyle0) {
michael@0 2857 styles.fill0 = record.fillStyle0;
michael@0 2858 }
michael@0 2859 if (record.hasFillStyle1) {
michael@0 2860 styles.fill1 = record.fillStyle1;
michael@0 2861 }
michael@0 2862 if (record.hasLineStyle) {
michael@0 2863 styles.line = record.lineStyle;
michael@0 2864 }
michael@0 2865 if (styles.fill1) {
michael@0 2866 path = fillPaths[styles.fill1 - 1];
michael@0 2867 } else if (styles.line) {
michael@0 2868 path = linePaths[styles.line - 1];
michael@0 2869 } else if (styles.fill0) {
michael@0 2870 path = fillPaths[styles.fill0 - 1];
michael@0 2871 }
michael@0 2872 if (record.move) {
michael@0 2873 x = record.moveX | 0;
michael@0 2874 y = record.moveY | 0;
michael@0 2875 }
michael@0 2876 if (path) {
michael@0 2877 segment = path.addSegment([], [], isMorph ? [] : null);
michael@0 2878 segment.commands.push(SHAPE_MOVE_TO);
michael@0 2879 segment.data.push(x, y);
michael@0 2880 if (isMorph) {
michael@0 2881 if (morphRecord.type === 0) {
michael@0 2882 morphX = morphRecord.moveX | 0;
michael@0 2883 morphY = morphRecord.moveY | 0;
michael@0 2884 } else {
michael@0 2885 morphX = x;
michael@0 2886 morphY = y;
michael@0 2887 j--;
michael@0 2888 }
michael@0 2889 segment.morphData.push(morphX, morphY);
michael@0 2890 }
michael@0 2891 }
michael@0 2892 } else {
michael@0 2893 if (!segment) {
michael@0 2894 if (!defaultPath) {
michael@0 2895 var style = {
michael@0 2896 color: {
michael@0 2897 red: 0,
michael@0 2898 green: 0,
michael@0 2899 blue: 0,
michael@0 2900 alpha: 255
michael@0 2901 },
michael@0 2902 width: 20
michael@0 2903 };
michael@0 2904 defaultPath = new SegmentedPath(null, processStyle(style, true));
michael@0 2905 }
michael@0 2906 segment = defaultPath.addSegment([], [], isMorph ? [] : null);
michael@0 2907 segment.commands.push(SHAPE_MOVE_TO);
michael@0 2908 segment.data.push(x, y);
michael@0 2909 if (isMorph) {
michael@0 2910 segment.morphData.push(morphX, morphY);
michael@0 2911 }
michael@0 2912 }
michael@0 2913 if (isMorph) {
michael@0 2914 while (morphRecord && morphRecord.type === 0) {
michael@0 2915 morphRecord = recordsMorph[j++];
michael@0 2916 }
michael@0 2917 if (!morphRecord) {
michael@0 2918 morphRecord = record;
michael@0 2919 }
michael@0 2920 }
michael@0 2921 if (record.isStraight && (!isMorph || morphRecord.isStraight)) {
michael@0 2922 x += record.deltaX | 0;
michael@0 2923 y += record.deltaY | 0;
michael@0 2924 segment.commands.push(SHAPE_LINE_TO);
michael@0 2925 segment.data.push(x, y);
michael@0 2926 if (isMorph) {
michael@0 2927 morphX += morphRecord.deltaX | 0;
michael@0 2928 morphY += morphRecord.deltaY | 0;
michael@0 2929 segment.morphData.push(morphX, morphY);
michael@0 2930 }
michael@0 2931 } else {
michael@0 2932 var cx, cy;
michael@0 2933 var deltaX, deltaY;
michael@0 2934 if (!record.isStraight) {
michael@0 2935 cx = x + record.controlDeltaX | 0;
michael@0 2936 cy = y + record.controlDeltaY | 0;
michael@0 2937 x = cx + record.anchorDeltaX | 0;
michael@0 2938 y = cy + record.anchorDeltaY | 0;
michael@0 2939 } else {
michael@0 2940 deltaX = record.deltaX | 0;
michael@0 2941 deltaY = record.deltaY | 0;
michael@0 2942 cx = x + (deltaX >> 1);
michael@0 2943 cy = y + (deltaY >> 1);
michael@0 2944 x += deltaX;
michael@0 2945 y += deltaY;
michael@0 2946 }
michael@0 2947 segment.commands.push(SHAPE_CURVE_TO);
michael@0 2948 segment.data.push(cx, cy, x, y);
michael@0 2949 if (isMorph) {
michael@0 2950 if (!morphRecord.isStraight) {
michael@0 2951 cx = morphX + morphRecord.controlDeltaX | 0;
michael@0 2952 cy = morphY + morphRecord.controlDeltaY | 0;
michael@0 2953 morphX = cx + morphRecord.anchorDeltaX | 0;
michael@0 2954 morphY = cy + morphRecord.anchorDeltaY | 0;
michael@0 2955 } else {
michael@0 2956 deltaX = morphRecord.deltaX | 0;
michael@0 2957 deltaY = morphRecord.deltaY | 0;
michael@0 2958 cx = morphX + (deltaX >> 1);
michael@0 2959 cy = morphY + (deltaY >> 1);
michael@0 2960 morphX += deltaX;
michael@0 2961 morphY += deltaY;
michael@0 2962 }
michael@0 2963 segment.morphData.push(cx, cy, morphX, morphY);
michael@0 2964 }
michael@0 2965 }
michael@0 2966 }
michael@0 2967 }
michael@0 2968 applySegmentToStyles(segment, styles, linePaths, fillPaths, isMorph);
michael@0 2969 if (allPaths) {
michael@0 2970 push.apply(allPaths, fillPaths);
michael@0 2971 } else {
michael@0 2972 allPaths = fillPaths;
michael@0 2973 }
michael@0 2974 push.apply(allPaths, linePaths);
michael@0 2975 if (defaultPath) {
michael@0 2976 allPaths.push(defaultPath);
michael@0 2977 }
michael@0 2978 var removeCount = 0;
michael@0 2979 for (i = 0; i < allPaths.length; i++) {
michael@0 2980 path = allPaths[i];
michael@0 2981 if (!path.head()) {
michael@0 2982 removeCount++;
michael@0 2983 continue;
michael@0 2984 }
michael@0 2985 allPaths[i - removeCount] = segmentedPathToShapePath(path, isMorph, transferables);
michael@0 2986 }
michael@0 2987 allPaths.length -= removeCount;
michael@0 2988 return allPaths;
michael@0 2989 }
michael@0 2990 function segmentedPathToShapePath(path, isMorph, transferables) {
michael@0 2991 var start = path.head();
michael@0 2992 var end = start;
michael@0 2993 var finalRoot = null;
michael@0 2994 var finalHead = null;
michael@0 2995 var skippedMoves = 0;
michael@0 2996 var current = start.prev;
michael@0 2997 while (start) {
michael@0 2998 while (current) {
michael@0 2999 if (path.segmentsConnect(current, start)) {
michael@0 3000 if (current.next !== start) {
michael@0 3001 path.removeSegment(current);
michael@0 3002 path.insertSegment(current, start);
michael@0 3003 }
michael@0 3004 start = current;
michael@0 3005 current = start.prev;
michael@0 3006 skippedMoves++;
michael@0 3007 continue;
michael@0 3008 }
michael@0 3009 if (path.segmentsConnect(end, current)) {
michael@0 3010 path.removeSegment(current);
michael@0 3011 end.next = current;
michael@0 3012 current = current.prev;
michael@0 3013 end.next.prev = end;
michael@0 3014 end.next.next = null;
michael@0 3015 end = end.next;
michael@0 3016 skippedMoves++;
michael@0 3017 continue;
michael@0 3018 }
michael@0 3019 current = current.prev;
michael@0 3020 }
michael@0 3021 current = start.prev;
michael@0 3022 if (!finalRoot) {
michael@0 3023 finalRoot = start;
michael@0 3024 finalHead = end;
michael@0 3025 } else {
michael@0 3026 finalHead.next = start;
michael@0 3027 start.prev = finalHead;
michael@0 3028 finalHead = end;
michael@0 3029 finalHead.next = null;
michael@0 3030 }
michael@0 3031 if (!current) {
michael@0 3032 break;
michael@0 3033 }
michael@0 3034 start = end = current;
michael@0 3035 current = start.prev;
michael@0 3036 }
michael@0 3037 var totalCommandsLength = -skippedMoves;
michael@0 3038 var totalDataLength = -skippedMoves << 1;
michael@0 3039 current = finalRoot;
michael@0 3040 while (current) {
michael@0 3041 totalCommandsLength += current.commands.length;
michael@0 3042 totalDataLength += current.data.length;
michael@0 3043 current = current.next;
michael@0 3044 }
michael@0 3045 var shape = new ShapePath(path.fillStyle, path.lineStyle, totalCommandsLength, totalDataLength, isMorph, transferables);
michael@0 3046 var allCommands = shape.commands;
michael@0 3047 var allData = shape.data;
michael@0 3048 var allMorphData = shape.morphData;
michael@0 3049 var commandsIndex = 0;
michael@0 3050 var dataIndex = 0;
michael@0 3051 current = finalRoot;
michael@0 3052 while (current) {
michael@0 3053 var commands = current.commands;
michael@0 3054 var data = current.data;
michael@0 3055 var morphData = current.morphData;
michael@0 3056 var offset = +(data[0] === allData[dataIndex - 2] && data[1] === allData[dataIndex - 1]);
michael@0 3057 for (var i = offset; i < commands.length; i++, commandsIndex++) {
michael@0 3058 allCommands[commandsIndex] = commands[i];
michael@0 3059 }
michael@0 3060 for (i = offset << 1; i < data.length; i++, dataIndex++) {
michael@0 3061 allData[dataIndex] = data[i];
michael@0 3062 if (isMorph) {
michael@0 3063 allMorphData[dataIndex] = morphData[i];
michael@0 3064 }
michael@0 3065 }
michael@0 3066 current = current.next;
michael@0 3067 }
michael@0 3068 return shape;
michael@0 3069 }
michael@0 3070 var CAPS_STYLE_TYPES = [
michael@0 3071 'round',
michael@0 3072 'none',
michael@0 3073 'square'
michael@0 3074 ];
michael@0 3075 var JOIN_STYLE_TYPES = [
michael@0 3076 'round',
michael@0 3077 'bevel',
michael@0 3078 'miter'
michael@0 3079 ];
michael@0 3080 function processStyle(style, isLineStyle, dictionary, dependencies) {
michael@0 3081 if (isLineStyle) {
michael@0 3082 style.lineCap = CAPS_STYLE_TYPES[style.endCapStyle | 0];
michael@0 3083 style.lineJoin = JOIN_STYLE_TYPES[style.joinStyle | 0];
michael@0 3084 style.miterLimit = (style.miterLimitFactor || 1.5) * 2;
michael@0 3085 if (!style.color && style.hasFill) {
michael@0 3086 var fillStyle = processStyle(style.fillStyle, false, dictionary, dependencies);
michael@0 3087 style.style = fillStyle.style;
michael@0 3088 style.type = fillStyle.type;
michael@0 3089 style.transform = fillStyle.transform;
michael@0 3090 style.records = fillStyle.records;
michael@0 3091 style.focalPoint = fillStyle.focalPoint;
michael@0 3092 style.bitmapId = fillStyle.bitmapId;
michael@0 3093 style.repeat = fillStyle.repeat;
michael@0 3094 style.fillStyle = null;
michael@0 3095 return style;
michael@0 3096 }
michael@0 3097 }
michael@0 3098 var color;
michael@0 3099 if (style.type === undefined || style.type === GRAPHICS_FILL_SOLID) {
michael@0 3100 color = style.color;
michael@0 3101 style.style = 'rgba(' + color.red + ',' + color.green + ',' + color.blue + ',' + color.alpha / 255 + ')';
michael@0 3102 style.color = null;
michael@0 3103 return style;
michael@0 3104 }
michael@0 3105 var scale;
michael@0 3106 switch (style.type) {
michael@0 3107 case GRAPHICS_FILL_LINEAR_GRADIENT:
michael@0 3108 case GRAPHICS_FILL_RADIAL_GRADIENT:
michael@0 3109 case GRAPHICS_FILL_FOCAL_RADIAL_GRADIENT:
michael@0 3110 scale = 819.2;
michael@0 3111 break;
michael@0 3112 case GRAPHICS_FILL_REPEATING_BITMAP:
michael@0 3113 case GRAPHICS_FILL_CLIPPED_BITMAP:
michael@0 3114 case GRAPHICS_FILL_NONSMOOTHED_REPEATING_BITMAP:
michael@0 3115 case GRAPHICS_FILL_NONSMOOTHED_CLIPPED_BITMAP:
michael@0 3116 if (dictionary[style.bitmapId]) {
michael@0 3117 dependencies.push(dictionary[style.bitmapId].id);
michael@0 3118 scale = 0.05;
michael@0 3119 }
michael@0 3120 break;
michael@0 3121 default:
michael@0 3122 fail('invalid fill style', 'shape');
michael@0 3123 }
michael@0 3124 if (!style.matrix) {
michael@0 3125 return style;
michael@0 3126 }
michael@0 3127 var matrix = style.matrix;
michael@0 3128 style.transform = {
michael@0 3129 a: matrix.a * scale,
michael@0 3130 b: matrix.b * scale,
michael@0 3131 c: matrix.c * scale,
michael@0 3132 d: matrix.d * scale,
michael@0 3133 e: matrix.tx,
michael@0 3134 f: matrix.ty
michael@0 3135 };
michael@0 3136 style.matrix = null;
michael@0 3137 return style;
michael@0 3138 }
michael@0 3139 function createPathsList(styles, isLineStyle, dictionary, dependencies) {
michael@0 3140 var paths = [];
michael@0 3141 for (var i = 0; i < styles.length; i++) {
michael@0 3142 var style = processStyle(styles[i], isLineStyle, dictionary, dependencies);
michael@0 3143 if (!isLineStyle) {
michael@0 3144 paths[i] = new SegmentedPath(style, null);
michael@0 3145 } else {
michael@0 3146 paths[i] = new SegmentedPath(null, style);
michael@0 3147 }
michael@0 3148 }
michael@0 3149 return paths;
michael@0 3150 }
michael@0 3151 function defineShape(tag, dictionary) {
michael@0 3152 var dependencies = [];
michael@0 3153 var transferables = [];
michael@0 3154 var fillPaths = createPathsList(tag.fillStyles, false, dictionary, dependencies);
michael@0 3155 var linePaths = createPathsList(tag.lineStyles, true, dictionary, dependencies);
michael@0 3156 var paths = convertRecordsToStyledPaths(tag.records, fillPaths, linePaths, dictionary, dependencies, tag.recordsMorph || null, transferables);
michael@0 3157 if (tag.bboxMorph) {
michael@0 3158 var mbox = tag.bboxMorph;
michael@0 3159 extendBoundsByPoint(tag.bbox, mbox.xMin, mbox.yMin);
michael@0 3160 extendBoundsByPoint(tag.bbox, mbox.xMax, mbox.yMax);
michael@0 3161 mbox = tag.strokeBboxMorph;
michael@0 3162 if (mbox) {
michael@0 3163 extendBoundsByPoint(tag.strokeBbox, mbox.xMin, mbox.yMin);
michael@0 3164 extendBoundsByPoint(tag.strokeBbox, mbox.xMax, mbox.yMax);
michael@0 3165 }
michael@0 3166 }
michael@0 3167 return {
michael@0 3168 type: 'shape',
michael@0 3169 id: tag.id,
michael@0 3170 strokeBbox: tag.strokeBbox,
michael@0 3171 strokeBboxMorph: tag.strokeBboxMorph,
michael@0 3172 bbox: tag.bbox,
michael@0 3173 bboxMorph: tag.bboxMorph,
michael@0 3174 isMorph: tag.isMorph,
michael@0 3175 paths: paths,
michael@0 3176 require: dependencies.length ? dependencies : null,
michael@0 3177 transferables: transferables
michael@0 3178 };
michael@0 3179 }
michael@0 3180 function logShape(paths, bbox) {
michael@0 3181 var output = '{"bounds":' + JSON.stringify(bbox) + ',"paths":[' + paths.map(function (path) {
michael@0 3182 return path.serialize();
michael@0 3183 }).join() + ']}';
michael@0 3184 console.log(output);
michael@0 3185 }
michael@0 3186 function SegmentedPath(fillStyle, lineStyle) {
michael@0 3187 this.fillStyle = fillStyle;
michael@0 3188 this.lineStyle = lineStyle;
michael@0 3189 this._head = null;
michael@0 3190 }
michael@0 3191 SegmentedPath.prototype = {
michael@0 3192 addSegment: function (commands, data, morphData) {
michael@0 3193 var segment = {
michael@0 3194 commands: commands,
michael@0 3195 data: data,
michael@0 3196 morphData: morphData,
michael@0 3197 prev: this._head,
michael@0 3198 next: null
michael@0 3199 };
michael@0 3200 if (this._head) {
michael@0 3201 this._head.next = segment;
michael@0 3202 }
michael@0 3203 this._head = segment;
michael@0 3204 return segment;
michael@0 3205 },
michael@0 3206 removeSegment: function (segment) {
michael@0 3207 if (segment.prev) {
michael@0 3208 segment.prev.next = segment.next;
michael@0 3209 }
michael@0 3210 if (segment.next) {
michael@0 3211 segment.next.prev = segment.prev;
michael@0 3212 }
michael@0 3213 },
michael@0 3214 insertSegment: function (segment, next) {
michael@0 3215 var prev = next.prev;
michael@0 3216 segment.prev = prev;
michael@0 3217 segment.next = next;
michael@0 3218 if (prev) {
michael@0 3219 prev.next = segment;
michael@0 3220 }
michael@0 3221 next.prev = segment;
michael@0 3222 },
michael@0 3223 head: function () {
michael@0 3224 return this._head;
michael@0 3225 },
michael@0 3226 segmentsConnect: function (first, second) {
michael@0 3227 var firstLength = first.data.length;
michael@0 3228 return first.data[firstLength - 2] === second.data[0] && first.data[firstLength - 1] === second.data[1];
michael@0 3229 }
michael@0 3230 };
michael@0 3231 var SHAPE_MOVE_TO = 1;
michael@0 3232 var SHAPE_LINE_TO = 2;
michael@0 3233 var SHAPE_CURVE_TO = 3;
michael@0 3234 var SHAPE_WIDE_MOVE_TO = 4;
michael@0 3235 var SHAPE_WIDE_LINE_TO = 5;
michael@0 3236 var SHAPE_CUBIC_CURVE_TO = 6;
michael@0 3237 var SHAPE_CIRCLE = 7;
michael@0 3238 var SHAPE_ELLIPSE = 8;
michael@0 3239 function ShapePath(fillStyle, lineStyle, commandsCount, dataLength, isMorph, transferables) {
michael@0 3240 this.fillStyle = fillStyle;
michael@0 3241 this.lineStyle = lineStyle;
michael@0 3242 if (commandsCount) {
michael@0 3243 this.commands = new Uint8Array(commandsCount);
michael@0 3244 this.data = new Int32Array(dataLength);
michael@0 3245 this.morphData = isMorph ? new Int32Array(dataLength) : null;
michael@0 3246 } else {
michael@0 3247 this.commands = [];
michael@0 3248 this.data = [];
michael@0 3249 }
michael@0 3250 this.bounds = null;
michael@0 3251 this.strokeBounds = null;
michael@0 3252 this.isMorph = !(!isMorph);
michael@0 3253 this.fullyInitialized = false;
michael@0 3254 if (inWorker) {
michael@0 3255 this.buffers = [
michael@0 3256 this.commands.buffer,
michael@0 3257 this.data.buffer
michael@0 3258 ];
michael@0 3259 transferables.push(this.commands.buffer, this.data.buffer);
michael@0 3260 if (isMorph) {
michael@0 3261 this.buffers.push(this.morphData.buffer);
michael@0 3262 transferables.push(this.morphData.buffer);
michael@0 3263 }
michael@0 3264 } else {
michael@0 3265 this.buffers = null;
michael@0 3266 }
michael@0 3267 }
michael@0 3268 ShapePath.prototype = {
michael@0 3269 get isEmpty() {
michael@0 3270 return this.commands.length === 0;
michael@0 3271 },
michael@0 3272 moveTo: function (x, y) {
michael@0 3273 if (this.commands[this.commands.length - 1] === SHAPE_MOVE_TO) {
michael@0 3274 this.data[this.data.length - 2] = x;
michael@0 3275 this.data[this.data.length - 1] = y;
michael@0 3276 return;
michael@0 3277 }
michael@0 3278 this.commands.push(SHAPE_MOVE_TO);
michael@0 3279 this.data.push(x, y);
michael@0 3280 },
michael@0 3281 lineTo: function (x, y) {
michael@0 3282 this.commands.push(SHAPE_LINE_TO);
michael@0 3283 this.data.push(x, y);
michael@0 3284 },
michael@0 3285 curveTo: function (controlX, controlY, anchorX, anchorY) {
michael@0 3286 this.commands.push(SHAPE_CURVE_TO);
michael@0 3287 this.data.push(controlX, controlY, anchorX, anchorY);
michael@0 3288 },
michael@0 3289 cubicCurveTo: function (control1X, control1Y, control2X, control2Y, anchorX, anchorY) {
michael@0 3290 this.commands.push(SHAPE_CUBIC_CURVE_TO);
michael@0 3291 this.data.push(control1X, control1Y, control2X, control2Y, anchorX, anchorY);
michael@0 3292 },
michael@0 3293 rect: function (x, y, w, h) {
michael@0 3294 var x2 = x + w;
michael@0 3295 var y2 = y + h;
michael@0 3296 this.commands.push(SHAPE_MOVE_TO, SHAPE_LINE_TO, SHAPE_LINE_TO, SHAPE_LINE_TO, SHAPE_LINE_TO);
michael@0 3297 this.data.push(x, y, x2, y, x2, y2, x, y2, x, y);
michael@0 3298 },
michael@0 3299 circle: function (x, y, radius) {
michael@0 3300 this.commands.push(SHAPE_CIRCLE);
michael@0 3301 this.data.push(x, y, radius);
michael@0 3302 },
michael@0 3303 ellipse: function (x, y, radiusX, radiusY) {
michael@0 3304 this.commands.push(SHAPE_ELLIPSE);
michael@0 3305 this.data.push(x, y, radiusX, radiusY);
michael@0 3306 },
michael@0 3307 draw: function (ctx, clip, ratio, colorTransform) {
michael@0 3308 if (clip && !this.fillStyle) {
michael@0 3309 return;
michael@0 3310 }
michael@0 3311 ctx.beginPath();
michael@0 3312 var commands = this.commands;
michael@0 3313 var data = this.data;
michael@0 3314 var morphData = this.morphData;
michael@0 3315 var formOpen = false;
michael@0 3316 var formOpenX = 0;
michael@0 3317 var formOpenY = 0;
michael@0 3318 if (!this.isMorph) {
michael@0 3319 for (var j = 0, k = 0; j < commands.length; j++) {
michael@0 3320 switch (commands[j]) {
michael@0 3321 case SHAPE_MOVE_TO:
michael@0 3322 formOpen = true;
michael@0 3323 formOpenX = data[k++] / 20;
michael@0 3324 formOpenY = data[k++] / 20;
michael@0 3325 ctx.moveTo(formOpenX, formOpenY);
michael@0 3326 break;
michael@0 3327 case SHAPE_WIDE_MOVE_TO:
michael@0 3328 ctx.moveTo(data[k++] / 20, data[k++] / 20);
michael@0 3329 k += 2;
michael@0 3330 break;
michael@0 3331 case SHAPE_LINE_TO:
michael@0 3332 ctx.lineTo(data[k++] / 20, data[k++] / 20);
michael@0 3333 break;
michael@0 3334 case SHAPE_WIDE_LINE_TO:
michael@0 3335 ctx.lineTo(data[k++] / 20, data[k++] / 20);
michael@0 3336 k += 2;
michael@0 3337 break;
michael@0 3338 case SHAPE_CURVE_TO:
michael@0 3339 ctx.quadraticCurveTo(data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20);
michael@0 3340 break;
michael@0 3341 case SHAPE_CUBIC_CURVE_TO:
michael@0 3342 ctx.bezierCurveTo(data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20);
michael@0 3343 break;
michael@0 3344 case SHAPE_CIRCLE:
michael@0 3345 if (formOpen) {
michael@0 3346 ctx.lineTo(formOpenX, formOpenY);
michael@0 3347 formOpen = false;
michael@0 3348 }
michael@0 3349 ctx.moveTo((data[k] + data[k + 2]) / 20, data[k + 1] / 20);
michael@0 3350 ctx.arc(data[k++] / 20, data[k++] / 20, data[k++] / 20, 0, Math.PI * 2, false);
michael@0 3351 break;
michael@0 3352 case SHAPE_ELLIPSE:
michael@0 3353 if (formOpen) {
michael@0 3354 ctx.lineTo(formOpenX, formOpenY);
michael@0 3355 formOpen = false;
michael@0 3356 }
michael@0 3357 var x = data[k++];
michael@0 3358 var y = data[k++];
michael@0 3359 var rX = data[k++];
michael@0 3360 var rY = data[k++];
michael@0 3361 var radius;
michael@0 3362 if (rX !== rY) {
michael@0 3363 ctx.save();
michael@0 3364 var ellipseScale;
michael@0 3365 if (rX > rY) {
michael@0 3366 ellipseScale = rX / rY;
michael@0 3367 radius = rY;
michael@0 3368 x /= ellipseScale;
michael@0 3369 ctx.scale(ellipseScale, 1);
michael@0 3370 } else {
michael@0 3371 ellipseScale = rY / rX;
michael@0 3372 radius = rX;
michael@0 3373 y /= ellipseScale;
michael@0 3374 ctx.scale(1, ellipseScale);
michael@0 3375 }
michael@0 3376 }
michael@0 3377 ctx.moveTo((x + radius) / 20, y / 20);
michael@0 3378 ctx.arc(x / 20, y / 20, radius / 20, 0, Math.PI * 2, false);
michael@0 3379 if (rX !== rY) {
michael@0 3380 ctx.restore();
michael@0 3381 }
michael@0 3382 break;
michael@0 3383 default:
michael@0 3384 if (commands[j] === 0 && j === commands.length - 1) {
michael@0 3385 break;
michael@0 3386 }
michael@0 3387 console.warn('Unknown drawing command encountered: ' + commands[j]);
michael@0 3388 }
michael@0 3389 }
michael@0 3390 } else {
michael@0 3391 for (var j = 0, k = 0; j < commands.length; j++) {
michael@0 3392 switch (commands[j]) {
michael@0 3393 case SHAPE_MOVE_TO:
michael@0 3394 ctx.moveTo(morph(data[k] / 20, morphData[k++] / 20, ratio), morph(data[k] / 20, morphData[k++] / 20, ratio));
michael@0 3395 break;
michael@0 3396 case SHAPE_LINE_TO:
michael@0 3397 ctx.lineTo(morph(data[k] / 20, morphData[k++] / 20, ratio), morph(data[k] / 20, morphData[k++] / 20, ratio));
michael@0 3398 break;
michael@0 3399 case SHAPE_CURVE_TO:
michael@0 3400 ctx.quadraticCurveTo(morph(data[k] / 20, morphData[k++] / 20, ratio), morph(data[k] / 20, morphData[k++] / 20, ratio), morph(data[k] / 20, morphData[k++] / 20, ratio), morph(data[k] / 20, morphData[k++] / 20, ratio));
michael@0 3401 break;
michael@0 3402 default:
michael@0 3403 console.warn('Drawing command not supported for morph shapes: ' + commands[j]);
michael@0 3404 }
michael@0 3405 }
michael@0 3406 }
michael@0 3407 if (!clip) {
michael@0 3408 var fillStyle = this.fillStyle;
michael@0 3409 if (fillStyle) {
michael@0 3410 colorTransform.setFillStyle(ctx, fillStyle.style);
michael@0 3411 ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = fillStyle.smooth;
michael@0 3412 var m = fillStyle.transform;
michael@0 3413 ctx.save();
michael@0 3414 colorTransform.setAlpha(ctx);
michael@0 3415 if (m) {
michael@0 3416 ctx.transform(m.a, m.b, m.c, m.d, m.e / 20, m.f / 20);
michael@0 3417 }
michael@0 3418 ctx.fill();
michael@0 3419 ctx.restore();
michael@0 3420 }
michael@0 3421 var lineStyle = this.lineStyle;
michael@0 3422 if (lineStyle) {
michael@0 3423 colorTransform.setStrokeStyle(ctx, lineStyle.style);
michael@0 3424 ctx.save();
michael@0 3425 colorTransform.setAlpha(ctx);
michael@0 3426 ctx.lineWidth = Math.max(lineStyle.width / 20, 1);
michael@0 3427 ctx.lineCap = lineStyle.lineCap;
michael@0 3428 ctx.lineJoin = lineStyle.lineJoin;
michael@0 3429 ctx.miterLimit = lineStyle.miterLimit;
michael@0 3430 ctx.stroke();
michael@0 3431 ctx.restore();
michael@0 3432 }
michael@0 3433 } else {
michael@0 3434 ctx.fill();
michael@0 3435 }
michael@0 3436 ctx.closePath();
michael@0 3437 },
michael@0 3438 isPointInPath: function (x, y) {
michael@0 3439 if (!(this.fillStyle || this.lineStyle)) {
michael@0 3440 return false;
michael@0 3441 }
michael@0 3442 var bounds = this.strokeBounds || this.bounds || this._calculateBounds();
michael@0 3443 if (x < bounds.xMin || x > bounds.xMax || y < bounds.yMin || y > bounds.yMax) {
michael@0 3444 return false;
michael@0 3445 }
michael@0 3446 if (this.fillStyle && this.isPointInFill(x, y)) {
michael@0 3447 return true;
michael@0 3448 }
michael@0 3449 return this.lineStyle && this.lineStyle.width !== undefined && this.isPointInStroke(x, y);
michael@0 3450 },
michael@0 3451 isPointInFill: function (x, y) {
michael@0 3452 var commands = this.commands;
michael@0 3453 var data = this.data;
michael@0 3454 var length = commands.length;
michael@0 3455 var inside = false;
michael@0 3456 var fromX = 0;
michael@0 3457 var fromY = 0;
michael@0 3458 var toX = 0;
michael@0 3459 var toY = 0;
michael@0 3460 var localX;
michael@0 3461 var localY;
michael@0 3462 var cpX;
michael@0 3463 var cpY;
michael@0 3464 var rX;
michael@0 3465 var rY;
michael@0 3466 var formOpen = false;
michael@0 3467 var formOpenX = 0;
michael@0 3468 var formOpenY = 0;
michael@0 3469 for (var commandIndex = 0, dataIndex = 0; commandIndex < length; commandIndex++) {
michael@0 3470 switch (commands[commandIndex]) {
michael@0 3471 case SHAPE_WIDE_MOVE_TO:
michael@0 3472 dataIndex += 2;
michael@0 3473 case SHAPE_MOVE_TO:
michael@0 3474 toX = data[dataIndex++];
michael@0 3475 toY = data[dataIndex++];
michael@0 3476 if (formOpen && intersectsLine(x, y, fromX, fromY, formOpenX, formOpenY)) {
michael@0 3477 inside = !inside;
michael@0 3478 }
michael@0 3479 formOpen = true;
michael@0 3480 formOpenX = toX;
michael@0 3481 formOpenY = toY;
michael@0 3482 break;
michael@0 3483 case SHAPE_WIDE_LINE_TO:
michael@0 3484 dataIndex += 2;
michael@0 3485 case SHAPE_LINE_TO:
michael@0 3486 toX = data[dataIndex++];
michael@0 3487 toY = data[dataIndex++];
michael@0 3488 if (intersectsLine(x, y, fromX, fromY, toX, toY)) {
michael@0 3489 inside = !inside;
michael@0 3490 }
michael@0 3491 break;
michael@0 3492 case SHAPE_CURVE_TO:
michael@0 3493 cpX = data[dataIndex++];
michael@0 3494 cpY = data[dataIndex++];
michael@0 3495 toX = data[dataIndex++];
michael@0 3496 toY = data[dataIndex++];
michael@0 3497 if (cpY > y === fromY > y && toY > y === fromY > y) {
michael@0 3498 break;
michael@0 3499 }
michael@0 3500 if (fromX >= x && cpX >= x && toX >= x) {
michael@0 3501 inside = !inside;
michael@0 3502 break;
michael@0 3503 }
michael@0 3504 var a = fromY - 2 * cpY + toY;
michael@0 3505 var c = fromY - y;
michael@0 3506 var b = 2 * (cpY - fromY);
michael@0 3507 var d = b * b - 4 * a * c;
michael@0 3508 if (d < 0) {
michael@0 3509 break;
michael@0 3510 }
michael@0 3511 d = Math.sqrt(d);
michael@0 3512 a = 1 / (a + a);
michael@0 3513 var t1 = (d - b) * a;
michael@0 3514 var t2 = (-b - d) * a;
michael@0 3515 if (t1 >= 0 && t1 <= 1 && quadraticBezier(fromX, cpX, toX, t1) > x) {
michael@0 3516 inside = !inside;
michael@0 3517 }
michael@0 3518 if (t2 >= 0 && t2 <= 1 && quadraticBezier(fromX, cpX, toX, t2) > x) {
michael@0 3519 inside = !inside;
michael@0 3520 }
michael@0 3521 break;
michael@0 3522 case SHAPE_CUBIC_CURVE_TO:
michael@0 3523 cpX = data[dataIndex++];
michael@0 3524 cpY = data[dataIndex++];
michael@0 3525 var cp2X = data[dataIndex++];
michael@0 3526 var cp2Y = data[dataIndex++];
michael@0 3527 toX = data[dataIndex++];
michael@0 3528 toY = data[dataIndex++];
michael@0 3529 if (cpY > y === fromY > y && cp2Y > y === fromY > y && toY > y === fromY > y) {
michael@0 3530 break;
michael@0 3531 }
michael@0 3532 if (fromX >= x && cpX >= x && cp2X >= x && toX >= x) {
michael@0 3533 inside = !inside;
michael@0 3534 break;
michael@0 3535 }
michael@0 3536 var roots = cubicXAtY(fromX, fromY, cpX, cpY, cp2X, cp2Y, toX, toY, y);
michael@0 3537 for (var i = roots.length; i--;) {
michael@0 3538 if (roots[i] >= x) {
michael@0 3539 inside = !inside;
michael@0 3540 }
michael@0 3541 }
michael@0 3542 break;
michael@0 3543 case SHAPE_CIRCLE:
michael@0 3544 toX = data[dataIndex++];
michael@0 3545 toY = data[dataIndex++];
michael@0 3546 var r = data[dataIndex++];
michael@0 3547 localX = x - toX;
michael@0 3548 localY = y - toY;
michael@0 3549 if (localX * localX + localY * localY < r * r) {
michael@0 3550 inside = !inside;
michael@0 3551 }
michael@0 3552 toX += r;
michael@0 3553 break;
michael@0 3554 case SHAPE_ELLIPSE:
michael@0 3555 cpX = data[dataIndex++];
michael@0 3556 cpY = data[dataIndex++];
michael@0 3557 rX = data[dataIndex++];
michael@0 3558 rY = data[dataIndex++];
michael@0 3559 localX = x - cpX;
michael@0 3560 localY = y - cpY;
michael@0 3561 if (localX * localX / (rX * rX) + localY * localY / (rY * rY) <= 1) {
michael@0 3562 inside = !inside;
michael@0 3563 }
michael@0 3564 toX = cpX + rX;
michael@0 3565 toY = cpY;
michael@0 3566 break;
michael@0 3567 default:
michael@0 3568 if (!inWorker) {
michael@0 3569 console.warn('Drawing command not handled in isPointInPath: ' + commands[commandIndex]);
michael@0 3570 }
michael@0 3571 }
michael@0 3572 fromX = toX;
michael@0 3573 fromY = toY;
michael@0 3574 }
michael@0 3575 if (formOpen && intersectsLine(x, y, fromX, fromY, formOpenX, formOpenY)) {
michael@0 3576 inside = !inside;
michael@0 3577 }
michael@0 3578 return inside;
michael@0 3579 },
michael@0 3580 isPointInStroke: function (x, y) {
michael@0 3581 var commands = this.commands;
michael@0 3582 var data = this.data;
michael@0 3583 var length = commands.length;
michael@0 3584 var width = this.lineStyle.width;
michael@0 3585 var halfWidth = width / 2;
michael@0 3586 var halfWidthSq = halfWidth * halfWidth;
michael@0 3587 var minX = x - halfWidth;
michael@0 3588 var maxX = x + halfWidth;
michael@0 3589 var minY = y - halfWidth;
michael@0 3590 var maxY = y + halfWidth;
michael@0 3591 var fromX = 0;
michael@0 3592 var fromY = 0;
michael@0 3593 var toX = 0;
michael@0 3594 var toY = 0;
michael@0 3595 var localX;
michael@0 3596 var localY;
michael@0 3597 var cpX;
michael@0 3598 var cpY;
michael@0 3599 var rX;
michael@0 3600 var rY;
michael@0 3601 var curveX;
michael@0 3602 var curveY;
michael@0 3603 var t;
michael@0 3604 for (var commandIndex = 0, dataIndex = 0; commandIndex < length; commandIndex++) {
michael@0 3605 switch (commands[commandIndex]) {
michael@0 3606 case SHAPE_WIDE_MOVE_TO:
michael@0 3607 dataIndex += 2;
michael@0 3608 case SHAPE_MOVE_TO:
michael@0 3609 toX = data[dataIndex++];
michael@0 3610 toY = data[dataIndex++];
michael@0 3611 break;
michael@0 3612 case SHAPE_WIDE_LINE_TO:
michael@0 3613 dataIndex += 2;
michael@0 3614 case SHAPE_LINE_TO:
michael@0 3615 toX = data[dataIndex++];
michael@0 3616 toY = data[dataIndex++];
michael@0 3617 if (fromX === toX && fromY === toY) {
michael@0 3618 break;
michael@0 3619 }
michael@0 3620 if (maxX < fromX && maxX < toX || minX > fromX && minX > toX || maxY < fromY && maxY < toY || minY > fromY && minY > toY) {
michael@0 3621 break;
michael@0 3622 }
michael@0 3623 if (toX === fromX || toY === fromY) {
michael@0 3624 return true;
michael@0 3625 }
michael@0 3626 t = ((x - fromX) * (toX - fromX) + (y - fromY) * (toY - fromY)) / distanceSq(fromX, fromY, toX, toY);
michael@0 3627 if (t < 0) {
michael@0 3628 if (distanceSq(x, y, fromX, fromY) <= halfWidthSq) {
michael@0 3629 return true;
michael@0 3630 }
michael@0 3631 break;
michael@0 3632 }
michael@0 3633 if (t > 1) {
michael@0 3634 if (distanceSq(x, y, toX, toY) <= halfWidthSq) {
michael@0 3635 return true;
michael@0 3636 }
michael@0 3637 break;
michael@0 3638 }
michael@0 3639 if (distanceSq(x, y, fromX + t * (toX - fromX), fromY + t * (toY - fromY)) <= halfWidthSq) {
michael@0 3640 return true;
michael@0 3641 }
michael@0 3642 break;
michael@0 3643 case SHAPE_CURVE_TO:
michael@0 3644 cpX = data[dataIndex++];
michael@0 3645 cpY = data[dataIndex++];
michael@0 3646 toX = data[dataIndex++];
michael@0 3647 toY = data[dataIndex++];
michael@0 3648 var extremeX = quadraticBezierExtreme(fromX, cpX, toX);
michael@0 3649 if (maxX < fromX && maxX < extremeX && maxX < toX || minX > fromX && minX > extremeX && minX > toX) {
michael@0 3650 break;
michael@0 3651 }
michael@0 3652 var extremeY = quadraticBezierExtreme(fromY, cpY, toY);
michael@0 3653 if (maxY < fromY && maxY < extremeY && maxY < toY || minY > fromY && minY > extremeY && minY > toY) {
michael@0 3654 break;
michael@0 3655 }
michael@0 3656 for (t = 0; t < 1; t += 0.02) {
michael@0 3657 curveX = quadraticBezier(fromX, cpX, toX, t);
michael@0 3658 if (curveX < minX || curveX > maxX) {
michael@0 3659 continue;
michael@0 3660 }
michael@0 3661 curveY = quadraticBezier(fromY, cpY, toY, t);
michael@0 3662 if (curveY < minY || curveY > maxY) {
michael@0 3663 continue;
michael@0 3664 }
michael@0 3665 if ((x - curveX) * (x - curveX) + (y - curveY) * (y - curveY) < halfWidthSq) {
michael@0 3666 return true;
michael@0 3667 }
michael@0 3668 }
michael@0 3669 break;
michael@0 3670 case SHAPE_CUBIC_CURVE_TO:
michael@0 3671 cpX = data[dataIndex++];
michael@0 3672 cpY = data[dataIndex++];
michael@0 3673 var cp2X = data[dataIndex++];
michael@0 3674 var cp2Y = data[dataIndex++];
michael@0 3675 toX = data[dataIndex++];
michael@0 3676 toY = data[dataIndex++];
michael@0 3677 var extremesX = cubicBezierExtremes(fromX, cpX, cp2X, toX);
michael@0 3678 while (extremesX.length < 2) {
michael@0 3679 extremesX.push(toX);
michael@0 3680 }
michael@0 3681 if (maxX < fromX && maxX < toX && maxX < extremesX[0] && maxX < extremesX[1] || minX > fromX && minX > toX && minX > extremesX[0] && minX > extremesX[1]) {
michael@0 3682 break;
michael@0 3683 }
michael@0 3684 var extremesY = cubicBezierExtremes(fromY, cpY, cp2Y, toY);
michael@0 3685 while (extremesY.length < 2) {
michael@0 3686 extremesY.push(toY);
michael@0 3687 }
michael@0 3688 if (maxY < fromY && maxY < toY && maxY < extremesY[0] && maxY < extremesY[1] || minY > fromY && minY > toY && minY > extremesY[0] && minY > extremesY[1]) {
michael@0 3689 break;
michael@0 3690 }
michael@0 3691 for (t = 0; t < 1; t += 0.02) {
michael@0 3692 curveX = cubicBezier(fromX, cpX, cp2X, toX, t);
michael@0 3693 if (curveX < minX || curveX > maxX) {
michael@0 3694 continue;
michael@0 3695 }
michael@0 3696 curveY = cubicBezier(fromY, cpY, cp2Y, toY, t);
michael@0 3697 if (curveY < minY || curveY > maxY) {
michael@0 3698 continue;
michael@0 3699 }
michael@0 3700 if ((x - curveX) * (x - curveX) + (y - curveY) * (y - curveY) < halfWidthSq) {
michael@0 3701 return true;
michael@0 3702 }
michael@0 3703 }
michael@0 3704 break;
michael@0 3705 case SHAPE_CIRCLE:
michael@0 3706 cpX = data[dataIndex++];
michael@0 3707 cpY = data[dataIndex++];
michael@0 3708 var r = data[dataIndex++];
michael@0 3709 toX = cpX + r;
michael@0 3710 toY = cpY;
michael@0 3711 if (maxX < cpX - r || minX > cpX + r || maxY < cpY - r || minY > cpY + r) {
michael@0 3712 break;
michael@0 3713 }
michael@0 3714 localX = x - cpX;
michael@0 3715 localY = y - cpY;
michael@0 3716 var rMin = r - halfWidth;
michael@0 3717 var rMax = r + halfWidth;
michael@0 3718 var distSq = localX * localX + localY * localY;
michael@0 3719 if (distSq >= rMin * rMin && distSq <= rMax * rMax) {
michael@0 3720 return true;
michael@0 3721 }
michael@0 3722 break;
michael@0 3723 case SHAPE_ELLIPSE:
michael@0 3724 cpX = data[dataIndex++];
michael@0 3725 cpY = data[dataIndex++];
michael@0 3726 rX = data[dataIndex++];
michael@0 3727 rY = data[dataIndex++];
michael@0 3728 toX = cpX + rX;
michael@0 3729 toY = cpY;
michael@0 3730 localX = Math.abs(x - cpX);
michael@0 3731 localY = Math.abs(y - cpY);
michael@0 3732 localX -= halfWidth;
michael@0 3733 localY -= halfWidth;
michael@0 3734 if (localX * localX / (rX * rX) + localY * localY / (rY * rY) > 1) {
michael@0 3735 break;
michael@0 3736 }
michael@0 3737 localX += width;
michael@0 3738 localY += width;
michael@0 3739 if (localX * localX / (rX * rX) + localY * localY / (rY * rY) > 1) {
michael@0 3740 return true;
michael@0 3741 }
michael@0 3742 break;
michael@0 3743 default:
michael@0 3744 if (!inWorker) {
michael@0 3745 console.warn('Drawing command not handled in isPointInPath: ' + commands[commandIndex]);
michael@0 3746 }
michael@0 3747 }
michael@0 3748 fromX = toX;
michael@0 3749 fromY = toY;
michael@0 3750 }
michael@0 3751 return false;
michael@0 3752 },
michael@0 3753 getBounds: function (includeStroke) {
michael@0 3754 var bounds = includeStroke ? this.strokeBounds : this.bounds;
michael@0 3755 if (!bounds) {
michael@0 3756 this._calculateBounds();
michael@0 3757 bounds = includeStroke ? this.strokeBounds : this.bounds;
michael@0 3758 }
michael@0 3759 return bounds;
michael@0 3760 },
michael@0 3761 _calculateBounds: function () {
michael@0 3762 var commands = this.commands;
michael@0 3763 var data = this.data;
michael@0 3764 var length = commands.length;
michael@0 3765 var bounds;
michael@0 3766 if (commands[0] === SHAPE_MOVE_TO || commands[0] > SHAPE_CUBIC_CURVE_TO) {
michael@0 3767 bounds = {
michael@0 3768 xMin: data[0],
michael@0 3769 yMin: data[1]
michael@0 3770 };
michael@0 3771 } else {
michael@0 3772 bounds = {
michael@0 3773 xMin: 0,
michael@0 3774 yMin: 0
michael@0 3775 };
michael@0 3776 }
michael@0 3777 bounds.xMax = bounds.xMin;
michael@0 3778 bounds.yMax = bounds.yMin;
michael@0 3779 var fromX = bounds.xMin;
michael@0 3780 var fromY = bounds.yMin;
michael@0 3781 for (var commandIndex = 0, dataIndex = 0; commandIndex < length; commandIndex++) {
michael@0 3782 var toX;
michael@0 3783 var toY;
michael@0 3784 var cpX;
michael@0 3785 var cpY;
michael@0 3786 switch (commands[commandIndex]) {
michael@0 3787 case SHAPE_WIDE_MOVE_TO:
michael@0 3788 dataIndex += 2;
michael@0 3789 case SHAPE_MOVE_TO:
michael@0 3790 toX = data[dataIndex++];
michael@0 3791 toY = data[dataIndex++];
michael@0 3792 extendBoundsByPoint(bounds, toX, toY);
michael@0 3793 break;
michael@0 3794 case SHAPE_WIDE_LINE_TO:
michael@0 3795 dataIndex += 2;
michael@0 3796 case SHAPE_LINE_TO:
michael@0 3797 toX = data[dataIndex++];
michael@0 3798 toY = data[dataIndex++];
michael@0 3799 extendBoundsByPoint(bounds, toX, toY);
michael@0 3800 break;
michael@0 3801 case SHAPE_CURVE_TO:
michael@0 3802 cpX = data[dataIndex++];
michael@0 3803 cpY = data[dataIndex++];
michael@0 3804 toX = data[dataIndex++];
michael@0 3805 toY = data[dataIndex++];
michael@0 3806 extendBoundsByPoint(bounds, toX, toY);
michael@0 3807 if (cpX < fromX || cpX > toX) {
michael@0 3808 extendBoundsByX(bounds, quadraticBezierExtreme(fromX, cpX, toX));
michael@0 3809 }
michael@0 3810 if (cpY < fromY || cpY > toY) {
michael@0 3811 extendBoundsByY(bounds, quadraticBezierExtreme(fromY, cpY, toY));
michael@0 3812 }
michael@0 3813 break;
michael@0 3814 case SHAPE_CUBIC_CURVE_TO:
michael@0 3815 cpX = data[dataIndex++];
michael@0 3816 cpY = data[dataIndex++];
michael@0 3817 var cp2X = data[dataIndex++];
michael@0 3818 var cp2Y = data[dataIndex++];
michael@0 3819 toX = data[dataIndex++];
michael@0 3820 toY = data[dataIndex++];
michael@0 3821 extendBoundsByPoint(bounds, toX, toY);
michael@0 3822 var extremes;
michael@0 3823 var i;
michael@0 3824 if (cpX < fromX || cp2X < fromX || cpX > toX || cp2X > toX) {
michael@0 3825 extremes = cubicBezierExtremes(fromX, cpX, cp2X, toX);
michael@0 3826 for (i = extremes.length; i--;) {
michael@0 3827 extendBoundsByX(bounds, extremes[i]);
michael@0 3828 }
michael@0 3829 }
michael@0 3830 if (cpY < fromY || cp2Y < fromY || cpY > toY || cp2Y > toY) {
michael@0 3831 extremes = cubicBezierExtremes(fromY, cpY, cp2Y, toY);
michael@0 3832 for (i = extremes.length; i--;) {
michael@0 3833 extendBoundsByY(bounds, extremes[i]);
michael@0 3834 }
michael@0 3835 }
michael@0 3836 break;
michael@0 3837 case SHAPE_CIRCLE:
michael@0 3838 toX = data[dataIndex++];
michael@0 3839 toY = data[dataIndex++];
michael@0 3840 var radius = data[dataIndex++];
michael@0 3841 extendBoundsByPoint(bounds, toX - radius, toY - radius);
michael@0 3842 extendBoundsByPoint(bounds, toX + radius, toY + radius);
michael@0 3843 toX += radius;
michael@0 3844 break;
michael@0 3845 case SHAPE_ELLIPSE:
michael@0 3846 toX = data[dataIndex++];
michael@0 3847 toY = data[dataIndex++];
michael@0 3848 var radiusX = data[dataIndex++];
michael@0 3849 var radiusY = data[dataIndex++];
michael@0 3850 extendBoundsByPoint(bounds, toX - radiusX, toY - radiusY);
michael@0 3851 extendBoundsByPoint(bounds, toX + radiusX, toY + radiusY);
michael@0 3852 toX += radiusX;
michael@0 3853 break;
michael@0 3854 default:
michael@0 3855 if (!inWorker) {
michael@0 3856 console.warn('Drawing command not handled in bounds calculation: ' + commands[commandIndex]);
michael@0 3857 }
michael@0 3858 }
michael@0 3859 fromX = toX;
michael@0 3860 fromY = toY;
michael@0 3861 }
michael@0 3862 this.bounds = bounds;
michael@0 3863 if (this.lineStyle) {
michael@0 3864 var halfLineWidth = this.lineStyle.width / 2;
michael@0 3865 this.strokeBounds = {
michael@0 3866 xMin: bounds.xMin - halfLineWidth,
michael@0 3867 yMin: bounds.yMin - halfLineWidth,
michael@0 3868 xMax: bounds.xMax + halfLineWidth,
michael@0 3869 yMax: bounds.yMax + halfLineWidth
michael@0 3870 };
michael@0 3871 return this.strokeBounds;
michael@0 3872 } else {
michael@0 3873 this.strokeBounds = bounds;
michael@0 3874 }
michael@0 3875 return bounds;
michael@0 3876 },
michael@0 3877 serialize: function () {
michael@0 3878 var output = '{';
michael@0 3879 if (this.fillStyle) {
michael@0 3880 output += '"fill":' + JSON.stringify(this.fillStyle) + ',';
michael@0 3881 }
michael@0 3882 if (this.lineStyle) {
michael@0 3883 output += '"stroke":' + JSON.stringify(this.lineStyle) + ',';
michael@0 3884 }
michael@0 3885 output += '"commands":[' + Array.apply([], this.commands).join() + '],';
michael@0 3886 output += '"data":[' + Array.apply([], this.data).join() + ']';
michael@0 3887 return output + '}';
michael@0 3888 }
michael@0 3889 };
michael@0 3890 ShapePath.fromPlainObject = function (obj) {
michael@0 3891 var path = new ShapePath(obj.fill || null, obj.stroke || null);
michael@0 3892 path.commands = new Uint8Array(obj.commands);
michael@0 3893 path.data = new Int32Array(obj.data);
michael@0 3894 if (!inWorker) {
michael@0 3895 finishShapePath(path);
michael@0 3896 }
michael@0 3897 return path;
michael@0 3898 };
michael@0 3899 function distanceSq(x1, y1, x2, y2) {
michael@0 3900 var dX = x2 - x1;
michael@0 3901 var dY = y2 - y1;
michael@0 3902 return dX * dX + dY * dY;
michael@0 3903 }
michael@0 3904 function intersectsLine(x, y, x1, y1, x2, y2) {
michael@0 3905 return y2 > y !== y1 > y && x < (x1 - x2) * (y - y2) / (y1 - y2) + x2;
michael@0 3906 }
michael@0 3907 function quadraticBezier(from, cp, to, t) {
michael@0 3908 var inverseT = 1 - t;
michael@0 3909 return from * inverseT * inverseT + 2 * cp * inverseT * t + to * t * t;
michael@0 3910 }
michael@0 3911 function quadraticBezierExtreme(from, cp, to) {
michael@0 3912 var t = (from - cp) / (from - 2 * cp + to);
michael@0 3913 if (t < 0) {
michael@0 3914 return from;
michael@0 3915 }
michael@0 3916 if (t > 1) {
michael@0 3917 return to;
michael@0 3918 }
michael@0 3919 return quadraticBezier(from, cp, to, t);
michael@0 3920 }
michael@0 3921 function cubicBezier(from, cp, cp2, to, t) {
michael@0 3922 var tSq = t * t;
michael@0 3923 var inverseT = 1 - t;
michael@0 3924 var inverseTSq = inverseT * inverseT;
michael@0 3925 return from * inverseT * inverseTSq + 3 * cp * t * inverseTSq + 3 * cp2 * inverseT * tSq + to * t * tSq;
michael@0 3926 }
michael@0 3927 function cubicBezierExtremes(from, cp, cp2, to) {
michael@0 3928 var d1 = cp - from;
michael@0 3929 var d2 = cp2 - cp;
michael@0 3930 d2 *= 2;
michael@0 3931 var d3 = to - cp2;
michael@0 3932 if (d1 + d3 === d2) {
michael@0 3933 d3 *= 1.0001;
michael@0 3934 }
michael@0 3935 var fHead = 2 * d1 - d2;
michael@0 3936 var part1 = d2 - 2 * d1;
michael@0 3937 var fCenter = Math.sqrt(part1 * part1 - 4 * d1 * (d1 - d2 + d3));
michael@0 3938 var fTail = 2 * (d1 - d2 + d3);
michael@0 3939 var t1 = (fHead + fCenter) / fTail;
michael@0 3940 var t2 = (fHead - fCenter) / fTail;
michael@0 3941 var result = [];
michael@0 3942 if (t1 >= 0 && t1 <= 1) {
michael@0 3943 result.push(cubicBezier(from, cp, cp2, to, t1));
michael@0 3944 }
michael@0 3945 if (t2 >= 0 && t2 <= 1) {
michael@0 3946 result.push(cubicBezier(from, cp, cp2, to, t2));
michael@0 3947 }
michael@0 3948 return result;
michael@0 3949 }
michael@0 3950 function cubicXAtY(x0, y0, cx, cy, cx1, cy1, x1, y1, y) {
michael@0 3951 var dX = 3 * (cx - x0);
michael@0 3952 var dY = 3 * (cy - y0);
michael@0 3953 var bX = 3 * (cx1 - cx) - dX;
michael@0 3954 var bY = 3 * (cy1 - cy) - dY;
michael@0 3955 var c3X = x1 - x0 - dX - bX;
michael@0 3956 var c3Y = y1 - y0 - dY - bY;
michael@0 3957 function f(t) {
michael@0 3958 return t * (dY + t * (bY + t * c3Y)) + y0 - y;
michael@0 3959 }
michael@0 3960 function pointAt(t) {
michael@0 3961 if (t < 0) {
michael@0 3962 t = 0;
michael@0 3963 } else if (t > 1) {
michael@0 3964 t = 1;
michael@0 3965 }
michael@0 3966 return x0 + t * (dX + t * (bX + t * c3X));
michael@0 3967 }
michael@0 3968 function bisectCubicBezierRange(f, l, r, limit) {
michael@0 3969 if (Math.abs(r - l) <= limit) {
michael@0 3970 return;
michael@0 3971 }
michael@0 3972 var middle = 0.5 * (l + r);
michael@0 3973 if (f(l) * f(r) <= 0) {
michael@0 3974 left = l;
michael@0 3975 right = r;
michael@0 3976 return;
michael@0 3977 }
michael@0 3978 bisectCubicBezierRange(f, l, middle, limit);
michael@0 3979 bisectCubicBezierRange(f, middle, r, limit);
michael@0 3980 }
michael@0 3981 var left = 0;
michael@0 3982 var right = 1;
michael@0 3983 bisectCubicBezierRange(f, 0, 1, 0.05);
michael@0 3984 var t0 = findRoot(left, right, f, 50, 0.000001);
michael@0 3985 var evalResult = Math.abs(f(t0));
michael@0 3986 if (evalResult > 0.00001) {
michael@0 3987 return [];
michael@0 3988 }
michael@0 3989 var result = [];
michael@0 3990 if (t0 <= 1) {
michael@0 3991 result.push(pointAt(t0));
michael@0 3992 }
michael@0 3993 var a = c3Y;
michael@0 3994 var b = t0 * a + bY;
michael@0 3995 var c = t0 * b + dY;
michael@0 3996 var d = b * b - 4 * a * c;
michael@0 3997 if (d < 0) {
michael@0 3998 return result;
michael@0 3999 }
michael@0 4000 d = Math.sqrt(d);
michael@0 4001 a = 1 / (a + a);
michael@0 4002 var t1 = (d - b) * a;
michael@0 4003 var t2 = (-b - d) * a;
michael@0 4004 if (t1 >= 0 && t1 <= 1) {
michael@0 4005 result.push(pointAt(t1));
michael@0 4006 }
michael@0 4007 if (t2 >= 0 && t2 <= 1) {
michael@0 4008 result.push(pointAt(t2));
michael@0 4009 }
michael@0 4010 return result;
michael@0 4011 }
michael@0 4012 function findRoot(x0, x2, f, maxIterations, epsilon) {
michael@0 4013 var x1;
michael@0 4014 var y0;
michael@0 4015 var y1;
michael@0 4016 var y2;
michael@0 4017 var b;
michael@0 4018 var c;
michael@0 4019 var y10;
michael@0 4020 var y20;
michael@0 4021 var y21;
michael@0 4022 var xm;
michael@0 4023 var ym;
michael@0 4024 var temp;
michael@0 4025 var xmlast = x0;
michael@0 4026 y0 = f(x0);
michael@0 4027 if (y0 === 0) {
michael@0 4028 return x0;
michael@0 4029 }
michael@0 4030 y2 = f(x2);
michael@0 4031 if (y2 === 0) {
michael@0 4032 return x2;
michael@0 4033 }
michael@0 4034 if (y2 * y0 > 0) {
michael@0 4035 return x0;
michael@0 4036 }
michael@0 4037 var __iter = 0;
michael@0 4038 for (var i = 0; i < maxIterations; ++i) {
michael@0 4039 __iter++;
michael@0 4040 x1 = 0.5 * (x2 + x0);
michael@0 4041 y1 = f(x1);
michael@0 4042 if (y1 === 0) {
michael@0 4043 return x1;
michael@0 4044 }
michael@0 4045 if (Math.abs(x1 - x0) < epsilon) {
michael@0 4046 return x1;
michael@0 4047 }
michael@0 4048 if (y1 * y0 > 0) {
michael@0 4049 temp = x0;
michael@0 4050 x0 = x2;
michael@0 4051 x2 = temp;
michael@0 4052 temp = y0;
michael@0 4053 y0 = y2;
michael@0 4054 y2 = temp;
michael@0 4055 }
michael@0 4056 y10 = y1 - y0;
michael@0 4057 y21 = y2 - y1;
michael@0 4058 y20 = y2 - y0;
michael@0 4059 if (y2 * y20 < 2 * y1 * y10) {
michael@0 4060 x2 = x1;
michael@0 4061 y2 = y1;
michael@0 4062 } else {
michael@0 4063 b = (x1 - x0) / y10;
michael@0 4064 c = (y10 - y21) / (y21 * y20);
michael@0 4065 xm = x0 - b * y0 * (1 - c * y1);
michael@0 4066 ym = f(xm);
michael@0 4067 if (ym === 0) {
michael@0 4068 return xm;
michael@0 4069 }
michael@0 4070 if (Math.abs(xm - xmlast) < epsilon) {
michael@0 4071 return xm;
michael@0 4072 }
michael@0 4073 xmlast = xm;
michael@0 4074 if (ym * y0 < 0) {
michael@0 4075 x2 = xm;
michael@0 4076 y2 = ym;
michael@0 4077 } else {
michael@0 4078 x0 = xm;
michael@0 4079 y0 = ym;
michael@0 4080 x2 = x1;
michael@0 4081 y2 = y1;
michael@0 4082 }
michael@0 4083 }
michael@0 4084 }
michael@0 4085 return x1;
michael@0 4086 }
michael@0 4087 function extendBoundsByPoint(bounds, x, y) {
michael@0 4088 if (x < bounds.xMin) {
michael@0 4089 bounds.xMin = x;
michael@0 4090 } else if (x > bounds.xMax) {
michael@0 4091 bounds.xMax = x;
michael@0 4092 }
michael@0 4093 if (y < bounds.yMin) {
michael@0 4094 bounds.yMin = y;
michael@0 4095 } else if (y > bounds.yMax) {
michael@0 4096 bounds.yMax = y;
michael@0 4097 }
michael@0 4098 }
michael@0 4099 function extendBoundsByX(bounds, x) {
michael@0 4100 if (x < bounds.xMin) {
michael@0 4101 bounds.xMin = x;
michael@0 4102 } else if (x > bounds.xMax) {
michael@0 4103 bounds.xMax = x;
michael@0 4104 }
michael@0 4105 }
michael@0 4106 function extendBoundsByY(bounds, y) {
michael@0 4107 if (y < bounds.yMin) {
michael@0 4108 bounds.yMin = y;
michael@0 4109 } else if (y > bounds.yMax) {
michael@0 4110 bounds.yMax = y;
michael@0 4111 }
michael@0 4112 }
michael@0 4113 function morph(start, end, ratio) {
michael@0 4114 return start + (end - start) * ratio;
michael@0 4115 }
michael@0 4116 function finishShapePath(path, dictionaryResolved) {
michael@0 4117 if (path.fullyInitialized) {
michael@0 4118 return path;
michael@0 4119 }
michael@0 4120 if (!(path instanceof ShapePath)) {
michael@0 4121 var untypedPath = path;
michael@0 4122 path = new ShapePath(path.fillStyle, path.lineStyle, 0, 0, path.isMorph);
michael@0 4123 path.commands = new Uint8Array(untypedPath.buffers[0]);
michael@0 4124 path.data = new Int32Array(untypedPath.buffers[1]);
michael@0 4125 if (untypedPath.isMorph) {
michael@0 4126 path.morphData = new Int32Array(untypedPath.buffers[2]);
michael@0 4127 }
michael@0 4128 path.buffers = null;
michael@0 4129 }
michael@0 4130 path.fillStyle && initStyle(path.fillStyle, dictionaryResolved);
michael@0 4131 path.lineStyle && initStyle(path.lineStyle, dictionaryResolved);
michael@0 4132 path.fullyInitialized = true;
michael@0 4133 return path;
michael@0 4134 }
michael@0 4135 var inWorker = typeof window === 'undefined';
michael@0 4136 var factoryCtx = !inWorker ? document.createElement('canvas').getContext('2d') : null;
michael@0 4137 function buildLinearGradientFactory(colorStops) {
michael@0 4138 var defaultGradient = factoryCtx.createLinearGradient(-1, 0, 1, 0);
michael@0 4139 for (var i = 0; i < colorStops.length; i++) {
michael@0 4140 defaultGradient.addColorStop(colorStops[i].ratio, colorStops[i].color);
michael@0 4141 }
michael@0 4142 var fn = function createLinearGradient(ctx, colorTransform) {
michael@0 4143 var gradient = ctx.createLinearGradient(-1, 0, 1, 0);
michael@0 4144 for (var i = 0; i < colorStops.length; i++) {
michael@0 4145 colorTransform.addGradientColorStop(gradient, colorStops[i].ratio, colorStops[i].color);
michael@0 4146 }
michael@0 4147 return gradient;
michael@0 4148 };
michael@0 4149 fn.defaultFillStyle = defaultGradient;
michael@0 4150 return fn;
michael@0 4151 }
michael@0 4152 function buildRadialGradientFactory(focalPoint, colorStops) {
michael@0 4153 var defaultGradient = factoryCtx.createRadialGradient(focalPoint, 0, 0, 0, 0, 1);
michael@0 4154 for (var i = 0; i < colorStops.length; i++) {
michael@0 4155 defaultGradient.addColorStop(colorStops[i].ratio, colorStops[i].color);
michael@0 4156 }
michael@0 4157 var fn = function createRadialGradient(ctx, colorTransform) {
michael@0 4158 var gradient = ctx.createRadialGradient(focalPoint, 0, 0, 0, 0, 1);
michael@0 4159 for (var i = 0; i < colorStops.length; i++) {
michael@0 4160 colorTransform.addGradientColorStop(gradient, colorStops[i].ratio, colorStops[i].color);
michael@0 4161 }
michael@0 4162 return gradient;
michael@0 4163 };
michael@0 4164 fn.defaultFillStyle = defaultGradient;
michael@0 4165 return fn;
michael@0 4166 }
michael@0 4167 function buildBitmapPatternFactory(img, repeat) {
michael@0 4168 var defaultPattern = factoryCtx.createPattern(img, repeat);
michael@0 4169 var cachedTransform, cachedTransformKey;
michael@0 4170 var fn = function createBitmapPattern(ctx, colorTransform) {
michael@0 4171 if (!colorTransform.mode) {
michael@0 4172 return defaultPattern;
michael@0 4173 }
michael@0 4174 var key = colorTransform.getTransformFingerprint();
michael@0 4175 if (key === cachedTransformKey) {
michael@0 4176 return cachedTransform;
michael@0 4177 }
michael@0 4178 var canvas = document.createElement('canvas');
michael@0 4179 canvas.width = img.width;
michael@0 4180 canvas.height = img.height;
michael@0 4181 var ctx = canvas.getContext('2d');
michael@0 4182 colorTransform.setAlpha(ctx, true);
michael@0 4183 ctx.drawImage(img, 0, 0);
michael@0 4184 cachedTransform = ctx.createPattern(canvas, repeat);
michael@0 4185 cachedTransformKey = key;
michael@0 4186 return cachedTransform;
michael@0 4187 };
michael@0 4188 fn.defaultFillStyle = defaultPattern;
michael@0 4189 return fn;
michael@0 4190 }
michael@0 4191 function initStyle(style, dictionaryResolved) {
michael@0 4192 if (style.type === undefined) {
michael@0 4193 return;
michael@0 4194 }
michael@0 4195 switch (style.type) {
michael@0 4196 case GRAPHICS_FILL_SOLID:
michael@0 4197 break;
michael@0 4198 case GRAPHICS_FILL_LINEAR_GRADIENT:
michael@0 4199 case GRAPHICS_FILL_RADIAL_GRADIENT:
michael@0 4200 case GRAPHICS_FILL_FOCAL_RADIAL_GRADIENT:
michael@0 4201 var records = style.records, colorStops = [];
michael@0 4202 for (var j = 0, n = records.length; j < n; j++) {
michael@0 4203 var record = records[j];
michael@0 4204 var colorStr = rgbaObjToStr(record.color);
michael@0 4205 colorStops.push({
michael@0 4206 ratio: record.ratio / 255,
michael@0 4207 color: colorStr
michael@0 4208 });
michael@0 4209 }
michael@0 4210 var gradientConstructor;
michael@0 4211 var isLinear = style.type === GRAPHICS_FILL_LINEAR_GRADIENT;
michael@0 4212 if (isLinear) {
michael@0 4213 gradientConstructor = buildLinearGradientFactory(colorStops);
michael@0 4214 } else {
michael@0 4215 gradientConstructor = buildRadialGradientFactory((style.focalPoint | 0) / 20, colorStops);
michael@0 4216 }
michael@0 4217 style.style = gradientConstructor;
michael@0 4218 break;
michael@0 4219 case GRAPHICS_FILL_REPEATING_BITMAP:
michael@0 4220 case GRAPHICS_FILL_CLIPPED_BITMAP:
michael@0 4221 case GRAPHICS_FILL_NONSMOOTHED_REPEATING_BITMAP:
michael@0 4222 case GRAPHICS_FILL_NONSMOOTHED_CLIPPED_BITMAP:
michael@0 4223 var bitmap = dictionaryResolved[style.bitmapId];
michael@0 4224 var repeat = style.type === GRAPHICS_FILL_REPEATING_BITMAP || style.type === GRAPHICS_FILL_NONSMOOTHED_REPEATING_BITMAP;
michael@0 4225 style.style = buildBitmapPatternFactory(bitmap.props.img, repeat ? 'repeat' : 'no-repeat');
michael@0 4226 break;
michael@0 4227 default:
michael@0 4228 fail('invalid fill style', 'shape');
michael@0 4229 }
michael@0 4230 }
michael@0 4231 var SOUND_SIZE_8_BIT = 0;
michael@0 4232 var SOUND_SIZE_16_BIT = 1;
michael@0 4233 var SOUND_TYPE_MONO = 0;
michael@0 4234 var SOUND_TYPE_STEREO = 1;
michael@0 4235 var SOUND_FORMAT_PCM_BE = 0;
michael@0 4236 var SOUND_FORMAT_ADPCM = 1;
michael@0 4237 var SOUND_FORMAT_MP3 = 2;
michael@0 4238 var SOUND_FORMAT_PCM_LE = 3;
michael@0 4239 var SOUND_FORMAT_NELLYMOSER_16 = 4;
michael@0 4240 var SOUND_FORMAT_NELLYMOSER_8 = 5;
michael@0 4241 var SOUND_FORMAT_NELLYMOSER = 6;
michael@0 4242 var SOUND_FORMAT_SPEEX = 11;
michael@0 4243 var SOUND_RATES = [
michael@0 4244 5512,
michael@0 4245 11250,
michael@0 4246 22500,
michael@0 4247 44100
michael@0 4248 ];
michael@0 4249 var WaveHeader = new Uint8Array([
michael@0 4250 82,
michael@0 4251 73,
michael@0 4252 70,
michael@0 4253 70,
michael@0 4254 0,
michael@0 4255 0,
michael@0 4256 0,
michael@0 4257 0,
michael@0 4258 87,
michael@0 4259 65,
michael@0 4260 86,
michael@0 4261 69,
michael@0 4262 102,
michael@0 4263 109,
michael@0 4264 116,
michael@0 4265 32,
michael@0 4266 16,
michael@0 4267 0,
michael@0 4268 0,
michael@0 4269 0,
michael@0 4270 1,
michael@0 4271 0,
michael@0 4272 2,
michael@0 4273 0,
michael@0 4274 68,
michael@0 4275 172,
michael@0 4276 0,
michael@0 4277 0,
michael@0 4278 16,
michael@0 4279 177,
michael@0 4280 2,
michael@0 4281 0,
michael@0 4282 4,
michael@0 4283 0,
michael@0 4284 16,
michael@0 4285 0,
michael@0 4286 100,
michael@0 4287 97,
michael@0 4288 116,
michael@0 4289 97,
michael@0 4290 0,
michael@0 4291 0,
michael@0 4292 0,
michael@0 4293 0
michael@0 4294 ]);
michael@0 4295 function packageWave(data, sampleRate, channels, size, swapBytes) {
michael@0 4296 var sizeInBytes = size >> 3;
michael@0 4297 var sizePerSecond = channels * sampleRate * sizeInBytes;
michael@0 4298 var sizePerSample = channels * sizeInBytes;
michael@0 4299 var dataLength = data.length + (data.length & 1);
michael@0 4300 var buffer = new ArrayBuffer(WaveHeader.length + dataLength);
michael@0 4301 var bytes = new Uint8Array(buffer);
michael@0 4302 bytes.set(WaveHeader);
michael@0 4303 if (swapBytes) {
michael@0 4304 for (var i = 0, j = WaveHeader.length; i < data.length; i += 2, j += 2) {
michael@0 4305 bytes[j] = data[i + 1];
michael@0 4306 bytes[j + 1] = data[i];
michael@0 4307 }
michael@0 4308 } else {
michael@0 4309 bytes.set(data, WaveHeader.length);
michael@0 4310 }
michael@0 4311 var view = new DataView(buffer);
michael@0 4312 view.setUint32(4, dataLength + 36, true);
michael@0 4313 view.setUint16(22, channels, true);
michael@0 4314 view.setUint32(24, sampleRate, true);
michael@0 4315 view.setUint32(28, sizePerSecond, true);
michael@0 4316 view.setUint16(32, sizePerSample, true);
michael@0 4317 view.setUint16(34, size, true);
michael@0 4318 view.setUint32(40, dataLength, true);
michael@0 4319 return {
michael@0 4320 data: bytes,
michael@0 4321 mimeType: 'audio/wav'
michael@0 4322 };
michael@0 4323 }
michael@0 4324 function defineSound(tag, dictionary) {
michael@0 4325 var channels = tag.soundType == SOUND_TYPE_STEREO ? 2 : 1;
michael@0 4326 var samplesCount = tag.samplesCount;
michael@0 4327 var sampleRate = SOUND_RATES[tag.soundRate];
michael@0 4328 var data = tag.soundData;
michael@0 4329 var pcm, packaged;
michael@0 4330 switch (tag.soundFormat) {
michael@0 4331 case SOUND_FORMAT_PCM_BE:
michael@0 4332 pcm = new Float32Array(samplesCount * channels);
michael@0 4333 if (tag.soundSize == SOUND_SIZE_16_BIT) {
michael@0 4334 for (var i = 0, j = 0; i < pcm.length; i++, j += 2)
michael@0 4335 pcm[i] = (data[j] << 24 | data[j + 1] << 16) / 2147483648;
michael@0 4336 packaged = packageWave(data, sampleRate, channels, 16, true);
michael@0 4337 } else {
michael@0 4338 for (var i = 0; i < pcm.length; i++)
michael@0 4339 pcm[i] = (data[i] - 128) / 128;
michael@0 4340 packaged = packageWave(data, sampleRate, channels, 8, false);
michael@0 4341 }
michael@0 4342 break;
michael@0 4343 case SOUND_FORMAT_PCM_LE:
michael@0 4344 pcm = new Float32Array(samplesCount * channels);
michael@0 4345 if (tag.soundSize == SOUND_SIZE_16_BIT) {
michael@0 4346 for (var i = 0, j = 0; i < pcm.length; i++, j += 2)
michael@0 4347 pcm[i] = (data[j + 1] << 24 | data[j] << 16) / 2147483648;
michael@0 4348 packaged = packageWave(data, sampleRate, channels, 16, false);
michael@0 4349 } else {
michael@0 4350 for (var i = 0; i < pcm.length; i++)
michael@0 4351 pcm[i] = (data[i] - 128) / 128;
michael@0 4352 packaged = packageWave(data, sampleRate, channels, 8, false);
michael@0 4353 }
michael@0 4354 break;
michael@0 4355 case SOUND_FORMAT_MP3:
michael@0 4356 packaged = {
michael@0 4357 data: new Uint8Array(data.subarray(2)),
michael@0 4358 mimeType: 'audio/mpeg'
michael@0 4359 };
michael@0 4360 break;
michael@0 4361 case SOUND_FORMAT_ADPCM:
michael@0 4362 var pcm16 = new Int16Array(samplesCount * channels);
michael@0 4363 decodeACPCMSoundData(data, pcm16, channels);
michael@0 4364 pcm = new Float32Array(samplesCount * channels);
michael@0 4365 for (var i = 0; i < pcm.length; i++)
michael@0 4366 pcm[i] = pcm16[i] / 32768;
michael@0 4367 packaged = packageWave(new Uint8Array(pcm16.buffer), sampleRate, channels, 16, !new Uint8Array(new Uint16Array([
michael@0 4368 1
michael@0 4369 ]).buffer)[0]);
michael@0 4370 break;
michael@0 4371 default:
michael@0 4372 throw new Error('Unsupported audio format: ' + tag.soundFormat);
michael@0 4373 }
michael@0 4374 var sound = {
michael@0 4375 type: 'sound',
michael@0 4376 id: tag.id,
michael@0 4377 sampleRate: sampleRate,
michael@0 4378 channels: channels,
michael@0 4379 pcm: pcm
michael@0 4380 };
michael@0 4381 if (packaged)
michael@0 4382 sound.packaged = packaged;
michael@0 4383 return sound;
michael@0 4384 }
michael@0 4385 var ACPCMIndexTables = [
michael@0 4386 [
michael@0 4387 -1,
michael@0 4388 2
michael@0 4389 ],
michael@0 4390 [
michael@0 4391 -1,
michael@0 4392 -1,
michael@0 4393 2,
michael@0 4394 4
michael@0 4395 ],
michael@0 4396 [
michael@0 4397 -1,
michael@0 4398 -1,
michael@0 4399 -1,
michael@0 4400 -1,
michael@0 4401 2,
michael@0 4402 4,
michael@0 4403 6,
michael@0 4404 8
michael@0 4405 ],
michael@0 4406 [
michael@0 4407 -1,
michael@0 4408 -1,
michael@0 4409 -1,
michael@0 4410 -1,
michael@0 4411 -1,
michael@0 4412 -1,
michael@0 4413 -1,
michael@0 4414 -1,
michael@0 4415 1,
michael@0 4416 2,
michael@0 4417 4,
michael@0 4418 6,
michael@0 4419 8,
michael@0 4420 10,
michael@0 4421 13,
michael@0 4422 16
michael@0 4423 ]
michael@0 4424 ];
michael@0 4425 var ACPCMStepSizeTable = [
michael@0 4426 7,
michael@0 4427 8,
michael@0 4428 9,
michael@0 4429 10,
michael@0 4430 11,
michael@0 4431 12,
michael@0 4432 13,
michael@0 4433 14,
michael@0 4434 16,
michael@0 4435 17,
michael@0 4436 19,
michael@0 4437 21,
michael@0 4438 23,
michael@0 4439 25,
michael@0 4440 28,
michael@0 4441 31,
michael@0 4442 34,
michael@0 4443 37,
michael@0 4444 41,
michael@0 4445 45,
michael@0 4446 50,
michael@0 4447 55,
michael@0 4448 60,
michael@0 4449 66,
michael@0 4450 73,
michael@0 4451 80,
michael@0 4452 88,
michael@0 4453 97,
michael@0 4454 107,
michael@0 4455 118,
michael@0 4456 130,
michael@0 4457 143,
michael@0 4458 157,
michael@0 4459 173,
michael@0 4460 190,
michael@0 4461 209,
michael@0 4462 230,
michael@0 4463 253,
michael@0 4464 279,
michael@0 4465 307,
michael@0 4466 337,
michael@0 4467 371,
michael@0 4468 408,
michael@0 4469 449,
michael@0 4470 494,
michael@0 4471 544,
michael@0 4472 598,
michael@0 4473 658,
michael@0 4474 724,
michael@0 4475 796,
michael@0 4476 876,
michael@0 4477 963,
michael@0 4478 1060,
michael@0 4479 1166,
michael@0 4480 1282,
michael@0 4481 1411,
michael@0 4482 1552,
michael@0 4483 1707,
michael@0 4484 1878,
michael@0 4485 2066,
michael@0 4486 2272,
michael@0 4487 2499,
michael@0 4488 2749,
michael@0 4489 3024,
michael@0 4490 3327,
michael@0 4491 3660,
michael@0 4492 4026,
michael@0 4493 4428,
michael@0 4494 4871,
michael@0 4495 5358,
michael@0 4496 5894,
michael@0 4497 6484,
michael@0 4498 7132,
michael@0 4499 7845,
michael@0 4500 8630,
michael@0 4501 9493,
michael@0 4502 10442,
michael@0 4503 11487,
michael@0 4504 12635,
michael@0 4505 13899,
michael@0 4506 15289,
michael@0 4507 16818,
michael@0 4508 18500,
michael@0 4509 20350,
michael@0 4510 22385,
michael@0 4511 24623,
michael@0 4512 27086,
michael@0 4513 29794,
michael@0 4514 32767
michael@0 4515 ];
michael@0 4516 function decodeACPCMSoundData(data, pcm16, channels) {
michael@0 4517 function readBits(n, signed) {
michael@0 4518 while (dataBufferLength < n) {
michael@0 4519 dataBuffer = dataBuffer << 8 | data[dataPosition++];
michael@0 4520 dataBufferLength += 8;
michael@0 4521 }
michael@0 4522 dataBufferLength -= n;
michael@0 4523 return dataBuffer >>> dataBufferLength & (1 << n) - 1;
michael@0 4524 }
michael@0 4525 var dataPosition = 0;
michael@0 4526 var dataBuffer = 0;
michael@0 4527 var dataBufferLength = 0;
michael@0 4528 var pcmPosition = 0;
michael@0 4529 var codeSize = readBits(2);
michael@0 4530 var indexTable = ACPCMIndexTables[codeSize];
michael@0 4531 while (pcmPosition < pcm16.length) {
michael@0 4532 var x = pcm16[pcmPosition++] = readBits(16) << 16 >> 16, x2;
michael@0 4533 var stepIndex = readBits(6), stepIndex2;
michael@0 4534 if (channels > 1) {
michael@0 4535 x2 = pcm16[pcmPosition++] = readBits(16) << 16 >> 16;
michael@0 4536 stepIndex2 = readBits(6);
michael@0 4537 }
michael@0 4538 var signMask = 1 << codeSize + 1;
michael@0 4539 for (var i = 0; i < 4095; i++) {
michael@0 4540 var nibble = readBits(codeSize + 2);
michael@0 4541 var step = ACPCMStepSizeTable[stepIndex];
michael@0 4542 var sum = 0;
michael@0 4543 for (var currentBit = signMask >> 1; currentBit; currentBit >>= 1, step >>= 1) {
michael@0 4544 if (nibble & currentBit)
michael@0 4545 sum += step;
michael@0 4546 }
michael@0 4547 x += (nibble & signMask ? -1 : 1) * (sum + step);
michael@0 4548 pcm16[pcmPosition++] = x = x < -32768 ? -32768 : x > 32767 ? 32767 : x;
michael@0 4549 stepIndex += indexTable[nibble & ~signMask];
michael@0 4550 stepIndex = stepIndex < 0 ? 0 : stepIndex > 88 ? 88 : stepIndex;
michael@0 4551 if (channels > 1) {
michael@0 4552 nibble = readBits(codeSize + 2);
michael@0 4553 step = ACPCMStepSizeTable[stepIndex2];
michael@0 4554 sum = 0;
michael@0 4555 for (var currentBit = signMask >> 1; currentBit; currentBit >>= 1, step >>= 1) {
michael@0 4556 if (nibble & currentBit)
michael@0 4557 sum += step;
michael@0 4558 }
michael@0 4559 x2 += (nibble & signMask ? -1 : 1) * (sum + step);
michael@0 4560 pcm16[pcmPosition++] = x2 = x2 < -32768 ? -32768 : x2 > 32767 ? 32767 : x2;
michael@0 4561 stepIndex2 += indexTable[nibble & ~signMask];
michael@0 4562 stepIndex2 = stepIndex2 < 0 ? 0 : stepIndex2 > 88 ? 88 : stepIndex2;
michael@0 4563 }
michael@0 4564 }
michael@0 4565 }
michael@0 4566 }
michael@0 4567 var nextSoundStreamId = 0;
michael@0 4568 function SwfSoundStream(samplesCount, sampleRate, channels) {
michael@0 4569 this.streamId = nextSoundStreamId++;
michael@0 4570 this.samplesCount = samplesCount;
michael@0 4571 this.sampleRate = sampleRate;
michael@0 4572 this.channels = channels;
michael@0 4573 this.format = null;
michael@0 4574 this.currentSample = 0;
michael@0 4575 }
michael@0 4576 SwfSoundStream.prototype = {
michael@0 4577 get info() {
michael@0 4578 return {
michael@0 4579 samplesCount: this.samplesCount,
michael@0 4580 sampleRate: this.sampleRate,
michael@0 4581 channels: this.channels,
michael@0 4582 format: this.format,
michael@0 4583 streamId: this.streamId
michael@0 4584 };
michael@0 4585 },
michael@0 4586 decode: function (data) {
michael@0 4587 throw new Error('SwfSoundStream.decode: not implemented');
michael@0 4588 }
michael@0 4589 };
michael@0 4590 function SwfSoundStream_decode_PCM(data) {
michael@0 4591 var pcm = new Float32Array(data.length);
michael@0 4592 for (var i = 0; i < pcm.length; i++)
michael@0 4593 pcm[i] = (data[i] - 128) / 128;
michael@0 4594 this.currentSample += pcm.length / this.channels;
michael@0 4595 return {
michael@0 4596 streamId: this.streamId,
michael@0 4597 samplesCount: pcm.length / this.channels,
michael@0 4598 pcm: pcm
michael@0 4599 };
michael@0 4600 }
michael@0 4601 function SwfSoundStream_decode_PCM_be(data) {
michael@0 4602 var pcm = new Float32Array(data.length / 2);
michael@0 4603 for (var i = 0, j = 0; i < pcm.length; i++, j += 2)
michael@0 4604 pcm[i] = (data[j] << 24 | data[j + 1] << 16) / 2147483648;
michael@0 4605 this.currentSample += pcm.length / this.channels;
michael@0 4606 return {
michael@0 4607 streamId: this.streamId,
michael@0 4608 samplesCount: pcm.length / this.channels,
michael@0 4609 pcm: pcm
michael@0 4610 };
michael@0 4611 }
michael@0 4612 function SwfSoundStream_decode_PCM_le(data) {
michael@0 4613 var pcm = new Float32Array(data.length / 2);
michael@0 4614 for (var i = 0, j = 0; i < pcm.length; i++, j += 2)
michael@0 4615 pcm[i] = (data[j + 1] << 24 | data[j] << 16) / 2147483648;
michael@0 4616 this.currentSample += pcm.length / this.channels;
michael@0 4617 return {
michael@0 4618 streamId: this.streamId,
michael@0 4619 samplesCount: pcm.length / this.channels,
michael@0 4620 pcm: pcm
michael@0 4621 };
michael@0 4622 }
michael@0 4623 function SwfSoundStream_decode_MP3(data) {
michael@0 4624 var samplesCount = data[1] << 8 | data[0];
michael@0 4625 var seek = data[3] << 8 | data[2];
michael@0 4626 this.currentSample += samplesCount;
michael@0 4627 return {
michael@0 4628 streamId: this.streamId,
michael@0 4629 samplesCount: samplesCount,
michael@0 4630 data: new Uint8Array(data.subarray(4)),
michael@0 4631 seek: seek
michael@0 4632 };
michael@0 4633 }
michael@0 4634 function createSoundStream(tag) {
michael@0 4635 var channels = tag.streamType == SOUND_TYPE_STEREO ? 2 : 1;
michael@0 4636 var samplesCount = tag.samplesCount;
michael@0 4637 var sampleRate = SOUND_RATES[tag.streamRate];
michael@0 4638 var stream = new SwfSoundStream(samplesCount, sampleRate, channels);
michael@0 4639 switch (tag.streamCompression) {
michael@0 4640 case SOUND_FORMAT_PCM_BE:
michael@0 4641 stream.format = 'wave';
michael@0 4642 if (tag.soundSize == SOUND_SIZE_16_BIT) {
michael@0 4643 stream.decode = SwfSoundStream_decode_PCM_be;
michael@0 4644 } else {
michael@0 4645 stream.decode = SwfSoundStream_decode_PCM;
michael@0 4646 }
michael@0 4647 break;
michael@0 4648 case SOUND_FORMAT_PCM_LE:
michael@0 4649 stream.format = 'wave';
michael@0 4650 if (tag.soundSize == SOUND_SIZE_16_BIT) {
michael@0 4651 stream.decode = SwfSoundStream_decode_PCM_le;
michael@0 4652 } else {
michael@0 4653 stream.decode = SwfSoundStream_decode_PCM;
michael@0 4654 }
michael@0 4655 break;
michael@0 4656 case SOUND_FORMAT_MP3:
michael@0 4657 stream.format = 'mp3';
michael@0 4658 stream.decode = SwfSoundStream_decode_MP3;
michael@0 4659 break;
michael@0 4660 default:
michael@0 4661 throw new Error('Unsupported audio format: ' + tag.soundFormat);
michael@0 4662 }
michael@0 4663 return stream;
michael@0 4664 }
michael@0 4665 function defineText(tag, dictionary) {
michael@0 4666 var dependencies = [];
michael@0 4667 if (tag.hasFont) {
michael@0 4668 var font = dictionary[tag.fontId];
michael@0 4669 tag.font = font.uniqueName;
michael@0 4670 dependencies.push(font.id);
michael@0 4671 }
michael@0 4672 var props = {
michael@0 4673 type: 'text',
michael@0 4674 id: tag.id,
michael@0 4675 variableName: tag.variableName,
michael@0 4676 tag: tag
michael@0 4677 };
michael@0 4678 if (dependencies.length)
michael@0 4679 props.require = dependencies;
michael@0 4680 return props;
michael@0 4681 }
michael@0 4682 var isWorker = typeof window === 'undefined';
michael@0 4683 if (isWorker) {
michael@0 4684 importScripts('../../../lib/mp3/mp3.js');
michael@0 4685 self.addEventListener('message', function (e) {
michael@0 4686 var data = e.data;
michael@0 4687 var sessionId = data.sessionId;
michael@0 4688 try {
michael@0 4689 switch (data.action) {
michael@0 4690 case 'create':
michael@0 4691 var session = new Session(sessionId);
michael@0 4692 sessions[sessionId] = session;
michael@0 4693 break;
michael@0 4694 case 'close':
michael@0 4695 var session = sessions[sessionId];
michael@0 4696 if (session) {
michael@0 4697 session.close();
michael@0 4698 sessions[sessionId] = null;
michael@0 4699 }
michael@0 4700 break;
michael@0 4701 case 'decode':
michael@0 4702 var session = sessions[sessionId];
michael@0 4703 if (!session) {
michael@0 4704 throw new Error('mp3 decoding session is unavailable');
michael@0 4705 }
michael@0 4706 session.decode(data.data);
michael@0 4707 break;
michael@0 4708 }
michael@0 4709 } catch (ex) {
michael@0 4710 self.postMessage({
michael@0 4711 sessionId: sessionId,
michael@0 4712 action: 'error',
michael@0 4713 message: ex.message
michael@0 4714 });
michael@0 4715 }
michael@0 4716 }, false);
michael@0 4717 var sessions = {};
michael@0 4718 function Session(id) {
michael@0 4719 this.id = id;
michael@0 4720 if (typeof MP3Decoder === 'undefined') {
michael@0 4721 throw new Error('mp3 decoder is not available');
michael@0 4722 }
michael@0 4723 var decoder = new MP3Decoder();
michael@0 4724 decoder.onframedata = function (frameData, channels, sampleRate, bitRate) {
michael@0 4725 self.postMessage({
michael@0 4726 sessionId: this.id,
michael@0 4727 action: 'frame',
michael@0 4728 frameData: frameData,
michael@0 4729 channels: channels,
michael@0 4730 sampleRate: sampleRate,
michael@0 4731 bitRate: bitRate
michael@0 4732 });
michael@0 4733 }.bind(this);
michael@0 4734 decoder.onid3tag = function (data) {
michael@0 4735 self.postMessage({
michael@0 4736 sessionId: this.id,
michael@0 4737 action: 'id3',
michael@0 4738 id3Data: data
michael@0 4739 });
michael@0 4740 }.bind(this);
michael@0 4741 this.decoder = decoder;
michael@0 4742 }
michael@0 4743 Session.prototype = {
michael@0 4744 decode: function (data) {
michael@0 4745 this.decoder.push(data);
michael@0 4746 },
michael@0 4747 close: function () {
michael@0 4748 self.postMessage({
michael@0 4749 sessionId: this.id,
michael@0 4750 action: 'closed'
michael@0 4751 });
michael@0 4752 }
michael@0 4753 };
michael@0 4754 self.console = {
michael@0 4755 log: function (s) {
michael@0 4756 self.postMessage({
michael@0 4757 action: 'console',
michael@0 4758 method: 'log',
michael@0 4759 message: s
michael@0 4760 });
michael@0 4761 },
michael@0 4762 error: function (s) {
michael@0 4763 self.postMessage({
michael@0 4764 action: 'console',
michael@0 4765 method: 'error',
michael@0 4766 message: s
michael@0 4767 });
michael@0 4768 }
michael@0 4769 };
michael@0 4770 } else {
michael@0 4771 var mp3Worker;
michael@0 4772 function createMP3Worker() {
michael@0 4773 var worker = new Worker(SHUMWAY_ROOT + 'swf/mp3worker.js');
michael@0 4774 worker.addEventListener('message', function (e) {
michael@0 4775 if (e.data.action === 'console') {
michael@0 4776 console[e.data.method].call(console, e.data.message);
michael@0 4777 }
michael@0 4778 });
michael@0 4779 return worker;
michael@0 4780 }
michael@0 4781 var nextSessionId = 0;
michael@0 4782 function MP3DecoderSession() {
michael@0 4783 mp3Worker = mp3Worker || createMP3Worker();
michael@0 4784 var sessionId = nextSessionId++;
michael@0 4785 this.id = sessionId;
michael@0 4786 this.onworkermessage = function (e) {
michael@0 4787 if (e.data.sessionId !== sessionId)
michael@0 4788 return;
michael@0 4789 var action = e.data.action;
michael@0 4790 switch (action) {
michael@0 4791 case 'closed':
michael@0 4792 if (this.onclosed)
michael@0 4793 this.onclosed();
michael@0 4794 mp3Worker.removeEventListener('message', this.onworkermessage, false);
michael@0 4795 break;
michael@0 4796 case 'frame':
michael@0 4797 this.onframedata(e.data.frameData, e.data.channels, e.data.sampleRate, e.data.bitRate);
michael@0 4798 break;
michael@0 4799 case 'id3':
michael@0 4800 if (this.onid3tag)
michael@0 4801 this.onid3tag(e.data.id3Data);
michael@0 4802 break;
michael@0 4803 case 'error':
michael@0 4804 if (this.onerror)
michael@0 4805 this.onerror(e.data.message);
michael@0 4806 break;
michael@0 4807 }
michael@0 4808 }.bind(this);
michael@0 4809 mp3Worker.addEventListener('message', this.onworkermessage, false);
michael@0 4810 mp3Worker.postMessage({
michael@0 4811 sessionId: sessionId,
michael@0 4812 action: 'create'
michael@0 4813 });
michael@0 4814 }
michael@0 4815 MP3DecoderSession.prototype = {
michael@0 4816 pushAsync: function (data) {
michael@0 4817 mp3Worker.postMessage({
michael@0 4818 sessionId: this.id,
michael@0 4819 action: 'decode',
michael@0 4820 data: data
michael@0 4821 });
michael@0 4822 },
michael@0 4823 close: function () {
michael@0 4824 mp3Worker.postMessage({
michael@0 4825 sessionId: this.id,
michael@0 4826 action: 'close'
michael@0 4827 });
michael@0 4828 }
michael@0 4829 };
michael@0 4830 MP3DecoderSession.processAll = function (data, onloaded) {
michael@0 4831 var currentBufferSize = 8000;
michael@0 4832 var currentBuffer = new Float32Array(currentBufferSize);
michael@0 4833 var bufferPosition = 0;
michael@0 4834 var id3Tags = [];
michael@0 4835 var sessionAborted = false;
michael@0 4836 var session = new MP3DecoderSession();
michael@0 4837 session.onframedata = function (frameData, channels, sampleRate, bitRate) {
michael@0 4838 var needed = frameData.length + bufferPosition;
michael@0 4839 if (needed > currentBufferSize) {
michael@0 4840 do {
michael@0 4841 currentBufferSize *= 2;
michael@0 4842 } while (needed > currentBufferSize);
michael@0 4843 var newBuffer = new Float32Array(currentBufferSize);
michael@0 4844 newBuffer.set(currentBuffer);
michael@0 4845 currentBuffer = newBuffer;
michael@0 4846 }
michael@0 4847 currentBuffer.set(frameData, bufferPosition);
michael@0 4848 bufferPosition += frameData.length;
michael@0 4849 };
michael@0 4850 session.onid3tag = function (tagData) {
michael@0 4851 id3Tags.push(tagData);
michael@0 4852 };
michael@0 4853 session.onclosed = function () {
michael@0 4854 if (sessionAborted)
michael@0 4855 return;
michael@0 4856 onloaded(currentBuffer.subarray(0, bufferPosition), id3Tags);
michael@0 4857 };
michael@0 4858 session.onerror = function (error) {
michael@0 4859 if (sessionAborted)
michael@0 4860 return;
michael@0 4861 sessionAborted = true;
michael@0 4862 onloaded(null, null, error);
michael@0 4863 };
michael@0 4864 session.pushAsync(data);
michael@0 4865 session.close();
michael@0 4866 };
michael@0 4867 }
michael@0 4868 SWF.embed = function (file, doc, container, options) {
michael@0 4869 var canvas = doc.createElement('canvas');
michael@0 4870 var ctx = canvas.getContext('2d');
michael@0 4871 var loader = new flash.display.Loader();
michael@0 4872 var loaderInfo = loader._contentLoaderInfo;
michael@0 4873 var stage = new flash.display.Stage();
michael@0 4874 var pixelRatio = 1;
michael@0 4875 var forceHidpiSetting = forceHidpi.value;
michael@0 4876 stage._loader = loader;
michael@0 4877 loaderInfo._parameters = options.movieParams;
michael@0 4878 loaderInfo._url = options.url || (typeof file === 'string' ? file : null);
michael@0 4879 loaderInfo._loaderURL = options.loaderURL || loaderInfo._url;
michael@0 4880 loader._parent = stage;
michael@0 4881 loader._stage = stage;
michael@0 4882 function setCanvasSize(width, height) {
michael@0 4883 if (pixelRatio === 1) {
michael@0 4884 canvas.width = width | 0;
michael@0 4885 canvas.height = height | 0;
michael@0 4886 return;
michael@0 4887 }
michael@0 4888 var canvasWidth = Math.floor(width * pixelRatio);
michael@0 4889 var canvasHeight = Math.floor(height * pixelRatio);
michael@0 4890 canvas.style.width = canvasWidth / pixelRatio + 'px';
michael@0 4891 canvas.style.height = canvasHeight / pixelRatio + 'px';
michael@0 4892 canvas.width = canvasWidth;
michael@0 4893 canvas.height = canvasHeight;
michael@0 4894 }
michael@0 4895 function fitCanvas(container) {
michael@0 4896 setCanvasSize(container.clientWidth, container.clientHeight);
michael@0 4897 stage._invalid = true;
michael@0 4898 }
michael@0 4899 loaderInfo._addEventListener('init', function () {
michael@0 4900 if (forceHidpiSetting || loaderInfo._swfVersion >= 18) {
michael@0 4901 pixelRatio = 'devicePixelRatio' in window ? window.devicePixelRatio : 1;
michael@0 4902 }
michael@0 4903 canvas._pixelRatio = pixelRatio;
michael@0 4904 stage._contentsScaleFactor = pixelRatio;
michael@0 4905 if (container.clientHeight) {
michael@0 4906 fitCanvas(container);
michael@0 4907 window.addEventListener('resize', function () {
michael@0 4908 fitCanvas(container);
michael@0 4909 });
michael@0 4910 } else {
michael@0 4911 setCanvasSize(stage._stageWidth / 20, stage._stageHeight / 20);
michael@0 4912 }
michael@0 4913 container.setAttribute('style', 'position: relative');
michael@0 4914 canvas.addEventListener('click', function () {
michael@0 4915 ShumwayKeyboardListener.focus = stage;
michael@0 4916 stage._mouseTarget._dispatchEvent('click');
michael@0 4917 });
michael@0 4918 canvas.addEventListener('dblclick', function () {
michael@0 4919 if (stage._mouseTarget._doubleClickEnabled) {
michael@0 4920 stage._mouseTarget._dispatchEvent('doubleClick');
michael@0 4921 }
michael@0 4922 });
michael@0 4923 canvas.addEventListener('mousedown', function () {
michael@0 4924 stage._mouseEvents.push('mousedown');
michael@0 4925 });
michael@0 4926 canvas.addEventListener('mousemove', function (domEvt) {
michael@0 4927 var node = this;
michael@0 4928 var left = 0;
michael@0 4929 var top = 0;
michael@0 4930 if (node.offsetParent) {
michael@0 4931 do {
michael@0 4932 left += node.offsetLeft;
michael@0 4933 top += node.offsetTop;
michael@0 4934 } while (node = node.offsetParent);
michael@0 4935 }
michael@0 4936 var m = stage._concatenatedTransform;
michael@0 4937 var mouseX = ((domEvt.pageX - left) * pixelRatio - m.tx / 20) / m.a;
michael@0 4938 var mouseY = ((domEvt.pageY - top) * pixelRatio - m.ty / 20) / m.d;
michael@0 4939 if (mouseX !== stage._mouseX || mouseY !== stage._mouseY) {
michael@0 4940 stage._mouseMoved = true;
michael@0 4941 stage._mouseX = mouseX * 20;
michael@0 4942 stage._mouseY = mouseY * 20;
michael@0 4943 }
michael@0 4944 });
michael@0 4945 canvas.addEventListener('mouseup', function () {
michael@0 4946 stage._mouseEvents.push('mouseup');
michael@0 4947 });
michael@0 4948 canvas.addEventListener('mouseover', function () {
michael@0 4949 stage._mouseMoved = true;
michael@0 4950 stage._mouseOver = true;
michael@0 4951 });
michael@0 4952 canvas.addEventListener('mouseout', function () {
michael@0 4953 stage._mouseMoved = true;
michael@0 4954 stage._mouseOver = false;
michael@0 4955 });
michael@0 4956 window.addEventListener('message', function (evt) {
michael@0 4957 var data = evt.data;
michael@0 4958 if (typeof data !== 'object' || data === null) {
michael@0 4959 return;
michael@0 4960 }
michael@0 4961 var type = data.type;
michael@0 4962 switch (type) {
michael@0 4963 case 'mousemove':
michael@0 4964 case 'mouseup':
michael@0 4965 case 'mousedown':
michael@0 4966 var isMouseMove = type === 'mousemove';
michael@0 4967 stage._mouseMoved = true;
michael@0 4968 stage._mouseOver = true;
michael@0 4969 stage._mouseX = data.x * 20;
michael@0 4970 stage._mouseY = data.y * 20;
michael@0 4971 if (!isMouseMove) {
michael@0 4972 stage._mouseEvents.push(type);
michael@0 4973 }
michael@0 4974 break;
michael@0 4975 case 'mouseover':
michael@0 4976 case 'mouseout':
michael@0 4977 stage._mouseMoved = true;
michael@0 4978 stage._mouseOver = type === 'mouseover';
michael@0 4979 break;
michael@0 4980 case 'keyup':
michael@0 4981 case 'keydown':
michael@0 4982 stage._dispatchEvent(new flash.events.KeyboardEvent(type === 'keyup' ? 'keyUp' : 'keyDown', true, false, data.charCode, data.keyCode, data.keyLocation, data.ctrlKey || false, data.altKey || false, data.shiftKey || false));
michael@0 4983 break;
michael@0 4984 }
michael@0 4985 }, false);
michael@0 4986 var bgcolor = loaderInfo._backgroundColor;
michael@0 4987 if (options.objectParams) {
michael@0 4988 var m;
michael@0 4989 if (options.objectParams.bgcolor && (m = /#([0-9A-F]{6})/i.exec(options.objectParams.bgcolor))) {
michael@0 4990 var hexColor = parseInt(m[1], 16);
michael@0 4991 bgcolor = {
michael@0 4992 red: hexColor >> 16 & 255,
michael@0 4993 green: hexColor >> 8 & 255,
michael@0 4994 blue: hexColor & 255,
michael@0 4995 alpha: 255
michael@0 4996 };
michael@0 4997 }
michael@0 4998 if (options.objectParams.wmode === 'transparent') {
michael@0 4999 bgcolor = {
michael@0 5000 red: 0,
michael@0 5001 green: 0,
michael@0 5002 blue: 0,
michael@0 5003 alpha: 0
michael@0 5004 };
michael@0 5005 }
michael@0 5006 }
michael@0 5007 stage._color = bgcolor;
michael@0 5008 ctx.fillStyle = rgbaObjToStr(bgcolor);
michael@0 5009 ctx.fillRect(0, 0, canvas.width, canvas.height);
michael@0 5010 var root = loader._content;
michael@0 5011 root._dispatchEvent('added', undefined, true);
michael@0 5012 root._dispatchEvent('addedToStage');
michael@0 5013 container.appendChild(canvas);
michael@0 5014 stage._domContainer = container;
michael@0 5015 if (options.onStageInitialized) {
michael@0 5016 options.onStageInitialized(stage);
michael@0 5017 }
michael@0 5018 var startPromise = options.startPromise || Promise.resolve();
michael@0 5019 startPromise.then(function () {
michael@0 5020 renderStage(stage, ctx, options);
michael@0 5021 });
michael@0 5022 });
michael@0 5023 if (options.onParsed) {
michael@0 5024 loaderInfo._addEventListener('parsed', function () {
michael@0 5025 options.onParsed();
michael@0 5026 });
michael@0 5027 }
michael@0 5028 if (options.onComplete) {
michael@0 5029 loaderInfo._addEventListener('complete', function () {
michael@0 5030 options.onComplete();
michael@0 5031 });
michael@0 5032 }
michael@0 5033 loader._load(typeof file === 'string' ? new flash.net.URLRequest(file) : file);
michael@0 5034 return loader;
michael@0 5035 };
michael@0 5036 var rendererOptions = coreOptions.register(new OptionSet('Renderer Options'));
michael@0 5037 var traceRenderer = rendererOptions.register(new Option('tr', 'traceRenderer', 'number', 0, 'trace renderer execution'));
michael@0 5038 var disableRenderVisitor = rendererOptions.register(new Option('drv', 'disableRenderVisitor', 'boolean', false, 'disable render visitor'));
michael@0 5039 var disableMouseVisitor = rendererOptions.register(new Option('dmv', 'disableMouseVisitor', 'boolean', false, 'disable mouse visitor'));
michael@0 5040 var showRedrawRegions = rendererOptions.register(new Option('rr', 'showRedrawRegions', 'boolean', false, 'show redraw regions'));
michael@0 5041 var renderAsWireframe = rendererOptions.register(new Option('raw', 'renderAsWireframe', 'boolean', false, 'render as wireframe'));
michael@0 5042 var showQuadTree = rendererOptions.register(new Option('qt', 'showQuadTree', 'boolean', false, 'show quad tree'));
michael@0 5043 var turboMode = rendererOptions.register(new Option('', 'turbo', 'boolean', false, 'turbo mode'));
michael@0 5044 var forceHidpi = rendererOptions.register(new Option('', 'forceHidpi', 'boolean', false, 'force hidpi'));
michael@0 5045 var skipFrameDraw = rendererOptions.register(new Option('', 'skipFrameDraw', 'boolean', false, 'skip frame when not on time'));
michael@0 5046 var hud = rendererOptions.register(new Option('', 'hud', 'boolean', false, 'show hud mode'));
michael@0 5047 var dummyAnimation = rendererOptions.register(new Option('', 'dummy', 'boolean', false, 'show test balls animation'));
michael@0 5048 var enableConstructChildren = rendererOptions.register(new Option('', 'constructChildren', 'boolean', true, 'Construct Children'));
michael@0 5049 var enableEnterFrame = rendererOptions.register(new Option('', 'enterFrame', 'boolean', true, 'Enter Frame'));
michael@0 5050 var enableAdvanceFrame = rendererOptions.register(new Option('', 'advanceFrame', 'boolean', true, 'Advance Frame'));
michael@0 5051 var CanvasCache = {
michael@0 5052 cache: [],
michael@0 5053 getCanvas: function getCanvas(protoCanvas) {
michael@0 5054 var tempCanvas = this.cache.shift();
michael@0 5055 if (!tempCanvas) {
michael@0 5056 tempCanvas = {
michael@0 5057 canvas: document.createElement('canvas')
michael@0 5058 };
michael@0 5059 tempCanvas.ctx = tempCanvas.canvas.getContext('2d');
michael@0 5060 }
michael@0 5061 tempCanvas.canvas.width = protoCanvas.width;
michael@0 5062 tempCanvas.canvas.height = protoCanvas.height;
michael@0 5063 tempCanvas.ctx.save();
michael@0 5064 return tempCanvas;
michael@0 5065 },
michael@0 5066 releaseCanvas: function releaseCanvas(tempCanvas) {
michael@0 5067 tempCanvas.ctx.restore();
michael@0 5068 this.cache.push(tempCanvas);
michael@0 5069 }
michael@0 5070 };
michael@0 5071 function isCanvasVisible(canvas) {
michael@0 5072 if (canvas.ownerDocument.hidden) {
michael@0 5073 return false;
michael@0 5074 }
michael@0 5075 if (canvas.mozVisible === false) {
michael@0 5076 return false;
michael@0 5077 }
michael@0 5078 return true;
michael@0 5079 }
michael@0 5080 function visitContainer(container, visitor, context) {
michael@0 5081 var children = container._children;
michael@0 5082 visitor.childrenStart(container);
michael@0 5083 for (var i = 0, n = children.length; i < n; i++) {
michael@0 5084 var child = children[i];
michael@0 5085 if (!child) {
michael@0 5086 continue;
michael@0 5087 }
michael@0 5088 if (visitor.ignoreVisibleAttribute || child._visible && !child._maskedObject) {
michael@0 5089 visitor.visit(child, visitContainer, context);
michael@0 5090 }
michael@0 5091 }
michael@0 5092 visitor.childrenEnd(container);
michael@0 5093 }
michael@0 5094 var BlendModeNameMap = {
michael@0 5095 'normal': 'normal',
michael@0 5096 'multiply': 'multiply',
michael@0 5097 'screen': 'screen',
michael@0 5098 'lighten': 'lighten',
michael@0 5099 'darken': 'darken',
michael@0 5100 'difference': 'difference',
michael@0 5101 'overlay': 'overlay',
michael@0 5102 'hardlight': 'hard-light'
michael@0 5103 };
michael@0 5104 function getBlendModeName(blendMode) {
michael@0 5105 return BlendModeNameMap[blendMode] || 'normal';
michael@0 5106 }
michael@0 5107 function RenderVisitor(root, ctx, invalidPath, refreshStage) {
michael@0 5108 this.root = root;
michael@0 5109 this.ctx = ctx;
michael@0 5110 this.depth = 0;
michael@0 5111 this.invalidPath = invalidPath;
michael@0 5112 this.refreshStage = refreshStage;
michael@0 5113 this.clipDepth = null;
michael@0 5114 this.clipStack = null;
michael@0 5115 }
michael@0 5116 RenderVisitor.prototype = {
michael@0 5117 ignoreVisibleAttribute: false,
michael@0 5118 start: function () {
michael@0 5119 visitContainer(this.root, this, new RenderingContext(this.refreshStage, this.invalidPath));
michael@0 5120 },
michael@0 5121 startFragment: function (matrix) {
michael@0 5122 var root = this.root;
michael@0 5123 var currentTransform = root._currentTransform;
michael@0 5124 var t = currentTransform;
michael@0 5125 if (matrix) {
michael@0 5126 t = root._currentTransform = {
michael@0 5127 a: matrix.a,
michael@0 5128 b: matrix.b,
michael@0 5129 c: matrix.c,
michael@0 5130 d: matrix.d,
michael@0 5131 tx: matrix.tx * 20 | 0,
michael@0 5132 ty: matrix.ty * 20 | 0
michael@0 5133 };
michael@0 5134 root._invalidateTransform();
michael@0 5135 }
michael@0 5136 var inverse;
michael@0 5137 if (t) {
michael@0 5138 inverse = new flash.geom.Matrix(t.a, t.b, t.c, t.d, t.tx / 20, t.ty / 20);
michael@0 5139 inverse.invert();
michael@0 5140 this.ctx.save();
michael@0 5141 this.ctx.transform(inverse.a, inverse.b, inverse.c, inverse.d, inverse.tx, inverse.ty);
michael@0 5142 }
michael@0 5143 this.visit(root, visitContainer, new RenderingContext(this.refreshStage, this.invalidPath));
michael@0 5144 if (t) {
michael@0 5145 this.ctx.restore();
michael@0 5146 }
michael@0 5147 if (matrix) {
michael@0 5148 root._currentTransform = currentTransform;
michael@0 5149 root._invalidateTransform();
michael@0 5150 }
michael@0 5151 },
michael@0 5152 childrenStart: function (parent) {
michael@0 5153 if (this.depth === 0) {
michael@0 5154 var ctx = this.ctx;
michael@0 5155 ctx.save();
michael@0 5156 if (this.invalidPath && !this.refreshStage && !renderAsWireframe.value) {
michael@0 5157 this.invalidPath.draw(ctx, false, 0, null);
michael@0 5158 ctx.clip();
michael@0 5159 }
michael@0 5160 var bgcolor = this.root._color;
michael@0 5161 if (bgcolor) {
michael@0 5162 if (bgcolor.alpha < 255) {
michael@0 5163 ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
michael@0 5164 }
michael@0 5165 if (bgcolor.alpha > 0) {
michael@0 5166 ctx.fillStyle = rgbaObjToStr(bgcolor);
michael@0 5167 if (this.invalidPath && !this.refreshStage && !renderAsWireframe.value) {
michael@0 5168 ctx.fill();
michael@0 5169 } else {
michael@0 5170 ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
michael@0 5171 }
michael@0 5172 }
michael@0 5173 }
michael@0 5174 ctx.mozFillRule = 'evenodd';
michael@0 5175 }
michael@0 5176 this.depth++;
michael@0 5177 if (this.clipDepth && this.clipDepth.length > 0) {
michael@0 5178 this.clipStack = {
michael@0 5179 depth: this.depth,
michael@0 5180 clip: this.clipDepth,
michael@0 5181 next: this.clipStack
michael@0 5182 };
michael@0 5183 this.clipDepth = null;
michael@0 5184 }
michael@0 5185 },
michael@0 5186 childrenEnd: function (parent) {
michael@0 5187 if (this.clipDepth) {
michael@0 5188 while (this.clipDepth.length > 0) {
michael@0 5189 var clipDepthInfo = this.clipDepth.pop();
michael@0 5190 this.clipEnd(clipDepthInfo);
michael@0 5191 this.ctx = clipDepthInfo.ctx;
michael@0 5192 }
michael@0 5193 this.clipDepth = null;
michael@0 5194 }
michael@0 5195 if (this.clipStack && this.clipStack.depth === this.depth) {
michael@0 5196 this.clipDepth = this.clipStack.clip;
michael@0 5197 this.clipStack = this.clipStack.next;
michael@0 5198 }
michael@0 5199 this.depth--;
michael@0 5200 if (this.depth === 0) {
michael@0 5201 this.ctx.restore();
michael@0 5202 this.invalidPath = null;
michael@0 5203 }
michael@0 5204 },
michael@0 5205 visit: function (child, visitContainer, context) {
michael@0 5206 var ctx = this.ctx;
michael@0 5207 var parentHasClippingMask = context.isClippingMask;
michael@0 5208 var parentColorTransform = context.colorTransform;
michael@0 5209 var clippingMask = parentHasClippingMask === true;
michael@0 5210 if (child._cxform) {
michael@0 5211 context.colorTransform = parentColorTransform.applyCXForm(child._cxform);
michael@0 5212 }
michael@0 5213 if (!clippingMask) {
michael@0 5214 while (this.clipDepth && this.clipDepth.length > 0 && child._depth > this.clipDepth[0].clipDepth) {
michael@0 5215 var clipDepthInfo = this.clipDepth.shift();
michael@0 5216 this.clipEnd(clipDepthInfo);
michael@0 5217 context.parentCtxs.shift();
michael@0 5218 ctx = this.ctx = clipDepthInfo.ctx;
michael@0 5219 }
michael@0 5220 if (this.clipDepth && this.clipDepth.length > 0 && child._depth <= this.clipDepth[0].clipDepth) {
michael@0 5221 ctx = this.ctx = this.clipDepth[0].maskee.ctx;
michael@0 5222 }
michael@0 5223 if (child._clipDepth) {
michael@0 5224 context.isClippingMask = clippingMask = true;
michael@0 5225 var clipDepthInfo = this.clipStart(child);
michael@0 5226 if (!this.clipDepth) {
michael@0 5227 this.clipDepth = [
michael@0 5228 clipDepthInfo
michael@0 5229 ];
michael@0 5230 } else {
michael@0 5231 this.clipDepth.unshift(clipDepthInfo);
michael@0 5232 }
michael@0 5233 context.parentCtxs.unshift(ctx);
michael@0 5234 ctx = this.ctx = clipDepthInfo.mask.ctx;
michael@0 5235 }
michael@0 5236 }
michael@0 5237 if (clippingMask && child._isContainer) {
michael@0 5238 ctx.save();
michael@0 5239 renderDisplayObject(child, ctx, context);
michael@0 5240 for (var i = 0, n = child._children.length; i < n; i++) {
michael@0 5241 var child1 = child._children[i];
michael@0 5242 if (!child1) {
michael@0 5243 continue;
michael@0 5244 }
michael@0 5245 if (this.ignoreVisibleAttribute || child1._visible && !child1._maskedObject) {
michael@0 5246 this.visit(child1, visitContainer, context);
michael@0 5247 }
michael@0 5248 }
michael@0 5249 ctx.restore();
michael@0 5250 ctx.fill();
michael@0 5251 context.isClippingMask = parentHasClippingMask;
michael@0 5252 context.colorTransform = parentColorTransform;
michael@0 5253 return;
michael@0 5254 }
michael@0 5255 ctx.save();
michael@0 5256 ctx.globalCompositeOperation = getBlendModeName(child._blendMode);
michael@0 5257 if (child._mask) {
michael@0 5258 var clipInfo = this.clipStart(child);
michael@0 5259 var mask = clipInfo.mask;
michael@0 5260 var maskee = clipInfo.maskee;
michael@0 5261 context.parentCtxs.push(ctx);
michael@0 5262 var savedClipDepth = this.clipDepth;
michael@0 5263 this.clipDepth = null;
michael@0 5264 this.ctx = mask.ctx;
michael@0 5265 this.visit(child._mask, visitContainer, new RenderingContext(this.refreshStage));
michael@0 5266 this.ctx = ctx;
michael@0 5267 this.clipDepth = savedClipDepth;
michael@0 5268 renderDisplayObject(child, maskee.ctx, context);
michael@0 5269 if (child._isContainer) {
michael@0 5270 this.ctx = maskee.ctx;
michael@0 5271 visitContainer(child, this, context);
michael@0 5272 this.ctx = ctx;
michael@0 5273 }
michael@0 5274 context.parentCtxs.pop();
michael@0 5275 this.clipEnd(clipInfo);
michael@0 5276 } else {
michael@0 5277 renderDisplayObject(child, ctx, context);
michael@0 5278 if (child._isContainer) {
michael@0 5279 visitContainer(child, this, context);
michael@0 5280 }
michael@0 5281 }
michael@0 5282 ctx.restore();
michael@0 5283 if (clippingMask) {
michael@0 5284 ctx.fill();
michael@0 5285 }
michael@0 5286 context.isClippingMask = parentHasClippingMask;
michael@0 5287 context.colorTransform = parentColorTransform;
michael@0 5288 },
michael@0 5289 clipStart: function (child) {
michael@0 5290 var m = child._parent._getConcatenatedTransform(null, true);
michael@0 5291 var tx = m.tx / 20;
michael@0 5292 var ty = m.ty / 20;
michael@0 5293 var mask = CanvasCache.getCanvas(this.ctx.canvas);
michael@0 5294 mask.ctx.setTransform(m.a, m.b, m.c, m.d, tx, ty);
michael@0 5295 var maskee = CanvasCache.getCanvas(this.ctx.canvas);
michael@0 5296 maskee.ctx.setTransform(m.a, m.b, m.c, m.d, tx, ty);
michael@0 5297 var clipInfo = {
michael@0 5298 ctx: this.ctx,
michael@0 5299 mask: mask,
michael@0 5300 maskee: maskee,
michael@0 5301 clipDepth: child._clipDepth
michael@0 5302 };
michael@0 5303 return clipInfo;
michael@0 5304 },
michael@0 5305 clipEnd: function (clipInfo) {
michael@0 5306 var ctx = clipInfo.ctx;
michael@0 5307 var mask = clipInfo.mask;
michael@0 5308 var maskee = clipInfo.maskee;
michael@0 5309 maskee.ctx.globalCompositeOperation = 'destination-in';
michael@0 5310 maskee.ctx.setTransform(1, 0, 0, 1, 0, 0);
michael@0 5311 maskee.ctx.drawImage(mask.canvas, 0, 0);
michael@0 5312 ctx.save();
michael@0 5313 ctx.setTransform(1, 0, 0, 1, 0, 0);
michael@0 5314 ctx.drawImage(maskee.canvas, 0, 0);
michael@0 5315 ctx.restore();
michael@0 5316 CanvasCache.releaseCanvas(mask);
michael@0 5317 CanvasCache.releaseCanvas(maskee);
michael@0 5318 }
michael@0 5319 };
michael@0 5320 function RenderingColorTransform() {
michael@0 5321 this.mode = null;
michael@0 5322 this.transform = [
michael@0 5323 1,
michael@0 5324 1,
michael@0 5325 1,
michael@0 5326 1,
michael@0 5327 0,
michael@0 5328 0,
michael@0 5329 0,
michael@0 5330 0
michael@0 5331 ];
michael@0 5332 }
michael@0 5333 RenderingColorTransform.prototype = {
michael@0 5334 applyCXForm: function (cxform) {
michael@0 5335 var t = this.transform;
michael@0 5336 t = [
michael@0 5337 t[0] * cxform.redMultiplier / 256,
michael@0 5338 t[1] * cxform.greenMultiplier / 256,
michael@0 5339 t[2] * cxform.blueMultiplier / 256,
michael@0 5340 t[3] * cxform.alphaMultiplier / 256,
michael@0 5341 t[4] * cxform.redMultiplier / 256 + cxform.redOffset,
michael@0 5342 t[5] * cxform.greenMultiplier / 256 + cxform.greenOffset,
michael@0 5343 t[6] * cxform.blueMultiplier / 256 + cxform.blueOffset,
michael@0 5344 t[7] * cxform.alphaMultiplier / 256 + cxform.alphaOffset
michael@0 5345 ];
michael@0 5346 var mode;
michael@0 5347 var PRECISION = 0.0001;
michael@0 5348 if (Math.abs(t[0] - 1) < PRECISION && Math.abs(t[1] - 1) < PRECISION && Math.abs(t[2] - 1) < PRECISION && t[3] >= 0 && Math.abs(t[4]) < PRECISION && Math.abs(t[5]) < PRECISION && Math.abs(t[6]) < PRECISION && Math.abs(t[7]) < PRECISION) {
michael@0 5349 mode = Math.abs(t[3] - 1) < PRECISION ? null : 'simple';
michael@0 5350 } else {
michael@0 5351 mode = 'complex';
michael@0 5352 }
michael@0 5353 var clone = Object.create(RenderingColorTransform.prototype);
michael@0 5354 clone.mode = mode;
michael@0 5355 clone.transform = t;
michael@0 5356 return clone;
michael@0 5357 },
michael@0 5358 setFillStyle: function (ctx, style) {
michael@0 5359 if (this.mode === 'complex') {
michael@0 5360 style = typeof style === 'function' ? style(ctx, this) : this.convertColor(style);
michael@0 5361 } else if (typeof style === 'number') {
michael@0 5362 style = this.convertNumericColor(style);
michael@0 5363 } else if (typeof style === 'function') {
michael@0 5364 style = style.defaultFillStyle;
michael@0 5365 }
michael@0 5366 ctx.fillStyle = style;
michael@0 5367 },
michael@0 5368 setStrokeStyle: function (ctx, style) {
michael@0 5369 if (this.mode === 'complex') {
michael@0 5370 style = typeof style === 'function' ? style(ctx, this) : this.convertColor(style);
michael@0 5371 } else if (typeof style === 'number') {
michael@0 5372 style = this.convertNumericColor(style);
michael@0 5373 } else if (typeof style === 'function') {
michael@0 5374 style = style.defaultFillStyle;
michael@0 5375 }
michael@0 5376 ctx.strokeStyle = style;
michael@0 5377 },
michael@0 5378 addGradientColorStop: function (gradient, ratio, style) {
michael@0 5379 if (this.mode === 'complex') {
michael@0 5380 style = this.convertColor(style);
michael@0 5381 } else if (typeof style === 'number') {
michael@0 5382 style = this.convertNumericColor(style);
michael@0 5383 }
michael@0 5384 gradient.addColorStop(ratio, style);
michael@0 5385 },
michael@0 5386 setAlpha: function (ctx, force) {
michael@0 5387 if (this.mode === 'simple' || force) {
michael@0 5388 var t = this.transform;
michael@0 5389 ctx.globalAlpha = Math.min(1, Math.max(0, ctx.globalAlpha * t[3]));
michael@0 5390 }
michael@0 5391 },
michael@0 5392 convertNumericColor: function (num) {
michael@0 5393 return '#' + (num | 16777216).toString(16).substr(1);
michael@0 5394 },
michael@0 5395 convertColor: function (style) {
michael@0 5396 var t = this.transform;
michael@0 5397 var m;
michael@0 5398 switch (typeof style) {
michael@0 5399 case 'string':
michael@0 5400 if (style[0] === '#') {
michael@0 5401 m = [
michael@0 5402 undefined,
michael@0 5403 parseInt(style.substr(1, 2), 16),
michael@0 5404 parseInt(style.substr(3, 2), 16),
michael@0 5405 parseInt(style.substr(5, 2), 16),
michael@0 5406 1
michael@0 5407 ];
michael@0 5408 }
michael@0 5409 m = m || /rgba\(([^,]+),([^,]+),([^,]+),([^)]+)\)/.exec(style);
michael@0 5410 if (!m) {
michael@0 5411 return style;
michael@0 5412 }
michael@0 5413 break;
michael@0 5414 case 'number':
michael@0 5415 m = [
michael@0 5416 style,
michael@0 5417 style >> 16 & 255,
michael@0 5418 style >> 8 & 255,
michael@0 5419 style & 255,
michael@0 5420 1
michael@0 5421 ];
michael@0 5422 break;
michael@0 5423 default:
michael@0 5424 return style;
michael@0 5425 }
michael@0 5426 var r = Math.min(255, Math.max(0, m[1] * t[0] + t[4])) | 0;
michael@0 5427 var g = Math.min(255, Math.max(0, m[2] * t[1] + t[5])) | 0;
michael@0 5428 var b = Math.min(255, Math.max(0, m[3] * t[2] + t[6])) | 0;
michael@0 5429 var a = Math.min(1, Math.max(0, m[4] * t[3] + t[7] / 256));
michael@0 5430 return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
michael@0 5431 },
michael@0 5432 getTransformFingerprint: function () {
michael@0 5433 return this.transform.join('|');
michael@0 5434 }
michael@0 5435 };
michael@0 5436 function RenderingContext(refreshStage, invalidPath) {
michael@0 5437 this.refreshStage = refreshStage === true;
michael@0 5438 this.invalidPath = invalidPath;
michael@0 5439 this.isClippingMask = false;
michael@0 5440 this.colorTransform = new RenderingColorTransform();
michael@0 5441 this.parentCtxs = [];
michael@0 5442 }
michael@0 5443 function renderDisplayObject(child, ctx, context) {
michael@0 5444 var m = child._currentTransform;
michael@0 5445 if (m) {
michael@0 5446 ctx.transform(m.a, m.b, m.c, m.d, m.tx / 20, m.ty / 20);
michael@0 5447 }
michael@0 5448 if (!renderAsWireframe.value) {
michael@0 5449 if (child._alpha !== 1) {
michael@0 5450 ctx.globalAlpha *= child._alpha;
michael@0 5451 }
michael@0 5452 if (context.invalidPath && !child._invalid && !context.refreshStage) {
michael@0 5453 return;
michael@0 5454 }
michael@0 5455 if (child._graphics) {
michael@0 5456 var graphics = child._graphics;
michael@0 5457 if (graphics._bitmap) {
michael@0 5458 ctx.save();
michael@0 5459 ctx.translate(child._bbox.xMin / 20, child._bbox.yMin / 20);
michael@0 5460 context.colorTransform.setAlpha(ctx, true);
michael@0 5461 ctx.drawImage(graphics._bitmap, 0, 0);
michael@0 5462 ctx.restore();
michael@0 5463 } else {
michael@0 5464 var ratio = child.ratio;
michael@0 5465 if (ratio === undefined) {
michael@0 5466 ratio = 0;
michael@0 5467 }
michael@0 5468 graphics.draw(ctx, context.isClippingMask, ratio, context.colorTransform);
michael@0 5469 }
michael@0 5470 }
michael@0 5471 if (child.draw) {
michael@0 5472 child.draw(ctx, child.ratio, context.colorTransform, context.parentCtxs);
michael@0 5473 }
michael@0 5474 } else {
michael@0 5475 if (!child._invalid && !context.refreshStage) {
michael@0 5476 return;
michael@0 5477 }
michael@0 5478 if (child.getBounds) {
michael@0 5479 var b = child.getBounds(null);
michael@0 5480 if (b && b.xMax - b.xMin > 0 && b.yMax - b.yMin > 0) {
michael@0 5481 if (!child._wireframeStrokeStyle) {
michael@0 5482 child._wireframeStrokeStyle = randomStyle();
michael@0 5483 }
michael@0 5484 ctx.save();
michael@0 5485 ctx.strokeStyle = child._wireframeStrokeStyle;
michael@0 5486 var x = b.xMin / 20;
michael@0 5487 var y = b.yMin / 20;
michael@0 5488 ctx.strokeRect(x + 0.5, y + 0.5, b.xMax / 20 - x - 1, b.yMax / 20 - y - 1);
michael@0 5489 ctx.restore();
michael@0 5490 }
michael@0 5491 }
michael@0 5492 }
michael@0 5493 child._invalid = false;
michael@0 5494 }
michael@0 5495 function renderQuadTree(ctx, qtree) {
michael@0 5496 ctx.strokeRect(qtree.x / 20, qtree.y / 20, qtree.width / 20, qtree.height / 20);
michael@0 5497 var nodes = qtree.nodes;
michael@0 5498 for (var i = 0; i < nodes.length; i++) {
michael@0 5499 renderQuadTree(ctx, nodes[i]);
michael@0 5500 }
michael@0 5501 }
michael@0 5502 var renderingTerminated = false;
michael@0 5503 var samplesLeftPlusOne = 0;
michael@0 5504 function triggerSampling(count) {
michael@0 5505 samplesLeftPlusOne = -count - 1;
michael@0 5506 }
michael@0 5507 function sampleStart() {
michael@0 5508 if (!samplesLeftPlusOne) {
michael@0 5509 return;
michael@0 5510 }
michael@0 5511 if (samplesLeftPlusOne < 0) {
michael@0 5512 console.profile('Sample');
michael@0 5513 samplesLeftPlusOne *= -1;
michael@0 5514 }
michael@0 5515 if (samplesLeftPlusOne > 0) {
michael@0 5516 console.info('Sampling Frame: ' + (samplesLeftPlusOne - 1));
michael@0 5517 }
michael@0 5518 }
michael@0 5519 function sampleEnd() {
michael@0 5520 if (!samplesLeftPlusOne) {
michael@0 5521 return;
michael@0 5522 }
michael@0 5523 samplesLeftPlusOne--;
michael@0 5524 if (samplesLeftPlusOne === 1) {
michael@0 5525 console.profileEnd('Sample');
michael@0 5526 }
michael@0 5527 }
michael@0 5528 var timeline;
michael@0 5529 var hudTimeline;
michael@0 5530 function timelineEnter(name) {
michael@0 5531 timeline && timeline.enter(name);
michael@0 5532 hudTimeline && hudTimeline.enter(name);
michael@0 5533 }
michael@0 5534 function timelineLeave(name) {
michael@0 5535 timeline && timeline.leave(name);
michael@0 5536 hudTimeline && hudTimeline.leave(name);
michael@0 5537 }
michael@0 5538 function timelineWrapBroadcastMessage(domain, message) {
michael@0 5539 timelineEnter(message);
michael@0 5540 domain.broadcastMessage(message);
michael@0 5541 timelineLeave(message);
michael@0 5542 }
michael@0 5543 function initializeHUD(stage, parentCanvas) {
michael@0 5544 var canvas = document.createElement('canvas');
michael@0 5545 var canvasContainer = document.createElement('div');
michael@0 5546 canvasContainer.appendChild(canvas);
michael@0 5547 canvasContainer.style.position = 'absolute';
michael@0 5548 canvasContainer.style.top = '0px';
michael@0 5549 canvasContainer.style.left = '0px';
michael@0 5550 canvasContainer.style.width = '100%';
michael@0 5551 canvasContainer.style.height = '150px';
michael@0 5552 canvasContainer.style.backgroundColor = 'rgba(0, 0, 0, 0.4)';
michael@0 5553 canvasContainer.style.pointerEvents = 'none';
michael@0 5554 parentCanvas.parentElement.appendChild(canvasContainer);
michael@0 5555 hudTimeline = new Timeline(canvas);
michael@0 5556 hudTimeline.setFrameRate(stage._frameRate);
michael@0 5557 hudTimeline.refreshEvery(10);
michael@0 5558 }
michael@0 5559 function createRenderDummyBalls(ctx, stage) {
michael@0 5560 var dummyBalls;
michael@0 5561 var radius = 10;
michael@0 5562 var speed = 1;
michael@0 5563 var m = stage._concatenatedTransform;
michael@0 5564 var scaleX = m.a, scaleY = m.d;
michael@0 5565 dummyBalls = [];
michael@0 5566 for (var i = 0; i < 10; i++) {
michael@0 5567 dummyBalls.push({
michael@0 5568 position: {
michael@0 5569 x: radius + Math.random() * ((ctx.canvas.width - 2 * radius) / scaleX),
michael@0 5570 y: radius + Math.random() * ((ctx.canvas.height - 2 * radius) / scaleY)
michael@0 5571 },
michael@0 5572 velocity: {
michael@0 5573 x: speed * (Math.random() - 0.5),
michael@0 5574 y: speed * (Math.random() - 0.5)
michael@0 5575 }
michael@0 5576 });
michael@0 5577 }
michael@0 5578 ctx.fillStyle = 'black';
michael@0 5579 ctx.lineWidth = 2;
michael@0 5580 ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
michael@0 5581 return function renderDummyBalls() {
michael@0 5582 ctx.fillStyle = 'black';
michael@0 5583 ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
michael@0 5584 ctx.strokeStyle = 'green';
michael@0 5585 dummyBalls.forEach(function (ball) {
michael@0 5586 var position = ball.position;
michael@0 5587 var velocity = ball.velocity;
michael@0 5588 ctx.beginPath();
michael@0 5589 ctx.arc(position.x, position.y, radius, 0, Math.PI * 2, true);
michael@0 5590 ctx.stroke();
michael@0 5591 var x = position.x + velocity.x;
michael@0 5592 var y = position.y + velocity.y;
michael@0 5593 if (x < radius || x > ctx.canvas.width / scaleX - radius) {
michael@0 5594 velocity.x *= -1;
michael@0 5595 }
michael@0 5596 if (y < radius || y > ctx.canvas.height / scaleY - radius) {
michael@0 5597 velocity.y *= -1;
michael@0 5598 }
michael@0 5599 position.x += velocity.x;
michael@0 5600 position.y += velocity.y;
michael@0 5601 });
michael@0 5602 };
michael@0 5603 }
michael@0 5604 function renderStage(stage, ctx, events) {
michael@0 5605 var frameWidth, frameHeight;
michael@0 5606 if (!timeline && hud.value) {
michael@0 5607 initializeHUD(stage, ctx.canvas);
michael@0 5608 }
michael@0 5609 function updateRenderTransform() {
michael@0 5610 frameWidth = ctx.canvas.width;
michael@0 5611 frameHeight = ctx.canvas.height;
michael@0 5612 var scaleX = frameWidth / stage._stageWidth * 20;
michael@0 5613 var scaleY = frameHeight / stage._stageHeight * 20;
michael@0 5614 switch (stage._scaleMode) {
michael@0 5615 case 'exactFit':
michael@0 5616 break;
michael@0 5617 case 'noBorder':
michael@0 5618 if (scaleX > scaleY) {
michael@0 5619 scaleY = scaleX;
michael@0 5620 } else {
michael@0 5621 scaleX = scaleY;
michael@0 5622 }
michael@0 5623 break;
michael@0 5624 case 'noScale':
michael@0 5625 var pixelRatio = ctx.canvas._pixelRatio || 1;
michael@0 5626 scaleX = pixelRatio;
michael@0 5627 scaleY = pixelRatio;
michael@0 5628 break;
michael@0 5629 case 'showAll':
michael@0 5630 if (scaleX < scaleY) {
michael@0 5631 scaleY = scaleX;
michael@0 5632 } else {
michael@0 5633 scaleX = scaleY;
michael@0 5634 }
michael@0 5635 break;
michael@0 5636 }
michael@0 5637 var align = stage._align;
michael@0 5638 var offsetX, offsetY;
michael@0 5639 if (align.indexOf('L') >= 0) {
michael@0 5640 offsetX = 0;
michael@0 5641 } else if (align.indexOf('R') >= 0) {
michael@0 5642 offsetX = frameWidth - scaleX * stage._stageWidth / 20;
michael@0 5643 } else {
michael@0 5644 offsetX = (frameWidth - scaleX * stage._stageWidth / 20) / 2;
michael@0 5645 }
michael@0 5646 if (align.indexOf('T') >= 0) {
michael@0 5647 offsetY = 0;
michael@0 5648 } else if (align.indexOf('B') >= 0) {
michael@0 5649 offsetY = frameHeight - scaleY * stage._stageHeight / 20;
michael@0 5650 } else {
michael@0 5651 offsetY = (frameHeight - scaleY * stage._stageHeight / 20) / 2;
michael@0 5652 }
michael@0 5653 ctx.setTransform(scaleX, 0, 0, scaleY, offsetX, offsetY);
michael@0 5654 var m = stage._concatenatedTransform;
michael@0 5655 m.a = scaleX;
michael@0 5656 m.d = scaleY;
michael@0 5657 m.tx = offsetX * 20;
michael@0 5658 m.ty = offsetY * 20;
michael@0 5659 }
michael@0 5660 updateRenderTransform();
michael@0 5661 var frameScheduler = new FrameScheduler();
michael@0 5662 stage._frameScheduler = frameScheduler;
michael@0 5663 var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || window.setTimeout;
michael@0 5664 var renderDummyBalls = dummyAnimation.value && createRenderDummyBalls(ctx, stage);
michael@0 5665 console.timeEnd('Initialize Renderer');
michael@0 5666 console.timeEnd('Total');
michael@0 5667 var firstRun = true;
michael@0 5668 var frameCount = 0;
michael@0 5669 var frameFPSAverage = new Shumway.Metrics.Average(120);
michael@0 5670 var frameRequested = true;
michael@0 5671 function drawFrame(renderFrame, repaint) {
michael@0 5672 sampleStart();
michael@0 5673 var refreshStage = false;
michael@0 5674 if (stage._invalid) {
michael@0 5675 updateRenderTransform();
michael@0 5676 stage._invalid = false;
michael@0 5677 refreshStage = true;
michael@0 5678 }
michael@0 5679 var mouseMoved = false;
michael@0 5680 if (stage._mouseMoved) {
michael@0 5681 stage._mouseMoved = false;
michael@0 5682 mouseMoved = stage._mouseOver;
michael@0 5683 } else {
michael@0 5684 stage._handleMouseButtons();
michael@0 5685 }
michael@0 5686 if (renderFrame || refreshStage || mouseMoved) {
michael@0 5687 FrameCounter.clear();
michael@0 5688 var frameStartTime = performance.now();
michael@0 5689 timelineEnter('frame');
michael@0 5690 traceRenderer.value && appendToFrameTerminal('Begin Frame #' + frameCount++, 'purple');
michael@0 5691 var domain = avm2.systemDomain;
michael@0 5692 if (renderFrame) {
michael@0 5693 timelineEnter('events');
michael@0 5694 if (firstRun) {
michael@0 5695 firstRun = false;
michael@0 5696 } else {
michael@0 5697 enableAdvanceFrame.value && timelineWrapBroadcastMessage(domain, 'advanceFrame');
michael@0 5698 enableEnterFrame.value && timelineWrapBroadcastMessage(domain, 'enterFrame');
michael@0 5699 enableConstructChildren.value && timelineWrapBroadcastMessage(domain, 'constructChildren');
michael@0 5700 }
michael@0 5701 timelineWrapBroadcastMessage(domain, 'frameConstructed');
michael@0 5702 timelineWrapBroadcastMessage(domain, 'executeFrame');
michael@0 5703 timelineWrapBroadcastMessage(domain, 'exitFrame');
michael@0 5704 timelineLeave('events');
michael@0 5705 }
michael@0 5706 if (stage._deferRenderEvent) {
michael@0 5707 stage._deferRenderEvent = false;
michael@0 5708 domain.broadcastMessage('render', 'render');
michael@0 5709 }
michael@0 5710 var drawEnabled = isCanvasVisible(ctx.canvas) && (refreshStage || renderFrame) && (frameRequested || repaint || !skipFrameDraw.value);
michael@0 5711 if (drawEnabled && !repaint && skipFrameDraw.value && frameScheduler.shallSkipDraw) {
michael@0 5712 drawEnabled = false;
michael@0 5713 frameScheduler.skipDraw();
michael@0 5714 traceRenderer.value && appendToFrameTerminal('Skip Frame Draw', 'red');
michael@0 5715 }
michael@0 5716 if (drawEnabled) {
michael@0 5717 frameScheduler.startDraw();
michael@0 5718 var invalidPath = null;
michael@0 5719 traceRenderer.value && frameWriter.enter('> Invalidation');
michael@0 5720 timelineEnter('invalidate');
michael@0 5721 invalidPath = stage._processInvalidations(refreshStage);
michael@0 5722 timelineLeave('invalidate');
michael@0 5723 traceRenderer.value && frameWriter.leave('< Invalidation');
michael@0 5724 if (!disableRenderVisitor.value && !invalidPath.isEmpty) {
michael@0 5725 timelineEnter('render');
michael@0 5726 traceRenderer.value && frameWriter.enter('> Rendering');
michael@0 5727 new RenderVisitor(stage, ctx, invalidPath, refreshStage).start();
michael@0 5728 traceRenderer.value && frameWriter.leave('< Rendering');
michael@0 5729 timelineLeave('render');
michael@0 5730 }
michael@0 5731 if (showQuadTree.value) {
michael@0 5732 ctx.strokeStyle = 'green';
michael@0 5733 renderQuadTree(ctx, stage._qtree);
michael@0 5734 }
michael@0 5735 if (invalidPath && !refreshStage && showRedrawRegions.value) {
michael@0 5736 ctx.strokeStyle = 'red';
michael@0 5737 invalidPath.draw(ctx);
michael@0 5738 ctx.stroke();
michael@0 5739 }
michael@0 5740 frameScheduler.endDraw();
michael@0 5741 }
michael@0 5742 if (mouseMoved && !disableMouseVisitor.value) {
michael@0 5743 renderFrame && timelineEnter('mouse');
michael@0 5744 traceRenderer.value && frameWriter.enter('> Mouse Handling');
michael@0 5745 stage._handleMouse();
michael@0 5746 traceRenderer.value && frameWriter.leave('< Mouse Handling');
michael@0 5747 renderFrame && timelineLeave('mouse');
michael@0 5748 ctx.canvas.style.cursor = stage._cursor;
michael@0 5749 }
michael@0 5750 if (traceRenderer.value) {
michael@0 5751 frameWriter.enter('> Frame Counters');
michael@0 5752 for (var name in FrameCounter.counts) {
michael@0 5753 frameWriter.writeLn(name + ': ' + FrameCounter.counts[name]);
michael@0 5754 }
michael@0 5755 frameWriter.leave('< Frame Counters');
michael@0 5756 var frameElapsedTime = performance.now() - frameStartTime;
michael@0 5757 var frameFPS = 1000 / frameElapsedTime;
michael@0 5758 frameFPSAverage.push(frameFPS);
michael@0 5759 traceRenderer.value && appendToFrameTerminal('End Frame Time: ' + frameElapsedTime.toFixed(2) + ' (' + frameFPS.toFixed(2) + ' fps, ' + frameFPSAverage.average().toFixed(2) + ' average fps)', 'purple');
michael@0 5760 }
michael@0 5761 timelineLeave('frame');
michael@0 5762 } else {
michael@0 5763 traceRenderer.value && appendToFrameTerminal('Skip Frame', 'black');
michael@0 5764 }
michael@0 5765 sampleEnd();
michael@0 5766 }
michael@0 5767 (function draw() {
michael@0 5768 var renderFrame = true;
michael@0 5769 if (events.onBeforeFrame) {
michael@0 5770 var e = {
michael@0 5771 cancel: false
michael@0 5772 };
michael@0 5773 events.onBeforeFrame(e);
michael@0 5774 renderFrame = !e.cancel;
michael@0 5775 }
michael@0 5776 if (renderDummyBalls) {
michael@0 5777 if (renderFrame) {
michael@0 5778 renderDummyBalls();
michael@0 5779 events.onAfterFrame && events.onAfterFrame();
michael@0 5780 }
michael@0 5781 setTimeout(draw);
michael@0 5782 return;
michael@0 5783 }
michael@0 5784 frameScheduler.startFrame(stage._frameRate);
michael@0 5785 drawFrame(renderFrame, false);
michael@0 5786 frameScheduler.endFrame();
michael@0 5787 frameRequested = false;
michael@0 5788 if (!frameScheduler.isOnTime) {
michael@0 5789 traceRenderer.value && appendToFrameTerminal('Frame Is Late', 'red');
michael@0 5790 }
michael@0 5791 if (renderFrame && events.onAfterFrame) {
michael@0 5792 events.onAfterFrame();
michael@0 5793 }
michael@0 5794 if (renderingTerminated) {
michael@0 5795 if (events.onTerminated) {
michael@0 5796 events.onTerminated();
michael@0 5797 }
michael@0 5798 return;
michael@0 5799 }
michael@0 5800 setTimeout(draw, turboMode.value ? 0 : frameScheduler.nextFrameIn);
michael@0 5801 }());
michael@0 5802 (function frame() {
michael@0 5803 if (renderingTerminated) {
michael@0 5804 return;
michael@0 5805 }
michael@0 5806 frameRequested = true;
michael@0 5807 if ((stage._invalid || stage._mouseMoved) && !renderDummyBalls) {
michael@0 5808 drawFrame(false, true);
michael@0 5809 }
michael@0 5810 requestAnimationFrame(frame);
michael@0 5811 }());
michael@0 5812 }
michael@0 5813 var FrameScheduler = function () {
michael@0 5814 var STATS_TO_REMEMBER = 50;
michael@0 5815 var MAX_DRAWS_TO_SKIP = 2;
michael@0 5816 var INTERVAL_PADDING_MS = 4;
michael@0 5817 var SPEED_ADJUST_RATE = 0.9;
michael@0 5818 function FrameScheduler() {
michael@0 5819 this._drawStats = [];
michael@0 5820 this._drawStatsSum = 0;
michael@0 5821 this._drawStarted = 0;
michael@0 5822 this._drawsSkipped = 0;
michael@0 5823 this._expectedNextFrameAt = performance.now();
michael@0 5824 this._onTime = true;
michael@0 5825 this._trackDelta = false;
michael@0 5826 this._delta = 0;
michael@0 5827 this._onTimeDelta = 0;
michael@0 5828 }
michael@0 5829 FrameScheduler.prototype = {
michael@0 5830 get shallSkipDraw() {
michael@0 5831 if (this._drawsSkipped >= MAX_DRAWS_TO_SKIP) {
michael@0 5832 return false;
michael@0 5833 }
michael@0 5834 var averageDraw = this._drawStats.length < STATS_TO_REMEMBER ? 0 : this._drawStatsSum / this._drawStats.length;
michael@0 5835 var estimatedDrawEnd = performance.now() + averageDraw;
michael@0 5836 return estimatedDrawEnd + INTERVAL_PADDING_MS > this._expectedNextFrameAt;
michael@0 5837 },
michael@0 5838 get nextFrameIn() {
michael@0 5839 return Math.max(0, this._expectedNextFrameAt - performance.now());
michael@0 5840 },
michael@0 5841 get isOnTime() {
michael@0 5842 return this._onTime;
michael@0 5843 },
michael@0 5844 startFrame: function (frameRate) {
michael@0 5845 var interval = 1000 / frameRate;
michael@0 5846 var adjustedInterval = interval;
michael@0 5847 var delta = this._onTimeDelta + this._delta;
michael@0 5848 if (delta !== 0) {
michael@0 5849 if (delta < 0) {
michael@0 5850 adjustedInterval *= SPEED_ADJUST_RATE;
michael@0 5851 } else if (delta > 0) {
michael@0 5852 adjustedInterval /= SPEED_ADJUST_RATE;
michael@0 5853 }
michael@0 5854 this._onTimeDelta += interval - adjustedInterval;
michael@0 5855 }
michael@0 5856 this._expectedNextFrameAt += adjustedInterval;
michael@0 5857 this._onTime = true;
michael@0 5858 },
michael@0 5859 endFrame: function () {
michael@0 5860 var estimatedNextFrameStart = performance.now() + INTERVAL_PADDING_MS;
michael@0 5861 if (estimatedNextFrameStart > this._expectedNextFrameAt) {
michael@0 5862 if (this._trackDelta) {
michael@0 5863 this._onTimeDelta += this._expectedNextFrameAt - estimatedNextFrameStart;
michael@0 5864 console.log(this._onTimeDelta);
michael@0 5865 }
michael@0 5866 this._expectedNextFrameAt = estimatedNextFrameStart;
michael@0 5867 this._onTime = false;
michael@0 5868 }
michael@0 5869 },
michael@0 5870 startDraw: function () {
michael@0 5871 this._drawsSkipped = 0;
michael@0 5872 this._drawStarted = performance.now();
michael@0 5873 },
michael@0 5874 endDraw: function () {
michael@0 5875 var drawTime = performance.now() - this._drawStarted;
michael@0 5876 this._drawStats.push(drawTime);
michael@0 5877 this._drawStatsSum += drawTime;
michael@0 5878 while (this._drawStats.length > STATS_TO_REMEMBER) {
michael@0 5879 this._drawStatsSum -= this._drawStats.shift();
michael@0 5880 }
michael@0 5881 },
michael@0 5882 skipDraw: function () {
michael@0 5883 this._drawsSkipped++;
michael@0 5884 },
michael@0 5885 setDelta: function (value) {
michael@0 5886 if (!this._trackDelta) {
michael@0 5887 return;
michael@0 5888 }
michael@0 5889 this._delta = value;
michael@0 5890 },
michael@0 5891 startTrackDelta: function () {
michael@0 5892 this._trackDelta = true;
michael@0 5893 },
michael@0 5894 endTrackDelta: function () {
michael@0 5895 if (!this._trackDelta) {
michael@0 5896 return;
michael@0 5897 }
michael@0 5898 this._trackDelta = false;
michael@0 5899 this._delta = 0;
michael@0 5900 this._onTimeDelta = 0;
michael@0 5901 }
michael@0 5902 };
michael@0 5903 return FrameScheduler;
michael@0 5904 }();
michael@0 5905 var tagHandler = function (global) {
michael@0 5906 function defineShape($bytes, $stream, $, swfVersion, tagCode) {
michael@0 5907 $ || ($ = {});
michael@0 5908 $.id = readUi16($bytes, $stream);
michael@0 5909 var $0 = $.bbox = {};
michael@0 5910 bbox($bytes, $stream, $0, swfVersion, tagCode);
michael@0 5911 var isMorph = $.isMorph = tagCode === 46 || tagCode === 84;
michael@0 5912 if (isMorph) {
michael@0 5913 var $1 = $.bboxMorph = {};
michael@0 5914 bbox($bytes, $stream, $1, swfVersion, tagCode);
michael@0 5915 }
michael@0 5916 var hasStrokes = $.hasStrokes = tagCode === 83 || tagCode === 84;
michael@0 5917 if (hasStrokes) {
michael@0 5918 var $2 = $.strokeBbox = {};
michael@0 5919 bbox($bytes, $stream, $2, swfVersion, tagCode);
michael@0 5920 if (isMorph) {
michael@0 5921 var $3 = $.strokeBboxMorph = {};
michael@0 5922 bbox($bytes, $stream, $3, swfVersion, tagCode);
michael@0 5923 }
michael@0 5924 var reserved = readUb($bytes, $stream, 5);
michael@0 5925 $.fillWinding = readUb($bytes, $stream, 1);
michael@0 5926 $.nonScalingStrokes = readUb($bytes, $stream, 1);
michael@0 5927 $.scalingStrokes = readUb($bytes, $stream, 1);
michael@0 5928 }
michael@0 5929 if (isMorph) {
michael@0 5930 $.offsetMorph = readUi32($bytes, $stream);
michael@0 5931 morphShapeWithStyle($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes);
michael@0 5932 } else {
michael@0 5933 shapeWithStyle($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes);
michael@0 5934 }
michael@0 5935 return $;
michael@0 5936 }
michael@0 5937 function placeObject($bytes, $stream, $, swfVersion, tagCode) {
michael@0 5938 var flags, hasEvents, clip, hasName, hasRatio, hasCxform, hasMatrix, place;
michael@0 5939 var move, hasBackgroundColor, hasVisibility, hasImage, hasClassName, cache;
michael@0 5940 var blend, hasFilters, eoe;
michael@0 5941 $ || ($ = {});
michael@0 5942 if (tagCode > 4) {
michael@0 5943 if (tagCode > 26) {
michael@0 5944 flags = readUi16($bytes, $stream);
michael@0 5945 } else {
michael@0 5946 flags = readUi8($bytes, $stream);
michael@0 5947 }
michael@0 5948 hasEvents = $.hasEvents = flags >> 7 & 1;
michael@0 5949 clip = $.clip = flags >> 6 & 1;
michael@0 5950 hasName = $.hasName = flags >> 5 & 1;
michael@0 5951 hasRatio = $.hasRatio = flags >> 4 & 1;
michael@0 5952 hasCxform = $.hasCxform = flags >> 3 & 1;
michael@0 5953 hasMatrix = $.hasMatrix = flags >> 2 & 1;
michael@0 5954 place = $.place = flags >> 1 & 1;
michael@0 5955 move = $.move = flags & 1;
michael@0 5956 if (tagCode === 70) {
michael@0 5957 hasBackgroundColor = $.hasBackgroundColor = flags >> 15 & 1;
michael@0 5958 hasVisibility = $.hasVisibility = flags >> 14 & 1;
michael@0 5959 hasImage = $.hasImage = flags >> 12 & 1;
michael@0 5960 hasClassName = $.hasClassName = flags >> 11 & 1;
michael@0 5961 cache = $.cache = flags >> 10 & 1;
michael@0 5962 blend = $.blend = flags >> 9 & 1;
michael@0 5963 hasFilters = $.hasFilters = flags >> 8 & 1;
michael@0 5964 } else {
michael@0 5965 cache = $.cache = 0;
michael@0 5966 blend = $.blend = 0;
michael@0 5967 hasFilters = $.hasFilters = 0;
michael@0 5968 }
michael@0 5969 $.depth = readUi16($bytes, $stream);
michael@0 5970 if (hasClassName) {
michael@0 5971 $.className = readString($bytes, $stream, 0);
michael@0 5972 }
michael@0 5973 if (place) {
michael@0 5974 $.symbolId = readUi16($bytes, $stream);
michael@0 5975 }
michael@0 5976 if (hasMatrix) {
michael@0 5977 var $0 = $.matrix = {};
michael@0 5978 matrix($bytes, $stream, $0, swfVersion, tagCode);
michael@0 5979 }
michael@0 5980 if (hasCxform) {
michael@0 5981 var $1 = $.cxform = {};
michael@0 5982 cxform($bytes, $stream, $1, swfVersion, tagCode);
michael@0 5983 }
michael@0 5984 if (hasRatio) {
michael@0 5985 $.ratio = readUi16($bytes, $stream);
michael@0 5986 }
michael@0 5987 if (hasName) {
michael@0 5988 $.name = readString($bytes, $stream, 0);
michael@0 5989 }
michael@0 5990 if (clip) {
michael@0 5991 $.clipDepth = readUi16($bytes, $stream);
michael@0 5992 }
michael@0 5993 if (hasFilters) {
michael@0 5994 var count = readUi8($bytes, $stream);
michael@0 5995 var $2 = $.filters = [];
michael@0 5996 var $3 = count;
michael@0 5997 while ($3--) {
michael@0 5998 var $4 = {};
michael@0 5999 anyFilter($bytes, $stream, $4, swfVersion, tagCode);
michael@0 6000 $2.push($4);
michael@0 6001 }
michael@0 6002 }
michael@0 6003 if (blend) {
michael@0 6004 $.blendMode = readUi8($bytes, $stream);
michael@0 6005 }
michael@0 6006 if (cache) {
michael@0 6007 $.bmpCache = readUi8($bytes, $stream);
michael@0 6008 }
michael@0 6009 if (hasEvents) {
michael@0 6010 var reserved = readUi16($bytes, $stream);
michael@0 6011 if (swfVersion >= 6) {
michael@0 6012 var allFlags = readUi32($bytes, $stream);
michael@0 6013 } else {
michael@0 6014 var allFlags = readUi16($bytes, $stream);
michael@0 6015 }
michael@0 6016 var $28 = $.events = [];
michael@0 6017 do {
michael@0 6018 var $29 = {};
michael@0 6019 var temp = events($bytes, $stream, $29, swfVersion, tagCode);
michael@0 6020 eoe = temp.eoe;
michael@0 6021 $28.push($29);
michael@0 6022 } while (!eoe);
michael@0 6023 }
michael@0 6024 if (hasBackgroundColor) {
michael@0 6025 var $126 = $.backgroundColor = {};
michael@0 6026 argb($bytes, $stream, $126, swfVersion, tagCode);
michael@0 6027 }
michael@0 6028 if (hasVisibility) {
michael@0 6029 $.visibility = readUi8($bytes, $stream);
michael@0 6030 }
michael@0 6031 } else {
michael@0 6032 $.place = 1;
michael@0 6033 $.symbolId = readUi16($bytes, $stream);
michael@0 6034 $.depth = readUi16($bytes, $stream);
michael@0 6035 $.hasMatrix = 1;
michael@0 6036 var $30 = $.matrix = {};
michael@0 6037 matrix($bytes, $stream, $30, swfVersion, tagCode);
michael@0 6038 if ($stream.remaining()) {
michael@0 6039 $.hasCxform = 1;
michael@0 6040 var $31 = $.cxform = {};
michael@0 6041 cxform($bytes, $stream, $31, swfVersion, tagCode);
michael@0 6042 }
michael@0 6043 }
michael@0 6044 return $;
michael@0 6045 }
michael@0 6046 function removeObject($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6047 $ || ($ = {});
michael@0 6048 if (tagCode === 5) {
michael@0 6049 $.symbolId = readUi16($bytes, $stream);
michael@0 6050 }
michael@0 6051 $.depth = readUi16($bytes, $stream);
michael@0 6052 return $;
michael@0 6053 }
michael@0 6054 function defineImage($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6055 var imgData;
michael@0 6056 $ || ($ = {});
michael@0 6057 $.id = readUi16($bytes, $stream);
michael@0 6058 if (tagCode > 21) {
michael@0 6059 var alphaDataOffset = readUi32($bytes, $stream);
michael@0 6060 if (tagCode === 90) {
michael@0 6061 $.deblock = readFixed8($bytes, $stream);
michael@0 6062 }
michael@0 6063 imgData = $.imgData = readBinary($bytes, $stream, alphaDataOffset);
michael@0 6064 $.alphaData = readBinary($bytes, $stream, 0);
michael@0 6065 } else {
michael@0 6066 imgData = $.imgData = readBinary($bytes, $stream, 0);
michael@0 6067 }
michael@0 6068 switch (imgData[0] << 8 | imgData[1]) {
michael@0 6069 case 65496:
michael@0 6070 case 65497:
michael@0 6071 $.mimeType = 'image/jpeg';
michael@0 6072 break;
michael@0 6073 case 35152:
michael@0 6074 $.mimeType = 'image/png';
michael@0 6075 break;
michael@0 6076 case 18249:
michael@0 6077 $.mimeType = 'image/gif';
michael@0 6078 break;
michael@0 6079 default:
michael@0 6080 $.mimeType = 'application/octet-stream';
michael@0 6081 }
michael@0 6082 if (tagCode === 6) {
michael@0 6083 $.incomplete = 1;
michael@0 6084 }
michael@0 6085 return $;
michael@0 6086 }
michael@0 6087 function defineButton($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6088 var eob, hasFilters, count, blend;
michael@0 6089 $ || ($ = {});
michael@0 6090 $.id = readUi16($bytes, $stream);
michael@0 6091 if (tagCode == 7) {
michael@0 6092 var $0 = $.characters = [];
michael@0 6093 do {
michael@0 6094 var $1 = {};
michael@0 6095 var temp = button($bytes, $stream, $1, swfVersion, tagCode);
michael@0 6096 eob = temp.eob;
michael@0 6097 $0.push($1);
michael@0 6098 } while (!eob);
michael@0 6099 $.actionsData = readBinary($bytes, $stream, 0);
michael@0 6100 } else {
michael@0 6101 var trackFlags = readUi8($bytes, $stream);
michael@0 6102 $.trackAsMenu = trackFlags >> 7 & 1;
michael@0 6103 var actionOffset = readUi16($bytes, $stream);
michael@0 6104 var $28 = $.characters = [];
michael@0 6105 do {
michael@0 6106 var $29 = {};
michael@0 6107 var flags = readUi8($bytes, $stream);
michael@0 6108 var eob = $29.eob = !flags;
michael@0 6109 if (swfVersion >= 8) {
michael@0 6110 blend = $29.blend = flags >> 5 & 1;
michael@0 6111 hasFilters = $29.hasFilters = flags >> 4 & 1;
michael@0 6112 } else {
michael@0 6113 blend = $29.blend = 0;
michael@0 6114 hasFilters = $29.hasFilters = 0;
michael@0 6115 }
michael@0 6116 $29.stateHitTest = flags >> 3 & 1;
michael@0 6117 $29.stateDown = flags >> 2 & 1;
michael@0 6118 $29.stateOver = flags >> 1 & 1;
michael@0 6119 $29.stateUp = flags & 1;
michael@0 6120 if (!eob) {
michael@0 6121 $29.symbolId = readUi16($bytes, $stream);
michael@0 6122 $29.depth = readUi16($bytes, $stream);
michael@0 6123 var $30 = $29.matrix = {};
michael@0 6124 matrix($bytes, $stream, $30, swfVersion, tagCode);
michael@0 6125 if (tagCode === 34) {
michael@0 6126 var $31 = $29.cxform = {};
michael@0 6127 cxform($bytes, $stream, $31, swfVersion, tagCode);
michael@0 6128 }
michael@0 6129 if (hasFilters) {
michael@0 6130 var count = readUi8($bytes, $stream);
michael@0 6131 var $2 = $.filters = [];
michael@0 6132 var $3 = count;
michael@0 6133 while ($3--) {
michael@0 6134 var $4 = {};
michael@0 6135 anyFilter($bytes, $stream, $4, swfVersion, tagCode);
michael@0 6136 $2.push($4);
michael@0 6137 }
michael@0 6138 }
michael@0 6139 if (blend) {
michael@0 6140 $29.blendMode = readUi8($bytes, $stream);
michael@0 6141 }
michael@0 6142 }
michael@0 6143 $28.push($29);
michael@0 6144 } while (!eob);
michael@0 6145 if (!(!actionOffset)) {
michael@0 6146 var $56 = $.buttonActions = [];
michael@0 6147 do {
michael@0 6148 var $57 = {};
michael@0 6149 buttonCondAction($bytes, $stream, $57, swfVersion, tagCode);
michael@0 6150 $56.push($57);
michael@0 6151 } while ($stream.remaining() > 0);
michael@0 6152 }
michael@0 6153 }
michael@0 6154 return $;
michael@0 6155 }
michael@0 6156 function defineJPEGTables($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6157 $ || ($ = {});
michael@0 6158 $.id = 0;
michael@0 6159 $.imgData = readBinary($bytes, $stream, 0);
michael@0 6160 $.mimeType = 'application/octet-stream';
michael@0 6161 return $;
michael@0 6162 }
michael@0 6163 function setBackgroundColor($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6164 $ || ($ = {});
michael@0 6165 var $0 = $.color = {};
michael@0 6166 rgb($bytes, $stream, $0, swfVersion, tagCode);
michael@0 6167 return $;
michael@0 6168 }
michael@0 6169 function defineBinaryData($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6170 $ || ($ = {});
michael@0 6171 $.id = readUi16($bytes, $stream);
michael@0 6172 var reserved = readUi32($bytes, $stream);
michael@0 6173 $.data = readBinary($bytes, $stream, 0);
michael@0 6174 return $;
michael@0 6175 }
michael@0 6176 function defineFont($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6177 $ || ($ = {});
michael@0 6178 $.id = readUi16($bytes, $stream);
michael@0 6179 var firstOffset = readUi16($bytes, $stream);
michael@0 6180 var glyphCount = $.glyphCount = firstOffset / 2;
michael@0 6181 var restOffsets = [];
michael@0 6182 var $0 = glyphCount - 1;
michael@0 6183 while ($0--) {
michael@0 6184 restOffsets.push(readUi16($bytes, $stream));
michael@0 6185 }
michael@0 6186 $.offsets = [
michael@0 6187 firstOffset
michael@0 6188 ].concat(restOffsets);
michael@0 6189 var $1 = $.glyphs = [];
michael@0 6190 var $2 = glyphCount;
michael@0 6191 while ($2--) {
michael@0 6192 var $3 = {};
michael@0 6193 shape($bytes, $stream, $3, swfVersion, tagCode);
michael@0 6194 $1.push($3);
michael@0 6195 }
michael@0 6196 return $;
michael@0 6197 }
michael@0 6198 function defineLabel($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6199 var eot;
michael@0 6200 $ || ($ = {});
michael@0 6201 $.id = readUi16($bytes, $stream);
michael@0 6202 var $0 = $.bbox = {};
michael@0 6203 bbox($bytes, $stream, $0, swfVersion, tagCode);
michael@0 6204 var $1 = $.matrix = {};
michael@0 6205 matrix($bytes, $stream, $1, swfVersion, tagCode);
michael@0 6206 var glyphBits = $.glyphBits = readUi8($bytes, $stream);
michael@0 6207 var advanceBits = $.advanceBits = readUi8($bytes, $stream);
michael@0 6208 var $2 = $.records = [];
michael@0 6209 do {
michael@0 6210 var $3 = {};
michael@0 6211 var temp = textRecord($bytes, $stream, $3, swfVersion, tagCode, glyphBits, advanceBits);
michael@0 6212 eot = temp.eot;
michael@0 6213 $2.push($3);
michael@0 6214 } while (!eot);
michael@0 6215 return $;
michael@0 6216 }
michael@0 6217 function doAction($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6218 $ || ($ = {});
michael@0 6219 if (tagCode === 59) {
michael@0 6220 $.spriteId = readUi16($bytes, $stream);
michael@0 6221 }
michael@0 6222 $.actionsData = readBinary($bytes, $stream, 0);
michael@0 6223 return $;
michael@0 6224 }
michael@0 6225 function defineSound($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6226 $ || ($ = {});
michael@0 6227 $.id = readUi16($bytes, $stream);
michael@0 6228 var soundFlags = readUi8($bytes, $stream);
michael@0 6229 $.soundFormat = soundFlags >> 4 & 15;
michael@0 6230 $.soundRate = soundFlags >> 2 & 3;
michael@0 6231 $.soundSize = soundFlags >> 1 & 1;
michael@0 6232 $.soundType = soundFlags & 1;
michael@0 6233 $.samplesCount = readUi32($bytes, $stream);
michael@0 6234 $.soundData = readBinary($bytes, $stream, 0);
michael@0 6235 return $;
michael@0 6236 }
michael@0 6237 function startSound($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6238 $ || ($ = {});
michael@0 6239 if (tagCode == 15) {
michael@0 6240 $.soundId = readUi16($bytes, $stream);
michael@0 6241 }
michael@0 6242 if (tagCode == 89) {
michael@0 6243 $.soundClassName = readString($bytes, $stream, 0);
michael@0 6244 }
michael@0 6245 var $0 = $.soundInfo = {};
michael@0 6246 soundInfo($bytes, $stream, $0, swfVersion, tagCode);
michael@0 6247 return $;
michael@0 6248 }
michael@0 6249 function soundStreamHead($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6250 $ || ($ = {});
michael@0 6251 var playbackFlags = readUi8($bytes, $stream);
michael@0 6252 $.playbackRate = playbackFlags >> 2 & 3;
michael@0 6253 $.playbackSize = playbackFlags >> 1 & 1;
michael@0 6254 $.playbackType = playbackFlags & 1;
michael@0 6255 var streamFlags = readUi8($bytes, $stream);
michael@0 6256 var streamCompression = $.streamCompression = streamFlags >> 4 & 15;
michael@0 6257 $.streamRate = streamFlags >> 2 & 3;
michael@0 6258 $.streamSize = streamFlags >> 1 & 1;
michael@0 6259 $.streamType = streamFlags & 1;
michael@0 6260 $.samplesCount = readUi32($bytes, $stream);
michael@0 6261 if (streamCompression == 2) {
michael@0 6262 $.latencySeek = readSi16($bytes, $stream);
michael@0 6263 }
michael@0 6264 return $;
michael@0 6265 }
michael@0 6266 function soundStreamBlock($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6267 $ || ($ = {});
michael@0 6268 $.data = readBinary($bytes, $stream, 0);
michael@0 6269 return $;
michael@0 6270 }
michael@0 6271 function defineBitmap($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6272 $ || ($ = {});
michael@0 6273 $.id = readUi16($bytes, $stream);
michael@0 6274 var format = $.format = readUi8($bytes, $stream);
michael@0 6275 $.width = readUi16($bytes, $stream);
michael@0 6276 $.height = readUi16($bytes, $stream);
michael@0 6277 $.hasAlpha = tagCode === 36;
michael@0 6278 if (format === 3) {
michael@0 6279 $.colorTableSize = readUi8($bytes, $stream);
michael@0 6280 }
michael@0 6281 $.bmpData = readBinary($bytes, $stream, 0);
michael@0 6282 return $;
michael@0 6283 }
michael@0 6284 function defineText($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6285 $ || ($ = {});
michael@0 6286 $.id = readUi16($bytes, $stream);
michael@0 6287 var $0 = $.bbox = {};
michael@0 6288 bbox($bytes, $stream, $0, swfVersion, tagCode);
michael@0 6289 var flags = readUi16($bytes, $stream);
michael@0 6290 var hasText = $.hasText = flags >> 7 & 1;
michael@0 6291 $.wordWrap = flags >> 6 & 1;
michael@0 6292 $.multiline = flags >> 5 & 1;
michael@0 6293 $.password = flags >> 4 & 1;
michael@0 6294 $.readonly = flags >> 3 & 1;
michael@0 6295 var hasColor = $.hasColor = flags >> 2 & 1;
michael@0 6296 var hasMaxLength = $.hasMaxLength = flags >> 1 & 1;
michael@0 6297 var hasFont = $.hasFont = flags & 1;
michael@0 6298 var hasFontClass = $.hasFontClass = flags >> 15 & 1;
michael@0 6299 $.autoSize = flags >> 14 & 1;
michael@0 6300 var hasLayout = $.hasLayout = flags >> 13 & 1;
michael@0 6301 $.noSelect = flags >> 12 & 1;
michael@0 6302 $.border = flags >> 11 & 1;
michael@0 6303 $.wasStatic = flags >> 10 & 1;
michael@0 6304 $.html = flags >> 9 & 1;
michael@0 6305 $.useOutlines = flags >> 8 & 1;
michael@0 6306 if (hasFont) {
michael@0 6307 $.fontId = readUi16($bytes, $stream);
michael@0 6308 }
michael@0 6309 if (hasFontClass) {
michael@0 6310 $.fontClass = readString($bytes, $stream, 0);
michael@0 6311 }
michael@0 6312 if (hasFont) {
michael@0 6313 $.fontHeight = readUi16($bytes, $stream);
michael@0 6314 }
michael@0 6315 if (hasColor) {
michael@0 6316 var $1 = $.color = {};
michael@0 6317 rgba($bytes, $stream, $1, swfVersion, tagCode);
michael@0 6318 }
michael@0 6319 if (hasMaxLength) {
michael@0 6320 $.maxLength = readUi16($bytes, $stream);
michael@0 6321 }
michael@0 6322 if (hasLayout) {
michael@0 6323 $.align = readUi8($bytes, $stream);
michael@0 6324 $.leftMargin = readUi16($bytes, $stream);
michael@0 6325 $.rightMargin = readUi16($bytes, $stream);
michael@0 6326 $.indent = readSi16($bytes, $stream);
michael@0 6327 $.leading = readSi16($bytes, $stream);
michael@0 6328 }
michael@0 6329 $.variableName = readString($bytes, $stream, 0);
michael@0 6330 if (hasText) {
michael@0 6331 $.initialText = readString($bytes, $stream, 0);
michael@0 6332 }
michael@0 6333 return $;
michael@0 6334 }
michael@0 6335 function frameLabel($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6336 $ || ($ = {});
michael@0 6337 $.name = readString($bytes, $stream, 0);
michael@0 6338 return $;
michael@0 6339 }
michael@0 6340 function defineFont2($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6341 $ || ($ = {});
michael@0 6342 $.id = readUi16($bytes, $stream);
michael@0 6343 var hasLayout = $.hasLayout = readUb($bytes, $stream, 1);
michael@0 6344 if (swfVersion > 5) {
michael@0 6345 $.shiftJis = readUb($bytes, $stream, 1);
michael@0 6346 } else {
michael@0 6347 var reserved = readUb($bytes, $stream, 1);
michael@0 6348 }
michael@0 6349 $.smallText = readUb($bytes, $stream, 1);
michael@0 6350 $.ansi = readUb($bytes, $stream, 1);
michael@0 6351 var wideOffset = $.wideOffset = readUb($bytes, $stream, 1);
michael@0 6352 var wide = $.wide = readUb($bytes, $stream, 1);
michael@0 6353 $.italic = readUb($bytes, $stream, 1);
michael@0 6354 $.bold = readUb($bytes, $stream, 1);
michael@0 6355 if (swfVersion > 5) {
michael@0 6356 $.language = readUi8($bytes, $stream);
michael@0 6357 } else {
michael@0 6358 var reserved = readUi8($bytes, $stream);
michael@0 6359 $.language = 0;
michael@0 6360 }
michael@0 6361 var nameLength = readUi8($bytes, $stream);
michael@0 6362 $.name = readString($bytes, $stream, nameLength);
michael@0 6363 if (tagCode === 75) {
michael@0 6364 $.resolution = 20;
michael@0 6365 }
michael@0 6366 var glyphCount = $.glyphCount = readUi16($bytes, $stream);
michael@0 6367 if (wideOffset) {
michael@0 6368 var $0 = $.offsets = [];
michael@0 6369 var $1 = glyphCount;
michael@0 6370 while ($1--) {
michael@0 6371 $0.push(readUi32($bytes, $stream));
michael@0 6372 }
michael@0 6373 $.mapOffset = readUi32($bytes, $stream);
michael@0 6374 } else {
michael@0 6375 var $2 = $.offsets = [];
michael@0 6376 var $3 = glyphCount;
michael@0 6377 while ($3--) {
michael@0 6378 $2.push(readUi16($bytes, $stream));
michael@0 6379 }
michael@0 6380 $.mapOffset = readUi16($bytes, $stream);
michael@0 6381 }
michael@0 6382 var $4 = $.glyphs = [];
michael@0 6383 var $5 = glyphCount;
michael@0 6384 while ($5--) {
michael@0 6385 var $6 = {};
michael@0 6386 shape($bytes, $stream, $6, swfVersion, tagCode);
michael@0 6387 $4.push($6);
michael@0 6388 }
michael@0 6389 if (wide) {
michael@0 6390 var $47 = $.codes = [];
michael@0 6391 var $48 = glyphCount;
michael@0 6392 while ($48--) {
michael@0 6393 $47.push(readUi16($bytes, $stream));
michael@0 6394 }
michael@0 6395 } else {
michael@0 6396 var $49 = $.codes = [];
michael@0 6397 var $50 = glyphCount;
michael@0 6398 while ($50--) {
michael@0 6399 $49.push(readUi8($bytes, $stream));
michael@0 6400 }
michael@0 6401 }
michael@0 6402 if (hasLayout) {
michael@0 6403 $.ascent = readUi16($bytes, $stream);
michael@0 6404 $.descent = readUi16($bytes, $stream);
michael@0 6405 $.leading = readSi16($bytes, $stream);
michael@0 6406 var $51 = $.advance = [];
michael@0 6407 var $52 = glyphCount;
michael@0 6408 while ($52--) {
michael@0 6409 $51.push(readSi16($bytes, $stream));
michael@0 6410 }
michael@0 6411 var $53 = $.bbox = [];
michael@0 6412 var $54 = glyphCount;
michael@0 6413 while ($54--) {
michael@0 6414 var $55 = {};
michael@0 6415 bbox($bytes, $stream, $55, swfVersion, tagCode);
michael@0 6416 $53.push($55);
michael@0 6417 }
michael@0 6418 var kerningCount = readUi16($bytes, $stream);
michael@0 6419 var $56 = $.kerning = [];
michael@0 6420 var $57 = kerningCount;
michael@0 6421 while ($57--) {
michael@0 6422 var $58 = {};
michael@0 6423 kerning($bytes, $stream, $58, swfVersion, tagCode, wide);
michael@0 6424 $56.push($58);
michael@0 6425 }
michael@0 6426 }
michael@0 6427 return $;
michael@0 6428 }
michael@0 6429 function fileAttributes($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6430 $ || ($ = {});
michael@0 6431 var reserved = readUb($bytes, $stream, 1);
michael@0 6432 $.useDirectBlit = readUb($bytes, $stream, 1);
michael@0 6433 $.useGpu = readUb($bytes, $stream, 1);
michael@0 6434 $.hasMetadata = readUb($bytes, $stream, 1);
michael@0 6435 $.doAbc = readUb($bytes, $stream, 1);
michael@0 6436 $.noCrossDomainCaching = readUb($bytes, $stream, 1);
michael@0 6437 $.relativeUrls = readUb($bytes, $stream, 1);
michael@0 6438 $.network = readUb($bytes, $stream, 1);
michael@0 6439 var pad = readUb($bytes, $stream, 24);
michael@0 6440 return $;
michael@0 6441 }
michael@0 6442 function doABC($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6443 $ || ($ = {});
michael@0 6444 if (tagCode === 82) {
michael@0 6445 $.flags = readUi32($bytes, $stream);
michael@0 6446 } else {
michael@0 6447 $.flags = 0;
michael@0 6448 }
michael@0 6449 if (tagCode === 82) {
michael@0 6450 $.name = readString($bytes, $stream, 0);
michael@0 6451 } else {
michael@0 6452 $.name = '';
michael@0 6453 }
michael@0 6454 $.data = readBinary($bytes, $stream, 0);
michael@0 6455 return $;
michael@0 6456 }
michael@0 6457 function exportAssets($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6458 $ || ($ = {});
michael@0 6459 var exportsCount = readUi16($bytes, $stream);
michael@0 6460 var $0 = $.exports = [];
michael@0 6461 var $1 = exportsCount;
michael@0 6462 while ($1--) {
michael@0 6463 var $2 = {};
michael@0 6464 $2.symbolId = readUi16($bytes, $stream);
michael@0 6465 $2.className = readString($bytes, $stream, 0);
michael@0 6466 $0.push($2);
michael@0 6467 }
michael@0 6468 return $;
michael@0 6469 }
michael@0 6470 function symbolClass($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6471 $ || ($ = {});
michael@0 6472 var symbolCount = readUi16($bytes, $stream);
michael@0 6473 var $0 = $.exports = [];
michael@0 6474 var $1 = symbolCount;
michael@0 6475 while ($1--) {
michael@0 6476 var $2 = {};
michael@0 6477 $2.symbolId = readUi16($bytes, $stream);
michael@0 6478 $2.className = readString($bytes, $stream, 0);
michael@0 6479 $0.push($2);
michael@0 6480 }
michael@0 6481 return $;
michael@0 6482 }
michael@0 6483 function defineScalingGrid($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6484 $ || ($ = {});
michael@0 6485 $.symbolId = readUi16($bytes, $stream);
michael@0 6486 var $0 = $.splitter = {};
michael@0 6487 bbox($bytes, $stream, $0, swfVersion, tagCode);
michael@0 6488 return $;
michael@0 6489 }
michael@0 6490 function defineScene($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6491 $ || ($ = {});
michael@0 6492 var sceneCount = readEncodedU32($bytes, $stream);
michael@0 6493 var $0 = $.scenes = [];
michael@0 6494 var $1 = sceneCount;
michael@0 6495 while ($1--) {
michael@0 6496 var $2 = {};
michael@0 6497 $2.offset = readEncodedU32($bytes, $stream);
michael@0 6498 $2.name = readString($bytes, $stream, 0);
michael@0 6499 $0.push($2);
michael@0 6500 }
michael@0 6501 var labelCount = readEncodedU32($bytes, $stream);
michael@0 6502 var $3 = $.labels = [];
michael@0 6503 var $4 = labelCount;
michael@0 6504 while ($4--) {
michael@0 6505 var $5 = {};
michael@0 6506 $5.frame = readEncodedU32($bytes, $stream);
michael@0 6507 $5.name = readString($bytes, $stream, 0);
michael@0 6508 $3.push($5);
michael@0 6509 }
michael@0 6510 return $;
michael@0 6511 }
michael@0 6512 function bbox($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6513 align($bytes, $stream);
michael@0 6514 var bits = readUb($bytes, $stream, 5);
michael@0 6515 var xMin = readSb($bytes, $stream, bits);
michael@0 6516 var xMax = readSb($bytes, $stream, bits);
michael@0 6517 var yMin = readSb($bytes, $stream, bits);
michael@0 6518 var yMax = readSb($bytes, $stream, bits);
michael@0 6519 $.xMin = xMin;
michael@0 6520 $.xMax = xMax;
michael@0 6521 $.yMin = yMin;
michael@0 6522 $.yMax = yMax;
michael@0 6523 align($bytes, $stream);
michael@0 6524 }
michael@0 6525 function rgb($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6526 $.red = readUi8($bytes, $stream);
michael@0 6527 $.green = readUi8($bytes, $stream);
michael@0 6528 $.blue = readUi8($bytes, $stream);
michael@0 6529 $.alpha = 255;
michael@0 6530 return;
michael@0 6531 }
michael@0 6532 function rgba($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6533 $.red = readUi8($bytes, $stream);
michael@0 6534 $.green = readUi8($bytes, $stream);
michael@0 6535 $.blue = readUi8($bytes, $stream);
michael@0 6536 $.alpha = readUi8($bytes, $stream);
michael@0 6537 return;
michael@0 6538 }
michael@0 6539 function argb($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6540 $.alpha = readUi8($bytes, $stream);
michael@0 6541 $.red = readUi8($bytes, $stream);
michael@0 6542 $.green = readUi8($bytes, $stream);
michael@0 6543 $.blue = readUi8($bytes, $stream);
michael@0 6544 }
michael@0 6545 function fillSolid($bytes, $stream, $, swfVersion, tagCode, isMorph) {
michael@0 6546 if (tagCode > 22 || isMorph) {
michael@0 6547 var $125 = $.color = {};
michael@0 6548 rgba($bytes, $stream, $125, swfVersion, tagCode);
michael@0 6549 } else {
michael@0 6550 var $126 = $.color = {};
michael@0 6551 rgb($bytes, $stream, $126, swfVersion, tagCode);
michael@0 6552 }
michael@0 6553 if (isMorph) {
michael@0 6554 var $127 = $.colorMorph = {};
michael@0 6555 rgba($bytes, $stream, $127, swfVersion, tagCode);
michael@0 6556 }
michael@0 6557 return;
michael@0 6558 }
michael@0 6559 function matrix($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6560 align($bytes, $stream);
michael@0 6561 var hasScale = readUb($bytes, $stream, 1);
michael@0 6562 if (hasScale) {
michael@0 6563 var bits = readUb($bytes, $stream, 5);
michael@0 6564 $.a = readFb($bytes, $stream, bits);
michael@0 6565 $.d = readFb($bytes, $stream, bits);
michael@0 6566 } else {
michael@0 6567 $.a = 1;
michael@0 6568 $.d = 1;
michael@0 6569 }
michael@0 6570 var hasRotate = readUb($bytes, $stream, 1);
michael@0 6571 if (hasRotate) {
michael@0 6572 var bits = readUb($bytes, $stream, 5);
michael@0 6573 $.b = readFb($bytes, $stream, bits);
michael@0 6574 $.c = readFb($bytes, $stream, bits);
michael@0 6575 } else {
michael@0 6576 $.b = 0;
michael@0 6577 $.c = 0;
michael@0 6578 }
michael@0 6579 var bits = readUb($bytes, $stream, 5);
michael@0 6580 var e = readSb($bytes, $stream, bits);
michael@0 6581 var f = readSb($bytes, $stream, bits);
michael@0 6582 $.tx = e;
michael@0 6583 $.ty = f;
michael@0 6584 align($bytes, $stream);
michael@0 6585 }
michael@0 6586 function cxform($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6587 align($bytes, $stream);
michael@0 6588 var hasOffsets = readUb($bytes, $stream, 1);
michael@0 6589 var hasMultipliers = readUb($bytes, $stream, 1);
michael@0 6590 var bits = readUb($bytes, $stream, 4);
michael@0 6591 if (hasMultipliers) {
michael@0 6592 $.redMultiplier = readSb($bytes, $stream, bits);
michael@0 6593 $.greenMultiplier = readSb($bytes, $stream, bits);
michael@0 6594 $.blueMultiplier = readSb($bytes, $stream, bits);
michael@0 6595 if (tagCode > 4) {
michael@0 6596 $.alphaMultiplier = readSb($bytes, $stream, bits);
michael@0 6597 } else {
michael@0 6598 $.alphaMultiplier = 256;
michael@0 6599 }
michael@0 6600 } else {
michael@0 6601 $.redMultiplier = 256;
michael@0 6602 $.greenMultiplier = 256;
michael@0 6603 $.blueMultiplier = 256;
michael@0 6604 $.alphaMultiplier = 256;
michael@0 6605 }
michael@0 6606 if (hasOffsets) {
michael@0 6607 $.redOffset = readSb($bytes, $stream, bits);
michael@0 6608 $.greenOffset = readSb($bytes, $stream, bits);
michael@0 6609 $.blueOffset = readSb($bytes, $stream, bits);
michael@0 6610 if (tagCode > 4) {
michael@0 6611 $.alphaOffset = readSb($bytes, $stream, bits);
michael@0 6612 } else {
michael@0 6613 $.alphaOffset = 0;
michael@0 6614 }
michael@0 6615 } else {
michael@0 6616 $.redOffset = 0;
michael@0 6617 $.greenOffset = 0;
michael@0 6618 $.blueOffset = 0;
michael@0 6619 $.alphaOffset = 0;
michael@0 6620 }
michael@0 6621 align($bytes, $stream);
michael@0 6622 }
michael@0 6623 function fillGradient($bytes, $stream, $, swfVersion, tagCode, isMorph, type) {
michael@0 6624 var $128 = $.matrix = {};
michael@0 6625 matrix($bytes, $stream, $128, swfVersion, tagCode);
michael@0 6626 if (isMorph) {
michael@0 6627 var $129 = $.matrixMorph = {};
michael@0 6628 matrix($bytes, $stream, $129, swfVersion, tagCode);
michael@0 6629 }
michael@0 6630 gradient($bytes, $stream, $, swfVersion, tagCode, isMorph, type);
michael@0 6631 }
michael@0 6632 function gradient($bytes, $stream, $, swfVersion, tagCode, isMorph, type) {
michael@0 6633 if (tagCode === 83) {
michael@0 6634 $.spreadMode = readUb($bytes, $stream, 2);
michael@0 6635 $.interpolationMode = readUb($bytes, $stream, 2);
michael@0 6636 } else {
michael@0 6637 var pad = readUb($bytes, $stream, 4);
michael@0 6638 }
michael@0 6639 var count = $.count = readUb($bytes, $stream, 4);
michael@0 6640 var $130 = $.records = [];
michael@0 6641 var $131 = count;
michael@0 6642 while ($131--) {
michael@0 6643 var $132 = {};
michael@0 6644 gradientRecord($bytes, $stream, $132, swfVersion, tagCode, isMorph);
michael@0 6645 $130.push($132);
michael@0 6646 }
michael@0 6647 if (type === 19) {
michael@0 6648 $.focalPoint = readFixed8($bytes, $stream);
michael@0 6649 if (isMorph) {
michael@0 6650 $.focalPointMorph = readFixed8($bytes, $stream);
michael@0 6651 }
michael@0 6652 }
michael@0 6653 }
michael@0 6654 function gradientRecord($bytes, $stream, $, swfVersion, tagCode, isMorph) {
michael@0 6655 $.ratio = readUi8($bytes, $stream);
michael@0 6656 if (tagCode > 22) {
michael@0 6657 var $133 = $.color = {};
michael@0 6658 rgba($bytes, $stream, $133, swfVersion, tagCode);
michael@0 6659 } else {
michael@0 6660 var $134 = $.color = {};
michael@0 6661 rgb($bytes, $stream, $134, swfVersion, tagCode);
michael@0 6662 }
michael@0 6663 if (isMorph) {
michael@0 6664 $.ratioMorph = readUi8($bytes, $stream);
michael@0 6665 var $135 = $.colorMorph = {};
michael@0 6666 rgba($bytes, $stream, $135, swfVersion, tagCode);
michael@0 6667 }
michael@0 6668 }
michael@0 6669 function morphShapeWithStyle($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes) {
michael@0 6670 var eos, bits;
michael@0 6671 var temp = styles($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes);
michael@0 6672 var lineBits = temp.lineBits;
michael@0 6673 var fillBits = temp.fillBits;
michael@0 6674 var $160 = $.records = [];
michael@0 6675 do {
michael@0 6676 var $161 = {};
michael@0 6677 var temp = shapeRecord($bytes, $stream, $161, swfVersion, tagCode, isMorph, fillBits, lineBits, hasStrokes, bits);
michael@0 6678 var eos = temp.eos;
michael@0 6679 var flags = temp.flags;
michael@0 6680 var type = temp.type;
michael@0 6681 var fillBits = temp.fillBits;
michael@0 6682 var lineBits = temp.lineBits;
michael@0 6683 var bits = temp.bits;
michael@0 6684 $160.push($161);
michael@0 6685 } while (!eos);
michael@0 6686 var temp = styleBits($bytes, $stream, $, swfVersion, tagCode);
michael@0 6687 var fillBits = temp.fillBits;
michael@0 6688 var lineBits = temp.lineBits;
michael@0 6689 var $162 = $.recordsMorph = [];
michael@0 6690 do {
michael@0 6691 var $163 = {};
michael@0 6692 var temp = shapeRecord($bytes, $stream, $163, swfVersion, tagCode, isMorph, fillBits, lineBits, hasStrokes, bits);
michael@0 6693 eos = temp.eos;
michael@0 6694 var flags = temp.flags;
michael@0 6695 var type = temp.type;
michael@0 6696 var fillBits = temp.fillBits;
michael@0 6697 var lineBits = temp.lineBits;
michael@0 6698 bits = temp.bits;
michael@0 6699 $162.push($163);
michael@0 6700 } while (!eos);
michael@0 6701 }
michael@0 6702 function shapeWithStyle($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes) {
michael@0 6703 var eos;
michael@0 6704 var temp = styles($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes);
michael@0 6705 var fillBits = temp.fillBits;
michael@0 6706 var lineBits = temp.lineBits;
michael@0 6707 var $160 = $.records = [];
michael@0 6708 do {
michael@0 6709 var $161 = {};
michael@0 6710 var temp = shapeRecord($bytes, $stream, $161, swfVersion, tagCode, isMorph, fillBits, lineBits, hasStrokes, bits);
michael@0 6711 eos = temp.eos;
michael@0 6712 var flags = temp.flags;
michael@0 6713 var type = temp.type;
michael@0 6714 var fillBits = temp.fillBits;
michael@0 6715 var lineBits = temp.lineBits;
michael@0 6716 var bits = temp.bits;
michael@0 6717 $160.push($161);
michael@0 6718 } while (!eos);
michael@0 6719 }
michael@0 6720 function shapeRecord($bytes, $stream, $, swfVersion, tagCode, isMorph, fillBits, lineBits, hasStrokes, bits) {
michael@0 6721 var type = $.type = readUb($bytes, $stream, 1);
michael@0 6722 var flags = readUb($bytes, $stream, 5);
michael@0 6723 var eos = $.eos = !(type || flags);
michael@0 6724 if (type) {
michael@0 6725 var temp = shapeRecordEdge($bytes, $stream, $, swfVersion, tagCode, flags, bits);
michael@0 6726 var bits = temp.bits;
michael@0 6727 } else {
michael@0 6728 var temp = shapeRecordSetup($bytes, $stream, $, swfVersion, tagCode, flags, isMorph, fillBits, lineBits, hasStrokes, bits);
michael@0 6729 var fillBits = temp.fillBits;
michael@0 6730 var lineBits = temp.lineBits;
michael@0 6731 var bits = temp.bits;
michael@0 6732 }
michael@0 6733 return {
michael@0 6734 type: type,
michael@0 6735 flags: flags,
michael@0 6736 eos: eos,
michael@0 6737 fillBits: fillBits,
michael@0 6738 lineBits: lineBits,
michael@0 6739 bits: bits
michael@0 6740 };
michael@0 6741 }
michael@0 6742 function shapeRecordEdge($bytes, $stream, $, swfVersion, tagCode, flags, bits) {
michael@0 6743 var isStraight = 0, tmp = 0, bits = 0, isGeneral = 0, isVertical = 0;
michael@0 6744 isStraight = $.isStraight = flags >> 4;
michael@0 6745 tmp = flags & 15;
michael@0 6746 bits = tmp + 2;
michael@0 6747 if (isStraight) {
michael@0 6748 isGeneral = $.isGeneral = readUb($bytes, $stream, 1);
michael@0 6749 if (isGeneral) {
michael@0 6750 $.deltaX = readSb($bytes, $stream, bits);
michael@0 6751 $.deltaY = readSb($bytes, $stream, bits);
michael@0 6752 } else {
michael@0 6753 isVertical = $.isVertical = readUb($bytes, $stream, 1);
michael@0 6754 if (isVertical) {
michael@0 6755 $.deltaY = readSb($bytes, $stream, bits);
michael@0 6756 } else {
michael@0 6757 $.deltaX = readSb($bytes, $stream, bits);
michael@0 6758 }
michael@0 6759 }
michael@0 6760 } else {
michael@0 6761 $.controlDeltaX = readSb($bytes, $stream, bits);
michael@0 6762 $.controlDeltaY = readSb($bytes, $stream, bits);
michael@0 6763 $.anchorDeltaX = readSb($bytes, $stream, bits);
michael@0 6764 $.anchorDeltaY = readSb($bytes, $stream, bits);
michael@0 6765 }
michael@0 6766 return {
michael@0 6767 bits: bits
michael@0 6768 };
michael@0 6769 }
michael@0 6770 function shapeRecordSetup($bytes, $stream, $, swfVersion, tagCode, flags, isMorph, fillBits, lineBits, hasStrokes, bits) {
michael@0 6771 var hasNewStyles = 0, hasLineStyle = 0, hasFillStyle1 = 0;
michael@0 6772 var hasFillStyle0 = 0, move = 0;
michael@0 6773 if (tagCode > 2) {
michael@0 6774 hasNewStyles = $.hasNewStyles = flags >> 4;
michael@0 6775 } else {
michael@0 6776 hasNewStyles = $.hasNewStyles = 0;
michael@0 6777 }
michael@0 6778 hasLineStyle = $.hasLineStyle = flags >> 3 & 1;
michael@0 6779 hasFillStyle1 = $.hasFillStyle1 = flags >> 2 & 1;
michael@0 6780 hasFillStyle0 = $.hasFillStyle0 = flags >> 1 & 1;
michael@0 6781 move = $.move = flags & 1;
michael@0 6782 if (move) {
michael@0 6783 bits = readUb($bytes, $stream, 5);
michael@0 6784 $.moveX = readSb($bytes, $stream, bits);
michael@0 6785 $.moveY = readSb($bytes, $stream, bits);
michael@0 6786 }
michael@0 6787 if (hasFillStyle0) {
michael@0 6788 $.fillStyle0 = readUb($bytes, $stream, fillBits);
michael@0 6789 }
michael@0 6790 if (hasFillStyle1) {
michael@0 6791 $.fillStyle1 = readUb($bytes, $stream, fillBits);
michael@0 6792 }
michael@0 6793 if (hasLineStyle) {
michael@0 6794 $.lineStyle = readUb($bytes, $stream, lineBits);
michael@0 6795 }
michael@0 6796 if (hasNewStyles) {
michael@0 6797 var temp = styles($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes);
michael@0 6798 var lineBits = temp.lineBits;
michael@0 6799 var fillBits = temp.fillBits;
michael@0 6800 }
michael@0 6801 return {
michael@0 6802 lineBits: lineBits,
michael@0 6803 fillBits: fillBits,
michael@0 6804 bits: bits
michael@0 6805 };
michael@0 6806 }
michael@0 6807 function styles($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes) {
michael@0 6808 fillStyleArray($bytes, $stream, $, swfVersion, tagCode, isMorph);
michael@0 6809 lineStyleArray($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes);
michael@0 6810 var temp = styleBits($bytes, $stream, $, swfVersion, tagCode);
michael@0 6811 var fillBits = temp.fillBits;
michael@0 6812 var lineBits = temp.lineBits;
michael@0 6813 return {
michael@0 6814 fillBits: fillBits,
michael@0 6815 lineBits: lineBits
michael@0 6816 };
michael@0 6817 }
michael@0 6818 function fillStyleArray($bytes, $stream, $, swfVersion, tagCode, isMorph) {
michael@0 6819 var count;
michael@0 6820 var tmp = readUi8($bytes, $stream);
michael@0 6821 if (tagCode > 2 && tmp === 255) {
michael@0 6822 count = readUi16($bytes, $stream);
michael@0 6823 } else {
michael@0 6824 count = tmp;
michael@0 6825 }
michael@0 6826 var $4 = $.fillStyles = [];
michael@0 6827 var $5 = count;
michael@0 6828 while ($5--) {
michael@0 6829 var $6 = {};
michael@0 6830 fillStyle($bytes, $stream, $6, swfVersion, tagCode, isMorph);
michael@0 6831 $4.push($6);
michael@0 6832 }
michael@0 6833 }
michael@0 6834 function lineStyleArray($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes) {
michael@0 6835 var count;
michael@0 6836 var tmp = readUi8($bytes, $stream);
michael@0 6837 if (tagCode > 2 && tmp === 255) {
michael@0 6838 count = readUi16($bytes, $stream);
michael@0 6839 } else {
michael@0 6840 count = tmp;
michael@0 6841 }
michael@0 6842 var $138 = $.lineStyles = [];
michael@0 6843 var $139 = count;
michael@0 6844 while ($139--) {
michael@0 6845 var $140 = {};
michael@0 6846 lineStyle($bytes, $stream, $140, swfVersion, tagCode, isMorph, hasStrokes);
michael@0 6847 $138.push($140);
michael@0 6848 }
michael@0 6849 }
michael@0 6850 function styleBits($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6851 align($bytes, $stream);
michael@0 6852 var fillBits = readUb($bytes, $stream, 4);
michael@0 6853 var lineBits = readUb($bytes, $stream, 4);
michael@0 6854 return {
michael@0 6855 fillBits: fillBits,
michael@0 6856 lineBits: lineBits
michael@0 6857 };
michael@0 6858 }
michael@0 6859 function fillStyle($bytes, $stream, $, swfVersion, tagCode, isMorph) {
michael@0 6860 var type = $.type = readUi8($bytes, $stream);
michael@0 6861 switch (type) {
michael@0 6862 case 0:
michael@0 6863 fillSolid($bytes, $stream, $, swfVersion, tagCode, isMorph);
michael@0 6864 break;
michael@0 6865 case 16:
michael@0 6866 case 18:
michael@0 6867 case 19:
michael@0 6868 fillGradient($bytes, $stream, $, swfVersion, tagCode, isMorph, type);
michael@0 6869 break;
michael@0 6870 case 64:
michael@0 6871 case 65:
michael@0 6872 case 66:
michael@0 6873 case 67:
michael@0 6874 fillBitmap($bytes, $stream, $, swfVersion, tagCode, isMorph, type);
michael@0 6875 break;
michael@0 6876 default:
michael@0 6877 }
michael@0 6878 }
michael@0 6879 function lineStyle($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes) {
michael@0 6880 $.width = readUi16($bytes, $stream);
michael@0 6881 if (isMorph) {
michael@0 6882 $.widthMorph = readUi16($bytes, $stream);
michael@0 6883 }
michael@0 6884 if (hasStrokes) {
michael@0 6885 align($bytes, $stream);
michael@0 6886 $.startCapStyle = readUb($bytes, $stream, 2);
michael@0 6887 var joinStyle = $.joinStyle = readUb($bytes, $stream, 2);
michael@0 6888 var hasFill = $.hasFill = readUb($bytes, $stream, 1);
michael@0 6889 $.noHscale = readUb($bytes, $stream, 1);
michael@0 6890 $.noVscale = readUb($bytes, $stream, 1);
michael@0 6891 $.pixelHinting = readUb($bytes, $stream, 1);
michael@0 6892 var reserved = readUb($bytes, $stream, 5);
michael@0 6893 $.noClose = readUb($bytes, $stream, 1);
michael@0 6894 $.endCapStyle = readUb($bytes, $stream, 2);
michael@0 6895 if (joinStyle === 2) {
michael@0 6896 $.miterLimitFactor = readFixed8($bytes, $stream);
michael@0 6897 }
michael@0 6898 if (hasFill) {
michael@0 6899 var $141 = $.fillStyle = {};
michael@0 6900 fillStyle($bytes, $stream, $141, swfVersion, tagCode, isMorph);
michael@0 6901 } else {
michael@0 6902 var $155 = $.color = {};
michael@0 6903 rgba($bytes, $stream, $155, swfVersion, tagCode);
michael@0 6904 if (isMorph) {
michael@0 6905 var $156 = $.colorMorph = {};
michael@0 6906 rgba($bytes, $stream, $156, swfVersion, tagCode);
michael@0 6907 }
michael@0 6908 }
michael@0 6909 } else {
michael@0 6910 if (tagCode > 22) {
michael@0 6911 var $157 = $.color = {};
michael@0 6912 rgba($bytes, $stream, $157, swfVersion, tagCode);
michael@0 6913 } else {
michael@0 6914 var $158 = $.color = {};
michael@0 6915 rgb($bytes, $stream, $158, swfVersion, tagCode);
michael@0 6916 }
michael@0 6917 if (isMorph) {
michael@0 6918 var $159 = $.colorMorph = {};
michael@0 6919 rgba($bytes, $stream, $159, swfVersion, tagCode);
michael@0 6920 }
michael@0 6921 }
michael@0 6922 }
michael@0 6923 function fillBitmap($bytes, $stream, $, swfVersion, tagCode, isMorph, type) {
michael@0 6924 $.bitmapId = readUi16($bytes, $stream);
michael@0 6925 var $18 = $.matrix = {};
michael@0 6926 matrix($bytes, $stream, $18, swfVersion, tagCode);
michael@0 6927 if (isMorph) {
michael@0 6928 var $19 = $.matrixMorph = {};
michael@0 6929 matrix($bytes, $stream, $19, swfVersion, tagCode);
michael@0 6930 }
michael@0 6931 $.condition = type === 64 || type === 67;
michael@0 6932 }
michael@0 6933 function filterGlow($bytes, $stream, $, swfVersion, tagCode, type) {
michael@0 6934 var count;
michael@0 6935 if (type === 4 || type === 7) {
michael@0 6936 count = readUi8($bytes, $stream);
michael@0 6937 } else {
michael@0 6938 count = 1;
michael@0 6939 }
michael@0 6940 var $5 = $.colors = [];
michael@0 6941 var $6 = count;
michael@0 6942 while ($6--) {
michael@0 6943 var $7 = {};
michael@0 6944 rgba($bytes, $stream, $7, swfVersion, tagCode);
michael@0 6945 $5.push($7);
michael@0 6946 }
michael@0 6947 if (type === 3) {
michael@0 6948 var $8 = $.higlightColor = {};
michael@0 6949 rgba($bytes, $stream, $8, swfVersion, tagCode);
michael@0 6950 }
michael@0 6951 if (type === 4 || type === 7) {
michael@0 6952 var $9 = $.ratios = [];
michael@0 6953 var $10 = count;
michael@0 6954 while ($10--) {
michael@0 6955 $9.push(readUi8($bytes, $stream));
michael@0 6956 }
michael@0 6957 }
michael@0 6958 $.blurX = readFixed($bytes, $stream);
michael@0 6959 $.blurY = readFixed($bytes, $stream);
michael@0 6960 if (type !== 2) {
michael@0 6961 $.angle = readFixed($bytes, $stream);
michael@0 6962 $.distance = readFixed($bytes, $stream);
michael@0 6963 }
michael@0 6964 $.strength = readFixed8($bytes, $stream);
michael@0 6965 $.innerShadow = readUb($bytes, $stream, 1);
michael@0 6966 $.knockout = readUb($bytes, $stream, 1);
michael@0 6967 $.compositeSource = readUb($bytes, $stream, 1);
michael@0 6968 if (type === 3) {
michael@0 6969 $.onTop = readUb($bytes, $stream, 1);
michael@0 6970 } else {
michael@0 6971 var reserved = readUb($bytes, $stream, 1);
michael@0 6972 }
michael@0 6973 if (type === 4 || type === 7) {
michael@0 6974 $.passes = readUb($bytes, $stream, 4);
michael@0 6975 } else {
michael@0 6976 var reserved = readUb($bytes, $stream, 4);
michael@0 6977 }
michael@0 6978 }
michael@0 6979 function filterBlur($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6980 $.blurX = readFixed($bytes, $stream);
michael@0 6981 $.blurY = readFixed($bytes, $stream);
michael@0 6982 $.passes = readUb($bytes, $stream, 5);
michael@0 6983 var reserved = readUb($bytes, $stream, 3);
michael@0 6984 }
michael@0 6985 function filterConvolution($bytes, $stream, $, swfVersion, tagCode) {
michael@0 6986 var columns = $.columns = readUi8($bytes, $stream);
michael@0 6987 var rows = $.rows = readUi8($bytes, $stream);
michael@0 6988 $.divisor = readFloat($bytes, $stream);
michael@0 6989 $.bias = readFloat($bytes, $stream);
michael@0 6990 var $17 = $.weights = [];
michael@0 6991 var $18 = columns * rows;
michael@0 6992 while ($18--) {
michael@0 6993 $17.push(readFloat($bytes, $stream));
michael@0 6994 }
michael@0 6995 var $19 = $.defaultColor = {};
michael@0 6996 rgba($bytes, $stream, $19, swfVersion, tagCode);
michael@0 6997 var reserved = readUb($bytes, $stream, 6);
michael@0 6998 $.clamp = readUb($bytes, $stream, 1);
michael@0 6999 $.preserveAlpha = readUb($bytes, $stream, 1);
michael@0 7000 }
michael@0 7001 function filterColorMatrix($bytes, $stream, $, swfVersion, tagCode) {
michael@0 7002 var $20 = $.matrix = [];
michael@0 7003 var $21 = 20;
michael@0 7004 while ($21--) {
michael@0 7005 $20.push(readFloat($bytes, $stream));
michael@0 7006 }
michael@0 7007 }
michael@0 7008 function anyFilter($bytes, $stream, $, swfVersion, tagCode) {
michael@0 7009 var type = $.type = readUi8($bytes, $stream);
michael@0 7010 switch (type) {
michael@0 7011 case 0:
michael@0 7012 case 2:
michael@0 7013 case 3:
michael@0 7014 case 4:
michael@0 7015 case 7:
michael@0 7016 filterGlow($bytes, $stream, $, swfVersion, tagCode, type);
michael@0 7017 break;
michael@0 7018 case 1:
michael@0 7019 filterBlur($bytes, $stream, $, swfVersion, tagCode);
michael@0 7020 break;
michael@0 7021 case 5:
michael@0 7022 filterConvolution($bytes, $stream, $, swfVersion, tagCode);
michael@0 7023 break;
michael@0 7024 case 6:
michael@0 7025 filterColorMatrix($bytes, $stream, $, swfVersion, tagCode);
michael@0 7026 break;
michael@0 7027 default:
michael@0 7028 }
michael@0 7029 }
michael@0 7030 function events($bytes, $stream, $, swfVersion, tagCode) {
michael@0 7031 var flags, keyPress;
michael@0 7032 if (swfVersion >= 6) {
michael@0 7033 flags = readUi32($bytes, $stream);
michael@0 7034 } else {
michael@0 7035 flags = readUi16($bytes, $stream);
michael@0 7036 }
michael@0 7037 var eoe = $.eoe = !flags;
michael@0 7038 $.onKeyUp = flags >> 7 & 1;
michael@0 7039 $.onKeyDown = flags >> 6 & 1;
michael@0 7040 $.onMouseUp = flags >> 5 & 1;
michael@0 7041 $.onMouseDown = flags >> 4 & 1;
michael@0 7042 $.onMouseMove = flags >> 3 & 1;
michael@0 7043 $.onUnload = flags >> 2 & 1;
michael@0 7044 $.onEnterFrame = flags >> 1 & 1;
michael@0 7045 $.onLoad = flags & 1;
michael@0 7046 if (swfVersion >= 6) {
michael@0 7047 $.onDragOver = flags >> 15 & 1;
michael@0 7048 $.onRollOut = flags >> 14 & 1;
michael@0 7049 $.onRollOver = flags >> 13 & 1;
michael@0 7050 $.onReleaseOutside = flags >> 12 & 1;
michael@0 7051 $.onRelease = flags >> 11 & 1;
michael@0 7052 $.onPress = flags >> 10 & 1;
michael@0 7053 $.onInitialize = flags >> 9 & 1;
michael@0 7054 $.onData = flags >> 8 & 1;
michael@0 7055 if (swfVersion >= 7) {
michael@0 7056 $.onConstruct = flags >> 18 & 1;
michael@0 7057 } else {
michael@0 7058 $.onConstruct = 0;
michael@0 7059 }
michael@0 7060 keyPress = $.keyPress = flags >> 17 & 1;
michael@0 7061 $.onDragOut = flags >> 16 & 1;
michael@0 7062 }
michael@0 7063 if (!eoe) {
michael@0 7064 var length = $.length = readUi32($bytes, $stream);
michael@0 7065 if (keyPress) {
michael@0 7066 $.keyCode = readUi8($bytes, $stream);
michael@0 7067 }
michael@0 7068 $.actionsData = readBinary($bytes, $stream, length - (keyPress ? 1 : 0));
michael@0 7069 }
michael@0 7070 return {
michael@0 7071 eoe: eoe
michael@0 7072 };
michael@0 7073 }
michael@0 7074 function kerning($bytes, $stream, $, swfVersion, tagCode, wide) {
michael@0 7075 if (wide) {
michael@0 7076 $.code1 = readUi16($bytes, $stream);
michael@0 7077 $.code2 = readUi16($bytes, $stream);
michael@0 7078 } else {
michael@0 7079 $.code1 = readUi8($bytes, $stream);
michael@0 7080 $.code2 = readUi8($bytes, $stream);
michael@0 7081 }
michael@0 7082 $.adjustment = readUi16($bytes, $stream);
michael@0 7083 }
michael@0 7084 function textEntry($bytes, $stream, $, swfVersion, tagCode, glyphBits, advanceBits) {
michael@0 7085 $.glyphIndex = readUb($bytes, $stream, glyphBits);
michael@0 7086 $.advance = readSb($bytes, $stream, advanceBits);
michael@0 7087 }
michael@0 7088 function textRecordSetup($bytes, $stream, $, swfVersion, tagCode, flags) {
michael@0 7089 var hasFont = $.hasFont = flags >> 3 & 1;
michael@0 7090 var hasColor = $.hasColor = flags >> 2 & 1;
michael@0 7091 var hasMoveY = $.hasMoveY = flags >> 1 & 1;
michael@0 7092 var hasMoveX = $.hasMoveX = flags & 1;
michael@0 7093 if (hasFont) {
michael@0 7094 $.fontId = readUi16($bytes, $stream);
michael@0 7095 }
michael@0 7096 if (hasColor) {
michael@0 7097 if (tagCode === 33) {
michael@0 7098 var $4 = $.color = {};
michael@0 7099 rgba($bytes, $stream, $4, swfVersion, tagCode);
michael@0 7100 } else {
michael@0 7101 var $5 = $.color = {};
michael@0 7102 rgb($bytes, $stream, $5, swfVersion, tagCode);
michael@0 7103 }
michael@0 7104 }
michael@0 7105 if (hasMoveX) {
michael@0 7106 $.moveX = readSi16($bytes, $stream);
michael@0 7107 }
michael@0 7108 if (hasMoveY) {
michael@0 7109 $.moveY = readSi16($bytes, $stream);
michael@0 7110 }
michael@0 7111 if (hasFont) {
michael@0 7112 $.fontHeight = readUi16($bytes, $stream);
michael@0 7113 }
michael@0 7114 }
michael@0 7115 function textRecord($bytes, $stream, $, swfVersion, tagCode, glyphBits, advanceBits) {
michael@0 7116 var glyphCount;
michael@0 7117 align($bytes, $stream);
michael@0 7118 var flags = readUb($bytes, $stream, 8);
michael@0 7119 var eot = $.eot = !flags;
michael@0 7120 textRecordSetup($bytes, $stream, $, swfVersion, tagCode, flags);
michael@0 7121 if (!eot) {
michael@0 7122 var tmp = readUi8($bytes, $stream);
michael@0 7123 if (swfVersion > 6) {
michael@0 7124 glyphCount = $.glyphCount = tmp;
michael@0 7125 } else {
michael@0 7126 glyphCount = $.glyphCount = tmp & 127;
michael@0 7127 }
michael@0 7128 var $6 = $.entries = [];
michael@0 7129 var $7 = glyphCount;
michael@0 7130 while ($7--) {
michael@0 7131 var $8 = {};
michael@0 7132 textEntry($bytes, $stream, $8, swfVersion, tagCode, glyphBits, advanceBits);
michael@0 7133 $6.push($8);
michael@0 7134 }
michael@0 7135 }
michael@0 7136 return {
michael@0 7137 eot: eot
michael@0 7138 };
michael@0 7139 }
michael@0 7140 function soundEnvelope($bytes, $stream, $, swfVersion, tagCode) {
michael@0 7141 $.pos44 = readUi32($bytes, $stream);
michael@0 7142 $.volumeLeft = readUi16($bytes, $stream);
michael@0 7143 $.volumeRight = readUi16($bytes, $stream);
michael@0 7144 }
michael@0 7145 function soundInfo($bytes, $stream, $, swfVersion, tagCode) {
michael@0 7146 var reserved = readUb($bytes, $stream, 2);
michael@0 7147 $.stop = readUb($bytes, $stream, 1);
michael@0 7148 $.noMultiple = readUb($bytes, $stream, 1);
michael@0 7149 var hasEnvelope = $.hasEnvelope = readUb($bytes, $stream, 1);
michael@0 7150 var hasLoops = $.hasLoops = readUb($bytes, $stream, 1);
michael@0 7151 var hasOutPoint = $.hasOutPoint = readUb($bytes, $stream, 1);
michael@0 7152 var hasInPoint = $.hasInPoint = readUb($bytes, $stream, 1);
michael@0 7153 if (hasInPoint) {
michael@0 7154 $.inPoint = readUi32($bytes, $stream);
michael@0 7155 }
michael@0 7156 if (hasOutPoint) {
michael@0 7157 $.outPoint = readUi32($bytes, $stream);
michael@0 7158 }
michael@0 7159 if (hasLoops) {
michael@0 7160 $.loopCount = readUi16($bytes, $stream);
michael@0 7161 }
michael@0 7162 if (hasEnvelope) {
michael@0 7163 var envelopeCount = $.envelopeCount = readUi8($bytes, $stream);
michael@0 7164 var $1 = $.envelopes = [];
michael@0 7165 var $2 = envelopeCount;
michael@0 7166 while ($2--) {
michael@0 7167 var $3 = {};
michael@0 7168 soundEnvelope($bytes, $stream, $3, swfVersion, tagCode);
michael@0 7169 $1.push($3);
michael@0 7170 }
michael@0 7171 }
michael@0 7172 }
michael@0 7173 function button($bytes, $stream, $, swfVersion, tagCode) {
michael@0 7174 var hasFilters, blend;
michael@0 7175 var flags = readUi8($bytes, $stream);
michael@0 7176 var eob = $.eob = !flags;
michael@0 7177 if (swfVersion >= 8) {
michael@0 7178 blend = $.blend = flags >> 5 & 1;
michael@0 7179 hasFilters = $.hasFilters = flags >> 4 & 1;
michael@0 7180 } else {
michael@0 7181 blend = $.blend = 0;
michael@0 7182 hasFilters = $.hasFilters = 0;
michael@0 7183 }
michael@0 7184 $.stateHitTest = flags >> 3 & 1;
michael@0 7185 $.stateDown = flags >> 2 & 1;
michael@0 7186 $.stateOver = flags >> 1 & 1;
michael@0 7187 $.stateUp = flags & 1;
michael@0 7188 if (!eob) {
michael@0 7189 $.symbolId = readUi16($bytes, $stream);
michael@0 7190 $.depth = readUi16($bytes, $stream);
michael@0 7191 var $2 = $.matrix = {};
michael@0 7192 matrix($bytes, $stream, $2, swfVersion, tagCode);
michael@0 7193 if (tagCode === 34) {
michael@0 7194 var $3 = $.cxform = {};
michael@0 7195 cxform($bytes, $stream, $3, swfVersion, tagCode);
michael@0 7196 }
michael@0 7197 if (hasFilters) {
michael@0 7198 $.filterCount = readUi8($bytes, $stream);
michael@0 7199 var $4 = $.filters = {};
michael@0 7200 anyFilter($bytes, $stream, $4, swfVersion, tagCode);
michael@0 7201 }
michael@0 7202 if (blend) {
michael@0 7203 $.blendMode = readUi8($bytes, $stream);
michael@0 7204 }
michael@0 7205 }
michael@0 7206 return {
michael@0 7207 eob: eob
michael@0 7208 };
michael@0 7209 }
michael@0 7210 function buttonCondAction($bytes, $stream, $, swfVersion, tagCode) {
michael@0 7211 var buttonCondSize = readUi16($bytes, $stream);
michael@0 7212 var buttonConditions = readUi16($bytes, $stream);
michael@0 7213 $.idleToOverDown = buttonConditions >> 7 & 1;
michael@0 7214 $.outDownToIdle = buttonConditions >> 6 & 1;
michael@0 7215 $.outDownToOverDown = buttonConditions >> 5 & 1;
michael@0 7216 $.overDownToOutDown = buttonConditions >> 4 & 1;
michael@0 7217 $.overDownToOverUp = buttonConditions >> 3 & 1;
michael@0 7218 $.overUpToOverDown = buttonConditions >> 2 & 1;
michael@0 7219 $.overUpToIdle = buttonConditions >> 1 & 1;
michael@0 7220 $.idleToOverUp = buttonConditions & 1;
michael@0 7221 $.mouseEventFlags = buttonConditions & 511;
michael@0 7222 $.keyPress = buttonConditions >> 9 & 127;
michael@0 7223 $.overDownToIdle = buttonConditions >> 8 & 1;
michael@0 7224 if (!buttonCondSize) {
michael@0 7225 $.actionsData = readBinary($bytes, $stream, 0);
michael@0 7226 } else {
michael@0 7227 $.actionsData = readBinary($bytes, $stream, buttonCondSize - 4);
michael@0 7228 }
michael@0 7229 }
michael@0 7230 function shape($bytes, $stream, $, swfVersion, tagCode) {
michael@0 7231 var eos;
michael@0 7232 var temp = styleBits($bytes, $stream, $, swfVersion, tagCode);
michael@0 7233 var fillBits = temp.fillBits;
michael@0 7234 var lineBits = temp.lineBits;
michael@0 7235 var $4 = $.records = [];
michael@0 7236 do {
michael@0 7237 var $5 = {};
michael@0 7238 var isMorph = false;
michael@0 7239 var hasStrokes = false;
michael@0 7240 var temp = shapeRecord($bytes, $stream, $5, swfVersion, tagCode, isMorph, fillBits, lineBits, hasStrokes, bits);
michael@0 7241 eos = temp.eos;
michael@0 7242 var fillBits = temp.fillBits;
michael@0 7243 var lineBits = temp.lineBits;
michael@0 7244 var bits = bits;
michael@0 7245 $4.push($5);
michael@0 7246 } while (!eos);
michael@0 7247 }
michael@0 7248 return {
michael@0 7249 0: undefined,
michael@0 7250 1: undefined,
michael@0 7251 2: defineShape,
michael@0 7252 4: placeObject,
michael@0 7253 5: removeObject,
michael@0 7254 6: defineImage,
michael@0 7255 7: defineButton,
michael@0 7256 8: defineJPEGTables,
michael@0 7257 9: setBackgroundColor,
michael@0 7258 10: defineFont,
michael@0 7259 11: defineLabel,
michael@0 7260 12: doAction,
michael@0 7261 13: undefined,
michael@0 7262 14: defineSound,
michael@0 7263 15: startSound,
michael@0 7264 17: undefined,
michael@0 7265 18: soundStreamHead,
michael@0 7266 19: soundStreamBlock,
michael@0 7267 20: defineBitmap,
michael@0 7268 21: defineImage,
michael@0 7269 22: defineShape,
michael@0 7270 23: undefined,
michael@0 7271 24: undefined,
michael@0 7272 26: placeObject,
michael@0 7273 28: removeObject,
michael@0 7274 32: defineShape,
michael@0 7275 33: defineLabel,
michael@0 7276 34: defineButton,
michael@0 7277 35: defineImage,
michael@0 7278 36: defineBitmap,
michael@0 7279 37: defineText,
michael@0 7280 39: undefined,
michael@0 7281 43: frameLabel,
michael@0 7282 45: soundStreamHead,
michael@0 7283 46: defineShape,
michael@0 7284 48: defineFont2,
michael@0 7285 56: exportAssets,
michael@0 7286 57: undefined,
michael@0 7287 58: undefined,
michael@0 7288 59: doAction,
michael@0 7289 60: undefined,
michael@0 7290 61: undefined,
michael@0 7291 62: undefined,
michael@0 7292 64: undefined,
michael@0 7293 65: undefined,
michael@0 7294 66: undefined,
michael@0 7295 69: fileAttributes,
michael@0 7296 70: placeObject,
michael@0 7297 71: undefined,
michael@0 7298 72: doABC,
michael@0 7299 73: undefined,
michael@0 7300 74: undefined,
michael@0 7301 75: defineFont2,
michael@0 7302 76: symbolClass,
michael@0 7303 77: undefined,
michael@0 7304 78: defineScalingGrid,
michael@0 7305 82: doABC,
michael@0 7306 83: defineShape,
michael@0 7307 84: defineShape,
michael@0 7308 86: defineScene,
michael@0 7309 87: defineBinaryData,
michael@0 7310 88: undefined,
michael@0 7311 89: startSound,
michael@0 7312 90: defineImage,
michael@0 7313 91: undefined
michael@0 7314 };
michael@0 7315 }(this);
michael@0 7316 var readHeader = function readHeader($bytes, $stream, $, swfVersion, tagCode) {
michael@0 7317 $ || ($ = {});
michael@0 7318 var $0 = $.bbox = {};
michael@0 7319 align($bytes, $stream);
michael@0 7320 var bits = readUb($bytes, $stream, 5);
michael@0 7321 var xMin = readSb($bytes, $stream, bits);
michael@0 7322 var xMax = readSb($bytes, $stream, bits);
michael@0 7323 var yMin = readSb($bytes, $stream, bits);
michael@0 7324 var yMax = readSb($bytes, $stream, bits);
michael@0 7325 $0.xMin = xMin;
michael@0 7326 $0.xMax = xMax;
michael@0 7327 $0.yMin = yMin;
michael@0 7328 $0.yMax = yMax;
michael@0 7329 align($bytes, $stream);
michael@0 7330 var frameRateFraction = readUi8($bytes, $stream);
michael@0 7331 $.frameRate = readUi8($bytes, $stream) + frameRateFraction / 256;
michael@0 7332 $.frameCount = readUi16($bytes, $stream);
michael@0 7333 return $;
michael@0 7334 };
michael@0 7335 function readTags(context, stream, swfVersion, final, onprogress, onexception) {
michael@0 7336 var tags = context.tags;
michael@0 7337 var bytes = stream.bytes;
michael@0 7338 var lastSuccessfulPosition;
michael@0 7339 var tag = null;
michael@0 7340 if (context._readTag) {
michael@0 7341 tag = context._readTag;
michael@0 7342 context._readTag = null;
michael@0 7343 }
michael@0 7344 try {
michael@0 7345 while (stream.pos < stream.end) {
michael@0 7346 lastSuccessfulPosition = stream.pos;
michael@0 7347 stream.ensure(2);
michael@0 7348 var tagCodeAndLength = readUi16(bytes, stream);
michael@0 7349 if (!tagCodeAndLength) {
michael@0 7350 final = true;
michael@0 7351 break;
michael@0 7352 }
michael@0 7353 var tagCode = tagCodeAndLength >> 6;
michael@0 7354 var length = tagCodeAndLength & 63;
michael@0 7355 if (length === 63) {
michael@0 7356 stream.ensure(4);
michael@0 7357 length = readUi32(bytes, stream);
michael@0 7358 }
michael@0 7359 if (tag) {
michael@0 7360 if (tagCode === 1 && tag.code === 1) {
michael@0 7361 tag.repeat++;
michael@0 7362 stream.pos += length;
michael@0 7363 continue;
michael@0 7364 }
michael@0 7365 tags.push(tag);
michael@0 7366 if (onprogress && tag.id !== undefined) {
michael@0 7367 onprogress(context);
michael@0 7368 }
michael@0 7369 tag = null;
michael@0 7370 }
michael@0 7371 stream.ensure(length);
michael@0 7372 var substream = stream.substream(stream.pos, stream.pos += length);
michael@0 7373 var subbytes = substream.bytes;
michael@0 7374 var nextTag = {
michael@0 7375 code: tagCode
michael@0 7376 };
michael@0 7377 if (tagCode === 39) {
michael@0 7378 nextTag.type = 'sprite';
michael@0 7379 nextTag.id = readUi16(subbytes, substream);
michael@0 7380 nextTag.frameCount = readUi16(subbytes, substream);
michael@0 7381 nextTag.tags = [];
michael@0 7382 readTags(nextTag, substream, swfVersion, true);
michael@0 7383 } else if (tagCode === 1) {
michael@0 7384 nextTag.repeat = 1;
michael@0 7385 } else {
michael@0 7386 var handler = tagHandler[tagCode];
michael@0 7387 if (handler) {
michael@0 7388 handler(subbytes, substream, nextTag, swfVersion, tagCode);
michael@0 7389 }
michael@0 7390 }
michael@0 7391 tag = nextTag;
michael@0 7392 }
michael@0 7393 if (tag && final) {
michael@0 7394 tag.finalTag = true;
michael@0 7395 tags.push(tag);
michael@0 7396 if (onprogress) {
michael@0 7397 onprogress(context);
michael@0 7398 }
michael@0 7399 } else {
michael@0 7400 context._readTag = tag;
michael@0 7401 }
michael@0 7402 } catch (e) {
michael@0 7403 if (e !== StreamNoDataError) {
michael@0 7404 onexception && onexception(e);
michael@0 7405 throw e;
michael@0 7406 }
michael@0 7407 stream.pos = lastSuccessfulPosition;
michael@0 7408 context._readTag = tag;
michael@0 7409 }
michael@0 7410 }
michael@0 7411 function HeadTailBuffer(defaultSize) {
michael@0 7412 this.bufferSize = defaultSize || 16;
michael@0 7413 this.buffer = new Uint8Array(this.bufferSize);
michael@0 7414 this.pos = 0;
michael@0 7415 }
michael@0 7416 HeadTailBuffer.prototype = {
michael@0 7417 push: function (data, need) {
michael@0 7418 var bufferLengthNeed = this.pos + data.length;
michael@0 7419 if (this.bufferSize < bufferLengthNeed) {
michael@0 7420 var newBufferSize = this.bufferSize;
michael@0 7421 while (newBufferSize < bufferLengthNeed) {
michael@0 7422 newBufferSize <<= 1;
michael@0 7423 }
michael@0 7424 var newBuffer = new Uint8Array(newBufferSize);
michael@0 7425 if (this.bufferSize > 0) {
michael@0 7426 newBuffer.set(this.buffer);
michael@0 7427 }
michael@0 7428 this.buffer = newBuffer;
michael@0 7429 this.bufferSize = newBufferSize;
michael@0 7430 }
michael@0 7431 this.buffer.set(data, this.pos);
michael@0 7432 this.pos += data.length;
michael@0 7433 if (need)
michael@0 7434 return this.pos >= need;
michael@0 7435 },
michael@0 7436 getHead: function (size) {
michael@0 7437 return this.buffer.subarray(0, size);
michael@0 7438 },
michael@0 7439 getTail: function (offset) {
michael@0 7440 return this.buffer.subarray(offset, this.pos);
michael@0 7441 },
michael@0 7442 removeHead: function (size) {
michael@0 7443 var tail = this.getTail(size);
michael@0 7444 this.buffer = new Uint8Array(this.bufferSize);
michael@0 7445 this.buffer.set(tail);
michael@0 7446 this.pos = tail.length;
michael@0 7447 },
michael@0 7448 get arrayBuffer() {
michael@0 7449 return this.buffer.buffer;
michael@0 7450 },
michael@0 7451 get length() {
michael@0 7452 return this.pos;
michael@0 7453 },
michael@0 7454 createStream: function () {
michael@0 7455 return new Stream(this.arrayBuffer, 0, this.length);
michael@0 7456 }
michael@0 7457 };
michael@0 7458 function CompressedPipe(target, length) {
michael@0 7459 this.target = target;
michael@0 7460 this.length = length;
michael@0 7461 this.initialize = true;
michael@0 7462 this.buffer = new HeadTailBuffer(8096);
michael@0 7463 this.state = {
michael@0 7464 bitBuffer: 0,
michael@0 7465 bitLength: 0,
michael@0 7466 compression: {
michael@0 7467 header: null,
michael@0 7468 distanceTable: null,
michael@0 7469 literalTable: null,
michael@0 7470 sym: null,
michael@0 7471 len: null,
michael@0 7472 sym2: null
michael@0 7473 }
michael@0 7474 };
michael@0 7475 this.output = {
michael@0 7476 data: new Uint8Array(length),
michael@0 7477 available: 0,
michael@0 7478 completed: false
michael@0 7479 };
michael@0 7480 }
michael@0 7481 CompressedPipe.prototype = {
michael@0 7482 push: function (data, progressInfo) {
michael@0 7483 var buffer = this.buffer;
michael@0 7484 if (this.initialize) {
michael@0 7485 if (!buffer.push(data, 2))
michael@0 7486 return;
michael@0 7487 var headerBytes = buffer.getHead(2);
michael@0 7488 verifyDeflateHeader(headerBytes);
michael@0 7489 buffer.removeHead(2);
michael@0 7490 this.initialize = false;
michael@0 7491 } else {
michael@0 7492 buffer.push(data);
michael@0 7493 }
michael@0 7494 var stream = buffer.createStream();
michael@0 7495 stream.bitBuffer = this.state.bitBuffer;
michael@0 7496 stream.bitLength = this.state.bitLength;
michael@0 7497 var output = this.output;
michael@0 7498 var lastAvailable = output.available;
michael@0 7499 try {
michael@0 7500 do {
michael@0 7501 inflateBlock(stream, output, this.state.compression);
michael@0 7502 } while (stream.pos < buffer.length && !output.completed);
michael@0 7503 } catch (e) {
michael@0 7504 if (e !== InflateNoDataError)
michael@0 7505 throw e;
michael@0 7506 } finally {
michael@0 7507 this.state.bitBuffer = stream.bitBuffer;
michael@0 7508 this.state.bitLength = stream.bitLength;
michael@0 7509 }
michael@0 7510 buffer.removeHead(stream.pos);
michael@0 7511 this.target.push(output.data.subarray(lastAvailable, output.available), progressInfo);
michael@0 7512 }
michael@0 7513 };
michael@0 7514 function BodyParser(swfVersion, length, options) {
michael@0 7515 this.swf = {
michael@0 7516 swfVersion: swfVersion,
michael@0 7517 parseTime: 0
michael@0 7518 };
michael@0 7519 this.buffer = new HeadTailBuffer(32768);
michael@0 7520 this.initialize = true;
michael@0 7521 this.totalRead = 0;
michael@0 7522 this.length = length;
michael@0 7523 this.options = options;
michael@0 7524 }
michael@0 7525 BodyParser.prototype = {
michael@0 7526 push: function (data, progressInfo) {
michael@0 7527 if (data.length === 0)
michael@0 7528 return;
michael@0 7529 var swf = this.swf;
michael@0 7530 var swfVersion = swf.swfVersion;
michael@0 7531 var buffer = this.buffer;
michael@0 7532 var options = this.options;
michael@0 7533 var stream;
michael@0 7534 if (this.initialize) {
michael@0 7535 var PREFETCH_SIZE = 27;
michael@0 7536 if (!buffer.push(data, PREFETCH_SIZE))
michael@0 7537 return;
michael@0 7538 stream = buffer.createStream();
michael@0 7539 var bytes = stream.bytes;
michael@0 7540 readHeader(bytes, stream, swf);
michael@0 7541 var nextTagHeader = readUi16(bytes, stream);
michael@0 7542 var FILE_ATTRIBUTES_LENGTH = 4;
michael@0 7543 if (nextTagHeader == (SWF_TAG_CODE_FILE_ATTRIBUTES << 6 | FILE_ATTRIBUTES_LENGTH)) {
michael@0 7544 stream.ensure(FILE_ATTRIBUTES_LENGTH);
michael@0 7545 var substream = stream.substream(stream.pos, stream.pos += FILE_ATTRIBUTES_LENGTH);
michael@0 7546 var handler = tagHandler[SWF_TAG_CODE_FILE_ATTRIBUTES];
michael@0 7547 var fileAttributesTag = {
michael@0 7548 code: SWF_TAG_CODE_FILE_ATTRIBUTES
michael@0 7549 };
michael@0 7550 handler(substream.bytes, substream, fileAttributesTag, swfVersion, SWF_TAG_CODE_FILE_ATTRIBUTES);
michael@0 7551 swf.fileAttributes = fileAttributesTag;
michael@0 7552 } else {
michael@0 7553 stream.pos -= 2;
michael@0 7554 swf.fileAttributes = {};
michael@0 7555 }
michael@0 7556 if (options.onstart)
michael@0 7557 options.onstart(swf);
michael@0 7558 swf.tags = [];
michael@0 7559 this.initialize = false;
michael@0 7560 } else {
michael@0 7561 buffer.push(data);
michael@0 7562 stream = buffer.createStream();
michael@0 7563 }
michael@0 7564 var finalBlock = false;
michael@0 7565 if (progressInfo) {
michael@0 7566 swf.bytesLoaded = progressInfo.bytesLoaded;
michael@0 7567 swf.bytesTotal = progressInfo.bytesTotal;
michael@0 7568 finalBlock = progressInfo.bytesLoaded >= progressInfo.bytesTotal;
michael@0 7569 }
michael@0 7570 var readStartTime = performance.now();
michael@0 7571 readTags(swf, stream, swfVersion, finalBlock, options.onprogress, options.onexception);
michael@0 7572 swf.parseTime += performance.now() - readStartTime;
michael@0 7573 var read = stream.pos;
michael@0 7574 buffer.removeHead(read);
michael@0 7575 this.totalRead += read;
michael@0 7576 if (options.oncomplete && swf.tags[swf.tags.length - 1].finalTag) {
michael@0 7577 options.oncomplete(swf);
michael@0 7578 }
michael@0 7579 }
michael@0 7580 };
michael@0 7581 SWF.parseAsync = function swf_parseAsync(options) {
michael@0 7582 var buffer = new HeadTailBuffer();
michael@0 7583 var pipe = {
michael@0 7584 push: function (data, progressInfo) {
michael@0 7585 if (this.target !== undefined) {
michael@0 7586 return this.target.push(data, progressInfo);
michael@0 7587 }
michael@0 7588 if (!buffer.push(data, 8)) {
michael@0 7589 return null;
michael@0 7590 }
michael@0 7591 var bytes = buffer.getHead(8);
michael@0 7592 var magic1 = bytes[0];
michael@0 7593 var magic2 = bytes[1];
michael@0 7594 var magic3 = bytes[2];
michael@0 7595 if ((magic1 === 70 || magic1 === 67) && magic2 === 87 && magic3 === 83) {
michael@0 7596 var swfVersion = bytes[3];
michael@0 7597 var compressed = magic1 === 67;
michael@0 7598 parseSWF(compressed, swfVersion, progressInfo);
michael@0 7599 buffer = null;
michael@0 7600 return;
michael@0 7601 }
michael@0 7602 var isImage = false;
michael@0 7603 var imageType;
michael@0 7604 if (magic1 === 255 && magic2 === 216 && magic3 === 255) {
michael@0 7605 isImage = true;
michael@0 7606 imageType = 'image/jpeg';
michael@0 7607 } else if (magic1 === 137 && magic2 === 80 && magic3 === 78) {
michael@0 7608 isImage = true;
michael@0 7609 imageType = 'image/png';
michael@0 7610 }
michael@0 7611 if (isImage) {
michael@0 7612 parseImage(data, progressInfo.bytesTotal, imageType);
michael@0 7613 }
michael@0 7614 buffer = null;
michael@0 7615 },
michael@0 7616 close: function () {
michael@0 7617 if (buffer) {
michael@0 7618 var symbol = {
michael@0 7619 command: 'empty',
michael@0 7620 data: buffer.buffer.subarray(0, buffer.pos)
michael@0 7621 };
michael@0 7622 options.oncomplete && options.oncomplete(symbol);
michael@0 7623 }
michael@0 7624 if (this.target !== undefined && this.target.close) {
michael@0 7625 this.target.close();
michael@0 7626 }
michael@0 7627 }
michael@0 7628 };
michael@0 7629 function parseSWF(compressed, swfVersion, progressInfo) {
michael@0 7630 var stream = buffer.createStream();
michael@0 7631 stream.pos += 4;
michael@0 7632 var fileLength = readUi32(null, stream);
michael@0 7633 var bodyLength = fileLength - 8;
michael@0 7634 var target = new BodyParser(swfVersion, bodyLength, options);
michael@0 7635 if (compressed) {
michael@0 7636 target = new CompressedPipe(target, bodyLength);
michael@0 7637 }
michael@0 7638 target.push(buffer.getTail(8), progressInfo);
michael@0 7639 pipe['target'] = target;
michael@0 7640 }
michael@0 7641 function parseImage(data, bytesTotal, type) {
michael@0 7642 var buffer = new Uint8Array(bytesTotal);
michael@0 7643 buffer.set(data);
michael@0 7644 var bufferPos = data.length;
michael@0 7645 pipe['target'] = {
michael@0 7646 push: function (data) {
michael@0 7647 buffer.set(data, bufferPos);
michael@0 7648 bufferPos += data.length;
michael@0 7649 },
michael@0 7650 close: function () {
michael@0 7651 var props = {};
michael@0 7652 var chunks;
michael@0 7653 if (type == 'image/jpeg') {
michael@0 7654 chunks = parseJpegChunks(props, buffer);
michael@0 7655 } else {
michael@0 7656 chunks = [
michael@0 7657 buffer
michael@0 7658 ];
michael@0 7659 }
michael@0 7660 var symbol = {
michael@0 7661 type: 'image',
michael@0 7662 props: props,
michael@0 7663 data: new Blob(chunks, {
michael@0 7664 type: type
michael@0 7665 })
michael@0 7666 };
michael@0 7667 options.oncomplete && options.oncomplete(symbol);
michael@0 7668 }
michael@0 7669 };
michael@0 7670 }
michael@0 7671 return pipe;
michael@0 7672 };
michael@0 7673 SWF.parse = function (buffer, options) {
michael@0 7674 if (!options)
michael@0 7675 options = {};
michael@0 7676 var pipe = SWF.parseAsync(options);
michael@0 7677 var bytes = new Uint8Array(buffer);
michael@0 7678 var progressInfo = {
michael@0 7679 bytesLoaded: bytes.length,
michael@0 7680 bytesTotal: bytes.length
michael@0 7681 };
michael@0 7682 pipe.push(bytes, progressInfo);
michael@0 7683 pipe.close();
michael@0 7684 };
michael@0 7685 var $RELEASE = false;
michael@0 7686 var isWorker = typeof window === 'undefined';
michael@0 7687 if (isWorker && !true) {
michael@0 7688 importScripts.apply(null, [
michael@0 7689 '../../lib/DataView.js/DataView.js',
michael@0 7690 '../flash/util.js',
michael@0 7691 'config.js',
michael@0 7692 'swf.js',
michael@0 7693 'types.js',
michael@0 7694 'structs.js',
michael@0 7695 'tags.js',
michael@0 7696 'inflate.js',
michael@0 7697 'stream.js',
michael@0 7698 'templates.js',
michael@0 7699 'generator.js',
michael@0 7700 'handlers.js',
michael@0 7701 'parser.js',
michael@0 7702 'bitmap.js',
michael@0 7703 'button.js',
michael@0 7704 'font.js',
michael@0 7705 'image.js',
michael@0 7706 'label.js',
michael@0 7707 'shape.js',
michael@0 7708 'sound.js',
michael@0 7709 'text.js'
michael@0 7710 ]);
michael@0 7711 }
michael@0 7712 function defineSymbol(swfTag, symbols) {
michael@0 7713 var symbol;
michael@0 7714 switch (swfTag.code) {
michael@0 7715 case SWF_TAG_CODE_DEFINE_BITS:
michael@0 7716 case SWF_TAG_CODE_DEFINE_BITS_JPEG2:
michael@0 7717 case SWF_TAG_CODE_DEFINE_BITS_JPEG3:
michael@0 7718 case SWF_TAG_CODE_DEFINE_BITS_JPEG4:
michael@0 7719 case SWF_TAG_CODE_JPEG_TABLES:
michael@0 7720 symbol = defineImage(swfTag, symbols);
michael@0 7721 break;
michael@0 7722 case SWF_TAG_CODE_DEFINE_BITS_LOSSLESS:
michael@0 7723 case SWF_TAG_CODE_DEFINE_BITS_LOSSLESS2:
michael@0 7724 symbol = defineBitmap(swfTag);
michael@0 7725 break;
michael@0 7726 case SWF_TAG_CODE_DEFINE_BUTTON:
michael@0 7727 case SWF_TAG_CODE_DEFINE_BUTTON2:
michael@0 7728 symbol = defineButton(swfTag, symbols);
michael@0 7729 break;
michael@0 7730 case SWF_TAG_CODE_DEFINE_EDIT_TEXT:
michael@0 7731 symbol = defineText(swfTag, symbols);
michael@0 7732 break;
michael@0 7733 case SWF_TAG_CODE_DEFINE_FONT:
michael@0 7734 case SWF_TAG_CODE_DEFINE_FONT2:
michael@0 7735 case SWF_TAG_CODE_DEFINE_FONT3:
michael@0 7736 case SWF_TAG_CODE_DEFINE_FONT4:
michael@0 7737 symbol = defineFont(swfTag, symbols);
michael@0 7738 break;
michael@0 7739 case SWF_TAG_CODE_DEFINE_MORPH_SHAPE:
michael@0 7740 case SWF_TAG_CODE_DEFINE_MORPH_SHAPE2:
michael@0 7741 case SWF_TAG_CODE_DEFINE_SHAPE:
michael@0 7742 case SWF_TAG_CODE_DEFINE_SHAPE2:
michael@0 7743 case SWF_TAG_CODE_DEFINE_SHAPE3:
michael@0 7744 case SWF_TAG_CODE_DEFINE_SHAPE4:
michael@0 7745 symbol = defineShape(swfTag, symbols);
michael@0 7746 break;
michael@0 7747 case SWF_TAG_CODE_DEFINE_SOUND:
michael@0 7748 symbol = defineSound(swfTag, symbols);
michael@0 7749 break;
michael@0 7750 case SWF_TAG_CODE_DEFINE_BINARY_DATA:
michael@0 7751 symbol = {
michael@0 7752 type: 'binary',
michael@0 7753 id: swfTag.id,
michael@0 7754 data: swfTag.data
michael@0 7755 };
michael@0 7756 break;
michael@0 7757 case SWF_TAG_CODE_DEFINE_SPRITE:
michael@0 7758 var depths = {};
michael@0 7759 var frame = {
michael@0 7760 type: 'frame'
michael@0 7761 };
michael@0 7762 var frames = [];
michael@0 7763 var tags = swfTag.tags;
michael@0 7764 var frameScripts = null;
michael@0 7765 var frameIndex = 0;
michael@0 7766 var soundStream = null;
michael@0 7767 for (var i = 0, n = tags.length; i < n; i++) {
michael@0 7768 var tag = tags[i];
michael@0 7769 switch (tag.code) {
michael@0 7770 case SWF_TAG_CODE_DO_ACTION:
michael@0 7771 if (!frameScripts)
michael@0 7772 frameScripts = [];
michael@0 7773 frameScripts.push(frameIndex);
michael@0 7774 frameScripts.push(tag.actionsData);
michael@0 7775 break;
michael@0 7776 case SWF_TAG_CODE_START_SOUND:
michael@0 7777 var startSounds = frame.startSounds || (frame.startSounds = []);
michael@0 7778 startSounds.push(tag);
michael@0 7779 break;
michael@0 7780 case SWF_TAG_CODE_SOUND_STREAM_HEAD:
michael@0 7781 try {
michael@0 7782 soundStream = createSoundStream(tag);
michael@0 7783 frame.soundStream = soundStream.info;
michael@0 7784 } catch (e) {
michael@0 7785 }
michael@0 7786 break;
michael@0 7787 case SWF_TAG_CODE_SOUND_STREAM_BLOCK:
michael@0 7788 if (soundStream) {
michael@0 7789 frame.soundStreamBlock = soundStream.decode(tag.data);
michael@0 7790 }
michael@0 7791 break;
michael@0 7792 case SWF_TAG_CODE_FRAME_LABEL:
michael@0 7793 frame.labelName = tag.name;
michael@0 7794 break;
michael@0 7795 case SWF_TAG_CODE_PLACE_OBJECT:
michael@0 7796 case SWF_TAG_CODE_PLACE_OBJECT2:
michael@0 7797 case SWF_TAG_CODE_PLACE_OBJECT3:
michael@0 7798 depths[tag.depth] = tag;
michael@0 7799 break;
michael@0 7800 case SWF_TAG_CODE_REMOVE_OBJECT:
michael@0 7801 case SWF_TAG_CODE_REMOVE_OBJECT2:
michael@0 7802 depths[tag.depth] = null;
michael@0 7803 break;
michael@0 7804 case SWF_TAG_CODE_SHOW_FRAME:
michael@0 7805 frameIndex += tag.repeat;
michael@0 7806 frame.repeat = tag.repeat;
michael@0 7807 frame.depths = depths;
michael@0 7808 frames.push(frame);
michael@0 7809 depths = {};
michael@0 7810 frame = {
michael@0 7811 type: 'frame'
michael@0 7812 };
michael@0 7813 break;
michael@0 7814 }
michael@0 7815 }
michael@0 7816 symbol = {
michael@0 7817 type: 'sprite',
michael@0 7818 id: swfTag.id,
michael@0 7819 frameCount: swfTag.frameCount,
michael@0 7820 frames: frames,
michael@0 7821 frameScripts: frameScripts
michael@0 7822 };
michael@0 7823 break;
michael@0 7824 case SWF_TAG_CODE_DEFINE_TEXT:
michael@0 7825 case SWF_TAG_CODE_DEFINE_TEXT2:
michael@0 7826 symbol = defineLabel(swfTag, symbols);
michael@0 7827 break;
michael@0 7828 }
michael@0 7829 if (!symbol) {
michael@0 7830 return {
michael@0 7831 command: 'error',
michael@0 7832 message: 'unknown symbol type: ' + swfTag.code
michael@0 7833 };
michael@0 7834 }
michael@0 7835 symbol.isSymbol = true;
michael@0 7836 symbols[swfTag.id] = symbol;
michael@0 7837 return symbol;
michael@0 7838 }
michael@0 7839 function createParsingContext(commitData) {
michael@0 7840 var depths = {};
michael@0 7841 var symbols = {};
michael@0 7842 var frame = {
michael@0 7843 type: 'frame'
michael@0 7844 };
michael@0 7845 var tagsProcessed = 0;
michael@0 7846 var soundStream = null;
michael@0 7847 var lastProgressSent = 0;
michael@0 7848 return {
michael@0 7849 onstart: function (result) {
michael@0 7850 commitData({
michael@0 7851 command: 'init',
michael@0 7852 result: result
michael@0 7853 });
michael@0 7854 },
michael@0 7855 onprogress: function (result) {
michael@0 7856 if (Date.now() - lastProgressSent > 1000 / 24 || result.bytesLoaded === result.bytesTotal) {
michael@0 7857 commitData({
michael@0 7858 command: 'progress',
michael@0 7859 result: {
michael@0 7860 bytesLoaded: result.bytesLoaded,
michael@0 7861 bytesTotal: result.bytesTotal
michael@0 7862 }
michael@0 7863 });
michael@0 7864 lastProgressSent = Date.now();
michael@0 7865 }
michael@0 7866 var tags = result.tags;
michael@0 7867 for (var n = tags.length; tagsProcessed < n; tagsProcessed++) {
michael@0 7868 var tag = tags[tagsProcessed];
michael@0 7869 if ('id' in tag) {
michael@0 7870 var symbol = defineSymbol(tag, symbols);
michael@0 7871 commitData(symbol, symbol.transferables);
michael@0 7872 continue;
michael@0 7873 }
michael@0 7874 switch (tag.code) {
michael@0 7875 case SWF_TAG_CODE_DEFINE_SCENE_AND_FRAME_LABEL_DATA:
michael@0 7876 frame.sceneData = tag;
michael@0 7877 break;
michael@0 7878 case SWF_TAG_CODE_DEFINE_SCALING_GRID:
michael@0 7879 var symbolUpdate = {
michael@0 7880 isSymbol: true,
michael@0 7881 id: tag.symbolId,
michael@0 7882 updates: {
michael@0 7883 scale9Grid: tag.splitter
michael@0 7884 }
michael@0 7885 };
michael@0 7886 commitData(symbolUpdate);
michael@0 7887 break;
michael@0 7888 case SWF_TAG_CODE_DO_ABC:
michael@0 7889 case SWF_TAG_CODE_DO_ABC_:
michael@0 7890 var abcBlocks = frame.abcBlocks;
michael@0 7891 if (abcBlocks)
michael@0 7892 abcBlocks.push({
michael@0 7893 data: tag.data,
michael@0 7894 flags: tag.flags
michael@0 7895 });
michael@0 7896 else
michael@0 7897 frame.abcBlocks = [
michael@0 7898 {
michael@0 7899 data: tag.data,
michael@0 7900 flags: tag.flags
michael@0 7901 }
michael@0 7902 ];
michael@0 7903 break;
michael@0 7904 case SWF_TAG_CODE_DO_ACTION:
michael@0 7905 var actionBlocks = frame.actionBlocks;
michael@0 7906 if (actionBlocks)
michael@0 7907 actionBlocks.push(tag.actionsData);
michael@0 7908 else
michael@0 7909 frame.actionBlocks = [
michael@0 7910 tag.actionsData
michael@0 7911 ];
michael@0 7912 break;
michael@0 7913 case SWF_TAG_CODE_DO_INIT_ACTION:
michael@0 7914 var initActionBlocks = frame.initActionBlocks || (frame.initActionBlocks = []);
michael@0 7915 initActionBlocks.push({
michael@0 7916 spriteId: tag.spriteId,
michael@0 7917 actionsData: tag.actionsData
michael@0 7918 });
michael@0 7919 break;
michael@0 7920 case SWF_TAG_CODE_START_SOUND:
michael@0 7921 var startSounds = frame.startSounds;
michael@0 7922 if (!startSounds)
michael@0 7923 frame.startSounds = startSounds = [];
michael@0 7924 startSounds.push(tag);
michael@0 7925 break;
michael@0 7926 case SWF_TAG_CODE_SOUND_STREAM_HEAD:
michael@0 7927 try {
michael@0 7928 soundStream = createSoundStream(tag);
michael@0 7929 frame.soundStream = soundStream.info;
michael@0 7930 } catch (e) {
michael@0 7931 }
michael@0 7932 break;
michael@0 7933 case SWF_TAG_CODE_SOUND_STREAM_BLOCK:
michael@0 7934 if (soundStream) {
michael@0 7935 frame.soundStreamBlock = soundStream.decode(tag.data);
michael@0 7936 }
michael@0 7937 break;
michael@0 7938 case SWF_TAG_CODE_EXPORT_ASSETS:
michael@0 7939 var exports = frame.exports;
michael@0 7940 if (exports)
michael@0 7941 frame.exports = exports.concat(tag.exports);
michael@0 7942 else
michael@0 7943 frame.exports = tag.exports.slice(0);
michael@0 7944 break;
michael@0 7945 case SWF_TAG_CODE_SYMBOL_CLASS:
michael@0 7946 var symbolClasses = frame.symbolClasses;
michael@0 7947 if (symbolClasses)
michael@0 7948 frame.symbolClasses = symbolClasses.concat(tag.exports);
michael@0 7949 else
michael@0 7950 frame.symbolClasses = tag.exports.slice(0);
michael@0 7951 break;
michael@0 7952 case SWF_TAG_CODE_FRAME_LABEL:
michael@0 7953 frame.labelName = tag.name;
michael@0 7954 break;
michael@0 7955 case SWF_TAG_CODE_PLACE_OBJECT:
michael@0 7956 case SWF_TAG_CODE_PLACE_OBJECT2:
michael@0 7957 case SWF_TAG_CODE_PLACE_OBJECT3:
michael@0 7958 depths[tag.depth] = tag;
michael@0 7959 break;
michael@0 7960 case SWF_TAG_CODE_REMOVE_OBJECT:
michael@0 7961 case SWF_TAG_CODE_REMOVE_OBJECT2:
michael@0 7962 depths[tag.depth] = null;
michael@0 7963 break;
michael@0 7964 case SWF_TAG_CODE_SET_BACKGROUND_COLOR:
michael@0 7965 frame.bgcolor = tag.color;
michael@0 7966 break;
michael@0 7967 case SWF_TAG_CODE_SHOW_FRAME:
michael@0 7968 frame.repeat = tag.repeat;
michael@0 7969 frame.depths = depths;
michael@0 7970 frame.complete = !(!tag.finalTag);
michael@0 7971 commitData(frame);
michael@0 7972 depths = {};
michael@0 7973 frame = {
michael@0 7974 type: 'frame'
michael@0 7975 };
michael@0 7976 break;
michael@0 7977 }
michael@0 7978 }
michael@0 7979 },
michael@0 7980 oncomplete: function (result) {
michael@0 7981 commitData(result);
michael@0 7982 var stats;
michael@0 7983 if (typeof result.swfVersion === 'number') {
michael@0 7984 var bbox = result.bbox;
michael@0 7985 stats = {
michael@0 7986 topic: 'parseInfo',
michael@0 7987 parseTime: result.parseTime,
michael@0 7988 bytesTotal: result.bytesTotal,
michael@0 7989 swfVersion: result.swfVersion,
michael@0 7990 frameRate: result.frameRate,
michael@0 7991 width: (bbox.xMax - bbox.xMin) / 20,
michael@0 7992 height: (bbox.yMax - bbox.yMin) / 20,
michael@0 7993 isAvm2: !(!result.fileAttributes.doAbc)
michael@0 7994 };
michael@0 7995 }
michael@0 7996 commitData({
michael@0 7997 command: 'complete',
michael@0 7998 stats: stats
michael@0 7999 });
michael@0 8000 },
michael@0 8001 onexception: function (e) {
michael@0 8002 commitData({
michael@0 8003 type: 'exception',
michael@0 8004 message: e.message,
michael@0 8005 stack: e.stack
michael@0 8006 });
michael@0 8007 }
michael@0 8008 };
michael@0 8009 }
michael@0 8010 function parseBytes(bytes, commitData) {
michael@0 8011 SWF.parse(bytes, createParsingContext(commitData));
michael@0 8012 }
michael@0 8013 function ResourceLoader(scope) {
michael@0 8014 this.subscription = null;
michael@0 8015 var self = this;
michael@0 8016 if (!isWorker) {
michael@0 8017 this.messenger = {
michael@0 8018 postMessage: function (data) {
michael@0 8019 self.onmessage({
michael@0 8020 data: data
michael@0 8021 });
michael@0 8022 }
michael@0 8023 };
michael@0 8024 } else {
michael@0 8025 this.messenger = scope;
michael@0 8026 scope.onmessage = function (event) {
michael@0 8027 self.listener(event.data);
michael@0 8028 };
michael@0 8029 }
michael@0 8030 }
michael@0 8031 ResourceLoader.prototype = {
michael@0 8032 terminate: function () {
michael@0 8033 this.messenger = null;
michael@0 8034 this.listener = null;
michael@0 8035 },
michael@0 8036 onmessage: function (event) {
michael@0 8037 this.listener(event.data);
michael@0 8038 },
michael@0 8039 postMessage: function (data) {
michael@0 8040 this.listener && this.listener(data);
michael@0 8041 },
michael@0 8042 listener: function (data) {
michael@0 8043 if (this.subscription) {
michael@0 8044 this.subscription.callback(data.data, data.progress);
michael@0 8045 } else if (data === 'pipe:') {
michael@0 8046 this.subscription = {
michael@0 8047 subscribe: function (callback) {
michael@0 8048 this.callback = callback;
michael@0 8049 }
michael@0 8050 };
michael@0 8051 this.parseLoadedData(this.messenger, this.subscription);
michael@0 8052 } else {
michael@0 8053 this.parseLoadedData(this.messenger, data);
michael@0 8054 }
michael@0 8055 },
michael@0 8056 parseLoadedData: function (loader, request, context) {
michael@0 8057 function commitData(data, transferables) {
michael@0 8058 try {
michael@0 8059 loader.postMessage(data, transferables);
michael@0 8060 } catch (ex) {
michael@0 8061 if (ex != 'DataCloneError') {
michael@0 8062 throw ex;
michael@0 8063 }
michael@0 8064 loader.postMessage(data);
michael@0 8065 }
michael@0 8066 }
michael@0 8067 if (request instanceof ArrayBuffer) {
michael@0 8068 parseBytes(request, commitData);
michael@0 8069 } else if ('subscribe' in request) {
michael@0 8070 var pipe = SWF.parseAsync(createParsingContext(commitData));
michael@0 8071 request.subscribe(function (data, progress) {
michael@0 8072 if (data) {
michael@0 8073 pipe.push(data, progress);
michael@0 8074 } else {
michael@0 8075 pipe.close();
michael@0 8076 }
michael@0 8077 });
michael@0 8078 } else if (typeof FileReaderSync !== 'undefined') {
michael@0 8079 var reader = new FileReaderSync();
michael@0 8080 var buffer = reader.readAsArrayBuffer(request);
michael@0 8081 parseBytes(buffer, commitData);
michael@0 8082 } else {
michael@0 8083 var reader = new FileReader();
michael@0 8084 reader.onload = function () {
michael@0 8085 parseBytes(this.result, commitData);
michael@0 8086 };
michael@0 8087 reader.readAsArrayBuffer(request);
michael@0 8088 }
michael@0 8089 }
michael@0 8090 };
michael@0 8091 if (isWorker) {
michael@0 8092 var loader = new ResourceLoader(this);
michael@0 8093 }
michael@0 8094 function ActionsDataStream(array, swfVersion) {
michael@0 8095 this.array = array;
michael@0 8096 this.position = 0;
michael@0 8097 this.end = array.length;
michael@0 8098 if (swfVersion >= 6) {
michael@0 8099 this.readString = this.readUTF8String;
michael@0 8100 } else {
michael@0 8101 this.readString = this.readANSIString;
michael@0 8102 }
michael@0 8103 var buffer = new ArrayBuffer(4);
michael@0 8104 new Int32Array(buffer)[0] = 1;
michael@0 8105 if (!new Uint8Array(buffer)[0]) {
michael@0 8106 throw new Error('big-endian platform');
michael@0 8107 }
michael@0 8108 }
michael@0 8109 ActionsDataStream.prototype = {
michael@0 8110 readUI8: function ActionsDataStream_readUI8() {
michael@0 8111 return this.array[this.position++];
michael@0 8112 },
michael@0 8113 readUI16: function ActionsDataStream_readUI16() {
michael@0 8114 var position = this.position, array = this.array;
michael@0 8115 var value = array[position + 1] << 8 | array[position];
michael@0 8116 this.position = position + 2;
michael@0 8117 return value;
michael@0 8118 },
michael@0 8119 readSI16: function ActionsDataStream_readSI16() {
michael@0 8120 var position = this.position, array = this.array;
michael@0 8121 var value = array[position + 1] << 8 | array[position];
michael@0 8122 this.position = position + 2;
michael@0 8123 return value < 32768 ? value : value - 65536;
michael@0 8124 },
michael@0 8125 readInteger: function ActionsDataStream_readInteger() {
michael@0 8126 var position = this.position, array = this.array;
michael@0 8127 var value = array[position] | array[position + 1] << 8 | array[position + 2] << 16 | array[position + 3] << 24;
michael@0 8128 this.position = position + 4;
michael@0 8129 return value;
michael@0 8130 },
michael@0 8131 readFloat: function ActionsDataStream_readFloat() {
michael@0 8132 var position = this.position;
michael@0 8133 var array = this.array;
michael@0 8134 var buffer = new ArrayBuffer(4);
michael@0 8135 var bytes = new Uint8Array(buffer);
michael@0 8136 bytes[0] = array[position];
michael@0 8137 bytes[1] = array[position + 1];
michael@0 8138 bytes[2] = array[position + 2];
michael@0 8139 bytes[3] = array[position + 3];
michael@0 8140 this.position = position + 4;
michael@0 8141 return new Float32Array(buffer)[0];
michael@0 8142 },
michael@0 8143 readDouble: function ActionsDataStream_readDouble() {
michael@0 8144 var position = this.position;
michael@0 8145 var array = this.array;
michael@0 8146 var buffer = new ArrayBuffer(8);
michael@0 8147 var bytes = new Uint8Array(buffer);
michael@0 8148 bytes[4] = array[position];
michael@0 8149 bytes[5] = array[position + 1];
michael@0 8150 bytes[6] = array[position + 2];
michael@0 8151 bytes[7] = array[position + 3];
michael@0 8152 bytes[0] = array[position + 4];
michael@0 8153 bytes[1] = array[position + 5];
michael@0 8154 bytes[2] = array[position + 6];
michael@0 8155 bytes[3] = array[position + 7];
michael@0 8156 this.position = position + 8;
michael@0 8157 return new Float64Array(buffer)[0];
michael@0 8158 },
michael@0 8159 readBoolean: function ActionsDataStream_readBoolean() {
michael@0 8160 return !(!this.readUI8());
michael@0 8161 },
michael@0 8162 readANSIString: function ActionsDataStream_readANSIString() {
michael@0 8163 var value = '';
michael@0 8164 var ch;
michael@0 8165 while (ch = this.readUI8()) {
michael@0 8166 value += String.fromCharCode(ch);
michael@0 8167 }
michael@0 8168 return value;
michael@0 8169 },
michael@0 8170 readUTF8String: function ActionsDataStream_readUTF8String() {
michael@0 8171 var value = '';
michael@0 8172 var ch;
michael@0 8173 while (ch = this.readUI8()) {
michael@0 8174 if (ch < 128) {
michael@0 8175 value += String.fromCharCode(ch);
michael@0 8176 continue;
michael@0 8177 }
michael@0 8178 if ((ch & 192) === 128) {
michael@0 8179 throw new Error('Invalid UTF8 encoding');
michael@0 8180 }
michael@0 8181 var currentPrefix = 192;
michael@0 8182 var validBits = 5;
michael@0 8183 do {
michael@0 8184 var mask = currentPrefix >> 1 | 128;
michael@0 8185 if ((ch & mask) === currentPrefix) {
michael@0 8186 break;
michael@0 8187 }
michael@0 8188 currentPrefix = mask;
michael@0 8189 --validBits;
michael@0 8190 } while (validBits >= 0);
michael@0 8191 var code = ch & (1 << validBits) - 1;
michael@0 8192 for (var i = 5; i >= validBits; --i) {
michael@0 8193 ch = this.readUI8();
michael@0 8194 if ((ch & 192) !== 128) {
michael@0 8195 throw new Error('Invalid UTF8 encoding');
michael@0 8196 }
michael@0 8197 code = code << 6 | ch & 63;
michael@0 8198 }
michael@0 8199 if (code >= 65536) {
michael@0 8200 value += String.fromCharCode(code - 65536 >> 10 & 1023 | 55296, code & 1023 | 56320);
michael@0 8201 } else {
michael@0 8202 value += String.fromCharCode(code);
michael@0 8203 }
michael@0 8204 }
michael@0 8205 return value;
michael@0 8206 },
michael@0 8207 readBytes: function ActionsDataStream_readBytes(length) {
michael@0 8208 var position = this.position;
michael@0 8209 var remaining = Math.max(this.end - position, 0);
michael@0 8210 if (remaining < length) {
michael@0 8211 length = remaining;
michael@0 8212 }
michael@0 8213 var subarray = this.array.subarray(position, position + length);
michael@0 8214 this.position = position + length;
michael@0 8215 return subarray;
michael@0 8216 }
michael@0 8217 };
michael@0 8218 if (typeof GLOBAL !== 'undefined') {
michael@0 8219 GLOBAL.ActionsDataStream = ActionsDataStream;
michael@0 8220 }
michael@0 8221 var AVM1_TRACE_ENABLED = false;
michael@0 8222 var AVM1_ERRORS_IGNORED = true;
michael@0 8223 var MAX_AVM1_HANG_TIMEOUT = 1000;
michael@0 8224 var MAX_AVM1_ERRORS_LIMIT = 1000;
michael@0 8225 var MAX_AVM1_STACK_LIMIT = 256;
michael@0 8226 function AS2ScopeListItem(scope, next) {
michael@0 8227 this.scope = scope;
michael@0 8228 this.next = next;
michael@0 8229 }
michael@0 8230 AS2ScopeListItem.prototype = {
michael@0 8231 create: function (scope) {
michael@0 8232 return new AS2ScopeListItem(scope, this);
michael@0 8233 }
michael@0 8234 };
michael@0 8235 function AS2Context(swfVersion) {
michael@0 8236 this.swfVersion = swfVersion;
michael@0 8237 this.globals = new avm1lib.AS2Globals(this);
michael@0 8238 this.initialScope = new AS2ScopeListItem(this.globals, null);
michael@0 8239 this.assets = {};
michael@0 8240 this.isActive = false;
michael@0 8241 this.executionProhibited = false;
michael@0 8242 this.abortExecutionAt = 0;
michael@0 8243 this.stackDepth = 0;
michael@0 8244 this.isTryCatchListening = false;
michael@0 8245 this.errorsIgnored = 0;
michael@0 8246 this.deferScriptExecution = true;
michael@0 8247 this.pendingScripts = [];
michael@0 8248 }
michael@0 8249 AS2Context.instance = null;
michael@0 8250 AS2Context.prototype = {
michael@0 8251 addAsset: function (className, symbolProps) {
michael@0 8252 this.assets[className] = symbolProps;
michael@0 8253 },
michael@0 8254 resolveTarget: function (target) {
michael@0 8255 if (!target) {
michael@0 8256 target = this.defaultTarget;
michael@0 8257 } else if (typeof target === 'string') {
michael@0 8258 target = lookupAS2Children(target, this.defaultTarget, this.globals.asGetPublicProperty('_root'));
michael@0 8259 }
michael@0 8260 if (typeof target !== 'object' || target === null || !('$nativeObject' in target)) {
michael@0 8261 throw new Error('Invalid AS2 target object: ' + Object.prototype.toString.call(target));
michael@0 8262 }
michael@0 8263 return target;
michael@0 8264 },
michael@0 8265 resolveLevel: function (level) {
michael@0 8266 return this.resolveTarget(this.globals['_level' + level]);
michael@0 8267 },
michael@0 8268 addToPendingScripts: function (fn) {
michael@0 8269 if (!this.deferScriptExecution) {
michael@0 8270 return fn();
michael@0 8271 }
michael@0 8272 this.pendingScripts.push(fn);
michael@0 8273 },
michael@0 8274 flushPendingScripts: function () {
michael@0 8275 var scripts = this.pendingScripts;
michael@0 8276 while (scripts.length) {
michael@0 8277 scripts.shift()();
michael@0 8278 }
michael@0 8279 this.deferScriptExecution = false;
michael@0 8280 }
michael@0 8281 };
michael@0 8282 function AS2Error(error) {
michael@0 8283 this.error = error;
michael@0 8284 }
michael@0 8285 function AS2CriticalError(message, error) {
michael@0 8286 this.message = message;
michael@0 8287 this.error = error;
michael@0 8288 }
michael@0 8289 AS2CriticalError.prototype = Object.create(Error.prototype);
michael@0 8290 function isAS2MovieClip(obj) {
michael@0 8291 return typeof obj === 'object' && obj && obj instanceof avm1lib.AS2MovieClip;
michael@0 8292 }
michael@0 8293 function as2GetType(v) {
michael@0 8294 if (v === null) {
michael@0 8295 return 'null';
michael@0 8296 }
michael@0 8297 var type = typeof v;
michael@0 8298 if (type === 'function') {
michael@0 8299 return 'object';
michael@0 8300 }
michael@0 8301 if (type === 'object' && isAS2MovieClip(v)) {
michael@0 8302 return 'movieclip';
michael@0 8303 }
michael@0 8304 return type;
michael@0 8305 }
michael@0 8306 function as2ToPrimitive(value) {
michael@0 8307 return as2GetType(value) !== 'object' ? value : value.valueOf();
michael@0 8308 }
michael@0 8309 function as2ToAddPrimitive(value) {
michael@0 8310 if (as2GetType(value) !== 'object') {
michael@0 8311 return value;
michael@0 8312 }
michael@0 8313 if (value instanceof Date && AS2Context.instance.swfVersion >= 6) {
michael@0 8314 return value.toString();
michael@0 8315 } else {
michael@0 8316 return value.valueOf();
michael@0 8317 }
michael@0 8318 }
michael@0 8319 function as2ToBoolean(value) {
michael@0 8320 switch (as2GetType(value)) {
michael@0 8321 default:
michael@0 8322 case 'undefined':
michael@0 8323 case 'null':
michael@0 8324 return false;
michael@0 8325 case 'boolean':
michael@0 8326 return value;
michael@0 8327 case 'number':
michael@0 8328 return value !== 0 && !isNaN(value);
michael@0 8329 case 'string':
michael@0 8330 return value.length !== 0;
michael@0 8331 case 'movieclip':
michael@0 8332 case 'object':
michael@0 8333 return true;
michael@0 8334 }
michael@0 8335 }
michael@0 8336 function as2ToNumber(value) {
michael@0 8337 value = as2ToPrimitive(value);
michael@0 8338 switch (as2GetType(value)) {
michael@0 8339 case 'undefined':
michael@0 8340 case 'null':
michael@0 8341 return AS2Context.instance.swfVersion >= 7 ? NaN : 0;
michael@0 8342 case 'boolean':
michael@0 8343 return value ? 1 : +0;
michael@0 8344 case 'number':
michael@0 8345 return value;
michael@0 8346 case 'string':
michael@0 8347 if (value === '' && AS2Context.instance.swfVersion < 5) {
michael@0 8348 return 0;
michael@0 8349 }
michael@0 8350 return +value;
michael@0 8351 default:
michael@0 8352 return AS2Context.instance.swfVersion >= 5 ? NaN : 0;
michael@0 8353 }
michael@0 8354 }
michael@0 8355 function as2ToInteger(value) {
michael@0 8356 var result = as2ToNumber(value);
michael@0 8357 if (isNaN(result)) {
michael@0 8358 return 0;
michael@0 8359 }
michael@0 8360 if (!isFinite(result) || result === 0) {
michael@0 8361 return result;
michael@0 8362 }
michael@0 8363 return (result < 0 ? -1 : 1) * Math.abs(result) | 0;
michael@0 8364 }
michael@0 8365 function as2ToInt32(value) {
michael@0 8366 var result = as2ToNumber(value);
michael@0 8367 return isNaN(result) || !isFinite(result) || result === 0 ? 0 : result | 0;
michael@0 8368 }
michael@0 8369 function as2ToString(value) {
michael@0 8370 switch (as2GetType(value)) {
michael@0 8371 case 'undefined':
michael@0 8372 return AS2Context.instance.swfVersion >= 7 ? 'undefined' : '';
michael@0 8373 case 'null':
michael@0 8374 return 'null';
michael@0 8375 case 'boolean':
michael@0 8376 return value ? 'true' : 'false';
michael@0 8377 case 'number':
michael@0 8378 return value.toString();
michael@0 8379 case 'string':
michael@0 8380 return value;
michael@0 8381 case 'movieclip':
michael@0 8382 return value.$targetPath;
michael@0 8383 case 'object':
michael@0 8384 var result = value.toString !== Function.prototype.toString ? value.toString() : value;
michael@0 8385 if (typeof result === 'string') {
michael@0 8386 return result;
michael@0 8387 }
michael@0 8388 return typeof value === 'function' ? '[type Function]' : '[type Object]';
michael@0 8389 }
michael@0 8390 }
michael@0 8391 function as2Compare(x, y) {
michael@0 8392 var x2 = as2ToPrimitive(x);
michael@0 8393 var y2 = as2ToPrimitive(y);
michael@0 8394 if (typeof x2 === 'string' && typeof y2 === 'string') {
michael@0 8395 return x2 < y2;
michael@0 8396 } else {
michael@0 8397 return as2ToNumber(x2) < as2ToNumber(y2);
michael@0 8398 }
michael@0 8399 }
michael@0 8400 function as2InstanceOf(obj, constructor) {
michael@0 8401 if (obj instanceof constructor) {
michael@0 8402 return true;
michael@0 8403 }
michael@0 8404 return false;
michael@0 8405 }
michael@0 8406 function as2ResolveProperty(obj, name) {
michael@0 8407 var avm2PublicName = Multiname.getPublicQualifiedName(name);
michael@0 8408 if (avm2PublicName in obj) {
michael@0 8409 return name;
michael@0 8410 }
michael@0 8411 if (isNumeric(name)) {
michael@0 8412 return null;
michael@0 8413 }
michael@0 8414 var lowerCaseName = avm2PublicName.toLowerCase();
michael@0 8415 for (var i in obj) {
michael@0 8416 if (i.toLowerCase() === lowerCaseName) {
michael@0 8417 notImplemented('FIX THIS');
michael@0 8418 }
michael@0 8419 }
michael@0 8420 return null;
michael@0 8421 }
michael@0 8422 function as2GetPrototype(obj) {
michael@0 8423 return obj && obj.asGetPublicProperty('prototype');
michael@0 8424 }
michael@0 8425 function isAvm2Class(obj) {
michael@0 8426 return typeof obj === 'object' && obj !== null && 'instanceConstructor' in obj;
michael@0 8427 }
michael@0 8428 function as2CreatePrototypeProxy(obj) {
michael@0 8429 var prototype = obj.asGetPublicProperty('prototype');
michael@0 8430 if (typeof Proxy === 'undefined') {
michael@0 8431 console.error('ES6 proxies are not found');
michael@0 8432 return prototype;
michael@0 8433 }
michael@0 8434 return Proxy.create({
michael@0 8435 getOwnPropertyDescriptor: function (name) {
michael@0 8436 return Object.getOwnPropertyDescriptor(prototype, name);
michael@0 8437 },
michael@0 8438 getPropertyDescriptor: function (name) {
michael@0 8439 for (var p = prototype; p; p = Object.getPrototypeOf(p)) {
michael@0 8440 var desc = Object.getOwnPropertyDescriptor(p, name);
michael@0 8441 if (desc)
michael@0 8442 return desc;
michael@0 8443 }
michael@0 8444 },
michael@0 8445 getOwnPropertyNames: function () {
michael@0 8446 return Object.getOwnPropertyNames(prototype);
michael@0 8447 },
michael@0 8448 getPropertyNames: function () {
michael@0 8449 var names = Object.getOwnPropertyNames(prototype);
michael@0 8450 for (var p = Object.getPrototypeOf(prototype); p; p = Object.getPrototypeOf(p)) {
michael@0 8451 names = names.concat(Object.getOwnPropertyNames(p));
michael@0 8452 }
michael@0 8453 return names;
michael@0 8454 },
michael@0 8455 defineProperty: function (name, desc) {
michael@0 8456 if (desc) {
michael@0 8457 if (typeof desc.value === 'function' && desc.value._setClass) {
michael@0 8458 desc.value._setClass(obj);
michael@0 8459 }
michael@0 8460 if (typeof desc.get === 'function' && desc.get._setClass) {
michael@0 8461 desc.get._setClass(obj);
michael@0 8462 }
michael@0 8463 if (typeof desc.set === 'function' && desc.set._setClass) {
michael@0 8464 desc.set._setClass(obj);
michael@0 8465 }
michael@0 8466 }
michael@0 8467 return Object.defineProperty(prototype, name, desc);
michael@0 8468 },
michael@0 8469 delete: function (name) {
michael@0 8470 return delete prototype[name];
michael@0 8471 },
michael@0 8472 fix: function () {
michael@0 8473 return undefined;
michael@0 8474 }
michael@0 8475 });
michael@0 8476 }
michael@0 8477 function executeActions(actionsData, context, scope) {
michael@0 8478 if (context.executionProhibited) {
michael@0 8479 return;
michael@0 8480 }
michael@0 8481 var actionTracer = ActionTracerFactory.get();
michael@0 8482 var scopeContainer = context.initialScope.create(scope);
michael@0 8483 var savedContext = AS2Context.instance;
michael@0 8484 try {
michael@0 8485 AS2Context.instance = context;
michael@0 8486 context.isActive = true;
michael@0 8487 context.abortExecutionAt = Date.now() + MAX_AVM1_HANG_TIMEOUT;
michael@0 8488 context.errorsIgnored = 0;
michael@0 8489 context.defaultTarget = scope;
michael@0 8490 context.globals.asSetPublicProperty('this', scope);
michael@0 8491 actionTracer.message('ActionScript Execution Starts');
michael@0 8492 actionTracer.indent();
michael@0 8493 interpretActions(actionsData, scopeContainer, null, []);
michael@0 8494 } catch (e) {
michael@0 8495 if (e instanceof AS2CriticalError) {
michael@0 8496 console.error('Disabling AVM1 execution');
michael@0 8497 context.executionProhibited = true;
michael@0 8498 }
michael@0 8499 throw e;
michael@0 8500 } finally {
michael@0 8501 context.isActive = false;
michael@0 8502 actionTracer.unindent();
michael@0 8503 actionTracer.message('ActionScript Execution Stops');
michael@0 8504 AS2Context.instance = savedContext;
michael@0 8505 }
michael@0 8506 }
michael@0 8507 function lookupAS2Children(targetPath, defaultTarget, root) {
michael@0 8508 var path = targetPath.split(/[\/.]/g);
michael@0 8509 if (path[path.length - 1] === '') {
michael@0 8510 path.pop();
michael@0 8511 }
michael@0 8512 var obj = defaultTarget;
michael@0 8513 if (path[0] === '' || path[0] === '_level0' || path[0] === '_root') {
michael@0 8514 obj = root;
michael@0 8515 path.shift();
michael@0 8516 }
michael@0 8517 while (path.length > 0) {
michael@0 8518 var prevObj = obj;
michael@0 8519 obj = obj.$lookupChild(path[0]);
michael@0 8520 if (!obj) {
michael@0 8521 throw new Error(path[0] + ' (expr ' + targetPath + ') is not found in ' + prevObj._target);
michael@0 8522 }
michael@0 8523 path.shift();
michael@0 8524 }
michael@0 8525 return obj;
michael@0 8526 }
michael@0 8527 function createBuiltinType(obj, args) {
michael@0 8528 if (obj === Array) {
michael@0 8529 var result = args;
michael@0 8530 if (args.length == 1 && typeof args[0] === 'number') {
michael@0 8531 result = [];
michael@0 8532 result.length = args[0];
michael@0 8533 }
michael@0 8534 return result;
michael@0 8535 }
michael@0 8536 if (obj === Boolean || obj === Number || obj === String || obj === Function) {
michael@0 8537 return obj.apply(null, args);
michael@0 8538 }
michael@0 8539 if (obj === Date) {
michael@0 8540 switch (args.length) {
michael@0 8541 case 0:
michael@0 8542 return new Date();
michael@0 8543 case 1:
michael@0 8544 return new Date(args[0]);
michael@0 8545 default:
michael@0 8546 return new Date(args[0], args[1], args.length > 2 ? args[2] : 1, args.length > 3 ? args[3] : 0, args.length > 4 ? args[4] : 0, args.length > 5 ? args[5] : 0, args.length > 6 ? args[6] : 0);
michael@0 8547 }
michael@0 8548 }
michael@0 8549 if (obj === Object) {
michael@0 8550 return {};
michael@0 8551 }
michael@0 8552 }
michael@0 8553 var AS2_SUPER_STUB = {};
michael@0 8554 function interpretActions(actionsData, scopeContainer, constantPool, registers) {
michael@0 8555 var currentContext = AS2Context.instance;
michael@0 8556 function setTarget(targetPath) {
michael@0 8557 if (!targetPath) {
michael@0 8558 currentContext.defaultTarget = scope;
michael@0 8559 return;
michael@0 8560 }
michael@0 8561 try {
michael@0 8562 currentContext.defaultTarget = lookupAS2Children(targetPath, defaultTarget, _global.asGetPublicProperty('_root'));
michael@0 8563 } catch (e) {
michael@0 8564 currentContext.defaultTarget = null;
michael@0 8565 throw e;
michael@0 8566 }
michael@0 8567 }
michael@0 8568 function defineFunction(functionName, parametersNames, registersAllocation, actionsData) {
michael@0 8569 var ownerClass;
michael@0 8570 var fn = function () {
michael@0 8571 var newScope = {};
michael@0 8572 newScope.asSetPublicProperty('this', this);
michael@0 8573 newScope.asSetPublicProperty('arguments', arguments);
michael@0 8574 newScope.asSetPublicProperty('super', AS2_SUPER_STUB);
michael@0 8575 newScope.asSetPublicProperty('__class', ownerClass);
michael@0 8576 var newScopeContainer = scopeContainer.create(newScope);
michael@0 8577 var i;
michael@0 8578 for (i = 0; i < arguments.length || i < parametersNames.length; i++) {
michael@0 8579 newScope.asSetPublicProperty(parametersNames[i], arguments[i]);
michael@0 8580 }
michael@0 8581 var registers = [];
michael@0 8582 if (registersAllocation) {
michael@0 8583 for (i = 0; i < registersAllocation.length; i++) {
michael@0 8584 var registerAllocation = registersAllocation[i];
michael@0 8585 if (!registerAllocation) {
michael@0 8586 continue;
michael@0 8587 }
michael@0 8588 if (registerAllocation.type == 'param') {
michael@0 8589 registers[i] = arguments[registerAllocation.index];
michael@0 8590 } else {
michael@0 8591 switch (registerAllocation.name) {
michael@0 8592 case 'this':
michael@0 8593 registers[i] = this;
michael@0 8594 break;
michael@0 8595 case 'arguments':
michael@0 8596 registers[i] = arguments;
michael@0 8597 break;
michael@0 8598 case 'super':
michael@0 8599 registers[i] = AS2_SUPER_STUB;
michael@0 8600 break;
michael@0 8601 case '_global':
michael@0 8602 registers[i] = _global;
michael@0 8603 break;
michael@0 8604 case '_parent':
michael@0 8605 registers[i] = scope.asGetPublicProperty('_parent');
michael@0 8606 break;
michael@0 8607 case '_root':
michael@0 8608 registers[i] = _global.asGetPublicProperty('_root');
michael@0 8609 break;
michael@0 8610 }
michael@0 8611 }
michael@0 8612 }
michael@0 8613 }
michael@0 8614 var savedContext = AS2Context.instance;
michael@0 8615 var savedIsActive = currentContext.isActive;
michael@0 8616 try {
michael@0 8617 AS2Context.instance = currentContext;
michael@0 8618 if (!savedIsActive) {
michael@0 8619 currentContext.abortExecutionAt = Date.now() + MAX_AVM1_HANG_TIMEOUT;
michael@0 8620 currentContext.errorsIgnored = 0;
michael@0 8621 currentContext.isActive = true;
michael@0 8622 }
michael@0 8623 currentContext.defaultTarget = scope;
michael@0 8624 actionTracer.indent();
michael@0 8625 currentContext.stackDepth++;
michael@0 8626 if (currentContext.stackDepth >= MAX_AVM1_STACK_LIMIT) {
michael@0 8627 throw new AS2CriticalError('long running script -- AVM1 recursion limit is reached');
michael@0 8628 }
michael@0 8629 return interpretActions(actionsData, newScopeContainer, constantPool, registers);
michael@0 8630 } finally {
michael@0 8631 currentContext.isActive = savedIsActive;
michael@0 8632 currentContext.stackDepth--;
michael@0 8633 actionTracer.unindent();
michael@0 8634 currentContext.defaultTarget = defaultTarget;
michael@0 8635 AS2Context.instance = savedContext;
michael@0 8636 }
michael@0 8637 };
michael@0 8638 ownerClass = fn;
michael@0 8639 fn._setClass = function (class_) {
michael@0 8640 ownerClass = class_;
michael@0 8641 };
michael@0 8642 fn.instanceConstructor = fn;
michael@0 8643 fn.debugName = 'avm1 ' + (functionName || '<function>');
michael@0 8644 if (functionName) {
michael@0 8645 fn.name = functionName;
michael@0 8646 }
michael@0 8647 return fn;
michael@0 8648 }
michael@0 8649 function deleteProperty(propertyName) {
michael@0 8650 for (var p = scopeContainer; p; p = p.next) {
michael@0 8651 if (p.scope.asHasProperty(undefined, propertyName, 0)) {
michael@0 8652 p.scope.asSetPublicProperty(propertyName, undefined);
michael@0 8653 return p.scope.asDeleteProperty(undefined, propertyName, 0);
michael@0 8654 }
michael@0 8655 }
michael@0 8656 return false;
michael@0 8657 }
michael@0 8658 function resolveVariableName(variableName, nonStrict) {
michael@0 8659 var obj, name, i;
michael@0 8660 if (variableName.indexOf(':') >= 0) {
michael@0 8661 var parts = variableName.split(':');
michael@0 8662 obj = lookupAS2Children(parts[0], defaultTarget, _global.asGetPublicProperty('_root'));
michael@0 8663 if (!obj) {
michael@0 8664 throw new Error(parts[0] + ' is undefined');
michael@0 8665 }
michael@0 8666 name = parts[1];
michael@0 8667 } else if (variableName.indexOf('.') >= 0) {
michael@0 8668 var objPath = variableName.split('.');
michael@0 8669 name = objPath.pop();
michael@0 8670 obj = _global;
michael@0 8671 for (i = 0; i < objPath.length; i++) {
michael@0 8672 obj = obj.asGetPublicProperty(objPath[i]) || obj[objPath[i]];
michael@0 8673 if (!obj) {
michael@0 8674 throw new Error(objPath.slice(0, i + 1) + ' is undefined');
michael@0 8675 }
michael@0 8676 }
michael@0 8677 }
michael@0 8678 if (!obj) {
michael@0 8679 return null;
michael@0 8680 }
michael@0 8681 var resolvedName = as2ResolveProperty(obj, name);
michael@0 8682 var resolved = resolvedName !== null;
michael@0 8683 if (resolved || nonStrict) {
michael@0 8684 return {
michael@0 8685 obj: obj,
michael@0 8686 name: resolvedName || name,
michael@0 8687 resolved: resolved
michael@0 8688 };
michael@0 8689 }
michael@0 8690 return null;
michael@0 8691 }
michael@0 8692 function getThis() {
michael@0 8693 var _this = scope.asGetPublicProperty('this');
michael@0 8694 if (_this) {
michael@0 8695 return _this;
michael@0 8696 }
michael@0 8697 for (var p = scopeContainer; p; p = p.next) {
michael@0 8698 resolvedName = as2ResolveProperty(p.scope, 'this');
michael@0 8699 if (resolvedName !== null) {
michael@0 8700 return p.scope.asGetPublicProperty(resolvedName);
michael@0 8701 }
michael@0 8702 }
michael@0 8703 }
michael@0 8704 function getVariable(variableName) {
michael@0 8705 if (scope.asHasProperty(undefined, variableName, 0)) {
michael@0 8706 return scope.asGetPublicProperty(variableName);
michael@0 8707 }
michael@0 8708 var target = resolveVariableName(variableName);
michael@0 8709 if (target) {
michael@0 8710 return target.obj.asGetPublicProperty(target.name);
michael@0 8711 }
michael@0 8712 var resolvedName, _this = getThis();
michael@0 8713 for (var p = scopeContainer; p; p = p.next) {
michael@0 8714 resolvedName = as2ResolveProperty(p.scope, variableName);
michael@0 8715 if (resolvedName !== null) {
michael@0 8716 return p.scope.asGetPublicProperty(resolvedName);
michael@0 8717 }
michael@0 8718 }
michael@0 8719 if (_this && (resolvedName = as2ResolveProperty(_this, variableName))) {
michael@0 8720 return _this.asGetPublicProperty(resolvedName);
michael@0 8721 }
michael@0 8722 var mc = isAS2MovieClip(defaultTarget) && defaultTarget.$lookupChild(variableName);
michael@0 8723 if (mc) {
michael@0 8724 return mc;
michael@0 8725 }
michael@0 8726 }
michael@0 8727 function setVariable(variableName, value) {
michael@0 8728 if (scope.asHasProperty(undefined, variableName, 0)) {
michael@0 8729 scope.asSetPublicProperty(variableName, value);
michael@0 8730 return;
michael@0 8731 }
michael@0 8732 var target = resolveVariableName(variableName, true);
michael@0 8733 if (target) {
michael@0 8734 target.obj.asSetPublicProperty(target.name, value);
michael@0 8735 return;
michael@0 8736 }
michael@0 8737 var resolvedName, _this = getThis();
michael@0 8738 if (_this && (resolvedName = as2ResolveProperty(_this, variableName))) {
michael@0 8739 return _this.asSetPublicProperty(resolvedName, value);
michael@0 8740 }
michael@0 8741 for (var p = scopeContainer; p.next; p = p.next) {
michael@0 8742 resolvedName = as2ResolveProperty(p.scope, variableName);
michael@0 8743 if (resolvedName !== null) {
michael@0 8744 return p.scope.asSetPublicProperty(resolvedName, value);
michael@0 8745 }
michael@0 8746 }
michael@0 8747 (_this || scope).asSetPublicProperty(variableName, value);
michael@0 8748 }
michael@0 8749 function getFunction(functionName) {
michael@0 8750 var fn = getVariable(functionName);
michael@0 8751 if (!(fn instanceof Function)) {
michael@0 8752 throw new Error('Function "' + functionName + '" is not found');
michael@0 8753 }
michael@0 8754 return fn;
michael@0 8755 }
michael@0 8756 function getObjectByName(objectName) {
michael@0 8757 var obj = getVariable(objectName);
michael@0 8758 if (!(obj instanceof Object)) {
michael@0 8759 throw new Error('Object "' + objectName + '" is not found');
michael@0 8760 }
michael@0 8761 return obj;
michael@0 8762 }
michael@0 8763 function processWith(obj, withBlock) {
michael@0 8764 var newScopeContainer = scopeContainer.create(Object(obj));
michael@0 8765 interpretActions(withBlock, newScopeContainer, constantPool, registers);
michael@0 8766 }
michael@0 8767 function processTry(catchIsRegisterFlag, finallyBlockFlag, catchBlockFlag, catchTarget, tryBlock, catchBlock, finallyBlock) {
michael@0 8768 var savedTryCatchState = currentContext.isTryCatchListening;
michael@0 8769 try {
michael@0 8770 currentContext.isTryCatchListening = true;
michael@0 8771 interpretActions(tryBlock, scopeContainer, constantPool, registers);
michael@0 8772 } catch (e) {
michael@0 8773 currentContext.isTryCatchListening = savedTryCatchState;
michael@0 8774 if (!catchBlockFlag) {
michael@0 8775 throw e;
michael@0 8776 }
michael@0 8777 if (!(e instanceof AS2Error)) {
michael@0 8778 throw e;
michael@0 8779 }
michael@0 8780 if (typeof catchTarget === 'string') {
michael@0 8781 scope[catchTarget] = e.error;
michael@0 8782 } else {
michael@0 8783 registers[catchTarget] = e.error;
michael@0 8784 }
michael@0 8785 interpretActions(catchBlock, scopeContainer, constantPool, registers);
michael@0 8786 } finally {
michael@0 8787 currentContext.isTryCatchListening = savedTryCatchState;
michael@0 8788 if (finallyBlockFlag) {
michael@0 8789 interpretActions(finallyBlock, scopeContainer, constantPool, registers);
michael@0 8790 }
michael@0 8791 }
michael@0 8792 }
michael@0 8793 function validateArgsCount(numArgs, maxAmount) {
michael@0 8794 if (isNaN(numArgs) || numArgs < 0 || numArgs > maxAmount || numArgs != (0 | numArgs)) {
michael@0 8795 throw new Error('Invalid number of arguments: ' + numArgs);
michael@0 8796 }
michael@0 8797 }
michael@0 8798 function readArgs(stack) {
michael@0 8799 var numArgs = +stack.pop();
michael@0 8800 validateArgsCount(numArgs, stack.length);
michael@0 8801 var args = [];
michael@0 8802 for (var i = 0; i < numArgs; i++) {
michael@0 8803 args.push(stack.pop());
michael@0 8804 }
michael@0 8805 return args;
michael@0 8806 }
michael@0 8807 var stream = new ActionsDataStream(actionsData, currentContext.swfVersion);
michael@0 8808 var _global = currentContext.globals;
michael@0 8809 var defaultTarget = currentContext.defaultTarget;
michael@0 8810 var stack = [];
michael@0 8811 var scope = scopeContainer.scope;
michael@0 8812 var isSwfVersion5 = currentContext.swfVersion >= 5;
michael@0 8813 var actionTracer = ActionTracerFactory.get();
michael@0 8814 var nextPosition;
michael@0 8815 if (scope.$nativeObject && scope.$nativeObject._deferScriptExecution) {
michael@0 8816 currentContext.deferScriptExecution = true;
michael@0 8817 }
michael@0 8818 function skipActions(count) {
michael@0 8819 while (count > 0 && stream.position < stream.end) {
michael@0 8820 var actionCode = stream.readUI8();
michael@0 8821 var length = actionCode >= 128 ? stream.readUI16() : 0;
michael@0 8822 stream.position += length;
michael@0 8823 count--;
michael@0 8824 }
michael@0 8825 nextPosition = stream.position;
michael@0 8826 }
michael@0 8827 var recoveringFromError = false;
michael@0 8828 var stackItemsExpected;
michael@0 8829 while (stream.position < stream.end) {
michael@0 8830 try {
michael@0 8831 var instructionsExecuted = 0;
michael@0 8832 var abortExecutionAt = currentContext.abortExecutionAt;
michael@0 8833 while (stream.position < stream.end) {
michael@0 8834 if (instructionsExecuted++ % 100 === 0 && Date.now() >= abortExecutionAt) {
michael@0 8835 throw new AS2CriticalError('long running script -- AVM1 instruction hang timeout');
michael@0 8836 }
michael@0 8837 var actionCode = stream.readUI8();
michael@0 8838 var length = actionCode >= 128 ? stream.readUI16() : 0;
michael@0 8839 nextPosition = stream.position + length;
michael@0 8840 stackItemsExpected = 0;
michael@0 8841 actionTracer.print(stream.position, actionCode, stack);
michael@0 8842 var frame, type, count, index, target, method, constr, codeSize, offset;
michael@0 8843 var name, variableName, methodName, functionName, targetName;
michael@0 8844 var paramName, resolvedName, objectName;
michael@0 8845 var value, a, b, c, f, sa, sb, obj, args, fn, result, flags, i;
michael@0 8846 var dragParams, register;
michael@0 8847 switch (actionCode | 0) {
michael@0 8848 case 129:
michael@0 8849 frame = stream.readUI16();
michael@0 8850 var nextActionCode = stream.readUI8();
michael@0 8851 nextPosition++;
michael@0 8852 methodName = nextActionCode === 6 ? 'gotoAndPlay' : 'gotoAndStop';
michael@0 8853 _global[methodName](frame + 1);
michael@0 8854 break;
michael@0 8855 case 131:
michael@0 8856 var urlString = stream.readString();
michael@0 8857 var targetString = stream.readString();
michael@0 8858 _global.getURL(urlString, targetString);
michael@0 8859 break;
michael@0 8860 case 4:
michael@0 8861 _global.nextFrame();
michael@0 8862 break;
michael@0 8863 case 5:
michael@0 8864 _global.prevFrame();
michael@0 8865 break;
michael@0 8866 case 6:
michael@0 8867 _global.play();
michael@0 8868 break;
michael@0 8869 case 7:
michael@0 8870 _global.stop();
michael@0 8871 break;
michael@0 8872 case 8:
michael@0 8873 _global.toggleHighQuality();
michael@0 8874 break;
michael@0 8875 case 9:
michael@0 8876 _global.stopAllSounds();
michael@0 8877 break;
michael@0 8878 case 138:
michael@0 8879 frame = stream.readUI16();
michael@0 8880 count = stream.readUI8();
michael@0 8881 if (!_global.ifFrameLoaded(frame)) {
michael@0 8882 skipActions(count);
michael@0 8883 }
michael@0 8884 break;
michael@0 8885 case 139:
michael@0 8886 targetName = stream.readString();
michael@0 8887 setTarget(targetName);
michael@0 8888 break;
michael@0 8889 case 140:
michael@0 8890 var label = stream.readString();
michael@0 8891 _global.gotoLabel(label);
michael@0 8892 break;
michael@0 8893 case 150:
michael@0 8894 while (stream.position < nextPosition) {
michael@0 8895 type = stream.readUI8();
michael@0 8896 switch (type) {
michael@0 8897 case 0:
michael@0 8898 value = stream.readString();
michael@0 8899 break;
michael@0 8900 case 1:
michael@0 8901 value = stream.readFloat();
michael@0 8902 break;
michael@0 8903 case 2:
michael@0 8904 value = null;
michael@0 8905 break;
michael@0 8906 case 3:
michael@0 8907 value = void 0;
michael@0 8908 break;
michael@0 8909 case 4:
michael@0 8910 value = registers[stream.readUI8()];
michael@0 8911 break;
michael@0 8912 case 5:
michael@0 8913 value = stream.readBoolean();
michael@0 8914 break;
michael@0 8915 case 6:
michael@0 8916 value = stream.readDouble();
michael@0 8917 break;
michael@0 8918 case 7:
michael@0 8919 value = stream.readInteger();
michael@0 8920 break;
michael@0 8921 case 8:
michael@0 8922 value = constantPool[stream.readUI8()];
michael@0 8923 break;
michael@0 8924 case 9:
michael@0 8925 value = constantPool[stream.readUI16()];
michael@0 8926 break;
michael@0 8927 default:
michael@0 8928 throw new Error('Unknown value type: ' + type);
michael@0 8929 }
michael@0 8930 stack.push(value);
michael@0 8931 }
michael@0 8932 break;
michael@0 8933 case 23:
michael@0 8934 stack.pop();
michael@0 8935 break;
michael@0 8936 case 10:
michael@0 8937 a = as2ToNumber(stack.pop());
michael@0 8938 b = as2ToNumber(stack.pop());
michael@0 8939 stack.push(a + b);
michael@0 8940 break;
michael@0 8941 case 11:
michael@0 8942 a = as2ToNumber(stack.pop());
michael@0 8943 b = as2ToNumber(stack.pop());
michael@0 8944 stack.push(b - a);
michael@0 8945 break;
michael@0 8946 case 12:
michael@0 8947 a = as2ToNumber(stack.pop());
michael@0 8948 b = as2ToNumber(stack.pop());
michael@0 8949 stack.push(a * b);
michael@0 8950 break;
michael@0 8951 case 13:
michael@0 8952 a = as2ToNumber(stack.pop());
michael@0 8953 b = as2ToNumber(stack.pop());
michael@0 8954 c = b / a;
michael@0 8955 stack.push(isSwfVersion5 ? c : isFinite(c) ? c : '#ERROR#');
michael@0 8956 break;
michael@0 8957 case 14:
michael@0 8958 a = as2ToNumber(stack.pop());
michael@0 8959 b = as2ToNumber(stack.pop());
michael@0 8960 f = a == b;
michael@0 8961 stack.push(isSwfVersion5 ? f : f ? 1 : 0);
michael@0 8962 break;
michael@0 8963 case 15:
michael@0 8964 a = as2ToNumber(stack.pop());
michael@0 8965 b = as2ToNumber(stack.pop());
michael@0 8966 f = b < a;
michael@0 8967 stack.push(isSwfVersion5 ? f : f ? 1 : 0);
michael@0 8968 break;
michael@0 8969 case 16:
michael@0 8970 a = as2ToBoolean(stack.pop());
michael@0 8971 b = as2ToBoolean(stack.pop());
michael@0 8972 f = a && b;
michael@0 8973 stack.push(isSwfVersion5 ? f : f ? 1 : 0);
michael@0 8974 break;
michael@0 8975 case 17:
michael@0 8976 a = as2ToBoolean(stack.pop());
michael@0 8977 b = as2ToBoolean(stack.pop());
michael@0 8978 f = a || b;
michael@0 8979 stack.push(isSwfVersion5 ? f : f ? 1 : 0);
michael@0 8980 break;
michael@0 8981 case 18:
michael@0 8982 f = !as2ToBoolean(stack.pop());
michael@0 8983 stack.push(isSwfVersion5 ? f : f ? 1 : 0);
michael@0 8984 break;
michael@0 8985 case 19:
michael@0 8986 sa = as2ToString(stack.pop());
michael@0 8987 sb = as2ToString(stack.pop());
michael@0 8988 f = sa == sb;
michael@0 8989 stack.push(isSwfVersion5 ? f : f ? 1 : 0);
michael@0 8990 break;
michael@0 8991 case 20:
michael@0 8992 case 49:
michael@0 8993 sa = as2ToString(stack.pop());
michael@0 8994 stack.push(_global.length(sa));
michael@0 8995 break;
michael@0 8996 case 33:
michael@0 8997 sa = as2ToString(stack.pop());
michael@0 8998 sb = as2ToString(stack.pop());
michael@0 8999 stack.push(sb + sa);
michael@0 9000 break;
michael@0 9001 case 21:
michael@0 9002 count = stack.pop();
michael@0 9003 index = stack.pop();
michael@0 9004 value = as2ToString(stack.pop());
michael@0 9005 stack.push(_global.substring(value, index, count));
michael@0 9006 break;
michael@0 9007 case 53:
michael@0 9008 count = stack.pop();
michael@0 9009 index = stack.pop();
michael@0 9010 value = as2ToString(stack.pop());
michael@0 9011 stack.push(_global.mbsubstring(value, index, count));
michael@0 9012 break;
michael@0 9013 case 41:
michael@0 9014 sa = as2ToString(stack.pop());
michael@0 9015 sb = as2ToString(stack.pop());
michael@0 9016 f = sb < sa;
michael@0 9017 stack.push(isSwfVersion5 ? f : f ? 1 : 0);
michael@0 9018 break;
michael@0 9019 case 24:
michael@0 9020 stack.push(_global.int(stack.pop()));
michael@0 9021 break;
michael@0 9022 case 50:
michael@0 9023 stack.push(_global.chr(stack.pop()));
michael@0 9024 break;
michael@0 9025 case 54:
michael@0 9026 stack.push(_global.mbchr(stack.pop()));
michael@0 9027 break;
michael@0 9028 case 51:
michael@0 9029 stack.push(_global.ord(stack.pop()));
michael@0 9030 break;
michael@0 9031 case 55:
michael@0 9032 stack.push(_global.mbord(stack.pop()));
michael@0 9033 break;
michael@0 9034 case 153:
michael@0 9035 offset = stream.readSI16();
michael@0 9036 nextPosition += offset;
michael@0 9037 break;
michael@0 9038 case 157:
michael@0 9039 offset = stream.readSI16();
michael@0 9040 f = !(!stack.pop());
michael@0 9041 if (f) {
michael@0 9042 nextPosition += offset;
michael@0 9043 }
michael@0 9044 break;
michael@0 9045 case 158:
michael@0 9046 label = stack.pop();
michael@0 9047 _global.call(label);
michael@0 9048 break;
michael@0 9049 case 28:
michael@0 9050 variableName = '' + stack.pop();
michael@0 9051 stackItemsExpected++;
michael@0 9052 stack.push(getVariable(variableName));
michael@0 9053 break;
michael@0 9054 case 29:
michael@0 9055 value = stack.pop();
michael@0 9056 variableName = '' + stack.pop();
michael@0 9057 setVariable(variableName, value);
michael@0 9058 break;
michael@0 9059 case 154:
michael@0 9060 flags = stream.readUI8();
michael@0 9061 target = stack.pop();
michael@0 9062 var url = stack.pop();
michael@0 9063 var sendVarsMethod;
michael@0 9064 if (flags & 1) {
michael@0 9065 sendVarsMethod = 'GET';
michael@0 9066 } else if (flags & 2) {
michael@0 9067 sendVarsMethod = 'POST';
michael@0 9068 }
michael@0 9069 var loadTargetFlag = flags & 1 << 6;
michael@0 9070 if (!loadTargetFlag) {
michael@0 9071 _global.getURL(url, target, sendVarsMethod);
michael@0 9072 break;
michael@0 9073 }
michael@0 9074 var loadVariablesFlag = flags & 1 << 7;
michael@0 9075 if (loadVariablesFlag) {
michael@0 9076 _global.loadVariables(url, target, sendVarsMethod);
michael@0 9077 } else {
michael@0 9078 _global.loadMovie(url, target, sendVarsMethod);
michael@0 9079 }
michael@0 9080 break;
michael@0 9081 case 159:
michael@0 9082 flags = stream.readUI8();
michael@0 9083 var gotoParams = [
michael@0 9084 stack.pop()
michael@0 9085 ];
michael@0 9086 if (!(!(flags & 2))) {
michael@0 9087 gotoParams.push(stream.readUI16());
michael@0 9088 }
michael@0 9089 var gotoMethod = !(!(flags & 1)) ? _global.gotoAndPlay : _global.gotoAndStop;
michael@0 9090 gotoMethod.apply(_global, gotoParams);
michael@0 9091 break;
michael@0 9092 case 32:
michael@0 9093 target = stack.pop();
michael@0 9094 setTarget(target);
michael@0 9095 break;
michael@0 9096 case 34:
michael@0 9097 index = stack.pop();
michael@0 9098 target = stack.pop();
michael@0 9099 stackItemsExpected++;
michael@0 9100 stack.push(_global.getAS2Property(target, index));
michael@0 9101 break;
michael@0 9102 case 35:
michael@0 9103 value = stack.pop();
michael@0 9104 index = stack.pop();
michael@0 9105 target = stack.pop();
michael@0 9106 _global.setAS2Property(target, index, value);
michael@0 9107 break;
michael@0 9108 case 36:
michael@0 9109 var depth = stack.pop();
michael@0 9110 target = stack.pop();
michael@0 9111 var source = stack.pop();
michael@0 9112 _global.duplicateMovieClip(source, target, depth);
michael@0 9113 break;
michael@0 9114 case 37:
michael@0 9115 target = stack.pop();
michael@0 9116 _global.removeMovieClip(target);
michael@0 9117 break;
michael@0 9118 case 39:
michael@0 9119 target = stack.pop();
michael@0 9120 var lockcenter = stack.pop();
michael@0 9121 var constrain = !stack.pop() ? null : {
michael@0 9122 y2: stack.pop(),
michael@0 9123 x2: stack.pop(),
michael@0 9124 y1: stack.pop(),
michael@0 9125 x1: stack.pop()
michael@0 9126 };
michael@0 9127 dragParams = [
michael@0 9128 target,
michael@0 9129 lockcenter
michael@0 9130 ];
michael@0 9131 if (constrain) {
michael@0 9132 dragParams = dragParams.push(constrain.x1, constrain.y1, constrain.x2, constrain.y2);
michael@0 9133 }
michael@0 9134 _global.startDrag.apply(_global, dragParams);
michael@0 9135 break;
michael@0 9136 case 40:
michael@0 9137 _global.stopDrag();
michael@0 9138 break;
michael@0 9139 case 141:
michael@0 9140 count = stream.readUI8();
michael@0 9141 frame = stack.pop();
michael@0 9142 if (!_global.ifFrameLoaded(frame)) {
michael@0 9143 skipActions(count);
michael@0 9144 }
michael@0 9145 break;
michael@0 9146 case 38:
michael@0 9147 value = stack.pop();
michael@0 9148 _global.trace(value);
michael@0 9149 break;
michael@0 9150 case 52:
michael@0 9151 stack.push(_global.getTimer());
michael@0 9152 break;
michael@0 9153 case 48:
michael@0 9154 stack.push(_global.random(stack.pop()));
michael@0 9155 break;
michael@0 9156 case 61:
michael@0 9157 functionName = stack.pop();
michael@0 9158 args = readArgs(stack);
michael@0 9159 stackItemsExpected++;
michael@0 9160 fn = getFunction(functionName);
michael@0 9161 result = fn.apply(scope, args);
michael@0 9162 stack.push(result);
michael@0 9163 break;
michael@0 9164 case 82:
michael@0 9165 methodName = stack.pop();
michael@0 9166 obj = stack.pop();
michael@0 9167 args = readArgs(stack);
michael@0 9168 stackItemsExpected++;
michael@0 9169 if (methodName !== null && methodName !== undefined && methodName !== '') {
michael@0 9170 if (obj === null || obj === undefined) {
michael@0 9171 throw new Error('Cannot call method ' + methodName + ' of ' + typeof obj);
michael@0 9172 } else if (obj !== AS2_SUPER_STUB) {
michael@0 9173 target = Object(obj);
michael@0 9174 } else {
michael@0 9175 target = as2GetPrototype(getVariable('__class').__super);
michael@0 9176 obj = getVariable('this');
michael@0 9177 }
michael@0 9178 resolvedName = as2ResolveProperty(target, methodName);
michael@0 9179 if (resolvedName === null) {
michael@0 9180 throw new Error('Method ' + methodName + ' is not defined.');
michael@0 9181 }
michael@0 9182 result = target.asGetPublicProperty(resolvedName).apply(obj, args);
michael@0 9183 } else if (obj !== AS2_SUPER_STUB) {
michael@0 9184 result = obj.apply(obj, args);
michael@0 9185 } else {
michael@0 9186 result = getVariable('__class').__super.apply(getVariable('this'), args);
michael@0 9187 }
michael@0 9188 stack.push(result);
michael@0 9189 break;
michael@0 9190 case 136:
michael@0 9191 count = stream.readUI16();
michael@0 9192 constantPool = [];
michael@0 9193 for (i = 0; i < count; i++) {
michael@0 9194 constantPool.push(stream.readString());
michael@0 9195 }
michael@0 9196 break;
michael@0 9197 case 155:
michael@0 9198 functionName = stream.readString();
michael@0 9199 count = stream.readUI16();
michael@0 9200 args = [];
michael@0 9201 for (i = 0; i < count; i++) {
michael@0 9202 args.push(stream.readString());
michael@0 9203 }
michael@0 9204 codeSize = stream.readUI16();
michael@0 9205 nextPosition += codeSize;
michael@0 9206 fn = defineFunction(functionName, args, null, stream.readBytes(codeSize));
michael@0 9207 if (functionName) {
michael@0 9208 scope.asSetPublicProperty(functionName, fn);
michael@0 9209 } else {
michael@0 9210 stack.push(fn);
michael@0 9211 }
michael@0 9212 break;
michael@0 9213 case 60:
michael@0 9214 value = stack.pop();
michael@0 9215 name = stack.pop();
michael@0 9216 scope.asSetPublicProperty(name, value);
michael@0 9217 break;
michael@0 9218 case 65:
michael@0 9219 name = stack.pop();
michael@0 9220 scope.asSetPublicProperty(name, undefined);
michael@0 9221 break;
michael@0 9222 case 58:
michael@0 9223 name = stack.pop();
michael@0 9224 obj = stack.pop();
michael@0 9225 obj.asSetPublicProperty(name, undefined);
michael@0 9226 stack.push(obj.asDeleteProperty(undefined, name, 0));
michael@0 9227 break;
michael@0 9228 case 59:
michael@0 9229 name = stack.pop();
michael@0 9230 result = deleteProperty(name);
michael@0 9231 stack.push(result);
michael@0 9232 break;
michael@0 9233 case 70:
michael@0 9234 objectName = stack.pop();
michael@0 9235 stack.push(null);
michael@0 9236 obj = getObjectByName(objectName);
michael@0 9237 forEachPublicProperty(obj, function (name) {
michael@0 9238 stack.push(name);
michael@0 9239 });
michael@0 9240 break;
michael@0 9241 case 73:
michael@0 9242 a = stack.pop();
michael@0 9243 b = stack.pop();
michael@0 9244 stack.push(a == b);
michael@0 9245 break;
michael@0 9246 case 78:
michael@0 9247 name = stack.pop();
michael@0 9248 obj = stack.pop();
michael@0 9249 if (name === 'prototype') {
michael@0 9250 stack.push(as2CreatePrototypeProxy(obj));
michael@0 9251 } else {
michael@0 9252 resolvedName = as2ResolveProperty(Object(obj), name);
michael@0 9253 stack.push(resolvedName === null ? undefined : obj.asGetPublicProperty(resolvedName));
michael@0 9254 }
michael@0 9255 break;
michael@0 9256 case 66:
michael@0 9257 obj = readArgs(stack);
michael@0 9258 stack.push(obj);
michael@0 9259 break;
michael@0 9260 case 67:
michael@0 9261 count = +stack.pop();
michael@0 9262 validateArgsCount(count, stack.length >> 1);
michael@0 9263 obj = {};
michael@0 9264 for (i = 0; i < count; i++) {
michael@0 9265 value = stack.pop();
michael@0 9266 name = stack.pop();
michael@0 9267 obj.asSetPublicProperty(name, value);
michael@0 9268 }
michael@0 9269 stack.push(obj);
michael@0 9270 break;
michael@0 9271 case 83:
michael@0 9272 methodName = stack.pop();
michael@0 9273 obj = stack.pop();
michael@0 9274 args = readArgs(stack);
michael@0 9275 stackItemsExpected++;
michael@0 9276 if (methodName !== null && methodName !== undefined && methodName !== '') {
michael@0 9277 resolvedName = as2ResolveProperty(obj, methodName);
michael@0 9278 if (resolvedName === null) {
michael@0 9279 throw new Error('Method ' + methodName + ' is not defined.');
michael@0 9280 }
michael@0 9281 if (obj === null || obj === undefined) {
michael@0 9282 throw new Error('Cannot call new using method ' + resolvedName + ' of ' + typeof obj);
michael@0 9283 }
michael@0 9284 method = obj.asGetPublicProperty(resolvedName);
michael@0 9285 } else {
michael@0 9286 if (obj === null || obj === undefined) {
michael@0 9287 throw new Error('Cannot call new using ' + typeof obj);
michael@0 9288 }
michael@0 9289 method = obj;
michael@0 9290 }
michael@0 9291 if (isAvm2Class(obj)) {
michael@0 9292 result = construct(obj, args);
michael@0 9293 } else {
michael@0 9294 result = Object.create(as2GetPrototype(method) || as2GetPrototype(Object));
michael@0 9295 method.apply(result, args);
michael@0 9296 }
michael@0 9297 result.constructor = method;
michael@0 9298 stack.push(result);
michael@0 9299 break;
michael@0 9300 case 64:
michael@0 9301 objectName = stack.pop();
michael@0 9302 obj = getObjectByName(objectName);
michael@0 9303 args = readArgs(stack);
michael@0 9304 stackItemsExpected++;
michael@0 9305 result = createBuiltinType(obj, args);
michael@0 9306 if (typeof result === 'undefined') {
michael@0 9307 if (isAvm2Class(obj)) {
michael@0 9308 result = construct(obj, args);
michael@0 9309 } else {
michael@0 9310 result = Object.create(as2GetPrototype(obj) || as2GetPrototype(Object));
michael@0 9311 obj.apply(result, args);
michael@0 9312 }
michael@0 9313 result.constructor = obj;
michael@0 9314 }
michael@0 9315 stack.push(result);
michael@0 9316 break;
michael@0 9317 case 79:
michael@0 9318 value = stack.pop();
michael@0 9319 name = stack.pop();
michael@0 9320 obj = stack.pop();
michael@0 9321 obj.asSetPublicProperty(name, value);
michael@0 9322 break;
michael@0 9323 case 69:
michael@0 9324 obj = stack.pop();
michael@0 9325 stack.push(as2GetType(obj) === 'movieclip' ? obj._target : void 0);
michael@0 9326 break;
michael@0 9327 case 148:
michael@0 9328 codeSize = stream.readUI16();
michael@0 9329 obj = stack.pop();
michael@0 9330 nextPosition += codeSize;
michael@0 9331 processWith(obj, stream.readBytes(codeSize));
michael@0 9332 break;
michael@0 9333 case 74:
michael@0 9334 stack.push(as2ToNumber(stack.pop()));
michael@0 9335 break;
michael@0 9336 case 75:
michael@0 9337 stack.push(as2ToString(stack.pop()));
michael@0 9338 break;
michael@0 9339 case 68:
michael@0 9340 obj = stack.pop();
michael@0 9341 result = as2GetType(obj);
michael@0 9342 stack.push(result);
michael@0 9343 break;
michael@0 9344 case 71:
michael@0 9345 a = as2ToAddPrimitive(stack.pop());
michael@0 9346 b = as2ToAddPrimitive(stack.pop());
michael@0 9347 if (typeof a === 'string' || typeof b === 'string') {
michael@0 9348 stack.push(as2ToString(b) + as2ToString(a));
michael@0 9349 } else {
michael@0 9350 stack.push(as2ToNumber(b) + as2ToNumber(a));
michael@0 9351 }
michael@0 9352 break;
michael@0 9353 case 72:
michael@0 9354 a = stack.pop();
michael@0 9355 b = stack.pop();
michael@0 9356 stack.push(as2Compare(b, a));
michael@0 9357 break;
michael@0 9358 case 63:
michael@0 9359 a = as2ToNumber(stack.pop());
michael@0 9360 b = as2ToNumber(stack.pop());
michael@0 9361 stack.push(b % a);
michael@0 9362 break;
michael@0 9363 case 96:
michael@0 9364 a = as2ToInt32(stack.pop());
michael@0 9365 b = as2ToInt32(stack.pop());
michael@0 9366 stack.push(b & a);
michael@0 9367 break;
michael@0 9368 case 99:
michael@0 9369 a = as2ToInt32(stack.pop());
michael@0 9370 b = as2ToInt32(stack.pop());
michael@0 9371 stack.push(b << a);
michael@0 9372 break;
michael@0 9373 case 97:
michael@0 9374 a = as2ToInt32(stack.pop());
michael@0 9375 b = as2ToInt32(stack.pop());
michael@0 9376 stack.push(b | a);
michael@0 9377 break;
michael@0 9378 case 100:
michael@0 9379 a = as2ToInt32(stack.pop());
michael@0 9380 b = as2ToInt32(stack.pop());
michael@0 9381 stack.push(b >> a);
michael@0 9382 break;
michael@0 9383 case 101:
michael@0 9384 a = as2ToInt32(stack.pop());
michael@0 9385 b = as2ToInt32(stack.pop());
michael@0 9386 stack.push(b >>> a);
michael@0 9387 break;
michael@0 9388 case 98:
michael@0 9389 a = as2ToInt32(stack.pop());
michael@0 9390 b = as2ToInt32(stack.pop());
michael@0 9391 stack.push(b ^ a);
michael@0 9392 break;
michael@0 9393 case 81:
michael@0 9394 a = as2ToNumber(stack.pop());
michael@0 9395 a--;
michael@0 9396 stack.push(a);
michael@0 9397 break;
michael@0 9398 case 80:
michael@0 9399 a = as2ToNumber(stack.pop());
michael@0 9400 a++;
michael@0 9401 stack.push(a);
michael@0 9402 break;
michael@0 9403 case 76:
michael@0 9404 stack.push(stack[stack.length - 1]);
michael@0 9405 break;
michael@0 9406 case 62:
michael@0 9407 return stack.pop();
michael@0 9408 case 77:
michael@0 9409 stack.push(stack.pop(), stack.pop());
michael@0 9410 break;
michael@0 9411 case 135:
michael@0 9412 register = stream.readUI8();
michael@0 9413 registers[register] = stack[stack.length - 1];
michael@0 9414 break;
michael@0 9415 case 84:
michael@0 9416 constr = stack.pop();
michael@0 9417 obj = stack.pop();
michael@0 9418 stack.push(as2InstanceOf(Object(obj), constr));
michael@0 9419 break;
michael@0 9420 case 85:
michael@0 9421 obj = stack.pop();
michael@0 9422 stack.push(null);
michael@0 9423 forEachPublicProperty(obj, function (name) {
michael@0 9424 stack.push(name);
michael@0 9425 });
michael@0 9426 break;
michael@0 9427 case 102:
michael@0 9428 a = stack.pop();
michael@0 9429 b = stack.pop();
michael@0 9430 stack.push(b === a);
michael@0 9431 break;
michael@0 9432 case 103:
michael@0 9433 a = stack.pop();
michael@0 9434 b = stack.pop();
michael@0 9435 stack.push(as2Compare(a, b));
michael@0 9436 break;
michael@0 9437 case 104:
michael@0 9438 sa = as2ToString(stack.pop());
michael@0 9439 sb = as2ToString(stack.pop());
michael@0 9440 f = sb > sa;
michael@0 9441 stack.push(isSwfVersion5 ? f : f ? 1 : 0);
michael@0 9442 break;
michael@0 9443 case 142:
michael@0 9444 functionName = stream.readString();
michael@0 9445 count = stream.readUI16();
michael@0 9446 var registerCount = stream.readUI8();
michael@0 9447 flags = stream.readUI16();
michael@0 9448 var registerAllocation = [];
michael@0 9449 args = [];
michael@0 9450 for (i = 0; i < count; i++) {
michael@0 9451 register = stream.readUI8();
michael@0 9452 paramName = stream.readString();
michael@0 9453 args.push(paramName);
michael@0 9454 if (register) {
michael@0 9455 registerAllocation[register] = {
michael@0 9456 type: 'param',
michael@0 9457 name: paramName,
michael@0 9458 index: i
michael@0 9459 };
michael@0 9460 }
michael@0 9461 }
michael@0 9462 codeSize = stream.readUI16();
michael@0 9463 nextPosition += codeSize;
michael@0 9464 var j = 1;
michael@0 9465 if (flags & 1) {
michael@0 9466 registerAllocation[j++] = {
michael@0 9467 type: 'var',
michael@0 9468 name: 'this'
michael@0 9469 };
michael@0 9470 }
michael@0 9471 if (flags & 4) {
michael@0 9472 registerAllocation[j++] = {
michael@0 9473 type: 'var',
michael@0 9474 name: 'arguments'
michael@0 9475 };
michael@0 9476 }
michael@0 9477 if (flags & 16) {
michael@0 9478 registerAllocation[j++] = {
michael@0 9479 type: 'var',
michael@0 9480 name: 'super'
michael@0 9481 };
michael@0 9482 }
michael@0 9483 if (flags & 64) {
michael@0 9484 registerAllocation[j++] = {
michael@0 9485 type: 'var',
michael@0 9486 name: '_root'
michael@0 9487 };
michael@0 9488 }
michael@0 9489 if (flags & 128) {
michael@0 9490 registerAllocation[j++] = {
michael@0 9491 type: 'var',
michael@0 9492 name: '_parent'
michael@0 9493 };
michael@0 9494 }
michael@0 9495 if (flags & 256) {
michael@0 9496 registerAllocation[j++] = {
michael@0 9497 type: 'var',
michael@0 9498 name: '_global'
michael@0 9499 };
michael@0 9500 }
michael@0 9501 fn = defineFunction(functionName, args, registerAllocation, stream.readBytes(codeSize));
michael@0 9502 if (functionName) {
michael@0 9503 scope.asSetPublicProperty(functionName, fn);
michael@0 9504 } else {
michael@0 9505 stack.push(fn);
michael@0 9506 }
michael@0 9507 break;
michael@0 9508 case 105:
michael@0 9509 var constrSuper = stack.pop();
michael@0 9510 constr = stack.pop();
michael@0 9511 obj = Object.create(constrSuper.traitsPrototype || as2GetPrototype(constrSuper), {
michael@0 9512 constructor: {
michael@0 9513 value: constr,
michael@0 9514 enumerable: false
michael@0 9515 }
michael@0 9516 });
michael@0 9517 constr.__super = constrSuper;
michael@0 9518 constr.prototype = obj;
michael@0 9519 break;
michael@0 9520 case 43:
michael@0 9521 obj = stack.pop();
michael@0 9522 constr = stack.pop();
michael@0 9523 stack.push(as2InstanceOf(obj, constr) ? obj : null);
michael@0 9524 break;
michael@0 9525 case 44:
michael@0 9526 constr = stack.pop();
michael@0 9527 count = +stack.pop();
michael@0 9528 validateArgsCount(count, stack.length);
michael@0 9529 var interfaces = [];
michael@0 9530 for (i = 0; i < count; i++) {
michael@0 9531 interfaces.push(stack.pop());
michael@0 9532 }
michael@0 9533 constr.$interfaces = interfaces;
michael@0 9534 break;
michael@0 9535 case 143:
michael@0 9536 flags = stream.readUI8();
michael@0 9537 var catchIsRegisterFlag = !(!(flags & 4));
michael@0 9538 var finallyBlockFlag = !(!(flags & 2));
michael@0 9539 var catchBlockFlag = !(!(flags & 1));
michael@0 9540 var trySize = stream.readUI16();
michael@0 9541 var catchSize = stream.readUI16();
michael@0 9542 var finallySize = stream.readUI16();
michael@0 9543 var catchTarget = catchIsRegisterFlag ? stream.readUI8() : stream.readString();
michael@0 9544 nextPosition += trySize + catchSize + finallySize;
michael@0 9545 processTry(catchIsRegisterFlag, finallyBlockFlag, catchBlockFlag, catchTarget, stream.readBytes(trySize), stream.readBytes(catchSize), stream.readBytes(finallySize));
michael@0 9546 break;
michael@0 9547 case 42:
michael@0 9548 obj = stack.pop();
michael@0 9549 throw new AS2Error(obj);
michael@0 9550 case 45:
michael@0 9551 args = readArgs(stack);
michael@0 9552 stackItemsExpected++;
michael@0 9553 result = _global.fscommand.apply(null, args);
michael@0 9554 stack.push(result);
michael@0 9555 break;
michael@0 9556 case 137:
michael@0 9557 var mode = stream.readUI8();
michael@0 9558 break;
michael@0 9559 case 0:
michael@0 9560 return;
michael@0 9561 default:
michael@0 9562 throw new Error('Unknown action code: ' + actionCode);
michael@0 9563 }
michael@0 9564 stream.position = nextPosition;
michael@0 9565 recoveringFromError = false;
michael@0 9566 }
michael@0 9567 } catch (e) {
michael@0 9568 if (!AVM1_ERRORS_IGNORED && !currentContext.isTryCatchListening || e instanceof AS2CriticalError) {
michael@0 9569 throw e;
michael@0 9570 }
michael@0 9571 if (e instanceof AS2Error) {
michael@0 9572 throw e;
michael@0 9573 }
michael@0 9574 var AVM1_ERROR_TYPE = 1;
michael@0 9575 TelemetryService.reportTelemetry({
michael@0 9576 topic: 'error',
michael@0 9577 error: AVM1_ERROR_TYPE
michael@0 9578 });
michael@0 9579 stream.position = nextPosition;
michael@0 9580 if (stackItemsExpected > 0) {
michael@0 9581 while (stackItemsExpected--) {
michael@0 9582 stack.push(undefined);
michael@0 9583 }
michael@0 9584 }
michael@0 9585 if (!recoveringFromError) {
michael@0 9586 if (currentContext.errorsIgnored++ >= MAX_AVM1_ERRORS_LIMIT) {
michael@0 9587 throw new AS2CriticalError('long running script -- AVM1 errors limit is reached');
michael@0 9588 }
michael@0 9589 console.error('AVM1 error: ' + e);
michael@0 9590 avm2.exceptions.push({
michael@0 9591 source: 'avm1',
michael@0 9592 message: e.message,
michael@0 9593 stack: e.stack
michael@0 9594 });
michael@0 9595 recoveringFromError = true;
michael@0 9596 }
michael@0 9597 }
michael@0 9598 }
michael@0 9599 }
michael@0 9600 var ActionTracerFactory = function () {
michael@0 9601 var indentation = 0;
michael@0 9602 var tracer = {
michael@0 9603 print: function (position, actionCode, stack) {
michael@0 9604 var stackDump = [];
michael@0 9605 for (var q = 0; q < stack.length; q++) {
michael@0 9606 var item = stack[q];
michael@0 9607 stackDump.push(item && typeof item === 'object' ? '[' + (item.constructor && item.constructor.name ? item.constructor.name : 'Object') + ']' : item);
michael@0 9608 }
michael@0 9609 var indent = new Array(indentation + 1).join('..');
michael@0 9610 console.log('AVM1 trace: ' + indent + position + ': ' + ActionNamesMap[actionCode] + '(' + actionCode.toString(16) + '), ' + 'stack=' + stackDump);
michael@0 9611 },
michael@0 9612 indent: function () {
michael@0 9613 indentation++;
michael@0 9614 },
michael@0 9615 unindent: function () {
michael@0 9616 indentation--;
michael@0 9617 },
michael@0 9618 message: function (str) {
michael@0 9619 console.log('AVM1 trace: ------- ' + str);
michael@0 9620 }
michael@0 9621 };
michael@0 9622 var nullTracer = {
michael@0 9623 print: function () {
michael@0 9624 },
michael@0 9625 indent: function () {
michael@0 9626 },
michael@0 9627 unindent: function () {
michael@0 9628 },
michael@0 9629 message: function () {
michael@0 9630 }
michael@0 9631 };
michael@0 9632 function ActionTracerFactory() {
michael@0 9633 }
michael@0 9634 ActionTracerFactory.get = function () {
michael@0 9635 return AVM1_TRACE_ENABLED ? tracer : nullTracer;
michael@0 9636 };
michael@0 9637 return ActionTracerFactory;
michael@0 9638 }();
michael@0 9639 var ActionNamesMap = {
michael@0 9640 0: 'EOA',
michael@0 9641 4: 'ActionNextFrame',
michael@0 9642 5: 'ActionPreviousFrame',
michael@0 9643 6: 'ActionPlay',
michael@0 9644 7: 'ActionStop',
michael@0 9645 8: 'ActionToggleQuality',
michael@0 9646 9: 'ActionStopSounds',
michael@0 9647 10: 'ActionAdd',
michael@0 9648 11: 'ActionSubtract',
michael@0 9649 12: 'ActionMultiply',
michael@0 9650 13: 'ActionDivide',
michael@0 9651 14: 'ActionEquals',
michael@0 9652 15: 'ActionLess',
michael@0 9653 16: 'ActionAnd',
michael@0 9654 17: 'ActionOr',
michael@0 9655 18: 'ActionNot',
michael@0 9656 19: 'ActionStringEquals',
michael@0 9657 20: 'ActionStringLength',
michael@0 9658 21: 'ActionStringExtract',
michael@0 9659 23: 'ActionPop',
michael@0 9660 24: 'ActionToInteger',
michael@0 9661 28: 'ActionGetVariable',
michael@0 9662 29: 'ActionSetVariable',
michael@0 9663 32: 'ActionSetTarget2',
michael@0 9664 33: 'ActionStringAdd',
michael@0 9665 34: 'ActionGetProperty',
michael@0 9666 35: 'ActionSetProperty',
michael@0 9667 36: 'ActionCloneSprite',
michael@0 9668 37: 'ActionRemoveSprite',
michael@0 9669 38: 'ActionTrace',
michael@0 9670 39: 'ActionStartDrag',
michael@0 9671 40: 'ActionEndDrag',
michael@0 9672 41: 'ActionStringLess',
michael@0 9673 42: 'ActionThrow',
michael@0 9674 43: 'ActionCastOp',
michael@0 9675 44: 'ActionImplementsOp',
michael@0 9676 45: 'ActionFSCommand2',
michael@0 9677 48: 'ActionRandomNumber',
michael@0 9678 49: 'ActionMBStringLength',
michael@0 9679 50: 'ActionCharToAscii',
michael@0 9680 51: 'ActionAsciiToChar',
michael@0 9681 52: 'ActionGetTime',
michael@0 9682 53: 'ActionMBStringExtrac',
michael@0 9683 54: 'ActionMBCharToAscii',
michael@0 9684 55: 'ActionMBAsciiToChar',
michael@0 9685 58: 'ActionDelete',
michael@0 9686 59: 'ActionDelete2',
michael@0 9687 60: 'ActionDefineLocal',
michael@0 9688 61: 'ActionCallFunction',
michael@0 9689 62: 'ActionReturn',
michael@0 9690 63: 'ActionModulo',
michael@0 9691 64: 'ActionNewObject',
michael@0 9692 65: 'ActionDefineLocal2',
michael@0 9693 66: 'ActionInitArray',
michael@0 9694 67: 'ActionInitObject',
michael@0 9695 68: 'ActionTypeOf',
michael@0 9696 69: 'ActionTargetPath',
michael@0 9697 70: 'ActionEnumerate',
michael@0 9698 71: 'ActionAdd2',
michael@0 9699 72: 'ActionLess2',
michael@0 9700 73: 'ActionEquals2',
michael@0 9701 74: 'ActionToNumber',
michael@0 9702 75: 'ActionToString',
michael@0 9703 76: 'ActionPushDuplicate',
michael@0 9704 77: 'ActionStackSwap',
michael@0 9705 78: 'ActionGetMember',
michael@0 9706 79: 'ActionSetMember',
michael@0 9707 80: 'ActionIncrement',
michael@0 9708 81: 'ActionDecrement',
michael@0 9709 82: 'ActionCallMethod',
michael@0 9710 83: 'ActionNewMethod',
michael@0 9711 84: 'ActionInstanceOf',
michael@0 9712 85: 'ActionEnumerate2',
michael@0 9713 96: 'ActionBitAnd',
michael@0 9714 97: 'ActionBitOr',
michael@0 9715 98: 'ActionBitXor',
michael@0 9716 99: 'ActionBitLShift',
michael@0 9717 100: 'ActionBitRShift',
michael@0 9718 101: 'ActionBitURShift',
michael@0 9719 102: 'ActionStrictEquals',
michael@0 9720 103: 'ActionGreater',
michael@0 9721 104: 'ActionStringGreater',
michael@0 9722 105: 'ActionExtends',
michael@0 9723 129: 'ActionGotoFrame',
michael@0 9724 131: 'ActionGetURL',
michael@0 9725 135: 'ActionStoreRegister',
michael@0 9726 136: 'ActionConstantPool',
michael@0 9727 137: 'ActionStrictMode',
michael@0 9728 138: 'ActionWaitForFrame',
michael@0 9729 139: 'ActionSetTarget',
michael@0 9730 140: 'ActionGoToLabel',
michael@0 9731 141: 'ActionWaitForFrame2',
michael@0 9732 142: 'ActionDefineFunction',
michael@0 9733 143: 'ActionTry',
michael@0 9734 148: 'ActionWith',
michael@0 9735 150: 'ActionPush',
michael@0 9736 153: 'ActionJump',
michael@0 9737 154: 'ActionGetURL2',
michael@0 9738 155: 'ActionDefineFunction',
michael@0 9739 157: 'ActionIf',
michael@0 9740 158: 'ActionCall',
michael@0 9741 159: 'ActionGotoFrame2'
michael@0 9742 };
michael@0 9743 if (typeof GLOBAL !== 'undefined') {
michael@0 9744 GLOBAL.createBuiltinType = createBuiltinType;
michael@0 9745 GLOBAL.executeActions = executeActions;
michael@0 9746 GLOBAL.AS2Context = AS2Context;
michael@0 9747 }
michael@0 9748 var jsGlobal = function () {
michael@0 9749 return this || (1, eval)('this');
michael@0 9750 }();
michael@0 9751 var inBrowser = typeof console != 'undefined';
michael@0 9752 var release = true;
michael@0 9753 var debug = !true;
michael@0 9754 if (!jsGlobal.performance) {
michael@0 9755 jsGlobal.performance = {};
michael@0 9756 }
michael@0 9757 if (!jsGlobal.performance.now) {
michael@0 9758 jsGlobal.performance.now = dateNow;
michael@0 9759 }
michael@0 9760 function log(message) {
michael@0 9761 var optionalParams = [];
michael@0 9762 for (var _i = 0; _i < arguments.length - 1; _i++) {
michael@0 9763 optionalParams[_i] = arguments[_i + 1];
michael@0 9764 }
michael@0 9765 jsGlobal.print(message);
michael@0 9766 }
michael@0 9767 function warn(message) {
michael@0 9768 var optionalParams = [];
michael@0 9769 for (var _i = 0; _i < arguments.length - 1; _i++) {
michael@0 9770 optionalParams[_i] = arguments[_i + 1];
michael@0 9771 }
michael@0 9772 if (inBrowser) {
michael@0 9773 console.warn(message);
michael@0 9774 } else {
michael@0 9775 jsGlobal.print(message);
michael@0 9776 }
michael@0 9777 }
michael@0 9778 var Shumway;
michael@0 9779 (function (Shumway) {
michael@0 9780 (function (CharacterCodes) {
michael@0 9781 CharacterCodes[CharacterCodes['_0'] = 48] = '_0';
michael@0 9782 CharacterCodes[CharacterCodes['_1'] = 49] = '_1';
michael@0 9783 CharacterCodes[CharacterCodes['_2'] = 50] = '_2';
michael@0 9784 CharacterCodes[CharacterCodes['_3'] = 51] = '_3';
michael@0 9785 CharacterCodes[CharacterCodes['_4'] = 52] = '_4';
michael@0 9786 CharacterCodes[CharacterCodes['_5'] = 53] = '_5';
michael@0 9787 CharacterCodes[CharacterCodes['_6'] = 54] = '_6';
michael@0 9788 CharacterCodes[CharacterCodes['_7'] = 55] = '_7';
michael@0 9789 CharacterCodes[CharacterCodes['_8'] = 56] = '_8';
michael@0 9790 CharacterCodes[CharacterCodes['_9'] = 57] = '_9';
michael@0 9791 }(Shumway.CharacterCodes || (Shumway.CharacterCodes = {})));
michael@0 9792 var CharacterCodes = Shumway.CharacterCodes;
michael@0 9793 Shumway.UINT32_CHAR_BUFFER_LENGTH = 10;
michael@0 9794 Shumway.UINT32_MAX = 4294967295;
michael@0 9795 Shumway.UINT32_MAX_DIV_10 = 429496729;
michael@0 9796 Shumway.UINT32_MAX_MOD_10 = 5;
michael@0 9797 function isString(value) {
michael@0 9798 return typeof value === 'string';
michael@0 9799 }
michael@0 9800 Shumway.isString = isString;
michael@0 9801 function isFunction(value) {
michael@0 9802 return typeof value === 'function';
michael@0 9803 }
michael@0 9804 Shumway.isFunction = isFunction;
michael@0 9805 function isNumber(value) {
michael@0 9806 return typeof value === 'number';
michael@0 9807 }
michael@0 9808 Shumway.isNumber = isNumber;
michael@0 9809 function isNumberOrString(value) {
michael@0 9810 return typeof value === 'number' || typeof value === 'string';
michael@0 9811 }
michael@0 9812 Shumway.isNumberOrString = isNumberOrString;
michael@0 9813 function isObject(value) {
michael@0 9814 return typeof value === 'object' || typeof value === 'function';
michael@0 9815 }
michael@0 9816 Shumway.isObject = isObject;
michael@0 9817 function toNumber(x) {
michael@0 9818 return +x;
michael@0 9819 }
michael@0 9820 Shumway.toNumber = toNumber;
michael@0 9821 function isNumericString(value) {
michael@0 9822 return String(Number(value)) === value;
michael@0 9823 }
michael@0 9824 Shumway.isNumericString = isNumericString;
michael@0 9825 function isNumeric(value) {
michael@0 9826 if (typeof value === 'number') {
michael@0 9827 return true;
michael@0 9828 } else if (typeof value === 'string') {
michael@0 9829 return isIndex(value) || isNumericString(value);
michael@0 9830 } else {
michael@0 9831 Debug.notImplemented(typeof value);
michael@0 9832 }
michael@0 9833 }
michael@0 9834 Shumway.isNumeric = isNumeric;
michael@0 9835 function isIndex(value) {
michael@0 9836 var index = 0;
michael@0 9837 if (typeof value === 'number') {
michael@0 9838 index = value | 0;
michael@0 9839 if (value === index && index >= 0) {
michael@0 9840 return true;
michael@0 9841 }
michael@0 9842 return value >>> 0 === value;
michael@0 9843 }
michael@0 9844 if (typeof value !== 'string') {
michael@0 9845 return false;
michael@0 9846 }
michael@0 9847 var length = value.length;
michael@0 9848 if (length === 0) {
michael@0 9849 return false;
michael@0 9850 }
michael@0 9851 if (value === '0') {
michael@0 9852 return true;
michael@0 9853 }
michael@0 9854 if (length > Shumway.UINT32_CHAR_BUFFER_LENGTH) {
michael@0 9855 return false;
michael@0 9856 }
michael@0 9857 var i = 0;
michael@0 9858 index = value.charCodeAt(i++) - 48;
michael@0 9859 if (index < 1 || index > 9) {
michael@0 9860 return false;
michael@0 9861 }
michael@0 9862 var oldIndex = 0;
michael@0 9863 var c = 0;
michael@0 9864 while (i < length) {
michael@0 9865 c = value.charCodeAt(i++) - 48;
michael@0 9866 if (c < 0 || c > 9) {
michael@0 9867 return false;
michael@0 9868 }
michael@0 9869 oldIndex = index;
michael@0 9870 index = 10 * index + c;
michael@0 9871 }
michael@0 9872 if (oldIndex < Shumway.UINT32_MAX_DIV_10 || oldIndex === Shumway.UINT32_MAX_DIV_10 && c <= Shumway.UINT32_MAX_MOD_10) {
michael@0 9873 return true;
michael@0 9874 }
michael@0 9875 return false;
michael@0 9876 }
michael@0 9877 Shumway.isIndex = isIndex;
michael@0 9878 function isNullOrUndefined(value) {
michael@0 9879 return value == undefined;
michael@0 9880 }
michael@0 9881 Shumway.isNullOrUndefined = isNullOrUndefined;
michael@0 9882 (function (Debug) {
michael@0 9883 function backtrace() {
michael@0 9884 try {
michael@0 9885 throw new Error();
michael@0 9886 } catch (e) {
michael@0 9887 return e.stack ? e.stack.split('\n').slice(2).join('\n') : '';
michael@0 9888 }
michael@0 9889 }
michael@0 9890 Debug.backtrace = backtrace;
michael@0 9891 function error(message) {
michael@0 9892 if (!inBrowser) {
michael@0 9893 warn(Debug.backtrace());
michael@0 9894 }
michael@0 9895 throw new Error(message);
michael@0 9896 }
michael@0 9897 Debug.error = error;
michael@0 9898 function assert(condition) {
michael@0 9899 var args = [];
michael@0 9900 for (var _i = 0; _i < arguments.length - 1; _i++) {
michael@0 9901 args[_i] = arguments[_i + 1];
michael@0 9902 }
michael@0 9903 if (condition === '') {
michael@0 9904 condition = true;
michael@0 9905 }
michael@0 9906 if (!condition) {
michael@0 9907 var message = Array.prototype.slice.call(arguments);
michael@0 9908 message.shift();
michael@0 9909 Debug.error(message.join(''));
michael@0 9910 }
michael@0 9911 }
michael@0 9912 Debug.assert = assert;
michael@0 9913 function assertNotImplemented(condition, message) {
michael@0 9914 if (!condition) {
michael@0 9915 Debug.error('NotImplemented: ' + message);
michael@0 9916 }
michael@0 9917 }
michael@0 9918 Debug.assertNotImplemented = assertNotImplemented;
michael@0 9919 function warning(message) {
michael@0 9920 true;
michael@0 9921 }
michael@0 9922 Debug.warning = warning;
michael@0 9923 function notUsed(message) {
michael@0 9924 true;
michael@0 9925 }
michael@0 9926 Debug.notUsed = notUsed;
michael@0 9927 function notImplemented(message) {
michael@0 9928 true;
michael@0 9929 }
michael@0 9930 Debug.notImplemented = notImplemented;
michael@0 9931 function somewhatImplemented(message) {
michael@0 9932 Debug.warning('somewhatImplemented: ' + message);
michael@0 9933 }
michael@0 9934 Debug.somewhatImplemented = somewhatImplemented;
michael@0 9935 function unexpected(message) {
michael@0 9936 Debug.assert(false, 'Unexpected: ' + message);
michael@0 9937 }
michael@0 9938 Debug.unexpected = unexpected;
michael@0 9939 }(Shumway.Debug || (Shumway.Debug = {})));
michael@0 9940 var Debug = Shumway.Debug;
michael@0 9941 function getTicks() {
michael@0 9942 return performance.now();
michael@0 9943 }
michael@0 9944 Shumway.getTicks = getTicks;
michael@0 9945 (function (ArrayUtilities) {
michael@0 9946 function popManyInto(src, count, dst) {
michael@0 9947 true;
michael@0 9948 for (var i = count - 1; i >= 0; i--) {
michael@0 9949 dst[i] = src.pop();
michael@0 9950 }
michael@0 9951 dst.length = count;
michael@0 9952 }
michael@0 9953 ArrayUtilities.popManyInto = popManyInto;
michael@0 9954 }(Shumway.ArrayUtilities || (Shumway.ArrayUtilities = {})));
michael@0 9955 var ArrayUtilities = Shumway.ArrayUtilities;
michael@0 9956 (function (ObjectUtilities) {
michael@0 9957 function boxValue(value) {
michael@0 9958 if (Shumway.isNullOrUndefined(value) || Shumway.isObject(value)) {
michael@0 9959 return value;
michael@0 9960 }
michael@0 9961 return Object(value);
michael@0 9962 }
michael@0 9963 ObjectUtilities.boxValue = boxValue;
michael@0 9964 function toKeyValueArray(object) {
michael@0 9965 var hasOwnProperty = Object.prototype.hasOwnProperty;
michael@0 9966 var array = [];
michael@0 9967 for (var k in object) {
michael@0 9968 if (hasOwnProperty.call(object, k)) {
michael@0 9969 array.push([
michael@0 9970 k,
michael@0 9971 object[k]
michael@0 9972 ]);
michael@0 9973 }
michael@0 9974 }
michael@0 9975 return array;
michael@0 9976 }
michael@0 9977 ObjectUtilities.toKeyValueArray = toKeyValueArray;
michael@0 9978 function hasOwnProperty(object, name) {
michael@0 9979 return Object.prototype.hasOwnProperty.call(object, name);
michael@0 9980 }
michael@0 9981 ObjectUtilities.hasOwnProperty = hasOwnProperty;
michael@0 9982 function createEmptyObject() {
michael@0 9983 return Object.create(null);
michael@0 9984 }
michael@0 9985 ObjectUtilities.createEmptyObject = createEmptyObject;
michael@0 9986 function createMap() {
michael@0 9987 return Object.create(null);
michael@0 9988 }
michael@0 9989 ObjectUtilities.createMap = createMap;
michael@0 9990 function createArrayMap() {
michael@0 9991 return [];
michael@0 9992 }
michael@0 9993 ObjectUtilities.createArrayMap = createArrayMap;
michael@0 9994 function defineReadOnlyProperty(object, name, value) {
michael@0 9995 Object.defineProperty(object, name, {
michael@0 9996 value: value,
michael@0 9997 writable: false,
michael@0 9998 configurable: true,
michael@0 9999 enumerable: false
michael@0 10000 });
michael@0 10001 }
michael@0 10002 ObjectUtilities.defineReadOnlyProperty = defineReadOnlyProperty;
michael@0 10003 function getOwnPropertyDescriptors(object) {
michael@0 10004 var o = ObjectUtilities.createMap();
michael@0 10005 var properties = Object.getOwnPropertyNames(object);
michael@0 10006 for (var i = 0; i < properties.length; i++) {
michael@0 10007 o[properties[i]] = Object.getOwnPropertyDescriptor(object, properties[i]);
michael@0 10008 }
michael@0 10009 return o;
michael@0 10010 }
michael@0 10011 ObjectUtilities.getOwnPropertyDescriptors = getOwnPropertyDescriptors;
michael@0 10012 function cloneObject(object) {
michael@0 10013 var clone = ObjectUtilities.createEmptyObject();
michael@0 10014 for (var property in object) {
michael@0 10015 clone[property] = object[property];
michael@0 10016 }
michael@0 10017 return clone;
michael@0 10018 }
michael@0 10019 ObjectUtilities.cloneObject = cloneObject;
michael@0 10020 function copyProperties(object, template) {
michael@0 10021 for (var property in template) {
michael@0 10022 object[property] = template[property];
michael@0 10023 }
michael@0 10024 }
michael@0 10025 ObjectUtilities.copyProperties = copyProperties;
michael@0 10026 function getLatestGetterOrSetterPropertyDescriptor(object, name) {
michael@0 10027 var descriptor = {};
michael@0 10028 while (object) {
michael@0 10029 var tmp = Object.getOwnPropertyDescriptor(object, name);
michael@0 10030 if (tmp) {
michael@0 10031 descriptor.get = descriptor.get || tmp.get;
michael@0 10032 descriptor.set = descriptor.set || tmp.set;
michael@0 10033 }
michael@0 10034 if (descriptor.get && descriptor.set) {
michael@0 10035 break;
michael@0 10036 }
michael@0 10037 object = Object.getPrototypeOf(object);
michael@0 10038 }
michael@0 10039 return descriptor;
michael@0 10040 }
michael@0 10041 ObjectUtilities.getLatestGetterOrSetterPropertyDescriptor = getLatestGetterOrSetterPropertyDescriptor;
michael@0 10042 function defineNonEnumerableGetterOrSetter(obj, name, value, isGetter) {
michael@0 10043 var descriptor = ObjectUtilities.getLatestGetterOrSetterPropertyDescriptor(obj, name);
michael@0 10044 descriptor.configurable = true;
michael@0 10045 descriptor.enumerable = false;
michael@0 10046 if (isGetter) {
michael@0 10047 descriptor.get = value;
michael@0 10048 } else {
michael@0 10049 descriptor.set = value;
michael@0 10050 }
michael@0 10051 Object.defineProperty(obj, name, descriptor);
michael@0 10052 }
michael@0 10053 ObjectUtilities.defineNonEnumerableGetterOrSetter = defineNonEnumerableGetterOrSetter;
michael@0 10054 function defineNonEnumerableGetter(obj, name, getter) {
michael@0 10055 Object.defineProperty(obj, name, {
michael@0 10056 get: getter,
michael@0 10057 configurable: true,
michael@0 10058 enumerable: false
michael@0 10059 });
michael@0 10060 }
michael@0 10061 ObjectUtilities.defineNonEnumerableGetter = defineNonEnumerableGetter;
michael@0 10062 function defineNonEnumerableSetter(obj, name, setter) {
michael@0 10063 Object.defineProperty(obj, name, {
michael@0 10064 set: setter,
michael@0 10065 configurable: true,
michael@0 10066 enumerable: false
michael@0 10067 });
michael@0 10068 }
michael@0 10069 ObjectUtilities.defineNonEnumerableSetter = defineNonEnumerableSetter;
michael@0 10070 function defineNonEnumerableProperty(obj, name, value) {
michael@0 10071 Object.defineProperty(obj, name, {
michael@0 10072 value: value,
michael@0 10073 writable: true,
michael@0 10074 configurable: true,
michael@0 10075 enumerable: false
michael@0 10076 });
michael@0 10077 }
michael@0 10078 ObjectUtilities.defineNonEnumerableProperty = defineNonEnumerableProperty;
michael@0 10079 function defineNonEnumerableForwardingProperty(obj, name, otherName) {
michael@0 10080 Object.defineProperty(obj, name, {
michael@0 10081 get: FunctionUtilities.makeForwardingGetter(otherName),
michael@0 10082 set: FunctionUtilities.makeForwardingSetter(otherName),
michael@0 10083 writable: true,
michael@0 10084 configurable: true,
michael@0 10085 enumerable: false
michael@0 10086 });
michael@0 10087 }
michael@0 10088 ObjectUtilities.defineNonEnumerableForwardingProperty = defineNonEnumerableForwardingProperty;
michael@0 10089 function defineNewNonEnumerableProperty(obj, name, value) {
michael@0 10090 true;
michael@0 10091 ObjectUtilities.defineNonEnumerableProperty(obj, name, value);
michael@0 10092 }
michael@0 10093 ObjectUtilities.defineNewNonEnumerableProperty = defineNewNonEnumerableProperty;
michael@0 10094 }(Shumway.ObjectUtilities || (Shumway.ObjectUtilities = {})));
michael@0 10095 var ObjectUtilities = Shumway.ObjectUtilities;
michael@0 10096 (function (FunctionUtilities) {
michael@0 10097 function makeForwardingGetter(target) {
michael@0 10098 return new Function('return this["' + target + '"]');
michael@0 10099 }
michael@0 10100 FunctionUtilities.makeForwardingGetter = makeForwardingGetter;
michael@0 10101 function makeForwardingSetter(target) {
michael@0 10102 return new Function('value', 'this["' + target + '"] = value;');
michael@0 10103 }
michael@0 10104 FunctionUtilities.makeForwardingSetter = makeForwardingSetter;
michael@0 10105 function bindSafely(fn, object) {
michael@0 10106 true;
michael@0 10107 var f = fn.bind(object);
michael@0 10108 f.boundTo = object;
michael@0 10109 return f;
michael@0 10110 }
michael@0 10111 FunctionUtilities.bindSafely = bindSafely;
michael@0 10112 }(Shumway.FunctionUtilities || (Shumway.FunctionUtilities = {})));
michael@0 10113 var FunctionUtilities = Shumway.FunctionUtilities;
michael@0 10114 (function (StringUtilities) {
michael@0 10115 function toSafeString(value) {
michael@0 10116 if (typeof value === 'string') {
michael@0 10117 return '"' + value + '"';
michael@0 10118 }
michael@0 10119 if (typeof value === 'number' || typeof value === 'boolean') {
michael@0 10120 return String(value);
michael@0 10121 }
michael@0 10122 return typeof value;
michael@0 10123 }
michael@0 10124 StringUtilities.toSafeString = toSafeString;
michael@0 10125 function toSafeArrayString(array) {
michael@0 10126 var str = [];
michael@0 10127 for (var i = 0; i < array.length; i++) {
michael@0 10128 str.push(toSafeString(array[i]));
michael@0 10129 }
michael@0 10130 return str.join(', ');
michael@0 10131 }
michael@0 10132 StringUtilities.toSafeArrayString = toSafeArrayString;
michael@0 10133 function utf8decode(str) {
michael@0 10134 var bytes = new Uint8Array(str.length * 4);
michael@0 10135 var b = 0;
michael@0 10136 for (var i = 0, j = str.length; i < j; i++) {
michael@0 10137 var code = str.charCodeAt(i);
michael@0 10138 if (code <= 127) {
michael@0 10139 bytes[b++] = code;
michael@0 10140 continue;
michael@0 10141 }
michael@0 10142 if (55296 <= code && code <= 56319) {
michael@0 10143 var codeLow = str.charCodeAt(i + 1);
michael@0 10144 if (56320 <= codeLow && codeLow <= 57343) {
michael@0 10145 code = ((code & 1023) << 10) + (codeLow & 1023) + 65536;
michael@0 10146 ++i;
michael@0 10147 }
michael@0 10148 }
michael@0 10149 if ((code & 4292870144) !== 0) {
michael@0 10150 bytes[b++] = 248 | code >>> 24 & 3;
michael@0 10151 bytes[b++] = 128 | code >>> 18 & 63;
michael@0 10152 bytes[b++] = 128 | code >>> 12 & 63;
michael@0 10153 bytes[b++] = 128 | code >>> 6 & 63;
michael@0 10154 bytes[b++] = 128 | code & 63;
michael@0 10155 } else if ((code & 4294901760) !== 0) {
michael@0 10156 bytes[b++] = 240 | code >>> 18 & 7;
michael@0 10157 bytes[b++] = 128 | code >>> 12 & 63;
michael@0 10158 bytes[b++] = 128 | code >>> 6 & 63;
michael@0 10159 bytes[b++] = 128 | code & 63;
michael@0 10160 } else if ((code & 4294965248) !== 0) {
michael@0 10161 bytes[b++] = 224 | code >>> 12 & 15;
michael@0 10162 bytes[b++] = 128 | code >>> 6 & 63;
michael@0 10163 bytes[b++] = 128 | code & 63;
michael@0 10164 } else {
michael@0 10165 bytes[b++] = 192 | code >>> 6 & 31;
michael@0 10166 bytes[b++] = 128 | code & 63;
michael@0 10167 }
michael@0 10168 }
michael@0 10169 return bytes.subarray(0, b);
michael@0 10170 }
michael@0 10171 StringUtilities.utf8decode = utf8decode;
michael@0 10172 function utf8encode(bytes) {
michael@0 10173 var j = 0, str = '';
michael@0 10174 while (j < bytes.length) {
michael@0 10175 var b1 = bytes[j++] & 255;
michael@0 10176 if (b1 <= 127) {
michael@0 10177 str += String.fromCharCode(b1);
michael@0 10178 } else {
michael@0 10179 var currentPrefix = 192;
michael@0 10180 var validBits = 5;
michael@0 10181 do {
michael@0 10182 var mask = currentPrefix >> 1 | 128;
michael@0 10183 if ((b1 & mask) === currentPrefix)
michael@0 10184 break;
michael@0 10185 currentPrefix = currentPrefix >> 1 | 128;
michael@0 10186 --validBits;
michael@0 10187 } while (validBits >= 0);
michael@0 10188 if (validBits <= 0) {
michael@0 10189 str += String.fromCharCode(b1);
michael@0 10190 continue;
michael@0 10191 }
michael@0 10192 var code = b1 & (1 << validBits) - 1;
michael@0 10193 var invalid = false;
michael@0 10194 for (var i = 5; i >= validBits; --i) {
michael@0 10195 var bi = bytes[j++];
michael@0 10196 if ((bi & 192) != 128) {
michael@0 10197 invalid = true;
michael@0 10198 break;
michael@0 10199 }
michael@0 10200 code = code << 6 | bi & 63;
michael@0 10201 }
michael@0 10202 if (invalid) {
michael@0 10203 for (var k = j - (7 - i); k < j; ++k) {
michael@0 10204 str += String.fromCharCode(bytes[k] & 255);
michael@0 10205 }
michael@0 10206 continue;
michael@0 10207 }
michael@0 10208 if (code >= 65536) {
michael@0 10209 str += String.fromCharCode(code - 65536 >> 10 & 1023 | 55296, code & 1023 | 56320);
michael@0 10210 } else {
michael@0 10211 str += String.fromCharCode(code);
michael@0 10212 }
michael@0 10213 }
michael@0 10214 }
michael@0 10215 return str;
michael@0 10216 }
michael@0 10217 StringUtilities.utf8encode = utf8encode;
michael@0 10218 function base64ArrayBuffer(arrayBuffer) {
michael@0 10219 var base64 = '';
michael@0 10220 var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
michael@0 10221 var bytes = new Uint8Array(arrayBuffer);
michael@0 10222 var byteLength = bytes.byteLength;
michael@0 10223 var byteRemainder = byteLength % 3;
michael@0 10224 var mainLength = byteLength - byteRemainder;
michael@0 10225 var a, b, c, d;
michael@0 10226 var chunk;
michael@0 10227 for (var i = 0; i < mainLength; i = i + 3) {
michael@0 10228 chunk = bytes[i] << 16 | bytes[i + 1] << 8 | bytes[i + 2];
michael@0 10229 a = (chunk & 16515072) >> 18;
michael@0 10230 b = (chunk & 258048) >> 12;
michael@0 10231 c = (chunk & 4032) >> 6;
michael@0 10232 d = chunk & 63;
michael@0 10233 base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d];
michael@0 10234 }
michael@0 10235 if (byteRemainder == 1) {
michael@0 10236 chunk = bytes[mainLength];
michael@0 10237 a = (chunk & 252) >> 2;
michael@0 10238 b = (chunk & 3) << 4;
michael@0 10239 base64 += encodings[a] + encodings[b] + '==';
michael@0 10240 } else if (byteRemainder == 2) {
michael@0 10241 chunk = bytes[mainLength] << 8 | bytes[mainLength + 1];
michael@0 10242 a = (chunk & 64512) >> 10;
michael@0 10243 b = (chunk & 1008) >> 4;
michael@0 10244 c = (chunk & 15) << 2;
michael@0 10245 base64 += encodings[a] + encodings[b] + encodings[c] + '=';
michael@0 10246 }
michael@0 10247 return base64;
michael@0 10248 }
michael@0 10249 StringUtilities.base64ArrayBuffer = base64ArrayBuffer;
michael@0 10250 function escapeString(str) {
michael@0 10251 if (str !== undefined) {
michael@0 10252 str = str.replace(/[^\w$]/gi, '$');
michael@0 10253 if (/^\d/.test(str)) {
michael@0 10254 str = '$' + str;
michael@0 10255 }
michael@0 10256 }
michael@0 10257 return str;
michael@0 10258 }
michael@0 10259 StringUtilities.escapeString = escapeString;
michael@0 10260 function fromCharCodeArray(buffer) {
michael@0 10261 var str = '', SLICE = 1024 * 16;
michael@0 10262 for (var i = 0; i < buffer.length; i += SLICE) {
michael@0 10263 var chunk = Math.min(buffer.length - i, SLICE);
michael@0 10264 str += String.fromCharCode.apply(null, buffer.subarray(i, i + chunk));
michael@0 10265 }
michael@0 10266 return str;
michael@0 10267 }
michael@0 10268 StringUtilities.fromCharCodeArray = fromCharCodeArray;
michael@0 10269 var _encoding = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789$_';
michael@0 10270 function variableLengthEncodeInt32(n) {
michael@0 10271 var e = _encoding;
michael@0 10272 var bitCount = 32 - IntegerUtilities.leadingZeros(n);
michael@0 10273 var l = Math.ceil(bitCount / 6);
michael@0 10274 var s = e[l];
michael@0 10275 for (var i = l - 1; i >= 0; i--) {
michael@0 10276 var offset = i * 6;
michael@0 10277 s += e[n >> offset & 63];
michael@0 10278 }
michael@0 10279 true;
michael@0 10280 return s;
michael@0 10281 }
michael@0 10282 StringUtilities.variableLengthEncodeInt32 = variableLengthEncodeInt32;
michael@0 10283 function toEncoding(n) {
michael@0 10284 return _encoding[n];
michael@0 10285 }
michael@0 10286 StringUtilities.toEncoding = toEncoding;
michael@0 10287 function fromEncoding(s) {
michael@0 10288 var c = s.charCodeAt(0);
michael@0 10289 var e = 0;
michael@0 10290 if (c >= 65 && c <= 90) {
michael@0 10291 return c - 65;
michael@0 10292 } else if (c >= 97 && c <= 122) {
michael@0 10293 return c - 71;
michael@0 10294 } else if (c >= 48 && c <= 57) {
michael@0 10295 return c + 4;
michael@0 10296 } else if (c === 36) {
michael@0 10297 return 62;
michael@0 10298 } else if (c === 95) {
michael@0 10299 return 63;
michael@0 10300 }
michael@0 10301 }
michael@0 10302 StringUtilities.fromEncoding = fromEncoding;
michael@0 10303 function variableLengthDecodeInt32(s) {
michael@0 10304 var l = StringUtilities.fromEncoding(s[0]);
michael@0 10305 var n = 0;
michael@0 10306 for (var i = 0; i < l; i++) {
michael@0 10307 var offset = (l - i - 1) * 6;
michael@0 10308 n |= StringUtilities.fromEncoding(s[1 + i]) << offset;
michael@0 10309 }
michael@0 10310 return n;
michael@0 10311 }
michael@0 10312 StringUtilities.variableLengthDecodeInt32 = variableLengthDecodeInt32;
michael@0 10313 }(Shumway.StringUtilities || (Shumway.StringUtilities = {})));
michael@0 10314 var StringUtilities = Shumway.StringUtilities;
michael@0 10315 (function (HashUtilities) {
michael@0 10316 var _md5R = new Uint8Array([
michael@0 10317 7,
michael@0 10318 12,
michael@0 10319 17,
michael@0 10320 22,
michael@0 10321 7,
michael@0 10322 12,
michael@0 10323 17,
michael@0 10324 22,
michael@0 10325 7,
michael@0 10326 12,
michael@0 10327 17,
michael@0 10328 22,
michael@0 10329 7,
michael@0 10330 12,
michael@0 10331 17,
michael@0 10332 22,
michael@0 10333 5,
michael@0 10334 9,
michael@0 10335 14,
michael@0 10336 20,
michael@0 10337 5,
michael@0 10338 9,
michael@0 10339 14,
michael@0 10340 20,
michael@0 10341 5,
michael@0 10342 9,
michael@0 10343 14,
michael@0 10344 20,
michael@0 10345 5,
michael@0 10346 9,
michael@0 10347 14,
michael@0 10348 20,
michael@0 10349 4,
michael@0 10350 11,
michael@0 10351 16,
michael@0 10352 23,
michael@0 10353 4,
michael@0 10354 11,
michael@0 10355 16,
michael@0 10356 23,
michael@0 10357 4,
michael@0 10358 11,
michael@0 10359 16,
michael@0 10360 23,
michael@0 10361 4,
michael@0 10362 11,
michael@0 10363 16,
michael@0 10364 23,
michael@0 10365 6,
michael@0 10366 10,
michael@0 10367 15,
michael@0 10368 21,
michael@0 10369 6,
michael@0 10370 10,
michael@0 10371 15,
michael@0 10372 21,
michael@0 10373 6,
michael@0 10374 10,
michael@0 10375 15,
michael@0 10376 21,
michael@0 10377 6,
michael@0 10378 10,
michael@0 10379 15,
michael@0 10380 21
michael@0 10381 ]);
michael@0 10382 var _md5K = new Int32Array([
michael@0 10383 -680876936,
michael@0 10384 -389564586,
michael@0 10385 606105819,
michael@0 10386 -1044525330,
michael@0 10387 -176418897,
michael@0 10388 1200080426,
michael@0 10389 -1473231341,
michael@0 10390 -45705983,
michael@0 10391 1770035416,
michael@0 10392 -1958414417,
michael@0 10393 -42063,
michael@0 10394 -1990404162,
michael@0 10395 1804603682,
michael@0 10396 -40341101,
michael@0 10397 -1502002290,
michael@0 10398 1236535329,
michael@0 10399 -165796510,
michael@0 10400 -1069501632,
michael@0 10401 643717713,
michael@0 10402 -373897302,
michael@0 10403 -701558691,
michael@0 10404 38016083,
michael@0 10405 -660478335,
michael@0 10406 -405537848,
michael@0 10407 568446438,
michael@0 10408 -1019803690,
michael@0 10409 -187363961,
michael@0 10410 1163531501,
michael@0 10411 -1444681467,
michael@0 10412 -51403784,
michael@0 10413 1735328473,
michael@0 10414 -1926607734,
michael@0 10415 -378558,
michael@0 10416 -2022574463,
michael@0 10417 1839030562,
michael@0 10418 -35309556,
michael@0 10419 -1530992060,
michael@0 10420 1272893353,
michael@0 10421 -155497632,
michael@0 10422 -1094730640,
michael@0 10423 681279174,
michael@0 10424 -358537222,
michael@0 10425 -722521979,
michael@0 10426 76029189,
michael@0 10427 -640364487,
michael@0 10428 -421815835,
michael@0 10429 530742520,
michael@0 10430 -995338651,
michael@0 10431 -198630844,
michael@0 10432 1126891415,
michael@0 10433 -1416354905,
michael@0 10434 -57434055,
michael@0 10435 1700485571,
michael@0 10436 -1894986606,
michael@0 10437 -1051523,
michael@0 10438 -2054922799,
michael@0 10439 1873313359,
michael@0 10440 -30611744,
michael@0 10441 -1560198380,
michael@0 10442 1309151649,
michael@0 10443 -145523070,
michael@0 10444 -1120210379,
michael@0 10445 718787259,
michael@0 10446 -343485551
michael@0 10447 ]);
michael@0 10448 function hashBytesTo32BitsMD5(data, offset, length) {
michael@0 10449 var r = _md5R;
michael@0 10450 var k = _md5K;
michael@0 10451 var h0 = 1732584193, h1 = -271733879, h2 = -1732584194, h3 = 271733878;
michael@0 10452 var paddedLength = length + 72 & ~63;
michael@0 10453 var padded = new Uint8Array(paddedLength);
michael@0 10454 var i, j, n;
michael@0 10455 for (i = 0; i < length; ++i) {
michael@0 10456 padded[i] = data[offset++];
michael@0 10457 }
michael@0 10458 padded[i++] = 128;
michael@0 10459 n = paddedLength - 8;
michael@0 10460 while (i < n) {
michael@0 10461 padded[i++] = 0;
michael@0 10462 }
michael@0 10463 padded[i++] = length << 3 & 255;
michael@0 10464 padded[i++] = length >> 5 & 255;
michael@0 10465 padded[i++] = length >> 13 & 255;
michael@0 10466 padded[i++] = length >> 21 & 255;
michael@0 10467 padded[i++] = length >>> 29 & 255;
michael@0 10468 padded[i++] = 0;
michael@0 10469 padded[i++] = 0;
michael@0 10470 padded[i++] = 0;
michael@0 10471 var w = new Int32Array(16);
michael@0 10472 for (i = 0; i < paddedLength;) {
michael@0 10473 for (j = 0; j < 16; ++j, i += 4) {
michael@0 10474 w[j] = padded[i] | padded[i + 1] << 8 | padded[i + 2] << 16 | padded[i + 3] << 24;
michael@0 10475 }
michael@0 10476 var a = h0, b = h1, c = h2, d = h3, f, g;
michael@0 10477 for (j = 0; j < 64; ++j) {
michael@0 10478 if (j < 16) {
michael@0 10479 f = b & c | ~b & d;
michael@0 10480 g = j;
michael@0 10481 } else if (j < 32) {
michael@0 10482 f = d & b | ~d & c;
michael@0 10483 g = 5 * j + 1 & 15;
michael@0 10484 } else if (j < 48) {
michael@0 10485 f = b ^ c ^ d;
michael@0 10486 g = 3 * j + 5 & 15;
michael@0 10487 } else {
michael@0 10488 f = c ^ (b | ~d);
michael@0 10489 g = 7 * j & 15;
michael@0 10490 }
michael@0 10491 var tmp = d, rotateArg = a + f + k[j] + w[g] | 0, rotate = r[j];
michael@0 10492 d = c;
michael@0 10493 c = b;
michael@0 10494 b = b + (rotateArg << rotate | rotateArg >>> 32 - rotate) | 0;
michael@0 10495 a = tmp;
michael@0 10496 }
michael@0 10497 h0 = h0 + a | 0;
michael@0 10498 h1 = h1 + b | 0;
michael@0 10499 h2 = h2 + c | 0;
michael@0 10500 h3 = h3 + d | 0;
michael@0 10501 }
michael@0 10502 return h0;
michael@0 10503 }
michael@0 10504 HashUtilities.hashBytesTo32BitsMD5 = hashBytesTo32BitsMD5;
michael@0 10505 function hashBytesTo32BitsAdler(data, offset, length) {
michael@0 10506 var a = 1;
michael@0 10507 var b = 0;
michael@0 10508 var end = offset + length;
michael@0 10509 for (var i = offset; i < end; ++i) {
michael@0 10510 a = (a + (data[i] & 255)) % 65521;
michael@0 10511 b = (b + a) % 65521;
michael@0 10512 }
michael@0 10513 return b << 16 | a;
michael@0 10514 }
michael@0 10515 HashUtilities.hashBytesTo32BitsAdler = hashBytesTo32BitsAdler;
michael@0 10516 }(Shumway.HashUtilities || (Shumway.HashUtilities = {})));
michael@0 10517 var HashUtilities = Shumway.HashUtilities;
michael@0 10518 (function (IntegerUtilities) {
michael@0 10519 function bitCount(i) {
michael@0 10520 i = i - (i >> 1 & 1431655765);
michael@0 10521 i = (i & 858993459) + (i >> 2 & 858993459);
michael@0 10522 return (i + (i >> 4) & 252645135) * 16843009 >> 24;
michael@0 10523 }
michael@0 10524 IntegerUtilities.bitCount = bitCount;
michael@0 10525 function ones(i) {
michael@0 10526 i = i - (i >> 1 & 1431655765);
michael@0 10527 i = (i & 858993459) + (i >> 2 & 858993459);
michael@0 10528 return (i + (i >> 4) & 252645135) * 16843009 >> 24;
michael@0 10529 }
michael@0 10530 IntegerUtilities.ones = ones;
michael@0 10531 function leadingZeros(i) {
michael@0 10532 i |= i >> 1;
michael@0 10533 i |= i >> 2;
michael@0 10534 i |= i >> 4;
michael@0 10535 i |= i >> 8;
michael@0 10536 i |= i >> 16;
michael@0 10537 return 32 - IntegerUtilities.ones(i);
michael@0 10538 }
michael@0 10539 IntegerUtilities.leadingZeros = leadingZeros;
michael@0 10540 function trailingZeros(i) {
michael@0 10541 return IntegerUtilities.ones((i & -i) - 1);
michael@0 10542 }
michael@0 10543 IntegerUtilities.trailingZeros = trailingZeros;
michael@0 10544 function getFlags(i, flags) {
michael@0 10545 var str = '';
michael@0 10546 for (var i = 0; i < flags.length; i++) {
michael@0 10547 if (i & 1 << i) {
michael@0 10548 str += flags[i] + ' ';
michael@0 10549 }
michael@0 10550 }
michael@0 10551 if (str.length === 0) {
michael@0 10552 return '';
michael@0 10553 }
michael@0 10554 return str.trim();
michael@0 10555 }
michael@0 10556 IntegerUtilities.getFlags = getFlags;
michael@0 10557 function isPowerOfTwo(x) {
michael@0 10558 return x && (x & x - 1) === 0;
michael@0 10559 }
michael@0 10560 IntegerUtilities.isPowerOfTwo = isPowerOfTwo;
michael@0 10561 }(Shumway.IntegerUtilities || (Shumway.IntegerUtilities = {})));
michael@0 10562 var IntegerUtilities = Shumway.IntegerUtilities;
michael@0 10563 var IndentingWriter = function () {
michael@0 10564 function IndentingWriter(suppressOutput, outFn) {
michael@0 10565 if (typeof suppressOutput === 'undefined') {
michael@0 10566 suppressOutput = false;
michael@0 10567 }
michael@0 10568 this._tab = ' ';
michael@0 10569 this._padding = '';
michael@0 10570 this._suppressOutput = suppressOutput;
michael@0 10571 this._out = outFn || IndentingWriter._consoleOutFn;
michael@0 10572 }
michael@0 10573 IndentingWriter.prototype.writeLn = function (str) {
michael@0 10574 if (!this._suppressOutput) {
michael@0 10575 this._out(this._padding + str);
michael@0 10576 }
michael@0 10577 };
michael@0 10578 IndentingWriter.prototype.writeLns = function (str) {
michael@0 10579 var lines = str.split('\n');
michael@0 10580 for (var i = 0; i < lines.length; i++) {
michael@0 10581 this.writeLn(lines[i]);
michael@0 10582 }
michael@0 10583 };
michael@0 10584 IndentingWriter.prototype.debugLn = function (str) {
michael@0 10585 this.colorLn(IndentingWriter.PURPLE, str);
michael@0 10586 };
michael@0 10587 IndentingWriter.prototype.yellowLn = function (str) {
michael@0 10588 this.colorLn(IndentingWriter.YELLOW, str);
michael@0 10589 };
michael@0 10590 IndentingWriter.prototype.greenLn = function (str) {
michael@0 10591 this.colorLn(IndentingWriter.GREEN, str);
michael@0 10592 };
michael@0 10593 IndentingWriter.prototype.redLn = function (str) {
michael@0 10594 this.colorLn(IndentingWriter.RED, str);
michael@0 10595 };
michael@0 10596 IndentingWriter.prototype.colorLn = function (color, str) {
michael@0 10597 if (!this._suppressOutput) {
michael@0 10598 if (!inBrowser) {
michael@0 10599 this._out(this._padding + color + str + IndentingWriter.ENDC);
michael@0 10600 } else {
michael@0 10601 this._out(this._padding + str);
michael@0 10602 }
michael@0 10603 }
michael@0 10604 };
michael@0 10605 IndentingWriter.prototype.enter = function (str) {
michael@0 10606 if (!this._suppressOutput) {
michael@0 10607 this._out(this._padding + str);
michael@0 10608 }
michael@0 10609 this.indent();
michael@0 10610 };
michael@0 10611 IndentingWriter.prototype.leaveAndEnter = function (str) {
michael@0 10612 this.leave(str);
michael@0 10613 this.indent();
michael@0 10614 };
michael@0 10615 IndentingWriter.prototype.leave = function (str) {
michael@0 10616 this.outdent();
michael@0 10617 if (!this._suppressOutput) {
michael@0 10618 this._out(this._padding + str);
michael@0 10619 }
michael@0 10620 };
michael@0 10621 IndentingWriter.prototype.indent = function () {
michael@0 10622 this._padding += this._tab;
michael@0 10623 };
michael@0 10624 IndentingWriter.prototype.outdent = function () {
michael@0 10625 if (this._padding.length > 0) {
michael@0 10626 this._padding = this._padding.substring(0, this._padding.length - this._tab.length);
michael@0 10627 }
michael@0 10628 };
michael@0 10629 IndentingWriter.prototype.writeArray = function (arr, detailed, noNumbers) {
michael@0 10630 if (typeof detailed === 'undefined') {
michael@0 10631 detailed = false;
michael@0 10632 }
michael@0 10633 if (typeof noNumbers === 'undefined') {
michael@0 10634 noNumbers = false;
michael@0 10635 }
michael@0 10636 detailed = detailed || false;
michael@0 10637 for (var i = 0, j = arr.length; i < j; i++) {
michael@0 10638 var prefix = '';
michael@0 10639 if (detailed) {
michael@0 10640 if (arr[i] === null) {
michael@0 10641 prefix = 'null';
michael@0 10642 } else if (arr[i] === undefined) {
michael@0 10643 prefix = 'undefined';
michael@0 10644 } else {
michael@0 10645 prefix = arr[i].constructor.name;
michael@0 10646 }
michael@0 10647 prefix += ' ';
michael@0 10648 }
michael@0 10649 var number = noNumbers ? '' : ('' + i).padRight(' ', 4);
michael@0 10650 this.writeLn(number + prefix + arr[i]);
michael@0 10651 }
michael@0 10652 };
michael@0 10653 IndentingWriter.PURPLE = '\x1b[94m';
michael@0 10654 IndentingWriter.YELLOW = '\x1b[93m';
michael@0 10655 IndentingWriter.GREEN = '\x1b[92m';
michael@0 10656 IndentingWriter.RED = '\x1b[91m';
michael@0 10657 IndentingWriter.ENDC = '\x1b[0m';
michael@0 10658 IndentingWriter._consoleOutFn = inBrowser ? console.info.bind(console) : print;
michael@0 10659 return IndentingWriter;
michael@0 10660 }();
michael@0 10661 Shumway.IndentingWriter = IndentingWriter;
michael@0 10662 var SortedListNode = function () {
michael@0 10663 function SortedListNode(value, next) {
michael@0 10664 this.value = value;
michael@0 10665 this.next = next;
michael@0 10666 }
michael@0 10667 return SortedListNode;
michael@0 10668 }();
michael@0 10669 var SortedList = function () {
michael@0 10670 function SortedList(compare) {
michael@0 10671 true;
michael@0 10672 this._compare = compare;
michael@0 10673 this._head = null;
michael@0 10674 this._length = 0;
michael@0 10675 }
michael@0 10676 SortedList.prototype.push = function (value) {
michael@0 10677 true;
michael@0 10678 this._length++;
michael@0 10679 if (!this._head) {
michael@0 10680 this._head = new SortedListNode(value, null);
michael@0 10681 return;
michael@0 10682 }
michael@0 10683 var curr = this._head;
michael@0 10684 var prev = null;
michael@0 10685 var node = new SortedListNode(value, null);
michael@0 10686 var compare = this._compare;
michael@0 10687 while (curr) {
michael@0 10688 if (compare(curr.value, node.value) > 0) {
michael@0 10689 if (prev) {
michael@0 10690 node.next = curr;
michael@0 10691 prev.next = node;
michael@0 10692 } else {
michael@0 10693 node.next = this._head;
michael@0 10694 this._head = node;
michael@0 10695 }
michael@0 10696 return;
michael@0 10697 }
michael@0 10698 prev = curr;
michael@0 10699 curr = curr.next;
michael@0 10700 }
michael@0 10701 prev.next = node;
michael@0 10702 };
michael@0 10703 SortedList.prototype.forEach = function (visitor) {
michael@0 10704 var curr = this._head;
michael@0 10705 var last = null;
michael@0 10706 while (curr) {
michael@0 10707 var result = visitor(curr.value);
michael@0 10708 if (result === SortedList.RETURN) {
michael@0 10709 return;
michael@0 10710 } else if (result === SortedList.DELETE) {
michael@0 10711 if (!last) {
michael@0 10712 curr = this._head = this._head.next;
michael@0 10713 } else {
michael@0 10714 curr = last.next = curr.next;
michael@0 10715 }
michael@0 10716 } else {
michael@0 10717 last = curr;
michael@0 10718 curr = curr.next;
michael@0 10719 }
michael@0 10720 }
michael@0 10721 };
michael@0 10722 SortedList.prototype.isEmpty = function () {
michael@0 10723 return !this._head;
michael@0 10724 };
michael@0 10725 SortedList.prototype.pop = function () {
michael@0 10726 if (!this._head) {
michael@0 10727 return undefined;
michael@0 10728 }
michael@0 10729 this._length--;
michael@0 10730 var ret = this._head;
michael@0 10731 this._head = this._head.next;
michael@0 10732 return ret.value;
michael@0 10733 };
michael@0 10734 SortedList.prototype.contains = function (value) {
michael@0 10735 var curr = this._head;
michael@0 10736 while (curr) {
michael@0 10737 if (curr.value === value) {
michael@0 10738 return true;
michael@0 10739 }
michael@0 10740 curr = curr.next;
michael@0 10741 }
michael@0 10742 return false;
michael@0 10743 };
michael@0 10744 SortedList.prototype.toString = function () {
michael@0 10745 var str = '[';
michael@0 10746 var curr = this._head;
michael@0 10747 while (curr) {
michael@0 10748 str += curr.value.toString();
michael@0 10749 curr = curr.next;
michael@0 10750 if (curr) {
michael@0 10751 str += ',';
michael@0 10752 }
michael@0 10753 }
michael@0 10754 str += ']';
michael@0 10755 return str;
michael@0 10756 };
michael@0 10757 SortedList.RETURN = 1;
michael@0 10758 SortedList.DELETE = 2;
michael@0 10759 return SortedList;
michael@0 10760 }();
michael@0 10761 Shumway.SortedList = SortedList;
michael@0 10762 var CIRCULAR_BUFFER_MASK = 4095;
michael@0 10763 var CIRCULAR_BUFFER_SIZE = 4096;
michael@0 10764 var CircularBuffer = function () {
michael@0 10765 function CircularBuffer(Type) {
michael@0 10766 this.index = 0;
michael@0 10767 this.start = 0;
michael@0 10768 this.array = new Type(CIRCULAR_BUFFER_SIZE);
michael@0 10769 }
michael@0 10770 CircularBuffer.prototype.get = function (i) {
michael@0 10771 return this.array[i];
michael@0 10772 };
michael@0 10773 CircularBuffer.prototype.forEachInReverse = function (visitor) {
michael@0 10774 if (this.isEmpty()) {
michael@0 10775 return;
michael@0 10776 }
michael@0 10777 var i = this.index === 0 ? CIRCULAR_BUFFER_SIZE - 1 : this.index - 1;
michael@0 10778 while (i !== this.start) {
michael@0 10779 if (visitor(this.array[i], i)) {
michael@0 10780 break;
michael@0 10781 }
michael@0 10782 i = i === 0 ? CIRCULAR_BUFFER_SIZE - 1 : i - 1;
michael@0 10783 }
michael@0 10784 };
michael@0 10785 CircularBuffer.prototype.write = function (value) {
michael@0 10786 this.array[this.index] = value;
michael@0 10787 this.index = this.index + 1 & CIRCULAR_BUFFER_MASK;
michael@0 10788 if (this.index === this.start) {
michael@0 10789 this.start = this.start + 1 & CIRCULAR_BUFFER_MASK;
michael@0 10790 }
michael@0 10791 };
michael@0 10792 CircularBuffer.prototype.isFull = function () {
michael@0 10793 return (this.index + 1 & CIRCULAR_BUFFER_MASK) === this.start;
michael@0 10794 };
michael@0 10795 CircularBuffer.prototype.isEmpty = function () {
michael@0 10796 return this.index === this.start;
michael@0 10797 };
michael@0 10798 return CircularBuffer;
michael@0 10799 }();
michael@0 10800 Shumway.CircularBuffer = CircularBuffer;
michael@0 10801 }(Shumway || (Shumway = {})));
michael@0 10802 var assert = Shumway.Debug.assert;
michael@0 10803 var IndentingWriter = Shumway.IndentingWriter;
michael@0 10804 var assert = Shumway.Debug.assert;
michael@0 10805 var $DEBUG;
michael@0 10806 var release = true;
michael@0 10807 var c4CoerceNonPrimitiveParameters = false;
michael@0 10808 var c4CoerceNonPrimitive = false;
michael@0 10809 var c4AsTypeLate = true;
michael@0 10810 var error = Shumway.Debug.error;
michael@0 10811 var assertNotImplemented = Shumway.Debug.assertNotImplemented;
michael@0 10812 var warning = Shumway.Debug.warning;
michael@0 10813 var notImplemented = Shumway.Debug.notImplemented;
michael@0 10814 var somewhatImplemented = Shumway.Debug.somewhatImplemented;
michael@0 10815 var unexpected = Shumway.Debug.unexpected;
michael@0 10816 var defineReadOnlyProperty = Shumway.ObjectUtilities.defineReadOnlyProperty;
michael@0 10817 var createEmptyObject = Shumway.ObjectUtilities.createEmptyObject;
michael@0 10818 var makeForwardingGetter = Shumway.FunctionUtilities.makeForwardingGetter;
michael@0 10819 var makeForwardingSetter = Shumway.FunctionUtilities.makeForwardingSetter;
michael@0 10820 var bindSafely = Shumway.FunctionUtilities.bindSafely;
michael@0 10821 var cloneObject = Shumway.ObjectUtilities.cloneObject;
michael@0 10822 var copyProperties = Shumway.ObjectUtilities.copyProperties;
michael@0 10823 var toSafeString = Shumway.StringUtilities.toSafeString;
michael@0 10824 var toSafeArrayString = Shumway.StringUtilities.toSafeArrayString;
michael@0 10825 var getLatestGetterOrSetterPropertyDescriptor = Shumway.ObjectUtilities.getLatestGetterOrSetterPropertyDescriptor;
michael@0 10826 var defineNonEnumerableGetterOrSetter = Shumway.ObjectUtilities.defineNonEnumerableGetterOrSetter;
michael@0 10827 var defineNonEnumerableGetter = Shumway.ObjectUtilities.defineNonEnumerableGetter;
michael@0 10828 var defineNonEnumerableSetter = Shumway.ObjectUtilities.defineNonEnumerableSetter;
michael@0 10829 var defineNonEnumerableProperty = Shumway.ObjectUtilities.defineNonEnumerableProperty;
michael@0 10830 var defineNonEnumerableForwardingProperty = Shumway.ObjectUtilities.defineNonEnumerableForwardingProperty;
michael@0 10831 var defineNewNonEnumerableProperty = Shumway.ObjectUtilities.defineNewNonEnumerableProperty;
michael@0 10832 var isNumeric = Shumway.isNumeric;
michael@0 10833 var isNullOrUndefined = Shumway.isNullOrUndefined;
michael@0 10834 var isPowerOfTwo = Shumway.IntegerUtilities.isPowerOfTwo;
michael@0 10835 function time(fn, count) {
michael@0 10836 var start = performance.now();
michael@0 10837 for (var i = 0; i < count; i++) {
michael@0 10838 fn();
michael@0 10839 }
michael@0 10840 var time = (performance.now() - start) / count;
michael@0 10841 console.info('Took: ' + time.toFixed(2) + 'ms.');
michael@0 10842 return time;
michael@0 10843 }
michael@0 10844 function clamp(x, min, max) {
michael@0 10845 if (x < min) {
michael@0 10846 return min;
michael@0 10847 } else if (x > max) {
michael@0 10848 return max;
michael@0 10849 }
michael@0 10850 return x;
michael@0 10851 }
michael@0 10852 var fromCharCodeArray = Shumway.StringUtilities.fromCharCodeArray;
michael@0 10853 function hasOwnProperty(object, name) {
michael@0 10854 return Object.prototype.hasOwnProperty.call(object, name);
michael@0 10855 }
michael@0 10856 var toKeyValueArray = Shumway.ObjectUtilities.toKeyValueArray;
michael@0 10857 var boxValue = Shumway.ObjectUtilities.boxValue;
michael@0 10858 function isObject(value) {
michael@0 10859 return typeof value === 'object' || typeof value === 'function';
michael@0 10860 }
michael@0 10861 function isString(value) {
michael@0 10862 return typeof value === 'string';
michael@0 10863 }
michael@0 10864 function isFunction(value) {
michael@0 10865 return typeof value === 'function';
michael@0 10866 }
michael@0 10867 function isNumber(value) {
michael@0 10868 return typeof value === 'number';
michael@0 10869 }
michael@0 10870 function toNumber(x) {
michael@0 10871 return +x;
michael@0 10872 }
michael@0 10873 function setBitFlags(flags, flag, value) {
michael@0 10874 return value ? flags | flag : flags & ~flag;
michael@0 10875 }
michael@0 10876 function getBitFlags(flags, flag) {
michael@0 10877 return !(!(flags & flag));
michael@0 10878 }
michael@0 10879 (function () {
michael@0 10880 function extendBuiltin(proto, prop, f) {
michael@0 10881 if (!proto[prop]) {
michael@0 10882 Object.defineProperty(proto, prop, {
michael@0 10883 value: f,
michael@0 10884 writable: true,
michael@0 10885 configurable: true,
michael@0 10886 enumerable: false
michael@0 10887 });
michael@0 10888 }
michael@0 10889 }
michael@0 10890 var Sp = String.prototype;
michael@0 10891 function removeColors(s) {
michael@0 10892 return s.replace(/\033\[[0-9]*m/g, '');
michael@0 10893 }
michael@0 10894 extendBuiltin(Sp, 'padRight', function (c, n) {
michael@0 10895 var str = this;
michael@0 10896 var length = removeColors(str).length;
michael@0 10897 if (!c || length >= n) {
michael@0 10898 return str;
michael@0 10899 }
michael@0 10900 var max = (n - length) / c.length;
michael@0 10901 for (var i = 0; i < max; i++) {
michael@0 10902 str += c;
michael@0 10903 }
michael@0 10904 return str;
michael@0 10905 });
michael@0 10906 extendBuiltin(Sp, 'padLeft', function (c, n) {
michael@0 10907 var str = this;
michael@0 10908 var length = str.length;
michael@0 10909 if (!c || length >= n) {
michael@0 10910 return str;
michael@0 10911 }
michael@0 10912 var max = (n - length) / c.length;
michael@0 10913 for (var i = 0; i < max; i++) {
michael@0 10914 str = c + str;
michael@0 10915 }
michael@0 10916 return str;
michael@0 10917 });
michael@0 10918 extendBuiltin(Sp, 'trim', function () {
michael@0 10919 return this.replace(/^\s+|\s+$/g, '');
michael@0 10920 });
michael@0 10921 extendBuiltin(Sp, 'endsWith', function (str) {
michael@0 10922 return this.indexOf(str, this.length - str.length) !== -1;
michael@0 10923 });
michael@0 10924 var Ap = Array.prototype;
michael@0 10925 extendBuiltin(Ap, 'popMany', function (count) {
michael@0 10926 true;
michael@0 10927 var start = this.length - count;
michael@0 10928 var res = this.slice(start, this.length);
michael@0 10929 this.splice(start, count);
michael@0 10930 return res;
michael@0 10931 });
michael@0 10932 extendBuiltin(Ap, 'pushMany', function (array) {
michael@0 10933 for (var i = 0; i < array.length; i++) {
michael@0 10934 this.push(array[i]);
michael@0 10935 }
michael@0 10936 });
michael@0 10937 extendBuiltin(Ap, 'clone', function () {
michael@0 10938 return this.slice(0);
michael@0 10939 });
michael@0 10940 extendBuiltin(Ap, 'first', function () {
michael@0 10941 true;
michael@0 10942 return this[0];
michael@0 10943 });
michael@0 10944 extendBuiltin(Ap, 'last', function () {
michael@0 10945 true;
michael@0 10946 return this[this.length - 1];
michael@0 10947 });
michael@0 10948 extendBuiltin(Ap, 'peek', function () {
michael@0 10949 true;
michael@0 10950 return this[this.length - 1];
michael@0 10951 });
michael@0 10952 extendBuiltin(Ap, 'empty', function () {
michael@0 10953 return this.length === 0;
michael@0 10954 });
michael@0 10955 extendBuiltin(Ap, 'pushUnique', function (v) {
michael@0 10956 for (var i = 0, j = this.length; i < j; i++) {
michael@0 10957 if (this[i] === v) {
michael@0 10958 return;
michael@0 10959 }
michael@0 10960 }
michael@0 10961 this.push(v);
michael@0 10962 });
michael@0 10963 var uniquesMap;
michael@0 10964 if (typeof Map !== 'undefined' && (uniquesMap = new Map()).clear) {
michael@0 10965 extendBuiltin(Ap, 'unique', function () {
michael@0 10966 var unique = [];
michael@0 10967 for (var i = 0; i < this.length; i++) {
michael@0 10968 if (uniquesMap.has(this[i])) {
michael@0 10969 continue;
michael@0 10970 }
michael@0 10971 unique.push(this[i]);
michael@0 10972 uniquesMap.set(this[i], true);
michael@0 10973 }
michael@0 10974 uniquesMap.clear();
michael@0 10975 return unique;
michael@0 10976 });
michael@0 10977 } else {
michael@0 10978 extendBuiltin(Ap, 'unique', function () {
michael@0 10979 var unique = [];
michael@0 10980 for (var i = 0; i < this.length; i++) {
michael@0 10981 unique.pushUnique(this[i]);
michael@0 10982 }
michael@0 10983 return unique;
michael@0 10984 });
michael@0 10985 }
michael@0 10986 extendBuiltin(Ap, 'replace', function (x, y) {
michael@0 10987 if (x === y) {
michael@0 10988 return 0;
michael@0 10989 }
michael@0 10990 var count = 0;
michael@0 10991 for (var i = 0; i < this.length; i++) {
michael@0 10992 if (this[i] === x) {
michael@0 10993 this[i] = y;
michael@0 10994 count++;
michael@0 10995 }
michael@0 10996 }
michael@0 10997 return count;
michael@0 10998 });
michael@0 10999 extendBuiltin(Ap, 'count', function (x) {
michael@0 11000 var count = 0;
michael@0 11001 for (var i = 0; i < this.length; i++) {
michael@0 11002 if (this[i] === x) {
michael@0 11003 count++;
michael@0 11004 }
michael@0 11005 }
michael@0 11006 return count;
michael@0 11007 });
michael@0 11008 extendBuiltin(Ap, 'notEmpty', function () {
michael@0 11009 return this.length > 0;
michael@0 11010 });
michael@0 11011 extendBuiltin(Ap, 'contains', function (val) {
michael@0 11012 return this.indexOf(val) >= 0;
michael@0 11013 });
michael@0 11014 extendBuiltin(Ap, 'top', function () {
michael@0 11015 return this.length && this[this.length - 1];
michael@0 11016 });
michael@0 11017 extendBuiltin(Ap, 'mapWithIndex', function (fn) {
michael@0 11018 var arr = [];
michael@0 11019 for (var i = 0; i < this.length; i++) {
michael@0 11020 arr.push(fn(this[i], i));
michael@0 11021 }
michael@0 11022 return arr;
michael@0 11023 });
michael@0 11024 }());
michael@0 11025 var utf8decode = Shumway.StringUtilities.utf8decode;
michael@0 11026 var utf8encode = Shumway.StringUtilities.utf8encode;
michael@0 11027 var escapeString = Shumway.StringUtilities.escapeString;
michael@0 11028 var bitCount = Shumway.IntegerUtilities.bitCount;
michael@0 11029 var ones = Shumway.IntegerUtilities.ones;
michael@0 11030 var leadingZeros = Shumway.IntegerUtilities.leadingZeros;
michael@0 11031 var trailingZeros = Shumway.IntegerUtilities.trailingZeros;
michael@0 11032 var getFlags = Shumway.IntegerUtilities.getFlags;
michael@0 11033 function BitSetFunctor(length) {
michael@0 11034 var ADDRESS_BITS_PER_WORD = 5;
michael@0 11035 var BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD;
michael@0 11036 var BIT_INDEX_MASK = BITS_PER_WORD - 1;
michael@0 11037 var SIZE = length + (BITS_PER_WORD - 1) >> ADDRESS_BITS_PER_WORD << ADDRESS_BITS_PER_WORD;
michael@0 11038 function BitSet() {
michael@0 11039 this.count = 0;
michael@0 11040 this.dirty = 0;
michael@0 11041 this.size = SIZE;
michael@0 11042 this.bits = new Uint32Array(SIZE >> ADDRESS_BITS_PER_WORD);
michael@0 11043 }
michael@0 11044 function BitSetS() {
michael@0 11045 this.count = 0;
michael@0 11046 this.dirty = 0;
michael@0 11047 this.size = SIZE;
michael@0 11048 this.bits = 0;
michael@0 11049 }
michael@0 11050 var singleword = SIZE >> ADDRESS_BITS_PER_WORD === 1;
michael@0 11051 var Ctor = singleword ? BitSetS : BitSet;
michael@0 11052 Ctor.ADDRESS_BITS_PER_WORD = ADDRESS_BITS_PER_WORD;
michael@0 11053 Ctor.BITS_PER_WORD = BITS_PER_WORD;
michael@0 11054 Ctor.BIT_INDEX_MASK = BIT_INDEX_MASK;
michael@0 11055 Ctor.singleword = singleword;
michael@0 11056 BitSet.prototype = {
michael@0 11057 recount: function recount() {
michael@0 11058 if (!this.dirty) {
michael@0 11059 return;
michael@0 11060 }
michael@0 11061 var bits = this.bits;
michael@0 11062 var c = 0;
michael@0 11063 for (var i = 0, j = bits.length; i < j; i++) {
michael@0 11064 var v = bits[i];
michael@0 11065 v = v - (v >> 1 & 1431655765);
michael@0 11066 v = (v & 858993459) + (v >> 2 & 858993459);
michael@0 11067 c += (v + (v >> 4) & 252645135) * 16843009 >> 24;
michael@0 11068 }
michael@0 11069 this.count = c;
michael@0 11070 this.dirty = 0;
michael@0 11071 },
michael@0 11072 set: function set(i) {
michael@0 11073 var n = i >> ADDRESS_BITS_PER_WORD;
michael@0 11074 var old = this.bits[n];
michael@0 11075 var b = old | 1 << (i & BIT_INDEX_MASK);
michael@0 11076 this.bits[n] = b;
michael@0 11077 this.dirty |= old ^ b;
michael@0 11078 },
michael@0 11079 setAll: function setAll() {
michael@0 11080 var bits = this.bits;
michael@0 11081 for (var i = 0, j = bits.length; i < j; i++) {
michael@0 11082 bits[i] = 4294967295;
michael@0 11083 }
michael@0 11084 this.count = this.size;
michael@0 11085 this.dirty = 0;
michael@0 11086 },
michael@0 11087 assign: function assign(set) {
michael@0 11088 this.count = set.count;
michael@0 11089 this.dirty = set.dirty;
michael@0 11090 this.size = set.size;
michael@0 11091 for (var i = 0, j = this.bits.length; i < j; i++) {
michael@0 11092 this.bits[i] = set.bits[i];
michael@0 11093 }
michael@0 11094 },
michael@0 11095 clear: function clear(i) {
michael@0 11096 var n = i >> ADDRESS_BITS_PER_WORD;
michael@0 11097 var old = this.bits[n];
michael@0 11098 var b = old & ~(1 << (i & BIT_INDEX_MASK));
michael@0 11099 this.bits[n] = b;
michael@0 11100 this.dirty |= old ^ b;
michael@0 11101 },
michael@0 11102 get: function get(i) {
michael@0 11103 var word = this.bits[i >> ADDRESS_BITS_PER_WORD];
michael@0 11104 return (word & 1 << (i & BIT_INDEX_MASK)) !== 0;
michael@0 11105 },
michael@0 11106 clearAll: function clearAll() {
michael@0 11107 var bits = this.bits;
michael@0 11108 for (var i = 0, j = bits.length; i < j; i++) {
michael@0 11109 bits[i] = 0;
michael@0 11110 }
michael@0 11111 this.count = 0;
michael@0 11112 this.dirty = 0;
michael@0 11113 },
michael@0 11114 _union: function _union(other) {
michael@0 11115 var dirty = this.dirty;
michael@0 11116 var bits = this.bits;
michael@0 11117 var otherBits = other.bits;
michael@0 11118 for (var i = 0, j = bits.length; i < j; i++) {
michael@0 11119 var old = bits[i];
michael@0 11120 var b = old | otherBits[i];
michael@0 11121 bits[i] = b;
michael@0 11122 dirty |= old ^ b;
michael@0 11123 }
michael@0 11124 this.dirty = dirty;
michael@0 11125 },
michael@0 11126 intersect: function intersect(other) {
michael@0 11127 var dirty = this.dirty;
michael@0 11128 var bits = this.bits;
michael@0 11129 var otherBits = other.bits;
michael@0 11130 for (var i = 0, j = bits.length; i < j; i++) {
michael@0 11131 var old = bits[i];
michael@0 11132 var b = old & otherBits[i];
michael@0 11133 bits[i] = b;
michael@0 11134 dirty |= old ^ b;
michael@0 11135 }
michael@0 11136 this.dirty = dirty;
michael@0 11137 },
michael@0 11138 subtract: function subtract(other) {
michael@0 11139 var dirty = this.dirty;
michael@0 11140 var bits = this.bits;
michael@0 11141 var otherBits = other.bits;
michael@0 11142 for (var i = 0, j = bits.length; i < j; i++) {
michael@0 11143 var old = bits[i];
michael@0 11144 var b = old & ~otherBits[i];
michael@0 11145 bits[i] = b;
michael@0 11146 dirty |= old ^ b;
michael@0 11147 }
michael@0 11148 this.dirty = dirty;
michael@0 11149 },
michael@0 11150 negate: function negate() {
michael@0 11151 var dirty = this.dirty;
michael@0 11152 var bits = this.bits;
michael@0 11153 for (var i = 0, j = bits.length; i < j; i++) {
michael@0 11154 var old = bits[i];
michael@0 11155 var b = ~old;
michael@0 11156 bits[i] = b;
michael@0 11157 dirty |= old ^ b;
michael@0 11158 }
michael@0 11159 this.dirty = dirty;
michael@0 11160 },
michael@0 11161 forEach: function forEach(fn) {
michael@0 11162 true;
michael@0 11163 var bits = this.bits;
michael@0 11164 for (var i = 0, j = bits.length; i < j; i++) {
michael@0 11165 var word = bits[i];
michael@0 11166 if (word) {
michael@0 11167 for (var k = 0; k < BITS_PER_WORD; k++) {
michael@0 11168 if (word & 1 << k) {
michael@0 11169 fn(i * BITS_PER_WORD + k);
michael@0 11170 }
michael@0 11171 }
michael@0 11172 }
michael@0 11173 }
michael@0 11174 },
michael@0 11175 toArray: function toArray() {
michael@0 11176 var set = [];
michael@0 11177 var bits = this.bits;
michael@0 11178 for (var i = 0, j = bits.length; i < j; i++) {
michael@0 11179 var word = bits[i];
michael@0 11180 if (word) {
michael@0 11181 for (var k = 0; k < BITS_PER_WORD; k++) {
michael@0 11182 if (word & 1 << k) {
michael@0 11183 set.push(i * BITS_PER_WORD + k);
michael@0 11184 }
michael@0 11185 }
michael@0 11186 }
michael@0 11187 }
michael@0 11188 return set;
michael@0 11189 },
michael@0 11190 equals: function equals(other) {
michael@0 11191 if (this.size !== other.size) {
michael@0 11192 return false;
michael@0 11193 }
michael@0 11194 var bits = this.bits;
michael@0 11195 var otherBits = other.bits;
michael@0 11196 for (var i = 0, j = bits.length; i < j; i++) {
michael@0 11197 if (bits[i] !== otherBits[i]) {
michael@0 11198 return false;
michael@0 11199 }
michael@0 11200 }
michael@0 11201 return true;
michael@0 11202 },
michael@0 11203 contains: function contains(other) {
michael@0 11204 if (this.size !== other.size) {
michael@0 11205 return false;
michael@0 11206 }
michael@0 11207 var bits = this.bits;
michael@0 11208 var otherBits = other.bits;
michael@0 11209 for (var i = 0, j = bits.length; i < j; i++) {
michael@0 11210 if ((bits[i] | otherBits[i]) !== bits[i]) {
michael@0 11211 return false;
michael@0 11212 }
michael@0 11213 }
michael@0 11214 return true;
michael@0 11215 },
michael@0 11216 toBitString: function toBitString(on, off) {
michael@0 11217 on = on || '1';
michael@0 11218 off = off || '0';
michael@0 11219 var str = '';
michael@0 11220 for (var i = 0; i < length; i++) {
michael@0 11221 str += this.get(i) ? on : off;
michael@0 11222 }
michael@0 11223 return str;
michael@0 11224 },
michael@0 11225 length: length,
michael@0 11226 toString: function toString(names) {
michael@0 11227 var set = [];
michael@0 11228 for (var i = 0; i < length; i++) {
michael@0 11229 if (this.get(i)) {
michael@0 11230 set.push(names ? names[i] : i);
michael@0 11231 }
michael@0 11232 }
michael@0 11233 return set.join(', ');
michael@0 11234 },
michael@0 11235 isEmpty: function isEmpty() {
michael@0 11236 this.recount();
michael@0 11237 return this.count === 0;
michael@0 11238 },
michael@0 11239 clone: function clone() {
michael@0 11240 var set = new BitSet();
michael@0 11241 set._union(this);
michael@0 11242 return set;
michael@0 11243 }
michael@0 11244 };
michael@0 11245 BitSetS.prototype = {
michael@0 11246 recount: function recount() {
michael@0 11247 if (!this.dirty) {
michael@0 11248 return;
michael@0 11249 }
michael@0 11250 var c = 0;
michael@0 11251 var v = this.bits;
michael@0 11252 v = v - (v >> 1 & 1431655765);
michael@0 11253 v = (v & 858993459) + (v >> 2 & 858993459);
michael@0 11254 c += (v + (v >> 4) & 252645135) * 16843009 >> 24;
michael@0 11255 this.count = c;
michael@0 11256 this.dirty = 0;
michael@0 11257 },
michael@0 11258 set: function set(i) {
michael@0 11259 var old = this.bits;
michael@0 11260 var b = old | 1 << (i & BIT_INDEX_MASK);
michael@0 11261 this.bits = b;
michael@0 11262 this.dirty |= old ^ b;
michael@0 11263 },
michael@0 11264 setAll: function setAll() {
michael@0 11265 this.bits = 4294967295;
michael@0 11266 this.count = this.size;
michael@0 11267 this.dirty = 0;
michael@0 11268 },
michael@0 11269 assign: function assign(set) {
michael@0 11270 this.count = set.count;
michael@0 11271 this.dirty = set.dirty;
michael@0 11272 this.size = set.size;
michael@0 11273 this.bits = set.bits;
michael@0 11274 },
michael@0 11275 clear: function clear(i) {
michael@0 11276 var old = this.bits;
michael@0 11277 var b = old & ~(1 << (i & BIT_INDEX_MASK));
michael@0 11278 this.bits = b;
michael@0 11279 this.dirty |= old ^ b;
michael@0 11280 },
michael@0 11281 get: function get(i) {
michael@0 11282 return (this.bits & 1 << (i & BIT_INDEX_MASK)) !== 0;
michael@0 11283 },
michael@0 11284 clearAll: function clearAll() {
michael@0 11285 this.bits = 0;
michael@0 11286 this.count = 0;
michael@0 11287 this.dirty = 0;
michael@0 11288 },
michael@0 11289 _union: function _union(other) {
michael@0 11290 var old = this.bits;
michael@0 11291 var b = old | other.bits;
michael@0 11292 this.bits = b;
michael@0 11293 this.dirty = old ^ b;
michael@0 11294 },
michael@0 11295 intersect: function intersect(other) {
michael@0 11296 var old = this.bits;
michael@0 11297 var b = old & other.bits;
michael@0 11298 this.bits = b;
michael@0 11299 this.dirty = old ^ b;
michael@0 11300 },
michael@0 11301 subtract: function subtract(other) {
michael@0 11302 var old = this.bits;
michael@0 11303 var b = old & ~other.bits;
michael@0 11304 this.bits = b;
michael@0 11305 this.dirty = old ^ b;
michael@0 11306 },
michael@0 11307 negate: function negate() {
michael@0 11308 var old = this.bits;
michael@0 11309 var b = ~old;
michael@0 11310 this.bits = b;
michael@0 11311 this.dirty = old ^ b;
michael@0 11312 },
michael@0 11313 forEach: function forEach(fn) {
michael@0 11314 true;
michael@0 11315 var word = this.bits;
michael@0 11316 if (word) {
michael@0 11317 for (var k = 0; k < BITS_PER_WORD; k++) {
michael@0 11318 if (word & 1 << k) {
michael@0 11319 fn(k);
michael@0 11320 }
michael@0 11321 }
michael@0 11322 }
michael@0 11323 },
michael@0 11324 toArray: function toArray() {
michael@0 11325 var set = [];
michael@0 11326 var word = this.bits;
michael@0 11327 if (word) {
michael@0 11328 for (var k = 0; k < BITS_PER_WORD; k++) {
michael@0 11329 if (word & 1 << k) {
michael@0 11330 set.push(k);
michael@0 11331 }
michael@0 11332 }
michael@0 11333 }
michael@0 11334 return set;
michael@0 11335 },
michael@0 11336 equals: function equals(other) {
michael@0 11337 return this.bits === other.bits;
michael@0 11338 },
michael@0 11339 contains: function contains(other) {
michael@0 11340 var bits = this.bits;
michael@0 11341 return (bits | other.bits) === bits;
michael@0 11342 },
michael@0 11343 isEmpty: function isEmpty() {
michael@0 11344 this.recount();
michael@0 11345 return this.count === 0;
michael@0 11346 },
michael@0 11347 clone: function clone() {
michael@0 11348 var set = new BitSetS();
michael@0 11349 set._union(this);
michael@0 11350 return set;
michael@0 11351 },
michael@0 11352 toBitString: BitSet.prototype.toBitString,
michael@0 11353 toString: BitSet.prototype.toString,
michael@0 11354 length: length
michael@0 11355 };
michael@0 11356 return Ctor;
michael@0 11357 }
michael@0 11358 var Map = function () {
michael@0 11359 function map() {
michael@0 11360 this.elements = {};
michael@0 11361 }
michael@0 11362 map.prototype.set = function set(k, v) {
michael@0 11363 this.elements[k] = v;
michael@0 11364 };
michael@0 11365 map.prototype.get = function get(k) {
michael@0 11366 if (this.has(k)) {
michael@0 11367 return this.elements[k];
michael@0 11368 }
michael@0 11369 return undefined;
michael@0 11370 };
michael@0 11371 map.prototype.has = function has(k) {
michael@0 11372 return Object.prototype.hasOwnProperty.call(this.elements, k);
michael@0 11373 };
michael@0 11374 map.prototype.remove = function remove(k) {
michael@0 11375 if (this.has(k)) {
michael@0 11376 delete this.elements[k];
michael@0 11377 }
michael@0 11378 };
michael@0 11379 return map;
michael@0 11380 }();
michael@0 11381 (function checkWeakMap() {
michael@0 11382 if (typeof this.WeakMap === 'function')
michael@0 11383 return;
michael@0 11384 var id = 0;
michael@0 11385 function WeakMap() {
michael@0 11386 this.id = '$weakmap' + id++;
michael@0 11387 }
michael@0 11388 ;
michael@0 11389 WeakMap.prototype = {
michael@0 11390 has: function (obj) {
michael@0 11391 return obj.hasOwnProperty(this.id);
michael@0 11392 },
michael@0 11393 get: function (obj, defaultValue) {
michael@0 11394 return obj.hasOwnProperty(this.id) ? obj[this.id] : defaultValue;
michael@0 11395 },
michael@0 11396 set: function (obj, value) {
michael@0 11397 Object.defineProperty(obj, this.id, {
michael@0 11398 value: value,
michael@0 11399 enumerable: false,
michael@0 11400 configurable: true
michael@0 11401 });
michael@0 11402 }
michael@0 11403 };
michael@0 11404 this.WeakMap = WeakMap;
michael@0 11405 }());
michael@0 11406 var Callback = function () {
michael@0 11407 function callback() {
michael@0 11408 this.queues = {};
michael@0 11409 }
michael@0 11410 callback.prototype.register = function register(type, callback) {
michael@0 11411 var queue = this.queues[type];
michael@0 11412 if (queue) {
michael@0 11413 if (queue.indexOf(callback) > -1) {
michael@0 11414 return;
michael@0 11415 }
michael@0 11416 } else {
michael@0 11417 queue = this.queues[type] = [];
michael@0 11418 }
michael@0 11419 queue.push(callback);
michael@0 11420 };
michael@0 11421 callback.prototype.unregister = function unregister(type, callback) {
michael@0 11422 var queue = this.queues[type];
michael@0 11423 if (!queue) {
michael@0 11424 return;
michael@0 11425 }
michael@0 11426 var i = queue.indexOf(callback);
michael@0 11427 if (i !== -1) {
michael@0 11428 queue.splice(i, 1);
michael@0 11429 }
michael@0 11430 if (queue.length === 0) {
michael@0 11431 this.queues[type] = null;
michael@0 11432 }
michael@0 11433 };
michael@0 11434 callback.prototype.notify = function notify(type, args) {
michael@0 11435 var queue = this.queues[type];
michael@0 11436 if (!queue) {
michael@0 11437 return;
michael@0 11438 }
michael@0 11439 queue = queue.slice();
michael@0 11440 var args = sliceArguments(arguments, 0);
michael@0 11441 for (var i = 0; i < queue.length; i++) {
michael@0 11442 if (false) {
michael@0 11443 Counter.count('callback(' + type + ').notify');
michael@0 11444 }
michael@0 11445 var callback = queue[i];
michael@0 11446 callback.apply(null, args);
michael@0 11447 }
michael@0 11448 };
michael@0 11449 callback.prototype.notify1 = function notify1(type, value) {
michael@0 11450 var queue = this.queues[type];
michael@0 11451 if (!queue) {
michael@0 11452 return;
michael@0 11453 }
michael@0 11454 queue = queue.slice();
michael@0 11455 for (var i = 0; i < queue.length; i++) {
michael@0 11456 if (false) {
michael@0 11457 Counter.count('callback(' + type + ').notify1');
michael@0 11458 }
michael@0 11459 var callback = queue[i];
michael@0 11460 callback(type, value);
michael@0 11461 }
michael@0 11462 };
michael@0 11463 return callback;
michael@0 11464 }();
michael@0 11465 function lazyClass(holder, name, initialize) {
michael@0 11466 Object.defineProperty(holder, name, {
michael@0 11467 get: function () {
michael@0 11468 var start = performance.now();
michael@0 11469 var value = initialize();
michael@0 11470 print('Initialized Class: ' + name + ' ' + (performance.now() - start).toFixed(4));
michael@0 11471 Object.defineProperty(holder, name, {
michael@0 11472 value: value,
michael@0 11473 writable: true
michael@0 11474 });
michael@0 11475 return value;
michael@0 11476 },
michael@0 11477 configurable: true
michael@0 11478 });
michael@0 11479 }
michael@0 11480 var hashBytesTo32BitsAdler = Shumway.HashUtilities.hashBytesTo32BitsAdler;
michael@0 11481 var hashBytesTo32BitsMD5 = Shumway.HashUtilities.hashBytesTo32BitsMD5;
michael@0 11482 var variableLengthEncodeInt32 = Shumway.StringUtilities.variableLengthEncodeInt32;
michael@0 11483 var fromEncoding = Shumway.StringUtilities.fromEncoding;
michael@0 11484 var variableLengthDecodeIdentifier = Shumway.StringUtilities.variableLengthDecodeInt32;
michael@0 11485 var toEncoding = Shumway.StringUtilities.toEncoding;
michael@0 11486 var Shumway;
michael@0 11487 (function (Shumway) {
michael@0 11488 (function (Options) {
michael@0 11489 var Argument = function () {
michael@0 11490 function Argument(shortName, longName, type, options) {
michael@0 11491 this.shortName = shortName;
michael@0 11492 this.longName = longName;
michael@0 11493 this.type = type;
michael@0 11494 options = options || {};
michael@0 11495 this.positional = options.positional;
michael@0 11496 this.parseFn = options.parse;
michael@0 11497 this.value = options.defaultValue;
michael@0 11498 }
michael@0 11499 Argument.prototype.parse = function (value) {
michael@0 11500 if (this.type === 'boolean') {
michael@0 11501 true;
michael@0 11502 this.value = value;
michael@0 11503 } else if (this.type === 'number') {
michael@0 11504 true;
michael@0 11505 this.value = parseInt(value, 10);
michael@0 11506 } else {
michael@0 11507 this.value = value;
michael@0 11508 }
michael@0 11509 if (this.parseFn) {
michael@0 11510 this.parseFn(this.value);
michael@0 11511 }
michael@0 11512 };
michael@0 11513 return Argument;
michael@0 11514 }();
michael@0 11515 Options.Argument = Argument;
michael@0 11516 var ArgumentParser = function () {
michael@0 11517 function ArgumentParser() {
michael@0 11518 this.args = [];
michael@0 11519 }
michael@0 11520 ArgumentParser.prototype.addArgument = function (shortName, longName, type, options) {
michael@0 11521 var argument = new Argument(shortName, longName, type, options);
michael@0 11522 this.args.push(argument);
michael@0 11523 return argument;
michael@0 11524 };
michael@0 11525 ArgumentParser.prototype.addBoundOption = function (option) {
michael@0 11526 var options = {
michael@0 11527 parse: function (x) {
michael@0 11528 option.value = x;
michael@0 11529 }
michael@0 11530 };
michael@0 11531 this.args.push(new Argument(option.shortName, option.longName, option.type, options));
michael@0 11532 };
michael@0 11533 ArgumentParser.prototype.addBoundOptionSet = function (optionSet) {
michael@0 11534 var self = this;
michael@0 11535 optionSet.options.forEach(function (x) {
michael@0 11536 if (x instanceof OptionSet) {
michael@0 11537 self.addBoundOptionSet(x);
michael@0 11538 } else {
michael@0 11539 true;
michael@0 11540 self.addBoundOption(x);
michael@0 11541 }
michael@0 11542 });
michael@0 11543 };
michael@0 11544 ArgumentParser.prototype.getUsage = function () {
michael@0 11545 var str = '';
michael@0 11546 this.args.forEach(function (x) {
michael@0 11547 if (!x.positional) {
michael@0 11548 str += '[-' + x.shortName + '|--' + x.longName + (x.type === 'boolean' ? '' : ' ' + x.type[0].toUpperCase()) + ']';
michael@0 11549 } else {
michael@0 11550 str += x.longName;
michael@0 11551 }
michael@0 11552 str += ' ';
michael@0 11553 });
michael@0 11554 return str;
michael@0 11555 };
michael@0 11556 ArgumentParser.prototype.parse = function (args) {
michael@0 11557 var nonPositionalArgumentMap = {};
michael@0 11558 var positionalArgumentList = [];
michael@0 11559 this.args.forEach(function (x) {
michael@0 11560 if (x.positional) {
michael@0 11561 positionalArgumentList.push(x);
michael@0 11562 } else {
michael@0 11563 nonPositionalArgumentMap['-' + x.shortName] = x;
michael@0 11564 nonPositionalArgumentMap['--' + x.longName] = x;
michael@0 11565 }
michael@0 11566 });
michael@0 11567 var leftoverArguments = [];
michael@0 11568 while (args.length) {
michael@0 11569 var argString = args.shift();
michael@0 11570 var argument = null, value = argString;
michael@0 11571 if (argString == '--') {
michael@0 11572 leftoverArguments = leftoverArguments.concat(args);
michael@0 11573 break;
michael@0 11574 } else if (argString.slice(0, 1) == '-' || argString.slice(0, 2) == '--') {
michael@0 11575 argument = nonPositionalArgumentMap[argString];
michael@0 11576 true;
michael@0 11577 if (!argument) {
michael@0 11578 continue;
michael@0 11579 }
michael@0 11580 if (argument.type !== 'boolean') {
michael@0 11581 value = args.shift();
michael@0 11582 true;
michael@0 11583 } else {
michael@0 11584 value = true;
michael@0 11585 }
michael@0 11586 } else if (positionalArgumentList.length) {
michael@0 11587 argument = positionalArgumentList.shift();
michael@0 11588 } else {
michael@0 11589 leftoverArguments.push(value);
michael@0 11590 }
michael@0 11591 if (argument) {
michael@0 11592 argument.parse(value);
michael@0 11593 }
michael@0 11594 }
michael@0 11595 true;
michael@0 11596 return leftoverArguments;
michael@0 11597 };
michael@0 11598 return ArgumentParser;
michael@0 11599 }();
michael@0 11600 Options.ArgumentParser = ArgumentParser;
michael@0 11601 var OptionSet = function () {
michael@0 11602 function OptionSet(name) {
michael@0 11603 this.name = name;
michael@0 11604 this.options = [];
michael@0 11605 }
michael@0 11606 OptionSet.prototype.register = function (option) {
michael@0 11607 this.options.push(option);
michael@0 11608 return option;
michael@0 11609 };
michael@0 11610 OptionSet.prototype.trace = function (writer) {
michael@0 11611 writer.enter(this.name + ' {');
michael@0 11612 this.options.forEach(function (option) {
michael@0 11613 option.trace(writer);
michael@0 11614 });
michael@0 11615 writer.leave('}');
michael@0 11616 };
michael@0 11617 return OptionSet;
michael@0 11618 }();
michael@0 11619 Options.OptionSet = OptionSet;
michael@0 11620 var Option = function () {
michael@0 11621 function Option(shortName, longName, type, defaultValue, description) {
michael@0 11622 this.longName = longName;
michael@0 11623 this.shortName = shortName;
michael@0 11624 this.type = type;
michael@0 11625 this.defaultValue = defaultValue;
michael@0 11626 this.value = defaultValue;
michael@0 11627 this.description = description;
michael@0 11628 }
michael@0 11629 Option.prototype.parse = function (value) {
michael@0 11630 this.value = value;
michael@0 11631 };
michael@0 11632 Option.prototype.trace = function (writer) {
michael@0 11633 writer.writeLn(('-' + this.shortName + '|--' + this.longName).padRight(' ', 30) + ' = ' + this.type + ' ' + this.value + ' [' + this.defaultValue + ']' + ' (' + this.description + ')');
michael@0 11634 };
michael@0 11635 return Option;
michael@0 11636 }();
michael@0 11637 Options.Option = Option;
michael@0 11638 }(Shumway.Options || (Shumway.Options = {})));
michael@0 11639 var Options = Shumway.Options;
michael@0 11640 }(Shumway || (Shumway = {})));
michael@0 11641 if (typeof exports !== 'undefined') {
michael@0 11642 exports['Shumway'] = Shumway;
michael@0 11643 }
michael@0 11644 var ArgumentParser = Shumway.Options.ArgumentParser;
michael@0 11645 var Option = Shumway.Options.Option;
michael@0 11646 var OptionSet = Shumway.Options.OptionSet;
michael@0 11647 var ArgumentParser = Shumway.Options.ArgumentParser;
michael@0 11648 var Option = Shumway.Options.Option;
michael@0 11649 var OptionSet = Shumway.Options.OptionSet;
michael@0 11650 var Shumway;
michael@0 11651 (function (Shumway) {
michael@0 11652 (function (Metrics) {
michael@0 11653 var Timer = function () {
michael@0 11654 function Timer(parent, name) {
michael@0 11655 this._parent = parent;
michael@0 11656 this._timers = Shumway.ObjectUtilities.createMap();
michael@0 11657 this._name = name;
michael@0 11658 this._begin = 0;
michael@0 11659 this._last = 0;
michael@0 11660 this._total = 0;
michael@0 11661 this._count = 0;
michael@0 11662 }
michael@0 11663 Timer.time = function (name, fn) {
michael@0 11664 Timer.start(name);
michael@0 11665 fn();
michael@0 11666 Timer.stop();
michael@0 11667 };
michael@0 11668 Timer.start = function (name) {
michael@0 11669 Timer._top = Timer._top._timers[name] || (Timer._top._timers[name] = new Timer(Timer._top, name));
michael@0 11670 Timer._top.start();
michael@0 11671 var tmp = Timer._flat._timers[name] || (Timer._flat._timers[name] = new Timer(Timer._flat, name));
michael@0 11672 tmp.start();
michael@0 11673 Timer._flatStack.push(tmp);
michael@0 11674 };
michael@0 11675 Timer.stop = function () {
michael@0 11676 Timer._top.stop();
michael@0 11677 Timer._top = Timer._top._parent;
michael@0 11678 Timer._flatStack.pop().stop();
michael@0 11679 };
michael@0 11680 Timer.stopStart = function (name) {
michael@0 11681 Timer.stop();
michael@0 11682 Timer.start(name);
michael@0 11683 };
michael@0 11684 Timer.prototype.start = function () {
michael@0 11685 this._begin = Shumway.getTicks();
michael@0 11686 };
michael@0 11687 Timer.prototype.stop = function () {
michael@0 11688 this._last = Shumway.getTicks() - this._begin;
michael@0 11689 this._total += this._last;
michael@0 11690 this._count += 1;
michael@0 11691 };
michael@0 11692 Timer.prototype.toJSON = function () {
michael@0 11693 return {
michael@0 11694 name: this._name,
michael@0 11695 total: this._total,
michael@0 11696 timers: this._timers
michael@0 11697 };
michael@0 11698 };
michael@0 11699 Timer.prototype.trace = function (writer) {
michael@0 11700 writer.enter(this._name + ': ' + this._total.toFixed(2) + ' ms' + ', count: ' + this._count + ', average: ' + (this._total / this._count).toFixed(2) + ' ms');
michael@0 11701 for (var name in this._timers) {
michael@0 11702 this._timers[name].trace(writer);
michael@0 11703 }
michael@0 11704 writer.outdent();
michael@0 11705 };
michael@0 11706 Timer.trace = function (writer) {
michael@0 11707 Timer._base.trace(writer);
michael@0 11708 Timer._flat.trace(writer);
michael@0 11709 };
michael@0 11710 Timer._base = new Timer(null, 'Total');
michael@0 11711 Timer._top = Timer._base;
michael@0 11712 Timer._flat = new Timer(null, 'Flat');
michael@0 11713 Timer._flatStack = [];
michael@0 11714 return Timer;
michael@0 11715 }();
michael@0 11716 Metrics.Timer = Timer;
michael@0 11717 var Counter = function () {
michael@0 11718 function Counter(enabled) {
michael@0 11719 this._enabled = enabled;
michael@0 11720 this.clear();
michael@0 11721 }
michael@0 11722 Counter.prototype.setEnabled = function (enabled) {
michael@0 11723 this._enabled = enabled;
michael@0 11724 };
michael@0 11725 Counter.prototype.clear = function () {
michael@0 11726 this._counts = Shumway.ObjectUtilities.createMap();
michael@0 11727 };
michael@0 11728 Counter.prototype.toJSON = function () {
michael@0 11729 return {
michael@0 11730 counts: this._counts
michael@0 11731 };
michael@0 11732 };
michael@0 11733 Counter.prototype.count = function (name, increment) {
michael@0 11734 if (typeof increment === 'undefined') {
michael@0 11735 increment = 1;
michael@0 11736 }
michael@0 11737 if (!this._enabled) {
michael@0 11738 return;
michael@0 11739 }
michael@0 11740 if (this._counts[name] === undefined) {
michael@0 11741 this._counts[name] = 0;
michael@0 11742 }
michael@0 11743 this._counts[name] += increment;
michael@0 11744 return this._counts[name];
michael@0 11745 };
michael@0 11746 Counter.prototype.trace = function (writer) {
michael@0 11747 for (var name in this._counts) {
michael@0 11748 writer.writeLn(name + ': ' + this._counts[name]);
michael@0 11749 }
michael@0 11750 };
michael@0 11751 Counter.prototype.traceSorted = function (writer) {
michael@0 11752 var pairs = [];
michael@0 11753 for (var name in this._counts) {
michael@0 11754 pairs.push([
michael@0 11755 name,
michael@0 11756 this._counts[name]
michael@0 11757 ]);
michael@0 11758 }
michael@0 11759 pairs.sort(function (a, b) {
michael@0 11760 return b[1] - a[1];
michael@0 11761 });
michael@0 11762 pairs.forEach(function (pair) {
michael@0 11763 writer.writeLn(pair[0] + ': ' + pair[1]);
michael@0 11764 });
michael@0 11765 };
michael@0 11766 return Counter;
michael@0 11767 }();
michael@0 11768 Metrics.Counter = Counter;
michael@0 11769 var Average = function () {
michael@0 11770 function Average(max) {
michael@0 11771 this._samples = new Float64Array(max);
michael@0 11772 this._count = 0;
michael@0 11773 this._index = 0;
michael@0 11774 }
michael@0 11775 Average.prototype.push = function (sample) {
michael@0 11776 if (this._count < this._samples.length) {
michael@0 11777 this._count++;
michael@0 11778 }
michael@0 11779 this._index++;
michael@0 11780 this._samples[this._index % this._samples.length] = sample;
michael@0 11781 };
michael@0 11782 Average.prototype.average = function () {
michael@0 11783 var sum = 0;
michael@0 11784 for (var i = 0; i < this._count; i++) {
michael@0 11785 sum += this._samples[i];
michael@0 11786 }
michael@0 11787 return sum / this._count;
michael@0 11788 };
michael@0 11789 return Average;
michael@0 11790 }();
michael@0 11791 Metrics.Average = Average;
michael@0 11792 }(Shumway.Metrics || (Shumway.Metrics = {})));
michael@0 11793 var Metrics = Shumway.Metrics;
michael@0 11794 }(Shumway || (Shumway = {})));
michael@0 11795 var Timer = Shumway.Metrics.Timer;
michael@0 11796 var Counter = new Shumway.Metrics.Counter(true);
michael@0 11797 var Timer = Shumway.Metrics.Timer;
michael@0 11798 var Counter = new Shumway.Metrics.Counter(true);
michael@0 11799 var FrameCounter = new Shumway.Metrics.Counter(true);
michael@0 11800 var systemOptions = new OptionSet('System Options');
michael@0 11801 var disassemble = systemOptions.register(new Option('d', 'disassemble', 'boolean', false, 'disassemble'));
michael@0 11802 var traceLevel = systemOptions.register(new Option('t', 'traceLevel', 'number', 0, 'trace level'));
michael@0 11803 window.print = function (s) {
michael@0 11804 console.log(s);
michael@0 11805 };
michael@0 11806 var CONSTANT_Undefined = 0;
michael@0 11807 var CONSTANT_Utf8 = 1;
michael@0 11808 var CONSTANT_Float = 2;
michael@0 11809 var CONSTANT_Int = 3;
michael@0 11810 var CONSTANT_UInt = 4;
michael@0 11811 var CONSTANT_PrivateNs = 5;
michael@0 11812 var CONSTANT_Double = 6;
michael@0 11813 var CONSTANT_QName = 7;
michael@0 11814 var CONSTANT_Namespace = 8;
michael@0 11815 var CONSTANT_Multiname = 9;
michael@0 11816 var CONSTANT_False = 10;
michael@0 11817 var CONSTANT_True = 11;
michael@0 11818 var CONSTANT_Null = 12;
michael@0 11819 var CONSTANT_QNameA = 13;
michael@0 11820 var CONSTANT_MultinameA = 14;
michael@0 11821 var CONSTANT_RTQName = 15;
michael@0 11822 var CONSTANT_RTQNameA = 16;
michael@0 11823 var CONSTANT_RTQNameL = 17;
michael@0 11824 var CONSTANT_RTQNameLA = 18;
michael@0 11825 var CONSTANT_NameL = 19;
michael@0 11826 var CONSTANT_NameLA = 20;
michael@0 11827 var CONSTANT_NamespaceSet = 21;
michael@0 11828 var CONSTANT_PackageNamespace = 22;
michael@0 11829 var CONSTANT_PackageInternalNs = 23;
michael@0 11830 var CONSTANT_ProtectedNamespace = 24;
michael@0 11831 var CONSTANT_ExplicitNamespace = 25;
michael@0 11832 var CONSTANT_StaticProtectedNs = 26;
michael@0 11833 var CONSTANT_MultinameL = 27;
michael@0 11834 var CONSTANT_MultinameLA = 28;
michael@0 11835 var CONSTANT_TypeName = 29;
michael@0 11836 var CONSTANT_ClassSealed = 1;
michael@0 11837 var CONSTANT_ClassFinal = 2;
michael@0 11838 var CONSTANT_ClassInterface = 4;
michael@0 11839 var CONSTANT_ClassProtectedNs = 8;
michael@0 11840 var TRAIT_Slot = 0;
michael@0 11841 var TRAIT_Method = 1;
michael@0 11842 var TRAIT_Getter = 2;
michael@0 11843 var TRAIT_Setter = 3;
michael@0 11844 var TRAIT_Class = 4;
michael@0 11845 var TRAIT_Function = 5;
michael@0 11846 var TRAIT_Const = 6;
michael@0 11847 var ATTR_Final = 1;
michael@0 11848 var ATTR_Override = 2;
michael@0 11849 var ATTR_Metadata = 4;
michael@0 11850 var SLOT_var = 0;
michael@0 11851 var SLOT_method = 1;
michael@0 11852 var SLOT_getter = 2;
michael@0 11853 var SLOT_setter = 3;
michael@0 11854 var SLOT_class = 4;
michael@0 11855 var SLOT_function = 6;
michael@0 11856 var METHOD_Arguments = 1;
michael@0 11857 var METHOD_Activation = 2;
michael@0 11858 var METHOD_Needrest = 4;
michael@0 11859 var METHOD_HasOptional = 8;
michael@0 11860 var METHOD_IgnoreRest = 16;
michael@0 11861 var METHOD_Native = 32;
michael@0 11862 var METHOD_Setsdxns = 64;
michael@0 11863 var METHOD_HasParamNames = 128;
michael@0 11864 var OP_bkpt = 1;
michael@0 11865 var OP_nop = 2;
michael@0 11866 var OP_throw = 3;
michael@0 11867 var OP_getsuper = 4;
michael@0 11868 var OP_setsuper = 5;
michael@0 11869 var OP_dxns = 6;
michael@0 11870 var OP_dxnslate = 7;
michael@0 11871 var OP_kill = 8;
michael@0 11872 var OP_label = 9;
michael@0 11873 var OP_lf32x4 = 10;
michael@0 11874 var OP_sf32x4 = 11;
michael@0 11875 var OP_ifnlt = 12;
michael@0 11876 var OP_ifnle = 13;
michael@0 11877 var OP_ifngt = 14;
michael@0 11878 var OP_ifnge = 15;
michael@0 11879 var OP_jump = 16;
michael@0 11880 var OP_iftrue = 17;
michael@0 11881 var OP_iffalse = 18;
michael@0 11882 var OP_ifeq = 19;
michael@0 11883 var OP_ifne = 20;
michael@0 11884 var OP_iflt = 21;
michael@0 11885 var OP_ifle = 22;
michael@0 11886 var OP_ifgt = 23;
michael@0 11887 var OP_ifge = 24;
michael@0 11888 var OP_ifstricteq = 25;
michael@0 11889 var OP_ifstrictne = 26;
michael@0 11890 var OP_lookupswitch = 27;
michael@0 11891 var OP_pushwith = 28;
michael@0 11892 var OP_popscope = 29;
michael@0 11893 var OP_nextname = 30;
michael@0 11894 var OP_hasnext = 31;
michael@0 11895 var OP_pushnull = 32;
michael@0 11896 var OP_pushundefined = 33;
michael@0 11897 var OP_pushfloat = 34;
michael@0 11898 var OP_nextvalue = 35;
michael@0 11899 var OP_pushbyte = 36;
michael@0 11900 var OP_pushshort = 37;
michael@0 11901 var OP_pushtrue = 38;
michael@0 11902 var OP_pushfalse = 39;
michael@0 11903 var OP_pushnan = 40;
michael@0 11904 var OP_pop = 41;
michael@0 11905 var OP_dup = 42;
michael@0 11906 var OP_swap = 43;
michael@0 11907 var OP_pushstring = 44;
michael@0 11908 var OP_pushint = 45;
michael@0 11909 var OP_pushuint = 46;
michael@0 11910 var OP_pushdouble = 47;
michael@0 11911 var OP_pushscope = 48;
michael@0 11912 var OP_pushnamespace = 49;
michael@0 11913 var OP_hasnext2 = 50;
michael@0 11914 var OP_li8 = 53;
michael@0 11915 var OP_li16 = 54;
michael@0 11916 var OP_li32 = 55;
michael@0 11917 var OP_lf32 = 56;
michael@0 11918 var OP_lf64 = 57;
michael@0 11919 var OP_si8 = 58;
michael@0 11920 var OP_si16 = 59;
michael@0 11921 var OP_si32 = 60;
michael@0 11922 var OP_sf32 = 61;
michael@0 11923 var OP_sf64 = 62;
michael@0 11924 var OP_newfunction = 64;
michael@0 11925 var OP_call = 65;
michael@0 11926 var OP_construct = 66;
michael@0 11927 var OP_callmethod = 67;
michael@0 11928 var OP_callstatic = 68;
michael@0 11929 var OP_callsuper = 69;
michael@0 11930 var OP_callproperty = 70;
michael@0 11931 var OP_returnvoid = 71;
michael@0 11932 var OP_returnvalue = 72;
michael@0 11933 var OP_constructsuper = 73;
michael@0 11934 var OP_constructprop = 74;
michael@0 11935 var OP_callsuperid = 75;
michael@0 11936 var OP_callproplex = 76;
michael@0 11937 var OP_callinterface = 77;
michael@0 11938 var OP_callsupervoid = 78;
michael@0 11939 var OP_callpropvoid = 79;
michael@0 11940 var OP_sxi1 = 80;
michael@0 11941 var OP_sxi8 = 81;
michael@0 11942 var OP_sxi16 = 82;
michael@0 11943 var OP_applytype = 83;
michael@0 11944 var OP_pushfloat4 = 84;
michael@0 11945 var OP_newobject = 85;
michael@0 11946 var OP_newarray = 86;
michael@0 11947 var OP_newactivation = 87;
michael@0 11948 var OP_newclass = 88;
michael@0 11949 var OP_getdescendants = 89;
michael@0 11950 var OP_newcatch = 90;
michael@0 11951 var OP_findpropstrict = 93;
michael@0 11952 var OP_findproperty = 94;
michael@0 11953 var OP_finddef = 95;
michael@0 11954 var OP_getlex = 96;
michael@0 11955 var OP_setproperty = 97;
michael@0 11956 var OP_getlocal = 98;
michael@0 11957 var OP_setlocal = 99;
michael@0 11958 var OP_getglobalscope = 100;
michael@0 11959 var OP_getscopeobject = 101;
michael@0 11960 var OP_getproperty = 102;
michael@0 11961 var OP_getouterscope = 103;
michael@0 11962 var OP_initproperty = 104;
michael@0 11963 var OP_setpropertylate = 105;
michael@0 11964 var OP_deleteproperty = 106;
michael@0 11965 var OP_deletepropertylate = 107;
michael@0 11966 var OP_getslot = 108;
michael@0 11967 var OP_setslot = 109;
michael@0 11968 var OP_getglobalslot = 110;
michael@0 11969 var OP_setglobalslot = 111;
michael@0 11970 var OP_convert_s = 112;
michael@0 11971 var OP_esc_xelem = 113;
michael@0 11972 var OP_esc_xattr = 114;
michael@0 11973 var OP_convert_i = 115;
michael@0 11974 var OP_convert_u = 116;
michael@0 11975 var OP_convert_d = 117;
michael@0 11976 var OP_convert_b = 118;
michael@0 11977 var OP_convert_o = 119;
michael@0 11978 var OP_checkfilter = 120;
michael@0 11979 var OP_convert_f = 121;
michael@0 11980 var OP_unplus = 122;
michael@0 11981 var OP_convert_f4 = 123;
michael@0 11982 var OP_coerce = 128;
michael@0 11983 var OP_coerce_b = 129;
michael@0 11984 var OP_coerce_a = 130;
michael@0 11985 var OP_coerce_i = 131;
michael@0 11986 var OP_coerce_d = 132;
michael@0 11987 var OP_coerce_s = 133;
michael@0 11988 var OP_astype = 134;
michael@0 11989 var OP_astypelate = 135;
michael@0 11990 var OP_coerce_u = 136;
michael@0 11991 var OP_coerce_o = 137;
michael@0 11992 var OP_negate = 144;
michael@0 11993 var OP_increment = 145;
michael@0 11994 var OP_inclocal = 146;
michael@0 11995 var OP_decrement = 147;
michael@0 11996 var OP_declocal = 148;
michael@0 11997 var OP_typeof = 149;
michael@0 11998 var OP_not = 150;
michael@0 11999 var OP_bitnot = 151;
michael@0 12000 var OP_add = 160;
michael@0 12001 var OP_subtract = 161;
michael@0 12002 var OP_multiply = 162;
michael@0 12003 var OP_divide = 163;
michael@0 12004 var OP_modulo = 164;
michael@0 12005 var OP_lshift = 165;
michael@0 12006 var OP_rshift = 166;
michael@0 12007 var OP_urshift = 167;
michael@0 12008 var OP_bitand = 168;
michael@0 12009 var OP_bitor = 169;
michael@0 12010 var OP_bitxor = 170;
michael@0 12011 var OP_equals = 171;
michael@0 12012 var OP_strictequals = 172;
michael@0 12013 var OP_lessthan = 173;
michael@0 12014 var OP_lessequals = 174;
michael@0 12015 var OP_greaterthan = 175;
michael@0 12016 var OP_greaterequals = 176;
michael@0 12017 var OP_instanceof = 177;
michael@0 12018 var OP_istype = 178;
michael@0 12019 var OP_istypelate = 179;
michael@0 12020 var OP_in = 180;
michael@0 12021 var OP_increment_i = 192;
michael@0 12022 var OP_decrement_i = 193;
michael@0 12023 var OP_inclocal_i = 194;
michael@0 12024 var OP_declocal_i = 195;
michael@0 12025 var OP_negate_i = 196;
michael@0 12026 var OP_add_i = 197;
michael@0 12027 var OP_subtract_i = 198;
michael@0 12028 var OP_multiply_i = 199;
michael@0 12029 var OP_getlocal0 = 208;
michael@0 12030 var OP_getlocal1 = 209;
michael@0 12031 var OP_getlocal2 = 210;
michael@0 12032 var OP_getlocal3 = 211;
michael@0 12033 var OP_setlocal0 = 212;
michael@0 12034 var OP_setlocal1 = 213;
michael@0 12035 var OP_setlocal2 = 214;
michael@0 12036 var OP_setlocal3 = 215;
michael@0 12037 var OP_invalid = 237;
michael@0 12038 var OP_debug = 239;
michael@0 12039 var OP_debugline = 240;
michael@0 12040 var OP_debugfile = 241;
michael@0 12041 var OP_bkptline = 242;
michael@0 12042 var OP_timestamp = 243;
michael@0 12043 var INT_MIN_VALUE = -2147483648;
michael@0 12044 var INT_MAX_VALUE = 2147483647;
michael@0 12045 var UINT_MIN_VALUE = 0;
michael@0 12046 var UINT_MAX_VALUE = 4294967295;
michael@0 12047 var SORT_CASEINSENSITIVE = 1;
michael@0 12048 var SORT_DESCENDING = 2;
michael@0 12049 var SORT_UNIQUESORT = 4;
michael@0 12050 var SORT_RETURNINDEXEDARRAY = 8;
michael@0 12051 var SORT_NUMERIC = 16;
michael@0 12052 var Shumway;
michael@0 12053 (function (Shumway) {
michael@0 12054 (function (AVM2) {
michael@0 12055 AVM2.Errors = {
michael@0 12056 CallOfNonFunctionError: {
michael@0 12057 code: 1006,
michael@0 12058 message: '%1 is not a function.'
michael@0 12059 },
michael@0 12060 ConvertNullToObjectError: {
michael@0 12061 code: 1009,
michael@0 12062 message: 'Cannot access a property or method of a null object reference.'
michael@0 12063 },
michael@0 12064 ConvertUndefinedToObjectError: {
michael@0 12065 code: 1010,
michael@0 12066 message: 'A term is undefined and has no properties.'
michael@0 12067 },
michael@0 12068 ClassNotFoundError: {
michael@0 12069 code: 1014,
michael@0 12070 message: 'Class %1 could not be found.'
michael@0 12071 },
michael@0 12072 CheckTypeFailedError: {
michael@0 12073 code: 1034,
michael@0 12074 message: 'Type Coercion failed: cannot convert %1 to %2.'
michael@0 12075 },
michael@0 12076 WrongArgumentCountError: {
michael@0 12077 code: 1063,
michael@0 12078 message: 'Argument count mismatch on %1. Expected %2, got %3.'
michael@0 12079 },
michael@0 12080 XMLMarkupMustBeWellFormed: {
michael@0 12081 code: 1088,
michael@0 12082 message: 'The markup in the document following the root element must be well-formed.'
michael@0 12083 },
michael@0 12084 OutOfRangeError: {
michael@0 12085 code: 1125,
michael@0 12086 message: 'The index %1 is out of range %2.'
michael@0 12087 },
michael@0 12088 VectorFixedError: {
michael@0 12089 code: 1126,
michael@0 12090 message: 'Cannot change the length of a fixed Vector.'
michael@0 12091 },
michael@0 12092 InvalidParamError: {
michael@0 12093 code: 2004,
michael@0 12094 message: 'One of the parameters is invalid.'
michael@0 12095 },
michael@0 12096 ParamRangeError: {
michael@0 12097 code: 2006,
michael@0 12098 message: 'The supplied index is out of bounds.'
michael@0 12099 },
michael@0 12100 NullPointerError: {
michael@0 12101 code: 2007,
michael@0 12102 message: 'Parameter %1 must be non-null.'
michael@0 12103 },
michael@0 12104 InvalidEnumError: {
michael@0 12105 code: 2008,
michael@0 12106 message: 'Parameter %1 must be one of the accepted values.'
michael@0 12107 },
michael@0 12108 ArgumentError: {
michael@0 12109 code: 2015,
michael@0 12110 message: 'Invalid BitmapData.'
michael@0 12111 },
michael@0 12112 CompressedDataError: {
michael@0 12113 code: 2058,
michael@0 12114 message: 'There was an error decompressing the data.'
michael@0 12115 },
michael@0 12116 SocketConnectError: {
michael@0 12117 code: 2011,
michael@0 12118 message: 'Socket connection failed to %1:%2.'
michael@0 12119 },
michael@0 12120 CantAddSelfError: {
michael@0 12121 code: 2024,
michael@0 12122 message: 'An object cannot be added as a child of itself.'
michael@0 12123 },
michael@0 12124 NotAChildError: {
michael@0 12125 code: 2025,
michael@0 12126 message: 'The supplied DisplayObject must be a child of the caller.'
michael@0 12127 },
michael@0 12128 ExternalInterfaceNotAvailableError: {
michael@0 12129 code: 2067,
michael@0 12130 message: 'The ExternalInterface is not available in this container. ExternalInterface requires Internet Explorer ActiveX, Firefox, Mozilla 1.7.5 and greater, or other browsers that support NPRuntime.'
michael@0 12131 }
michael@0 12132 };
michael@0 12133 function getErrorMessage(index) {
michael@0 12134 if (!Shumway.AVM2.Runtime.debuggerMode.value) {
michael@0 12135 return 'Error #' + index;
michael@0 12136 }
michael@0 12137 for (var k in AVM2.Errors) {
michael@0 12138 if (AVM2.Errors[k].code == index) {
michael@0 12139 return 'Error #' + index + ': ' + AVM2.Errors[k].message;
michael@0 12140 }
michael@0 12141 }
michael@0 12142 return 'Error #' + index + ': (unknown)';
michael@0 12143 }
michael@0 12144 AVM2.getErrorMessage = getErrorMessage;
michael@0 12145 function formatErrorMessage(error) {
michael@0 12146 var args = [];
michael@0 12147 for (var _i = 0; _i < arguments.length - 1; _i++) {
michael@0 12148 args[_i] = arguments[_i + 1];
michael@0 12149 }
michael@0 12150 var message = error.message;
michael@0 12151 Array.prototype.slice.call(arguments, 1).forEach(function (x, i) {
michael@0 12152 message = message.replace('%' + (i + 1), x);
michael@0 12153 });
michael@0 12154 return 'Error #' + error.code + ': ' + message;
michael@0 12155 }
michael@0 12156 AVM2.formatErrorMessage = formatErrorMessage;
michael@0 12157 function translateErrorMessage(error) {
michael@0 12158 if (error.type) {
michael@0 12159 switch (error.type) {
michael@0 12160 case 'undefined_method':
michael@0 12161 return formatErrorMessage(AVM2.Errors.CallOfNonFunctionError, 'value');
michael@0 12162 default:
michael@0 12163 throw Shumway.Debug.notImplemented(error.type);
michael@0 12164 }
michael@0 12165 } else {
michael@0 12166 if (error.message.indexOf('is not a function') >= 0) {
michael@0 12167 return formatErrorMessage(AVM2.Errors.CallOfNonFunctionError, 'value');
michael@0 12168 }
michael@0 12169 return error.message;
michael@0 12170 }
michael@0 12171 }
michael@0 12172 AVM2.translateErrorMessage = translateErrorMessage;
michael@0 12173 }(Shumway.AVM2 || (Shumway.AVM2 = {})));
michael@0 12174 var AVM2 = Shumway.AVM2;
michael@0 12175 }(Shumway || (Shumway = {})));
michael@0 12176 var Errors = Shumway.AVM2.Errors;
michael@0 12177 var getErrorMessage = Shumway.AVM2.getErrorMessage;
michael@0 12178 var formatErrorMessage = Shumway.AVM2.formatErrorMessage;
michael@0 12179 var translateErrorMessage = Shumway.AVM2.translateErrorMessage;
michael@0 12180 var Errors = Shumway.AVM2.Errors;
michael@0 12181 var getErrorMessage = Shumway.AVM2.getErrorMessage;
michael@0 12182 var formatErrorMessage = Shumway.AVM2.formatErrorMessage;
michael@0 12183 var translateErrorMessage = Shumway.AVM2.translateErrorMessage;
michael@0 12184 var Shumway;
michael@0 12185 (function (Shumway) {
michael@0 12186 (function (AVM2) {
michael@0 12187 AVM2.opcodeTable = [
michael@0 12188 null,
michael@0 12189 {
michael@0 12190 name: 'bkpt',
michael@0 12191 canThrow: false,
michael@0 12192 operands: []
michael@0 12193 },
michael@0 12194 {
michael@0 12195 name: 'nop',
michael@0 12196 canThrow: false,
michael@0 12197 operands: []
michael@0 12198 },
michael@0 12199 {
michael@0 12200 name: 'throw',
michael@0 12201 canThrow: true,
michael@0 12202 operands: []
michael@0 12203 },
michael@0 12204 {
michael@0 12205 name: 'getsuper',
michael@0 12206 canThrow: true,
michael@0 12207 operands: [
michael@0 12208 {
michael@0 12209 name: 'index',
michael@0 12210 size: 'u30',
michael@0 12211 type: ''
michael@0 12212 }
michael@0 12213 ]
michael@0 12214 },
michael@0 12215 {
michael@0 12216 name: 'setsuper',
michael@0 12217 canThrow: true,
michael@0 12218 operands: [
michael@0 12219 {
michael@0 12220 name: 'index',
michael@0 12221 size: 'u30',
michael@0 12222 type: ''
michael@0 12223 }
michael@0 12224 ]
michael@0 12225 },
michael@0 12226 {
michael@0 12227 name: 'dxns',
michael@0 12228 canThrow: true,
michael@0 12229 operands: [
michael@0 12230 {
michael@0 12231 name: 'index',
michael@0 12232 size: 'u30',
michael@0 12233 type: ''
michael@0 12234 }
michael@0 12235 ]
michael@0 12236 },
michael@0 12237 {
michael@0 12238 name: 'dxnslate',
michael@0 12239 canThrow: true,
michael@0 12240 operands: []
michael@0 12241 },
michael@0 12242 {
michael@0 12243 name: 'kill',
michael@0 12244 canThrow: false,
michael@0 12245 operands: [
michael@0 12246 {
michael@0 12247 name: 'index',
michael@0 12248 size: 'u30',
michael@0 12249 type: ''
michael@0 12250 }
michael@0 12251 ]
michael@0 12252 },
michael@0 12253 {
michael@0 12254 name: 'label',
michael@0 12255 canThrow: false,
michael@0 12256 operands: []
michael@0 12257 },
michael@0 12258 {
michael@0 12259 name: 'lf32x4',
michael@0 12260 canThrow: true,
michael@0 12261 operands: []
michael@0 12262 },
michael@0 12263 {
michael@0 12264 name: 'sf32x4',
michael@0 12265 canThrow: true,
michael@0 12266 operands: []
michael@0 12267 },
michael@0 12268 {
michael@0 12269 name: 'ifnlt',
michael@0 12270 canThrow: true,
michael@0 12271 operands: [
michael@0 12272 {
michael@0 12273 name: 'offset',
michael@0 12274 size: 's24',
michael@0 12275 type: ''
michael@0 12276 }
michael@0 12277 ]
michael@0 12278 },
michael@0 12279 {
michael@0 12280 name: 'ifnle',
michael@0 12281 canThrow: true,
michael@0 12282 operands: [
michael@0 12283 {
michael@0 12284 name: 'offset',
michael@0 12285 size: 's24',
michael@0 12286 type: ''
michael@0 12287 }
michael@0 12288 ]
michael@0 12289 },
michael@0 12290 {
michael@0 12291 name: 'ifngt',
michael@0 12292 canThrow: true,
michael@0 12293 operands: [
michael@0 12294 {
michael@0 12295 name: 'offset',
michael@0 12296 size: 's24',
michael@0 12297 type: ''
michael@0 12298 }
michael@0 12299 ]
michael@0 12300 },
michael@0 12301 {
michael@0 12302 name: 'ifnge',
michael@0 12303 canThrow: true,
michael@0 12304 operands: [
michael@0 12305 {
michael@0 12306 name: 'offset',
michael@0 12307 size: 's24',
michael@0 12308 type: ''
michael@0 12309 }
michael@0 12310 ]
michael@0 12311 },
michael@0 12312 {
michael@0 12313 name: 'jump',
michael@0 12314 canThrow: false,
michael@0 12315 operands: [
michael@0 12316 {
michael@0 12317 name: 'offset',
michael@0 12318 size: 's24',
michael@0 12319 type: ''
michael@0 12320 }
michael@0 12321 ]
michael@0 12322 },
michael@0 12323 {
michael@0 12324 name: 'iftrue',
michael@0 12325 canThrow: false,
michael@0 12326 operands: [
michael@0 12327 {
michael@0 12328 name: 'offset',
michael@0 12329 size: 's24',
michael@0 12330 type: ''
michael@0 12331 }
michael@0 12332 ]
michael@0 12333 },
michael@0 12334 {
michael@0 12335 name: 'iffalse',
michael@0 12336 canThrow: false,
michael@0 12337 operands: [
michael@0 12338 {
michael@0 12339 name: 'offset',
michael@0 12340 size: 's24',
michael@0 12341 type: ''
michael@0 12342 }
michael@0 12343 ]
michael@0 12344 },
michael@0 12345 {
michael@0 12346 name: 'ifeq',
michael@0 12347 canThrow: true,
michael@0 12348 operands: [
michael@0 12349 {
michael@0 12350 name: 'offset',
michael@0 12351 size: 's24',
michael@0 12352 type: ''
michael@0 12353 }
michael@0 12354 ]
michael@0 12355 },
michael@0 12356 {
michael@0 12357 name: 'ifne',
michael@0 12358 canThrow: true,
michael@0 12359 operands: [
michael@0 12360 {
michael@0 12361 name: 'offset',
michael@0 12362 size: 's24',
michael@0 12363 type: ''
michael@0 12364 }
michael@0 12365 ]
michael@0 12366 },
michael@0 12367 {
michael@0 12368 name: 'iflt',
michael@0 12369 canThrow: true,
michael@0 12370 operands: [
michael@0 12371 {
michael@0 12372 name: 'offset',
michael@0 12373 size: 's24',
michael@0 12374 type: ''
michael@0 12375 }
michael@0 12376 ]
michael@0 12377 },
michael@0 12378 {
michael@0 12379 name: 'ifle',
michael@0 12380 canThrow: true,
michael@0 12381 operands: [
michael@0 12382 {
michael@0 12383 name: 'offset',
michael@0 12384 size: 's24',
michael@0 12385 type: ''
michael@0 12386 }
michael@0 12387 ]
michael@0 12388 },
michael@0 12389 {
michael@0 12390 name: 'ifgt',
michael@0 12391 canThrow: true,
michael@0 12392 operands: [
michael@0 12393 {
michael@0 12394 name: 'offset',
michael@0 12395 size: 's24',
michael@0 12396 type: ''
michael@0 12397 }
michael@0 12398 ]
michael@0 12399 },
michael@0 12400 {
michael@0 12401 name: 'ifge',
michael@0 12402 canThrow: true,
michael@0 12403 operands: [
michael@0 12404 {
michael@0 12405 name: 'offset',
michael@0 12406 size: 's24',
michael@0 12407 type: ''
michael@0 12408 }
michael@0 12409 ]
michael@0 12410 },
michael@0 12411 {
michael@0 12412 name: 'ifstricteq',
michael@0 12413 canThrow: false,
michael@0 12414 operands: [
michael@0 12415 {
michael@0 12416 name: 'offset',
michael@0 12417 size: 's24',
michael@0 12418 type: ''
michael@0 12419 }
michael@0 12420 ]
michael@0 12421 },
michael@0 12422 {
michael@0 12423 name: 'ifstrictne',
michael@0 12424 canThrow: false,
michael@0 12425 operands: [
michael@0 12426 {
michael@0 12427 name: 'offset',
michael@0 12428 size: 's24',
michael@0 12429 type: ''
michael@0 12430 }
michael@0 12431 ]
michael@0 12432 },
michael@0 12433 {
michael@0 12434 name: 'lookupswitch',
michael@0 12435 canThrow: false,
michael@0 12436 operands: null
michael@0 12437 },
michael@0 12438 {
michael@0 12439 name: 'pushwith',
michael@0 12440 canThrow: false,
michael@0 12441 operands: []
michael@0 12442 },
michael@0 12443 {
michael@0 12444 name: 'popscope',
michael@0 12445 canThrow: false,
michael@0 12446 operands: []
michael@0 12447 },
michael@0 12448 {
michael@0 12449 name: 'nextname',
michael@0 12450 canThrow: true,
michael@0 12451 operands: []
michael@0 12452 },
michael@0 12453 {
michael@0 12454 name: 'hasnext',
michael@0 12455 canThrow: true,
michael@0 12456 operands: []
michael@0 12457 },
michael@0 12458 {
michael@0 12459 name: 'pushnull',
michael@0 12460 canThrow: false,
michael@0 12461 operands: []
michael@0 12462 },
michael@0 12463 {
michael@0 12464 name: 'pushundefined',
michael@0 12465 canThrow: false,
michael@0 12466 operands: []
michael@0 12467 },
michael@0 12468 null,
michael@0 12469 {
michael@0 12470 name: 'nextvalue',
michael@0 12471 canThrow: true,
michael@0 12472 operands: []
michael@0 12473 },
michael@0 12474 {
michael@0 12475 name: 'pushbyte',
michael@0 12476 canThrow: false,
michael@0 12477 operands: [
michael@0 12478 {
michael@0 12479 name: 'value',
michael@0 12480 size: 's08',
michael@0 12481 type: ''
michael@0 12482 }
michael@0 12483 ]
michael@0 12484 },
michael@0 12485 {
michael@0 12486 name: 'pushshort',
michael@0 12487 canThrow: false,
michael@0 12488 operands: [
michael@0 12489 {
michael@0 12490 name: 'value',
michael@0 12491 size: 's16',
michael@0 12492 type: ''
michael@0 12493 }
michael@0 12494 ]
michael@0 12495 },
michael@0 12496 {
michael@0 12497 name: 'pushtrue',
michael@0 12498 canThrow: false,
michael@0 12499 operands: []
michael@0 12500 },
michael@0 12501 {
michael@0 12502 name: 'pushfalse',
michael@0 12503 canThrow: false,
michael@0 12504 operands: []
michael@0 12505 },
michael@0 12506 {
michael@0 12507 name: 'pushnan',
michael@0 12508 canThrow: false,
michael@0 12509 operands: []
michael@0 12510 },
michael@0 12511 {
michael@0 12512 name: 'pop',
michael@0 12513 canThrow: false,
michael@0 12514 operands: []
michael@0 12515 },
michael@0 12516 {
michael@0 12517 name: 'dup',
michael@0 12518 canThrow: false,
michael@0 12519 operands: []
michael@0 12520 },
michael@0 12521 {
michael@0 12522 name: 'swap',
michael@0 12523 canThrow: false,
michael@0 12524 operands: []
michael@0 12525 },
michael@0 12526 {
michael@0 12527 name: 'pushstring',
michael@0 12528 canThrow: false,
michael@0 12529 operands: [
michael@0 12530 {
michael@0 12531 name: 'index',
michael@0 12532 size: 'u30',
michael@0 12533 type: 'S'
michael@0 12534 }
michael@0 12535 ]
michael@0 12536 },
michael@0 12537 {
michael@0 12538 name: 'pushint',
michael@0 12539 canThrow: false,
michael@0 12540 operands: [
michael@0 12541 {
michael@0 12542 name: 'index',
michael@0 12543 size: 'u30',
michael@0 12544 type: 'I'
michael@0 12545 }
michael@0 12546 ]
michael@0 12547 },
michael@0 12548 {
michael@0 12549 name: 'pushuint',
michael@0 12550 canThrow: false,
michael@0 12551 operands: [
michael@0 12552 {
michael@0 12553 name: 'index',
michael@0 12554 size: 'u30',
michael@0 12555 type: 'U'
michael@0 12556 }
michael@0 12557 ]
michael@0 12558 },
michael@0 12559 {
michael@0 12560 name: 'pushdouble',
michael@0 12561 canThrow: false,
michael@0 12562 operands: [
michael@0 12563 {
michael@0 12564 name: 'index',
michael@0 12565 size: 'u30',
michael@0 12566 type: 'D'
michael@0 12567 }
michael@0 12568 ]
michael@0 12569 },
michael@0 12570 {
michael@0 12571 name: 'pushscope',
michael@0 12572 canThrow: false,
michael@0 12573 operands: []
michael@0 12574 },
michael@0 12575 {
michael@0 12576 name: 'pushnamespace',
michael@0 12577 canThrow: false,
michael@0 12578 operands: [
michael@0 12579 {
michael@0 12580 name: 'index',
michael@0 12581 size: 'u30',
michael@0 12582 type: 'N'
michael@0 12583 }
michael@0 12584 ]
michael@0 12585 },
michael@0 12586 {
michael@0 12587 name: 'hasnext2',
michael@0 12588 canThrow: true,
michael@0 12589 operands: [
michael@0 12590 {
michael@0 12591 name: 'object',
michael@0 12592 size: 'u30',
michael@0 12593 type: ''
michael@0 12594 },
michael@0 12595 {
michael@0 12596 name: 'index',
michael@0 12597 size: 'u30',
michael@0 12598 type: ''
michael@0 12599 }
michael@0 12600 ]
michael@0 12601 },
michael@0 12602 {
michael@0 12603 name: 'lix8',
michael@0 12604 canThrow: true,
michael@0 12605 operands: null
michael@0 12606 },
michael@0 12607 {
michael@0 12608 name: 'lix16',
michael@0 12609 canThrow: true,
michael@0 12610 operands: null
michael@0 12611 },
michael@0 12612 {
michael@0 12613 name: 'li8',
michael@0 12614 canThrow: true,
michael@0 12615 operands: []
michael@0 12616 },
michael@0 12617 {
michael@0 12618 name: 'li16',
michael@0 12619 canThrow: true,
michael@0 12620 operands: []
michael@0 12621 },
michael@0 12622 {
michael@0 12623 name: 'li32',
michael@0 12624 canThrow: true,
michael@0 12625 operands: []
michael@0 12626 },
michael@0 12627 {
michael@0 12628 name: 'lf32',
michael@0 12629 canThrow: true,
michael@0 12630 operands: []
michael@0 12631 },
michael@0 12632 {
michael@0 12633 name: 'lf64',
michael@0 12634 canThrow: true,
michael@0 12635 operands: []
michael@0 12636 },
michael@0 12637 {
michael@0 12638 name: 'si8',
michael@0 12639 canThrow: true,
michael@0 12640 operands: []
michael@0 12641 },
michael@0 12642 {
michael@0 12643 name: 'si16',
michael@0 12644 canThrow: true,
michael@0 12645 operands: []
michael@0 12646 },
michael@0 12647 {
michael@0 12648 name: 'si32',
michael@0 12649 canThrow: true,
michael@0 12650 operands: []
michael@0 12651 },
michael@0 12652 {
michael@0 12653 name: 'sf32',
michael@0 12654 canThrow: true,
michael@0 12655 operands: []
michael@0 12656 },
michael@0 12657 {
michael@0 12658 name: 'sf64',
michael@0 12659 canThrow: true,
michael@0 12660 operands: []
michael@0 12661 },
michael@0 12662 null,
michael@0 12663 {
michael@0 12664 name: 'newfunction',
michael@0 12665 canThrow: true,
michael@0 12666 operands: [
michael@0 12667 {
michael@0 12668 name: 'index',
michael@0 12669 size: 'u30',
michael@0 12670 type: 'MI'
michael@0 12671 }
michael@0 12672 ]
michael@0 12673 },
michael@0 12674 {
michael@0 12675 name: 'call',
michael@0 12676 canThrow: true,
michael@0 12677 operands: [
michael@0 12678 {
michael@0 12679 name: 'argCount',
michael@0 12680 size: 'u30',
michael@0 12681 type: ''
michael@0 12682 }
michael@0 12683 ]
michael@0 12684 },
michael@0 12685 {
michael@0 12686 name: 'construct',
michael@0 12687 canThrow: true,
michael@0 12688 operands: [
michael@0 12689 {
michael@0 12690 name: 'argCount',
michael@0 12691 size: 'u30',
michael@0 12692 type: ''
michael@0 12693 }
michael@0 12694 ]
michael@0 12695 },
michael@0 12696 {
michael@0 12697 name: 'callmethod',
michael@0 12698 canThrow: true,
michael@0 12699 operands: [
michael@0 12700 {
michael@0 12701 name: 'index',
michael@0 12702 size: 'u30',
michael@0 12703 type: ''
michael@0 12704 },
michael@0 12705 {
michael@0 12706 name: 'argCount',
michael@0 12707 size: 'u30',
michael@0 12708 type: ''
michael@0 12709 }
michael@0 12710 ]
michael@0 12711 },
michael@0 12712 {
michael@0 12713 name: 'callstatic',
michael@0 12714 canThrow: true,
michael@0 12715 operands: [
michael@0 12716 {
michael@0 12717 name: 'index',
michael@0 12718 size: 'u30',
michael@0 12719 type: 'MI'
michael@0 12720 },
michael@0 12721 {
michael@0 12722 name: 'argCount',
michael@0 12723 size: 'u30',
michael@0 12724 type: ''
michael@0 12725 }
michael@0 12726 ]
michael@0 12727 },
michael@0 12728 {
michael@0 12729 name: 'callsuper',
michael@0 12730 canThrow: true,
michael@0 12731 operands: [
michael@0 12732 {
michael@0 12733 name: 'index',
michael@0 12734 size: 'u30',
michael@0 12735 type: 'M'
michael@0 12736 },
michael@0 12737 {
michael@0 12738 name: 'argCount',
michael@0 12739 size: 'u30',
michael@0 12740 type: ''
michael@0 12741 }
michael@0 12742 ]
michael@0 12743 },
michael@0 12744 {
michael@0 12745 name: 'callproperty',
michael@0 12746 canThrow: true,
michael@0 12747 operands: [
michael@0 12748 {
michael@0 12749 name: 'index',
michael@0 12750 size: 'u30',
michael@0 12751 type: 'M'
michael@0 12752 },
michael@0 12753 {
michael@0 12754 name: 'argCount',
michael@0 12755 size: 'u30',
michael@0 12756 type: ''
michael@0 12757 }
michael@0 12758 ]
michael@0 12759 },
michael@0 12760 {
michael@0 12761 name: 'returnvoid',
michael@0 12762 canThrow: false,
michael@0 12763 operands: []
michael@0 12764 },
michael@0 12765 {
michael@0 12766 name: 'returnvalue',
michael@0 12767 canThrow: true,
michael@0 12768 operands: []
michael@0 12769 },
michael@0 12770 {
michael@0 12771 name: 'constructsuper',
michael@0 12772 canThrow: true,
michael@0 12773 operands: [
michael@0 12774 {
michael@0 12775 name: 'argCount',
michael@0 12776 size: 'u30',
michael@0 12777 type: ''
michael@0 12778 }
michael@0 12779 ]
michael@0 12780 },
michael@0 12781 {
michael@0 12782 name: 'constructprop',
michael@0 12783 canThrow: true,
michael@0 12784 operands: [
michael@0 12785 {
michael@0 12786 name: 'index',
michael@0 12787 size: 'u30',
michael@0 12788 type: 'M'
michael@0 12789 },
michael@0 12790 {
michael@0 12791 name: 'argCount',
michael@0 12792 size: 'u30',
michael@0 12793 type: ''
michael@0 12794 }
michael@0 12795 ]
michael@0 12796 },
michael@0 12797 {
michael@0 12798 name: 'callsuperid',
michael@0 12799 canThrow: true,
michael@0 12800 operands: null
michael@0 12801 },
michael@0 12802 {
michael@0 12803 name: 'callproplex',
michael@0 12804 canThrow: true,
michael@0 12805 operands: [
michael@0 12806 {
michael@0 12807 name: 'index',
michael@0 12808 size: 'u30',
michael@0 12809 type: 'M'
michael@0 12810 },
michael@0 12811 {
michael@0 12812 name: 'argCount',
michael@0 12813 size: 'u30',
michael@0 12814 type: ''
michael@0 12815 }
michael@0 12816 ]
michael@0 12817 },
michael@0 12818 {
michael@0 12819 name: 'callinterface',
michael@0 12820 canThrow: true,
michael@0 12821 operands: null
michael@0 12822 },
michael@0 12823 {
michael@0 12824 name: 'callsupervoid',
michael@0 12825 canThrow: true,
michael@0 12826 operands: [
michael@0 12827 {
michael@0 12828 name: 'index',
michael@0 12829 size: 'u30',
michael@0 12830 type: 'M'
michael@0 12831 },
michael@0 12832 {
michael@0 12833 name: 'argCount',
michael@0 12834 size: 'u30',
michael@0 12835 type: ''
michael@0 12836 }
michael@0 12837 ]
michael@0 12838 },
michael@0 12839 {
michael@0 12840 name: 'callpropvoid',
michael@0 12841 canThrow: true,
michael@0 12842 operands: [
michael@0 12843 {
michael@0 12844 name: 'index',
michael@0 12845 size: 'u30',
michael@0 12846 type: 'M'
michael@0 12847 },
michael@0 12848 {
michael@0 12849 name: 'argCount',
michael@0 12850 size: 'u30',
michael@0 12851 type: ''
michael@0 12852 }
michael@0 12853 ]
michael@0 12854 },
michael@0 12855 {
michael@0 12856 name: 'sxi1',
michael@0 12857 canThrow: false,
michael@0 12858 operands: []
michael@0 12859 },
michael@0 12860 {
michael@0 12861 name: 'sxi8',
michael@0 12862 canThrow: false,
michael@0 12863 operands: []
michael@0 12864 },
michael@0 12865 {
michael@0 12866 name: 'sxi16',
michael@0 12867 canThrow: false,
michael@0 12868 operands: []
michael@0 12869 },
michael@0 12870 {
michael@0 12871 name: 'applytype',
michael@0 12872 canThrow: true,
michael@0 12873 operands: [
michael@0 12874 {
michael@0 12875 name: 'argCount',
michael@0 12876 size: 'u30',
michael@0 12877 type: ''
michael@0 12878 }
michael@0 12879 ]
michael@0 12880 },
michael@0 12881 {
michael@0 12882 name: 'pushfloat4',
michael@0 12883 canThrow: false,
michael@0 12884 operands: null
michael@0 12885 },
michael@0 12886 {
michael@0 12887 name: 'newobject',
michael@0 12888 canThrow: true,
michael@0 12889 operands: [
michael@0 12890 {
michael@0 12891 name: 'argCount',
michael@0 12892 size: 'u30',
michael@0 12893 type: ''
michael@0 12894 }
michael@0 12895 ]
michael@0 12896 },
michael@0 12897 {
michael@0 12898 name: 'newarray',
michael@0 12899 canThrow: true,
michael@0 12900 operands: [
michael@0 12901 {
michael@0 12902 name: 'argCount',
michael@0 12903 size: 'u30',
michael@0 12904 type: ''
michael@0 12905 }
michael@0 12906 ]
michael@0 12907 },
michael@0 12908 {
michael@0 12909 name: 'newactivation',
michael@0 12910 canThrow: true,
michael@0 12911 operands: []
michael@0 12912 },
michael@0 12913 {
michael@0 12914 name: 'newclass',
michael@0 12915 canThrow: true,
michael@0 12916 operands: [
michael@0 12917 {
michael@0 12918 name: 'index',
michael@0 12919 size: 'u30',
michael@0 12920 type: 'CI'
michael@0 12921 }
michael@0 12922 ]
michael@0 12923 },
michael@0 12924 {
michael@0 12925 name: 'getdescendants',
michael@0 12926 canThrow: true,
michael@0 12927 operands: [
michael@0 12928 {
michael@0 12929 name: 'index',
michael@0 12930 size: 'u30',
michael@0 12931 type: 'M'
michael@0 12932 }
michael@0 12933 ]
michael@0 12934 },
michael@0 12935 {
michael@0 12936 name: 'newcatch',
michael@0 12937 canThrow: true,
michael@0 12938 operands: [
michael@0 12939 {
michael@0 12940 name: 'index',
michael@0 12941 size: 'u30',
michael@0 12942 type: 'EI'
michael@0 12943 }
michael@0 12944 ]
michael@0 12945 },
michael@0 12946 {
michael@0 12947 name: 'findpropglobalstrict',
michael@0 12948 canThrow: true,
michael@0 12949 operands: null
michael@0 12950 },
michael@0 12951 {
michael@0 12952 name: 'findpropglobal',
michael@0 12953 canThrow: true,
michael@0 12954 operands: null
michael@0 12955 },
michael@0 12956 {
michael@0 12957 name: 'findpropstrict',
michael@0 12958 canThrow: true,
michael@0 12959 operands: [
michael@0 12960 {
michael@0 12961 name: 'index',
michael@0 12962 size: 'u30',
michael@0 12963 type: 'M'
michael@0 12964 }
michael@0 12965 ]
michael@0 12966 },
michael@0 12967 {
michael@0 12968 name: 'findproperty',
michael@0 12969 canThrow: true,
michael@0 12970 operands: [
michael@0 12971 {
michael@0 12972 name: 'index',
michael@0 12973 size: 'u30',
michael@0 12974 type: 'M'
michael@0 12975 }
michael@0 12976 ]
michael@0 12977 },
michael@0 12978 {
michael@0 12979 name: 'finddef',
michael@0 12980 canThrow: true,
michael@0 12981 operands: null
michael@0 12982 },
michael@0 12983 {
michael@0 12984 name: 'getlex',
michael@0 12985 canThrow: true,
michael@0 12986 operands: [
michael@0 12987 {
michael@0 12988 name: 'index',
michael@0 12989 size: 'u30',
michael@0 12990 type: 'M'
michael@0 12991 }
michael@0 12992 ]
michael@0 12993 },
michael@0 12994 {
michael@0 12995 name: 'setproperty',
michael@0 12996 canThrow: true,
michael@0 12997 operands: [
michael@0 12998 {
michael@0 12999 name: 'index',
michael@0 13000 size: 'u30',
michael@0 13001 type: 'M'
michael@0 13002 }
michael@0 13003 ]
michael@0 13004 },
michael@0 13005 {
michael@0 13006 name: 'getlocal',
michael@0 13007 canThrow: false,
michael@0 13008 operands: [
michael@0 13009 {
michael@0 13010 name: 'index',
michael@0 13011 size: 'u30',
michael@0 13012 type: ''
michael@0 13013 }
michael@0 13014 ]
michael@0 13015 },
michael@0 13016 {
michael@0 13017 name: 'setlocal',
michael@0 13018 canThrow: false,
michael@0 13019 operands: [
michael@0 13020 {
michael@0 13021 name: 'index',
michael@0 13022 size: 'u30',
michael@0 13023 type: ''
michael@0 13024 }
michael@0 13025 ]
michael@0 13026 },
michael@0 13027 {
michael@0 13028 name: 'getglobalscope',
michael@0 13029 canThrow: false,
michael@0 13030 operands: []
michael@0 13031 },
michael@0 13032 {
michael@0 13033 name: 'getscopeobject',
michael@0 13034 canThrow: false,
michael@0 13035 operands: [
michael@0 13036 {
michael@0 13037 name: 'index',
michael@0 13038 size: 'u30',
michael@0 13039 type: ''
michael@0 13040 }
michael@0 13041 ]
michael@0 13042 },
michael@0 13043 {
michael@0 13044 name: 'getproperty',
michael@0 13045 canThrow: true,
michael@0 13046 operands: [
michael@0 13047 {
michael@0 13048 name: 'index',
michael@0 13049 size: 'u30',
michael@0 13050 type: 'M'
michael@0 13051 }
michael@0 13052 ]
michael@0 13053 },
michael@0 13054 {
michael@0 13055 name: 'getouterscope',
michael@0 13056 canThrow: false,
michael@0 13057 operands: null
michael@0 13058 },
michael@0 13059 {
michael@0 13060 name: 'initproperty',
michael@0 13061 canThrow: true,
michael@0 13062 operands: [
michael@0 13063 {
michael@0 13064 name: 'index',
michael@0 13065 size: 'u30',
michael@0 13066 type: 'M'
michael@0 13067 }
michael@0 13068 ]
michael@0 13069 },
michael@0 13070 null,
michael@0 13071 {
michael@0 13072 name: 'deleteproperty',
michael@0 13073 canThrow: true,
michael@0 13074 operands: [
michael@0 13075 {
michael@0 13076 name: 'index',
michael@0 13077 size: 'u30',
michael@0 13078 type: 'M'
michael@0 13079 }
michael@0 13080 ]
michael@0 13081 },
michael@0 13082 null,
michael@0 13083 {
michael@0 13084 name: 'getslot',
michael@0 13085 canThrow: true,
michael@0 13086 operands: [
michael@0 13087 {
michael@0 13088 name: 'index',
michael@0 13089 size: 'u30',
michael@0 13090 type: ''
michael@0 13091 }
michael@0 13092 ]
michael@0 13093 },
michael@0 13094 {
michael@0 13095 name: 'setslot',
michael@0 13096 canThrow: true,
michael@0 13097 operands: [
michael@0 13098 {
michael@0 13099 name: 'index',
michael@0 13100 size: 'u30',
michael@0 13101 type: ''
michael@0 13102 }
michael@0 13103 ]
michael@0 13104 },
michael@0 13105 {
michael@0 13106 name: 'getglobalslot',
michael@0 13107 canThrow: false,
michael@0 13108 operands: [
michael@0 13109 {
michael@0 13110 name: 'index',
michael@0 13111 size: 'u30',
michael@0 13112 type: ''
michael@0 13113 }
michael@0 13114 ]
michael@0 13115 },
michael@0 13116 {
michael@0 13117 name: 'setglobalslot',
michael@0 13118 canThrow: false,
michael@0 13119 operands: [
michael@0 13120 {
michael@0 13121 name: 'index',
michael@0 13122 size: 'u30',
michael@0 13123 type: ''
michael@0 13124 }
michael@0 13125 ]
michael@0 13126 },
michael@0 13127 {
michael@0 13128 name: 'convert_s',
michael@0 13129 canThrow: true,
michael@0 13130 operands: []
michael@0 13131 },
michael@0 13132 {
michael@0 13133 name: 'esc_xelem',
michael@0 13134 canThrow: true,
michael@0 13135 operands: []
michael@0 13136 },
michael@0 13137 {
michael@0 13138 name: 'esc_xattr',
michael@0 13139 canThrow: true,
michael@0 13140 operands: []
michael@0 13141 },
michael@0 13142 {
michael@0 13143 name: 'convert_i',
michael@0 13144 canThrow: true,
michael@0 13145 operands: []
michael@0 13146 },
michael@0 13147 {
michael@0 13148 name: 'convert_u',
michael@0 13149 canThrow: true,
michael@0 13150 operands: []
michael@0 13151 },
michael@0 13152 {
michael@0 13153 name: 'convert_d',
michael@0 13154 canThrow: true,
michael@0 13155 operands: []
michael@0 13156 },
michael@0 13157 {
michael@0 13158 name: 'convert_b',
michael@0 13159 canThrow: true,
michael@0 13160 operands: []
michael@0 13161 },
michael@0 13162 {
michael@0 13163 name: 'convert_o',
michael@0 13164 canThrow: true,
michael@0 13165 operands: []
michael@0 13166 },
michael@0 13167 {
michael@0 13168 name: 'checkfilter',
michael@0 13169 canThrow: true,
michael@0 13170 operands: []
michael@0 13171 },
michael@0 13172 {
michael@0 13173 name: 'convert_f',
michael@0 13174 canThrow: true,
michael@0 13175 operands: []
michael@0 13176 },
michael@0 13177 {
michael@0 13178 name: 'unplus',
michael@0 13179 canThrow: true,
michael@0 13180 operands: []
michael@0 13181 },
michael@0 13182 {
michael@0 13183 name: 'convert_f4',
michael@0 13184 canThrow: true,
michael@0 13185 operands: []
michael@0 13186 },
michael@0 13187 null,
michael@0 13188 null,
michael@0 13189 null,
michael@0 13190 null,
michael@0 13191 {
michael@0 13192 name: 'coerce',
michael@0 13193 canThrow: true,
michael@0 13194 operands: [
michael@0 13195 {
michael@0 13196 name: 'index',
michael@0 13197 size: 'u30',
michael@0 13198 type: 'M'
michael@0 13199 }
michael@0 13200 ]
michael@0 13201 },
michael@0 13202 {
michael@0 13203 name: 'coerce_b',
michael@0 13204 canThrow: true,
michael@0 13205 operands: []
michael@0 13206 },
michael@0 13207 {
michael@0 13208 name: 'coerce_a',
michael@0 13209 canThrow: true,
michael@0 13210 operands: []
michael@0 13211 },
michael@0 13212 {
michael@0 13213 name: 'coerce_i',
michael@0 13214 canThrow: true,
michael@0 13215 operands: []
michael@0 13216 },
michael@0 13217 {
michael@0 13218 name: 'coerce_d',
michael@0 13219 canThrow: true,
michael@0 13220 operands: []
michael@0 13221 },
michael@0 13222 {
michael@0 13223 name: 'coerce_s',
michael@0 13224 canThrow: true,
michael@0 13225 operands: []
michael@0 13226 },
michael@0 13227 {
michael@0 13228 name: 'astype',
michael@0 13229 canThrow: true,
michael@0 13230 operands: [
michael@0 13231 {
michael@0 13232 name: 'index',
michael@0 13233 size: 'u30',
michael@0 13234 type: 'M'
michael@0 13235 }
michael@0 13236 ]
michael@0 13237 },
michael@0 13238 {
michael@0 13239 name: 'astypelate',
michael@0 13240 canThrow: true,
michael@0 13241 operands: []
michael@0 13242 },
michael@0 13243 {
michael@0 13244 name: 'coerce_u',
michael@0 13245 canThrow: true,
michael@0 13246 operands: []
michael@0 13247 },
michael@0 13248 {
michael@0 13249 name: 'coerce_o',
michael@0 13250 canThrow: true,
michael@0 13251 operands: []
michael@0 13252 },
michael@0 13253 null,
michael@0 13254 null,
michael@0 13255 null,
michael@0 13256 null,
michael@0 13257 null,
michael@0 13258 null,
michael@0 13259 {
michael@0 13260 name: 'negate',
michael@0 13261 canThrow: true,
michael@0 13262 operands: []
michael@0 13263 },
michael@0 13264 {
michael@0 13265 name: 'increment',
michael@0 13266 canThrow: true,
michael@0 13267 operands: []
michael@0 13268 },
michael@0 13269 {
michael@0 13270 name: 'inclocal',
michael@0 13271 canThrow: true,
michael@0 13272 operands: [
michael@0 13273 {
michael@0 13274 name: 'index',
michael@0 13275 size: 'u30',
michael@0 13276 type: ''
michael@0 13277 }
michael@0 13278 ]
michael@0 13279 },
michael@0 13280 {
michael@0 13281 name: 'decrement',
michael@0 13282 canThrow: true,
michael@0 13283 operands: []
michael@0 13284 },
michael@0 13285 {
michael@0 13286 name: 'declocal',
michael@0 13287 canThrow: true,
michael@0 13288 operands: [
michael@0 13289 {
michael@0 13290 name: 'index',
michael@0 13291 size: 'u30',
michael@0 13292 type: ''
michael@0 13293 }
michael@0 13294 ]
michael@0 13295 },
michael@0 13296 {
michael@0 13297 name: 'typeof',
michael@0 13298 canThrow: false,
michael@0 13299 operands: []
michael@0 13300 },
michael@0 13301 {
michael@0 13302 name: 'not',
michael@0 13303 canThrow: false,
michael@0 13304 operands: []
michael@0 13305 },
michael@0 13306 {
michael@0 13307 name: 'bitnot',
michael@0 13308 canThrow: true,
michael@0 13309 operands: []
michael@0 13310 },
michael@0 13311 null,
michael@0 13312 null,
michael@0 13313 null,
michael@0 13314 null,
michael@0 13315 null,
michael@0 13316 null,
michael@0 13317 null,
michael@0 13318 null,
michael@0 13319 {
michael@0 13320 name: 'add',
michael@0 13321 canThrow: true,
michael@0 13322 operands: []
michael@0 13323 },
michael@0 13324 {
michael@0 13325 name: 'subtract',
michael@0 13326 canThrow: true,
michael@0 13327 operands: []
michael@0 13328 },
michael@0 13329 {
michael@0 13330 name: 'multiply',
michael@0 13331 canThrow: true,
michael@0 13332 operands: []
michael@0 13333 },
michael@0 13334 {
michael@0 13335 name: 'divide',
michael@0 13336 canThrow: true,
michael@0 13337 operands: []
michael@0 13338 },
michael@0 13339 {
michael@0 13340 name: 'modulo',
michael@0 13341 canThrow: true,
michael@0 13342 operands: []
michael@0 13343 },
michael@0 13344 {
michael@0 13345 name: 'lshift',
michael@0 13346 canThrow: true,
michael@0 13347 operands: []
michael@0 13348 },
michael@0 13349 {
michael@0 13350 name: 'rshift',
michael@0 13351 canThrow: true,
michael@0 13352 operands: []
michael@0 13353 },
michael@0 13354 {
michael@0 13355 name: 'urshift',
michael@0 13356 canThrow: true,
michael@0 13357 operands: []
michael@0 13358 },
michael@0 13359 {
michael@0 13360 name: 'bitand',
michael@0 13361 canThrow: true,
michael@0 13362 operands: []
michael@0 13363 },
michael@0 13364 {
michael@0 13365 name: 'bitor',
michael@0 13366 canThrow: true,
michael@0 13367 operands: []
michael@0 13368 },
michael@0 13369 {
michael@0 13370 name: 'bitxor',
michael@0 13371 canThrow: true,
michael@0 13372 operands: []
michael@0 13373 },
michael@0 13374 {
michael@0 13375 name: 'equals',
michael@0 13376 canThrow: true,
michael@0 13377 operands: []
michael@0 13378 },
michael@0 13379 {
michael@0 13380 name: 'strictequals',
michael@0 13381 canThrow: true,
michael@0 13382 operands: []
michael@0 13383 },
michael@0 13384 {
michael@0 13385 name: 'lessthan',
michael@0 13386 canThrow: true,
michael@0 13387 operands: []
michael@0 13388 },
michael@0 13389 {
michael@0 13390 name: 'lessequals',
michael@0 13391 canThrow: true,
michael@0 13392 operands: []
michael@0 13393 },
michael@0 13394 {
michael@0 13395 name: 'greaterthan',
michael@0 13396 canThrow: true,
michael@0 13397 operands: []
michael@0 13398 },
michael@0 13399 {
michael@0 13400 name: 'greaterequals',
michael@0 13401 canThrow: true,
michael@0 13402 operands: []
michael@0 13403 },
michael@0 13404 {
michael@0 13405 name: 'instanceof',
michael@0 13406 canThrow: true,
michael@0 13407 operands: []
michael@0 13408 },
michael@0 13409 {
michael@0 13410 name: 'istype',
michael@0 13411 canThrow: true,
michael@0 13412 operands: [
michael@0 13413 {
michael@0 13414 name: 'index',
michael@0 13415 size: 'u30',
michael@0 13416 type: 'M'
michael@0 13417 }
michael@0 13418 ]
michael@0 13419 },
michael@0 13420 {
michael@0 13421 name: 'istypelate',
michael@0 13422 canThrow: true,
michael@0 13423 operands: []
michael@0 13424 },
michael@0 13425 {
michael@0 13426 name: 'in',
michael@0 13427 canThrow: true,
michael@0 13428 operands: []
michael@0 13429 },
michael@0 13430 null,
michael@0 13431 null,
michael@0 13432 null,
michael@0 13433 null,
michael@0 13434 null,
michael@0 13435 null,
michael@0 13436 null,
michael@0 13437 null,
michael@0 13438 null,
michael@0 13439 null,
michael@0 13440 null,
michael@0 13441 {
michael@0 13442 name: 'increment_i',
michael@0 13443 canThrow: true,
michael@0 13444 operands: []
michael@0 13445 },
michael@0 13446 {
michael@0 13447 name: 'decrement_i',
michael@0 13448 canThrow: true,
michael@0 13449 operands: []
michael@0 13450 },
michael@0 13451 {
michael@0 13452 name: 'inclocal_i',
michael@0 13453 canThrow: true,
michael@0 13454 operands: [
michael@0 13455 {
michael@0 13456 name: 'index',
michael@0 13457 size: 'u30',
michael@0 13458 type: ''
michael@0 13459 }
michael@0 13460 ]
michael@0 13461 },
michael@0 13462 {
michael@0 13463 name: 'declocal_i',
michael@0 13464 canThrow: true,
michael@0 13465 operands: [
michael@0 13466 {
michael@0 13467 name: 'index',
michael@0 13468 size: 'u30',
michael@0 13469 type: ''
michael@0 13470 }
michael@0 13471 ]
michael@0 13472 },
michael@0 13473 {
michael@0 13474 name: 'negate_i',
michael@0 13475 canThrow: true,
michael@0 13476 operands: []
michael@0 13477 },
michael@0 13478 {
michael@0 13479 name: 'add_i',
michael@0 13480 canThrow: true,
michael@0 13481 operands: []
michael@0 13482 },
michael@0 13483 {
michael@0 13484 name: 'subtract_i',
michael@0 13485 canThrow: true,
michael@0 13486 operands: []
michael@0 13487 },
michael@0 13488 {
michael@0 13489 name: 'multiply_i',
michael@0 13490 canThrow: true,
michael@0 13491 operands: []
michael@0 13492 },
michael@0 13493 null,
michael@0 13494 null,
michael@0 13495 null,
michael@0 13496 null,
michael@0 13497 null,
michael@0 13498 null,
michael@0 13499 null,
michael@0 13500 null,
michael@0 13501 {
michael@0 13502 name: 'getlocal0',
michael@0 13503 canThrow: false,
michael@0 13504 operands: []
michael@0 13505 },
michael@0 13506 {
michael@0 13507 name: 'getlocal1',
michael@0 13508 canThrow: false,
michael@0 13509 operands: []
michael@0 13510 },
michael@0 13511 {
michael@0 13512 name: 'getlocal2',
michael@0 13513 canThrow: false,
michael@0 13514 operands: []
michael@0 13515 },
michael@0 13516 {
michael@0 13517 name: 'getlocal3',
michael@0 13518 canThrow: false,
michael@0 13519 operands: []
michael@0 13520 },
michael@0 13521 {
michael@0 13522 name: 'setlocal0',
michael@0 13523 canThrow: false,
michael@0 13524 operands: []
michael@0 13525 },
michael@0 13526 {
michael@0 13527 name: 'setlocal1',
michael@0 13528 canThrow: false,
michael@0 13529 operands: []
michael@0 13530 },
michael@0 13531 {
michael@0 13532 name: 'setlocal2',
michael@0 13533 canThrow: false,
michael@0 13534 operands: []
michael@0 13535 },
michael@0 13536 {
michael@0 13537 name: 'setlocal3',
michael@0 13538 canThrow: false,
michael@0 13539 operands: []
michael@0 13540 },
michael@0 13541 null,
michael@0 13542 null,
michael@0 13543 null,
michael@0 13544 null,
michael@0 13545 null,
michael@0 13546 null,
michael@0 13547 null,
michael@0 13548 null,
michael@0 13549 null,
michael@0 13550 null,
michael@0 13551 null,
michael@0 13552 null,
michael@0 13553 null,
michael@0 13554 null,
michael@0 13555 null,
michael@0 13556 null,
michael@0 13557 null,
michael@0 13558 null,
michael@0 13559 null,
michael@0 13560 null,
michael@0 13561 null,
michael@0 13562 {
michael@0 13563 name: 'invalid',
michael@0 13564 canThrow: false,
michael@0 13565 operands: []
michael@0 13566 },
michael@0 13567 null,
michael@0 13568 {
michael@0 13569 name: 'debug',
michael@0 13570 canThrow: true,
michael@0 13571 operands: [
michael@0 13572 {
michael@0 13573 name: 'debugType',
michael@0 13574 size: 'u08',
michael@0 13575 type: ''
michael@0 13576 },
michael@0 13577 {
michael@0 13578 name: 'index',
michael@0 13579 size: 'u30',
michael@0 13580 type: 'S'
michael@0 13581 },
michael@0 13582 {
michael@0 13583 name: 'reg',
michael@0 13584 size: 'u08',
michael@0 13585 type: ''
michael@0 13586 },
michael@0 13587 {
michael@0 13588 name: 'extra',
michael@0 13589 size: 'u30',
michael@0 13590 type: ''
michael@0 13591 }
michael@0 13592 ]
michael@0 13593 },
michael@0 13594 {
michael@0 13595 name: 'debugline',
michael@0 13596 canThrow: true,
michael@0 13597 operands: [
michael@0 13598 {
michael@0 13599 name: 'lineNumber',
michael@0 13600 size: 'u30',
michael@0 13601 type: ''
michael@0 13602 }
michael@0 13603 ]
michael@0 13604 },
michael@0 13605 {
michael@0 13606 name: 'debugfile',
michael@0 13607 canThrow: true,
michael@0 13608 operands: [
michael@0 13609 {
michael@0 13610 name: 'index',
michael@0 13611 size: 'u30',
michael@0 13612 type: 'S'
michael@0 13613 }
michael@0 13614 ]
michael@0 13615 },
michael@0 13616 null,
michael@0 13617 null,
michael@0 13618 null,
michael@0 13619 null,
michael@0 13620 null,
michael@0 13621 null,
michael@0 13622 null,
michael@0 13623 null,
michael@0 13624 null,
michael@0 13625 null,
michael@0 13626 null,
michael@0 13627 null,
michael@0 13628 null,
michael@0 13629 null
michael@0 13630 ];
michael@0 13631 function opcodeName(op) {
michael@0 13632 return AVM2.opcodeTable[op].name;
michael@0 13633 }
michael@0 13634 AVM2.opcodeName = opcodeName;
michael@0 13635 }(Shumway.AVM2 || (Shumway.AVM2 = {})));
michael@0 13636 var AVM2 = Shumway.AVM2;
michael@0 13637 }(Shumway || (Shumway = {})));
michael@0 13638 var opcodeTable = Shumway.AVM2.opcodeTable;
michael@0 13639 var opcodeName = Shumway.AVM2.opcodeName;
michael@0 13640 var opcodeTable = Shumway.AVM2.opcodeTable;
michael@0 13641 var opcodeName = Shumway.AVM2.opcodeName;
michael@0 13642 var __extends = this.__extends || function (d, b) {
michael@0 13643 for (var p in b)
michael@0 13644 if (b.hasOwnProperty(p))
michael@0 13645 d[p] = b[p];
michael@0 13646 function __() {
michael@0 13647 this.constructor = d;
michael@0 13648 }
michael@0 13649 __.prototype = b.prototype;
michael@0 13650 d.prototype = new __();
michael@0 13651 };
michael@0 13652 var Shumway;
michael@0 13653 (function (Shumway) {
michael@0 13654 (function (AVM2) {
michael@0 13655 (function (ABC) {
michael@0 13656 var Timer = Shumway.Metrics.Timer;
michael@0 13657 var isString = Shumway.isString;
michael@0 13658 var isNumber = Shumway.isNumber;
michael@0 13659 var isNumeric = Shumway.isNumeric;
michael@0 13660 var isObject = Shumway.isObject;
michael@0 13661 var textDecoder = null;
michael@0 13662 if (typeof TextDecoder !== 'undefined') {
michael@0 13663 textDecoder = new TextDecoder();
michael@0 13664 }
michael@0 13665 var AbcStream = function () {
michael@0 13666 function AbcStream(bytes) {
michael@0 13667 this._bytes = bytes;
michael@0 13668 this._view = new DataView(bytes.buffer, bytes.byteOffset);
michael@0 13669 this._position = 0;
michael@0 13670 }
michael@0 13671 AbcStream._getResultBuffer = function (length) {
michael@0 13672 if (!AbcStream._resultBuffer || AbcStream._resultBuffer.length < length) {
michael@0 13673 AbcStream._resultBuffer = new Int32Array(length * 2);
michael@0 13674 }
michael@0 13675 return AbcStream._resultBuffer;
michael@0 13676 };
michael@0 13677 Object.defineProperty(AbcStream.prototype, 'position', {
michael@0 13678 get: function () {
michael@0 13679 return this._position;
michael@0 13680 },
michael@0 13681 enumerable: true,
michael@0 13682 configurable: true
michael@0 13683 });
michael@0 13684 AbcStream.prototype.remaining = function () {
michael@0 13685 return this._bytes.length - this._position;
michael@0 13686 };
michael@0 13687 AbcStream.prototype.seek = function (position) {
michael@0 13688 this._position = position;
michael@0 13689 };
michael@0 13690 AbcStream.prototype.readU8 = function () {
michael@0 13691 return this._bytes[this._position++];
michael@0 13692 };
michael@0 13693 AbcStream.prototype.readU8s = function (count) {
michael@0 13694 var b = new Uint8Array(count);
michael@0 13695 b.set(this._bytes.subarray(this._position, this._position + count), 0);
michael@0 13696 this._position += count;
michael@0 13697 return b;
michael@0 13698 };
michael@0 13699 AbcStream.prototype.readS8 = function () {
michael@0 13700 return this._bytes[this._position++] << 24 >> 24;
michael@0 13701 };
michael@0 13702 AbcStream.prototype.readU32 = function () {
michael@0 13703 return this.readS32() >>> 0;
michael@0 13704 };
michael@0 13705 AbcStream.prototype.readU30 = function () {
michael@0 13706 var result = this.readU32();
michael@0 13707 if (result & 3221225472) {
michael@0 13708 return result;
michael@0 13709 }
michael@0 13710 return result;
michael@0 13711 };
michael@0 13712 AbcStream.prototype.readU30Unsafe = function () {
michael@0 13713 return this.readU32();
michael@0 13714 };
michael@0 13715 AbcStream.prototype.readS16 = function () {
michael@0 13716 return this.readU30Unsafe() << 16 >> 16;
michael@0 13717 };
michael@0 13718 AbcStream.prototype.readS32 = function () {
michael@0 13719 var result = this.readU8();
michael@0 13720 if (result & 128) {
michael@0 13721 result = result & 127 | this.readU8() << 7;
michael@0 13722 if (result & 16384) {
michael@0 13723 result = result & 16383 | this.readU8() << 14;
michael@0 13724 if (result & 2097152) {
michael@0 13725 result = result & 2097151 | this.readU8() << 21;
michael@0 13726 if (result & 268435456) {
michael@0 13727 result = result & 268435455 | this.readU8() << 28;
michael@0 13728 result = result & 4294967295;
michael@0 13729 }
michael@0 13730 }
michael@0 13731 }
michael@0 13732 }
michael@0 13733 return result;
michael@0 13734 };
michael@0 13735 AbcStream.prototype.readWord = function () {
michael@0 13736 var result = this._view.getUint32(this._position, true);
michael@0 13737 this._position += 4;
michael@0 13738 return result;
michael@0 13739 };
michael@0 13740 AbcStream.prototype.readS24 = function () {
michael@0 13741 var u = this.readU8() | this.readU8() << 8 | this.readU8() << 16;
michael@0 13742 return u << 8 >> 8;
michael@0 13743 };
michael@0 13744 AbcStream.prototype.readDouble = function () {
michael@0 13745 var result = this._view.getFloat64(this._position, true);
michael@0 13746 this._position += 8;
michael@0 13747 return result;
michael@0 13748 };
michael@0 13749 AbcStream.prototype.readUTFString = function (length) {
michael@0 13750 if (textDecoder) {
michael@0 13751 var position = this._position;
michael@0 13752 this._position += length;
michael@0 13753 return textDecoder.decode(this._bytes.subarray(position, position + length));
michael@0 13754 }
michael@0 13755 var pos = this._position;
michael@0 13756 var end = pos + length;
michael@0 13757 var bytes = this._bytes;
michael@0 13758 var i = 0;
michael@0 13759 var result = AbcStream._getResultBuffer(length * 2);
michael@0 13760 while (pos < end) {
michael@0 13761 var c = bytes[pos++];
michael@0 13762 if (c <= 127) {
michael@0 13763 result[i++] = c;
michael@0 13764 } else if (c >= 192) {
michael@0 13765 var code = 0;
michael@0 13766 if (c < 224) {
michael@0 13767 code = (c & 31) << 6 | bytes[pos++] & 63;
michael@0 13768 } else if (c < 240) {
michael@0 13769 code = (c & 15) << 12 | (bytes[pos++] & 63) << 6 | bytes[pos++] & 63;
michael@0 13770 } else {
michael@0 13771 code = ((c & 7) << 18 | (bytes[pos++] & 63) << 12 | (bytes[pos++] & 63) << 6 | bytes[pos++] & 63) - 65536;
michael@0 13772 result[i++] = ((code & 1047552) >>> 10) + 55296;
michael@0 13773 code = (code & 1023) + 56320;
michael@0 13774 }
michael@0 13775 result[i++] = code;
michael@0 13776 }
michael@0 13777 }
michael@0 13778 this._position = pos;
michael@0 13779 return Shumway.StringUtilities.fromCharCodeArray(result.subarray(0, i));
michael@0 13780 };
michael@0 13781 AbcStream._resultBuffer = new Int32Array(256);
michael@0 13782 return AbcStream;
michael@0 13783 }();
michael@0 13784 ABC.AbcStream = AbcStream;
michael@0 13785 var Parameter = function () {
michael@0 13786 function Parameter(name, type, value) {
michael@0 13787 this.name = name;
michael@0 13788 this.type = type;
michael@0 13789 this.value = value;
michael@0 13790 }
michael@0 13791 return Parameter;
michael@0 13792 }();
michael@0 13793 ABC.Parameter = Parameter;
michael@0 13794 var Trait = function () {
michael@0 13795 function Trait(abc, stream, holder) {
michael@0 13796 var constantPool = abc.constantPool;
michael@0 13797 var methods = abc.methods;
michael@0 13798 var classes = abc.classes;
michael@0 13799 var metadata = abc.metadata;
michael@0 13800 this.holder = holder;
michael@0 13801 this.name = constantPool.multinames[stream.readU30()];
michael@0 13802 var tag = stream.readU8();
michael@0 13803 this.kind = tag & 15;
michael@0 13804 this.attributes = tag >> 4 & 15;
michael@0 13805 true;
michael@0 13806 switch (this.kind) {
michael@0 13807 case 0:
michael@0 13808 case 6:
michael@0 13809 this.slotId = stream.readU30();
michael@0 13810 this.typeName = constantPool.multinames[stream.readU30()];
michael@0 13811 var valueIndex = stream.readU30();
michael@0 13812 this.value = undefined;
michael@0 13813 if (valueIndex !== 0) {
michael@0 13814 this.hasDefaultValue = true;
michael@0 13815 this.value = constantPool.getValue(stream.readU8(), valueIndex);
michael@0 13816 }
michael@0 13817 break;
michael@0 13818 case 1:
michael@0 13819 case 3:
michael@0 13820 case 2:
michael@0 13821 this.dispId = stream.readU30();
michael@0 13822 this.methodInfo = methods[stream.readU30()];
michael@0 13823 this.methodInfo.name = this.name;
michael@0 13824 AbcFile.attachHolder(this.methodInfo, this.holder);
michael@0 13825 this.methodInfo.abc = abc;
michael@0 13826 break;
michael@0 13827 case 4:
michael@0 13828 this.slotId = stream.readU30();
michael@0 13829 true;
michael@0 13830 this.classInfo = classes[stream.readU30()];
michael@0 13831 break;
michael@0 13832 case 5:
michael@0 13833 true;
michael@0 13834 break;
michael@0 13835 }
michael@0 13836 if (this.attributes & 4) {
michael@0 13837 var traitMetadata;
michael@0 13838 for (var i = 0, j = stream.readU30(); i < j; i++) {
michael@0 13839 var md = metadata[stream.readU30()];
michael@0 13840 if (md.name === '__go_to_definition_help' || md.name === '__go_to_ctor_definition_help') {
michael@0 13841 continue;
michael@0 13842 }
michael@0 13843 if (!traitMetadata) {
michael@0 13844 traitMetadata = {};
michael@0 13845 }
michael@0 13846 traitMetadata[md.name] = md;
michael@0 13847 }
michael@0 13848 if (traitMetadata) {
michael@0 13849 if (this.isClass()) {
michael@0 13850 this.classInfo.metadata = traitMetadata;
michael@0 13851 }
michael@0 13852 this.metadata = traitMetadata;
michael@0 13853 }
michael@0 13854 }
michael@0 13855 }
michael@0 13856 Trait.prototype.isSlot = function () {
michael@0 13857 return this.kind === 0;
michael@0 13858 };
michael@0 13859 Trait.prototype.isConst = function () {
michael@0 13860 return this.kind === 6;
michael@0 13861 };
michael@0 13862 Trait.prototype.isMethod = function () {
michael@0 13863 return this.kind === 1;
michael@0 13864 };
michael@0 13865 Trait.prototype.isClass = function () {
michael@0 13866 return this.kind === 4;
michael@0 13867 };
michael@0 13868 Trait.prototype.isGetter = function () {
michael@0 13869 return this.kind === 2;
michael@0 13870 };
michael@0 13871 Trait.prototype.isSetter = function () {
michael@0 13872 return this.kind === 3;
michael@0 13873 };
michael@0 13874 Trait.prototype.isProtected = function () {
michael@0 13875 true;
michael@0 13876 return this.name.namespaces[0].isProtected();
michael@0 13877 };
michael@0 13878 Trait.prototype.kindName = function () {
michael@0 13879 switch (this.kind) {
michael@0 13880 case 0:
michael@0 13881 return 'Slot';
michael@0 13882 case 6:
michael@0 13883 return 'Const';
michael@0 13884 case 1:
michael@0 13885 return 'Method';
michael@0 13886 case 3:
michael@0 13887 return 'Setter';
michael@0 13888 case 2:
michael@0 13889 return 'Getter';
michael@0 13890 case 4:
michael@0 13891 return 'Class';
michael@0 13892 case 5:
michael@0 13893 return 'Function';
michael@0 13894 }
michael@0 13895 Shumway.Debug.unexpected();
michael@0 13896 };
michael@0 13897 Trait.prototype.isOverride = function () {
michael@0 13898 return this.attributes & 2;
michael@0 13899 };
michael@0 13900 Trait.prototype.isFinal = function () {
michael@0 13901 return this.attributes & 1;
michael@0 13902 };
michael@0 13903 Trait.prototype.toString = function () {
michael@0 13904 var str = Shumway.IntegerUtilities.getFlags(this.attributes, 'final|override|metadata'.split('|'));
michael@0 13905 if (str) {
michael@0 13906 str += ' ';
michael@0 13907 }
michael@0 13908 str += Multiname.getQualifiedName(this.name);
michael@0 13909 switch (this.kind) {
michael@0 13910 case 0:
michael@0 13911 case 6:
michael@0 13912 return str + ', typeName: ' + this.typeName + ', slotId: ' + this.slotId + ', value: ' + this.value;
michael@0 13913 case 1:
michael@0 13914 case 3:
michael@0 13915 case 2:
michael@0 13916 return str + ', ' + this.kindName() + ': ' + this.methodInfo.name;
michael@0 13917 case 4:
michael@0 13918 return str + ', slotId: ' + this.slotId + ', class: ' + this.classInfo;
michael@0 13919 case 5:
michael@0 13920 break;
michael@0 13921 }
michael@0 13922 };
michael@0 13923 Trait.parseTraits = function (abc, stream, holder) {
michael@0 13924 var count = stream.readU30();
michael@0 13925 var traits = [];
michael@0 13926 for (var i = 0; i < count; i++) {
michael@0 13927 traits.push(new Trait(abc, stream, holder));
michael@0 13928 }
michael@0 13929 return traits;
michael@0 13930 };
michael@0 13931 return Trait;
michael@0 13932 }();
michael@0 13933 ABC.Trait = Trait;
michael@0 13934 var Info = function () {
michael@0 13935 function Info(abc, index) {
michael@0 13936 this.abc = abc;
michael@0 13937 this.index = index;
michael@0 13938 }
michael@0 13939 return Info;
michael@0 13940 }();
michael@0 13941 ABC.Info = Info;
michael@0 13942 var MethodInfo = function (_super) {
michael@0 13943 __extends(MethodInfo, _super);
michael@0 13944 function MethodInfo(abc, index, stream) {
michael@0 13945 _super.call(this, abc, index);
michael@0 13946 var constantPool = abc.constantPool;
michael@0 13947 var parameterCount = stream.readU30();
michael@0 13948 this.returnType = constantPool.multinames[stream.readU30()];
michael@0 13949 this.parameters = [];
michael@0 13950 for (var i = 0; i < parameterCount; i++) {
michael@0 13951 this.parameters.push(new Parameter(undefined, constantPool.multinames[stream.readU30()], undefined));
michael@0 13952 }
michael@0 13953 this.debugName = constantPool.strings[stream.readU30()];
michael@0 13954 this.flags = stream.readU8();
michael@0 13955 var optionalCount = 0;
michael@0 13956 if (this.flags & 8) {
michael@0 13957 optionalCount = stream.readU30();
michael@0 13958 true;
michael@0 13959 for (var i = parameterCount - optionalCount; i < parameterCount; i++) {
michael@0 13960 var valueIndex = stream.readU30();
michael@0 13961 this.parameters[i].value = constantPool.getValue(stream.readU8(), valueIndex);
michael@0 13962 }
michael@0 13963 }
michael@0 13964 if (this.flags & 128) {
michael@0 13965 for (var i = 0; i < parameterCount; i++) {
michael@0 13966 if (false) {
michael@0 13967 this.parameters[i].name = constantPool.strings[stream.readU30()];
michael@0 13968 } else {
michael@0 13969 stream.readU30();
michael@0 13970 this.parameters[i].name = MethodInfo._getParameterName(i);
michael@0 13971 }
michael@0 13972 }
michael@0 13973 } else {
michael@0 13974 for (var i = 0; i < parameterCount; i++) {
michael@0 13975 this.parameters[i].name = MethodInfo._getParameterName(i);
michael@0 13976 }
michael@0 13977 }
michael@0 13978 }
michael@0 13979 MethodInfo._getParameterName = function (i) {
michael@0 13980 true;
michael@0 13981 return String.fromCharCode('A'.charCodeAt(0) + i);
michael@0 13982 };
michael@0 13983 MethodInfo.prototype.toString = function () {
michael@0 13984 var flags = Shumway.IntegerUtilities.getFlags(this.flags, 'NEED_ARGUMENTS|NEED_ACTIVATION|NEED_REST|HAS_OPTIONAL|||SET_DXN|HAS_PARAM_NAMES'.split('|'));
michael@0 13985 return (flags ? flags + ' ' : '') + this.name;
michael@0 13986 };
michael@0 13987 MethodInfo.prototype.hasOptional = function () {
michael@0 13988 return !(!(this.flags & 8));
michael@0 13989 };
michael@0 13990 MethodInfo.prototype.needsActivation = function () {
michael@0 13991 return !(!(this.flags & 2));
michael@0 13992 };
michael@0 13993 MethodInfo.prototype.needsRest = function () {
michael@0 13994 return !(!(this.flags & 4));
michael@0 13995 };
michael@0 13996 MethodInfo.prototype.needsArguments = function () {
michael@0 13997 return !(!(this.flags & 1));
michael@0 13998 };
michael@0 13999 MethodInfo.prototype.isNative = function () {
michael@0 14000 return !(!(this.flags & 32));
michael@0 14001 };
michael@0 14002 MethodInfo.prototype.isClassMember = function () {
michael@0 14003 return this.holder instanceof ClassInfo;
michael@0 14004 };
michael@0 14005 MethodInfo.prototype.isInstanceMember = function () {
michael@0 14006 return this.holder instanceof InstanceInfo;
michael@0 14007 };
michael@0 14008 MethodInfo.prototype.isScriptMember = function () {
michael@0 14009 return this.holder instanceof ScriptInfo;
michael@0 14010 };
michael@0 14011 MethodInfo.parseException = function (abc, stream) {
michael@0 14012 var multinames = abc.constantPool.multinames;
michael@0 14013 var ex = {
michael@0 14014 start: stream.readU30(),
michael@0 14015 end: stream.readU30(),
michael@0 14016 target: stream.readU30(),
michael@0 14017 typeName: multinames[stream.readU30()],
michael@0 14018 varName: multinames[stream.readU30()]
michael@0 14019 };
michael@0 14020 true;
michael@0 14021 true;
michael@0 14022 return ex;
michael@0 14023 };
michael@0 14024 MethodInfo.parseBody = function (abc, stream) {
michael@0 14025 var constantPool = abc.constantPool;
michael@0 14026 var methods = abc.methods;
michael@0 14027 var index = stream.readU30();
michael@0 14028 var mi = methods[index];
michael@0 14029 mi.index = index;
michael@0 14030 mi.hasBody = true;
michael@0 14031 mi.hash = abc.hash + 196608 + index;
michael@0 14032 true;
michael@0 14033 mi.maxStack = stream.readU30();
michael@0 14034 mi.localCount = stream.readU30();
michael@0 14035 mi.initScopeDepth = stream.readU30();
michael@0 14036 mi.maxScopeDepth = stream.readU30();
michael@0 14037 mi.code = stream.readU8s(stream.readU30());
michael@0 14038 var exceptions = [];
michael@0 14039 var exceptionCount = stream.readU30();
michael@0 14040 for (var i = 0; i < exceptionCount; ++i) {
michael@0 14041 exceptions.push(MethodInfo.parseException(abc, stream));
michael@0 14042 }
michael@0 14043 mi.exceptions = exceptions;
michael@0 14044 mi.traits = Trait.parseTraits(abc, stream, mi);
michael@0 14045 };
michael@0 14046 MethodInfo.prototype.hasExceptions = function () {
michael@0 14047 return this.exceptions.length > 0;
michael@0 14048 };
michael@0 14049 return MethodInfo;
michael@0 14050 }(Info);
michael@0 14051 ABC.MethodInfo = MethodInfo;
michael@0 14052 var InstanceInfo = function (_super) {
michael@0 14053 __extends(InstanceInfo, _super);
michael@0 14054 function InstanceInfo(abc, index, stream) {
michael@0 14055 _super.call(this, abc, index);
michael@0 14056 this.runtimeId = InstanceInfo.nextID++;
michael@0 14057 var constantPool = abc.constantPool;
michael@0 14058 var methods = abc.methods;
michael@0 14059 this.name = constantPool.multinames[stream.readU30()];
michael@0 14060 true;
michael@0 14061 this.superName = constantPool.multinames[stream.readU30()];
michael@0 14062 this.flags = stream.readU8();
michael@0 14063 this.protectedNs = undefined;
michael@0 14064 if (this.flags & 8) {
michael@0 14065 this.protectedNs = constantPool.namespaces[stream.readU30()];
michael@0 14066 }
michael@0 14067 var interfaceCount = stream.readU30();
michael@0 14068 this.interfaces = [];
michael@0 14069 for (var i = 0; i < interfaceCount; i++) {
michael@0 14070 this.interfaces[i] = constantPool.multinames[stream.readU30()];
michael@0 14071 }
michael@0 14072 this.init = methods[stream.readU30()];
michael@0 14073 this.init.isInstanceInitializer = true;
michael@0 14074 this.init.name = this.name;
michael@0 14075 AbcFile.attachHolder(this.init, this);
michael@0 14076 this.traits = Trait.parseTraits(abc, stream, this);
michael@0 14077 }
michael@0 14078 InstanceInfo.prototype.toString = function () {
michael@0 14079 var flags = Shumway.IntegerUtilities.getFlags(this.flags & 8, 'sealed|final|interface|protected'.split('|'));
michael@0 14080 var str = (flags ? flags + ' ' : '') + this.name;
michael@0 14081 if (this.superName) {
michael@0 14082 str += ' extends ' + this.superName;
michael@0 14083 }
michael@0 14084 return str;
michael@0 14085 };
michael@0 14086 InstanceInfo.prototype.isFinal = function () {
michael@0 14087 return !(!(this.flags & 2));
michael@0 14088 };
michael@0 14089 InstanceInfo.prototype.isSealed = function () {
michael@0 14090 return !(!(this.flags & 1));
michael@0 14091 };
michael@0 14092 InstanceInfo.prototype.isInterface = function () {
michael@0 14093 return !(!(this.flags & 4));
michael@0 14094 };
michael@0 14095 InstanceInfo.nextID = 1;
michael@0 14096 return InstanceInfo;
michael@0 14097 }(Info);
michael@0 14098 ABC.InstanceInfo = InstanceInfo;
michael@0 14099 var ClassInfo = function (_super) {
michael@0 14100 __extends(ClassInfo, _super);
michael@0 14101 function ClassInfo(abc, index, stream) {
michael@0 14102 _super.call(this, abc, index);
michael@0 14103 this.runtimeId = ClassInfo.nextID++;
michael@0 14104 this.abc = abc;
michael@0 14105 this.hash = abc.hash + 65536 + index;
michael@0 14106 this.index = index;
michael@0 14107 this.init = abc.methods[stream.readU30()];
michael@0 14108 this.init.isClassInitializer = true;
michael@0 14109 AbcFile.attachHolder(this.init, this);
michael@0 14110 this.traits = Trait.parseTraits(abc, stream, this);
michael@0 14111 this.instanceInfo = abc.instances[index];
michael@0 14112 this.instanceInfo.classInfo = this;
michael@0 14113 this.defaultValue = ClassInfo._getDefaultValue(this.instanceInfo.name);
michael@0 14114 }
michael@0 14115 ClassInfo._getDefaultValue = function (qn) {
michael@0 14116 if (Multiname.getQualifiedName(qn) === Multiname.Int || Multiname.getQualifiedName(qn) === Multiname.Uint) {
michael@0 14117 return 0;
michael@0 14118 } else if (Multiname.getQualifiedName(qn) === Multiname.Number) {
michael@0 14119 return NaN;
michael@0 14120 } else if (Multiname.getQualifiedName(qn) === Multiname.Boolean) {
michael@0 14121 return false;
michael@0 14122 } else {
michael@0 14123 return null;
michael@0 14124 }
michael@0 14125 };
michael@0 14126 ClassInfo.prototype.toString = function () {
michael@0 14127 return this.instanceInfo.name.toString();
michael@0 14128 };
michael@0 14129 ClassInfo.nextID = 1;
michael@0 14130 return ClassInfo;
michael@0 14131 }(Info);
michael@0 14132 ABC.ClassInfo = ClassInfo;
michael@0 14133 var ScriptInfo = function (_super) {
michael@0 14134 __extends(ScriptInfo, _super);
michael@0 14135 function ScriptInfo(abc, index, stream) {
michael@0 14136 _super.call(this, abc, index);
michael@0 14137 this.runtimeId = ClassInfo.nextID++;
michael@0 14138 this.hash = abc.hash + 131072 + index;
michael@0 14139 this.name = abc.name + '$script' + index;
michael@0 14140 this.init = abc.methods[stream.readU30()];
michael@0 14141 this.init.isScriptInitializer = true;
michael@0 14142 AbcFile.attachHolder(this.init, this);
michael@0 14143 this.traits = Trait.parseTraits(abc, stream, this);
michael@0 14144 }
michael@0 14145 Object.defineProperty(ScriptInfo.prototype, 'entryPoint', {
michael@0 14146 get: function () {
michael@0 14147 return this.init;
michael@0 14148 },
michael@0 14149 enumerable: true,
michael@0 14150 configurable: true
michael@0 14151 });
michael@0 14152 ScriptInfo.prototype.toString = function () {
michael@0 14153 return this.name;
michael@0 14154 };
michael@0 14155 ScriptInfo.nextID = 1;
michael@0 14156 return ScriptInfo;
michael@0 14157 }(Info);
michael@0 14158 ABC.ScriptInfo = ScriptInfo;
michael@0 14159 var AbcFile = function () {
michael@0 14160 function AbcFile(bytes, name, hash) {
michael@0 14161 if (typeof hash === 'undefined') {
michael@0 14162 hash = 0;
michael@0 14163 }
michael@0 14164 Timer.start('Parse ABC');
michael@0 14165 this.name = name;
michael@0 14166 this.env = {};
michael@0 14167 var computedHash;
michael@0 14168 if (!hash || !true) {
michael@0 14169 Timer.start('Adler');
michael@0 14170 computedHash = Shumway.HashUtilities.hashBytesTo32BitsAdler(bytes, 0, bytes.length);
michael@0 14171 Timer.stop();
michael@0 14172 }
michael@0 14173 if (hash) {
michael@0 14174 this.hash = hash;
michael@0 14175 true;
michael@0 14176 } else {
michael@0 14177 this.hash = computedHash;
michael@0 14178 }
michael@0 14179 var n, i;
michael@0 14180 var stream = new AbcStream(bytes);
michael@0 14181 AbcFile._checkMagic(stream);
michael@0 14182 Timer.start('Parse constantPool');
michael@0 14183 this.constantPool = new ConstantPool(stream, this);
michael@0 14184 Timer.stop();
michael@0 14185 Timer.start('Parse Method Infos');
michael@0 14186 this.methods = [];
michael@0 14187 n = stream.readU30();
michael@0 14188 for (i = 0; i < n; ++i) {
michael@0 14189 this.methods.push(new MethodInfo(this, i, stream));
michael@0 14190 }
michael@0 14191 Timer.stop();
michael@0 14192 Timer.start('Parse MetaData Infos');
michael@0 14193 this.metadata = [];
michael@0 14194 n = stream.readU30();
michael@0 14195 for (i = 0; i < n; ++i) {
michael@0 14196 this.metadata.push(new MetaDataInfo(this, stream));
michael@0 14197 }
michael@0 14198 Timer.stop();
michael@0 14199 Timer.start('Parse Instance Infos');
michael@0 14200 this.instances = [];
michael@0 14201 n = stream.readU30();
michael@0 14202 for (i = 0; i < n; ++i) {
michael@0 14203 this.instances.push(new InstanceInfo(this, i, stream));
michael@0 14204 }
michael@0 14205 Timer.stop();
michael@0 14206 Timer.start('Parse Class Infos');
michael@0 14207 this.classes = [];
michael@0 14208 for (i = 0; i < n; ++i) {
michael@0 14209 this.classes.push(new ClassInfo(this, i, stream));
michael@0 14210 }
michael@0 14211 Timer.stop();
michael@0 14212 Timer.start('Parse Script Infos');
michael@0 14213 this.scripts = [];
michael@0 14214 n = stream.readU30();
michael@0 14215 for (i = 0; i < n; ++i) {
michael@0 14216 this.scripts.push(new ScriptInfo(this, i, stream));
michael@0 14217 }
michael@0 14218 Timer.stop();
michael@0 14219 Timer.start('Parse Method Body Info');
michael@0 14220 n = stream.readU30();
michael@0 14221 for (i = 0; i < n; ++i) {
michael@0 14222 MethodInfo.parseBody(this, stream);
michael@0 14223 }
michael@0 14224 Timer.stop();
michael@0 14225 Timer.stop();
michael@0 14226 }
michael@0 14227 AbcFile._checkMagic = function (stream) {
michael@0 14228 var magic = stream.readWord();
michael@0 14229 var flashPlayerBrannan = 46 << 16 | 15;
michael@0 14230 if (magic < flashPlayerBrannan) {
michael@0 14231 throw new Error('Invalid ABC File (magic = ' + Number(magic).toString(16) + ')');
michael@0 14232 }
michael@0 14233 };
michael@0 14234 Object.defineProperty(AbcFile.prototype, 'lastScript', {
michael@0 14235 get: function () {
michael@0 14236 true;
michael@0 14237 return this.scripts[this.scripts.length - 1];
michael@0 14238 },
michael@0 14239 enumerable: true,
michael@0 14240 configurable: true
michael@0 14241 });
michael@0 14242 AbcFile.attachHolder = function (mi, holder) {
michael@0 14243 true;
michael@0 14244 mi.holder = holder;
michael@0 14245 };
michael@0 14246 AbcFile.prototype.toString = function () {
michael@0 14247 return this.name;
michael@0 14248 };
michael@0 14249 return AbcFile;
michael@0 14250 }();
michael@0 14251 ABC.AbcFile = AbcFile;
michael@0 14252 var Namespace = function () {
michael@0 14253 function Namespace(kind, uri, prefix, uniqueURIHash) {
michael@0 14254 if (typeof uri === 'undefined') {
michael@0 14255 uri = '';
michael@0 14256 }
michael@0 14257 if (uri === undefined) {
michael@0 14258 uri = '';
michael@0 14259 }
michael@0 14260 if (prefix !== undefined) {
michael@0 14261 this.prefix = prefix;
michael@0 14262 }
michael@0 14263 this.kind = kind;
michael@0 14264 this.uri = uri;
michael@0 14265 this._buildNamespace(uniqueURIHash);
michael@0 14266 }
michael@0 14267 Namespace.prototype._buildNamespace = function (uniqueURIHash) {
michael@0 14268 if (this.kind === 22) {
michael@0 14269 this.kind = 8;
michael@0 14270 }
michael@0 14271 if (this.isPublic() && this.uri) {
michael@0 14272 var n = this.uri.length - 1;
michael@0 14273 var mark = this.uri.charCodeAt(n);
michael@0 14274 if (mark > Namespace._MIN_API_MARK) {
michael@0 14275 this.uri = this.uri.substring(0, n - 1);
michael@0 14276 }
michael@0 14277 } else if (this.isUnique()) {
michael@0 14278 this.uri = 'private ' + uniqueURIHash;
michael@0 14279 }
michael@0 14280 this.qualifiedName = Namespace._qualifyNamespace(this.kind, this.uri, this.prefix ? this.prefix : '');
michael@0 14281 };
michael@0 14282 Namespace._hashNamespace = function (kind, uri, prefix) {
michael@0 14283 var data = new Int32Array(1 + uri.length + prefix.length);
michael@0 14284 var j = 0;
michael@0 14285 data[j++] = kind;
michael@0 14286 var index = Namespace._knownURIs.indexOf(uri);
michael@0 14287 if (index >= 0) {
michael@0 14288 return kind << 2 | index;
michael@0 14289 } else {
michael@0 14290 for (var i = 0; i < uri.length; i++) {
michael@0 14291 data[j++] = uri.charCodeAt(i);
michael@0 14292 }
michael@0 14293 }
michael@0 14294 for (var i = 0; i < prefix.length; i++) {
michael@0 14295 data[j++] = prefix.charCodeAt(i);
michael@0 14296 }
michael@0 14297 return Shumway.HashUtilities.hashBytesTo32BitsMD5(data, 0, j);
michael@0 14298 };
michael@0 14299 Namespace._qualifyNamespace = function (kind, uri, prefix) {
michael@0 14300 var key = kind + uri;
michael@0 14301 var mangledNamespace = Namespace._mangledNamespaceCache[key];
michael@0 14302 if (mangledNamespace) {
michael@0 14303 return mangledNamespace;
michael@0 14304 }
michael@0 14305 mangledNamespace = Shumway.StringUtilities.variableLengthEncodeInt32(Namespace._hashNamespace(kind, uri, prefix));
michael@0 14306 Namespace._mangledNamespaceMap[mangledNamespace] = {
michael@0 14307 kind: kind,
michael@0 14308 uri: uri,
michael@0 14309 prefix: prefix
michael@0 14310 };
michael@0 14311 Namespace._mangledNamespaceCache[key] = mangledNamespace;
michael@0 14312 return mangledNamespace;
michael@0 14313 };
michael@0 14314 Namespace.fromQualifiedName = function (qn) {
michael@0 14315 var length = Shumway.StringUtilities.fromEncoding(qn[0]);
michael@0 14316 var mangledNamespace = qn.substring(0, length + 1);
michael@0 14317 var ns = Namespace._mangledNamespaceMap[mangledNamespace];
michael@0 14318 return new Namespace(ns.kind, ns.uri, ns.prefix);
michael@0 14319 };
michael@0 14320 Namespace.kindFromString = function (str) {
michael@0 14321 for (var kind in Namespace._kinds) {
michael@0 14322 if (Namespace._kinds[kind] === str) {
michael@0 14323 return kind;
michael@0 14324 }
michael@0 14325 }
michael@0 14326 return true;
michael@0 14327 };
michael@0 14328 Namespace.createNamespace = function (uri, prefix) {
michael@0 14329 return new Namespace(8, uri, prefix);
michael@0 14330 };
michael@0 14331 Namespace.parse = function (constantPool, stream, hash) {
michael@0 14332 var kind = stream.readU8();
michael@0 14333 var uri = constantPool.strings[stream.readU30()];
michael@0 14334 return new Namespace(kind, uri, undefined, hash);
michael@0 14335 };
michael@0 14336 Namespace.prototype.isPublic = function () {
michael@0 14337 return this.kind === 8 || this.kind === 22;
michael@0 14338 };
michael@0 14339 Namespace.prototype.isProtected = function () {
michael@0 14340 return this.kind === 24;
michael@0 14341 };
michael@0 14342 Namespace.prototype.isUnique = function () {
michael@0 14343 return this.kind === 5 && !this.uri;
michael@0 14344 };
michael@0 14345 Namespace.prototype.isDynamic = function () {
michael@0 14346 return this.isPublic() && !this.uri;
michael@0 14347 };
michael@0 14348 Namespace.prototype.getURI = function () {
michael@0 14349 return this.uri;
michael@0 14350 };
michael@0 14351 Namespace.prototype.toString = function () {
michael@0 14352 return Namespace._kinds[this.kind] + (this.uri ? ' ' + this.uri : '');
michael@0 14353 };
michael@0 14354 Namespace.prototype.clone = function () {
michael@0 14355 var ns = Object.create(Namespace.prototype);
michael@0 14356 ns.kind = this.kind;
michael@0 14357 ns.uri = this.uri;
michael@0 14358 ns.prefix = this.prefix;
michael@0 14359 ns.qualifiedName = this.qualifiedName;
michael@0 14360 return ns;
michael@0 14361 };
michael@0 14362 Namespace.prototype.isEqualTo = function (other) {
michael@0 14363 return this.qualifiedName === other.qualifiedName;
michael@0 14364 };
michael@0 14365 Namespace.prototype.inNamespaceSet = function (set) {
michael@0 14366 for (var i = 0; i < set.length; i++) {
michael@0 14367 if (set[i].qualifiedName === this.qualifiedName) {
michael@0 14368 return true;
michael@0 14369 }
michael@0 14370 }
michael@0 14371 return false;
michael@0 14372 };
michael@0 14373 Namespace.prototype.getAccessModifier = function () {
michael@0 14374 return Namespace._kinds[this.kind];
michael@0 14375 };
michael@0 14376 Namespace.prototype.getQualifiedName = function () {
michael@0 14377 return this.qualifiedName;
michael@0 14378 };
michael@0 14379 Namespace.fromSimpleName = function (simpleName) {
michael@0 14380 if (simpleName in Namespace._simpleNameCache) {
michael@0 14381 return Namespace._simpleNameCache[simpleName];
michael@0 14382 }
michael@0 14383 var namespaceNames;
michael@0 14384 if (simpleName.indexOf('[') === 0) {
michael@0 14385 true;
michael@0 14386 namespaceNames = simpleName.substring(1, simpleName.length - 1).split(',');
michael@0 14387 } else {
michael@0 14388 namespaceNames = [
michael@0 14389 simpleName
michael@0 14390 ];
michael@0 14391 }
michael@0 14392 return Namespace._simpleNameCache[simpleName] = namespaceNames.map(function (name) {
michael@0 14393 name = name.trim();
michael@0 14394 var kindName, uri;
michael@0 14395 if (name.indexOf(' ') > 0) {
michael@0 14396 kindName = name.substring(0, name.indexOf(' ')).trim();
michael@0 14397 uri = name.substring(name.indexOf(' ') + 1).trim();
michael@0 14398 } else {
michael@0 14399 var kinds = Namespace._kinds;
michael@0 14400 if (name === kinds[8] || name === kinds[23] || name === kinds[5] || name === kinds[24] || name === kinds[25] || name === kinds[26]) {
michael@0 14401 kindName = name;
michael@0 14402 uri = '';
michael@0 14403 } else {
michael@0 14404 kindName = Namespace._publicPrefix;
michael@0 14405 uri = name;
michael@0 14406 }
michael@0 14407 }
michael@0 14408 return new Namespace(Namespace.kindFromString(kindName), uri);
michael@0 14409 });
michael@0 14410 };
michael@0 14411 Namespace._publicPrefix = 'public';
michael@0 14412 Namespace._kinds = function () {
michael@0 14413 var map = Shumway.ObjectUtilities.createMap();
michael@0 14414 map[8] = Namespace._publicPrefix;
michael@0 14415 map[23] = 'packageInternal';
michael@0 14416 map[5] = 'private';
michael@0 14417 map[24] = 'protected';
michael@0 14418 map[25] = 'explicit';
michael@0 14419 map[26] = 'staticProtected';
michael@0 14420 return map;
michael@0 14421 }();
michael@0 14422 Namespace._MIN_API_MARK = 58004;
michael@0 14423 Namespace._MAX_API_MARK = 63743;
michael@0 14424 Namespace._knownURIs = [
michael@0 14425 ''
michael@0 14426 ];
michael@0 14427 Namespace._mangledNamespaceCache = Shumway.ObjectUtilities.createMap();
michael@0 14428 Namespace._mangledNamespaceMap = Shumway.ObjectUtilities.createMap();
michael@0 14429 Namespace.PUBLIC = new Namespace(8);
michael@0 14430 Namespace.PROTECTED = new Namespace(24);
michael@0 14431 Namespace.PROXY = new Namespace(8, 'http://www.adobe.com/2006/actionscript/flash/proxy');
michael@0 14432 Namespace._simpleNameCache = Shumway.ObjectUtilities.createMap();
michael@0 14433 return Namespace;
michael@0 14434 }();
michael@0 14435 ABC.Namespace = Namespace;
michael@0 14436 var Multiname = function () {
michael@0 14437 function Multiname(namespaces, name, flags) {
michael@0 14438 if (typeof flags === 'undefined') {
michael@0 14439 flags = 0;
michael@0 14440 }
michael@0 14441 if (name !== undefined) {
michael@0 14442 true;
michael@0 14443 }
michael@0 14444 this.runtimeId = Multiname._nextID++;
michael@0 14445 this.namespaces = namespaces;
michael@0 14446 this.name = name;
michael@0 14447 this.flags = flags;
michael@0 14448 }
michael@0 14449 Multiname.parse = function (constantPool, stream, multinames, patchFactoryTypes) {
michael@0 14450 var index = 0;
michael@0 14451 var kind = stream.readU8();
michael@0 14452 var name, namespaces = [], flags = 0;
michael@0 14453 switch (kind) {
michael@0 14454 case 7:
michael@0 14455 case 13:
michael@0 14456 index = stream.readU30();
michael@0 14457 if (index) {
michael@0 14458 namespaces = [
michael@0 14459 constantPool.namespaces[index]
michael@0 14460 ];
michael@0 14461 } else {
michael@0 14462 flags &= ~Multiname.RUNTIME_NAME;
michael@0 14463 }
michael@0 14464 index = stream.readU30();
michael@0 14465 if (index) {
michael@0 14466 name = constantPool.strings[index];
michael@0 14467 }
michael@0 14468 break;
michael@0 14469 case 15:
michael@0 14470 case 16:
michael@0 14471 index = stream.readU30();
michael@0 14472 if (index) {
michael@0 14473 name = constantPool.strings[index];
michael@0 14474 } else {
michael@0 14475 flags &= ~Multiname.RUNTIME_NAME;
michael@0 14476 }
michael@0 14477 flags |= Multiname.RUNTIME_NAMESPACE;
michael@0 14478 break;
michael@0 14479 case 17:
michael@0 14480 case 18:
michael@0 14481 flags |= Multiname.RUNTIME_NAMESPACE;
michael@0 14482 flags |= Multiname.RUNTIME_NAME;
michael@0 14483 break;
michael@0 14484 case 9:
michael@0 14485 case 14:
michael@0 14486 index = stream.readU30();
michael@0 14487 if (index) {
michael@0 14488 name = constantPool.strings[index];
michael@0 14489 } else {
michael@0 14490 flags &= ~Multiname.RUNTIME_NAME;
michael@0 14491 }
michael@0 14492 index = stream.readU30();
michael@0 14493 true;
michael@0 14494 namespaces = constantPool.namespaceSets[index];
michael@0 14495 break;
michael@0 14496 case 27:
michael@0 14497 case 28:
michael@0 14498 flags |= Multiname.RUNTIME_NAME;
michael@0 14499 index = stream.readU30();
michael@0 14500 true;
michael@0 14501 namespaces = constantPool.namespaceSets[index];
michael@0 14502 break;
michael@0 14503 case 29:
michael@0 14504 var factoryTypeIndex = stream.readU32();
michael@0 14505 if (multinames[factoryTypeIndex]) {
michael@0 14506 namespaces = multinames[factoryTypeIndex].namespaces;
michael@0 14507 name = multinames[factoryTypeIndex].name;
michael@0 14508 }
michael@0 14509 var typeParameterCount = stream.readU32();
michael@0 14510 true;
michael@0 14511 var typeParameterIndex = stream.readU32();
michael@0 14512 true;
michael@0 14513 var mn = new Multiname(namespaces, name, flags);
michael@0 14514 mn.typeParameter = multinames[typeParameterIndex];
michael@0 14515 if (!multinames[factoryTypeIndex]) {
michael@0 14516 patchFactoryTypes.push({
michael@0 14517 multiname: mn,
michael@0 14518 index: factoryTypeIndex
michael@0 14519 });
michael@0 14520 }
michael@0 14521 return mn;
michael@0 14522 default:
michael@0 14523 Shumway.Debug.unexpected();
michael@0 14524 break;
michael@0 14525 }
michael@0 14526 switch (kind) {
michael@0 14527 case 13:
michael@0 14528 case 16:
michael@0 14529 case 18:
michael@0 14530 case 14:
michael@0 14531 case 28:
michael@0 14532 flags |= Multiname.ATTRIBUTE;
michael@0 14533 break;
michael@0 14534 }
michael@0 14535 return new Multiname(namespaces, name, flags);
michael@0 14536 };
michael@0 14537 Multiname.isMultiname = function (mn) {
michael@0 14538 return typeof mn === 'number' || typeof mn === 'string' || mn instanceof Multiname || mn instanceof Number;
michael@0 14539 };
michael@0 14540 Multiname.needsResolution = function (mn) {
michael@0 14541 return mn instanceof Multiname && mn.namespaces.length > 1;
michael@0 14542 };
michael@0 14543 Multiname.isQName = function (mn) {
michael@0 14544 if (mn instanceof Multiname) {
michael@0 14545 return mn.namespaces && mn.namespaces.length === 1;
michael@0 14546 }
michael@0 14547 return true;
michael@0 14548 };
michael@0 14549 Multiname.isRuntimeName = function (mn) {
michael@0 14550 return mn instanceof Multiname && mn.isRuntimeName();
michael@0 14551 };
michael@0 14552 Multiname.isRuntimeNamespace = function (mn) {
michael@0 14553 return mn instanceof Multiname && mn.isRuntimeNamespace();
michael@0 14554 };
michael@0 14555 Multiname.isRuntime = function (mn) {
michael@0 14556 return mn instanceof Multiname && mn.isRuntimeName() || mn.isRuntimeNamespace();
michael@0 14557 };
michael@0 14558 Multiname.getQualifiedName = function (mn) {
michael@0 14559 true;
michael@0 14560 if (mn instanceof Multiname) {
michael@0 14561 if (mn.qualifiedName !== undefined) {
michael@0 14562 return mn.qualifiedName;
michael@0 14563 }
michael@0 14564 var name = String(mn.name);
michael@0 14565 if (isNumeric(name) && mn.namespaces[0].isPublic()) {
michael@0 14566 return mn.qualifiedName = name;
michael@0 14567 }
michael@0 14568 mn = mn.qualifiedName = Multiname.qualifyName(mn.namespaces[0], name);
michael@0 14569 }
michael@0 14570 return mn;
michael@0 14571 };
michael@0 14572 Multiname.qualifyName = function (namespace, name) {
michael@0 14573 return '$' + namespace.qualifiedName + name;
michael@0 14574 };
michael@0 14575 Multiname.stripPublicQualifier = function (qn) {
michael@0 14576 var publicQualifier = '$' + Namespace.PUBLIC.qualifiedName;
michael@0 14577 var index = qn.indexOf(publicQualifier);
michael@0 14578 if (index !== 0) {
michael@0 14579 return undefined;
michael@0 14580 }
michael@0 14581 return qn.substring(publicQualifier.length);
michael@0 14582 };
michael@0 14583 Multiname.fromQualifiedName = function (qn) {
michael@0 14584 if (qn instanceof Multiname) {
michael@0 14585 return qn;
michael@0 14586 }
michael@0 14587 if (isNumeric(qn)) {
michael@0 14588 return new Multiname([
michael@0 14589 Namespace.PUBLIC
michael@0 14590 ], qn);
michael@0 14591 }
michael@0 14592 if (qn[0] !== '$') {
michael@0 14593 return;
michael@0 14594 }
michael@0 14595 var ns = Namespace.fromQualifiedName(qn.substring(1));
michael@0 14596 return new Multiname([
michael@0 14597 ns
michael@0 14598 ], qn.substring(1 + ns.qualifiedName.length));
michael@0 14599 };
michael@0 14600 Multiname.getNameFromPublicQualifiedName = function (qn) {
michael@0 14601 var mn = Multiname.fromQualifiedName(qn);
michael@0 14602 true;
michael@0 14603 return mn.name;
michael@0 14604 };
michael@0 14605 Multiname.getFullQualifiedName = function (mn) {
michael@0 14606 var qn = Multiname.getQualifiedName(mn);
michael@0 14607 if (mn instanceof Multiname && mn.typeParameter) {
michael@0 14608 qn += '$' + Multiname.getFullQualifiedName(mn.typeParameter);
michael@0 14609 }
michael@0 14610 return qn;
michael@0 14611 };
michael@0 14612 Multiname.getPublicQualifiedName = function (name) {
michael@0 14613 if (isNumeric(name)) {
michael@0 14614 return Shumway.toNumber(name);
michael@0 14615 } else if (name !== null && isObject(name)) {
michael@0 14616 return name;
michael@0 14617 }
michael@0 14618 return Multiname.qualifyName(Namespace.PUBLIC, name);
michael@0 14619 };
michael@0 14620 Multiname.isPublicQualifiedName = function (qn) {
michael@0 14621 return typeof qn === 'number' || isNumeric(qn) || qn.indexOf(Namespace.PUBLIC.qualifiedName) === 1;
michael@0 14622 };
michael@0 14623 Multiname.getAccessModifier = function (mn) {
michael@0 14624 true;
michael@0 14625 if (typeof mn === 'number' || typeof mn === 'string' || mn instanceof Number) {
michael@0 14626 return 'public';
michael@0 14627 }
michael@0 14628 true;
michael@0 14629 return mn.namespaces[0].getAccessModifier();
michael@0 14630 };
michael@0 14631 Multiname.isNumeric = function (mn) {
michael@0 14632 if (typeof mn === 'number') {
michael@0 14633 return true;
michael@0 14634 } else if (typeof mn === 'string') {
michael@0 14635 return isNumeric(mn);
michael@0 14636 }
michael@0 14637 return !isNaN(parseInt(Multiname.getName(mn), 10));
michael@0 14638 };
michael@0 14639 Multiname.getName = function (mn) {
michael@0 14640 true;
michael@0 14641 true;
michael@0 14642 return mn.getName();
michael@0 14643 };
michael@0 14644 Multiname.isAnyName = function (mn) {
michael@0 14645 return typeof mn === 'object' && !mn.isRuntimeName() && !mn.name;
michael@0 14646 };
michael@0 14647 Multiname.fromSimpleName = function (simpleName) {
michael@0 14648 true;
michael@0 14649 if (simpleName in Multiname._simpleNameCache) {
michael@0 14650 return Multiname._simpleNameCache[simpleName];
michael@0 14651 }
michael@0 14652 var nameIndex, namespaceIndex, name, namespace;
michael@0 14653 nameIndex = simpleName.lastIndexOf('.');
michael@0 14654 if (nameIndex <= 0) {
michael@0 14655 nameIndex = simpleName.lastIndexOf(' ');
michael@0 14656 }
michael@0 14657 if (nameIndex > 0 && nameIndex < simpleName.length - 1) {
michael@0 14658 name = simpleName.substring(nameIndex + 1).trim();
michael@0 14659 namespace = simpleName.substring(0, nameIndex).trim();
michael@0 14660 } else {
michael@0 14661 name = simpleName;
michael@0 14662 namespace = '';
michael@0 14663 }
michael@0 14664 return Multiname._simpleNameCache[simpleName] = new Multiname(Namespace.fromSimpleName(namespace), name);
michael@0 14665 };
michael@0 14666 Multiname.prototype.getQName = function (index) {
michael@0 14667 true;
michael@0 14668 if (!this._qualifiedNameCache) {
michael@0 14669 this._qualifiedNameCache = Shumway.ObjectUtilities.createArrayMap();
michael@0 14670 }
michael@0 14671 var name = this._qualifiedNameCache[index];
michael@0 14672 if (!name) {
michael@0 14673 name = this._qualifiedNameCache[index] = new Multiname([
michael@0 14674 this.namespaces[index]
michael@0 14675 ], this.name, this.flags);
michael@0 14676 }
michael@0 14677 return name;
michael@0 14678 };
michael@0 14679 Multiname.prototype.hasQName = function (qn) {
michael@0 14680 true;
michael@0 14681 if (this.name !== qn.name) {
michael@0 14682 return false;
michael@0 14683 }
michael@0 14684 for (var i = 0; i < this.namespaces.length; i++) {
michael@0 14685 if (this.namespaces[i].isEqualTo(qn.namespaces[0])) {
michael@0 14686 return true;
michael@0 14687 }
michael@0 14688 }
michael@0 14689 return false;
michael@0 14690 };
michael@0 14691 Multiname.prototype.isAttribute = function () {
michael@0 14692 return this.flags & Multiname.ATTRIBUTE;
michael@0 14693 };
michael@0 14694 Multiname.prototype.isAnyName = function () {
michael@0 14695 return Multiname.isAnyName(this);
michael@0 14696 };
michael@0 14697 Multiname.prototype.isAnyNamespace = function () {
michael@0 14698 return !this.isRuntimeNamespace() && (this.namespaces.length === 0 || this.isAnyName() && this.namespaces.length !== 1);
michael@0 14699 };
michael@0 14700 Multiname.prototype.isRuntimeName = function () {
michael@0 14701 return !(!(this.flags & Multiname.RUNTIME_NAME));
michael@0 14702 };
michael@0 14703 Multiname.prototype.isRuntimeNamespace = function () {
michael@0 14704 return !(!(this.flags & Multiname.RUNTIME_NAMESPACE));
michael@0 14705 };
michael@0 14706 Multiname.prototype.isRuntime = function () {
michael@0 14707 return !(!(this.flags & (Multiname.RUNTIME_NAME | Multiname.RUNTIME_NAMESPACE)));
michael@0 14708 };
michael@0 14709 Multiname.prototype.isQName = function () {
michael@0 14710 return this.namespaces.length === 1 && !this.isAnyName();
michael@0 14711 };
michael@0 14712 Multiname.prototype.hasTypeParameter = function () {
michael@0 14713 return !(!this.typeParameter);
michael@0 14714 };
michael@0 14715 Multiname.prototype.getName = function () {
michael@0 14716 return this.name;
michael@0 14717 };
michael@0 14718 Multiname.prototype.getOriginalName = function () {
michael@0 14719 true;
michael@0 14720 var name = this.namespaces[0].uri;
michael@0 14721 if (name) {
michael@0 14722 name += '.';
michael@0 14723 }
michael@0 14724 return name + this.name;
michael@0 14725 };
michael@0 14726 Multiname.prototype.getNamespace = function () {
michael@0 14727 true;
michael@0 14728 true;
michael@0 14729 return this.namespaces[0];
michael@0 14730 };
michael@0 14731 Multiname.prototype.nameToString = function () {
michael@0 14732 if (this.isAnyName()) {
michael@0 14733 return '*';
michael@0 14734 } else {
michael@0 14735 var name = this.getName();
michael@0 14736 return this.isRuntimeName() ? '[]' : name;
michael@0 14737 }
michael@0 14738 };
michael@0 14739 Multiname.prototype.hasObjectName = function () {
michael@0 14740 return typeof this.name === 'object';
michael@0 14741 };
michael@0 14742 Multiname.prototype.toString = function () {
michael@0 14743 var str = this.isAttribute() ? '@' : '';
michael@0 14744 if (this.isAnyNamespace()) {
michael@0 14745 str += '*::' + this.nameToString();
michael@0 14746 } else if (this.isRuntimeNamespace()) {
michael@0 14747 str += '[]::' + this.nameToString();
michael@0 14748 } else if (this.namespaces.length === 1 && this.isQName()) {
michael@0 14749 str += this.namespaces[0].toString() + '::';
michael@0 14750 str += this.nameToString();
michael@0 14751 } else {
michael@0 14752 str += '{';
michael@0 14753 for (var i = 0, count = this.namespaces.length; i < count; i++) {
michael@0 14754 str += this.namespaces[i].toString();
michael@0 14755 if (i + 1 < count) {
michael@0 14756 str += ',';
michael@0 14757 }
michael@0 14758 }
michael@0 14759 str += '}::' + this.nameToString();
michael@0 14760 }
michael@0 14761 if (this.hasTypeParameter()) {
michael@0 14762 str += '<' + this.typeParameter.toString() + '>';
michael@0 14763 }
michael@0 14764 return str;
michael@0 14765 };
michael@0 14766 Multiname.ATTRIBUTE = 1;
michael@0 14767 Multiname.RUNTIME_NAMESPACE = 2;
michael@0 14768 Multiname.RUNTIME_NAME = 4;
michael@0 14769 Multiname._nextID = 0;
michael@0 14770 Multiname._simpleNameCache = Shumway.ObjectUtilities.createMap();
michael@0 14771 Multiname.Int = Multiname.getPublicQualifiedName('int');
michael@0 14772 Multiname.Uint = Multiname.getPublicQualifiedName('uint');
michael@0 14773 Multiname.Class = Multiname.getPublicQualifiedName('Class');
michael@0 14774 Multiname.Array = Multiname.getPublicQualifiedName('Array');
michael@0 14775 Multiname.Object = Multiname.getPublicQualifiedName('Object');
michael@0 14776 Multiname.String = Multiname.getPublicQualifiedName('String');
michael@0 14777 Multiname.Number = Multiname.getPublicQualifiedName('Number');
michael@0 14778 Multiname.Boolean = Multiname.getPublicQualifiedName('Boolean');
michael@0 14779 Multiname.Function = Multiname.getPublicQualifiedName('Function');
michael@0 14780 Multiname.XML = Multiname.getPublicQualifiedName('XML');
michael@0 14781 Multiname.XMLList = Multiname.getPublicQualifiedName('XMLList');
michael@0 14782 Multiname.TEMPORARY = new Multiname([], '');
michael@0 14783 return Multiname;
michael@0 14784 }();
michael@0 14785 ABC.Multiname = Multiname;
michael@0 14786 var MetaDataInfo = function () {
michael@0 14787 function MetaDataInfo(abc, stream) {
michael@0 14788 var strings = abc.constantPool.strings;
michael@0 14789 var name = this.name = strings[stream.readU30()];
michael@0 14790 var itemCount = stream.readU30();
michael@0 14791 var keys = [];
michael@0 14792 var items = [];
michael@0 14793 for (var i = 0; i < itemCount; i++) {
michael@0 14794 keys[i] = strings[stream.readU30()];
michael@0 14795 }
michael@0 14796 for (var i = 0; i < itemCount; i++) {
michael@0 14797 var key = keys[i];
michael@0 14798 items[i] = {
michael@0 14799 key: key,
michael@0 14800 value: strings[stream.readU30()]
michael@0 14801 };
michael@0 14802 if (key && name === 'native') {
michael@0 14803 true;
michael@0 14804 this[key] = items[i].value;
michael@0 14805 }
michael@0 14806 }
michael@0 14807 this.value = items;
michael@0 14808 }
michael@0 14809 MetaDataInfo.prototype.toString = function () {
michael@0 14810 return '[' + this.name + ']';
michael@0 14811 };
michael@0 14812 return MetaDataInfo;
michael@0 14813 }();
michael@0 14814 ABC.MetaDataInfo = MetaDataInfo;
michael@0 14815 (function (CONSTANT) {
michael@0 14816 CONSTANT[CONSTANT['Undefined'] = 0] = 'Undefined';
michael@0 14817 CONSTANT[CONSTANT['Utf8'] = 1] = 'Utf8';
michael@0 14818 CONSTANT[CONSTANT['Float'] = 2] = 'Float';
michael@0 14819 CONSTANT[CONSTANT['Int'] = 3] = 'Int';
michael@0 14820 CONSTANT[CONSTANT['UInt'] = 4] = 'UInt';
michael@0 14821 CONSTANT[CONSTANT['PrivateNs'] = 5] = 'PrivateNs';
michael@0 14822 CONSTANT[CONSTANT['Double'] = 6] = 'Double';
michael@0 14823 CONSTANT[CONSTANT['QName'] = 7] = 'QName';
michael@0 14824 CONSTANT[CONSTANT['Namespace'] = 8] = 'Namespace';
michael@0 14825 CONSTANT[CONSTANT['Multiname'] = 9] = 'Multiname';
michael@0 14826 CONSTANT[CONSTANT['False'] = 10] = 'False';
michael@0 14827 CONSTANT[CONSTANT['True'] = 11] = 'True';
michael@0 14828 CONSTANT[CONSTANT['Null'] = 12] = 'Null';
michael@0 14829 CONSTANT[CONSTANT['QNameA'] = 13] = 'QNameA';
michael@0 14830 CONSTANT[CONSTANT['MultinameA'] = 14] = 'MultinameA';
michael@0 14831 CONSTANT[CONSTANT['RTQName'] = 15] = 'RTQName';
michael@0 14832 CONSTANT[CONSTANT['RTQNameA'] = 16] = 'RTQNameA';
michael@0 14833 CONSTANT[CONSTANT['RTQNameL'] = 17] = 'RTQNameL';
michael@0 14834 CONSTANT[CONSTANT['RTQNameLA'] = 18] = 'RTQNameLA';
michael@0 14835 CONSTANT[CONSTANT['NameL'] = 19] = 'NameL';
michael@0 14836 CONSTANT[CONSTANT['NameLA'] = 20] = 'NameLA';
michael@0 14837 CONSTANT[CONSTANT['NamespaceSet'] = 21] = 'NamespaceSet';
michael@0 14838 CONSTANT[CONSTANT['PackageNamespace'] = 22] = 'PackageNamespace';
michael@0 14839 CONSTANT[CONSTANT['PackageInternalNs'] = 23] = 'PackageInternalNs';
michael@0 14840 CONSTANT[CONSTANT['ProtectedNamespace'] = 24] = 'ProtectedNamespace';
michael@0 14841 CONSTANT[CONSTANT['ExplicitNamespace'] = 25] = 'ExplicitNamespace';
michael@0 14842 CONSTANT[CONSTANT['StaticProtectedNs'] = 26] = 'StaticProtectedNs';
michael@0 14843 CONSTANT[CONSTANT['MultinameL'] = 27] = 'MultinameL';
michael@0 14844 CONSTANT[CONSTANT['MultinameLA'] = 28] = 'MultinameLA';
michael@0 14845 CONSTANT[CONSTANT['TypeName'] = 29] = 'TypeName';
michael@0 14846 CONSTANT[CONSTANT['ClassSealed'] = 1] = 'ClassSealed';
michael@0 14847 CONSTANT[CONSTANT['ClassFinal'] = 2] = 'ClassFinal';
michael@0 14848 CONSTANT[CONSTANT['ClassInterface'] = 4] = 'ClassInterface';
michael@0 14849 CONSTANT[CONSTANT['ClassProtectedNs'] = 8] = 'ClassProtectedNs';
michael@0 14850 }(ABC.CONSTANT || (ABC.CONSTANT = {})));
michael@0 14851 var CONSTANT = ABC.CONSTANT;
michael@0 14852 (function (METHOD) {
michael@0 14853 METHOD[METHOD['Arguments'] = 1] = 'Arguments';
michael@0 14854 METHOD[METHOD['Activation'] = 2] = 'Activation';
michael@0 14855 METHOD[METHOD['Needrest'] = 4] = 'Needrest';
michael@0 14856 METHOD[METHOD['HasOptional'] = 8] = 'HasOptional';
michael@0 14857 METHOD[METHOD['IgnoreRest'] = 16] = 'IgnoreRest';
michael@0 14858 METHOD[METHOD['Native'] = 32] = 'Native';
michael@0 14859 METHOD[METHOD['Setsdxns'] = 64] = 'Setsdxns';
michael@0 14860 METHOD[METHOD['HasParamNames'] = 128] = 'HasParamNames';
michael@0 14861 }(ABC.METHOD || (ABC.METHOD = {})));
michael@0 14862 var METHOD = ABC.METHOD;
michael@0 14863 (function (TRAIT) {
michael@0 14864 TRAIT[TRAIT['Slot'] = 0] = 'Slot';
michael@0 14865 TRAIT[TRAIT['Method'] = 1] = 'Method';
michael@0 14866 TRAIT[TRAIT['Getter'] = 2] = 'Getter';
michael@0 14867 TRAIT[TRAIT['Setter'] = 3] = 'Setter';
michael@0 14868 TRAIT[TRAIT['Class'] = 4] = 'Class';
michael@0 14869 TRAIT[TRAIT['Function'] = 5] = 'Function';
michael@0 14870 TRAIT[TRAIT['Const'] = 6] = 'Const';
michael@0 14871 }(ABC.TRAIT || (ABC.TRAIT = {})));
michael@0 14872 var TRAIT = ABC.TRAIT;
michael@0 14873 (function (ATTR) {
michael@0 14874 ATTR[ATTR['Final'] = 1] = 'Final';
michael@0 14875 ATTR[ATTR['Override'] = 2] = 'Override';
michael@0 14876 ATTR[ATTR['Metadata'] = 4] = 'Metadata';
michael@0 14877 }(ABC.ATTR || (ABC.ATTR = {})));
michael@0 14878 var ATTR = ABC.ATTR;
michael@0 14879 (function (SORT) {
michael@0 14880 SORT[SORT['CASEINSENSITIVE'] = 1] = 'CASEINSENSITIVE';
michael@0 14881 SORT[SORT['DESCENDING'] = 2] = 'DESCENDING';
michael@0 14882 SORT[SORT['UNIQUESORT'] = 4] = 'UNIQUESORT';
michael@0 14883 SORT[SORT['RETURNINDEXEDARRAY'] = 8] = 'RETURNINDEXEDARRAY';
michael@0 14884 SORT[SORT['NUMERIC'] = 16] = 'NUMERIC';
michael@0 14885 }(ABC.SORT || (ABC.SORT = {})));
michael@0 14886 var SORT = ABC.SORT;
michael@0 14887 (function (OP) {
michael@0 14888 OP[OP['bkpt'] = 1] = 'bkpt';
michael@0 14889 OP[OP['nop'] = 2] = 'nop';
michael@0 14890 OP[OP['throw'] = 3] = 'throw';
michael@0 14891 OP[OP['getsuper'] = 4] = 'getsuper';
michael@0 14892 OP[OP['setsuper'] = 5] = 'setsuper';
michael@0 14893 OP[OP['dxns'] = 6] = 'dxns';
michael@0 14894 OP[OP['dxnslate'] = 7] = 'dxnslate';
michael@0 14895 OP[OP['kill'] = 8] = 'kill';
michael@0 14896 OP[OP['label'] = 9] = 'label';
michael@0 14897 OP[OP['lf32x4'] = 10] = 'lf32x4';
michael@0 14898 OP[OP['sf32x4'] = 11] = 'sf32x4';
michael@0 14899 OP[OP['ifnlt'] = 12] = 'ifnlt';
michael@0 14900 OP[OP['ifnle'] = 13] = 'ifnle';
michael@0 14901 OP[OP['ifngt'] = 14] = 'ifngt';
michael@0 14902 OP[OP['ifnge'] = 15] = 'ifnge';
michael@0 14903 OP[OP['jump'] = 16] = 'jump';
michael@0 14904 OP[OP['iftrue'] = 17] = 'iftrue';
michael@0 14905 OP[OP['iffalse'] = 18] = 'iffalse';
michael@0 14906 OP[OP['ifeq'] = 19] = 'ifeq';
michael@0 14907 OP[OP['ifne'] = 20] = 'ifne';
michael@0 14908 OP[OP['iflt'] = 21] = 'iflt';
michael@0 14909 OP[OP['ifle'] = 22] = 'ifle';
michael@0 14910 OP[OP['ifgt'] = 23] = 'ifgt';
michael@0 14911 OP[OP['ifge'] = 24] = 'ifge';
michael@0 14912 OP[OP['ifstricteq'] = 25] = 'ifstricteq';
michael@0 14913 OP[OP['ifstrictne'] = 26] = 'ifstrictne';
michael@0 14914 OP[OP['lookupswitch'] = 27] = 'lookupswitch';
michael@0 14915 OP[OP['pushwith'] = 28] = 'pushwith';
michael@0 14916 OP[OP['popscope'] = 29] = 'popscope';
michael@0 14917 OP[OP['nextname'] = 30] = 'nextname';
michael@0 14918 OP[OP['hasnext'] = 31] = 'hasnext';
michael@0 14919 OP[OP['pushnull'] = 32] = 'pushnull';
michael@0 14920 OP[OP['c'] = 33] = 'c';
michael@0 14921 OP[OP['pushundefined'] = 33] = 'pushundefined';
michael@0 14922 OP[OP['pushfloat'] = 34] = 'pushfloat';
michael@0 14923 OP[OP['nextvalue'] = 35] = 'nextvalue';
michael@0 14924 OP[OP['pushbyte'] = 36] = 'pushbyte';
michael@0 14925 OP[OP['pushshort'] = 37] = 'pushshort';
michael@0 14926 OP[OP['pushtrue'] = 38] = 'pushtrue';
michael@0 14927 OP[OP['pushfalse'] = 39] = 'pushfalse';
michael@0 14928 OP[OP['pushnan'] = 40] = 'pushnan';
michael@0 14929 OP[OP['pop'] = 41] = 'pop';
michael@0 14930 OP[OP['dup'] = 42] = 'dup';
michael@0 14931 OP[OP['swap'] = 43] = 'swap';
michael@0 14932 OP[OP['pushstring'] = 44] = 'pushstring';
michael@0 14933 OP[OP['pushint'] = 45] = 'pushint';
michael@0 14934 OP[OP['pushuint'] = 46] = 'pushuint';
michael@0 14935 OP[OP['pushdouble'] = 47] = 'pushdouble';
michael@0 14936 OP[OP['pushscope'] = 48] = 'pushscope';
michael@0 14937 OP[OP['pushnamespace'] = 49] = 'pushnamespace';
michael@0 14938 OP[OP['hasnext2'] = 50] = 'hasnext2';
michael@0 14939 OP[OP['li8'] = 53] = 'li8';
michael@0 14940 OP[OP['li16'] = 54] = 'li16';
michael@0 14941 OP[OP['li32'] = 55] = 'li32';
michael@0 14942 OP[OP['lf32'] = 56] = 'lf32';
michael@0 14943 OP[OP['lf64'] = 57] = 'lf64';
michael@0 14944 OP[OP['si8'] = 58] = 'si8';
michael@0 14945 OP[OP['si16'] = 59] = 'si16';
michael@0 14946 OP[OP['si32'] = 60] = 'si32';
michael@0 14947 OP[OP['sf32'] = 61] = 'sf32';
michael@0 14948 OP[OP['sf64'] = 62] = 'sf64';
michael@0 14949 OP[OP['newfunction'] = 64] = 'newfunction';
michael@0 14950 OP[OP['call'] = 65] = 'call';
michael@0 14951 OP[OP['construct'] = 66] = 'construct';
michael@0 14952 OP[OP['callmethod'] = 67] = 'callmethod';
michael@0 14953 OP[OP['callstatic'] = 68] = 'callstatic';
michael@0 14954 OP[OP['callsuper'] = 69] = 'callsuper';
michael@0 14955 OP[OP['callproperty'] = 70] = 'callproperty';
michael@0 14956 OP[OP['returnvoid'] = 71] = 'returnvoid';
michael@0 14957 OP[OP['returnvalue'] = 72] = 'returnvalue';
michael@0 14958 OP[OP['constructsuper'] = 73] = 'constructsuper';
michael@0 14959 OP[OP['constructprop'] = 74] = 'constructprop';
michael@0 14960 OP[OP['callsuperid'] = 75] = 'callsuperid';
michael@0 14961 OP[OP['callproplex'] = 76] = 'callproplex';
michael@0 14962 OP[OP['callinterface'] = 77] = 'callinterface';
michael@0 14963 OP[OP['callsupervoid'] = 78] = 'callsupervoid';
michael@0 14964 OP[OP['callpropvoid'] = 79] = 'callpropvoid';
michael@0 14965 OP[OP['sxi1'] = 80] = 'sxi1';
michael@0 14966 OP[OP['sxi8'] = 81] = 'sxi8';
michael@0 14967 OP[OP['sxi16'] = 82] = 'sxi16';
michael@0 14968 OP[OP['applytype'] = 83] = 'applytype';
michael@0 14969 OP[OP['pushfloat4'] = 84] = 'pushfloat4';
michael@0 14970 OP[OP['newobject'] = 85] = 'newobject';
michael@0 14971 OP[OP['newarray'] = 86] = 'newarray';
michael@0 14972 OP[OP['newactivation'] = 87] = 'newactivation';
michael@0 14973 OP[OP['newclass'] = 88] = 'newclass';
michael@0 14974 OP[OP['getdescendants'] = 89] = 'getdescendants';
michael@0 14975 OP[OP['newcatch'] = 90] = 'newcatch';
michael@0 14976 OP[OP['findpropstrict'] = 93] = 'findpropstrict';
michael@0 14977 OP[OP['findproperty'] = 94] = 'findproperty';
michael@0 14978 OP[OP['finddef'] = 95] = 'finddef';
michael@0 14979 OP[OP['getlex'] = 96] = 'getlex';
michael@0 14980 OP[OP['setproperty'] = 97] = 'setproperty';
michael@0 14981 OP[OP['getlocal'] = 98] = 'getlocal';
michael@0 14982 OP[OP['setlocal'] = 99] = 'setlocal';
michael@0 14983 OP[OP['getglobalscope'] = 100] = 'getglobalscope';
michael@0 14984 OP[OP['getscopeobject'] = 101] = 'getscopeobject';
michael@0 14985 OP[OP['getproperty'] = 102] = 'getproperty';
michael@0 14986 OP[OP['getouterscope'] = 103] = 'getouterscope';
michael@0 14987 OP[OP['initproperty'] = 104] = 'initproperty';
michael@0 14988 OP[OP['setpropertylate'] = 105] = 'setpropertylate';
michael@0 14989 OP[OP['deleteproperty'] = 106] = 'deleteproperty';
michael@0 14990 OP[OP['deletepropertylate'] = 107] = 'deletepropertylate';
michael@0 14991 OP[OP['getslot'] = 108] = 'getslot';
michael@0 14992 OP[OP['setslot'] = 109] = 'setslot';
michael@0 14993 OP[OP['getglobalslot'] = 110] = 'getglobalslot';
michael@0 14994 OP[OP['setglobalslot'] = 111] = 'setglobalslot';
michael@0 14995 OP[OP['convert_s'] = 112] = 'convert_s';
michael@0 14996 OP[OP['esc_xelem'] = 113] = 'esc_xelem';
michael@0 14997 OP[OP['esc_xattr'] = 114] = 'esc_xattr';
michael@0 14998 OP[OP['convert_i'] = 115] = 'convert_i';
michael@0 14999 OP[OP['convert_u'] = 116] = 'convert_u';
michael@0 15000 OP[OP['convert_d'] = 117] = 'convert_d';
michael@0 15001 OP[OP['convert_b'] = 118] = 'convert_b';
michael@0 15002 OP[OP['convert_o'] = 119] = 'convert_o';
michael@0 15003 OP[OP['checkfilter'] = 120] = 'checkfilter';
michael@0 15004 OP[OP['convert_f'] = 121] = 'convert_f';
michael@0 15005 OP[OP['unplus'] = 122] = 'unplus';
michael@0 15006 OP[OP['convert_f4'] = 123] = 'convert_f4';
michael@0 15007 OP[OP['coerce'] = 128] = 'coerce';
michael@0 15008 OP[OP['coerce_b'] = 129] = 'coerce_b';
michael@0 15009 OP[OP['coerce_a'] = 130] = 'coerce_a';
michael@0 15010 OP[OP['coerce_i'] = 131] = 'coerce_i';
michael@0 15011 OP[OP['coerce_d'] = 132] = 'coerce_d';
michael@0 15012 OP[OP['coerce_s'] = 133] = 'coerce_s';
michael@0 15013 OP[OP['astype'] = 134] = 'astype';
michael@0 15014 OP[OP['astypelate'] = 135] = 'astypelate';
michael@0 15015 OP[OP['coerce_u'] = 136] = 'coerce_u';
michael@0 15016 OP[OP['coerce_o'] = 137] = 'coerce_o';
michael@0 15017 OP[OP['negate'] = 144] = 'negate';
michael@0 15018 OP[OP['increment'] = 145] = 'increment';
michael@0 15019 OP[OP['inclocal'] = 146] = 'inclocal';
michael@0 15020 OP[OP['decrement'] = 147] = 'decrement';
michael@0 15021 OP[OP['declocal'] = 148] = 'declocal';
michael@0 15022 OP[OP['typeof'] = 149] = 'typeof';
michael@0 15023 OP[OP['not'] = 150] = 'not';
michael@0 15024 OP[OP['bitnot'] = 151] = 'bitnot';
michael@0 15025 OP[OP['add'] = 160] = 'add';
michael@0 15026 OP[OP['subtract'] = 161] = 'subtract';
michael@0 15027 OP[OP['multiply'] = 162] = 'multiply';
michael@0 15028 OP[OP['divide'] = 163] = 'divide';
michael@0 15029 OP[OP['modulo'] = 164] = 'modulo';
michael@0 15030 OP[OP['lshift'] = 165] = 'lshift';
michael@0 15031 OP[OP['rshift'] = 166] = 'rshift';
michael@0 15032 OP[OP['urshift'] = 167] = 'urshift';
michael@0 15033 OP[OP['bitand'] = 168] = 'bitand';
michael@0 15034 OP[OP['bitor'] = 169] = 'bitor';
michael@0 15035 OP[OP['bitxor'] = 170] = 'bitxor';
michael@0 15036 OP[OP['equals'] = 171] = 'equals';
michael@0 15037 OP[OP['strictequals'] = 172] = 'strictequals';
michael@0 15038 OP[OP['lessthan'] = 173] = 'lessthan';
michael@0 15039 OP[OP['lessequals'] = 174] = 'lessequals';
michael@0 15040 OP[OP['greaterthan'] = 175] = 'greaterthan';
michael@0 15041 OP[OP['greaterequals'] = 176] = 'greaterequals';
michael@0 15042 OP[OP['instanceof'] = 177] = 'instanceof';
michael@0 15043 OP[OP['istype'] = 178] = 'istype';
michael@0 15044 OP[OP['istypelate'] = 179] = 'istypelate';
michael@0 15045 OP[OP['in'] = 180] = 'in';
michael@0 15046 OP[OP['increment_i'] = 192] = 'increment_i';
michael@0 15047 OP[OP['decrement_i'] = 193] = 'decrement_i';
michael@0 15048 OP[OP['inclocal_i'] = 194] = 'inclocal_i';
michael@0 15049 OP[OP['declocal_i'] = 195] = 'declocal_i';
michael@0 15050 OP[OP['negate_i'] = 196] = 'negate_i';
michael@0 15051 OP[OP['add_i'] = 197] = 'add_i';
michael@0 15052 OP[OP['subtract_i'] = 198] = 'subtract_i';
michael@0 15053 OP[OP['multiply_i'] = 199] = 'multiply_i';
michael@0 15054 OP[OP['getlocal0'] = 208] = 'getlocal0';
michael@0 15055 OP[OP['getlocal1'] = 209] = 'getlocal1';
michael@0 15056 OP[OP['getlocal2'] = 210] = 'getlocal2';
michael@0 15057 OP[OP['getlocal3'] = 211] = 'getlocal3';
michael@0 15058 OP[OP['setlocal0'] = 212] = 'setlocal0';
michael@0 15059 OP[OP['setlocal1'] = 213] = 'setlocal1';
michael@0 15060 OP[OP['setlocal2'] = 214] = 'setlocal2';
michael@0 15061 OP[OP['setlocal3'] = 215] = 'setlocal3';
michael@0 15062 OP[OP['invalid'] = 237] = 'invalid';
michael@0 15063 OP[OP['debug'] = 239] = 'debug';
michael@0 15064 OP[OP['debugline'] = 240] = 'debugline';
michael@0 15065 OP[OP['debugfile'] = 241] = 'debugfile';
michael@0 15066 OP[OP['bkptline'] = 242] = 'bkptline';
michael@0 15067 OP[OP['timestamp'] = 243] = 'timestamp';
michael@0 15068 }(ABC.OP || (ABC.OP = {})));
michael@0 15069 var OP = ABC.OP;
michael@0 15070 var ConstantPool = function () {
michael@0 15071 function ConstantPool(stream, abc) {
michael@0 15072 var n;
michael@0 15073 var ints = [
michael@0 15074 0
michael@0 15075 ];
michael@0 15076 n = stream.readU30();
michael@0 15077 for (var i = 1; i < n; ++i) {
michael@0 15078 ints.push(stream.readS32());
michael@0 15079 }
michael@0 15080 var uints = [
michael@0 15081 0
michael@0 15082 ];
michael@0 15083 n = stream.readU30();
michael@0 15084 for (var i = 1; i < n; ++i) {
michael@0 15085 uints.push(stream.readU32());
michael@0 15086 }
michael@0 15087 var doubles = [
michael@0 15088 NaN
michael@0 15089 ];
michael@0 15090 n = stream.readU30();
michael@0 15091 for (var i = 1; i < n; ++i) {
michael@0 15092 doubles.push(stream.readDouble());
michael@0 15093 }
michael@0 15094 Timer.start('Parse Strings');
michael@0 15095 var strings = [
michael@0 15096 ''
michael@0 15097 ];
michael@0 15098 n = stream.readU30();
michael@0 15099 for (var i = 1; i < n; ++i) {
michael@0 15100 strings.push(stream.readUTFString(stream.readU30()));
michael@0 15101 }
michael@0 15102 this.positionAfterUTFStrings = stream.position;
michael@0 15103 Timer.stop();
michael@0 15104 this.ints = ints;
michael@0 15105 this.uints = uints;
michael@0 15106 this.doubles = doubles;
michael@0 15107 this.strings = strings;
michael@0 15108 Timer.start('Parse Namespaces');
michael@0 15109 var namespaces = [
michael@0 15110 undefined
michael@0 15111 ];
michael@0 15112 n = stream.readU30();
michael@0 15113 for (var i = 1; i < n; ++i) {
michael@0 15114 namespaces.push(Namespace.parse(this, stream, abc.hash + i));
michael@0 15115 }
michael@0 15116 Timer.stop();
michael@0 15117 Timer.start('Parse Namespace Sets');
michael@0 15118 var namespaceSets = [
michael@0 15119 undefined
michael@0 15120 ];
michael@0 15121 n = stream.readU30();
michael@0 15122 for (var i = 1; i < n; ++i) {
michael@0 15123 var count = stream.readU30();
michael@0 15124 var set = [];
michael@0 15125 set.runtimeId = ConstantPool._nextNamespaceSetID++;
michael@0 15126 for (var j = 0; j < count; ++j) {
michael@0 15127 set.push(namespaces[stream.readU30()]);
michael@0 15128 }
michael@0 15129 namespaceSets.push(set);
michael@0 15130 }
michael@0 15131 Timer.stop();
michael@0 15132 this.namespaces = namespaces;
michael@0 15133 this.namespaceSets = namespaceSets;
michael@0 15134 Timer.start('Parse Multinames');
michael@0 15135 var multinames = [
michael@0 15136 undefined
michael@0 15137 ];
michael@0 15138 var patchFactoryTypes = [];
michael@0 15139 n = stream.readU30();
michael@0 15140 for (var i = 1; i < n; ++i) {
michael@0 15141 multinames.push(Multiname.parse(this, stream, multinames, patchFactoryTypes));
michael@0 15142 }
michael@0 15143 Timer.stop();
michael@0 15144 this.multinames = multinames;
michael@0 15145 }
michael@0 15146 ConstantPool.prototype.getValue = function (kind, index) {
michael@0 15147 switch (kind) {
michael@0 15148 case 3:
michael@0 15149 return this.ints[index];
michael@0 15150 case 4:
michael@0 15151 return this.uints[index];
michael@0 15152 case 6:
michael@0 15153 return this.doubles[index];
michael@0 15154 case 1:
michael@0 15155 return this.strings[index];
michael@0 15156 case 11:
michael@0 15157 return true;
michael@0 15158 case 10:
michael@0 15159 return false;
michael@0 15160 case 12:
michael@0 15161 return null;
michael@0 15162 case 0:
michael@0 15163 return undefined;
michael@0 15164 case 8:
michael@0 15165 case 23:
michael@0 15166 return this.namespaces[index];
michael@0 15167 case 7:
michael@0 15168 case 14:
michael@0 15169 case 15:
michael@0 15170 case 16:
michael@0 15171 case 17:
michael@0 15172 case 18:
michael@0 15173 case 19:
michael@0 15174 case 20:
michael@0 15175 return this.multinames[index];
michael@0 15176 case 2:
michael@0 15177 Shumway.Debug.warning('TODO: CONSTANT.Float may be deprecated?');
michael@0 15178 break;
michael@0 15179 default:
michael@0 15180 true;
michael@0 15181 }
michael@0 15182 };
michael@0 15183 ConstantPool._nextNamespaceSetID = 1;
michael@0 15184 return ConstantPool;
michael@0 15185 }();
michael@0 15186 ABC.ConstantPool = ConstantPool;
michael@0 15187 }(AVM2.ABC || (AVM2.ABC = {})));
michael@0 15188 var ABC = AVM2.ABC;
michael@0 15189 }(Shumway.AVM2 || (Shumway.AVM2 = {})));
michael@0 15190 var AVM2 = Shumway.AVM2;
michael@0 15191 }(Shumway || (Shumway = {})));
michael@0 15192 var AbcFile = Shumway.AVM2.ABC.AbcFile;
michael@0 15193 var AbcStream = Shumway.AVM2.ABC.AbcStream;
michael@0 15194 var ConstantPool = Shumway.AVM2.ABC.ConstantPool;
michael@0 15195 var ClassInfo = Shumway.AVM2.ABC.ClassInfo;
michael@0 15196 var MetaDataInfo = Shumway.AVM2.ABC.MetaDataInfo;
michael@0 15197 var InstanceInfo = Shumway.AVM2.ABC.InstanceInfo;
michael@0 15198 var ScriptInfo = Shumway.AVM2.ABC.ScriptInfo;
michael@0 15199 var Trait = Shumway.AVM2.ABC.Trait;
michael@0 15200 var MethodInfo = Shumway.AVM2.ABC.MethodInfo;
michael@0 15201 var Multiname = Shumway.AVM2.ABC.Multiname;
michael@0 15202 var ASNamespace = Shumway.AVM2.ABC.Namespace;
michael@0 15203 var AbcFile = Shumway.AVM2.ABC.AbcFile;
michael@0 15204 var AbcStream = Shumway.AVM2.ABC.AbcStream;
michael@0 15205 var ConstantPool = Shumway.AVM2.ABC.ConstantPool;
michael@0 15206 var ClassInfo = Shumway.AVM2.ABC.ClassInfo;
michael@0 15207 var MetaDataInfo = Shumway.AVM2.ABC.MetaDataInfo;
michael@0 15208 var InstanceInfo = Shumway.AVM2.ABC.InstanceInfo;
michael@0 15209 var ScriptInfo = Shumway.AVM2.ABC.ScriptInfo;
michael@0 15210 var Trait = Shumway.AVM2.ABC.Trait;
michael@0 15211 var MethodInfo = Shumway.AVM2.ABC.MethodInfo;
michael@0 15212 var Multiname = Shumway.AVM2.ABC.Multiname;
michael@0 15213 var ASNamespace = Shumway.AVM2.ABC.Namespace;
michael@0 15214 var Bytecode = function () {
michael@0 15215 function Bytecode(code) {
michael@0 15216 var op = code.readU8();
michael@0 15217 this.op = op;
michael@0 15218 this.originalPosition = code.position;
michael@0 15219 var opdesc = Shumway.AVM2.opcodeTable[op];
michael@0 15220 if (!opdesc) {
michael@0 15221 unexpected('Unknown Op ' + op);
michael@0 15222 }
michael@0 15223 this.canThrow = opdesc.canThrow;
michael@0 15224 var i, n;
michael@0 15225 switch (op) {
michael@0 15226 case OP_lookupswitch:
michael@0 15227 var defaultOffset = code.readS24();
michael@0 15228 this.offsets = [];
michael@0 15229 var n = code.readU30() + 1;
michael@0 15230 for (i = 0; i < n; i++) {
michael@0 15231 this.offsets.push(code.readS24());
michael@0 15232 }
michael@0 15233 this.offsets.push(defaultOffset);
michael@0 15234 break;
michael@0 15235 default:
michael@0 15236 for (i = 0, n = opdesc.operands.length; i < n; i++) {
michael@0 15237 var operand = opdesc.operands[i];
michael@0 15238 switch (operand.size) {
michael@0 15239 case 'u08':
michael@0 15240 this[operand.name] = code.readU8();
michael@0 15241 break;
michael@0 15242 case 's08':
michael@0 15243 this[operand.name] = code.readS8();
michael@0 15244 break;
michael@0 15245 case 's16':
michael@0 15246 this[operand.name] = code.readS16();
michael@0 15247 break;
michael@0 15248 case 's24':
michael@0 15249 this[operand.name] = code.readS24();
michael@0 15250 break;
michael@0 15251 case 'u30':
michael@0 15252 this[operand.name] = code.readU30();
michael@0 15253 break;
michael@0 15254 case 'u32':
michael@0 15255 this[operand.name] = code.readU32();
michael@0 15256 break;
michael@0 15257 default:
michael@0 15258 unexpected();
michael@0 15259 }
michael@0 15260 }
michael@0 15261 }
michael@0 15262 }
michael@0 15263 Bytecode.prototype = {
michael@0 15264 makeBlockHead: function makeBlockHead(id) {
michael@0 15265 if (this.succs) {
michael@0 15266 return id;
michael@0 15267 }
michael@0 15268 this.bid = id;
michael@0 15269 this.succs = [];
michael@0 15270 this.preds = [];
michael@0 15271 this.dominatees = [];
michael@0 15272 return id + 1;
michael@0 15273 },
michael@0 15274 trace: function trace(writer) {
michael@0 15275 if (!this.succs) {
michael@0 15276 return;
michael@0 15277 }
michael@0 15278 writer.writeLn('#' + this.bid);
michael@0 15279 },
michael@0 15280 toString: function toString(abc) {
michael@0 15281 var opDescription = Shumway.AVM2.opcodeTable[this.op];
michael@0 15282 var str = opDescription.name.padRight(' ', 20);
michael@0 15283 var i, j;
michael@0 15284 if (this.op === OP_lookupswitch) {
michael@0 15285 str += 'targets:';
michael@0 15286 for (i = 0, j = this.targets.length; i < j; i++) {
michael@0 15287 str += (i > 0 ? ',' : '') + this.targets[i].position;
michael@0 15288 }
michael@0 15289 } else {
michael@0 15290 for (i = 0, j = opDescription.operands.length; i < j; i++) {
michael@0 15291 var operand = opDescription.operands[i];
michael@0 15292 if (operand.name === 'offset') {
michael@0 15293 str += 'target:' + this.target.position;
michael@0 15294 } else {
michael@0 15295 str += operand.name + ': ';
michael@0 15296 var value = this[operand.name];
michael@0 15297 if (abc) {
michael@0 15298 switch (operand.type) {
michael@0 15299 case '':
michael@0 15300 str += value;
michael@0 15301 break;
michael@0 15302 case 'I':
michael@0 15303 str += abc.constantPool.ints[value];
michael@0 15304 break;
michael@0 15305 case 'U':
michael@0 15306 str += abc.constantPool.uints[value];
michael@0 15307 break;
michael@0 15308 case 'D':
michael@0 15309 str += abc.constantPool.doubles[value];
michael@0 15310 break;
michael@0 15311 case 'S':
michael@0 15312 str += abc.constantPool.strings[value];
michael@0 15313 break;
michael@0 15314 case 'N':
michael@0 15315 str += abc.constantPool.namespaces[value];
michael@0 15316 break;
michael@0 15317 case 'CI':
michael@0 15318 str += abc.classes[value];
michael@0 15319 break;
michael@0 15320 case 'M':
michael@0 15321 str += abc.constantPool.multinames[value];
michael@0 15322 break;
michael@0 15323 default:
michael@0 15324 str += '?';
michael@0 15325 break;
michael@0 15326 }
michael@0 15327 } else {
michael@0 15328 str += value;
michael@0 15329 }
michael@0 15330 }
michael@0 15331 if (i < j - 1) {
michael@0 15332 str += ', ';
michael@0 15333 }
michael@0 15334 }
michael@0 15335 }
michael@0 15336 return str;
michael@0 15337 }
michael@0 15338 };
michael@0 15339 return Bytecode;
michael@0 15340 }();
michael@0 15341 var Analysis = function () {
michael@0 15342 function blockSetClass(length, blockById) {
michael@0 15343 var BlockSet = BitSetFunctor(length);
michael@0 15344 var ADDRESS_BITS_PER_WORD = BlockSet.ADDRESS_BITS_PER_WORD;
michael@0 15345 var BITS_PER_WORD = BlockSet.BITS_PER_WORD;
michael@0 15346 var BIT_INDEX_MASK = BlockSet.BIT_INDEX_MASK;
michael@0 15347 BlockSet.singleton = function singleton(b) {
michael@0 15348 var bs = new BlockSet();
michael@0 15349 bs.set(b.bid);
michael@0 15350 bs.count = 1;
michael@0 15351 bs.dirty = 0;
michael@0 15352 return bs;
michael@0 15353 };
michael@0 15354 BlockSet.fromBlocks = function fromArray(other) {
michael@0 15355 var bs = new BlockSet();
michael@0 15356 bs.setBlocks(other);
michael@0 15357 return bs;
michael@0 15358 };
michael@0 15359 var Bsp = BlockSet.prototype;
michael@0 15360 if (BlockSet.singleword) {
michael@0 15361 Bsp.forEachBlock = function forEach(fn) {
michael@0 15362 true;
michael@0 15363 var byId = blockById;
michael@0 15364 var word = this.bits;
michael@0 15365 if (word) {
michael@0 15366 for (var k = 0; k < BITS_PER_WORD; k++) {
michael@0 15367 if (word & 1 << k) {
michael@0 15368 fn(byId[k]);
michael@0 15369 }
michael@0 15370 }
michael@0 15371 }
michael@0 15372 };
michael@0 15373 Bsp.choose = function choose() {
michael@0 15374 var byId = blockById;
michael@0 15375 var word = this.bits;
michael@0 15376 if (word) {
michael@0 15377 for (var k = 0; k < BITS_PER_WORD; k++) {
michael@0 15378 if (word & 1 << k) {
michael@0 15379 return byId[k];
michael@0 15380 }
michael@0 15381 }
michael@0 15382 }
michael@0 15383 };
michael@0 15384 Bsp.members = function members() {
michael@0 15385 var byId = blockById;
michael@0 15386 var set = [];
michael@0 15387 var word = this.bits;
michael@0 15388 if (word) {
michael@0 15389 for (var k = 0; k < BITS_PER_WORD; k++) {
michael@0 15390 if (word & 1 << k) {
michael@0 15391 set.push(byId[k]);
michael@0 15392 }
michael@0 15393 }
michael@0 15394 }
michael@0 15395 return set;
michael@0 15396 };
michael@0 15397 Bsp.setBlocks = function setBlocks(bs) {
michael@0 15398 var bits = this.bits;
michael@0 15399 for (var i = 0, j = bs.length; i < j; i++) {
michael@0 15400 var id = bs[i].bid;
michael@0 15401 bits |= 1 << (id & BIT_INDEX_MASK);
michael@0 15402 }
michael@0 15403 this.bits = bits;
michael@0 15404 };
michael@0 15405 } else {
michael@0 15406 Bsp.forEachBlock = function forEach(fn) {
michael@0 15407 true;
michael@0 15408 var byId = blockById;
michael@0 15409 var bits = this.bits;
michael@0 15410 for (var i = 0, j = bits.length; i < j; i++) {
michael@0 15411 var word = bits[i];
michael@0 15412 if (word) {
michael@0 15413 for (var k = 0; k < BITS_PER_WORD; k++) {
michael@0 15414 if (word & 1 << k) {
michael@0 15415 fn(byId[i * BITS_PER_WORD + k]);
michael@0 15416 }
michael@0 15417 }
michael@0 15418 }
michael@0 15419 }
michael@0 15420 };
michael@0 15421 Bsp.choose = function choose() {
michael@0 15422 var byId = blockById;
michael@0 15423 var bits = this.bits;
michael@0 15424 for (var i = 0, j = bits.length; i < j; i++) {
michael@0 15425 var word = bits[i];
michael@0 15426 if (word) {
michael@0 15427 for (var k = 0; k < BITS_PER_WORD; k++) {
michael@0 15428 if (word & 1 << k) {
michael@0 15429 return byId[i * BITS_PER_WORD + k];
michael@0 15430 }
michael@0 15431 }
michael@0 15432 }
michael@0 15433 }
michael@0 15434 };
michael@0 15435 Bsp.members = function members() {
michael@0 15436 var byId = blockById;
michael@0 15437 var set = [];
michael@0 15438 var bits = this.bits;
michael@0 15439 for (var i = 0, j = bits.length; i < j; i++) {
michael@0 15440 var word = bits[i];
michael@0 15441 if (word) {
michael@0 15442 for (var k = 0; k < BITS_PER_WORD; k++) {
michael@0 15443 if (word & 1 << k) {
michael@0 15444 set.push(byId[i * BITS_PER_WORD + k]);
michael@0 15445 }
michael@0 15446 }
michael@0 15447 }
michael@0 15448 }
michael@0 15449 return set;
michael@0 15450 };
michael@0 15451 Bsp.setBlocks = function setBlocks(bs) {
michael@0 15452 var bits = this.bits;
michael@0 15453 for (var i = 0, j = bs.length; i < j; i++) {
michael@0 15454 var id = bs[i].bid;
michael@0 15455 bits[id >> ADDRESS_BITS_PER_WORD] |= 1 << (id & BIT_INDEX_MASK);
michael@0 15456 }
michael@0 15457 };
michael@0 15458 }
michael@0 15459 return BlockSet;
michael@0 15460 }
michael@0 15461 function Analysis(method) {
michael@0 15462 Counter.count('Analysis');
michael@0 15463 this.method = method;
michael@0 15464 if (this.method.code) {
michael@0 15465 Timer.start('Normalize');
michael@0 15466 this.normalizeBytecode();
michael@0 15467 Timer.stop();
michael@0 15468 }
michael@0 15469 }
michael@0 15470 Analysis.prototype = {
michael@0 15471 normalizeBytecode: function normalizeBytecode() {
michael@0 15472 function getInvalidTarget(cache, offset) {
michael@0 15473 if (cache && cache[offset]) {
michael@0 15474 return cache[offset];
michael@0 15475 }
michael@0 15476 var code = Object.create(Bytecode.prototype);
michael@0 15477 code.op = OP_invalid;
michael@0 15478 code.position = offset;
michael@0 15479 cache && (cache[offset] = code);
michael@0 15480 return code;
michael@0 15481 }
michael@0 15482 var method = this.method;
michael@0 15483 function accessLocal(index) {
michael@0 15484 if (index-- === 0)
michael@0 15485 return;
michael@0 15486 if (index < method.parameters.length) {
michael@0 15487 method.parameters[index].isUsed = true;
michael@0 15488 }
michael@0 15489 }
michael@0 15490 var bytecodesOffset = [];
michael@0 15491 var bytecodes = [];
michael@0 15492 var codeStream = new AbcStream(this.method.code);
michael@0 15493 var code;
michael@0 15494 while (codeStream.remaining() > 0) {
michael@0 15495 var pos = codeStream.position;
michael@0 15496 code = new Bytecode(codeStream);
michael@0 15497 switch (code.op) {
michael@0 15498 case OP_nop:
michael@0 15499 case OP_label:
michael@0 15500 bytecodesOffset[pos] = bytecodes.length;
michael@0 15501 continue;
michael@0 15502 case OP_lookupswitch:
michael@0 15503 this.method.hasLookupSwitches = true;
michael@0 15504 code.targets = [];
michael@0 15505 var offsets = code.offsets;
michael@0 15506 for (var i = 0, j = offsets.length; i < j; i++) {
michael@0 15507 offsets[i] += pos;
michael@0 15508 }
michael@0 15509 break;
michael@0 15510 case OP_jump:
michael@0 15511 case OP_iflt:
michael@0 15512 case OP_ifnlt:
michael@0 15513 case OP_ifle:
michael@0 15514 case OP_ifnle:
michael@0 15515 case OP_ifgt:
michael@0 15516 case OP_ifngt:
michael@0 15517 case OP_ifge:
michael@0 15518 case OP_ifnge:
michael@0 15519 case OP_ifeq:
michael@0 15520 case OP_ifne:
michael@0 15521 case OP_ifstricteq:
michael@0 15522 case OP_ifstrictne:
michael@0 15523 case OP_iftrue:
michael@0 15524 case OP_iffalse:
michael@0 15525 code.offset += codeStream.position;
michael@0 15526 break;
michael@0 15527 case OP_getlocal0:
michael@0 15528 case OP_getlocal1:
michael@0 15529 case OP_getlocal2:
michael@0 15530 case OP_getlocal3:
michael@0 15531 accessLocal(code.op - OP_getlocal0);
michael@0 15532 break;
michael@0 15533 case OP_getlocal:
michael@0 15534 accessLocal(code.index);
michael@0 15535 break;
michael@0 15536 default:
michael@0 15537 break;
michael@0 15538 }
michael@0 15539 code.position = bytecodes.length;
michael@0 15540 bytecodesOffset[pos] = bytecodes.length;
michael@0 15541 bytecodes.push(code);
michael@0 15542 }
michael@0 15543 var invalidJumps = {};
michael@0 15544 var newOffset;
michael@0 15545 for (var pc = 0, end = bytecodes.length; pc < end; pc++) {
michael@0 15546 code = bytecodes[pc];
michael@0 15547 switch (code.op) {
michael@0 15548 case OP_lookupswitch:
michael@0 15549 var offsets = code.offsets;
michael@0 15550 for (var i = 0, j = offsets.length; i < j; i++) {
michael@0 15551 newOffset = bytecodesOffset[offsets[i]];
michael@0 15552 code.targets.push(bytecodes[newOffset] || getInvalidTarget(invalidJumps, offsets[i]));
michael@0 15553 offsets[i] = newOffset;
michael@0 15554 }
michael@0 15555 break;
michael@0 15556 case OP_jump:
michael@0 15557 case OP_iflt:
michael@0 15558 case OP_ifnlt:
michael@0 15559 case OP_ifle:
michael@0 15560 case OP_ifnle:
michael@0 15561 case OP_ifgt:
michael@0 15562 case OP_ifngt:
michael@0 15563 case OP_ifge:
michael@0 15564 case OP_ifnge:
michael@0 15565 case OP_ifeq:
michael@0 15566 case OP_ifne:
michael@0 15567 case OP_ifstricteq:
michael@0 15568 case OP_ifstrictne:
michael@0 15569 case OP_iftrue:
michael@0 15570 case OP_iffalse:
michael@0 15571 newOffset = bytecodesOffset[code.offset];
michael@0 15572 code.target = bytecodes[newOffset] || getInvalidTarget(invalidJumps, code.offset);
michael@0 15573 code.offset = newOffset;
michael@0 15574 break;
michael@0 15575 default:
michael@0 15576 }
michael@0 15577 }
michael@0 15578 this.bytecodes = bytecodes;
michael@0 15579 var exceptions = this.method.exceptions;
michael@0 15580 for (var i = 0, j = exceptions.length; i < j; i++) {
michael@0 15581 var ex = exceptions[i];
michael@0 15582 ex.start = bytecodesOffset[ex.start];
michael@0 15583 ex.end = bytecodesOffset[ex.end];
michael@0 15584 ex.offset = bytecodesOffset[ex.target];
michael@0 15585 ex.target = bytecodes[ex.offset];
michael@0 15586 ex.target.exception = ex;
michael@0 15587 }
michael@0 15588 },
michael@0 15589 detectBasicBlocks: function detectBasicBlocks() {
michael@0 15590 var bytecodes = this.bytecodes;
michael@0 15591 var exceptions = this.method.exceptions;
michael@0 15592 var hasExceptions = exceptions.length > 0;
michael@0 15593 var blockById = {};
michael@0 15594 var code;
michael@0 15595 var pc, end;
michael@0 15596 var id = 0;
michael@0 15597 function tryTargets(block) {
michael@0 15598 var targets = [];
michael@0 15599 for (var i = 0, j = exceptions.length; i < j; i++) {
michael@0 15600 var ex = exceptions[i];
michael@0 15601 if (block.position >= ex.start && block.end.position <= ex.end) {
michael@0 15602 targets.push(ex.target);
michael@0 15603 }
michael@0 15604 }
michael@0 15605 return targets;
michael@0 15606 }
michael@0 15607 id = bytecodes[0].makeBlockHead(id);
michael@0 15608 for (pc = 0, end = bytecodes.length - 1; pc < end; pc++) {
michael@0 15609 code = bytecodes[pc];
michael@0 15610 switch (code.op) {
michael@0 15611 case OP_returnvoid:
michael@0 15612 case OP_returnvalue:
michael@0 15613 case OP_throw:
michael@0 15614 id = bytecodes[pc + 1].makeBlockHead(id);
michael@0 15615 break;
michael@0 15616 case OP_lookupswitch:
michael@0 15617 var targets = code.targets;
michael@0 15618 for (var i = 0, j = targets.length; i < j; i++) {
michael@0 15619 id = targets[i].makeBlockHead(id);
michael@0 15620 }
michael@0 15621 id = bytecodes[pc + 1].makeBlockHead(id);
michael@0 15622 break;
michael@0 15623 case OP_jump:
michael@0 15624 case OP_iflt:
michael@0 15625 case OP_ifnlt:
michael@0 15626 case OP_ifle:
michael@0 15627 case OP_ifnle:
michael@0 15628 case OP_ifgt:
michael@0 15629 case OP_ifngt:
michael@0 15630 case OP_ifge:
michael@0 15631 case OP_ifnge:
michael@0 15632 case OP_ifeq:
michael@0 15633 case OP_ifne:
michael@0 15634 case OP_ifstricteq:
michael@0 15635 case OP_ifstrictne:
michael@0 15636 case OP_iftrue:
michael@0 15637 case OP_iffalse:
michael@0 15638 id = code.target.makeBlockHead(id);
michael@0 15639 id = bytecodes[pc + 1].makeBlockHead(id);
michael@0 15640 break;
michael@0 15641 default:
michael@0 15642 }
michael@0 15643 }
michael@0 15644 code = bytecodes[end];
michael@0 15645 switch (code.op) {
michael@0 15646 case OP_returnvoid:
michael@0 15647 case OP_returnvalue:
michael@0 15648 case OP_throw:
michael@0 15649 break;
michael@0 15650 case OP_lookupswitch:
michael@0 15651 var targets = code.targets;
michael@0 15652 for (var i = 0, j = targets.length; i < j; i++) {
michael@0 15653 id = targets[i].makeBlockHead(id);
michael@0 15654 }
michael@0 15655 break;
michael@0 15656 case OP_jump:
michael@0 15657 id = code.target.makeBlockHead(id);
michael@0 15658 break;
michael@0 15659 case OP_iflt:
michael@0 15660 case OP_ifnlt:
michael@0 15661 case OP_ifle:
michael@0 15662 case OP_ifnle:
michael@0 15663 case OP_ifgt:
michael@0 15664 case OP_ifngt:
michael@0 15665 case OP_ifge:
michael@0 15666 case OP_ifnge:
michael@0 15667 case OP_ifeq:
michael@0 15668 case OP_ifne:
michael@0 15669 case OP_ifstricteq:
michael@0 15670 case OP_ifstrictne:
michael@0 15671 case OP_iftrue:
michael@0 15672 case OP_iffalse:
michael@0 15673 id = code.target.makeBlockHead(id);
michael@0 15674 bytecodes[pc + 1] = getInvalidTarget(null, pc + 1);
michael@0 15675 id = bytecodes[pc + 1].makeBlockHead(id);
michael@0 15676 break;
michael@0 15677 default:
michael@0 15678 }
michael@0 15679 if (hasExceptions) {
michael@0 15680 for (var i = 0, j = exceptions.length; i < j; i++) {
michael@0 15681 var ex = exceptions[i];
michael@0 15682 var tryStart = bytecodes[ex.start];
michael@0 15683 var afterTry = bytecodes[ex.end + 1];
michael@0 15684 id = tryStart.makeBlockHead(id);
michael@0 15685 if (afterTry) {
michael@0 15686 id = afterTry.makeBlockHead(id);
michael@0 15687 }
michael@0 15688 id = ex.target.makeBlockHead(id);
michael@0 15689 }
michael@0 15690 }
michael@0 15691 var currentBlock = bytecodes[0];
michael@0 15692 for (pc = 1, end = bytecodes.length; pc < end; pc++) {
michael@0 15693 if (!bytecodes[pc].succs) {
michael@0 15694 continue;
michael@0 15695 }
michael@0 15696 true;
michael@0 15697 blockById[currentBlock.bid] = currentBlock;
michael@0 15698 code = bytecodes[pc - 1];
michael@0 15699 currentBlock.end = code;
michael@0 15700 var nextBlock = bytecodes[pc];
michael@0 15701 switch (code.op) {
michael@0 15702 case OP_returnvoid:
michael@0 15703 case OP_returnvalue:
michael@0 15704 case OP_throw:
michael@0 15705 break;
michael@0 15706 case OP_lookupswitch:
michael@0 15707 for (var i = 0, j = code.targets.length; i < j; i++) {
michael@0 15708 currentBlock.succs.push(code.targets[i]);
michael@0 15709 }
michael@0 15710 break;
michael@0 15711 case OP_jump:
michael@0 15712 currentBlock.succs.push(code.target);
michael@0 15713 break;
michael@0 15714 case OP_iflt:
michael@0 15715 case OP_ifnlt:
michael@0 15716 case OP_ifle:
michael@0 15717 case OP_ifnle:
michael@0 15718 case OP_ifgt:
michael@0 15719 case OP_ifngt:
michael@0 15720 case OP_ifge:
michael@0 15721 case OP_ifnge:
michael@0 15722 case OP_ifeq:
michael@0 15723 case OP_ifne:
michael@0 15724 case OP_ifstricteq:
michael@0 15725 case OP_ifstrictne:
michael@0 15726 case OP_iftrue:
michael@0 15727 case OP_iffalse:
michael@0 15728 currentBlock.succs.push(code.target);
michael@0 15729 if (code.target !== nextBlock) {
michael@0 15730 currentBlock.succs.push(nextBlock);
michael@0 15731 }
michael@0 15732 break;
michael@0 15733 default:
michael@0 15734 currentBlock.succs.push(nextBlock);
michael@0 15735 }
michael@0 15736 if (hasExceptions) {
michael@0 15737 var targets = tryTargets(currentBlock);
michael@0 15738 currentBlock.hasCatches = targets.length > 0;
michael@0 15739 currentBlock.succs.push.apply(currentBlock.succs, targets);
michael@0 15740 }
michael@0 15741 currentBlock = nextBlock;
michael@0 15742 }
michael@0 15743 blockById[currentBlock.bid] = currentBlock;
michael@0 15744 code = bytecodes[end - 1];
michael@0 15745 switch (code.op) {
michael@0 15746 case OP_lookupswitch:
michael@0 15747 for (var i = 0, j = code.targets.length; i < j; i++) {
michael@0 15748 currentBlock.succs.push(code.targets[i]);
michael@0 15749 }
michael@0 15750 break;
michael@0 15751 case OP_jump:
michael@0 15752 currentBlock.succs.push(code.target);
michael@0 15753 break;
michael@0 15754 default:
michael@0 15755 }
michael@0 15756 currentBlock.end = code;
michael@0 15757 this.BlockSet = blockSetClass(id, blockById);
michael@0 15758 },
michael@0 15759 normalizeReachableBlocks: function normalizeReachableBlocks() {
michael@0 15760 var root = this.bytecodes[0];
michael@0 15761 true;
michael@0 15762 var ONCE = 1;
michael@0 15763 var BUNCH_OF_TIMES = 2;
michael@0 15764 var BlockSet = this.BlockSet;
michael@0 15765 var blocks = [];
michael@0 15766 var visited = {};
michael@0 15767 var ancestors = {};
michael@0 15768 var worklist = [
michael@0 15769 root
michael@0 15770 ];
michael@0 15771 var node;
michael@0 15772 ancestors[root.bid] = true;
michael@0 15773 while (node = worklist.top()) {
michael@0 15774 if (visited[node.bid]) {
michael@0 15775 if (visited[node.bid] === ONCE) {
michael@0 15776 visited[node.bid] = BUNCH_OF_TIMES;
michael@0 15777 blocks.push(node);
michael@0 15778 var succs = node.succs;
michael@0 15779 for (var i = 0, j = succs.length; i < j; i++) {
michael@0 15780 succs[i].preds.push(node);
michael@0 15781 }
michael@0 15782 }
michael@0 15783 ancestors[node.bid] = false;
michael@0 15784 worklist.pop();
michael@0 15785 continue;
michael@0 15786 }
michael@0 15787 visited[node.bid] = ONCE;
michael@0 15788 ancestors[node.bid] = true;
michael@0 15789 var succs = node.succs;
michael@0 15790 for (var i = 0, j = succs.length; i < j; i++) {
michael@0 15791 var s = succs[i];
michael@0 15792 if (ancestors[s.bid]) {
michael@0 15793 if (!node.spbacks) {
michael@0 15794 node.spbacks = new BlockSet();
michael@0 15795 }
michael@0 15796 node.spbacks.set(s.bid);
michael@0 15797 }
michael@0 15798 !visited[s.bid] && worklist.push(s);
michael@0 15799 }
michael@0 15800 }
michael@0 15801 this.blocks = blocks.reverse();
michael@0 15802 },
michael@0 15803 computeDominance: function computeDominance() {
michael@0 15804 function intersectDominators(doms, b1, b2) {
michael@0 15805 var finger1 = b1;
michael@0 15806 var finger2 = b2;
michael@0 15807 while (finger1 !== finger2) {
michael@0 15808 while (finger1 > finger2) {
michael@0 15809 finger1 = doms[finger1];
michael@0 15810 }
michael@0 15811 while (finger2 > finger1) {
michael@0 15812 finger2 = doms[finger2];
michael@0 15813 }
michael@0 15814 }
michael@0 15815 return finger1;
michael@0 15816 }
michael@0 15817 var blocks = this.blocks;
michael@0 15818 var n = blocks.length;
michael@0 15819 var doms = new Array(n);
michael@0 15820 doms[0] = 0;
michael@0 15821 var rpo = {};
michael@0 15822 for (var b = 0; b < n; b++) {
michael@0 15823 rpo[blocks[b].bid] = b;
michael@0 15824 }
michael@0 15825 var changed = true;
michael@0 15826 while (changed) {
michael@0 15827 changed = false;
michael@0 15828 for (var b = 1; b < n; b++) {
michael@0 15829 var preds = blocks[b].preds;
michael@0 15830 var j = preds.length;
michael@0 15831 var newIdom = rpo[preds[0].bid];
michael@0 15832 if (!(newIdom in doms)) {
michael@0 15833 for (var i = 1; i < j; i++) {
michael@0 15834 newIdom = rpo[preds[i].bid];
michael@0 15835 if (newIdom in doms) {
michael@0 15836 break;
michael@0 15837 }
michael@0 15838 }
michael@0 15839 }
michael@0 15840 true;
michael@0 15841 for (var i = 0; i < j; i++) {
michael@0 15842 var p = rpo[preds[i].bid];
michael@0 15843 if (p === newIdom) {
michael@0 15844 continue;
michael@0 15845 }
michael@0 15846 if (p in doms) {
michael@0 15847 newIdom = intersectDominators(doms, p, newIdom);
michael@0 15848 }
michael@0 15849 }
michael@0 15850 if (doms[b] !== newIdom) {
michael@0 15851 doms[b] = newIdom;
michael@0 15852 changed = true;
michael@0 15853 }
michael@0 15854 }
michael@0 15855 }
michael@0 15856 blocks[0].dominator = blocks[0];
michael@0 15857 var block;
michael@0 15858 for (var b = 1; b < n; b++) {
michael@0 15859 block = blocks[b];
michael@0 15860 var idom = blocks[doms[b]];
michael@0 15861 block.dominator = idom;
michael@0 15862 idom.dominatees.push(block);
michael@0 15863 block.npreds = block.preds.length;
michael@0 15864 }
michael@0 15865 var worklist = [
michael@0 15866 blocks[0]
michael@0 15867 ];
michael@0 15868 blocks[0].level || (blocks[0].level = 0);
michael@0 15869 while (block = worklist.shift()) {
michael@0 15870 var dominatees = block.dominatees;
michael@0 15871 for (var i = 0, j = dominatees.length; i < j; i++) {
michael@0 15872 dominatees[i].level = block.level + 1;
michael@0 15873 }
michael@0 15874 worklist.push.apply(worklist, dominatees);
michael@0 15875 }
michael@0 15876 },
michael@0 15877 analyzeControlFlow: function analyzeControlFlow() {
michael@0 15878 true;
michael@0 15879 this.detectBasicBlocks();
michael@0 15880 this.normalizeReachableBlocks();
michael@0 15881 this.computeDominance();
michael@0 15882 this.analyzedControlFlow = true;
michael@0 15883 return true;
michael@0 15884 },
michael@0 15885 markLoops: function markLoops() {
michael@0 15886 if (!this.analyzedControlFlow && !this.analyzeControlFlow()) {
michael@0 15887 return false;
michael@0 15888 }
michael@0 15889 var BlockSet = this.BlockSet;
michael@0 15890 function findSCCs(root) {
michael@0 15891 var preorderId = 1;
michael@0 15892 var preorder = {};
michael@0 15893 var assigned = {};
michael@0 15894 var unconnectedNodes = [];
michael@0 15895 var pendingNodes = [];
michael@0 15896 var sccs = [];
michael@0 15897 var level = root.level + 1;
michael@0 15898 var worklist = [
michael@0 15899 root
michael@0 15900 ];
michael@0 15901 var node;
michael@0 15902 var u, s;
michael@0 15903 while (node = worklist.top()) {
michael@0 15904 if (preorder[node.bid]) {
michael@0 15905 if (pendingNodes.peek() === node) {
michael@0 15906 pendingNodes.pop();
michael@0 15907 var scc = [];
michael@0 15908 do {
michael@0 15909 u = unconnectedNodes.pop();
michael@0 15910 assigned[u.bid] = true;
michael@0 15911 scc.push(u);
michael@0 15912 } while (u !== node);
michael@0 15913 if (scc.length > 1 || u.spbacks && u.spbacks.get(u.bid)) {
michael@0 15914 sccs.push(scc);
michael@0 15915 }
michael@0 15916 }
michael@0 15917 worklist.pop();
michael@0 15918 continue;
michael@0 15919 }
michael@0 15920 preorder[node.bid] = preorderId++;
michael@0 15921 unconnectedNodes.push(node);
michael@0 15922 pendingNodes.push(node);
michael@0 15923 var succs = node.succs;
michael@0 15924 for (var i = 0, j = succs.length; i < j; i++) {
michael@0 15925 s = succs[i];
michael@0 15926 if (s.level < level) {
michael@0 15927 continue;
michael@0 15928 }
michael@0 15929 var sid = s.bid;
michael@0 15930 if (!preorder[sid]) {
michael@0 15931 worklist.push(s);
michael@0 15932 } else if (!assigned[sid]) {
michael@0 15933 while (preorder[pendingNodes.peek().bid] > preorder[sid]) {
michael@0 15934 pendingNodes.pop();
michael@0 15935 }
michael@0 15936 }
michael@0 15937 }
michael@0 15938 }
michael@0 15939 return sccs;
michael@0 15940 }
michael@0 15941 function findLoopHeads(blocks) {
michael@0 15942 var heads = new BlockSet();
michael@0 15943 for (var i = 0, j = blocks.length; i < j; i++) {
michael@0 15944 var block = blocks[i];
michael@0 15945 var spbacks = block.spbacks;
michael@0 15946 if (!spbacks) {
michael@0 15947 continue;
michael@0 15948 }
michael@0 15949 var succs = block.succs;
michael@0 15950 for (var k = 0, l = succs.length; k < l; k++) {
michael@0 15951 var s = succs[k];
michael@0 15952 if (spbacks.get(s.bid)) {
michael@0 15953 heads.set(s.dominator.bid);
michael@0 15954 }
michael@0 15955 }
michael@0 15956 }
michael@0 15957 return heads.members();
michael@0 15958 }
michael@0 15959 function LoopInfo(scc, loopId) {
michael@0 15960 var body = new BlockSet();
michael@0 15961 body.setBlocks(scc);
michael@0 15962 body.recount();
michael@0 15963 this.id = loopId;
michael@0 15964 this.body = body;
michael@0 15965 this.exit = new BlockSet();
michael@0 15966 this.save = {};
michael@0 15967 this.head = new BlockSet();
michael@0 15968 this.npreds = 0;
michael@0 15969 }
michael@0 15970 var heads = findLoopHeads(this.blocks);
michael@0 15971 if (heads.length <= 0) {
michael@0 15972 this.markedLoops = true;
michael@0 15973 return true;
michael@0 15974 }
michael@0 15975 var worklist = heads.sort(function (a, b) {
michael@0 15976 return a.level - b.level;
michael@0 15977 });
michael@0 15978 var loopId = 0;
michael@0 15979 for (var n = worklist.length - 1; n >= 0; n--) {
michael@0 15980 var top = worklist[n];
michael@0 15981 var sccs = findSCCs(top);
michael@0 15982 if (sccs.length === 0) {
michael@0 15983 continue;
michael@0 15984 }
michael@0 15985 for (var i = 0, j = sccs.length; i < j; i++) {
michael@0 15986 var scc = sccs[i];
michael@0 15987 var loop = new LoopInfo(scc, loopId++);
michael@0 15988 for (var k = 0, l = scc.length; k < l; k++) {
michael@0 15989 var h = scc[k];
michael@0 15990 if (h.level === top.level + 1 && !h.loop) {
michael@0 15991 h.loop = loop;
michael@0 15992 loop.head.set(h.bid);
michael@0 15993 var preds = h.preds;
michael@0 15994 for (var pi = 0, pj = preds.length; pi < pj; pi++) {
michael@0 15995 loop.body.get(preds[pi].bid) && h.npreds--;
michael@0 15996 }
michael@0 15997 loop.npreds += h.npreds;
michael@0 15998 }
michael@0 15999 }
michael@0 16000 for (var k = 0, l = scc.length; k < l; k++) {
michael@0 16001 var h = scc[k];
michael@0 16002 if (h.level === top.level + 1) {
michael@0 16003 h.npreds = loop.npreds;
michael@0 16004 }
michael@0 16005 }
michael@0 16006 loop.head.recount();
michael@0 16007 }
michael@0 16008 }
michael@0 16009 this.markedLoops = true;
michael@0 16010 return true;
michael@0 16011 }
michael@0 16012 };
michael@0 16013 return Analysis;
michael@0 16014 }();
michael@0 16015 (function (exports) {
michael@0 16016 var lang = exports.lang = {
michael@0 16017 Node: {},
michael@0 16018 Program: {
michael@0 16019 extends: 'Node',
michael@0 16020 fields: [
michael@0 16021 '@body'
michael@0 16022 ]
michael@0 16023 },
michael@0 16024 Statement: {
michael@0 16025 extends: 'Node'
michael@0 16026 },
michael@0 16027 EmptyStatement: {
michael@0 16028 extends: 'Statement'
michael@0 16029 },
michael@0 16030 BlockStatement: {
michael@0 16031 extends: 'Statement',
michael@0 16032 fields: [
michael@0 16033 '@body'
michael@0 16034 ]
michael@0 16035 },
michael@0 16036 ExpressionStatement: {
michael@0 16037 extends: 'Statement',
michael@0 16038 fields: [
michael@0 16039 '@expression'
michael@0 16040 ]
michael@0 16041 },
michael@0 16042 IfStatement: {
michael@0 16043 extends: 'Statement',
michael@0 16044 fields: [
michael@0 16045 '@test',
michael@0 16046 '@consequent',
michael@0 16047 '@alternate'
michael@0 16048 ]
michael@0 16049 },
michael@0 16050 LabeledStatement: {
michael@0 16051 extends: 'Statement',
michael@0 16052 fields: [
michael@0 16053 '@label',
michael@0 16054 '@body'
michael@0 16055 ]
michael@0 16056 },
michael@0 16057 BreakStatement: {
michael@0 16058 extends: 'Statement',
michael@0 16059 fields: [
michael@0 16060 '@label'
michael@0 16061 ]
michael@0 16062 },
michael@0 16063 ContinueStatement: {
michael@0 16064 extends: 'Statement',
michael@0 16065 fields: [
michael@0 16066 '@label'
michael@0 16067 ]
michael@0 16068 },
michael@0 16069 WithStatement: {
michael@0 16070 extends: 'Statement',
michael@0 16071 fields: [
michael@0 16072 '@object',
michael@0 16073 '@body'
michael@0 16074 ]
michael@0 16075 },
michael@0 16076 SwitchStatement: {
michael@0 16077 extends: 'Statement',
michael@0 16078 fields: [
michael@0 16079 '@discriminant',
michael@0 16080 '@cases',
michael@0 16081 'lexical'
michael@0 16082 ]
michael@0 16083 },
michael@0 16084 ReturnStatement: {
michael@0 16085 extends: 'Statement',
michael@0 16086 fields: [
michael@0 16087 '@argument'
michael@0 16088 ]
michael@0 16089 },
michael@0 16090 ThrowStatement: {
michael@0 16091 extends: 'Statement',
michael@0 16092 fields: [
michael@0 16093 '@argument'
michael@0 16094 ]
michael@0 16095 },
michael@0 16096 TryStatement: {
michael@0 16097 extends: 'Statement',
michael@0 16098 fields: [
michael@0 16099 '@block',
michael@0 16100 '@handlers',
michael@0 16101 '@finalizer'
michael@0 16102 ]
michael@0 16103 },
michael@0 16104 WhileStatement: {
michael@0 16105 extends: 'Statement',
michael@0 16106 fields: [
michael@0 16107 '@test',
michael@0 16108 '@body'
michael@0 16109 ]
michael@0 16110 },
michael@0 16111 DoWhileStatement: {
michael@0 16112 extends: 'Statement',
michael@0 16113 fields: [
michael@0 16114 '@body',
michael@0 16115 '@test'
michael@0 16116 ]
michael@0 16117 },
michael@0 16118 ForStatement: {
michael@0 16119 extends: 'Statement',
michael@0 16120 fields: [
michael@0 16121 '@init',
michael@0 16122 '@test',
michael@0 16123 '@update',
michael@0 16124 '@body'
michael@0 16125 ]
michael@0 16126 },
michael@0 16127 ForInStatement: {
michael@0 16128 extends: 'Statement',
michael@0 16129 fields: [
michael@0 16130 '@left',
michael@0 16131 '@right',
michael@0 16132 '@body',
michael@0 16133 'each'
michael@0 16134 ]
michael@0 16135 },
michael@0 16136 LetStatement: {
michael@0 16137 extends: 'Statement',
michael@0 16138 fields: [
michael@0 16139 '@head',
michael@0 16140 '@body'
michael@0 16141 ]
michael@0 16142 },
michael@0 16143 DebuggerStatement: {
michael@0 16144 extends: 'Statement'
michael@0 16145 },
michael@0 16146 Declaration: {
michael@0 16147 extends: 'Statement'
michael@0 16148 },
michael@0 16149 FunctionDeclaration: {
michael@0 16150 extends: 'Declaration',
michael@0 16151 fields: [
michael@0 16152 '@id',
michael@0 16153 '@params',
michael@0 16154 '@body',
michael@0 16155 '@decltype',
michael@0 16156 'generator',
michael@0 16157 'expression',
michael@0 16158 '@modifiers'
michael@0 16159 ]
michael@0 16160 },
michael@0 16161 VariableDeclaration: {
michael@0 16162 extends: 'Declaration',
michael@0 16163 fields: [
michael@0 16164 'kind',
michael@0 16165 '@declarations'
michael@0 16166 ]
michael@0 16167 },
michael@0 16168 VariableDeclarator: {
michael@0 16169 extends: 'Node',
michael@0 16170 fields: [
michael@0 16171 '@id',
michael@0 16172 '@init',
michael@0 16173 '@decltype',
michael@0 16174 '@arguments'
michael@0 16175 ]
michael@0 16176 },
michael@0 16177 Expression: {
michael@0 16178 extends: 'Pattern'
michael@0 16179 },
michael@0 16180 ThisExpression: {
michael@0 16181 extends: 'Expression'
michael@0 16182 },
michael@0 16183 ArrayExpression: {
michael@0 16184 extends: 'Expression',
michael@0 16185 fields: [
michael@0 16186 '@elements'
michael@0 16187 ]
michael@0 16188 },
michael@0 16189 ObjectExpression: {
michael@0 16190 extends: 'Expression',
michael@0 16191 fields: [
michael@0 16192 '@properties'
michael@0 16193 ]
michael@0 16194 },
michael@0 16195 Property: {
michael@0 16196 extends: 'Node',
michael@0 16197 fields: [
michael@0 16198 '@key',
michael@0 16199 '@value',
michael@0 16200 'kind'
michael@0 16201 ]
michael@0 16202 },
michael@0 16203 FunctionExpression: {
michael@0 16204 extends: 'Expression',
michael@0 16205 fields: [
michael@0 16206 '@id',
michael@0 16207 '@params',
michael@0 16208 '@body',
michael@0 16209 '@decltype',
michael@0 16210 'generator',
michael@0 16211 'expression'
michael@0 16212 ]
michael@0 16213 },
michael@0 16214 SequenceExpression: {
michael@0 16215 extends: 'Expression',
michael@0 16216 fields: [
michael@0 16217 '@expressions'
michael@0 16218 ]
michael@0 16219 },
michael@0 16220 UnaryExpression: {
michael@0 16221 extends: 'Expression',
michael@0 16222 fields: [
michael@0 16223 'operator',
michael@0 16224 '@argument',
michael@0 16225 'prefix'
michael@0 16226 ]
michael@0 16227 },
michael@0 16228 BinaryExpression: {
michael@0 16229 extends: 'Expression',
michael@0 16230 fields: [
michael@0 16231 'operator',
michael@0 16232 '@left',
michael@0 16233 '@right'
michael@0 16234 ]
michael@0 16235 },
michael@0 16236 AssignmentExpression: {
michael@0 16237 extends: 'Expression',
michael@0 16238 fields: [
michael@0 16239 '@left',
michael@0 16240 'operator',
michael@0 16241 '@right'
michael@0 16242 ]
michael@0 16243 },
michael@0 16244 UpdateExpression: {
michael@0 16245 extends: 'Expression',
michael@0 16246 fields: [
michael@0 16247 'operator',
michael@0 16248 '@argument',
michael@0 16249 'prefix'
michael@0 16250 ]
michael@0 16251 },
michael@0 16252 LogicalExpression: {
michael@0 16253 extends: 'Expression',
michael@0 16254 fields: [
michael@0 16255 'operator',
michael@0 16256 '@left',
michael@0 16257 '@right'
michael@0 16258 ]
michael@0 16259 },
michael@0 16260 ConditionalExpression: {
michael@0 16261 extends: 'Expression',
michael@0 16262 fields: [
michael@0 16263 '@test',
michael@0 16264 '@consequent',
michael@0 16265 '@alternate'
michael@0 16266 ]
michael@0 16267 },
michael@0 16268 NewExpression: {
michael@0 16269 extends: 'Expression',
michael@0 16270 fields: [
michael@0 16271 '@callee',
michael@0 16272 '@arguments'
michael@0 16273 ]
michael@0 16274 },
michael@0 16275 CallExpression: {
michael@0 16276 extends: 'Expression',
michael@0 16277 fields: [
michael@0 16278 '@callee',
michael@0 16279 '@arguments'
michael@0 16280 ]
michael@0 16281 },
michael@0 16282 MemberExpression: {
michael@0 16283 extends: 'Expression',
michael@0 16284 fields: [
michael@0 16285 '@object',
michael@0 16286 '@property',
michael@0 16287 'computed',
michael@0 16288 'kind'
michael@0 16289 ]
michael@0 16290 },
michael@0 16291 YieldExpression: {
michael@0 16292 extends: 'Expression',
michael@0 16293 fields: [
michael@0 16294 '@argument'
michael@0 16295 ]
michael@0 16296 },
michael@0 16297 ComprehensionExpression: {
michael@0 16298 extends: 'Expression',
michael@0 16299 fields: [
michael@0 16300 '@blocks',
michael@0 16301 '@filter'
michael@0 16302 ]
michael@0 16303 },
michael@0 16304 GeneratorExpression: {
michael@0 16305 extends: 'Expression',
michael@0 16306 fields: [
michael@0 16307 '@blocks',
michael@0 16308 '@filter'
michael@0 16309 ]
michael@0 16310 },
michael@0 16311 LetExpression: {
michael@0 16312 extends: 'Expression',
michael@0 16313 fields: [
michael@0 16314 '@head',
michael@0 16315 '@body'
michael@0 16316 ]
michael@0 16317 },
michael@0 16318 Pattern: {
michael@0 16319 extends: 'Node'
michael@0 16320 },
michael@0 16321 ObjectPattern: {
michael@0 16322 extends: 'Pattern',
michael@0 16323 fields: [
michael@0 16324 '@properties'
michael@0 16325 ]
michael@0 16326 },
michael@0 16327 ArrayPattern: {
michael@0 16328 extends: 'Pattern',
michael@0 16329 fields: [
michael@0 16330 '@elements'
michael@0 16331 ]
michael@0 16332 },
michael@0 16333 SwitchCase: {
michael@0 16334 extends: 'Node',
michael@0 16335 fields: [
michael@0 16336 '@test',
michael@0 16337 '@consequent'
michael@0 16338 ]
michael@0 16339 },
michael@0 16340 CatchClause: {
michael@0 16341 extends: 'Node',
michael@0 16342 fields: [
michael@0 16343 '@param',
michael@0 16344 '@guard',
michael@0 16345 '@body'
michael@0 16346 ]
michael@0 16347 },
michael@0 16348 Identifier: {
michael@0 16349 extends: 'Expression',
michael@0 16350 fields: [
michael@0 16351 'name',
michael@0 16352 'kind'
michael@0 16353 ]
michael@0 16354 },
michael@0 16355 Literal: {
michael@0 16356 extends: 'Expression',
michael@0 16357 fields: [
michael@0 16358 'value'
michael@0 16359 ]
michael@0 16360 },
michael@0 16361 Type: {
michael@0 16362 extends: 'Node'
michael@0 16363 },
michael@0 16364 PointerType: {
michael@0 16365 extends: 'Type',
michael@0 16366 fields: [
michael@0 16367 '@base'
michael@0 16368 ]
michael@0 16369 },
michael@0 16370 ArrayType: {
michael@0 16371 extends: 'PointerType',
michael@0 16372 fields: [
michael@0 16373 'length'
michael@0 16374 ]
michael@0 16375 },
michael@0 16376 StructType: {
michael@0 16377 extends: 'Type',
michael@0 16378 fields: [
michael@0 16379 '@id',
michael@0 16380 '@members',
michael@0 16381 'isUnion'
michael@0 16382 ]
michael@0 16383 },
michael@0 16384 MemberDeclarator: {
michael@0 16385 extends: 'Node',
michael@0 16386 fields: [
michael@0 16387 'modifiers',
michael@0 16388 '@declarator'
michael@0 16389 ]
michael@0 16390 },
michael@0 16391 ArrowType: {
michael@0 16392 extends: 'Type',
michael@0 16393 fields: [
michael@0 16394 '@params',
michael@0 16395 '@return'
michael@0 16396 ]
michael@0 16397 },
michael@0 16398 TypeIdentifier: {
michael@0 16399 extends: 'Type',
michael@0 16400 fields: [
michael@0 16401 'name'
michael@0 16402 ]
michael@0 16403 },
michael@0 16404 TypeAliasDirective: {
michael@0 16405 extends: 'Node',
michael@0 16406 fields: [
michael@0 16407 '@original',
michael@0 16408 '@alias'
michael@0 16409 ]
michael@0 16410 },
michael@0 16411 CastExpression: {
michael@0 16412 extends: 'Expression',
michael@0 16413 fields: [
michael@0 16414 '@as',
michael@0 16415 '@argument'
michael@0 16416 ]
michael@0 16417 }
michael@0 16418 };
michael@0 16419 function allFields(spec) {
michael@0 16420 var fields = [
michael@0 16421 'leadingComments',
michael@0 16422 'loc'
michael@0 16423 ];
michael@0 16424 while (spec) {
michael@0 16425 if (spec.fields) {
michael@0 16426 fields = spec.fields.concat(fields);
michael@0 16427 }
michael@0 16428 spec = spec.extends ? lang[spec.extends] : null;
michael@0 16429 }
michael@0 16430 return fields;
michael@0 16431 }
michael@0 16432 ;
michael@0 16433 exports.allFields = allFields;
michael@0 16434 function prefixUnderscore(s) {
michael@0 16435 return '_' + s;
michael@0 16436 }
michael@0 16437 function ensureConstructor(name, spec) {
michael@0 16438 if (!exports[name]) {
michael@0 16439 var fields = allFields(spec);
michael@0 16440 var children = [];
michael@0 16441 var body = [
michael@0 16442 'this.type = "' + name + '";'
michael@0 16443 ];
michael@0 16444 for (var i = 0, j = fields.length; i < j; i++) {
michael@0 16445 var fname = fields[i];
michael@0 16446 if (fname.charAt(0) === '@') {
michael@0 16447 fields[i] = fname = fname.substr(1);
michael@0 16448 children.push(fname);
michael@0 16449 }
michael@0 16450 body.push('this.' + fname + ' = _' + fname + ';');
michael@0 16451 }
michael@0 16452 var node = new Function(fields.map(prefixUnderscore), body.join('\n'));
michael@0 16453 if (spec.extends) {
michael@0 16454 var pnode = ensureConstructor(spec.extends, lang[spec.extends]);
michael@0 16455 node.prototype = Object.create(pnode.prototype);
michael@0 16456 }
michael@0 16457 Object.defineProperty(node.prototype, '_children', {
michael@0 16458 value: children,
michael@0 16459 writable: true,
michael@0 16460 configurable: true,
michael@0 16461 enumerable: false
michael@0 16462 });
michael@0 16463 exports[name] = node;
michael@0 16464 }
michael@0 16465 return exports[name];
michael@0 16466 }
michael@0 16467 for (var name in lang) {
michael@0 16468 ensureConstructor(name, lang[name]);
michael@0 16469 }
michael@0 16470 exports.makePass = function makePass(name, prop) {
michael@0 16471 return function (o) {
michael@0 16472 var trans, arr;
michael@0 16473 var child, children = this._children;
michael@0 16474 for (var i = 0, j = children.length; i < j; i++) {
michael@0 16475 if (!(child = this[children[i]])) {
michael@0 16476 continue;
michael@0 16477 }
michael@0 16478 if (child instanceof Array) {
michael@0 16479 arr = this[children[i]] = [];
michael@0 16480 for (var k = 0, l = child.length; k < l; k++) {
michael@0 16481 if (!child[k]) {
michael@0 16482 arr.push(child[k]);
michael@0 16483 } else if (typeof child[k][name] === 'function') {
michael@0 16484 trans = child[k][name](o);
michael@0 16485 if (trans !== null) {
michael@0 16486 arr.push(trans);
michael@0 16487 }
michael@0 16488 }
michael@0 16489 }
michael@0 16490 } else if (typeof child[name] === 'function') {
michael@0 16491 trans = child[name](o);
michael@0 16492 if (trans === null) {
michael@0 16493 this[children[i]] = undefined;
michael@0 16494 } else {
michael@0 16495 this[children[i]] = trans;
michael@0 16496 }
michael@0 16497 }
michael@0 16498 }
michael@0 16499 if (typeof this[prop] === 'function') {
michael@0 16500 if (o.logger && typeof this.loc !== 'undefined') {
michael@0 16501 o.logger.push(this);
michael@0 16502 trans = this[prop](o);
michael@0 16503 o.logger.pop();
michael@0 16504 } else {
michael@0 16505 trans = this[prop](o);
michael@0 16506 }
michael@0 16507 if (trans === null) {
michael@0 16508 return null;
michael@0 16509 }
michael@0 16510 return trans ? trans : this;
michael@0 16511 }
michael@0 16512 return this;
michael@0 16513 };
michael@0 16514 };
michael@0 16515 exports.makePass = function makePass(name, prop, backward) {
michael@0 16516 return function (o) {
michael@0 16517 var trans, arr;
michael@0 16518 var child, children = this._children;
michael@0 16519 var i, k;
michael@0 16520 for (var x = 0, j = children.length; x < j; x++) {
michael@0 16521 i = backward ? children.length - 1 - x : x;
michael@0 16522 if (!(child = this[children[i]])) {
michael@0 16523 continue;
michael@0 16524 }
michael@0 16525 if (child instanceof Array) {
michael@0 16526 arr = this[children[i]] = [];
michael@0 16527 var y;
michael@0 16528 for (var y = 0, l = child.length; y < l; y++) {
michael@0 16529 k = backward ? child.length - 1 - y : y;
michael@0 16530 if (!child[k]) {
michael@0 16531 if (backward) {
michael@0 16532 arr.unshift(child[k]);
michael@0 16533 } else {
michael@0 16534 arr.push(child[k]);
michael@0 16535 }
michael@0 16536 } else if (typeof child[k][name] === 'function') {
michael@0 16537 trans = child[k][name](o);
michael@0 16538 if (trans !== null) {
michael@0 16539 if (backward) {
michael@0 16540 arr.unshift(trans);
michael@0 16541 } else {
michael@0 16542 arr.push(trans);
michael@0 16543 }
michael@0 16544 }
michael@0 16545 }
michael@0 16546 }
michael@0 16547 } else if (typeof child[name] === 'function') {
michael@0 16548 trans = child[name](o);
michael@0 16549 if (trans === null) {
michael@0 16550 this[children[i]] = undefined;
michael@0 16551 } else {
michael@0 16552 this[children[i]] = trans;
michael@0 16553 }
michael@0 16554 }
michael@0 16555 }
michael@0 16556 if (typeof this[prop] === 'function') {
michael@0 16557 if (o.logger && typeof this.loc !== 'undefined') {
michael@0 16558 o.logger.push(this);
michael@0 16559 trans = this[prop](o);
michael@0 16560 o.logger.pop();
michael@0 16561 } else {
michael@0 16562 trans = this[prop](o);
michael@0 16563 }
michael@0 16564 if (trans === null) {
michael@0 16565 return null;
michael@0 16566 }
michael@0 16567 return trans ? trans : this;
michael@0 16568 }
michael@0 16569 return this;
michael@0 16570 };
michael@0 16571 };
michael@0 16572 exports.lift = function lift(raw) {
michael@0 16573 if (!raw) {
michael@0 16574 return raw;
michael@0 16575 }
michael@0 16576 if (raw instanceof Array) {
michael@0 16577 return raw.map(function (r) {
michael@0 16578 return r ? lift(r) : r;
michael@0 16579 });
michael@0 16580 }
michael@0 16581 var type = raw.type;
michael@0 16582 var Node = exports[type];
michael@0 16583 if (!Node) {
michael@0 16584 throw new Error('unknown node type `' + type + '\'');
michael@0 16585 }
michael@0 16586 var node = new Node();
michael@0 16587 node.loc = raw.loc;
michael@0 16588 var fields = allFields(lang[type]);
michael@0 16589 for (var i = 0, j = fields.length; i < j; i++) {
michael@0 16590 var field;
michael@0 16591 if (fields[i].charAt(0) === '@') {
michael@0 16592 field = fields[i].substr(1);
michael@0 16593 if (raw[field]) {
michael@0 16594 node[field] = lift(raw[field]);
michael@0 16595 }
michael@0 16596 } else {
michael@0 16597 field = fields[i];
michael@0 16598 node[field] = raw[field];
michael@0 16599 }
michael@0 16600 }
michael@0 16601 return node;
michael@0 16602 };
michael@0 16603 exports.flatten = function flatten(node) {
michael@0 16604 if (!node) {
michael@0 16605 return node;
michael@0 16606 }
michael@0 16607 if (node instanceof Array) {
michael@0 16608 return node.map(function (n) {
michael@0 16609 return flatten(n);
michael@0 16610 });
michael@0 16611 }
michael@0 16612 var type = node.type;
michael@0 16613 var raw = {
michael@0 16614 type: type
michael@0 16615 };
michael@0 16616 var fields = allFields(lang[type]);
michael@0 16617 for (var i = 0, j = fields.length; i < j; i++) {
michael@0 16618 var field;
michael@0 16619 if (fields[i].charAt(0) === '@') {
michael@0 16620 field = fields[i].substr(1);
michael@0 16621 if (node[field]) {
michael@0 16622 raw[field] = flatten(node[field]);
michael@0 16623 } else {
michael@0 16624 raw[field] = null;
michael@0 16625 }
michael@0 16626 } else {
michael@0 16627 field = fields[i];
michael@0 16628 raw[field] = node[field];
michael@0 16629 }
michael@0 16630 }
michael@0 16631 return raw;
michael@0 16632 };
michael@0 16633 }(typeof exports === 'undefined' ? estransform = {} : exports));
michael@0 16634 (function (exports) {
michael@0 16635 var Syntax, Precedence, BinaryPrecedence, Regex, VisitorKeys, VisitorOption, isArray, base, indent, json, renumber, hexadecimal, quotes, escapeless, newline, space, parentheses, semicolons, extra, parse;
michael@0 16636 Syntax = {
michael@0 16637 AssignmentExpression: 'AssignmentExpression',
michael@0 16638 ArrayExpression: 'ArrayExpression',
michael@0 16639 BlockStatement: 'BlockStatement',
michael@0 16640 BinaryExpression: 'BinaryExpression',
michael@0 16641 BreakStatement: 'BreakStatement',
michael@0 16642 CallExpression: 'CallExpression',
michael@0 16643 CatchClause: 'CatchClause',
michael@0 16644 ConditionalExpression: 'ConditionalExpression',
michael@0 16645 ContinueStatement: 'ContinueStatement',
michael@0 16646 DoWhileStatement: 'DoWhileStatement',
michael@0 16647 DebuggerStatement: 'DebuggerStatement',
michael@0 16648 EmptyStatement: 'EmptyStatement',
michael@0 16649 ExpressionStatement: 'ExpressionStatement',
michael@0 16650 ForStatement: 'ForStatement',
michael@0 16651 ForInStatement: 'ForInStatement',
michael@0 16652 FunctionDeclaration: 'FunctionDeclaration',
michael@0 16653 FunctionExpression: 'FunctionExpression',
michael@0 16654 Identifier: 'Identifier',
michael@0 16655 IfStatement: 'IfStatement',
michael@0 16656 Literal: 'Literal',
michael@0 16657 LabeledStatement: 'LabeledStatement',
michael@0 16658 LogicalExpression: 'LogicalExpression',
michael@0 16659 MemberExpression: 'MemberExpression',
michael@0 16660 NewExpression: 'NewExpression',
michael@0 16661 ObjectExpression: 'ObjectExpression',
michael@0 16662 Program: 'Program',
michael@0 16663 Property: 'Property',
michael@0 16664 ReturnStatement: 'ReturnStatement',
michael@0 16665 SequenceExpression: 'SequenceExpression',
michael@0 16666 SwitchStatement: 'SwitchStatement',
michael@0 16667 SwitchCase: 'SwitchCase',
michael@0 16668 ThisExpression: 'ThisExpression',
michael@0 16669 ThrowStatement: 'ThrowStatement',
michael@0 16670 TryStatement: 'TryStatement',
michael@0 16671 UnaryExpression: 'UnaryExpression',
michael@0 16672 UpdateExpression: 'UpdateExpression',
michael@0 16673 VariableDeclaration: 'VariableDeclaration',
michael@0 16674 VariableDeclarator: 'VariableDeclarator',
michael@0 16675 WhileStatement: 'WhileStatement',
michael@0 16676 WithStatement: 'WithStatement'
michael@0 16677 };
michael@0 16678 Precedence = {
michael@0 16679 Sequence: 0,
michael@0 16680 Assignment: 1,
michael@0 16681 Conditional: 2,
michael@0 16682 LogicalOR: 3,
michael@0 16683 LogicalAND: 4,
michael@0 16684 BitwiseOR: 5,
michael@0 16685 BitwiseXOR: 6,
michael@0 16686 BitwiseAND: 7,
michael@0 16687 Equality: 8,
michael@0 16688 Relational: 9,
michael@0 16689 BitwiseSHIFT: 10,
michael@0 16690 Additive: 11,
michael@0 16691 Multiplicative: 12,
michael@0 16692 Unary: 13,
michael@0 16693 Postfix: 14,
michael@0 16694 Call: 15,
michael@0 16695 New: 16,
michael@0 16696 Member: 17,
michael@0 16697 Primary: 18
michael@0 16698 };
michael@0 16699 BinaryPrecedence = {
michael@0 16700 '||': Precedence.LogicalOR,
michael@0 16701 '&&': Precedence.LogicalAND,
michael@0 16702 '|': Precedence.BitwiseOR,
michael@0 16703 '^': Precedence.BitwiseXOR,
michael@0 16704 '&': Precedence.BitwiseAND,
michael@0 16705 '==': Precedence.Equality,
michael@0 16706 '!=': Precedence.Equality,
michael@0 16707 '===': Precedence.Equality,
michael@0 16708 '!==': Precedence.Equality,
michael@0 16709 '<': Precedence.Relational,
michael@0 16710 '>': Precedence.Relational,
michael@0 16711 '<=': Precedence.Relational,
michael@0 16712 '>=': Precedence.Relational,
michael@0 16713 'in': Precedence.Relational,
michael@0 16714 'instanceof': Precedence.Relational,
michael@0 16715 '<<': Precedence.BitwiseSHIFT,
michael@0 16716 '>>': Precedence.BitwiseSHIFT,
michael@0 16717 '>>>': Precedence.BitwiseSHIFT,
michael@0 16718 '+': Precedence.Additive,
michael@0 16719 '-': Precedence.Additive,
michael@0 16720 '*': Precedence.Multiplicative,
michael@0 16721 '%': Precedence.Multiplicative,
michael@0 16722 '/': Precedence.Multiplicative
michael@0 16723 };
michael@0 16724 Regex = {
michael@0 16725 NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]')
michael@0 16726 };
michael@0 16727 function getDefaultOptions() {
michael@0 16728 return {
michael@0 16729 indent: null,
michael@0 16730 base: null,
michael@0 16731 parse: null,
michael@0 16732 comment: false,
michael@0 16733 format: {
michael@0 16734 indent: {
michael@0 16735 style: ' ',
michael@0 16736 base: 0,
michael@0 16737 adjustMultilineComment: false
michael@0 16738 },
michael@0 16739 json: false,
michael@0 16740 renumber: false,
michael@0 16741 hexadecimal: false,
michael@0 16742 quotes: 'single',
michael@0 16743 escapeless: false,
michael@0 16744 compact: false,
michael@0 16745 parentheses: true,
michael@0 16746 semicolons: true
michael@0 16747 }
michael@0 16748 };
michael@0 16749 }
michael@0 16750 function stringToArray(str) {
michael@0 16751 var length = str.length, result = [], i;
michael@0 16752 for (i = 0; i < length; i += 1) {
michael@0 16753 result[i] = str.charAt(i);
michael@0 16754 }
michael@0 16755 return result;
michael@0 16756 }
michael@0 16757 function stringRepeat(str, num) {
michael@0 16758 var result = '';
michael@0 16759 for (num |= 0; num > 0; num >>>= 1, str += str) {
michael@0 16760 if (num & 1) {
michael@0 16761 result += str;
michael@0 16762 }
michael@0 16763 }
michael@0 16764 return result;
michael@0 16765 }
michael@0 16766 isArray = Array.isArray;
michael@0 16767 if (!isArray) {
michael@0 16768 isArray = function isArray(array) {
michael@0 16769 return Object.prototype.toString.call(array) === '[object Array]';
michael@0 16770 };
michael@0 16771 }
michael@0 16772 function endsWithLineTerminator(str) {
michael@0 16773 var len, ch;
michael@0 16774 len = str.length;
michael@0 16775 ch = str.charAt(len - 1);
michael@0 16776 return ch === '\r' || ch === '\n';
michael@0 16777 }
michael@0 16778 function shallowCopy(obj) {
michael@0 16779 var ret = {}, key;
michael@0 16780 for (key in obj) {
michael@0 16781 if (obj.hasOwnProperty(key)) {
michael@0 16782 ret[key] = obj[key];
michael@0 16783 }
michael@0 16784 }
michael@0 16785 return ret;
michael@0 16786 }
michael@0 16787 function deepCopy(obj) {
michael@0 16788 var ret = {}, key, val;
michael@0 16789 for (key in obj) {
michael@0 16790 if (obj.hasOwnProperty(key)) {
michael@0 16791 val = obj[key];
michael@0 16792 if (typeof val === 'object' && val !== null) {
michael@0 16793 ret[key] = deepCopy(val);
michael@0 16794 } else {
michael@0 16795 ret[key] = val;
michael@0 16796 }
michael@0 16797 }
michael@0 16798 }
michael@0 16799 return ret;
michael@0 16800 }
michael@0 16801 function updateDeeply(target, override) {
michael@0 16802 var key, val;
michael@0 16803 function isHashObject(target) {
michael@0 16804 return typeof target === 'object' && target instanceof Object && !(target instanceof RegExp);
michael@0 16805 }
michael@0 16806 for (key in override) {
michael@0 16807 if (override.hasOwnProperty(key)) {
michael@0 16808 val = override[key];
michael@0 16809 if (isHashObject(val)) {
michael@0 16810 if (isHashObject(target[key])) {
michael@0 16811 updateDeeply(target[key], val);
michael@0 16812 } else {
michael@0 16813 target[key] = updateDeeply({}, val);
michael@0 16814 }
michael@0 16815 } else {
michael@0 16816 target[key] = val;
michael@0 16817 }
michael@0 16818 }
michael@0 16819 }
michael@0 16820 return target;
michael@0 16821 }
michael@0 16822 function generateNumber(value) {
michael@0 16823 var result, point, temp, exponent, pos;
michael@0 16824 if (value !== value) {
michael@0 16825 throw new Error('Numeric literal whose value is NaN');
michael@0 16826 }
michael@0 16827 if (1 / value < 0) {
michael@0 16828 throw new Error('Numeric literal whose value is negative');
michael@0 16829 }
michael@0 16830 if (value === 1 / 0) {
michael@0 16831 return json ? 'null' : renumber ? '1e400' : '1e+400';
michael@0 16832 }
michael@0 16833 result = '' + value;
michael@0 16834 if (!renumber || result.length < 3) {
michael@0 16835 return result;
michael@0 16836 }
michael@0 16837 point = result.indexOf('.');
michael@0 16838 if (!json && result.charAt(0) === '0' && point === 1) {
michael@0 16839 point = 0;
michael@0 16840 result = result.slice(1);
michael@0 16841 }
michael@0 16842 temp = result;
michael@0 16843 result = result.replace('e+', 'e');
michael@0 16844 exponent = 0;
michael@0 16845 if ((pos = temp.indexOf('e')) > 0) {
michael@0 16846 exponent = +temp.slice(pos + 1);
michael@0 16847 temp = temp.slice(0, pos);
michael@0 16848 }
michael@0 16849 if (point >= 0) {
michael@0 16850 exponent -= temp.length - point - 1;
michael@0 16851 temp = +(temp.slice(0, point) + temp.slice(point + 1)) + '';
michael@0 16852 }
michael@0 16853 pos = 0;
michael@0 16854 while (temp.charAt(temp.length + pos - 1) === '0') {
michael@0 16855 pos -= 1;
michael@0 16856 }
michael@0 16857 if (pos !== 0) {
michael@0 16858 exponent -= pos;
michael@0 16859 temp = temp.slice(0, pos);
michael@0 16860 }
michael@0 16861 if (exponent !== 0) {
michael@0 16862 temp += 'e' + exponent;
michael@0 16863 }
michael@0 16864 if ((temp.length < result.length || hexadecimal && value > 1000000000000 && Math.floor(value) === value && (temp = '0x' + value.toString(16)).length < result.length) && +temp === value) {
michael@0 16865 result = temp;
michael@0 16866 }
michael@0 16867 return result;
michael@0 16868 }
michael@0 16869 function escapeAllowedCharacter(ch, next) {
michael@0 16870 var code = ch.charCodeAt(0), hex = code.toString(16), result = '\\';
michael@0 16871 switch (ch) {
michael@0 16872 case '\b':
michael@0 16873 result += 'b';
michael@0 16874 break;
michael@0 16875 case '\f':
michael@0 16876 result += 'f';
michael@0 16877 break;
michael@0 16878 case '\t':
michael@0 16879 result += 't';
michael@0 16880 break;
michael@0 16881 default:
michael@0 16882 if (json || code > 255) {
michael@0 16883 result += 'u' + '0000'.slice(hex.length) + hex;
michael@0 16884 } else if (ch === '\0' && '0123456789'.indexOf(next) < 0) {
michael@0 16885 result += '0';
michael@0 16886 } else if (ch === '\v') {
michael@0 16887 result += 'v';
michael@0 16888 } else {
michael@0 16889 result += 'x' + '00'.slice(hex.length) + hex;
michael@0 16890 }
michael@0 16891 break;
michael@0 16892 }
michael@0 16893 return result;
michael@0 16894 }
michael@0 16895 function escapeDisallowedCharacter(ch) {
michael@0 16896 var result = '\\';
michael@0 16897 switch (ch) {
michael@0 16898 case '\\':
michael@0 16899 result += '\\';
michael@0 16900 break;
michael@0 16901 case '\n':
michael@0 16902 result += 'n';
michael@0 16903 break;
michael@0 16904 case '\r':
michael@0 16905 result += 'r';
michael@0 16906 break;
michael@0 16907 case '\u2028':
michael@0 16908 result += 'u2028';
michael@0 16909 break;
michael@0 16910 case '\u2029':
michael@0 16911 result += 'u2029';
michael@0 16912 break;
michael@0 16913 default:
michael@0 16914 throw new Error('Incorrectly classified character');
michael@0 16915 }
michael@0 16916 return result;
michael@0 16917 }
michael@0 16918 function escapeString(str) {
michael@0 16919 var result = '', i, len, ch, next, singleQuotes = 0, doubleQuotes = 0, single;
michael@0 16920 if (typeof str[0] === 'undefined') {
michael@0 16921 str = stringToArray(str);
michael@0 16922 }
michael@0 16923 for (i = 0, len = str.length; i < len; i += 1) {
michael@0 16924 ch = str[i];
michael@0 16925 if (ch === '\'') {
michael@0 16926 singleQuotes += 1;
michael@0 16927 } else if (ch === '"') {
michael@0 16928 doubleQuotes += 1;
michael@0 16929 } else if (ch === '/' && json) {
michael@0 16930 result += '\\';
michael@0 16931 } else if ('\\\n\r\u2028\u2029'.indexOf(ch) >= 0) {
michael@0 16932 result += escapeDisallowedCharacter(ch);
michael@0 16933 continue;
michael@0 16934 } else if (json && ch < ' ' || !(json || escapeless || ch >= ' ' && ch <= '~')) {
michael@0 16935 result += escapeAllowedCharacter(ch, str[i + 1]);
michael@0 16936 continue;
michael@0 16937 }
michael@0 16938 result += ch;
michael@0 16939 }
michael@0 16940 single = !(quotes === 'double' || quotes === 'auto' && doubleQuotes < singleQuotes);
michael@0 16941 str = result;
michael@0 16942 result = single ? '\'' : '"';
michael@0 16943 if (typeof str[0] === 'undefined') {
michael@0 16944 str = stringToArray(str);
michael@0 16945 }
michael@0 16946 for (i = 0, len = str.length; i < len; i += 1) {
michael@0 16947 ch = str[i];
michael@0 16948 if (ch === '\'' && single || ch === '"' && !single) {
michael@0 16949 result += '\\';
michael@0 16950 }
michael@0 16951 result += ch;
michael@0 16952 }
michael@0 16953 return result + (single ? '\'' : '"');
michael@0 16954 }
michael@0 16955 function isWhiteSpace(ch) {
michael@0 16956 return '\t\v\f \xa0'.indexOf(ch) >= 0 || ch.charCodeAt(0) >= 5760 && '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\ufeff'.indexOf(ch) >= 0;
michael@0 16957 }
michael@0 16958 function isLineTerminator(ch) {
michael@0 16959 return '\n\r\u2028\u2029'.indexOf(ch) >= 0;
michael@0 16960 }
michael@0 16961 function isIdentifierPart(ch) {
michael@0 16962 return ch === '$' || ch === '_' || ch === '\\' || ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9' || ch.charCodeAt(0) >= 128 && Regex.NonAsciiIdentifierPart.test(ch);
michael@0 16963 }
michael@0 16964 function join(left, right) {
michael@0 16965 var leftChar = left.charAt(left.length - 1), rightChar = right.charAt(0);
michael@0 16966 if ((leftChar === '+' || leftChar === '-') && leftChar === rightChar || isIdentifierPart(leftChar) && isIdentifierPart(rightChar)) {
michael@0 16967 return left + ' ' + right;
michael@0 16968 } else if (isWhiteSpace(leftChar) || isLineTerminator(leftChar) || isWhiteSpace(rightChar) || isLineTerminator(rightChar)) {
michael@0 16969 return left + right;
michael@0 16970 }
michael@0 16971 return left + space + right;
michael@0 16972 }
michael@0 16973 function addIndent(stmt) {
michael@0 16974 return base + stmt;
michael@0 16975 }
michael@0 16976 function calculateSpaces(str) {
michael@0 16977 var i;
michael@0 16978 for (i = str.length - 1; i >= 0; i -= 1) {
michael@0 16979 if (isLineTerminator(str.charAt(i))) {
michael@0 16980 break;
michael@0 16981 }
michael@0 16982 }
michael@0 16983 return str.length - 1 - i;
michael@0 16984 }
michael@0 16985 function adjustMultilineComment(value, specialBase) {
michael@0 16986 var array, i, len, line, j, ch, spaces, previousBase;
michael@0 16987 array = value.split(/\r\n|[\r\n]/);
michael@0 16988 spaces = Number.MAX_VALUE;
michael@0 16989 for (i = 1, len = array.length; i < len; i += 1) {
michael@0 16990 line = array[i];
michael@0 16991 j = 0;
michael@0 16992 while (j < line.length && isWhiteSpace(line[j])) {
michael@0 16993 j += 1;
michael@0 16994 }
michael@0 16995 if (spaces > j) {
michael@0 16996 spaces = j;
michael@0 16997 }
michael@0 16998 }
michael@0 16999 if (typeof specialBase !== 'undefined') {
michael@0 17000 previousBase = base;
michael@0 17001 if (array[1][spaces] === '*') {
michael@0 17002 specialBase += ' ';
michael@0 17003 }
michael@0 17004 base = specialBase;
michael@0 17005 } else {
michael@0 17006 if (spaces % 2 === 1) {
michael@0 17007 spaces -= 1;
michael@0 17008 }
michael@0 17009 previousBase = base;
michael@0 17010 }
michael@0 17011 for (i = 1, len = array.length; i < len; i += 1) {
michael@0 17012 array[i] = addIndent(array[i].slice(spaces));
michael@0 17013 }
michael@0 17014 base = previousBase;
michael@0 17015 return array.join('\n');
michael@0 17016 }
michael@0 17017 function generateComment(comment, specialBase) {
michael@0 17018 if (comment.type === 'Line') {
michael@0 17019 if (endsWithLineTerminator(comment.value)) {
michael@0 17020 return '//' + comment.value;
michael@0 17021 } else {
michael@0 17022 return '//' + comment.value + '\n';
michael@0 17023 }
michael@0 17024 }
michael@0 17025 if (extra.format.indent.adjustMultilineComment && /[\n\r]/.test(comment.value)) {
michael@0 17026 return adjustMultilineComment('/*' + comment.value + '*/', specialBase);
michael@0 17027 }
michael@0 17028 return '/*' + comment.value + '*/';
michael@0 17029 }
michael@0 17030 function addCommentsToStatement(stmt, result) {
michael@0 17031 var i, len, comment, save, node, tailingToStatement, specialBase, fragment;
michael@0 17032 if (stmt.leadingComments) {
michael@0 17033 save = result;
michael@0 17034 comment = stmt.leadingComments[0];
michael@0 17035 result = generateComment(comment);
michael@0 17036 if (!endsWithLineTerminator(result)) {
michael@0 17037 result += '\n';
michael@0 17038 }
michael@0 17039 for (i = 1, len = stmt.leadingComments.length; i < len; i += 1) {
michael@0 17040 comment = stmt.leadingComments[i];
michael@0 17041 fragment = generateComment(comment);
michael@0 17042 if (!endsWithLineTerminator(fragment)) {
michael@0 17043 fragment += '\n';
michael@0 17044 }
michael@0 17045 result += addIndent(fragment);
michael@0 17046 }
michael@0 17047 result += addIndent(save);
michael@0 17048 }
michael@0 17049 if (stmt.trailingComments) {
michael@0 17050 tailingToStatement = !endsWithLineTerminator(result);
michael@0 17051 specialBase = stringRepeat(' ', calculateSpaces(base + result + indent));
michael@0 17052 for (i = 0, len = stmt.trailingComments.length; i < len; i += 1) {
michael@0 17053 comment = stmt.trailingComments[i];
michael@0 17054 if (tailingToStatement) {
michael@0 17055 if (i === 0) {
michael@0 17056 result += indent;
michael@0 17057 } else {
michael@0 17058 result += specialBase;
michael@0 17059 }
michael@0 17060 result += generateComment(comment, specialBase);
michael@0 17061 } else {
michael@0 17062 result += addIndent(generateComment(comment));
michael@0 17063 }
michael@0 17064 if (i !== len - 1 && !endsWithLineTerminator(result)) {
michael@0 17065 result += '\n';
michael@0 17066 }
michael@0 17067 }
michael@0 17068 }
michael@0 17069 return result;
michael@0 17070 }
michael@0 17071 function parenthesize(text, current, should) {
michael@0 17072 if (current < should) {
michael@0 17073 return '(' + text + ')';
michael@0 17074 }
michael@0 17075 return text;
michael@0 17076 }
michael@0 17077 function maybeBlock(stmt, semicolonOptional) {
michael@0 17078 var previousBase, result, noLeadingComment;
michael@0 17079 noLeadingComment = !extra.comment || !stmt.leadingComments;
michael@0 17080 if (stmt.type === Syntax.BlockStatement && noLeadingComment) {
michael@0 17081 return space + generateStatement(stmt);
michael@0 17082 }
michael@0 17083 if (stmt.type === Syntax.EmptyStatement && noLeadingComment) {
michael@0 17084 return ';';
michael@0 17085 }
michael@0 17086 previousBase = base;
michael@0 17087 base += indent;
michael@0 17088 result = newline + addIndent(generateStatement(stmt, {
michael@0 17089 semicolonOptional: semicolonOptional
michael@0 17090 }));
michael@0 17091 base = previousBase;
michael@0 17092 return result;
michael@0 17093 }
michael@0 17094 function maybeBlockSuffix(stmt, result) {
michael@0 17095 if (stmt.type === Syntax.BlockStatement && (!extra.comment || !stmt.leadingComments) && !endsWithLineTerminator(result)) {
michael@0 17096 return space;
michael@0 17097 }
michael@0 17098 if (endsWithLineTerminator(result)) {
michael@0 17099 return addIndent('');
michael@0 17100 }
michael@0 17101 return (newline === '' ? ' ' : newline) + addIndent('');
michael@0 17102 }
michael@0 17103 function generateFunctionBody(node) {
michael@0 17104 var result, i, len;
michael@0 17105 result = '(';
michael@0 17106 for (i = 0, len = node.params.length; i < len; i += 1) {
michael@0 17107 result += node.params[i].name;
michael@0 17108 if (i + 1 < len) {
michael@0 17109 result += ',' + space;
michael@0 17110 }
michael@0 17111 }
michael@0 17112 return result + ')' + maybeBlock(node.body);
michael@0 17113 }
michael@0 17114 function generateExpression(expr, option) {
michael@0 17115 var result, precedence, currentPrecedence, previousBase, i, len, raw, fragment, allowIn, allowCall, allowUnparenthesizedNew;
michael@0 17116 precedence = option.precedence;
michael@0 17117 allowIn = option.allowIn;
michael@0 17118 allowCall = option.allowCall;
michael@0 17119 switch (expr.type) {
michael@0 17120 case Syntax.SequenceExpression:
michael@0 17121 result = '';
michael@0 17122 allowIn |= Precedence.Sequence < precedence;
michael@0 17123 for (i = 0, len = expr.expressions.length; i < len; i += 1) {
michael@0 17124 result += generateExpression(expr.expressions[i], {
michael@0 17125 precedence: Precedence.Assignment,
michael@0 17126 allowIn: allowIn,
michael@0 17127 allowCall: true
michael@0 17128 });
michael@0 17129 if (i + 1 < len) {
michael@0 17130 result += ',' + space;
michael@0 17131 }
michael@0 17132 }
michael@0 17133 result = parenthesize(result, Precedence.Sequence, precedence);
michael@0 17134 break;
michael@0 17135 case Syntax.AssignmentExpression:
michael@0 17136 allowIn |= Precedence.Assignment < precedence;
michael@0 17137 result = parenthesize(generateExpression(expr.left, {
michael@0 17138 precedence: Precedence.Call,
michael@0 17139 allowIn: allowIn,
michael@0 17140 allowCall: true
michael@0 17141 }) + space + expr.operator + space + generateExpression(expr.right, {
michael@0 17142 precedence: Precedence.Assignment,
michael@0 17143 allowIn: allowIn,
michael@0 17144 allowCall: true
michael@0 17145 }), Precedence.Assignment, precedence);
michael@0 17146 break;
michael@0 17147 case Syntax.ConditionalExpression:
michael@0 17148 allowIn |= Precedence.Conditional < precedence;
michael@0 17149 result = parenthesize(generateExpression(expr.test, {
michael@0 17150 precedence: Precedence.LogicalOR,
michael@0 17151 allowIn: allowIn,
michael@0 17152 allowCall: true
michael@0 17153 }) + space + '?' + space + generateExpression(expr.consequent, {
michael@0 17154 precedence: Precedence.Assignment,
michael@0 17155 allowIn: allowIn,
michael@0 17156 allowCall: true
michael@0 17157 }) + space + ':' + space + generateExpression(expr.alternate, {
michael@0 17158 precedence: Precedence.Assignment,
michael@0 17159 allowIn: allowIn,
michael@0 17160 allowCall: true
michael@0 17161 }), Precedence.Conditional, precedence);
michael@0 17162 break;
michael@0 17163 case Syntax.LogicalExpression:
michael@0 17164 case Syntax.BinaryExpression:
michael@0 17165 currentPrecedence = BinaryPrecedence[expr.operator];
michael@0 17166 allowIn |= currentPrecedence < precedence;
michael@0 17167 result = join(generateExpression(expr.left, {
michael@0 17168 precedence: currentPrecedence,
michael@0 17169 allowIn: allowIn,
michael@0 17170 allowCall: true
michael@0 17171 }), expr.operator);
michael@0 17172 fragment = generateExpression(expr.right, {
michael@0 17173 precedence: currentPrecedence + 1,
michael@0 17174 allowIn: allowIn,
michael@0 17175 allowCall: true
michael@0 17176 });
michael@0 17177 if (expr.operator === '/' && result.charAt(result.length - 1) === '/') {
michael@0 17178 result += ' ' + fragment;
michael@0 17179 } else {
michael@0 17180 result = join(result, fragment);
michael@0 17181 }
michael@0 17182 if (expr.operator === 'in' && !allowIn) {
michael@0 17183 result = '(' + result + ')';
michael@0 17184 } else {
michael@0 17185 result = parenthesize(result, currentPrecedence, precedence);
michael@0 17186 }
michael@0 17187 break;
michael@0 17188 case Syntax.CallExpression:
michael@0 17189 result = generateExpression(expr.callee, {
michael@0 17190 precedence: Precedence.Call,
michael@0 17191 allowIn: true,
michael@0 17192 allowCall: true,
michael@0 17193 allowUnparenthesizedNew: false
michael@0 17194 });
michael@0 17195 result += '(';
michael@0 17196 for (i = 0, len = expr['arguments'].length; i < len; i += 1) {
michael@0 17197 result += generateExpression(expr['arguments'][i], {
michael@0 17198 precedence: Precedence.Assignment,
michael@0 17199 allowIn: true,
michael@0 17200 allowCall: true
michael@0 17201 });
michael@0 17202 if (i + 1 < len) {
michael@0 17203 result += ',' + space;
michael@0 17204 }
michael@0 17205 }
michael@0 17206 result += ')';
michael@0 17207 if (!allowCall) {
michael@0 17208 result = '(' + result + ')';
michael@0 17209 } else {
michael@0 17210 result = parenthesize(result, Precedence.Call, precedence);
michael@0 17211 }
michael@0 17212 break;
michael@0 17213 case Syntax.NewExpression:
michael@0 17214 len = expr['arguments'].length;
michael@0 17215 allowUnparenthesizedNew = option.allowUnparenthesizedNew === undefined || option.allowUnparenthesizedNew;
michael@0 17216 result = join('new', generateExpression(expr.callee, {
michael@0 17217 precedence: Precedence.New,
michael@0 17218 allowIn: true,
michael@0 17219 allowCall: false,
michael@0 17220 allowUnparenthesizedNew: allowUnparenthesizedNew && !parentheses && len === 0
michael@0 17221 }));
michael@0 17222 if (!allowUnparenthesizedNew || parentheses || len > 0) {
michael@0 17223 result += '(';
michael@0 17224 for (i = 0; i < len; i += 1) {
michael@0 17225 result += generateExpression(expr['arguments'][i], {
michael@0 17226 precedence: Precedence.Assignment,
michael@0 17227 allowIn: true,
michael@0 17228 allowCall: true
michael@0 17229 });
michael@0 17230 if (i + 1 < len) {
michael@0 17231 result += ',' + space;
michael@0 17232 }
michael@0 17233 }
michael@0 17234 result += ')';
michael@0 17235 }
michael@0 17236 result = parenthesize(result, Precedence.New, precedence);
michael@0 17237 break;
michael@0 17238 case Syntax.MemberExpression:
michael@0 17239 result = generateExpression(expr.object, {
michael@0 17240 precedence: Precedence.Call,
michael@0 17241 allowIn: true,
michael@0 17242 allowCall: allowCall,
michael@0 17243 allowUnparenthesizedNew: false
michael@0 17244 });
michael@0 17245 if (expr.computed) {
michael@0 17246 result += '[' + generateExpression(expr.property, {
michael@0 17247 precedence: Precedence.Sequence,
michael@0 17248 allowIn: true,
michael@0 17249 allowCall: allowCall
michael@0 17250 }) + ']';
michael@0 17251 } else {
michael@0 17252 if (expr.object.type === Syntax.Literal && typeof expr.object.value === 'number') {
michael@0 17253 if (result.indexOf('.') < 0) {
michael@0 17254 if (!/[eExX]/.test(result) && !(result.length >= 2 && result[0] === '0')) {
michael@0 17255 result += '.';
michael@0 17256 }
michael@0 17257 }
michael@0 17258 }
michael@0 17259 result += '.' + expr.property.name;
michael@0 17260 }
michael@0 17261 result = parenthesize(result, Precedence.Member, precedence);
michael@0 17262 break;
michael@0 17263 case Syntax.UnaryExpression:
michael@0 17264 fragment = generateExpression(expr.argument, {
michael@0 17265 precedence: Precedence.Unary + (expr.argument.type === Syntax.UnaryExpression && expr.operator.length < 3 && expr.argument.operator === expr.operator ? 1 : 0),
michael@0 17266 allowIn: true,
michael@0 17267 allowCall: true
michael@0 17268 });
michael@0 17269 if (space === '') {
michael@0 17270 result = join(expr.operator, fragment);
michael@0 17271 } else {
michael@0 17272 result = expr.operator;
michael@0 17273 if (result.length > 2) {
michael@0 17274 result += ' ';
michael@0 17275 }
michael@0 17276 result += fragment;
michael@0 17277 }
michael@0 17278 result = parenthesize(result, Precedence.Unary, precedence);
michael@0 17279 break;
michael@0 17280 case Syntax.UpdateExpression:
michael@0 17281 if (expr.prefix) {
michael@0 17282 result = parenthesize(expr.operator + generateExpression(expr.argument, {
michael@0 17283 precedence: Precedence.Unary,
michael@0 17284 allowIn: true,
michael@0 17285 allowCall: true
michael@0 17286 }), Precedence.Unary, precedence);
michael@0 17287 } else {
michael@0 17288 result = parenthesize(generateExpression(expr.argument, {
michael@0 17289 precedence: Precedence.Postfix,
michael@0 17290 allowIn: true,
michael@0 17291 allowCall: true
michael@0 17292 }) + expr.operator, Precedence.Postfix, precedence);
michael@0 17293 }
michael@0 17294 break;
michael@0 17295 case Syntax.FunctionExpression:
michael@0 17296 result = 'function';
michael@0 17297 if (expr.id) {
michael@0 17298 result += ' ' + expr.id.name;
michael@0 17299 } else {
michael@0 17300 result += space;
michael@0 17301 }
michael@0 17302 result += generateFunctionBody(expr);
michael@0 17303 break;
michael@0 17304 case Syntax.ArrayExpression:
michael@0 17305 if (!expr.elements.length) {
michael@0 17306 result = '[]';
michael@0 17307 break;
michael@0 17308 }
michael@0 17309 result = '[' + newline;
michael@0 17310 previousBase = base;
michael@0 17311 base += indent;
michael@0 17312 for (i = 0, len = expr.elements.length; i < len; i += 1) {
michael@0 17313 if (!expr.elements[i]) {
michael@0 17314 result += addIndent('');
michael@0 17315 if (i + 1 === len) {
michael@0 17316 result += ',';
michael@0 17317 }
michael@0 17318 } else {
michael@0 17319 result += addIndent(generateExpression(expr.elements[i], {
michael@0 17320 precedence: Precedence.Assignment,
michael@0 17321 allowIn: true,
michael@0 17322 allowCall: true
michael@0 17323 }));
michael@0 17324 }
michael@0 17325 if (i + 1 < len) {
michael@0 17326 result += ',' + newline;
michael@0 17327 }
michael@0 17328 }
michael@0 17329 base = previousBase;
michael@0 17330 if (!endsWithLineTerminator(result)) {
michael@0 17331 result += newline;
michael@0 17332 }
michael@0 17333 result += addIndent(']');
michael@0 17334 break;
michael@0 17335 case Syntax.Property:
michael@0 17336 if (expr.kind === 'get' || expr.kind === 'set') {
michael@0 17337 result = expr.kind + ' ' + generateExpression(expr.key, {
michael@0 17338 precedence: Precedence.Sequence,
michael@0 17339 allowIn: true,
michael@0 17340 allowCall: true
michael@0 17341 }) + generateFunctionBody(expr.value);
michael@0 17342 } else {
michael@0 17343 result = generateExpression(expr.key, {
michael@0 17344 precedence: Precedence.Sequence,
michael@0 17345 allowIn: true,
michael@0 17346 allowCall: true
michael@0 17347 }) + ':' + space + generateExpression(expr.value, {
michael@0 17348 precedence: Precedence.Assignment,
michael@0 17349 allowIn: true,
michael@0 17350 allowCall: true
michael@0 17351 });
michael@0 17352 }
michael@0 17353 break;
michael@0 17354 case Syntax.ObjectExpression:
michael@0 17355 if (!expr.properties.length) {
michael@0 17356 result = '{}';
michael@0 17357 break;
michael@0 17358 }
michael@0 17359 result = '{' + newline;
michael@0 17360 previousBase = base;
michael@0 17361 base += indent;
michael@0 17362 for (i = 0, len = expr.properties.length; i < len; i += 1) {
michael@0 17363 result += addIndent(generateExpression(expr.properties[i], {
michael@0 17364 precedence: Precedence.Sequence,
michael@0 17365 allowIn: true,
michael@0 17366 allowCall: true
michael@0 17367 }));
michael@0 17368 if (i + 1 < len) {
michael@0 17369 result += ',' + newline;
michael@0 17370 }
michael@0 17371 }
michael@0 17372 base = previousBase;
michael@0 17373 if (!endsWithLineTerminator(result)) {
michael@0 17374 result += newline;
michael@0 17375 }
michael@0 17376 result += addIndent('}');
michael@0 17377 break;
michael@0 17378 case Syntax.ThisExpression:
michael@0 17379 result = 'this';
michael@0 17380 break;
michael@0 17381 case Syntax.Identifier:
michael@0 17382 result = expr.name;
michael@0 17383 break;
michael@0 17384 case Syntax.Literal:
michael@0 17385 if (expr.hasOwnProperty('raw') && parse) {
michael@0 17386 try {
michael@0 17387 raw = parse(expr.raw).body[0].expression;
michael@0 17388 if (raw.type === Syntax.Literal) {
michael@0 17389 if (raw.value === expr.value) {
michael@0 17390 result = expr.raw;
michael@0 17391 break;
michael@0 17392 }
michael@0 17393 }
michael@0 17394 } catch (e) {
michael@0 17395 }
michael@0 17396 }
michael@0 17397 if (expr.value === null) {
michael@0 17398 result = 'null';
michael@0 17399 break;
michael@0 17400 }
michael@0 17401 if (typeof expr.value === 'string') {
michael@0 17402 result = escapeString(expr.value);
michael@0 17403 break;
michael@0 17404 }
michael@0 17405 if (typeof expr.value === 'number') {
michael@0 17406 result = generateNumber(expr.value);
michael@0 17407 break;
michael@0 17408 }
michael@0 17409 result = expr.value.toString();
michael@0 17410 break;
michael@0 17411 default:
michael@0 17412 break;
michael@0 17413 }
michael@0 17414 if (result === undefined) {
michael@0 17415 throw new Error('Unknown expression type: ' + expr.type);
michael@0 17416 }
michael@0 17417 return result;
michael@0 17418 }
michael@0 17419 function generateStatement(stmt, option) {
michael@0 17420 var i, len, result, previousBase, node, allowIn, fragment, semicolon;
michael@0 17421 allowIn = true;
michael@0 17422 semicolon = ';';
michael@0 17423 if (option) {
michael@0 17424 allowIn = option.allowIn === undefined || option.allowIn;
michael@0 17425 if (!semicolons && option.semicolonOptional === true) {
michael@0 17426 semicolon = '';
michael@0 17427 }
michael@0 17428 }
michael@0 17429 switch (stmt.type) {
michael@0 17430 case Syntax.BlockStatement:
michael@0 17431 result = '{' + newline;
michael@0 17432 previousBase = base;
michael@0 17433 base += indent;
michael@0 17434 for (i = 0, len = stmt.body.length; i < len; i += 1) {
michael@0 17435 fragment = addIndent(generateStatement(stmt.body[i], {
michael@0 17436 semicolonOptional: i === len - 1
michael@0 17437 }));
michael@0 17438 result += fragment;
michael@0 17439 if (!endsWithLineTerminator(fragment)) {
michael@0 17440 result += newline;
michael@0 17441 }
michael@0 17442 }
michael@0 17443 base = previousBase;
michael@0 17444 result += addIndent('}');
michael@0 17445 break;
michael@0 17446 case Syntax.BreakStatement:
michael@0 17447 if (stmt.label) {
michael@0 17448 result = 'break ' + stmt.label.name + semicolon;
michael@0 17449 } else {
michael@0 17450 result = 'break' + semicolon;
michael@0 17451 }
michael@0 17452 break;
michael@0 17453 case Syntax.ContinueStatement:
michael@0 17454 if (stmt.label) {
michael@0 17455 result = 'continue ' + stmt.label.name + semicolon;
michael@0 17456 } else {
michael@0 17457 result = 'continue' + semicolon;
michael@0 17458 }
michael@0 17459 break;
michael@0 17460 case Syntax.DoWhileStatement:
michael@0 17461 result = join('do', maybeBlock(stmt.body));
michael@0 17462 result += maybeBlockSuffix(stmt.body, result);
michael@0 17463 result += 'while' + space + '(' + generateExpression(stmt.test, {
michael@0 17464 precedence: Precedence.Sequence,
michael@0 17465 allowIn: true,
michael@0 17466 allowCall: true
michael@0 17467 }) + ')' + semicolon;
michael@0 17468 break;
michael@0 17469 case Syntax.CatchClause:
michael@0 17470 previousBase = base;
michael@0 17471 base += indent;
michael@0 17472 result = 'catch' + space + '(' + generateExpression(stmt.param, {
michael@0 17473 precedence: Precedence.Sequence,
michael@0 17474 allowIn: true,
michael@0 17475 allowCall: true
michael@0 17476 }) + ')';
michael@0 17477 base = previousBase;
michael@0 17478 result += maybeBlock(stmt.body);
michael@0 17479 break;
michael@0 17480 case Syntax.DebuggerStatement:
michael@0 17481 result = 'debugger' + semicolon;
michael@0 17482 break;
michael@0 17483 case Syntax.EmptyStatement:
michael@0 17484 result = ';';
michael@0 17485 break;
michael@0 17486 case Syntax.ExpressionStatement:
michael@0 17487 result = generateExpression(stmt.expression, {
michael@0 17488 precedence: Precedence.Sequence,
michael@0 17489 allowIn: true,
michael@0 17490 allowCall: true
michael@0 17491 });
michael@0 17492 if (result.charAt(0) === '{' || result.slice(0, 8) === 'function' && ' ('.indexOf(result.charAt(8)) >= 0) {
michael@0 17493 result = '(' + result + ')' + semicolon;
michael@0 17494 } else {
michael@0 17495 result += semicolon;
michael@0 17496 }
michael@0 17497 break;
michael@0 17498 case Syntax.VariableDeclarator:
michael@0 17499 if (stmt.init) {
michael@0 17500 result = stmt.id.name + space + '=' + space + generateExpression(stmt.init, {
michael@0 17501 precedence: Precedence.Assignment,
michael@0 17502 allowIn: allowIn,
michael@0 17503 allowCall: true
michael@0 17504 });
michael@0 17505 } else {
michael@0 17506 result = stmt.id.name;
michael@0 17507 }
michael@0 17508 break;
michael@0 17509 case Syntax.VariableDeclaration:
michael@0 17510 result = stmt.kind;
michael@0 17511 if (stmt.declarations.length === 1 && stmt.declarations[0].init && stmt.declarations[0].init.type === Syntax.FunctionExpression) {
michael@0 17512 result += ' ' + generateStatement(stmt.declarations[0], {
michael@0 17513 allowIn: allowIn
michael@0 17514 });
michael@0 17515 } else {
michael@0 17516 previousBase = base;
michael@0 17517 base += indent;
michael@0 17518 node = stmt.declarations[0];
michael@0 17519 if (extra.comment && node.leadingComments) {
michael@0 17520 result += '\n' + addIndent(generateStatement(node, {
michael@0 17521 allowIn: allowIn
michael@0 17522 }));
michael@0 17523 } else {
michael@0 17524 result += ' ' + generateStatement(node, {
michael@0 17525 allowIn: allowIn
michael@0 17526 });
michael@0 17527 }
michael@0 17528 for (i = 1, len = stmt.declarations.length; i < len; i += 1) {
michael@0 17529 node = stmt.declarations[i];
michael@0 17530 if (extra.comment && node.leadingComments) {
michael@0 17531 result += ',' + newline + addIndent(generateStatement(node, {
michael@0 17532 allowIn: allowIn
michael@0 17533 }));
michael@0 17534 } else {
michael@0 17535 result += ',' + space + generateStatement(node, {
michael@0 17536 allowIn: allowIn
michael@0 17537 });
michael@0 17538 }
michael@0 17539 }
michael@0 17540 base = previousBase;
michael@0 17541 }
michael@0 17542 result += semicolon;
michael@0 17543 break;
michael@0 17544 case Syntax.ThrowStatement:
michael@0 17545 result = join('throw', generateExpression(stmt.argument, {
michael@0 17546 precedence: Precedence.Sequence,
michael@0 17547 allowIn: true,
michael@0 17548 allowCall: true
michael@0 17549 })) + semicolon;
michael@0 17550 break;
michael@0 17551 case Syntax.TryStatement:
michael@0 17552 result = 'try' + maybeBlock(stmt.block);
michael@0 17553 result += maybeBlockSuffix(stmt.block, result);
michael@0 17554 for (i = 0, len = stmt.handlers.length; i < len; i += 1) {
michael@0 17555 result += generateStatement(stmt.handlers[i]);
michael@0 17556 if (stmt.finalizer || i + 1 !== len) {
michael@0 17557 result += maybeBlockSuffix(stmt.handlers[i].body, result);
michael@0 17558 }
michael@0 17559 }
michael@0 17560 if (stmt.finalizer) {
michael@0 17561 result += 'finally' + maybeBlock(stmt.finalizer);
michael@0 17562 }
michael@0 17563 break;
michael@0 17564 case Syntax.SwitchStatement:
michael@0 17565 previousBase = base;
michael@0 17566 base += indent;
michael@0 17567 result = 'switch' + space + '(' + generateExpression(stmt.discriminant, {
michael@0 17568 precedence: Precedence.Sequence,
michael@0 17569 allowIn: true,
michael@0 17570 allowCall: true
michael@0 17571 }) + ')' + space + '{' + newline;
michael@0 17572 base = previousBase;
michael@0 17573 if (stmt.cases) {
michael@0 17574 for (i = 0, len = stmt.cases.length; i < len; i += 1) {
michael@0 17575 fragment = addIndent(generateStatement(stmt.cases[i], {
michael@0 17576 semicolonOptional: i === len - 1
michael@0 17577 }));
michael@0 17578 result += fragment;
michael@0 17579 if (!endsWithLineTerminator(fragment)) {
michael@0 17580 result += newline;
michael@0 17581 }
michael@0 17582 }
michael@0 17583 }
michael@0 17584 result += addIndent('}');
michael@0 17585 break;
michael@0 17586 case Syntax.SwitchCase:
michael@0 17587 previousBase = base;
michael@0 17588 base += indent;
michael@0 17589 if (stmt.test) {
michael@0 17590 result = join('case', generateExpression(stmt.test, {
michael@0 17591 precedence: Precedence.Sequence,
michael@0 17592 allowIn: true,
michael@0 17593 allowCall: true
michael@0 17594 })) + ':';
michael@0 17595 } else {
michael@0 17596 result = 'default:';
michael@0 17597 }
michael@0 17598 i = 0;
michael@0 17599 len = stmt.consequent.length;
michael@0 17600 if (len && stmt.consequent[0].type === Syntax.BlockStatement) {
michael@0 17601 fragment = maybeBlock(stmt.consequent[0]);
michael@0 17602 result += fragment;
michael@0 17603 i = 1;
michael@0 17604 }
michael@0 17605 if (i !== len && !endsWithLineTerminator(result)) {
michael@0 17606 result += newline;
michael@0 17607 }
michael@0 17608 for (; i < len; i += 1) {
michael@0 17609 fragment = addIndent(generateStatement(stmt.consequent[i], {
michael@0 17610 semicolonOptional: i === len - 1 && semicolon === ''
michael@0 17611 }));
michael@0 17612 result += fragment;
michael@0 17613 if (i + 1 !== len && !endsWithLineTerminator(fragment)) {
michael@0 17614 result += newline;
michael@0 17615 }
michael@0 17616 }
michael@0 17617 base = previousBase;
michael@0 17618 break;
michael@0 17619 case Syntax.IfStatement:
michael@0 17620 previousBase = base;
michael@0 17621 base += indent;
michael@0 17622 if (stmt.alternate) {
michael@0 17623 if (stmt.alternate.type === Syntax.IfStatement) {
michael@0 17624 result = 'if' + space + '(' + generateExpression(stmt.test, {
michael@0 17625 precedence: Precedence.Sequence,
michael@0 17626 allowIn: true,
michael@0 17627 allowCall: true
michael@0 17628 }) + ')';
michael@0 17629 base = previousBase;
michael@0 17630 result += maybeBlock(stmt.consequent);
michael@0 17631 result += maybeBlockSuffix(stmt.consequent, result);
michael@0 17632 result += 'else ' + generateStatement(stmt.alternate);
michael@0 17633 } else {
michael@0 17634 result = 'if' + space + '(' + generateExpression(stmt.test, {
michael@0 17635 precedence: Precedence.Sequence,
michael@0 17636 allowIn: true,
michael@0 17637 allowCall: true
michael@0 17638 }) + ')';
michael@0 17639 base = previousBase;
michael@0 17640 result += maybeBlock(stmt.consequent);
michael@0 17641 result += maybeBlockSuffix(stmt.consequent, result);
michael@0 17642 result += 'else';
michael@0 17643 result = join(result, maybeBlock(stmt.alternate, semicolon === ''));
michael@0 17644 }
michael@0 17645 } else {
michael@0 17646 result = 'if' + space + '(' + generateExpression(stmt.test, {
michael@0 17647 precedence: Precedence.Sequence,
michael@0 17648 allowIn: true,
michael@0 17649 allowCall: true
michael@0 17650 }) + ')';
michael@0 17651 base = previousBase;
michael@0 17652 result += maybeBlock(stmt.consequent, semicolon === '');
michael@0 17653 }
michael@0 17654 break;
michael@0 17655 case Syntax.ForStatement:
michael@0 17656 previousBase = base;
michael@0 17657 base += indent;
michael@0 17658 result = 'for' + space + '(';
michael@0 17659 if (stmt.init) {
michael@0 17660 if (stmt.init.type === Syntax.VariableDeclaration) {
michael@0 17661 result += generateStatement(stmt.init, {
michael@0 17662 allowIn: false
michael@0 17663 });
michael@0 17664 } else {
michael@0 17665 result += generateExpression(stmt.init, {
michael@0 17666 precedence: Precedence.Sequence,
michael@0 17667 allowIn: false,
michael@0 17668 allowCall: true
michael@0 17669 }) + ';';
michael@0 17670 }
michael@0 17671 } else {
michael@0 17672 result += ';';
michael@0 17673 }
michael@0 17674 if (stmt.test) {
michael@0 17675 result += space + generateExpression(stmt.test, {
michael@0 17676 precedence: Precedence.Sequence,
michael@0 17677 allowIn: true,
michael@0 17678 allowCall: true
michael@0 17679 }) + ';';
michael@0 17680 } else {
michael@0 17681 result += ';';
michael@0 17682 }
michael@0 17683 if (stmt.update) {
michael@0 17684 result += space + generateExpression(stmt.update, {
michael@0 17685 precedence: Precedence.Sequence,
michael@0 17686 allowIn: true,
michael@0 17687 allowCall: true
michael@0 17688 }) + ')';
michael@0 17689 } else {
michael@0 17690 result += ')';
michael@0 17691 }
michael@0 17692 base = previousBase;
michael@0 17693 result += maybeBlock(stmt.body, semicolon === '');
michael@0 17694 break;
michael@0 17695 case Syntax.ForInStatement:
michael@0 17696 result = 'for' + space + '(';
michael@0 17697 if (stmt.left.type === Syntax.VariableDeclaration) {
michael@0 17698 previousBase = base;
michael@0 17699 base += indent + indent;
michael@0 17700 result += stmt.left.kind + ' ' + generateStatement(stmt.left.declarations[0], {
michael@0 17701 allowIn: false
michael@0 17702 });
michael@0 17703 base = previousBase;
michael@0 17704 } else {
michael@0 17705 previousBase = base;
michael@0 17706 base += indent;
michael@0 17707 result += generateExpression(stmt.left, {
michael@0 17708 precedence: Precedence.Call,
michael@0 17709 allowIn: true,
michael@0 17710 allowCall: true
michael@0 17711 });
michael@0 17712 base = previousBase;
michael@0 17713 }
michael@0 17714 previousBase = base;
michael@0 17715 base += indent;
michael@0 17716 result = join(result, 'in');
michael@0 17717 result = join(result, generateExpression(stmt.right, {
michael@0 17718 precedence: Precedence.Sequence,
michael@0 17719 allowIn: true,
michael@0 17720 allowCall: true
michael@0 17721 })) + ')';
michael@0 17722 base = previousBase;
michael@0 17723 result += maybeBlock(stmt.body, semicolon === '');
michael@0 17724 break;
michael@0 17725 case Syntax.LabeledStatement:
michael@0 17726 result = stmt.label.name + ':' + maybeBlock(stmt.body, semicolon === '');
michael@0 17727 break;
michael@0 17728 case Syntax.Program:
michael@0 17729 result = '';
michael@0 17730 for (i = 0, len = stmt.body.length; i < len; i += 1) {
michael@0 17731 fragment = addIndent(generateStatement(stmt.body[i], {
michael@0 17732 semicolonOptional: i === len - 1
michael@0 17733 }));
michael@0 17734 result += fragment;
michael@0 17735 if (i + 1 < len && !endsWithLineTerminator(fragment)) {
michael@0 17736 result += newline;
michael@0 17737 }
michael@0 17738 }
michael@0 17739 break;
michael@0 17740 case Syntax.FunctionDeclaration:
michael@0 17741 result = 'function' + space;
michael@0 17742 if (stmt.id) {
michael@0 17743 result += (space === '' ? ' ' : '') + stmt.id.name;
michael@0 17744 }
michael@0 17745 result += generateFunctionBody(stmt);
michael@0 17746 break;
michael@0 17747 case Syntax.ReturnStatement:
michael@0 17748 if (stmt.argument) {
michael@0 17749 result = join('return', generateExpression(stmt.argument, {
michael@0 17750 precedence: Precedence.Sequence,
michael@0 17751 allowIn: true,
michael@0 17752 allowCall: true
michael@0 17753 })) + semicolon;
michael@0 17754 } else {
michael@0 17755 result = 'return' + semicolon;
michael@0 17756 }
michael@0 17757 break;
michael@0 17758 case Syntax.WhileStatement:
michael@0 17759 previousBase = base;
michael@0 17760 base += indent;
michael@0 17761 result = 'while' + space + '(' + generateExpression(stmt.test, {
michael@0 17762 precedence: Precedence.Sequence,
michael@0 17763 allowIn: true,
michael@0 17764 allowCall: true
michael@0 17765 }) + ')';
michael@0 17766 base = previousBase;
michael@0 17767 result += maybeBlock(stmt.body, semicolon === '');
michael@0 17768 break;
michael@0 17769 case Syntax.WithStatement:
michael@0 17770 previousBase = base;
michael@0 17771 base += indent;
michael@0 17772 result = 'with' + space + '(' + generateExpression(stmt.object, {
michael@0 17773 precedence: Precedence.Sequence,
michael@0 17774 allowIn: true,
michael@0 17775 allowCall: true
michael@0 17776 }) + ')';
michael@0 17777 base = previousBase;
michael@0 17778 result += maybeBlock(stmt.body, semicolon === '');
michael@0 17779 break;
michael@0 17780 default:
michael@0 17781 break;
michael@0 17782 }
michael@0 17783 if (result === undefined) {
michael@0 17784 throw new Error('Unknown statement type: ' + stmt.type);
michael@0 17785 }
michael@0 17786 if (extra.comment) {
michael@0 17787 return addCommentsToStatement(stmt, result);
michael@0 17788 }
michael@0 17789 return result;
michael@0 17790 }
michael@0 17791 function generate(node, options) {
michael@0 17792 var defaultOptions = getDefaultOptions();
michael@0 17793 if (typeof options !== 'undefined') {
michael@0 17794 if (typeof options.indent === 'string') {
michael@0 17795 defaultOptions.format.indent.style = options.indent;
michael@0 17796 }
michael@0 17797 if (typeof options.base === 'number') {
michael@0 17798 defaultOptions.format.indent.base = options.base;
michael@0 17799 }
michael@0 17800 options = updateDeeply(defaultOptions, options);
michael@0 17801 indent = options.format.indent.style;
michael@0 17802 if (typeof options.base === 'string') {
michael@0 17803 base = options.base;
michael@0 17804 } else {
michael@0 17805 base = stringRepeat(indent, options.format.indent.base);
michael@0 17806 }
michael@0 17807 } else {
michael@0 17808 options = defaultOptions;
michael@0 17809 indent = options.format.indent.style;
michael@0 17810 base = stringRepeat(indent, options.format.indent.base);
michael@0 17811 }
michael@0 17812 json = options.format.json;
michael@0 17813 renumber = options.format.renumber;
michael@0 17814 hexadecimal = json ? false : options.format.hexadecimal;
michael@0 17815 quotes = json ? 'double' : options.format.quotes;
michael@0 17816 escapeless = options.format.escapeless;
michael@0 17817 if (options.format.compact) {
michael@0 17818 newline = space = indent = base = '';
michael@0 17819 } else {
michael@0 17820 newline = '\n';
michael@0 17821 space = ' ';
michael@0 17822 }
michael@0 17823 parentheses = options.format.parentheses;
michael@0 17824 semicolons = options.format.semicolons;
michael@0 17825 parse = json ? null : options.parse;
michael@0 17826 extra = options;
michael@0 17827 switch (node.type) {
michael@0 17828 case Syntax.BlockStatement:
michael@0 17829 case Syntax.BreakStatement:
michael@0 17830 case Syntax.CatchClause:
michael@0 17831 case Syntax.ContinueStatement:
michael@0 17832 case Syntax.DoWhileStatement:
michael@0 17833 case Syntax.DebuggerStatement:
michael@0 17834 case Syntax.EmptyStatement:
michael@0 17835 case Syntax.ExpressionStatement:
michael@0 17836 case Syntax.ForStatement:
michael@0 17837 case Syntax.ForInStatement:
michael@0 17838 case Syntax.FunctionDeclaration:
michael@0 17839 case Syntax.IfStatement:
michael@0 17840 case Syntax.LabeledStatement:
michael@0 17841 case Syntax.Program:
michael@0 17842 case Syntax.ReturnStatement:
michael@0 17843 case Syntax.SwitchStatement:
michael@0 17844 case Syntax.SwitchCase:
michael@0 17845 case Syntax.ThrowStatement:
michael@0 17846 case Syntax.TryStatement:
michael@0 17847 case Syntax.VariableDeclaration:
michael@0 17848 case Syntax.VariableDeclarator:
michael@0 17849 case Syntax.WhileStatement:
michael@0 17850 case Syntax.WithStatement:
michael@0 17851 return generateStatement(node);
michael@0 17852 case Syntax.AssignmentExpression:
michael@0 17853 case Syntax.ArrayExpression:
michael@0 17854 case Syntax.BinaryExpression:
michael@0 17855 case Syntax.CallExpression:
michael@0 17856 case Syntax.ConditionalExpression:
michael@0 17857 case Syntax.FunctionExpression:
michael@0 17858 case Syntax.Identifier:
michael@0 17859 case Syntax.Literal:
michael@0 17860 case Syntax.LogicalExpression:
michael@0 17861 case Syntax.MemberExpression:
michael@0 17862 case Syntax.NewExpression:
michael@0 17863 case Syntax.ObjectExpression:
michael@0 17864 case Syntax.Property:
michael@0 17865 case Syntax.SequenceExpression:
michael@0 17866 case Syntax.ThisExpression:
michael@0 17867 case Syntax.UnaryExpression:
michael@0 17868 case Syntax.UpdateExpression:
michael@0 17869 return generateExpression(node, {
michael@0 17870 precedence: Precedence.Sequence,
michael@0 17871 allowIn: true,
michael@0 17872 allowCall: true
michael@0 17873 });
michael@0 17874 default:
michael@0 17875 break;
michael@0 17876 }
michael@0 17877 throw new Error('Unknown node type: ' + node.type);
michael@0 17878 }
michael@0 17879 VisitorKeys = {
michael@0 17880 AssignmentExpression: [
michael@0 17881 'left',
michael@0 17882 'right'
michael@0 17883 ],
michael@0 17884 ArrayExpression: [
michael@0 17885 'elements'
michael@0 17886 ],
michael@0 17887 BlockStatement: [
michael@0 17888 'body'
michael@0 17889 ],
michael@0 17890 BinaryExpression: [
michael@0 17891 'left',
michael@0 17892 'right'
michael@0 17893 ],
michael@0 17894 BreakStatement: [
michael@0 17895 'label'
michael@0 17896 ],
michael@0 17897 CallExpression: [
michael@0 17898 'callee',
michael@0 17899 'arguments'
michael@0 17900 ],
michael@0 17901 CatchClause: [
michael@0 17902 'param',
michael@0 17903 'body'
michael@0 17904 ],
michael@0 17905 ConditionalExpression: [
michael@0 17906 'test',
michael@0 17907 'consequent',
michael@0 17908 'alternate'
michael@0 17909 ],
michael@0 17910 ContinueStatement: [
michael@0 17911 'label'
michael@0 17912 ],
michael@0 17913 DoWhileStatement: [
michael@0 17914 'body',
michael@0 17915 'test'
michael@0 17916 ],
michael@0 17917 DebuggerStatement: [],
michael@0 17918 EmptyStatement: [],
michael@0 17919 ExpressionStatement: [
michael@0 17920 'expression'
michael@0 17921 ],
michael@0 17922 ForStatement: [
michael@0 17923 'init',
michael@0 17924 'test',
michael@0 17925 'update',
michael@0 17926 'body'
michael@0 17927 ],
michael@0 17928 ForInStatement: [
michael@0 17929 'left',
michael@0 17930 'right',
michael@0 17931 'body'
michael@0 17932 ],
michael@0 17933 FunctionDeclaration: [
michael@0 17934 'id',
michael@0 17935 'params',
michael@0 17936 'body'
michael@0 17937 ],
michael@0 17938 FunctionExpression: [
michael@0 17939 'id',
michael@0 17940 'params',
michael@0 17941 'body'
michael@0 17942 ],
michael@0 17943 Identifier: [],
michael@0 17944 IfStatement: [
michael@0 17945 'test',
michael@0 17946 'consequent',
michael@0 17947 'alternate'
michael@0 17948 ],
michael@0 17949 Literal: [],
michael@0 17950 LabeledStatement: [
michael@0 17951 'label',
michael@0 17952 'body'
michael@0 17953 ],
michael@0 17954 LogicalExpression: [
michael@0 17955 'left',
michael@0 17956 'right'
michael@0 17957 ],
michael@0 17958 MemberExpression: [
michael@0 17959 'object',
michael@0 17960 'property'
michael@0 17961 ],
michael@0 17962 NewExpression: [
michael@0 17963 'callee',
michael@0 17964 'arguments'
michael@0 17965 ],
michael@0 17966 ObjectExpression: [
michael@0 17967 'properties'
michael@0 17968 ],
michael@0 17969 Program: [
michael@0 17970 'body'
michael@0 17971 ],
michael@0 17972 Property: [
michael@0 17973 'key',
michael@0 17974 'value'
michael@0 17975 ],
michael@0 17976 ReturnStatement: [
michael@0 17977 'argument'
michael@0 17978 ],
michael@0 17979 SequenceExpression: [
michael@0 17980 'expressions'
michael@0 17981 ],
michael@0 17982 SwitchStatement: [
michael@0 17983 'descriminant',
michael@0 17984 'cases'
michael@0 17985 ],
michael@0 17986 SwitchCase: [
michael@0 17987 'test',
michael@0 17988 'consequent'
michael@0 17989 ],
michael@0 17990 ThisExpression: [],
michael@0 17991 ThrowStatement: [
michael@0 17992 'argument'
michael@0 17993 ],
michael@0 17994 TryStatement: [
michael@0 17995 'block',
michael@0 17996 'handlers',
michael@0 17997 'finalizer'
michael@0 17998 ],
michael@0 17999 UnaryExpression: [
michael@0 18000 'argument'
michael@0 18001 ],
michael@0 18002 UpdateExpression: [
michael@0 18003 'argument'
michael@0 18004 ],
michael@0 18005 VariableDeclaration: [
michael@0 18006 'declarations'
michael@0 18007 ],
michael@0 18008 VariableDeclarator: [
michael@0 18009 'id',
michael@0 18010 'init'
michael@0 18011 ],
michael@0 18012 WhileStatement: [
michael@0 18013 'test',
michael@0 18014 'body'
michael@0 18015 ],
michael@0 18016 WithStatement: [
michael@0 18017 'object',
michael@0 18018 'body'
michael@0 18019 ],
michael@0 18020 PointerType: [
michael@0 18021 'base'
michael@0 18022 ],
michael@0 18023 StructType: [
michael@0 18024 'id',
michael@0 18025 'fields'
michael@0 18026 ],
michael@0 18027 FieldDeclarator: [
michael@0 18028 'id',
michael@0 18029 'decltype'
michael@0 18030 ],
michael@0 18031 ArrowType: [
michael@0 18032 'params',
michael@0 18033 'return'
michael@0 18034 ],
michael@0 18035 TypeIdentifier: [],
michael@0 18036 TypeAliasDirective: [
michael@0 18037 'original',
michael@0 18038 'alias'
michael@0 18039 ],
michael@0 18040 CastExpression: [
michael@0 18041 'as',
michael@0 18042 'argument'
michael@0 18043 ]
michael@0 18044 };
michael@0 18045 VisitorOption = {
michael@0 18046 Break: 1,
michael@0 18047 Skip: 2
michael@0 18048 };
michael@0 18049 function traverse(top, visitor) {
michael@0 18050 var worklist, leavelist, node, ret, current, current2, candidates, candidate;
michael@0 18051 worklist = [
michael@0 18052 top
michael@0 18053 ];
michael@0 18054 leavelist = [];
michael@0 18055 while (worklist.length) {
michael@0 18056 node = worklist.pop();
michael@0 18057 if (node) {
michael@0 18058 if (visitor.enter) {
michael@0 18059 ret = visitor.enter(node);
michael@0 18060 } else {
michael@0 18061 ret = undefined;
michael@0 18062 }
michael@0 18063 if (ret === VisitorOption.Break) {
michael@0 18064 return;
michael@0 18065 }
michael@0 18066 worklist.push(null);
michael@0 18067 leavelist.push(node);
michael@0 18068 if (ret !== VisitorOption.Skip) {
michael@0 18069 candidates = VisitorKeys[node.type];
michael@0 18070 current = candidates.length;
michael@0 18071 while ((current -= 1) >= 0) {
michael@0 18072 candidate = node[candidates[current]];
michael@0 18073 if (candidate) {
michael@0 18074 if (isArray(candidate)) {
michael@0 18075 current2 = candidate.length;
michael@0 18076 while ((current2 -= 1) >= 0) {
michael@0 18077 if (candidate[current2]) {
michael@0 18078 worklist.push(candidate[current2]);
michael@0 18079 }
michael@0 18080 }
michael@0 18081 } else {
michael@0 18082 worklist.push(candidate);
michael@0 18083 }
michael@0 18084 }
michael@0 18085 }
michael@0 18086 }
michael@0 18087 } else {
michael@0 18088 node = leavelist.pop();
michael@0 18089 if (visitor.leave) {
michael@0 18090 ret = visitor.leave(node);
michael@0 18091 } else {
michael@0 18092 ret = undefined;
michael@0 18093 }
michael@0 18094 if (ret === VisitorOption.Break) {
michael@0 18095 return;
michael@0 18096 }
michael@0 18097 }
michael@0 18098 }
michael@0 18099 }
michael@0 18100 function upperBound(array, func) {
michael@0 18101 var diff, len, i, current;
michael@0 18102 len = array.length;
michael@0 18103 i = 0;
michael@0 18104 while (len) {
michael@0 18105 diff = len >>> 1;
michael@0 18106 current = i + diff;
michael@0 18107 if (func(array[current])) {
michael@0 18108 len = diff;
michael@0 18109 } else {
michael@0 18110 i = current + 1;
michael@0 18111 len -= diff + 1;
michael@0 18112 }
michael@0 18113 }
michael@0 18114 return i;
michael@0 18115 }
michael@0 18116 function lowerBound(array, func) {
michael@0 18117 var diff, len, i, current;
michael@0 18118 len = array.length;
michael@0 18119 i = 0;
michael@0 18120 while (len) {
michael@0 18121 diff = len >>> 1;
michael@0 18122 current = i + diff;
michael@0 18123 if (func(array[current])) {
michael@0 18124 i = current + 1;
michael@0 18125 len -= diff + 1;
michael@0 18126 } else {
michael@0 18127 len = diff;
michael@0 18128 }
michael@0 18129 }
michael@0 18130 return i;
michael@0 18131 }
michael@0 18132 function extendCommentRange(comment, tokens) {
michael@0 18133 var target, token;
michael@0 18134 target = upperBound(tokens, function search(token) {
michael@0 18135 return token.range[0] > comment.range[0];
michael@0 18136 });
michael@0 18137 comment.extendedRange = [
michael@0 18138 comment.range[0],
michael@0 18139 comment.range[1]
michael@0 18140 ];
michael@0 18141 if (target !== tokens.length) {
michael@0 18142 comment.extendedRange[1] = tokens[target].range[0];
michael@0 18143 }
michael@0 18144 target -= 1;
michael@0 18145 if (target >= 0) {
michael@0 18146 if (target < tokens.length) {
michael@0 18147 comment.extendedRange[0] = tokens[target].range[1];
michael@0 18148 } else if (token.length) {
michael@0 18149 comment.extendedRange[1] = tokens[tokens.length - 1].range[0];
michael@0 18150 }
michael@0 18151 }
michael@0 18152 return comment;
michael@0 18153 }
michael@0 18154 function attachComments(tree, providedComments, tokens) {
michael@0 18155 var comments = [], comment, len, i;
michael@0 18156 if (!tree.range) {
michael@0 18157 throw new Error('attachComments needs range information');
michael@0 18158 }
michael@0 18159 if (!tokens.length) {
michael@0 18160 if (providedComments.length) {
michael@0 18161 for (i = 0, len = providedComments.length; i < len; i += 1) {
michael@0 18162 comment = deepCopy(providedComments[i]);
michael@0 18163 comment.extendedRange = [
michael@0 18164 0,
michael@0 18165 tree.range[0]
michael@0 18166 ];
michael@0 18167 comments.push(comment);
michael@0 18168 }
michael@0 18169 tree.leadingComments = comments;
michael@0 18170 }
michael@0 18171 return tree;
michael@0 18172 }
michael@0 18173 for (i = 0, len = providedComments.length; i < len; i += 1) {
michael@0 18174 comments.push(extendCommentRange(deepCopy(providedComments[i]), tokens));
michael@0 18175 }
michael@0 18176 traverse(tree, {
michael@0 18177 cursor: 0,
michael@0 18178 enter: function (node) {
michael@0 18179 var comment;
michael@0 18180 while (this.cursor < comments.length) {
michael@0 18181 comment = comments[this.cursor];
michael@0 18182 if (comment.extendedRange[1] > node.range[0]) {
michael@0 18183 break;
michael@0 18184 }
michael@0 18185 if (comment.extendedRange[1] === node.range[0]) {
michael@0 18186 if (!node.leadingComments) {
michael@0 18187 node.leadingComments = [];
michael@0 18188 }
michael@0 18189 node.leadingComments.push(comment);
michael@0 18190 comments.splice(this.cursor, 1);
michael@0 18191 } else {
michael@0 18192 this.cursor += 1;
michael@0 18193 }
michael@0 18194 }
michael@0 18195 if (this.cursor === comments.length) {
michael@0 18196 return VisitorOption.Break;
michael@0 18197 }
michael@0 18198 if (comments[this.cursor].extendedRange[0] > node.range[1]) {
michael@0 18199 return VisitorOption.Skip;
michael@0 18200 }
michael@0 18201 }
michael@0 18202 });
michael@0 18203 traverse(tree, {
michael@0 18204 cursor: 0,
michael@0 18205 leave: function (node) {
michael@0 18206 var comment;
michael@0 18207 while (this.cursor < comments.length) {
michael@0 18208 comment = comments[this.cursor];
michael@0 18209 if (node.range[1] < comment.extendedRange[0]) {
michael@0 18210 break;
michael@0 18211 }
michael@0 18212 if (node.range[1] === comment.extendedRange[0]) {
michael@0 18213 if (!node.trailingComments) {
michael@0 18214 node.trailingComments = [];
michael@0 18215 }
michael@0 18216 node.trailingComments.push(comment);
michael@0 18217 comments.splice(this.cursor, 1);
michael@0 18218 } else {
michael@0 18219 this.cursor += 1;
michael@0 18220 }
michael@0 18221 }
michael@0 18222 if (this.cursor === comments.length) {
michael@0 18223 return VisitorOption.Break;
michael@0 18224 }
michael@0 18225 if (comments[this.cursor].extendedRange[0] > node.range[1]) {
michael@0 18226 return VisitorOption.Skip;
michael@0 18227 }
michael@0 18228 }
michael@0 18229 });
michael@0 18230 return tree;
michael@0 18231 }
michael@0 18232 exports.version = '0.0.6-dev';
michael@0 18233 exports.generate = generate;
michael@0 18234 exports.traverse = traverse;
michael@0 18235 exports.attachComments = attachComments;
michael@0 18236 }(typeof exports === 'undefined' ? escodegen = {} : exports));
michael@0 18237 var verifierOptions = systemOptions.register(new OptionSet('Verifier Options'));
michael@0 18238 var verifierTraceLevel = verifierOptions.register(new Option('tv', 'tv', 'number', 0, 'Verifier Trace Level'));
michael@0 18239 var Type = function () {
michael@0 18240 function type() {
michael@0 18241 unexpected('Type is Abstract');
michael@0 18242 }
michael@0 18243 type.prototype.equals = function (other) {
michael@0 18244 return this === other;
michael@0 18245 };
michael@0 18246 type.prototype.merge = function (other) {
michael@0 18247 unexpected('Merging ' + this + ' with ' + other);
michael@0 18248 };
michael@0 18249 type.cache = {
michael@0 18250 name: {},
michael@0 18251 classInfo: [],
michael@0 18252 instanceInfo: [],
michael@0 18253 scriptInfo: [],
michael@0 18254 methodInfo: []
michael@0 18255 };
michael@0 18256 type.from = function from(x, domain) {
michael@0 18257 var traitsTypeCache = null;
michael@0 18258 if (x instanceof ClassInfo) {
michael@0 18259 traitsTypeCache = type.cache.classInfo;
michael@0 18260 } else if (x instanceof InstanceInfo) {
michael@0 18261 traitsTypeCache = type.cache.instanceInfo;
michael@0 18262 } else if (x instanceof ScriptInfo) {
michael@0 18263 traitsTypeCache = type.cache.scriptInfo;
michael@0 18264 }
michael@0 18265 if (traitsTypeCache) {
michael@0 18266 return traitsTypeCache[x.runtimeId] || (traitsTypeCache[x.runtimeId] = new TraitsType(x, domain));
michael@0 18267 }
michael@0 18268 if (x instanceof ActivationInfo) {
michael@0 18269 return new TraitsType(x.methodInfo);
michael@0 18270 } else if (x instanceof Global) {
michael@0 18271 return new TraitsType(x.scriptInfo);
michael@0 18272 } else if (x instanceof Interface) {
michael@0 18273 return new TraitsType(x.classInfo, domain);
michael@0 18274 } else if (x instanceof MethodInfo) {
michael@0 18275 return new MethodType(x);
michael@0 18276 } else if (domain && x instanceof Class) {
michael@0 18277 return type.from(x.classInfo, domain);
michael@0 18278 }
michael@0 18279 return Type.Any;
michael@0 18280 };
michael@0 18281 type.fromSimpleName = function (name, domain) {
michael@0 18282 return Type.fromName(Multiname.fromSimpleName(name), domain);
michael@0 18283 };
michael@0 18284 type.fromName = function fromName(mn, domain) {
michael@0 18285 if (mn === undefined) {
michael@0 18286 return Type.Undefined;
michael@0 18287 } else {
michael@0 18288 var qn = Multiname.isQName(mn) ? Multiname.getFullQualifiedName(mn) : undefined;
michael@0 18289 if (qn) {
michael@0 18290 var ty = type.cache.name[qn];
michael@0 18291 if (ty) {
michael@0 18292 return ty;
michael@0 18293 }
michael@0 18294 }
michael@0 18295 if (qn === Multiname.getPublicQualifiedName('void')) {
michael@0 18296 return Type.Void;
michael@0 18297 }
michael@0 18298 true;
michael@0 18299 ty = domain.findClassInfo(mn);
michael@0 18300 ty = ty ? type.from(ty, domain) : Type.Any;
michael@0 18301 if (mn.hasTypeParameter()) {
michael@0 18302 ty = new ParameterizedType(ty, type.fromName(mn.typeParameter, domain));
michael@0 18303 }
michael@0 18304 return type.cache.name[qn] = ty;
michael@0 18305 }
michael@0 18306 };
michael@0 18307 type.prototype.applyType = function (parameter) {
michael@0 18308 return new ParameterizedType(this, parameter);
michael@0 18309 };
michael@0 18310 type.prototype.toString = function () {
michael@0 18311 return '[type]';
michael@0 18312 };
michael@0 18313 type.prototype.isNumeric = function () {
michael@0 18314 return this === Type.Int || this === Type.Uint || this === Type.Number;
michael@0 18315 };
michael@0 18316 type.prototype.isString = function () {
michael@0 18317 return this === Type.String;
michael@0 18318 };
michael@0 18319 type.prototype.isDirectlyReadable = function () {
michael@0 18320 return this === Type.Array;
michael@0 18321 };
michael@0 18322 type.prototype.isIndexedReadable = function () {
michael@0 18323 return this.isParameterizedType();
michael@0 18324 };
michael@0 18325 type.prototype.isDirectlyWriteable = function () {
michael@0 18326 return this === Type.Array;
michael@0 18327 };
michael@0 18328 type.prototype.isIndexedWriteable = function () {
michael@0 18329 return this.isParameterizedType();
michael@0 18330 };
michael@0 18331 type.prototype.isVector = function () {
michael@0 18332 return this.isParameterizedType();
michael@0 18333 };
michael@0 18334 type.prototype.isNotDirectlyIndexable = function () {
michael@0 18335 return this === Type.Any || this === Type.XML || this === Type.XMLList || this === Type.Dictionary;
michael@0 18336 };
michael@0 18337 type.prototype.isParameterizedType = function () {
michael@0 18338 return this instanceof ParameterizedType;
michael@0 18339 };
michael@0 18340 type.prototype.instanceType = function () {
michael@0 18341 return this;
michael@0 18342 };
michael@0 18343 type.prototype.getTrait = function () {
michael@0 18344 return null;
michael@0 18345 };
michael@0 18346 type.prototype.super = function () {
michael@0 18347 unexpected('Can\'t call super on ' + this);
michael@0 18348 };
michael@0 18349 type.prototype.isSubtypeOf = function (other) {
michael@0 18350 if (this === other || this.equals(other)) {
michael@0 18351 return true;
michael@0 18352 }
michael@0 18353 return this.merge(other) === this;
michael@0 18354 };
michael@0 18355 var typesInitialized = false;
michael@0 18356 type.initializeTypes = function (domain) {
michael@0 18357 if (typesInitialized) {
michael@0 18358 return;
michael@0 18359 }
michael@0 18360 type.Any = new AtomType('Any');
michael@0 18361 type.Null = new AtomType('Null');
michael@0 18362 type.Undefined = new AtomType('Undefined');
michael@0 18363 type.Void = new AtomType('Void');
michael@0 18364 type.Int = Type.fromSimpleName('int', domain).instanceType();
michael@0 18365 type.Uint = Type.fromSimpleName('uint', domain).instanceType();
michael@0 18366 type.Class = Type.fromSimpleName('Class', domain).instanceType();
michael@0 18367 type.Array = Type.fromSimpleName('Array', domain).instanceType();
michael@0 18368 type.Object = Type.fromSimpleName('Object', domain).instanceType();
michael@0 18369 type.String = Type.fromSimpleName('String', domain).instanceType();
michael@0 18370 type.Number = Type.fromSimpleName('Number', domain).instanceType();
michael@0 18371 type.Boolean = Type.fromSimpleName('Boolean', domain).instanceType();
michael@0 18372 type.Function = Type.fromSimpleName('Function', domain).instanceType();
michael@0 18373 type.XML = Type.fromSimpleName('XML', domain).instanceType();
michael@0 18374 type.XMLList = Type.fromSimpleName('XMLList', domain).instanceType();
michael@0 18375 type.Dictionary = Type.fromSimpleName('flash.utils.Dictionary', domain).instanceType();
michael@0 18376 typesInitialized = true;
michael@0 18377 };
michael@0 18378 return type;
michael@0 18379 }();
michael@0 18380 var AtomType = function () {
michael@0 18381 function atomType(name) {
michael@0 18382 this.name = name;
michael@0 18383 }
michael@0 18384 atomType.prototype = Object.create(Type.prototype);
michael@0 18385 atomType.prototype.toString = function () {
michael@0 18386 if (this === Type.Any) {
michael@0 18387 return '?';
michael@0 18388 } else if (this === Type.Undefined) {
michael@0 18389 return '_';
michael@0 18390 } else if (this === Type.Null) {
michael@0 18391 return 'X';
michael@0 18392 } else if (this === Type.Void) {
michael@0 18393 return 'V';
michael@0 18394 }
michael@0 18395 unexpected();
michael@0 18396 };
michael@0 18397 atomType.prototype.merge = function merge(other) {
michael@0 18398 if (other instanceof TraitsType) {
michael@0 18399 return Type.Any;
michael@0 18400 }
michael@0 18401 if (this === other) {
michael@0 18402 return this;
michael@0 18403 }
michael@0 18404 if (this === Type.Any || other === Type.Any) {
michael@0 18405 return Type.Any;
michael@0 18406 }
michael@0 18407 return Type.Any;
michael@0 18408 };
michael@0 18409 return atomType;
michael@0 18410 }();
michael@0 18411 var MethodType = function () {
michael@0 18412 function methodType(methodInfo) {
michael@0 18413 this.methodInfo = methodInfo;
michael@0 18414 }
michael@0 18415 methodType.prototype = Object.create(Type.prototype);
michael@0 18416 methodType.prototype.toString = function () {
michael@0 18417 return 'MT ' + this.methodInfo;
michael@0 18418 };
michael@0 18419 return methodType;
michael@0 18420 }();
michael@0 18421 var TraitsType = function () {
michael@0 18422 function traitsType(object, domain) {
michael@0 18423 true;
michael@0 18424 this.object = object;
michael@0 18425 this.traits = object.traits;
michael@0 18426 this.domain = domain;
michael@0 18427 if (this.object instanceof InstanceInfo) {
michael@0 18428 true;
michael@0 18429 }
michael@0 18430 }
michael@0 18431 traitsType.prototype = Object.create(Type.prototype);
michael@0 18432 function nameOf(x) {
michael@0 18433 if (x instanceof ScriptInfo) {
michael@0 18434 return 'SI';
michael@0 18435 } else if (x instanceof ClassInfo) {
michael@0 18436 return 'CI:' + x.instanceInfo.name.name;
michael@0 18437 } else if (x instanceof InstanceInfo) {
michael@0 18438 return 'II:' + x.name.name;
michael@0 18439 } else if (x instanceof MethodInfo) {
michael@0 18440 return 'MI';
michael@0 18441 } else if (x instanceof ActivationInfo) {
michael@0 18442 return 'AC';
michael@0 18443 }
michael@0 18444 true;
michael@0 18445 }
michael@0 18446 function findTraitBySlotId(traits, slotId) {
michael@0 18447 for (var i = traits.length - 1; i >= 0; i--) {
michael@0 18448 if (traits[i].slotId === slotId) {
michael@0 18449 return traits[i];
michael@0 18450 }
michael@0 18451 }
michael@0 18452 unexpected('Cannot find trait with slotId: ' + slotId + ' in ' + traits);
michael@0 18453 }
michael@0 18454 function findTraitByName(traits, mn, isSetter) {
michael@0 18455 var isGetter = !isSetter;
michael@0 18456 var trait;
michael@0 18457 if (!Multiname.isQName(mn)) {
michael@0 18458 if (mn instanceof MultinameType) {
michael@0 18459 return;
michael@0 18460 }
michael@0 18461 true;
michael@0 18462 var dy;
michael@0 18463 for (var i = 0, j = mn.namespaces.length; i < j; i++) {
michael@0 18464 var qn = mn.getQName(i);
michael@0 18465 if (mn.namespaces[i].isDynamic()) {
michael@0 18466 dy = qn;
michael@0 18467 } else {
michael@0 18468 if (trait = findTraitByName(traits, qn, isSetter)) {
michael@0 18469 return trait;
michael@0 18470 }
michael@0 18471 }
michael@0 18472 }
michael@0 18473 if (dy) {
michael@0 18474 return findTraitByName(traits, dy, isSetter);
michael@0 18475 }
michael@0 18476 } else {
michael@0 18477 var qn = Multiname.getQualifiedName(mn);
michael@0 18478 for (var i = 0, j = traits.length; i < j; i++) {
michael@0 18479 trait = traits[i];
michael@0 18480 if (Multiname.getQualifiedName(trait.name) === qn) {
michael@0 18481 if (isSetter && trait.isGetter() || isGetter && trait.isSetter()) {
michael@0 18482 continue;
michael@0 18483 }
michael@0 18484 return trait;
michael@0 18485 }
michael@0 18486 }
michael@0 18487 }
michael@0 18488 }
michael@0 18489 traitsType.prototype.getTrait = function (mn, isSetter, followSuperType) {
michael@0 18490 if (mn instanceof MultinameType) {
michael@0 18491 return null;
michael@0 18492 }
michael@0 18493 if (mn.isAttribute()) {
michael@0 18494 return null;
michael@0 18495 }
michael@0 18496 if (followSuperType && (this.isInstanceInfo() || this.isClassInfo())) {
michael@0 18497 var that = this;
michael@0 18498 do {
michael@0 18499 var trait = that.getTrait(mn, isSetter, false);
michael@0 18500 if (!trait) {
michael@0 18501 that = that.super();
michael@0 18502 }
michael@0 18503 } while (!trait && that);
michael@0 18504 return trait;
michael@0 18505 } else {
michael@0 18506 return findTraitByName(this.traits, mn, isSetter);
michael@0 18507 }
michael@0 18508 };
michael@0 18509 traitsType.prototype.getTraitAt = function (i) {
michael@0 18510 if (this.object instanceof ScriptInfo || this.object instanceof MethodInfo) {
michael@0 18511 return findTraitBySlotId(this.traits, i);
michael@0 18512 }
michael@0 18513 };
michael@0 18514 traitsType.prototype.toString = function () {
michael@0 18515 switch (this) {
michael@0 18516 case Type.Int:
michael@0 18517 return 'I';
michael@0 18518 case Type.Uint:
michael@0 18519 return 'U';
michael@0 18520 case Type.Array:
michael@0 18521 return 'A';
michael@0 18522 case Type.Object:
michael@0 18523 return 'O';
michael@0 18524 case Type.String:
michael@0 18525 return 'S';
michael@0 18526 case Type.Number:
michael@0 18527 return 'N';
michael@0 18528 case Type.Boolean:
michael@0 18529 return 'B';
michael@0 18530 case Type.Function:
michael@0 18531 return 'F';
michael@0 18532 }
michael@0 18533 return nameOf(this.object);
michael@0 18534 };
michael@0 18535 traitsType.prototype.instanceType = function () {
michael@0 18536 true;
michael@0 18537 return this.instanceCache || (this.instanceCache = Type.from(this.object.instanceInfo, this.domain));
michael@0 18538 };
michael@0 18539 traitsType.prototype.classType = function () {
michael@0 18540 true;
michael@0 18541 return this.instanceCache || (this.instanceCache = Type.from(this.object.classInfo, this.domain));
michael@0 18542 };
michael@0 18543 traitsType.prototype.super = function () {
michael@0 18544 if (this.object instanceof ClassInfo) {
michael@0 18545 return Type.Class;
michael@0 18546 }
michael@0 18547 true;
michael@0 18548 if (this.object.superName) {
michael@0 18549 var result = Type.fromName(this.object.superName, this.domain).instanceType();
michael@0 18550 true;
michael@0 18551 return result;
michael@0 18552 }
michael@0 18553 return null;
michael@0 18554 };
michael@0 18555 traitsType.prototype.isScriptInfo = function () {
michael@0 18556 return this.object instanceof ScriptInfo;
michael@0 18557 };
michael@0 18558 traitsType.prototype.isClassInfo = function () {
michael@0 18559 return this.object instanceof ClassInfo;
michael@0 18560 };
michael@0 18561 traitsType.prototype.isInstanceInfo = function () {
michael@0 18562 return this.object instanceof InstanceInfo;
michael@0 18563 };
michael@0 18564 traitsType.prototype.isInstanceOrClassInfo = function () {
michael@0 18565 return this.isInstanceInfo() || this.isClassInfo();
michael@0 18566 };
michael@0 18567 traitsType.prototype.equals = function (other) {
michael@0 18568 return this.traits === other.traits;
michael@0 18569 };
michael@0 18570 traitsType.prototype.merge = function (other) {
michael@0 18571 if (other instanceof TraitsType) {
michael@0 18572 if (this.equals(other)) {
michael@0 18573 return this;
michael@0 18574 }
michael@0 18575 if (this.isNumeric() && other.isNumeric()) {
michael@0 18576 return Type.Number;
michael@0 18577 }
michael@0 18578 if (this.isInstanceInfo() && other.isInstanceInfo()) {
michael@0 18579 var path = [];
michael@0 18580 for (var curr = this; curr; curr = curr.super()) {
michael@0 18581 path.push(curr);
michael@0 18582 }
michael@0 18583 for (var curr = other; curr; curr = curr.super()) {
michael@0 18584 for (var i = 0; i < path.length; i++) {
michael@0 18585 if (path[i].equals(curr)) {
michael@0 18586 return curr;
michael@0 18587 }
michael@0 18588 }
michael@0 18589 }
michael@0 18590 return Type.Object;
michael@0 18591 }
michael@0 18592 }
michael@0 18593 return Type.Any;
michael@0 18594 };
michael@0 18595 return traitsType;
michael@0 18596 }();
michael@0 18597 var MultinameType = function () {
michael@0 18598 function multinameType(namespaces, name, flags) {
michael@0 18599 this.namespaces = namespaces;
michael@0 18600 this.name = name;
michael@0 18601 this.flags = flags;
michael@0 18602 }
michael@0 18603 multinameType.prototype = Object.create(Type.prototype);
michael@0 18604 multinameType.prototype.toString = function () {
michael@0 18605 return 'MN';
michael@0 18606 };
michael@0 18607 return multinameType;
michael@0 18608 }();
michael@0 18609 var ParameterizedType = function () {
michael@0 18610 function parameterizedType(type, parameter) {
michael@0 18611 this.type = type;
michael@0 18612 this.parameter = parameter;
michael@0 18613 }
michael@0 18614 parameterizedType.prototype = Object.create(Type.prototype);
michael@0 18615 parameterizedType.prototype.toString = function () {
michael@0 18616 return this.type + '<' + this.parameter + '>';
michael@0 18617 };
michael@0 18618 parameterizedType.prototype.instanceType = function () {
michael@0 18619 true;
michael@0 18620 return new ParameterizedType(this.type.instanceType(), this.parameter.instanceType());
michael@0 18621 };
michael@0 18622 parameterizedType.prototype.equals = function (other) {
michael@0 18623 if (other instanceof ParameterizedType) {
michael@0 18624 return this.type.equals(other.type) && this.parameter.equals(other.parameter);
michael@0 18625 }
michael@0 18626 return false;
michael@0 18627 };
michael@0 18628 parameterizedType.prototype.merge = function (other) {
michael@0 18629 if (other instanceof TraitsType) {
michael@0 18630 if (this.equals(other)) {
michael@0 18631 return this;
michael@0 18632 }
michael@0 18633 }
michael@0 18634 return Type.Any;
michael@0 18635 };
michael@0 18636 return parameterizedType;
michael@0 18637 }();
michael@0 18638 var TypeInformation = function () {
michael@0 18639 function typeInformation() {
michael@0 18640 }
michael@0 18641 typeInformation.prototype.toString = function () {
michael@0 18642 return toKeyValueArray(this).map(function (x) {
michael@0 18643 return x[0] + ': ' + x[1];
michael@0 18644 }).join(' | ');
michael@0 18645 };
michael@0 18646 return typeInformation;
michael@0 18647 }();
michael@0 18648 var Verifier = function () {
michael@0 18649 function VerifierError(message) {
michael@0 18650 this.name = 'VerifierError';
michael@0 18651 this.message = message || '';
michael@0 18652 }
michael@0 18653 var State = function () {
michael@0 18654 var id = 0;
michael@0 18655 function state() {
michael@0 18656 this.id = id += 1;
michael@0 18657 this.stack = [];
michael@0 18658 this.scope = [];
michael@0 18659 this.local = [];
michael@0 18660 }
michael@0 18661 state.prototype.clone = function clone() {
michael@0 18662 var s = new State();
michael@0 18663 s.originalId = this.id;
michael@0 18664 s.stack = this.stack.slice(0);
michael@0 18665 s.scope = this.scope.slice(0);
michael@0 18666 s.local = this.local.slice(0);
michael@0 18667 return s;
michael@0 18668 };
michael@0 18669 state.prototype.trace = function trace(writer) {
michael@0 18670 writer.writeLn(this.toString());
michael@0 18671 };
michael@0 18672 state.prototype.toString = function () {
michael@0 18673 return '<' + this.id + (this.originalId ? ':' + this.originalId : '') + ', L[' + this.local.join(', ') + ']' + ', S[' + this.stack.join(', ') + ']' + ', $[' + this.scope.join(', ') + ']>';
michael@0 18674 };
michael@0 18675 state.prototype.equals = function (other) {
michael@0 18676 return arrayEquals(this.stack, other.stack) && arrayEquals(this.scope, other.scope) && arrayEquals(this.local, other.local);
michael@0 18677 };
michael@0 18678 function arrayEquals(a, b) {
michael@0 18679 if (a.length != b.length) {
michael@0 18680 return false;
michael@0 18681 }
michael@0 18682 for (var i = a.length - 1; i >= 0; i--) {
michael@0 18683 if (!a[i].equals(b[i])) {
michael@0 18684 return false;
michael@0 18685 }
michael@0 18686 }
michael@0 18687 return true;
michael@0 18688 }
michael@0 18689 state.prototype.isSubset = function (other) {
michael@0 18690 return arraySubset(this.stack, other.stack) && arraySubset(this.scope, other.scope) && arraySubset(this.local, other.local);
michael@0 18691 };
michael@0 18692 function arraySubset(a, b) {
michael@0 18693 if (a.length != b.length) {
michael@0 18694 return false;
michael@0 18695 }
michael@0 18696 for (var i = a.length - 1; i >= 0; i--) {
michael@0 18697 if (a[i] === b[i] || a[i].equals(b[i])) {
michael@0 18698 continue;
michael@0 18699 }
michael@0 18700 if (a[i].merge(b[i]) !== a[i]) {
michael@0 18701 return false;
michael@0 18702 }
michael@0 18703 }
michael@0 18704 return true;
michael@0 18705 }
michael@0 18706 state.prototype.merge = function (other) {
michael@0 18707 mergeArrays(this.local, other.local);
michael@0 18708 mergeArrays(this.stack, other.stack);
michael@0 18709 mergeArrays(this.scope, other.scope);
michael@0 18710 };
michael@0 18711 function mergeArrays(a, b) {
michael@0 18712 true;
michael@0 18713 for (var i = a.length - 1; i >= 0; i--) {
michael@0 18714 true;
michael@0 18715 if (a[i] === b[i]) {
michael@0 18716 continue;
michael@0 18717 }
michael@0 18718 a[i] = a[i].merge(b[i]);
michael@0 18719 }
michael@0 18720 }
michael@0 18721 return state;
michael@0 18722 }();
michael@0 18723 var Verification = function () {
michael@0 18724 function verification(methodInfo, domain, savedScope) {
michael@0 18725 this.savedScope = savedScope;
michael@0 18726 this.methodInfo = methodInfo;
michael@0 18727 this.domain = domain;
michael@0 18728 this.writer = new IndentingWriter();
michael@0 18729 this.returnType = Type.Undefined;
michael@0 18730 }
michael@0 18731 verification.prototype.verify = function verify() {
michael@0 18732 var mi = this.methodInfo;
michael@0 18733 var writer = verifierTraceLevel.value ? this.writer : null;
michael@0 18734 var blocks = mi.analysis.blocks;
michael@0 18735 blocks.forEach(function (x) {
michael@0 18736 x.entryState = x.exitState = null;
michael@0 18737 });
michael@0 18738 if (writer) {
michael@0 18739 this.methodInfo.trace(writer);
michael@0 18740 }
michael@0 18741 var entryState = new State();
michael@0 18742 true;
michael@0 18743 this.thisType = mi.holder ? Type.from(mi.holder, this.domain) : Type.Any;
michael@0 18744 entryState.local.push(this.thisType);
michael@0 18745 for (var i = 0; i < mi.parameters.length; i++) {
michael@0 18746 entryState.local.push(Type.fromName(mi.parameters[i].type, this.domain).instanceType());
michael@0 18747 }
michael@0 18748 var remainingLocals = mi.localCount - mi.parameters.length - 1;
michael@0 18749 if (mi.needsRest() || mi.needsArguments()) {
michael@0 18750 entryState.local.push(Type.Array);
michael@0 18751 remainingLocals -= 1;
michael@0 18752 }
michael@0 18753 for (var i = 0; i < remainingLocals; i++) {
michael@0 18754 entryState.local.push(Type.Undefined);
michael@0 18755 }
michael@0 18756 true;
michael@0 18757 if (writer) {
michael@0 18758 entryState.trace(writer);
michael@0 18759 }
michael@0 18760 for (var bi = 0, len = blocks.length; bi < len; bi++) {
michael@0 18761 blocks[bi].bdo = bi;
michael@0 18762 }
michael@0 18763 var worklist = new Shumway.SortedList(function compare(blockA, blockB) {
michael@0 18764 return blockA.bdo - blockB.bdo;
michael@0 18765 });
michael@0 18766 blocks[0].entryState = entryState;
michael@0 18767 worklist.push(blocks[0]);
michael@0 18768 while (!worklist.isEmpty()) {
michael@0 18769 var block = worklist.pop();
michael@0 18770 var exitState = block.exitState = block.entryState.clone();
michael@0 18771 this.verifyBlock(block, exitState);
michael@0 18772 block.succs.forEach(function (successor) {
michael@0 18773 if (worklist.contains(successor)) {
michael@0 18774 if (writer) {
michael@0 18775 writer.writeLn('Forward Merged Block: ' + successor.bid + ' ' + exitState.toString() + ' with ' + successor.entryState.toString());
michael@0 18776 }
michael@0 18777 successor.entryState.merge(exitState);
michael@0 18778 if (writer) {
michael@0 18779 writer.writeLn('Merged State: ' + successor.entryState);
michael@0 18780 }
michael@0 18781 return;
michael@0 18782 }
michael@0 18783 if (successor.entryState) {
michael@0 18784 if (!successor.entryState.isSubset(exitState)) {
michael@0 18785 if (writer) {
michael@0 18786 writer.writeLn('Backward Merged Block: ' + block.bid + ' with ' + successor.bid + ' ' + exitState.toString() + ' with ' + successor.entryState.toString());
michael@0 18787 }
michael@0 18788 successor.entryState.merge(exitState);
michael@0 18789 worklist.push(successor);
michael@0 18790 if (writer) {
michael@0 18791 writer.writeLn('Merged State: ' + successor.entryState);
michael@0 18792 }
michael@0 18793 }
michael@0 18794 return;
michael@0 18795 }
michael@0 18796 successor.entryState = exitState.clone();
michael@0 18797 worklist.push(successor);
michael@0 18798 if (writer) {
michael@0 18799 writer.writeLn('Added Block: ' + successor.bid + ' to worklist: ' + successor.entryState.toString());
michael@0 18800 }
michael@0 18801 });
michael@0 18802 }
michael@0 18803 if (writer) {
michael@0 18804 writer.writeLn('Inferred return type: ' + this.returnType);
michael@0 18805 }
michael@0 18806 this.methodInfo.inferredReturnType = this.returnType;
michael@0 18807 };
michael@0 18808 verification.prototype.verifyBlock = function verifyBlock(block, state) {
michael@0 18809 var savedScope = this.savedScope;
michael@0 18810 var globalScope = savedScope[0];
michael@0 18811 var local = state.local;
michael@0 18812 var stack = state.stack;
michael@0 18813 var scope = state.scope;
michael@0 18814 var writer = verifierTraceLevel.value ? this.writer : null;
michael@0 18815 var bytecodes = this.methodInfo.analysis.bytecodes;
michael@0 18816 var domain = this.domain;
michael@0 18817 var multinames = this.methodInfo.abc.constantPool.multinames;
michael@0 18818 var mi = this.methodInfo;
michael@0 18819 var bc, obj, fn, mn, l, r, val, type, returnType;
michael@0 18820 if (writer) {
michael@0 18821 writer.enter('verifyBlock: ' + block.bid + ', range: [' + block.position + ', ' + block.end.position + '], entryState: ' + state.toString() + ' {');
michael@0 18822 }
michael@0 18823 function construct(obj) {
michael@0 18824 if (obj instanceof TraitsType || obj instanceof ParameterizedType) {
michael@0 18825 if (obj === Type.Function || obj === Type.Class || obj === Type.Object) {
michael@0 18826 return Type.Object;
michael@0 18827 }
michael@0 18828 return obj.instanceType();
michael@0 18829 } else {
michael@0 18830 return Type.Any;
michael@0 18831 }
michael@0 18832 }
michael@0 18833 function ti() {
michael@0 18834 return bc.ti || (bc.ti = new TypeInformation());
michael@0 18835 }
michael@0 18836 function push(x) {
michael@0 18837 true;
michael@0 18838 ti().type = x;
michael@0 18839 stack.push(x);
michael@0 18840 }
michael@0 18841 function pop() {
michael@0 18842 return stack.pop();
michael@0 18843 }
michael@0 18844 function findProperty(mn, strict) {
michael@0 18845 if (mn instanceof MultinameType) {
michael@0 18846 if (mn.name === 'Array') {
michael@0 18847 debugger;
michael@0 18848 }
michael@0 18849 return Type.Any;
michael@0 18850 }
michael@0 18851 for (var i = scope.length - 1; i >= -savedScope.length; i--) {
michael@0 18852 var s = i >= 0 ? scope[i] : savedScope[savedScope.length + i];
michael@0 18853 if (s instanceof TraitsType) {
michael@0 18854 var trait = s.getTrait(mn, false, true);
michael@0 18855 if (trait) {
michael@0 18856 ti().scopeDepth = scope.length - i - 1;
michael@0 18857 if (s.isClassInfo() || s.isScriptInfo()) {
michael@0 18858 ti().object = LazyInitializer.create(s.object);
michael@0 18859 }
michael@0 18860 return s;
michael@0 18861 }
michael@0 18862 } else {
michael@0 18863 if (mn.name === 'Array') {
michael@0 18864 debugger;
michael@0 18865 }
michael@0 18866 return Type.Any;
michael@0 18867 }
michael@0 18868 }
michael@0 18869 var resolved = domain.findDefiningScript(mn, false);
michael@0 18870 if (resolved) {
michael@0 18871 ti().object = LazyInitializer.create(resolved.script);
michael@0 18872 return Type.from(resolved.script, domain);
michael@0 18873 }
michael@0 18874 if (mn.name === 'Array') {
michael@0 18875 debugger;
michael@0 18876 }
michael@0 18877 return Type.Any;
michael@0 18878 }
michael@0 18879 function popMultiname() {
michael@0 18880 var mn = multinames[bc.index];
michael@0 18881 if (mn.isRuntime()) {
michael@0 18882 var namespaces = mn.namespaces;
michael@0 18883 var name = mn.name;
michael@0 18884 if (mn.isRuntimeName()) {
michael@0 18885 name = pop();
michael@0 18886 }
michael@0 18887 if (mn.isRuntimeNamespace()) {
michael@0 18888 namespaces = [
michael@0 18889 pop()
michael@0 18890 ];
michael@0 18891 }
michael@0 18892 return new MultinameType(namespaces, name, mn.flags);
michael@0 18893 }
michael@0 18894 return mn;
michael@0 18895 }
michael@0 18896 function accessSlot(obj) {
michael@0 18897 if (obj instanceof TraitsType) {
michael@0 18898 var trait = obj.getTraitAt(bc.index);
michael@0 18899 writer && writer.debugLn('accessSlot() -> ' + trait);
michael@0 18900 if (trait) {
michael@0 18901 ti().trait = trait;
michael@0 18902 if (trait.isSlot()) {
michael@0 18903 return Type.fromName(trait.typeName, domain).instanceType();
michael@0 18904 } else if (trait.isClass()) {
michael@0 18905 return Type.from(trait.classInfo, domain);
michael@0 18906 }
michael@0 18907 }
michael@0 18908 }
michael@0 18909 return Type.Any;
michael@0 18910 }
michael@0 18911 function isNumericMultiname(mn) {
michael@0 18912 return mn instanceof Multiname && Multiname.isNumeric(mn) || mn instanceof MultinameType && (mn.name instanceof TraitsType && mn.name.isNumeric());
michael@0 18913 }
michael@0 18914 function getProperty(obj, mn) {
michael@0 18915 if (obj instanceof TraitsType || obj instanceof ParameterizedType) {
michael@0 18916 var trait = obj.getTrait(mn, false, true);
michael@0 18917 writer && writer.debugLn('getProperty(' + mn + ') -> ' + trait);
michael@0 18918 if (trait) {
michael@0 18919 ti().trait = trait;
michael@0 18920 if (trait.isSlot() || trait.isConst()) {
michael@0 18921 return Type.fromName(trait.typeName, domain).instanceType();
michael@0 18922 } else if (trait.isGetter()) {
michael@0 18923 return Type.fromName(trait.methodInfo.returnType, domain).instanceType();
michael@0 18924 } else if (trait.isClass()) {
michael@0 18925 return Type.from(trait.classInfo, domain);
michael@0 18926 } else if (trait.isMethod()) {
michael@0 18927 return Type.from(trait.methodInfo, domain);
michael@0 18928 }
michael@0 18929 } else if (obj.isDirectlyReadable() && mn instanceof Multiname) {
michael@0 18930 ti().propertyQName = Multiname.getPublicQualifiedName(mn.name);
michael@0 18931 }
michael@0 18932 if (isNumericMultiname(mn)) {
michael@0 18933 if (obj.isIndexedReadable()) {
michael@0 18934 ti().isIndexedReadable = true;
michael@0 18935 if (obj.isVector()) {
michael@0 18936 return obj.parameter;
michael@0 18937 }
michael@0 18938 } else if (obj.isDirectlyReadable()) {
michael@0 18939 ti().isDirectlyReadable = true;
michael@0 18940 }
michael@0 18941 }
michael@0 18942 }
michael@0 18943 return Type.Any;
michael@0 18944 }
michael@0 18945 function setProperty(obj, mn, value) {
michael@0 18946 if (obj instanceof TraitsType || obj instanceof ParameterizedType) {
michael@0 18947 var trait = obj.getTrait(mn, true, true);
michael@0 18948 writer && writer.debugLn('setProperty(' + mn + ') -> ' + trait);
michael@0 18949 if (trait) {
michael@0 18950 ti().trait = trait;
michael@0 18951 } else if (obj.isDirectlyWriteable() && mn instanceof Multiname) {
michael@0 18952 ti().propertyQName = Multiname.getPublicQualifiedName(mn.name);
michael@0 18953 }
michael@0 18954 if (isNumericMultiname(mn)) {
michael@0 18955 if (obj.isDirectlyWriteable()) {
michael@0 18956 ti().isDirectlyWriteable = true;
michael@0 18957 } else if (obj.isVector()) {
michael@0 18958 ti().isIndexedWriteable = true;
michael@0 18959 }
michael@0 18960 }
michael@0 18961 }
michael@0 18962 }
michael@0 18963 for (var bci = block.position, end = block.end.position; bci <= end; bci++) {
michael@0 18964 bc = bytecodes[bci];
michael@0 18965 var op = bc.op;
michael@0 18966 if (writer && verifierTraceLevel.value > 1) {
michael@0 18967 writer.writeLn(('stateBefore: ' + state.toString() + ' $$[' + savedScope.join(', ') + ']').padRight(' ', 100) + ' : ' + bci + ', ' + bc.toString(mi.abc));
michael@0 18968 }
michael@0 18969 switch (op) {
michael@0 18970 case 1:
michael@0 18971 break;
michael@0 18972 case 3:
michael@0 18973 pop();
michael@0 18974 break;
michael@0 18975 case 4:
michael@0 18976 mn = popMultiname();
michael@0 18977 obj = pop();
michael@0 18978 true;
michael@0 18979 ti().baseClass = LazyInitializer.create(this.thisType.super().classType().object);
michael@0 18980 push(getProperty(obj.super(), mn));
michael@0 18981 break;
michael@0 18982 case 5:
michael@0 18983 val = pop();
michael@0 18984 mn = popMultiname();
michael@0 18985 obj = pop();
michael@0 18986 true;
michael@0 18987 ti().baseClass = LazyInitializer.create(this.thisType.super().classType().object);
michael@0 18988 setProperty(obj.super(), mn, val);
michael@0 18989 break;
michael@0 18990 case 6:
michael@0 18991 notImplemented(bc);
michael@0 18992 break;
michael@0 18993 case 7:
michael@0 18994 notImplemented(bc);
michael@0 18995 break;
michael@0 18996 case 8:
michael@0 18997 state.local[bc.index] = Type.Undefined;
michael@0 18998 break;
michael@0 18999 case 10:
michael@0 19000 notImplemented(bc);
michael@0 19001 break;
michael@0 19002 case 11:
michael@0 19003 notImplemented(bc);
michael@0 19004 break;
michael@0 19005 case 12:
michael@0 19006 case 24:
michael@0 19007 case 13:
michael@0 19008 case 23:
michael@0 19009 case 14:
michael@0 19010 case 22:
michael@0 19011 case 15:
michael@0 19012 case 21:
michael@0 19013 case 19:
michael@0 19014 case 20:
michael@0 19015 case 25:
michael@0 19016 case 26:
michael@0 19017 pop();
michael@0 19018 pop();
michael@0 19019 break;
michael@0 19020 case 16:
michael@0 19021 break;
michael@0 19022 case 17:
michael@0 19023 case 18:
michael@0 19024 pop();
michael@0 19025 break;
michael@0 19026 case 27:
michael@0 19027 pop(Type.Int);
michael@0 19028 break;
michael@0 19029 case 29:
michael@0 19030 scope.pop();
michael@0 19031 break;
michael@0 19032 case 30:
michael@0 19033 case 35:
michael@0 19034 pop(Type.Int);
michael@0 19035 pop();
michael@0 19036 push(Type.Any);
michael@0 19037 break;
michael@0 19038 case 31:
michael@0 19039 push(Type.Boolean);
michael@0 19040 break;
michael@0 19041 case 50:
michael@0 19042 push(Type.Boolean);
michael@0 19043 break;
michael@0 19044 case 32:
michael@0 19045 push(Type.Null);
michael@0 19046 break;
michael@0 19047 case 33:
michael@0 19048 push(Type.Undefined);
michael@0 19049 break;
michael@0 19050 case 34:
michael@0 19051 notImplemented(bc);
michael@0 19052 break;
michael@0 19053 case 36:
michael@0 19054 push(Type.Int);
michael@0 19055 break;
michael@0 19056 case 37:
michael@0 19057 push(Type.Int);
michael@0 19058 break;
michael@0 19059 case 44:
michael@0 19060 push(Type.String);
michael@0 19061 break;
michael@0 19062 case 45:
michael@0 19063 push(Type.Int);
michael@0 19064 break;
michael@0 19065 case 46:
michael@0 19066 push(Type.Uint);
michael@0 19067 break;
michael@0 19068 case 47:
michael@0 19069 push(Type.Number);
michael@0 19070 break;
michael@0 19071 case 38:
michael@0 19072 push(Type.Boolean);
michael@0 19073 break;
michael@0 19074 case 39:
michael@0 19075 push(Type.Boolean);
michael@0 19076 break;
michael@0 19077 case 40:
michael@0 19078 push(Type.Number);
michael@0 19079 break;
michael@0 19080 case 41:
michael@0 19081 pop();
michael@0 19082 break;
michael@0 19083 case 42:
michael@0 19084 val = pop();
michael@0 19085 push(val);
michael@0 19086 push(val);
michael@0 19087 break;
michael@0 19088 case 43:
michael@0 19089 l = pop();
michael@0 19090 r = pop();
michael@0 19091 push(l);
michael@0 19092 push(r);
michael@0 19093 break;
michael@0 19094 case 28:
michael@0 19095 pop();
michael@0 19096 scope.push(Type.Any);
michael@0 19097 break;
michael@0 19098 case 48:
michael@0 19099 scope.push(pop());
michael@0 19100 break;
michael@0 19101 case 49:
michael@0 19102 notImplemented(bc);
michael@0 19103 break;
michael@0 19104 case 53:
michael@0 19105 case 54:
michael@0 19106 case 55:
michael@0 19107 push(Type.Int);
michael@0 19108 break;
michael@0 19109 case 56:
michael@0 19110 case 57:
michael@0 19111 push(Type.Number);
michael@0 19112 break;
michael@0 19113 case 58:
michael@0 19114 case 59:
michael@0 19115 case 60:
michael@0 19116 pop(Type.Int);
michael@0 19117 break;
michael@0 19118 case 61:
michael@0 19119 case 62:
michael@0 19120 pop(Type.Number);
michael@0 19121 break;
michael@0 19122 case 64:
michael@0 19123 push(Type.Function);
michael@0 19124 break;
michael@0 19125 case 65:
michael@0 19126 stack.popMany(bc.argCount);
michael@0 19127 obj = pop();
michael@0 19128 fn = pop();
michael@0 19129 push(Type.Any);
michael@0 19130 break;
michael@0 19131 case 67:
michael@0 19132 throw new VerifierError('callmethod');
michael@0 19133 case 68:
michael@0 19134 notImplemented(bc);
michael@0 19135 break;
michael@0 19136 case 69:
michael@0 19137 case 78:
michael@0 19138 case 79:
michael@0 19139 case 70:
michael@0 19140 case 76:
michael@0 19141 stack.popMany(bc.argCount);
michael@0 19142 mn = popMultiname();
michael@0 19143 obj = pop();
michael@0 19144 if (op === OP_callsuper || op === OP_callsupervoid) {
michael@0 19145 obj = this.thisType.super();
michael@0 19146 ti().baseClass = LazyInitializer.create(this.thisType.super().classType().object);
michael@0 19147 }
michael@0 19148 type = getProperty(obj, mn);
michael@0 19149 if (op === OP_callpropvoid || op === OP_callsupervoid) {
michael@0 19150 break;
michael@0 19151 }
michael@0 19152 if (type instanceof MethodType) {
michael@0 19153 returnType = Type.fromName(type.methodInfo.returnType, domain).instanceType();
michael@0 19154 } else if (type instanceof TraitsType && type.isClassInfo()) {
michael@0 19155 returnType = type.instanceType();
michael@0 19156 } else {
michael@0 19157 returnType = Type.Any;
michael@0 19158 }
michael@0 19159 push(returnType);
michael@0 19160 break;
michael@0 19161 case 71:
michael@0 19162 this.returnType.merge(Type.Undefined);
michael@0 19163 break;
michael@0 19164 case 72:
michael@0 19165 type = pop();
michael@0 19166 if (mi.returnType) {
michael@0 19167 var coerceType = Type.fromName(mi.returnType, this.domain).instanceType();
michael@0 19168 if (coerceType.isSubtypeOf(type)) {
michael@0 19169 ti().noCoercionNeeded = true;
michael@0 19170 }
michael@0 19171 }
michael@0 19172 break;
michael@0 19173 case 73:
michael@0 19174 stack.popMany(bc.argCount);
michael@0 19175 stack.pop();
michael@0 19176 if (this.thisType.isInstanceInfo() && this.thisType.super() === Type.Object) {
michael@0 19177 ti().noCallSuperNeeded = true;
michael@0 19178 } else {
michael@0 19179 ti().baseClass = LazyInitializer.create(this.thisType.super().classType().object);
michael@0 19180 }
michael@0 19181 break;
michael@0 19182 case 66:
michael@0 19183 stack.popMany(bc.argCount);
michael@0 19184 push(construct(pop()));
michael@0 19185 break;
michael@0 19186 case 74:
michael@0 19187 stack.popMany(bc.argCount);
michael@0 19188 mn = popMultiname();
michael@0 19189 push(construct(getProperty(stack.pop(), mn)));
michael@0 19190 break;
michael@0 19191 case 75:
michael@0 19192 notImplemented(bc);
michael@0 19193 break;
michael@0 19194 case 77:
michael@0 19195 notImplemented(bc);
michael@0 19196 break;
michael@0 19197 case 80:
michael@0 19198 case 81:
michael@0 19199 case 82:
michael@0 19200 break;
michael@0 19201 case 83:
michael@0 19202 true;
michael@0 19203 val = pop();
michael@0 19204 obj = pop();
michael@0 19205 if (obj === Type.Any) {
michael@0 19206 push(Type.Any);
michael@0 19207 } else {
michael@0 19208 push(obj.applyType(val));
michael@0 19209 }
michael@0 19210 break;
michael@0 19211 case 84:
michael@0 19212 notImplemented(bc);
michael@0 19213 break;
michael@0 19214 case 85:
michael@0 19215 stack.popMany(bc.argCount * 2);
michael@0 19216 push(Type.Object);
michael@0 19217 break;
michael@0 19218 case 86:
michael@0 19219 stack.popMany(bc.argCount);
michael@0 19220 push(Type.Array);
michael@0 19221 break;
michael@0 19222 case 87:
michael@0 19223 push(Type.from(new ActivationInfo(this.methodInfo)));
michael@0 19224 break;
michael@0 19225 case 88:
michael@0 19226 push(Type.Any);
michael@0 19227 break;
michael@0 19228 case 89:
michael@0 19229 popMultiname();
michael@0 19230 pop();
michael@0 19231 push(Type.XMLList);
michael@0 19232 break;
michael@0 19233 case 90:
michael@0 19234 push(Type.Any);
michael@0 19235 break;
michael@0 19236 case 93:
michael@0 19237 push(findProperty(popMultiname(), true));
michael@0 19238 break;
michael@0 19239 case 94:
michael@0 19240 push(findProperty(popMultiname(), false));
michael@0 19241 break;
michael@0 19242 case 95:
michael@0 19243 notImplemented(bc);
michael@0 19244 break;
michael@0 19245 case 96:
michael@0 19246 mn = popMultiname();
michael@0 19247 push(getProperty(findProperty(mn, true), mn));
michael@0 19248 break;
michael@0 19249 case 104:
michael@0 19250 case 97:
michael@0 19251 val = pop();
michael@0 19252 mn = popMultiname();
michael@0 19253 obj = pop();
michael@0 19254 setProperty(obj, mn, val, bc);
michael@0 19255 break;
michael@0 19256 case 98:
michael@0 19257 push(local[bc.index]);
michael@0 19258 break;
michael@0 19259 case 99:
michael@0 19260 local[bc.index] = pop();
michael@0 19261 break;
michael@0 19262 case 100:
michael@0 19263 push(globalScope);
michael@0 19264 ti().object = LazyInitializer.create(globalScope.object);
michael@0 19265 break;
michael@0 19266 case 101:
michael@0 19267 push(scope[bc.index]);
michael@0 19268 break;
michael@0 19269 case 102:
michael@0 19270 mn = popMultiname();
michael@0 19271 obj = pop();
michael@0 19272 push(getProperty(obj, mn));
michael@0 19273 break;
michael@0 19274 case 103:
michael@0 19275 notImplemented(bc);
michael@0 19276 break;
michael@0 19277 case 105:
michael@0 19278 notImplemented(bc);
michael@0 19279 break;
michael@0 19280 case 106:
michael@0 19281 popMultiname();
michael@0 19282 pop();
michael@0 19283 push(Type.Boolean);
michael@0 19284 break;
michael@0 19285 case 107:
michael@0 19286 notImplemented(bc);
michael@0 19287 break;
michael@0 19288 case 108:
michael@0 19289 push(accessSlot(pop()));
michael@0 19290 break;
michael@0 19291 case 109:
michael@0 19292 val = pop();
michael@0 19293 obj = pop();
michael@0 19294 accessSlot(obj);
michael@0 19295 break;
michael@0 19296 case 110:
michael@0 19297 notImplemented(bc);
michael@0 19298 break;
michael@0 19299 case 111:
michael@0 19300 notImplemented(bc);
michael@0 19301 break;
michael@0 19302 case 112:
michael@0 19303 pop();
michael@0 19304 push(Type.String);
michael@0 19305 break;
michael@0 19306 case 113:
michael@0 19307 pop();
michael@0 19308 push(Type.String);
michael@0 19309 break;
michael@0 19310 case 114:
michael@0 19311 pop();
michael@0 19312 push(Type.String);
michael@0 19313 break;
michael@0 19314 case 131:
michael@0 19315 case 115:
michael@0 19316 pop();
michael@0 19317 push(Type.Int);
michael@0 19318 break;
michael@0 19319 case 136:
michael@0 19320 case 116:
michael@0 19321 pop();
michael@0 19322 push(Type.Uint);
michael@0 19323 break;
michael@0 19324 case 132:
michael@0 19325 case 117:
michael@0 19326 pop();
michael@0 19327 push(Type.Number);
michael@0 19328 break;
michael@0 19329 case 129:
michael@0 19330 case 118:
michael@0 19331 pop();
michael@0 19332 push(Type.Boolean);
michael@0 19333 break;
michael@0 19334 case 119:
michael@0 19335 notImplemented(bc);
michael@0 19336 break;
michael@0 19337 case 120:
michael@0 19338 break;
michael@0 19339 case 121:
michael@0 19340 pop();
michael@0 19341 push(Type.Number);
michael@0 19342 break;
michael@0 19343 case 122:
michael@0 19344 notImplemented(bc);
michael@0 19345 break;
michael@0 19346 case 123:
michael@0 19347 notImplemented(bc);
michael@0 19348 break;
michael@0 19349 case 128:
michael@0 19350 type = pop();
michael@0 19351 var coerceType = Type.fromName(multinames[bc.index], this.domain).instanceType();
michael@0 19352 if (coerceType.isSubtypeOf(type)) {
michael@0 19353 ti().noCoercionNeeded = true;
michael@0 19354 }
michael@0 19355 push(coerceType);
michael@0 19356 break;
michael@0 19357 case 130:
michael@0 19358 break;
michael@0 19359 case 133:
michael@0 19360 pop();
michael@0 19361 push(Type.String);
michael@0 19362 break;
michael@0 19363 case 134:
michael@0 19364 notImplemented(bc);
michael@0 19365 break;
michael@0 19366 case 135:
michael@0 19367 type = pop();
michael@0 19368 pop();
michael@0 19369 if (type instanceof TraitsType) {
michael@0 19370 push(type.instanceType());
michael@0 19371 } else {
michael@0 19372 push(Type.Any);
michael@0 19373 }
michael@0 19374 break;
michael@0 19375 case 137:
michael@0 19376 notImplemented(bc);
michael@0 19377 break;
michael@0 19378 case 144:
michael@0 19379 case 145:
michael@0 19380 case 147:
michael@0 19381 pop();
michael@0 19382 push(Type.Number);
michael@0 19383 break;
michael@0 19384 case 146:
michael@0 19385 case 148:
michael@0 19386 local[bc.index] = Type.Number;
michael@0 19387 break;
michael@0 19388 case 149:
michael@0 19389 pop();
michael@0 19390 push(Type.String);
michael@0 19391 break;
michael@0 19392 case 150:
michael@0 19393 pop();
michael@0 19394 push(Type.Boolean);
michael@0 19395 break;
michael@0 19396 case 160:
michael@0 19397 r = pop();
michael@0 19398 l = pop();
michael@0 19399 if (l.isNumeric() && r.isNumeric()) {
michael@0 19400 push(Type.Number);
michael@0 19401 } else if (l === Type.String || r === Type.String) {
michael@0 19402 push(Type.String);
michael@0 19403 } else {
michael@0 19404 push(Type.Any);
michael@0 19405 }
michael@0 19406 break;
michael@0 19407 case 161:
michael@0 19408 case 162:
michael@0 19409 case 163:
michael@0 19410 case 164:
michael@0 19411 pop();
michael@0 19412 pop();
michael@0 19413 push(Type.Number);
michael@0 19414 break;
michael@0 19415 case 168:
michael@0 19416 case 169:
michael@0 19417 case 170:
michael@0 19418 case 165:
michael@0 19419 case 166:
michael@0 19420 case 167:
michael@0 19421 pop();
michael@0 19422 pop();
michael@0 19423 push(Type.Int);
michael@0 19424 break;
michael@0 19425 case 151:
michael@0 19426 pop();
michael@0 19427 push(Type.Int);
michael@0 19428 break;
michael@0 19429 case 171:
michael@0 19430 case 172:
michael@0 19431 case 173:
michael@0 19432 case 174:
michael@0 19433 case 175:
michael@0 19434 case 176:
michael@0 19435 case 177:
michael@0 19436 case 180:
michael@0 19437 pop();
michael@0 19438 pop();
michael@0 19439 push(Type.Boolean);
michael@0 19440 break;
michael@0 19441 case 178:
michael@0 19442 pop();
michael@0 19443 push(Type.Boolean);
michael@0 19444 break;
michael@0 19445 case 179:
michael@0 19446 pop();
michael@0 19447 pop();
michael@0 19448 push(Type.Boolean);
michael@0 19449 break;
michael@0 19450 case 194:
michael@0 19451 case 195:
michael@0 19452 local[bc.index] = Type.Int;
michael@0 19453 break;
michael@0 19454 case 193:
michael@0 19455 case 192:
michael@0 19456 case 196:
michael@0 19457 pop();
michael@0 19458 push(Type.Int);
michael@0 19459 break;
michael@0 19460 case 197:
michael@0 19461 case 198:
michael@0 19462 case 199:
michael@0 19463 pop();
michael@0 19464 pop();
michael@0 19465 push(Type.Int);
michael@0 19466 break;
michael@0 19467 case 208:
michael@0 19468 case 209:
michael@0 19469 case 210:
michael@0 19470 case 211:
michael@0 19471 push(local[op - OP_getlocal0]);
michael@0 19472 break;
michael@0 19473 case 212:
michael@0 19474 case 213:
michael@0 19475 case 214:
michael@0 19476 case 215:
michael@0 19477 local[op - OP_setlocal0] = pop();
michael@0 19478 break;
michael@0 19479 case 239:
michael@0 19480 break;
michael@0 19481 case 240:
michael@0 19482 break;
michael@0 19483 case 241:
michael@0 19484 break;
michael@0 19485 case 242:
michael@0 19486 break;
michael@0 19487 case 243:
michael@0 19488 break;
michael@0 19489 default:
michael@0 19490 console.info('Not Implemented: ' + bc);
michael@0 19491 }
michael@0 19492 if (writer) {
michael@0 19493 if (bc.ti) {
michael@0 19494 writer.debugLn('> TI: ' + bc.ti);
michael@0 19495 }
michael@0 19496 }
michael@0 19497 }
michael@0 19498 if (writer) {
michael@0 19499 writer.leave('}');
michael@0 19500 writer.writeLn('verifiedBlock: ' + block.bid + ', range: [' + block.position + ', ' + block.end.position + '], exitState: ' + state.toString());
michael@0 19501 }
michael@0 19502 };
michael@0 19503 return verification;
michael@0 19504 }();
michael@0 19505 function verifier() {
michael@0 19506 this.writer = new IndentingWriter();
michael@0 19507 }
michael@0 19508 verifier.prototype.verifyMethod = function (methodInfo, scope) {
michael@0 19509 try {
michael@0 19510 var domain = methodInfo.abc.applicationDomain;
michael@0 19511 var scopeObjects = scope.getScopeObjects();
michael@0 19512 if (!scopeObjects[scopeObjects.length - 1]) {
michael@0 19513 if (methodInfo.holder instanceof InstanceInfo) {
michael@0 19514 scopeObjects[scopeObjects.length - 1] = methodInfo.holder.classInfo;
michael@0 19515 } else if (methodInfo.holder instanceof ClassInfo) {
michael@0 19516 scopeObjects[scopeObjects.length - 1] = methodInfo.holder;
michael@0 19517 }
michael@0 19518 }
michael@0 19519 var savedScope = scopeObjects.map(function (object) {
michael@0 19520 if (object instanceof MethodInfo) {
michael@0 19521 return Type.from(new ActivationInfo(object));
michael@0 19522 }
michael@0 19523 return Type.from(object, domain);
michael@0 19524 });
michael@0 19525 new Verification(methodInfo, methodInfo.abc.applicationDomain, savedScope).verify();
michael@0 19526 methodInfo.verified = true;
michael@0 19527 Counter.count('Verifier: Methods');
michael@0 19528 } catch (e) {
michael@0 19529 if (e instanceof VerifierError) {
michael@0 19530 return;
michael@0 19531 }
michael@0 19532 throw e;
michael@0 19533 }
michael@0 19534 };
michael@0 19535 return verifier;
michael@0 19536 }();
michael@0 19537 (function (exports) {
michael@0 19538 var debug = false;
michael@0 19539 var IRDefinition = {
michael@0 19540 Control: {
michael@0 19541 Region: {
michael@0 19542 predecessors: {
michael@0 19543 array: true,
michael@0 19544 expand: 'control'
michael@0 19545 },
michael@0 19546 Start: {
michael@0 19547 _constructorText: 'this.control = this;',
michael@0 19548 scope: {
michael@0 19549 dynamic: true
michael@0 19550 },
michael@0 19551 domain: {
michael@0 19552 dynamic: true
michael@0 19553 }
michael@0 19554 }
michael@0 19555 },
michael@0 19556 End: {
michael@0 19557 control: {
michael@0 19558 assert: 'isControlOrNull'
michael@0 19559 },
michael@0 19560 Stop: {
michael@0 19561 store: {
michael@0 19562 assert: 'isStore'
michael@0 19563 },
michael@0 19564 argument: {
michael@0 19565 assert: ''
michael@0 19566 }
michael@0 19567 },
michael@0 19568 If: {
michael@0 19569 predicate: {
michael@0 19570 assert: ''
michael@0 19571 }
michael@0 19572 },
michael@0 19573 Switch: {
michael@0 19574 determinant: {
michael@0 19575 assert: ''
michael@0 19576 }
michael@0 19577 },
michael@0 19578 Jump: {}
michael@0 19579 }
michael@0 19580 },
michael@0 19581 Value: {
michael@0 19582 StoreDependent: {
michael@0 19583 control: {
michael@0 19584 assert: 'isControlOrNull',
michael@0 19585 nullable: true
michael@0 19586 },
michael@0 19587 store: {
michael@0 19588 assert: 'isStoreOrNull',
michael@0 19589 nullable: true
michael@0 19590 },
michael@0 19591 loads: {
michael@0 19592 dynamic: true,
michael@0 19593 nullable: true,
michael@0 19594 array: true
michael@0 19595 },
michael@0 19596 Call: {
michael@0 19597 callee: {
michael@0 19598 assert: ''
michael@0 19599 },
michael@0 19600 object: {
michael@0 19601 assert: 'isValueOrNull',
michael@0 19602 nullable: true
michael@0 19603 },
michael@0 19604 args: {
michael@0 19605 assert: 'isArray',
michael@0 19606 array: true
michael@0 19607 },
michael@0 19608 flags: {
michael@0 19609 internal: true,
michael@0 19610 assert: 'isNumber'
michael@0 19611 }
michael@0 19612 },
michael@0 19613 CallProperty: {
michael@0 19614 object: {
michael@0 19615 assert: ''
michael@0 19616 },
michael@0 19617 name: {
michael@0 19618 assert: ''
michael@0 19619 },
michael@0 19620 args: {
michael@0 19621 assert: 'isArray',
michael@0 19622 array: true
michael@0 19623 },
michael@0 19624 flags: {
michael@0 19625 internal: true,
michael@0 19626 assert: 'isNumber'
michael@0 19627 },
michael@0 19628 ASCallProperty: {
michael@0 19629 isLex: {
michael@0 19630 assert: '',
michael@0 19631 internal: true
michael@0 19632 }
michael@0 19633 },
michael@0 19634 ASCallSuper: {
michael@0 19635 scope: {
michael@0 19636 assert: ''
michael@0 19637 }
michael@0 19638 }
michael@0 19639 },
michael@0 19640 New: {
michael@0 19641 callee: {
michael@0 19642 assert: ''
michael@0 19643 },
michael@0 19644 args: {
michael@0 19645 assert: '',
michael@0 19646 array: true
michael@0 19647 },
michael@0 19648 ASNew: {}
michael@0 19649 },
michael@0 19650 GetProperty: {
michael@0 19651 object: {
michael@0 19652 assert: ''
michael@0 19653 },
michael@0 19654 name: {
michael@0 19655 assert: ''
michael@0 19656 },
michael@0 19657 ASGetProperty: {
michael@0 19658 flags: {
michael@0 19659 internal: true,
michael@0 19660 assert: 'isNumber'
michael@0 19661 }
michael@0 19662 },
michael@0 19663 ASGetDescendants: {},
michael@0 19664 ASHasProperty: {},
michael@0 19665 ASGetSlot: {},
michael@0 19666 ASGetSuper: {
michael@0 19667 scope: {
michael@0 19668 assert: ''
michael@0 19669 }
michael@0 19670 }
michael@0 19671 },
michael@0 19672 SetProperty: {
michael@0 19673 object: {
michael@0 19674 assert: ''
michael@0 19675 },
michael@0 19676 name: {
michael@0 19677 assert: ''
michael@0 19678 },
michael@0 19679 value: {
michael@0 19680 assert: ''
michael@0 19681 },
michael@0 19682 ASSetProperty: {
michael@0 19683 flags: {
michael@0 19684 internal: true
michael@0 19685 }
michael@0 19686 },
michael@0 19687 ASSetSlot: {},
michael@0 19688 ASSetSuper: {
michael@0 19689 scope: {
michael@0 19690 assert: ''
michael@0 19691 }
michael@0 19692 }
michael@0 19693 },
michael@0 19694 DeleteProperty: {
michael@0 19695 object: {
michael@0 19696 assert: ''
michael@0 19697 },
michael@0 19698 name: {
michael@0 19699 assert: ''
michael@0 19700 },
michael@0 19701 ASDeleteProperty: {}
michael@0 19702 },
michael@0 19703 ASFindProperty: {
michael@0 19704 scope: {
michael@0 19705 assert: ''
michael@0 19706 },
michael@0 19707 name: {
michael@0 19708 assert: ''
michael@0 19709 },
michael@0 19710 domain: {
michael@0 19711 assert: ''
michael@0 19712 },
michael@0 19713 strict: {
michael@0 19714 internal: true
michael@0 19715 }
michael@0 19716 }
michael@0 19717 },
michael@0 19718 Store: {},
michael@0 19719 Phi: {
michael@0 19720 control: {
michael@0 19721 assert: 'isControl',
michael@0 19722 nullable: true
michael@0 19723 },
michael@0 19724 args: {
michael@0 19725 array: true,
michael@0 19726 expand: 'value'
michael@0 19727 }
michael@0 19728 },
michael@0 19729 Variable: {
michael@0 19730 name: {
michael@0 19731 internal: true
michael@0 19732 }
michael@0 19733 },
michael@0 19734 Copy: {
michael@0 19735 argument: {}
michael@0 19736 },
michael@0 19737 Move: {
michael@0 19738 to: {},
michael@0 19739 from: {}
michael@0 19740 },
michael@0 19741 Projection: {
michael@0 19742 argument: {},
michael@0 19743 type: {
michael@0 19744 internal: true
michael@0 19745 },
michael@0 19746 selector: {
michael@0 19747 internal: true,
michael@0 19748 optional: true
michael@0 19749 }
michael@0 19750 },
michael@0 19751 Latch: {
michael@0 19752 control: {
michael@0 19753 assert: 'isControlOrNull',
michael@0 19754 nullable: true
michael@0 19755 },
michael@0 19756 condition: {},
michael@0 19757 left: {},
michael@0 19758 right: {}
michael@0 19759 },
michael@0 19760 Binary: {
michael@0 19761 operator: {
michael@0 19762 internal: true
michael@0 19763 },
michael@0 19764 left: {},
michael@0 19765 right: {}
michael@0 19766 },
michael@0 19767 Unary: {
michael@0 19768 operator: {
michael@0 19769 internal: true
michael@0 19770 },
michael@0 19771 argument: {}
michael@0 19772 },
michael@0 19773 Constant: {
michael@0 19774 value: {
michael@0 19775 internal: true
michael@0 19776 }
michael@0 19777 },
michael@0 19778 GlobalProperty: {
michael@0 19779 name: {
michael@0 19780 internal: true
michael@0 19781 }
michael@0 19782 },
michael@0 19783 This: {
michael@0 19784 control: {
michael@0 19785 assert: 'isControl'
michael@0 19786 }
michael@0 19787 },
michael@0 19788 Throw: {
michael@0 19789 control: {
michael@0 19790 assert: 'isControl'
michael@0 19791 },
michael@0 19792 argument: {}
michael@0 19793 },
michael@0 19794 Arguments: {
michael@0 19795 control: {
michael@0 19796 assert: 'isControl'
michael@0 19797 }
michael@0 19798 },
michael@0 19799 Parameter: {
michael@0 19800 control: {
michael@0 19801 assert: 'isControl'
michael@0 19802 },
michael@0 19803 index: {
michael@0 19804 internal: true
michael@0 19805 },
michael@0 19806 name: {
michael@0 19807 internal: true
michael@0 19808 }
michael@0 19809 },
michael@0 19810 NewArray: {
michael@0 19811 control: {
michael@0 19812 assert: 'isControl'
michael@0 19813 },
michael@0 19814 elements: {
michael@0 19815 array: true
michael@0 19816 }
michael@0 19817 },
michael@0 19818 NewObject: {
michael@0 19819 control: {
michael@0 19820 assert: 'isControl'
michael@0 19821 },
michael@0 19822 properties: {
michael@0 19823 array: true
michael@0 19824 }
michael@0 19825 },
michael@0 19826 KeyValuePair: {
michael@0 19827 key: {},
michael@0 19828 value: {}
michael@0 19829 },
michael@0 19830 ASScope: {
michael@0 19831 parent: {},
michael@0 19832 object: {},
michael@0 19833 isWith: {
michael@0 19834 internal: true
michael@0 19835 }
michael@0 19836 },
michael@0 19837 ASGlobal: {
michael@0 19838 control: {
michael@0 19839 assert: 'isControlOrNull',
michael@0 19840 nullable: true
michael@0 19841 },
michael@0 19842 scope: {
michael@0 19843 assert: 'isScope'
michael@0 19844 }
michael@0 19845 },
michael@0 19846 ASNewActivation: {
michael@0 19847 methodInfo: {
michael@0 19848 internal: true
michael@0 19849 }
michael@0 19850 },
michael@0 19851 ASMultiname: {
michael@0 19852 namespaces: {},
michael@0 19853 name: {},
michael@0 19854 flags: {
michael@0 19855 internal: true
michael@0 19856 }
michael@0 19857 }
michael@0 19858 }
michael@0 19859 };
michael@0 19860 function IRGenerator(root) {
michael@0 19861 var str = '';
michael@0 19862 function out(s) {
michael@0 19863 str += s + '\n';
michael@0 19864 }
michael@0 19865 var writer = new IndentingWriter(false, out);
michael@0 19866 function makeProperties(node) {
michael@0 19867 var result = [];
michael@0 19868 for (var k in node) {
michael@0 19869 if (isProperty(k)) {
michael@0 19870 node[k].name = k;
michael@0 19871 result.push(node[k]);
michael@0 19872 }
michael@0 19873 }
michael@0 19874 return result;
michael@0 19875 }
michael@0 19876 function isProperty(v) {
michael@0 19877 if (v[0] === '_') {
michael@0 19878 return false;
michael@0 19879 }
michael@0 19880 return v[0].toLowerCase() === v[0];
michael@0 19881 }
michael@0 19882 function generate(node, path) {
michael@0 19883 path = path.concat([
michael@0 19884 node
michael@0 19885 ]);
michael@0 19886 writer.enter('var ' + node._name + ' = (function () {');
michael@0 19887 var constructorName = node._name[0].toLowerCase() + node._name.slice(1) + 'Node';
michael@0 19888 if (constructorName.substring(0, 2) === 'aS') {
michael@0 19889 constructorName = 'as' + constructorName.substring(2);
michael@0 19890 }
michael@0 19891 var prototypeName = constructorName + '.prototype';
michael@0 19892 var properties = path.reduce(function (a, v) {
michael@0 19893 return a.concat(makeProperties(v));
michael@0 19894 }, []);
michael@0 19895 var parameters = properties.filter(function (property) {
michael@0 19896 return !property.dynamic;
michael@0 19897 });
michael@0 19898 var optionalParameters = parameters.filter(function (property) {
michael@0 19899 return property.optional;
michael@0 19900 });
michael@0 19901 var parameterString = parameters.map(function (property) {
michael@0 19902 if (property.expand) {
michael@0 19903 return property.expand;
michael@0 19904 }
michael@0 19905 return property.name;
michael@0 19906 }).join(', ');
michael@0 19907 writer.enter('function ' + constructorName + '(' + parameterString + ') {');
michael@0 19908 if (true) {
michael@0 19909 properties.forEach(function (property) {
michael@0 19910 if (property.assert === '') {
michael@0 19911 writer.writeLn('release || assert (!(' + property.name + ' == undefined), "' + property.name + '");');
michael@0 19912 } else if (property.assert) {
michael@0 19913 writer.writeLn('release || assert (' + property.assert + '(' + property.name + '), "' + property.name + '");');
michael@0 19914 }
michael@0 19915 });
michael@0 19916 writer.writeLn('release || assert (arguments.length >= ' + (parameters.length - optionalParameters.length) + ', "' + node._name + ' not enough args.");');
michael@0 19917 }
michael@0 19918 if (node._constructorText) {
michael@0 19919 writer.writeLn(node._constructorText);
michael@0 19920 }
michael@0 19921 properties.forEach(function (property) {
michael@0 19922 if (property.expand) {
michael@0 19923 writer.writeLn('this.' + property.name + ' = ' + property.expand + ' ? [' + property.expand + '] : [];');
michael@0 19924 } else if (property.dynamic) {
michael@0 19925 writer.writeLn('this.' + property.name + ' = undefined;');
michael@0 19926 } else {
michael@0 19927 writer.writeLn('this.' + property.name + ' = ' + property.name + ';');
michael@0 19928 }
michael@0 19929 });
michael@0 19930 writer.writeLn('this.id = nextID[nextID.length - 1] += 1;');
michael@0 19931 writer.leave('}');
michael@0 19932 if (path.length > 1) {
michael@0 19933 writer.writeLn(prototypeName + ' = ' + 'extend(' + path[path.length - 2]._name + ', "' + node._name + '");');
michael@0 19934 }
michael@0 19935 writer.writeLn(prototypeName + '.nodeName = "' + node._name + '";');
michael@0 19936 writer.enter(prototypeName + '.visitInputs = function (visitor) {');
michael@0 19937 properties.forEach(function (property) {
michael@0 19938 if (property.internal) {
michael@0 19939 return;
michael@0 19940 }
michael@0 19941 var str = '';
michael@0 19942 if (property.nullable) {
michael@0 19943 str += 'this.' + property.name + ' && ';
michael@0 19944 }
michael@0 19945 if (property.array) {
michael@0 19946 str += 'visitArrayInputs(this.' + property.name + ', visitor);';
michael@0 19947 } else {
michael@0 19948 str += 'visitor(this.' + property.name + ');';
michael@0 19949 }
michael@0 19950 writer.writeLn(str);
michael@0 19951 });
michael@0 19952 writer.leave('};');
michael@0 19953 writer.writeLn('return ' + constructorName + ';');
michael@0 19954 writer.leave('})();');
michael@0 19955 writer.writeLn('');
michael@0 19956 for (var name in node) {
michael@0 19957 if (name[0] === '_' || isProperty(name)) {
michael@0 19958 continue;
michael@0 19959 }
michael@0 19960 var child = node[name];
michael@0 19961 child._name = name;
michael@0 19962 generate(child, path);
michael@0 19963 }
michael@0 19964 }
michael@0 19965 IRDefinition._name = 'Node';
michael@0 19966 generate(IRDefinition, []);
michael@0 19967 return str;
michael@0 19968 }
michael@0 19969 var nextID = [];
michael@0 19970 var Node = function () {
michael@0 19971 function nodeNode() {
michael@0 19972 true;
michael@0 19973 this.id = nextID[nextID.length - 1] += 1;
michael@0 19974 }
michael@0 19975 nodeNode.prototype.nodeName = 'Node';
michael@0 19976 nodeNode.prototype.visitInputs = function (visitor) {
michael@0 19977 };
michael@0 19978 return nodeNode;
michael@0 19979 }();
michael@0 19980 var Control = function () {
michael@0 19981 function controlNode() {
michael@0 19982 true;
michael@0 19983 this.id = nextID[nextID.length - 1] += 1;
michael@0 19984 }
michael@0 19985 controlNode.prototype = extend(Node, 'Control');
michael@0 19986 controlNode.prototype.nodeName = 'Control';
michael@0 19987 controlNode.prototype.visitInputs = function (visitor) {
michael@0 19988 };
michael@0 19989 return controlNode;
michael@0 19990 }();
michael@0 19991 var Region = function () {
michael@0 19992 function regionNode(control) {
michael@0 19993 true;
michael@0 19994 this.predecessors = control ? [
michael@0 19995 control
michael@0 19996 ] : [];
michael@0 19997 this.id = nextID[nextID.length - 1] += 1;
michael@0 19998 }
michael@0 19999 regionNode.prototype = extend(Control, 'Region');
michael@0 20000 regionNode.prototype.nodeName = 'Region';
michael@0 20001 regionNode.prototype.visitInputs = function (visitor) {
michael@0 20002 visitArrayInputs(this.predecessors, visitor);
michael@0 20003 };
michael@0 20004 return regionNode;
michael@0 20005 }();
michael@0 20006 var Start = function () {
michael@0 20007 function startNode(control) {
michael@0 20008 true;
michael@0 20009 this.control = this;
michael@0 20010 this.predecessors = control ? [
michael@0 20011 control
michael@0 20012 ] : [];
michael@0 20013 this.scope = undefined;
michael@0 20014 this.domain = undefined;
michael@0 20015 this.id = nextID[nextID.length - 1] += 1;
michael@0 20016 }
michael@0 20017 startNode.prototype = extend(Region, 'Start');
michael@0 20018 startNode.prototype.nodeName = 'Start';
michael@0 20019 startNode.prototype.visitInputs = function (visitor) {
michael@0 20020 visitArrayInputs(this.predecessors, visitor);
michael@0 20021 visitor(this.scope);
michael@0 20022 visitor(this.domain);
michael@0 20023 };
michael@0 20024 return startNode;
michael@0 20025 }();
michael@0 20026 var End = function () {
michael@0 20027 function endNode(control) {
michael@0 20028 true;
michael@0 20029 true;
michael@0 20030 this.control = control;
michael@0 20031 this.id = nextID[nextID.length - 1] += 1;
michael@0 20032 }
michael@0 20033 endNode.prototype = extend(Control, 'End');
michael@0 20034 endNode.prototype.nodeName = 'End';
michael@0 20035 endNode.prototype.visitInputs = function (visitor) {
michael@0 20036 visitor(this.control);
michael@0 20037 };
michael@0 20038 return endNode;
michael@0 20039 }();
michael@0 20040 var Stop = function () {
michael@0 20041 function stopNode(control, store, argument) {
michael@0 20042 true;
michael@0 20043 true;
michael@0 20044 true;
michael@0 20045 true;
michael@0 20046 this.control = control;
michael@0 20047 this.store = store;
michael@0 20048 this.argument = argument;
michael@0 20049 this.id = nextID[nextID.length - 1] += 1;
michael@0 20050 }
michael@0 20051 stopNode.prototype = extend(End, 'Stop');
michael@0 20052 stopNode.prototype.nodeName = 'Stop';
michael@0 20053 stopNode.prototype.visitInputs = function (visitor) {
michael@0 20054 visitor(this.control);
michael@0 20055 visitor(this.store);
michael@0 20056 visitor(this.argument);
michael@0 20057 };
michael@0 20058 return stopNode;
michael@0 20059 }();
michael@0 20060 var If = function () {
michael@0 20061 function ifNode(control, predicate) {
michael@0 20062 true;
michael@0 20063 true;
michael@0 20064 true;
michael@0 20065 this.control = control;
michael@0 20066 this.predicate = predicate;
michael@0 20067 this.id = nextID[nextID.length - 1] += 1;
michael@0 20068 }
michael@0 20069 ifNode.prototype = extend(End, 'If');
michael@0 20070 ifNode.prototype.nodeName = 'If';
michael@0 20071 ifNode.prototype.visitInputs = function (visitor) {
michael@0 20072 visitor(this.control);
michael@0 20073 visitor(this.predicate);
michael@0 20074 };
michael@0 20075 return ifNode;
michael@0 20076 }();
michael@0 20077 var Switch = function () {
michael@0 20078 function switchNode(control, determinant) {
michael@0 20079 true;
michael@0 20080 true;
michael@0 20081 true;
michael@0 20082 this.control = control;
michael@0 20083 this.determinant = determinant;
michael@0 20084 this.id = nextID[nextID.length - 1] += 1;
michael@0 20085 }
michael@0 20086 switchNode.prototype = extend(End, 'Switch');
michael@0 20087 switchNode.prototype.nodeName = 'Switch';
michael@0 20088 switchNode.prototype.visitInputs = function (visitor) {
michael@0 20089 visitor(this.control);
michael@0 20090 visitor(this.determinant);
michael@0 20091 };
michael@0 20092 return switchNode;
michael@0 20093 }();
michael@0 20094 var Jump = function () {
michael@0 20095 function jumpNode(control) {
michael@0 20096 true;
michael@0 20097 true;
michael@0 20098 this.control = control;
michael@0 20099 this.id = nextID[nextID.length - 1] += 1;
michael@0 20100 }
michael@0 20101 jumpNode.prototype = extend(End, 'Jump');
michael@0 20102 jumpNode.prototype.nodeName = 'Jump';
michael@0 20103 jumpNode.prototype.visitInputs = function (visitor) {
michael@0 20104 visitor(this.control);
michael@0 20105 };
michael@0 20106 return jumpNode;
michael@0 20107 }();
michael@0 20108 var Value = function () {
michael@0 20109 function valueNode() {
michael@0 20110 true;
michael@0 20111 this.id = nextID[nextID.length - 1] += 1;
michael@0 20112 }
michael@0 20113 valueNode.prototype = extend(Node, 'Value');
michael@0 20114 valueNode.prototype.nodeName = 'Value';
michael@0 20115 valueNode.prototype.visitInputs = function (visitor) {
michael@0 20116 };
michael@0 20117 return valueNode;
michael@0 20118 }();
michael@0 20119 var StoreDependent = function () {
michael@0 20120 function storeDependentNode(control, store) {
michael@0 20121 true;
michael@0 20122 true;
michael@0 20123 true;
michael@0 20124 this.control = control;
michael@0 20125 this.store = store;
michael@0 20126 this.loads = undefined;
michael@0 20127 this.id = nextID[nextID.length - 1] += 1;
michael@0 20128 }
michael@0 20129 storeDependentNode.prototype = extend(Value, 'StoreDependent');
michael@0 20130 storeDependentNode.prototype.nodeName = 'StoreDependent';
michael@0 20131 storeDependentNode.prototype.visitInputs = function (visitor) {
michael@0 20132 this.control && visitor(this.control);
michael@0 20133 this.store && visitor(this.store);
michael@0 20134 this.loads && visitArrayInputs(this.loads, visitor);
michael@0 20135 };
michael@0 20136 return storeDependentNode;
michael@0 20137 }();
michael@0 20138 var Call = function () {
michael@0 20139 function callNode(control, store, callee, object, args, flags) {
michael@0 20140 true;
michael@0 20141 true;
michael@0 20142 true;
michael@0 20143 true;
michael@0 20144 true;
michael@0 20145 true;
michael@0 20146 true;
michael@0 20147 this.control = control;
michael@0 20148 this.store = store;
michael@0 20149 this.loads = undefined;
michael@0 20150 this.callee = callee;
michael@0 20151 this.object = object;
michael@0 20152 this.args = args;
michael@0 20153 this.flags = flags;
michael@0 20154 this.id = nextID[nextID.length - 1] += 1;
michael@0 20155 }
michael@0 20156 callNode.prototype = extend(StoreDependent, 'Call');
michael@0 20157 callNode.prototype.nodeName = 'Call';
michael@0 20158 callNode.prototype.visitInputs = function (visitor) {
michael@0 20159 this.control && visitor(this.control);
michael@0 20160 this.store && visitor(this.store);
michael@0 20161 this.loads && visitArrayInputs(this.loads, visitor);
michael@0 20162 visitor(this.callee);
michael@0 20163 this.object && visitor(this.object);
michael@0 20164 visitArrayInputs(this.args, visitor);
michael@0 20165 };
michael@0 20166 return callNode;
michael@0 20167 }();
michael@0 20168 var CallProperty = function () {
michael@0 20169 function callPropertyNode(control, store, object, name, args, flags) {
michael@0 20170 true;
michael@0 20171 true;
michael@0 20172 true;
michael@0 20173 true;
michael@0 20174 true;
michael@0 20175 true;
michael@0 20176 true;
michael@0 20177 this.control = control;
michael@0 20178 this.store = store;
michael@0 20179 this.loads = undefined;
michael@0 20180 this.object = object;
michael@0 20181 this.name = name;
michael@0 20182 this.args = args;
michael@0 20183 this.flags = flags;
michael@0 20184 this.id = nextID[nextID.length - 1] += 1;
michael@0 20185 }
michael@0 20186 callPropertyNode.prototype = extend(StoreDependent, 'CallProperty');
michael@0 20187 callPropertyNode.prototype.nodeName = 'CallProperty';
michael@0 20188 callPropertyNode.prototype.visitInputs = function (visitor) {
michael@0 20189 this.control && visitor(this.control);
michael@0 20190 this.store && visitor(this.store);
michael@0 20191 this.loads && visitArrayInputs(this.loads, visitor);
michael@0 20192 visitor(this.object);
michael@0 20193 visitor(this.name);
michael@0 20194 visitArrayInputs(this.args, visitor);
michael@0 20195 };
michael@0 20196 return callPropertyNode;
michael@0 20197 }();
michael@0 20198 var ASCallProperty = function () {
michael@0 20199 function asCallPropertyNode(control, store, object, name, args, flags, isLex) {
michael@0 20200 true;
michael@0 20201 true;
michael@0 20202 true;
michael@0 20203 true;
michael@0 20204 true;
michael@0 20205 true;
michael@0 20206 true;
michael@0 20207 true;
michael@0 20208 this.control = control;
michael@0 20209 this.store = store;
michael@0 20210 this.loads = undefined;
michael@0 20211 this.object = object;
michael@0 20212 this.name = name;
michael@0 20213 this.args = args;
michael@0 20214 this.flags = flags;
michael@0 20215 this.isLex = isLex;
michael@0 20216 this.id = nextID[nextID.length - 1] += 1;
michael@0 20217 }
michael@0 20218 asCallPropertyNode.prototype = extend(CallProperty, 'ASCallProperty');
michael@0 20219 asCallPropertyNode.prototype.nodeName = 'ASCallProperty';
michael@0 20220 asCallPropertyNode.prototype.visitInputs = function (visitor) {
michael@0 20221 this.control && visitor(this.control);
michael@0 20222 this.store && visitor(this.store);
michael@0 20223 this.loads && visitArrayInputs(this.loads, visitor);
michael@0 20224 visitor(this.object);
michael@0 20225 visitor(this.name);
michael@0 20226 visitArrayInputs(this.args, visitor);
michael@0 20227 };
michael@0 20228 return asCallPropertyNode;
michael@0 20229 }();
michael@0 20230 var ASCallSuper = function () {
michael@0 20231 function asCallSuperNode(control, store, object, name, args, flags, scope) {
michael@0 20232 true;
michael@0 20233 true;
michael@0 20234 true;
michael@0 20235 true;
michael@0 20236 true;
michael@0 20237 true;
michael@0 20238 true;
michael@0 20239 true;
michael@0 20240 this.control = control;
michael@0 20241 this.store = store;
michael@0 20242 this.loads = undefined;
michael@0 20243 this.object = object;
michael@0 20244 this.name = name;
michael@0 20245 this.args = args;
michael@0 20246 this.flags = flags;
michael@0 20247 this.scope = scope;
michael@0 20248 this.id = nextID[nextID.length - 1] += 1;
michael@0 20249 }
michael@0 20250 asCallSuperNode.prototype = extend(CallProperty, 'ASCallSuper');
michael@0 20251 asCallSuperNode.prototype.nodeName = 'ASCallSuper';
michael@0 20252 asCallSuperNode.prototype.visitInputs = function (visitor) {
michael@0 20253 this.control && visitor(this.control);
michael@0 20254 this.store && visitor(this.store);
michael@0 20255 this.loads && visitArrayInputs(this.loads, visitor);
michael@0 20256 visitor(this.object);
michael@0 20257 visitor(this.name);
michael@0 20258 visitArrayInputs(this.args, visitor);
michael@0 20259 visitor(this.scope);
michael@0 20260 };
michael@0 20261 return asCallSuperNode;
michael@0 20262 }();
michael@0 20263 var New = function () {
michael@0 20264 function newNode(control, store, callee, args) {
michael@0 20265 true;
michael@0 20266 true;
michael@0 20267 true;
michael@0 20268 true;
michael@0 20269 true;
michael@0 20270 this.control = control;
michael@0 20271 this.store = store;
michael@0 20272 this.loads = undefined;
michael@0 20273 this.callee = callee;
michael@0 20274 this.args = args;
michael@0 20275 this.id = nextID[nextID.length - 1] += 1;
michael@0 20276 }
michael@0 20277 newNode.prototype = extend(StoreDependent, 'New');
michael@0 20278 newNode.prototype.nodeName = 'New';
michael@0 20279 newNode.prototype.visitInputs = function (visitor) {
michael@0 20280 this.control && visitor(this.control);
michael@0 20281 this.store && visitor(this.store);
michael@0 20282 this.loads && visitArrayInputs(this.loads, visitor);
michael@0 20283 visitor(this.callee);
michael@0 20284 visitArrayInputs(this.args, visitor);
michael@0 20285 };
michael@0 20286 return newNode;
michael@0 20287 }();
michael@0 20288 var ASNew = function () {
michael@0 20289 function asNewNode(control, store, callee, args) {
michael@0 20290 true;
michael@0 20291 true;
michael@0 20292 true;
michael@0 20293 true;
michael@0 20294 true;
michael@0 20295 this.control = control;
michael@0 20296 this.store = store;
michael@0 20297 this.loads = undefined;
michael@0 20298 this.callee = callee;
michael@0 20299 this.args = args;
michael@0 20300 this.id = nextID[nextID.length - 1] += 1;
michael@0 20301 }
michael@0 20302 asNewNode.prototype = extend(New, 'ASNew');
michael@0 20303 asNewNode.prototype.nodeName = 'ASNew';
michael@0 20304 asNewNode.prototype.visitInputs = function (visitor) {
michael@0 20305 this.control && visitor(this.control);
michael@0 20306 this.store && visitor(this.store);
michael@0 20307 this.loads && visitArrayInputs(this.loads, visitor);
michael@0 20308 visitor(this.callee);
michael@0 20309 visitArrayInputs(this.args, visitor);
michael@0 20310 };
michael@0 20311 return asNewNode;
michael@0 20312 }();
michael@0 20313 var GetProperty = function () {
michael@0 20314 function getPropertyNode(control, store, object, name) {
michael@0 20315 true;
michael@0 20316 true;
michael@0 20317 true;
michael@0 20318 true;
michael@0 20319 true;
michael@0 20320 this.control = control;
michael@0 20321 this.store = store;
michael@0 20322 this.loads = undefined;
michael@0 20323 this.object = object;
michael@0 20324 this.name = name;
michael@0 20325 this.id = nextID[nextID.length - 1] += 1;
michael@0 20326 }
michael@0 20327 getPropertyNode.prototype = extend(StoreDependent, 'GetProperty');
michael@0 20328 getPropertyNode.prototype.nodeName = 'GetProperty';
michael@0 20329 getPropertyNode.prototype.visitInputs = function (visitor) {
michael@0 20330 this.control && visitor(this.control);
michael@0 20331 this.store && visitor(this.store);
michael@0 20332 this.loads && visitArrayInputs(this.loads, visitor);
michael@0 20333 visitor(this.object);
michael@0 20334 visitor(this.name);
michael@0 20335 };
michael@0 20336 return getPropertyNode;
michael@0 20337 }();
michael@0 20338 var ASGetProperty = function () {
michael@0 20339 function asGetPropertyNode(control, store, object, name, flags) {
michael@0 20340 true;
michael@0 20341 true;
michael@0 20342 true;
michael@0 20343 true;
michael@0 20344 true;
michael@0 20345 true;
michael@0 20346 this.control = control;
michael@0 20347 this.store = store;
michael@0 20348 this.loads = undefined;
michael@0 20349 this.object = object;
michael@0 20350 this.name = name;
michael@0 20351 this.flags = flags;
michael@0 20352 this.id = nextID[nextID.length - 1] += 1;
michael@0 20353 }
michael@0 20354 asGetPropertyNode.prototype = extend(GetProperty, 'ASGetProperty');
michael@0 20355 asGetPropertyNode.prototype.nodeName = 'ASGetProperty';
michael@0 20356 asGetPropertyNode.prototype.visitInputs = function (visitor) {
michael@0 20357 this.control && visitor(this.control);
michael@0 20358 this.store && visitor(this.store);
michael@0 20359 this.loads && visitArrayInputs(this.loads, visitor);
michael@0 20360 visitor(this.object);
michael@0 20361 visitor(this.name);
michael@0 20362 };
michael@0 20363 return asGetPropertyNode;
michael@0 20364 }();
michael@0 20365 var ASGetDescendants = function () {
michael@0 20366 function asGetDescendantsNode(control, store, object, name) {
michael@0 20367 true;
michael@0 20368 true;
michael@0 20369 true;
michael@0 20370 true;
michael@0 20371 true;
michael@0 20372 this.control = control;
michael@0 20373 this.store = store;
michael@0 20374 this.loads = undefined;
michael@0 20375 this.object = object;
michael@0 20376 this.name = name;
michael@0 20377 this.id = nextID[nextID.length - 1] += 1;
michael@0 20378 }
michael@0 20379 asGetDescendantsNode.prototype = extend(GetProperty, 'ASGetDescendants');
michael@0 20380 asGetDescendantsNode.prototype.nodeName = 'ASGetDescendants';
michael@0 20381 asGetDescendantsNode.prototype.visitInputs = function (visitor) {
michael@0 20382 this.control && visitor(this.control);
michael@0 20383 this.store && visitor(this.store);
michael@0 20384 this.loads && visitArrayInputs(this.loads, visitor);
michael@0 20385 visitor(this.object);
michael@0 20386 visitor(this.name);
michael@0 20387 };
michael@0 20388 return asGetDescendantsNode;
michael@0 20389 }();
michael@0 20390 var ASHasProperty = function () {
michael@0 20391 function asHasPropertyNode(control, store, object, name) {
michael@0 20392 true;
michael@0 20393 true;
michael@0 20394 true;
michael@0 20395 true;
michael@0 20396 true;
michael@0 20397 this.control = control;
michael@0 20398 this.store = store;
michael@0 20399 this.loads = undefined;
michael@0 20400 this.object = object;
michael@0 20401 this.name = name;
michael@0 20402 this.id = nextID[nextID.length - 1] += 1;
michael@0 20403 }
michael@0 20404 asHasPropertyNode.prototype = extend(GetProperty, 'ASHasProperty');
michael@0 20405 asHasPropertyNode.prototype.nodeName = 'ASHasProperty';
michael@0 20406 asHasPropertyNode.prototype.visitInputs = function (visitor) {
michael@0 20407 this.control && visitor(this.control);
michael@0 20408 this.store && visitor(this.store);
michael@0 20409 this.loads && visitArrayInputs(this.loads, visitor);
michael@0 20410 visitor(this.object);
michael@0 20411 visitor(this.name);
michael@0 20412 };
michael@0 20413 return asHasPropertyNode;
michael@0 20414 }();
michael@0 20415 var ASGetSlot = function () {
michael@0 20416 function asGetSlotNode(control, store, object, name) {
michael@0 20417 true;
michael@0 20418 true;
michael@0 20419 true;
michael@0 20420 true;
michael@0 20421 true;
michael@0 20422 this.control = control;
michael@0 20423 this.store = store;
michael@0 20424 this.loads = undefined;
michael@0 20425 this.object = object;
michael@0 20426 this.name = name;
michael@0 20427 this.id = nextID[nextID.length - 1] += 1;
michael@0 20428 }
michael@0 20429 asGetSlotNode.prototype = extend(GetProperty, 'ASGetSlot');
michael@0 20430 asGetSlotNode.prototype.nodeName = 'ASGetSlot';
michael@0 20431 asGetSlotNode.prototype.visitInputs = function (visitor) {
michael@0 20432 this.control && visitor(this.control);
michael@0 20433 this.store && visitor(this.store);
michael@0 20434 this.loads && visitArrayInputs(this.loads, visitor);
michael@0 20435 visitor(this.object);
michael@0 20436 visitor(this.name);
michael@0 20437 };
michael@0 20438 return asGetSlotNode;
michael@0 20439 }();
michael@0 20440 var ASGetSuper = function () {
michael@0 20441 function asGetSuperNode(control, store, object, name, scope) {
michael@0 20442 true;
michael@0 20443 true;
michael@0 20444 true;
michael@0 20445 true;
michael@0 20446 true;
michael@0 20447 true;
michael@0 20448 this.control = control;
michael@0 20449 this.store = store;
michael@0 20450 this.loads = undefined;
michael@0 20451 this.object = object;
michael@0 20452 this.name = name;
michael@0 20453 this.scope = scope;
michael@0 20454 this.id = nextID[nextID.length - 1] += 1;
michael@0 20455 }
michael@0 20456 asGetSuperNode.prototype = extend(GetProperty, 'ASGetSuper');
michael@0 20457 asGetSuperNode.prototype.nodeName = 'ASGetSuper';
michael@0 20458 asGetSuperNode.prototype.visitInputs = function (visitor) {
michael@0 20459 this.control && visitor(this.control);
michael@0 20460 this.store && visitor(this.store);
michael@0 20461 this.loads && visitArrayInputs(this.loads, visitor);
michael@0 20462 visitor(this.object);
michael@0 20463 visitor(this.name);
michael@0 20464 visitor(this.scope);
michael@0 20465 };
michael@0 20466 return asGetSuperNode;
michael@0 20467 }();
michael@0 20468 var SetProperty = function () {
michael@0 20469 function setPropertyNode(control, store, object, name, value) {
michael@0 20470 true;
michael@0 20471 true;
michael@0 20472 true;
michael@0 20473 true;
michael@0 20474 true;
michael@0 20475 true;
michael@0 20476 this.control = control;
michael@0 20477 this.store = store;
michael@0 20478 this.loads = undefined;
michael@0 20479 this.object = object;
michael@0 20480 this.name = name;
michael@0 20481 this.value = value;
michael@0 20482 this.id = nextID[nextID.length - 1] += 1;
michael@0 20483 }
michael@0 20484 setPropertyNode.prototype = extend(StoreDependent, 'SetProperty');
michael@0 20485 setPropertyNode.prototype.nodeName = 'SetProperty';
michael@0 20486 setPropertyNode.prototype.visitInputs = function (visitor) {
michael@0 20487 this.control && visitor(this.control);
michael@0 20488 this.store && visitor(this.store);
michael@0 20489 this.loads && visitArrayInputs(this.loads, visitor);
michael@0 20490 visitor(this.object);
michael@0 20491 visitor(this.name);
michael@0 20492 visitor(this.value);
michael@0 20493 };
michael@0 20494 return setPropertyNode;
michael@0 20495 }();
michael@0 20496 var ASSetProperty = function () {
michael@0 20497 function asSetPropertyNode(control, store, object, name, value, flags) {
michael@0 20498 true;
michael@0 20499 true;
michael@0 20500 true;
michael@0 20501 true;
michael@0 20502 true;
michael@0 20503 true;
michael@0 20504 this.control = control;
michael@0 20505 this.store = store;
michael@0 20506 this.loads = undefined;
michael@0 20507 this.object = object;
michael@0 20508 this.name = name;
michael@0 20509 this.value = value;
michael@0 20510 this.flags = flags;
michael@0 20511 this.id = nextID[nextID.length - 1] += 1;
michael@0 20512 }
michael@0 20513 asSetPropertyNode.prototype = extend(SetProperty, 'ASSetProperty');
michael@0 20514 asSetPropertyNode.prototype.nodeName = 'ASSetProperty';
michael@0 20515 asSetPropertyNode.prototype.visitInputs = function (visitor) {
michael@0 20516 this.control && visitor(this.control);
michael@0 20517 this.store && visitor(this.store);
michael@0 20518 this.loads && visitArrayInputs(this.loads, visitor);
michael@0 20519 visitor(this.object);
michael@0 20520 visitor(this.name);
michael@0 20521 visitor(this.value);
michael@0 20522 };
michael@0 20523 return asSetPropertyNode;
michael@0 20524 }();
michael@0 20525 var ASSetSlot = function () {
michael@0 20526 function asSetSlotNode(control, store, object, name, value) {
michael@0 20527 true;
michael@0 20528 true;
michael@0 20529 true;
michael@0 20530 true;
michael@0 20531 true;
michael@0 20532 true;
michael@0 20533 this.control = control;
michael@0 20534 this.store = store;
michael@0 20535 this.loads = undefined;
michael@0 20536 this.object = object;
michael@0 20537 this.name = name;
michael@0 20538 this.value = value;
michael@0 20539 this.id = nextID[nextID.length - 1] += 1;
michael@0 20540 }
michael@0 20541 asSetSlotNode.prototype = extend(SetProperty, 'ASSetSlot');
michael@0 20542 asSetSlotNode.prototype.nodeName = 'ASSetSlot';
michael@0 20543 asSetSlotNode.prototype.visitInputs = function (visitor) {
michael@0 20544 this.control && visitor(this.control);
michael@0 20545 this.store && visitor(this.store);
michael@0 20546 this.loads && visitArrayInputs(this.loads, visitor);
michael@0 20547 visitor(this.object);
michael@0 20548 visitor(this.name);
michael@0 20549 visitor(this.value);
michael@0 20550 };
michael@0 20551 return asSetSlotNode;
michael@0 20552 }();
michael@0 20553 var ASSetSuper = function () {
michael@0 20554 function asSetSuperNode(control, store, object, name, value, scope) {
michael@0 20555 true;
michael@0 20556 true;
michael@0 20557 true;
michael@0 20558 true;
michael@0 20559 true;
michael@0 20560 true;
michael@0 20561 true;
michael@0 20562 this.control = control;
michael@0 20563 this.store = store;
michael@0 20564 this.loads = undefined;
michael@0 20565 this.object = object;
michael@0 20566 this.name = name;
michael@0 20567 this.value = value;
michael@0 20568 this.scope = scope;
michael@0 20569 this.id = nextID[nextID.length - 1] += 1;
michael@0 20570 }
michael@0 20571 asSetSuperNode.prototype = extend(SetProperty, 'ASSetSuper');
michael@0 20572 asSetSuperNode.prototype.nodeName = 'ASSetSuper';
michael@0 20573 asSetSuperNode.prototype.visitInputs = function (visitor) {
michael@0 20574 this.control && visitor(this.control);
michael@0 20575 this.store && visitor(this.store);
michael@0 20576 this.loads && visitArrayInputs(this.loads, visitor);
michael@0 20577 visitor(this.object);
michael@0 20578 visitor(this.name);
michael@0 20579 visitor(this.value);
michael@0 20580 visitor(this.scope);
michael@0 20581 };
michael@0 20582 return asSetSuperNode;
michael@0 20583 }();
michael@0 20584 var DeleteProperty = function () {
michael@0 20585 function deletePropertyNode(control, store, object, name) {
michael@0 20586 true;
michael@0 20587 true;
michael@0 20588 true;
michael@0 20589 true;
michael@0 20590 true;
michael@0 20591 this.control = control;
michael@0 20592 this.store = store;
michael@0 20593 this.loads = undefined;
michael@0 20594 this.object = object;
michael@0 20595 this.name = name;
michael@0 20596 this.id = nextID[nextID.length - 1] += 1;
michael@0 20597 }
michael@0 20598 deletePropertyNode.prototype = extend(StoreDependent, 'DeleteProperty');
michael@0 20599 deletePropertyNode.prototype.nodeName = 'DeleteProperty';
michael@0 20600 deletePropertyNode.prototype.visitInputs = function (visitor) {
michael@0 20601 this.control && visitor(this.control);
michael@0 20602 this.store && visitor(this.store);
michael@0 20603 this.loads && visitArrayInputs(this.loads, visitor);
michael@0 20604 visitor(this.object);
michael@0 20605 visitor(this.name);
michael@0 20606 };
michael@0 20607 return deletePropertyNode;
michael@0 20608 }();
michael@0 20609 var ASDeleteProperty = function () {
michael@0 20610 function asDeletePropertyNode(control, store, object, name) {
michael@0 20611 true;
michael@0 20612 true;
michael@0 20613 true;
michael@0 20614 true;
michael@0 20615 true;
michael@0 20616 this.control = control;
michael@0 20617 this.store = store;
michael@0 20618 this.loads = undefined;
michael@0 20619 this.object = object;
michael@0 20620 this.name = name;
michael@0 20621 this.id = nextID[nextID.length - 1] += 1;
michael@0 20622 }
michael@0 20623 asDeletePropertyNode.prototype = extend(DeleteProperty, 'ASDeleteProperty');
michael@0 20624 asDeletePropertyNode.prototype.nodeName = 'ASDeleteProperty';
michael@0 20625 asDeletePropertyNode.prototype.visitInputs = function (visitor) {
michael@0 20626 this.control && visitor(this.control);
michael@0 20627 this.store && visitor(this.store);
michael@0 20628 this.loads && visitArrayInputs(this.loads, visitor);
michael@0 20629 visitor(this.object);
michael@0 20630 visitor(this.name);
michael@0 20631 };
michael@0 20632 return asDeletePropertyNode;
michael@0 20633 }();
michael@0 20634 var ASFindProperty = function () {
michael@0 20635 function asFindPropertyNode(control, store, scope, name, domain, strict) {
michael@0 20636 true;
michael@0 20637 true;
michael@0 20638 true;
michael@0 20639 true;
michael@0 20640 true;
michael@0 20641 true;
michael@0 20642 this.control = control;
michael@0 20643 this.store = store;
michael@0 20644 this.loads = undefined;
michael@0 20645 this.scope = scope;
michael@0 20646 this.name = name;
michael@0 20647 this.domain = domain;
michael@0 20648 this.strict = strict;
michael@0 20649 this.id = nextID[nextID.length - 1] += 1;
michael@0 20650 }
michael@0 20651 asFindPropertyNode.prototype = extend(StoreDependent, 'ASFindProperty');
michael@0 20652 asFindPropertyNode.prototype.nodeName = 'ASFindProperty';
michael@0 20653 asFindPropertyNode.prototype.visitInputs = function (visitor) {
michael@0 20654 this.control && visitor(this.control);
michael@0 20655 this.store && visitor(this.store);
michael@0 20656 this.loads && visitArrayInputs(this.loads, visitor);
michael@0 20657 visitor(this.scope);
michael@0 20658 visitor(this.name);
michael@0 20659 visitor(this.domain);
michael@0 20660 };
michael@0 20661 return asFindPropertyNode;
michael@0 20662 }();
michael@0 20663 var Store = function () {
michael@0 20664 function storeNode() {
michael@0 20665 true;
michael@0 20666 this.id = nextID[nextID.length - 1] += 1;
michael@0 20667 }
michael@0 20668 storeNode.prototype = extend(Value, 'Store');
michael@0 20669 storeNode.prototype.nodeName = 'Store';
michael@0 20670 storeNode.prototype.visitInputs = function (visitor) {
michael@0 20671 };
michael@0 20672 return storeNode;
michael@0 20673 }();
michael@0 20674 var Phi = function () {
michael@0 20675 function phiNode(control, value) {
michael@0 20676 true;
michael@0 20677 true;
michael@0 20678 this.control = control;
michael@0 20679 this.args = value ? [
michael@0 20680 value
michael@0 20681 ] : [];
michael@0 20682 this.id = nextID[nextID.length - 1] += 1;
michael@0 20683 }
michael@0 20684 phiNode.prototype = extend(Value, 'Phi');
michael@0 20685 phiNode.prototype.nodeName = 'Phi';
michael@0 20686 phiNode.prototype.visitInputs = function (visitor) {
michael@0 20687 this.control && visitor(this.control);
michael@0 20688 visitArrayInputs(this.args, visitor);
michael@0 20689 };
michael@0 20690 return phiNode;
michael@0 20691 }();
michael@0 20692 var Variable = function () {
michael@0 20693 function variableNode(name) {
michael@0 20694 true;
michael@0 20695 this.name = name;
michael@0 20696 this.id = nextID[nextID.length - 1] += 1;
michael@0 20697 }
michael@0 20698 variableNode.prototype = extend(Value, 'Variable');
michael@0 20699 variableNode.prototype.nodeName = 'Variable';
michael@0 20700 variableNode.prototype.visitInputs = function (visitor) {
michael@0 20701 };
michael@0 20702 return variableNode;
michael@0 20703 }();
michael@0 20704 var Copy = function () {
michael@0 20705 function copyNode(argument) {
michael@0 20706 true;
michael@0 20707 this.argument = argument;
michael@0 20708 this.id = nextID[nextID.length - 1] += 1;
michael@0 20709 }
michael@0 20710 copyNode.prototype = extend(Value, 'Copy');
michael@0 20711 copyNode.prototype.nodeName = 'Copy';
michael@0 20712 copyNode.prototype.visitInputs = function (visitor) {
michael@0 20713 visitor(this.argument);
michael@0 20714 };
michael@0 20715 return copyNode;
michael@0 20716 }();
michael@0 20717 var Move = function () {
michael@0 20718 function moveNode(to, from) {
michael@0 20719 true;
michael@0 20720 this.to = to;
michael@0 20721 this.from = from;
michael@0 20722 this.id = nextID[nextID.length - 1] += 1;
michael@0 20723 }
michael@0 20724 moveNode.prototype = extend(Value, 'Move');
michael@0 20725 moveNode.prototype.nodeName = 'Move';
michael@0 20726 moveNode.prototype.visitInputs = function (visitor) {
michael@0 20727 visitor(this.to);
michael@0 20728 visitor(this.from);
michael@0 20729 };
michael@0 20730 return moveNode;
michael@0 20731 }();
michael@0 20732 var Projection = function () {
michael@0 20733 function projectionNode(argument, type, selector) {
michael@0 20734 true;
michael@0 20735 this.argument = argument;
michael@0 20736 this.type = type;
michael@0 20737 this.selector = selector;
michael@0 20738 this.id = nextID[nextID.length - 1] += 1;
michael@0 20739 }
michael@0 20740 projectionNode.prototype = extend(Value, 'Projection');
michael@0 20741 projectionNode.prototype.nodeName = 'Projection';
michael@0 20742 projectionNode.prototype.visitInputs = function (visitor) {
michael@0 20743 visitor(this.argument);
michael@0 20744 };
michael@0 20745 return projectionNode;
michael@0 20746 }();
michael@0 20747 var Latch = function () {
michael@0 20748 function latchNode(control, condition, left, right) {
michael@0 20749 true;
michael@0 20750 true;
michael@0 20751 this.control = control;
michael@0 20752 this.condition = condition;
michael@0 20753 this.left = left;
michael@0 20754 this.right = right;
michael@0 20755 this.id = nextID[nextID.length - 1] += 1;
michael@0 20756 }
michael@0 20757 latchNode.prototype = extend(Value, 'Latch');
michael@0 20758 latchNode.prototype.nodeName = 'Latch';
michael@0 20759 latchNode.prototype.visitInputs = function (visitor) {
michael@0 20760 this.control && visitor(this.control);
michael@0 20761 visitor(this.condition);
michael@0 20762 visitor(this.left);
michael@0 20763 visitor(this.right);
michael@0 20764 };
michael@0 20765 return latchNode;
michael@0 20766 }();
michael@0 20767 var Binary = function () {
michael@0 20768 function binaryNode(operator, left, right) {
michael@0 20769 true;
michael@0 20770 this.operator = operator;
michael@0 20771 this.left = left;
michael@0 20772 this.right = right;
michael@0 20773 this.id = nextID[nextID.length - 1] += 1;
michael@0 20774 }
michael@0 20775 binaryNode.prototype = extend(Value, 'Binary');
michael@0 20776 binaryNode.prototype.nodeName = 'Binary';
michael@0 20777 binaryNode.prototype.visitInputs = function (visitor) {
michael@0 20778 visitor(this.left);
michael@0 20779 visitor(this.right);
michael@0 20780 };
michael@0 20781 return binaryNode;
michael@0 20782 }();
michael@0 20783 var Unary = function () {
michael@0 20784 function unaryNode(operator, argument) {
michael@0 20785 true;
michael@0 20786 this.operator = operator;
michael@0 20787 this.argument = argument;
michael@0 20788 this.id = nextID[nextID.length - 1] += 1;
michael@0 20789 }
michael@0 20790 unaryNode.prototype = extend(Value, 'Unary');
michael@0 20791 unaryNode.prototype.nodeName = 'Unary';
michael@0 20792 unaryNode.prototype.visitInputs = function (visitor) {
michael@0 20793 visitor(this.argument);
michael@0 20794 };
michael@0 20795 return unaryNode;
michael@0 20796 }();
michael@0 20797 var Constant = function () {
michael@0 20798 function constantNode(value) {
michael@0 20799 true;
michael@0 20800 this.value = value;
michael@0 20801 this.id = nextID[nextID.length - 1] += 1;
michael@0 20802 }
michael@0 20803 constantNode.prototype = extend(Value, 'Constant');
michael@0 20804 constantNode.prototype.nodeName = 'Constant';
michael@0 20805 constantNode.prototype.visitInputs = function (visitor) {
michael@0 20806 };
michael@0 20807 return constantNode;
michael@0 20808 }();
michael@0 20809 var GlobalProperty = function () {
michael@0 20810 function globalPropertyNode(name) {
michael@0 20811 true;
michael@0 20812 this.name = name;
michael@0 20813 this.id = nextID[nextID.length - 1] += 1;
michael@0 20814 }
michael@0 20815 globalPropertyNode.prototype = extend(Value, 'GlobalProperty');
michael@0 20816 globalPropertyNode.prototype.nodeName = 'GlobalProperty';
michael@0 20817 globalPropertyNode.prototype.visitInputs = function (visitor) {
michael@0 20818 };
michael@0 20819 return globalPropertyNode;
michael@0 20820 }();
michael@0 20821 var This = function () {
michael@0 20822 function thisNode(control) {
michael@0 20823 true;
michael@0 20824 true;
michael@0 20825 this.control = control;
michael@0 20826 this.id = nextID[nextID.length - 1] += 1;
michael@0 20827 }
michael@0 20828 thisNode.prototype = extend(Value, 'This');
michael@0 20829 thisNode.prototype.nodeName = 'This';
michael@0 20830 thisNode.prototype.visitInputs = function (visitor) {
michael@0 20831 visitor(this.control);
michael@0 20832 };
michael@0 20833 return thisNode;
michael@0 20834 }();
michael@0 20835 var Throw = function () {
michael@0 20836 function throwNode(control, argument) {
michael@0 20837 true;
michael@0 20838 true;
michael@0 20839 this.control = control;
michael@0 20840 this.argument = argument;
michael@0 20841 this.id = nextID[nextID.length - 1] += 1;
michael@0 20842 }
michael@0 20843 throwNode.prototype = extend(Value, 'Throw');
michael@0 20844 throwNode.prototype.nodeName = 'Throw';
michael@0 20845 throwNode.prototype.visitInputs = function (visitor) {
michael@0 20846 visitor(this.control);
michael@0 20847 visitor(this.argument);
michael@0 20848 };
michael@0 20849 return throwNode;
michael@0 20850 }();
michael@0 20851 var Arguments = function () {
michael@0 20852 function argumentsNode(control) {
michael@0 20853 true;
michael@0 20854 true;
michael@0 20855 this.control = control;
michael@0 20856 this.id = nextID[nextID.length - 1] += 1;
michael@0 20857 }
michael@0 20858 argumentsNode.prototype = extend(Value, 'Arguments');
michael@0 20859 argumentsNode.prototype.nodeName = 'Arguments';
michael@0 20860 argumentsNode.prototype.visitInputs = function (visitor) {
michael@0 20861 visitor(this.control);
michael@0 20862 };
michael@0 20863 return argumentsNode;
michael@0 20864 }();
michael@0 20865 var Parameter = function () {
michael@0 20866 function parameterNode(control, index, name) {
michael@0 20867 true;
michael@0 20868 true;
michael@0 20869 this.control = control;
michael@0 20870 this.index = index;
michael@0 20871 this.name = name;
michael@0 20872 this.id = nextID[nextID.length - 1] += 1;
michael@0 20873 }
michael@0 20874 parameterNode.prototype = extend(Value, 'Parameter');
michael@0 20875 parameterNode.prototype.nodeName = 'Parameter';
michael@0 20876 parameterNode.prototype.visitInputs = function (visitor) {
michael@0 20877 visitor(this.control);
michael@0 20878 };
michael@0 20879 return parameterNode;
michael@0 20880 }();
michael@0 20881 var NewArray = function () {
michael@0 20882 function newArrayNode(control, elements) {
michael@0 20883 true;
michael@0 20884 true;
michael@0 20885 this.control = control;
michael@0 20886 this.elements = elements;
michael@0 20887 this.id = nextID[nextID.length - 1] += 1;
michael@0 20888 }
michael@0 20889 newArrayNode.prototype = extend(Value, 'NewArray');
michael@0 20890 newArrayNode.prototype.nodeName = 'NewArray';
michael@0 20891 newArrayNode.prototype.visitInputs = function (visitor) {
michael@0 20892 visitor(this.control);
michael@0 20893 visitArrayInputs(this.elements, visitor);
michael@0 20894 };
michael@0 20895 return newArrayNode;
michael@0 20896 }();
michael@0 20897 var NewObject = function () {
michael@0 20898 function newObjectNode(control, properties) {
michael@0 20899 true;
michael@0 20900 true;
michael@0 20901 this.control = control;
michael@0 20902 this.properties = properties;
michael@0 20903 this.id = nextID[nextID.length - 1] += 1;
michael@0 20904 }
michael@0 20905 newObjectNode.prototype = extend(Value, 'NewObject');
michael@0 20906 newObjectNode.prototype.nodeName = 'NewObject';
michael@0 20907 newObjectNode.prototype.visitInputs = function (visitor) {
michael@0 20908 visitor(this.control);
michael@0 20909 visitArrayInputs(this.properties, visitor);
michael@0 20910 };
michael@0 20911 return newObjectNode;
michael@0 20912 }();
michael@0 20913 var KeyValuePair = function () {
michael@0 20914 function keyValuePairNode(key, value) {
michael@0 20915 true;
michael@0 20916 this.key = key;
michael@0 20917 this.value = value;
michael@0 20918 this.id = nextID[nextID.length - 1] += 1;
michael@0 20919 }
michael@0 20920 keyValuePairNode.prototype = extend(Value, 'KeyValuePair');
michael@0 20921 keyValuePairNode.prototype.nodeName = 'KeyValuePair';
michael@0 20922 keyValuePairNode.prototype.visitInputs = function (visitor) {
michael@0 20923 visitor(this.key);
michael@0 20924 visitor(this.value);
michael@0 20925 };
michael@0 20926 return keyValuePairNode;
michael@0 20927 }();
michael@0 20928 var ASScope = function () {
michael@0 20929 function asScopeNode(parent, object, isWith) {
michael@0 20930 true;
michael@0 20931 this.parent = parent;
michael@0 20932 this.object = object;
michael@0 20933 this.isWith = isWith;
michael@0 20934 this.id = nextID[nextID.length - 1] += 1;
michael@0 20935 }
michael@0 20936 asScopeNode.prototype = extend(Value, 'ASScope');
michael@0 20937 asScopeNode.prototype.nodeName = 'ASScope';
michael@0 20938 asScopeNode.prototype.visitInputs = function (visitor) {
michael@0 20939 visitor(this.parent);
michael@0 20940 visitor(this.object);
michael@0 20941 };
michael@0 20942 return asScopeNode;
michael@0 20943 }();
michael@0 20944 var ASGlobal = function () {
michael@0 20945 function asGlobalNode(control, scope) {
michael@0 20946 true;
michael@0 20947 true;
michael@0 20948 true;
michael@0 20949 this.control = control;
michael@0 20950 this.scope = scope;
michael@0 20951 this.id = nextID[nextID.length - 1] += 1;
michael@0 20952 }
michael@0 20953 asGlobalNode.prototype = extend(Value, 'ASGlobal');
michael@0 20954 asGlobalNode.prototype.nodeName = 'ASGlobal';
michael@0 20955 asGlobalNode.prototype.visitInputs = function (visitor) {
michael@0 20956 this.control && visitor(this.control);
michael@0 20957 visitor(this.scope);
michael@0 20958 };
michael@0 20959 return asGlobalNode;
michael@0 20960 }();
michael@0 20961 var ASNewActivation = function () {
michael@0 20962 function asNewActivationNode(methodInfo) {
michael@0 20963 true;
michael@0 20964 this.methodInfo = methodInfo;
michael@0 20965 this.id = nextID[nextID.length - 1] += 1;
michael@0 20966 }
michael@0 20967 asNewActivationNode.prototype = extend(Value, 'ASNewActivation');
michael@0 20968 asNewActivationNode.prototype.nodeName = 'ASNewActivation';
michael@0 20969 asNewActivationNode.prototype.visitInputs = function (visitor) {
michael@0 20970 };
michael@0 20971 return asNewActivationNode;
michael@0 20972 }();
michael@0 20973 var ASMultiname = function () {
michael@0 20974 function asMultinameNode(namespaces, name, flags) {
michael@0 20975 true;
michael@0 20976 this.namespaces = namespaces;
michael@0 20977 this.name = name;
michael@0 20978 this.flags = flags;
michael@0 20979 this.id = nextID[nextID.length - 1] += 1;
michael@0 20980 }
michael@0 20981 asMultinameNode.prototype = extend(Value, 'ASMultiname');
michael@0 20982 asMultinameNode.prototype.nodeName = 'ASMultiname';
michael@0 20983 asMultinameNode.prototype.visitInputs = function (visitor) {
michael@0 20984 visitor(this.namespaces);
michael@0 20985 visitor(this.name);
michael@0 20986 };
michael@0 20987 return asMultinameNode;
michael@0 20988 }();
michael@0 20989 function node() {
michael@0 20990 this.id = nextID[nextID.length - 1] += 1;
michael@0 20991 }
michael@0 20992 Node.startNumbering = function () {
michael@0 20993 nextID.push(0);
michael@0 20994 };
michael@0 20995 Node.stopNumbering = function () {
michael@0 20996 nextID.pop();
michael@0 20997 };
michael@0 20998 Node.prototype.toString = function (brief) {
michael@0 20999 if (brief) {
michael@0 21000 return nameOf(this);
michael@0 21001 }
michael@0 21002 var inputs = [];
michael@0 21003 this.visitInputs(function (input) {
michael@0 21004 inputs.push(nameOf(input));
michael@0 21005 });
michael@0 21006 var str = nameOf(this) + ' = ' + this.nodeName.toUpperCase();
michael@0 21007 if (this.toStringDetails) {
michael@0 21008 str += ' ' + this.toStringDetails();
michael@0 21009 }
michael@0 21010 if (inputs.length) {
michael@0 21011 str += ' ' + inputs.join(', ');
michael@0 21012 }
michael@0 21013 return str;
michael@0 21014 };
michael@0 21015 Node.prototype.visitInputsNoConstants = function visitInputs(visitor) {
michael@0 21016 this.visitInputs(function (node) {
michael@0 21017 if (isConstant(node)) {
michael@0 21018 return;
michael@0 21019 }
michael@0 21020 visitor(node);
michael@0 21021 });
michael@0 21022 };
michael@0 21023 Node.prototype.replaceInput = function (oldInput, newInput) {
michael@0 21024 var count = 0;
michael@0 21025 for (var k in this) {
michael@0 21026 var v = this[k];
michael@0 21027 if (v instanceof Node) {
michael@0 21028 if (v === oldInput) {
michael@0 21029 this[k] = newInput;
michael@0 21030 count++;
michael@0 21031 }
michael@0 21032 }
michael@0 21033 if (v instanceof Array) {
michael@0 21034 count += v.replace(oldInput, newInput);
michael@0 21035 }
michael@0 21036 }
michael@0 21037 return count;
michael@0 21038 };
michael@0 21039 Projection.Type = {
michael@0 21040 CASE: 'case',
michael@0 21041 TRUE: 'true',
michael@0 21042 FALSE: 'false',
michael@0 21043 STORE: 'store',
michael@0 21044 SCOPE: 'scope'
michael@0 21045 };
michael@0 21046 Projection.prototype.project = function () {
michael@0 21047 return this.argument;
michael@0 21048 };
michael@0 21049 Phi.prototype.seal = function seal() {
michael@0 21050 this.sealed = true;
michael@0 21051 };
michael@0 21052 Phi.prototype.pushValue = function pushValue(x) {
michael@0 21053 true;
michael@0 21054 true;
michael@0 21055 this.args.push(x);
michael@0 21056 };
michael@0 21057 KeyValuePair.prototype.mustFloat = true;
michael@0 21058 ASMultiname.prototype.mustFloat = true;
michael@0 21059 ASMultiname.prototype.isAttribute = function () {
michael@0 21060 return this.flags & 1;
michael@0 21061 };
michael@0 21062 var Flags = {
michael@0 21063 INDEXED: 1,
michael@0 21064 RESOLVED: 2,
michael@0 21065 PRISTINE: 4,
michael@0 21066 IS_METHOD: 8
michael@0 21067 };
michael@0 21068 var Operator = function () {
michael@0 21069 var map = {};
michael@0 21070 function operator(name, evaluate, binary) {
michael@0 21071 this.name = name;
michael@0 21072 this.binary = binary;
michael@0 21073 this.evaluate = evaluate;
michael@0 21074 map[name] = this;
michael@0 21075 }
michael@0 21076 operator.ADD = new operator('+', function (l, r) {
michael@0 21077 return l + r;
michael@0 21078 }, true);
michael@0 21079 operator.SUB = new operator('-', function (l, r) {
michael@0 21080 return l - r;
michael@0 21081 }, true);
michael@0 21082 operator.MUL = new operator('*', function (l, r) {
michael@0 21083 return l * r;
michael@0 21084 }, true);
michael@0 21085 operator.DIV = new operator('/', function (l, r) {
michael@0 21086 return l / r;
michael@0 21087 }, true);
michael@0 21088 operator.MOD = new operator('%', function (l, r) {
michael@0 21089 return l % r;
michael@0 21090 }, true);
michael@0 21091 operator.AND = new operator('&', function (l, r) {
michael@0 21092 return l & r;
michael@0 21093 }, true);
michael@0 21094 operator.OR = new operator('|', function (l, r) {
michael@0 21095 return l | r;
michael@0 21096 }, true);
michael@0 21097 operator.XOR = new operator('^', function (l, r) {
michael@0 21098 return l ^ r;
michael@0 21099 }, true);
michael@0 21100 operator.LSH = new operator('<<', function (l, r) {
michael@0 21101 return l << r;
michael@0 21102 }, true);
michael@0 21103 operator.RSH = new operator('>>', function (l, r) {
michael@0 21104 return l >> r;
michael@0 21105 }, true);
michael@0 21106 operator.URSH = new operator('>>>', function (l, r) {
michael@0 21107 return l >>> r;
michael@0 21108 }, true);
michael@0 21109 operator.SEQ = new operator('===', function (l, r) {
michael@0 21110 return l === r;
michael@0 21111 }, true);
michael@0 21112 operator.SNE = new operator('!==', function (l, r) {
michael@0 21113 return l !== r;
michael@0 21114 }, true);
michael@0 21115 operator.EQ = new operator('==', function (l, r) {
michael@0 21116 return l == r;
michael@0 21117 }, true);
michael@0 21118 operator.NE = new operator('!=', function (l, r) {
michael@0 21119 return l != r;
michael@0 21120 }, true);
michael@0 21121 operator.LE = new operator('<=', function (l, r) {
michael@0 21122 return l <= r;
michael@0 21123 }, true);
michael@0 21124 operator.GT = new operator('>', function (l, r) {
michael@0 21125 return l > r;
michael@0 21126 }, true);
michael@0 21127 operator.LT = new operator('<', function (l, r) {
michael@0 21128 return l < r;
michael@0 21129 }, true);
michael@0 21130 operator.GE = new operator('>=', function (l, r) {
michael@0 21131 return l >= r;
michael@0 21132 }, true);
michael@0 21133 operator.BITWISE_NOT = new operator('~', function (a) {
michael@0 21134 return ~a;
michael@0 21135 }, false);
michael@0 21136 operator.PLUS = new operator('+', function (a) {
michael@0 21137 return +a;
michael@0 21138 }, false);
michael@0 21139 operator.NEG = new operator('-', function (a) {
michael@0 21140 return -a;
michael@0 21141 }, false);
michael@0 21142 operator.TYPE_OF = new operator('typeof', function (a) {
michael@0 21143 return typeof a;
michael@0 21144 }, false);
michael@0 21145 operator.TRUE = new operator('!!', function (a) {
michael@0 21146 return !(!a);
michael@0 21147 }, false);
michael@0 21148 operator.FALSE = new operator('!', function (a) {
michael@0 21149 return !a;
michael@0 21150 }, false);
michael@0 21151 operator.AS_ADD = new operator('+', function (l, r) {
michael@0 21152 if (typeof l === 'string' || typeof r === 'string') {
michael@0 21153 return String(l) + String(r);
michael@0 21154 }
michael@0 21155 return l + r;
michael@0 21156 }, true);
michael@0 21157 function linkOpposites(a, b) {
michael@0 21158 a.not = b;
michael@0 21159 b.not = a;
michael@0 21160 }
michael@0 21161 linkOpposites(operator.SEQ, operator.SNE);
michael@0 21162 linkOpposites(operator.EQ, operator.NE);
michael@0 21163 linkOpposites(operator.TRUE, operator.FALSE);
michael@0 21164 operator.fromName = function fromName(name) {
michael@0 21165 return map[name];
michael@0 21166 };
michael@0 21167 operator.prototype.isBinary = function isBinary() {
michael@0 21168 return this.binary;
michael@0 21169 };
michael@0 21170 operator.prototype.toString = function toString() {
michael@0 21171 return this.name;
michael@0 21172 };
michael@0 21173 return operator;
michael@0 21174 }();
michael@0 21175 function extend(c, name) {
michael@0 21176 true;
michael@0 21177 return Object.create(c.prototype, {
michael@0 21178 nodeName: {
michael@0 21179 value: name
michael@0 21180 }
michael@0 21181 });
michael@0 21182 }
michael@0 21183 function nameOf(o) {
michael@0 21184 var useColors = false;
michael@0 21185 var result;
michael@0 21186 if (o instanceof Constant) {
michael@0 21187 if (o.value instanceof Multiname) {
michael@0 21188 return o.value.name;
michael@0 21189 }
michael@0 21190 return o.value;
michael@0 21191 } else if (o instanceof Variable) {
michael@0 21192 return o.name;
michael@0 21193 } else if (o instanceof Phi) {
michael@0 21194 return result = '|' + o.id + '|', useColors ? PURPLE + result + ENDC : result;
michael@0 21195 } else if (o instanceof Control) {
michael@0 21196 return result = '{' + o.id + '}', useColors ? RED + result + ENDC : result;
michael@0 21197 } else if (o instanceof Projection) {
michael@0 21198 if (o.type === Projection.Type.STORE) {
michael@0 21199 return result = '[' + o.id + '->' + o.argument.id + ']', useColors ? YELLOW + result + ENDC : result;
michael@0 21200 }
michael@0 21201 return result = '(' + o.id + ')', useColors ? GREEN + result + ENDC : result;
michael@0 21202 } else if (o instanceof Value) {
michael@0 21203 return result = '(' + o.id + ')', useColors ? GREEN + result + ENDC : result;
michael@0 21204 } else if (o instanceof Node) {
michael@0 21205 return o.id;
michael@0 21206 }
michael@0 21207 unexpected(o + ' ' + typeof o);
michael@0 21208 }
michael@0 21209 function toID(node) {
michael@0 21210 return node.id;
michael@0 21211 }
michael@0 21212 function visitArrayInputs(array, visitor) {
michael@0 21213 for (var i = 0; i < array.length; i++) {
michael@0 21214 visitor(array[i]);
michael@0 21215 }
michael@0 21216 }
michael@0 21217 function visitNothing() {
michael@0 21218 }
michael@0 21219 function isNotPhi(phi) {
michael@0 21220 return !isPhi(phi);
michael@0 21221 }
michael@0 21222 function isPhi(phi) {
michael@0 21223 return phi instanceof Phi;
michael@0 21224 }
michael@0 21225 function isScope(scope) {
michael@0 21226 return isPhi(scope) || scope instanceof ASScope || isProjection(scope, Projection.Type.SCOPE);
michael@0 21227 }
michael@0 21228 function isMultinameConstant(node) {
michael@0 21229 return node instanceof Constant && node.value instanceof Multiname;
michael@0 21230 }
michael@0 21231 function isMultiname(name) {
michael@0 21232 return isMultinameConstant(name) || name instanceof ASMultiname;
michael@0 21233 }
michael@0 21234 function isStore(store) {
michael@0 21235 return isPhi(store) || store instanceof Store || isProjection(store, Projection.Type.STORE);
michael@0 21236 }
michael@0 21237 function isConstant(constant) {
michael@0 21238 return constant instanceof Constant;
michael@0 21239 }
michael@0 21240 function isBoolean(boolean) {
michael@0 21241 return boolean === true || boolean === false;
michael@0 21242 }
michael@0 21243 function isInteger(integer) {
michael@0 21244 return integer | 0 === integer;
michael@0 21245 }
michael@0 21246 function isArray(array) {
michael@0 21247 return array instanceof Array;
michael@0 21248 }
michael@0 21249 function isControlOrNull(control) {
michael@0 21250 return isControl(control) || control === null;
michael@0 21251 }
michael@0 21252 function isStoreOrNull(store) {
michael@0 21253 return isStore(store) || store === null;
michael@0 21254 }
michael@0 21255 function isControl(control) {
michael@0 21256 return control instanceof Control;
michael@0 21257 }
michael@0 21258 function isValueOrNull(value) {
michael@0 21259 return isValue(value) || value === null;
michael@0 21260 }
michael@0 21261 function isValue(value) {
michael@0 21262 return value instanceof Value;
michael@0 21263 }
michael@0 21264 function isProjection(node, type) {
michael@0 21265 return node instanceof Projection && (!type || node.type === type);
michael@0 21266 }
michael@0 21267 var Null = new Constant(null);
michael@0 21268 var Undefined = new Constant(undefined);
michael@0 21269 Undefined.toString = function () {
michael@0 21270 return '_';
michael@0 21271 };
michael@0 21272 var Block = function () {
michael@0 21273 function block(id, start, end) {
michael@0 21274 if (start) {
michael@0 21275 true;
michael@0 21276 }
michael@0 21277 this.region = start;
michael@0 21278 this.id = id;
michael@0 21279 this.successors = [];
michael@0 21280 this.predecessors = [];
michael@0 21281 this.nodes = [
michael@0 21282 start,
michael@0 21283 end
michael@0 21284 ];
michael@0 21285 }
michael@0 21286 block.prototype.pushSuccessorAt = function pushSuccessor(successor, index, pushPredecessor) {
michael@0 21287 true;
michael@0 21288 true;
michael@0 21289 this.successors[index] = successor;
michael@0 21290 if (pushPredecessor) {
michael@0 21291 successor.pushPredecessor(this);
michael@0 21292 }
michael@0 21293 };
michael@0 21294 block.prototype.pushSuccessor = function pushSuccessor(successor, pushPredecessor) {
michael@0 21295 true;
michael@0 21296 this.successors.push(successor);
michael@0 21297 if (pushPredecessor) {
michael@0 21298 successor.pushPredecessor(this);
michael@0 21299 }
michael@0 21300 };
michael@0 21301 block.prototype.pushPredecessor = function pushPredecessor(predecessor) {
michael@0 21302 true;
michael@0 21303 this.predecessors.push(predecessor);
michael@0 21304 };
michael@0 21305 block.prototype.visitNodes = function (fn) {
michael@0 21306 var nodes = this.nodes;
michael@0 21307 for (var i = 0, j = nodes.length; i < j; i++) {
michael@0 21308 fn(nodes[i]);
michael@0 21309 }
michael@0 21310 };
michael@0 21311 block.prototype.visitSuccessors = function (fn) {
michael@0 21312 var successors = this.successors;
michael@0 21313 for (var i = 0, j = successors.length; i < j; i++) {
michael@0 21314 fn(successors[i]);
michael@0 21315 }
michael@0 21316 };
michael@0 21317 block.prototype.visitPredecessors = function (fn) {
michael@0 21318 var predecessors = this.predecessors;
michael@0 21319 for (var i = 0, j = predecessors.length; i < j; i++) {
michael@0 21320 fn(predecessors[i]);
michael@0 21321 }
michael@0 21322 };
michael@0 21323 block.prototype.append = function (node) {
michael@0 21324 true;
michael@0 21325 true;
michael@0 21326 true;
michael@0 21327 true;
michael@0 21328 if (node.mustFloat) {
michael@0 21329 return;
michael@0 21330 }
michael@0 21331 this.nodes.splice(this.nodes.length - 1, 0, node);
michael@0 21332 };
michael@0 21333 block.prototype.toString = function () {
michael@0 21334 return 'B' + this.id + (this.name ? ' (' + this.name + ')' : '');
michael@0 21335 };
michael@0 21336 block.prototype.trace = function (writer) {
michael@0 21337 writer.writeLn(this);
michael@0 21338 };
michael@0 21339 return block;
michael@0 21340 }();
michael@0 21341 var DFG = function () {
michael@0 21342 function constructor(exit) {
michael@0 21343 this.exit = exit;
michael@0 21344 }
michael@0 21345 constructor.prototype.buildCFG = function () {
michael@0 21346 return CFG.fromDFG(this);
michael@0 21347 };
michael@0 21348 function preOrderDepthFirstSearch(root, visitChildren, pre) {
michael@0 21349 var visited = [];
michael@0 21350 var worklist = [
michael@0 21351 root
michael@0 21352 ];
michael@0 21353 var push = worklist.push.bind(worklist);
michael@0 21354 var node;
michael@0 21355 while (node = worklist.pop()) {
michael@0 21356 if (visited[node.id] === 1) {
michael@0 21357 continue;
michael@0 21358 }
michael@0 21359 visited[node.id] = 1;
michael@0 21360 pre(node);
michael@0 21361 worklist.push(node);
michael@0 21362 visitChildren(node, push);
michael@0 21363 }
michael@0 21364 }
michael@0 21365 function postOrderDepthFirstSearch(root, visitChildren, post) {
michael@0 21366 var ONE_TIME = 1, MANY_TIMES = 2;
michael@0 21367 var visited = [];
michael@0 21368 var worklist = [
michael@0 21369 root
michael@0 21370 ];
michael@0 21371 function visitChild(child) {
michael@0 21372 if (!visited[child.id]) {
michael@0 21373 worklist.push(child);
michael@0 21374 }
michael@0 21375 }
michael@0 21376 var node;
michael@0 21377 while (node = worklist.top()) {
michael@0 21378 if (visited[node.id]) {
michael@0 21379 if (visited[node.id] === ONE_TIME) {
michael@0 21380 visited[node.id] = MANY_TIMES;
michael@0 21381 post(node);
michael@0 21382 }
michael@0 21383 worklist.pop();
michael@0 21384 continue;
michael@0 21385 }
michael@0 21386 visited[node.id] = ONE_TIME;
michael@0 21387 visitChildren(node, visitChild);
michael@0 21388 }
michael@0 21389 }
michael@0 21390 constructor.prototype.forEachInPreOrderDepthFirstSearch = function forEachInPreOrderDepthFirstSearch(visitor) {
michael@0 21391 var visited = new Array(1024);
michael@0 21392 var worklist = [
michael@0 21393 this.exit
michael@0 21394 ];
michael@0 21395 function push(node) {
michael@0 21396 if (isConstant(node)) {
michael@0 21397 return;
michael@0 21398 }
michael@0 21399 true;
michael@0 21400 worklist.push(node);
michael@0 21401 }
michael@0 21402 var node;
michael@0 21403 while (node = worklist.pop()) {
michael@0 21404 if (visited[node.id]) {
michael@0 21405 continue;
michael@0 21406 }
michael@0 21407 visited[node.id] = 1;
michael@0 21408 visitor && visitor(node);
michael@0 21409 worklist.push(node);
michael@0 21410 node.visitInputs(push);
michael@0 21411 }
michael@0 21412 };
michael@0 21413 constructor.prototype.forEach = function forEach(visitor, postOrder) {
michael@0 21414 var search = postOrder ? postOrderDepthFirstSearch : preOrderDepthFirstSearch;
michael@0 21415 search(this.exit, function (node, v) {
michael@0 21416 node.visitInputsNoConstants(v);
michael@0 21417 }, visitor);
michael@0 21418 };
michael@0 21419 constructor.prototype.traceMetrics = function (writer) {
michael@0 21420 var counter = new metrics.Counter(true);
michael@0 21421 preOrderDepthFirstSearch(this.exit, function (node, visitor) {
michael@0 21422 node.visitInputsNoConstants(visitor);
michael@0 21423 }, function (node) {
michael@0 21424 counter.count(node.nodeName);
michael@0 21425 });
michael@0 21426 counter.trace(writer);
michael@0 21427 };
michael@0 21428 constructor.prototype.trace = function (writer) {
michael@0 21429 var nodes = [];
michael@0 21430 var visited = {};
michael@0 21431 function colorOf(node) {
michael@0 21432 if (node instanceof Control) {
michael@0 21433 return 'yellow';
michael@0 21434 } else if (node instanceof Phi) {
michael@0 21435 return 'purple';
michael@0 21436 } else if (node instanceof Value) {
michael@0 21437 return 'green';
michael@0 21438 }
michael@0 21439 return 'white';
michael@0 21440 }
michael@0 21441 var blocks = [];
michael@0 21442 function followProjection(node) {
michael@0 21443 return node instanceof Projection ? node.project() : node;
michael@0 21444 }
michael@0 21445 function next(node) {
michael@0 21446 node = followProjection(node);
michael@0 21447 if (!visited[node.id]) {
michael@0 21448 visited[node.id] = true;
michael@0 21449 if (node.block) {
michael@0 21450 blocks.push(node.block);
michael@0 21451 }
michael@0 21452 nodes.push(node);
michael@0 21453 node.visitInputsNoConstants(next);
michael@0 21454 }
michael@0 21455 }
michael@0 21456 next(this.exit);
michael@0 21457 writer.writeLn('');
michael@0 21458 writer.enter('digraph DFG {');
michael@0 21459 writer.writeLn('graph [bgcolor = gray10];');
michael@0 21460 writer.writeLn('edge [color = white];');
michael@0 21461 writer.writeLn('node [shape = box, fontname = Consolas, fontsize = 11, color = white, fontcolor = white];');
michael@0 21462 writer.writeLn('rankdir = BT;');
michael@0 21463 function writeNode(node) {
michael@0 21464 writer.writeLn('N' + node.id + ' [label = "' + node.toString() + '", color = "' + colorOf(node) + '"];');
michael@0 21465 }
michael@0 21466 function defineNode(node) {
michael@0 21467 writer.writeLn('N' + node.id + ';');
michael@0 21468 }
michael@0 21469 blocks.forEach(function (block) {
michael@0 21470 writer.enter('subgraph cluster' + block.nodes[0].id + ' { bgcolor = gray20;');
michael@0 21471 block.visitNodes(function (node) {
michael@0 21472 defineNode(followProjection(node));
michael@0 21473 });
michael@0 21474 writer.leave('}');
michael@0 21475 });
michael@0 21476 nodes.forEach(writeNode);
michael@0 21477 nodes.forEach(function (node) {
michael@0 21478 node.visitInputsNoConstants(function (input) {
michael@0 21479 input = followProjection(input);
michael@0 21480 writer.writeLn('N' + node.id + ' -> ' + 'N' + input.id + ' [color=' + colorOf(input) + '];');
michael@0 21481 });
michael@0 21482 });
michael@0 21483 writer.leave('}');
michael@0 21484 writer.writeLn('');
michael@0 21485 };
michael@0 21486 return constructor;
michael@0 21487 }();
michael@0 21488 var CFG = function () {
michael@0 21489 function constructor() {
michael@0 21490 this.nextBlockID = 0;
michael@0 21491 this.blocks = [];
michael@0 21492 this.exit;
michael@0 21493 this.root;
michael@0 21494 }
michael@0 21495 constructor.fromDFG = function fromDFG(dfg) {
michael@0 21496 var cfg = new CFG();
michael@0 21497 true;
michael@0 21498 cfg.dfg = dfg;
michael@0 21499 var visited = [];
michael@0 21500 function buildEnd(end) {
michael@0 21501 if (end instanceof Projection) {
michael@0 21502 end = end.project();
michael@0 21503 }
michael@0 21504 true;
michael@0 21505 if (visited[end.id]) {
michael@0 21506 return;
michael@0 21507 }
michael@0 21508 visited[end.id] = true;
michael@0 21509 var start = end.control;
michael@0 21510 if (!(start instanceof Region)) {
michael@0 21511 start = end.control = new Region(start);
michael@0 21512 }
michael@0 21513 var block = start.block = cfg.buildBlock(start, end);
michael@0 21514 if (start instanceof Start) {
michael@0 21515 cfg.root = block;
michael@0 21516 }
michael@0 21517 for (var i = 0; i < start.predecessors.length; i++) {
michael@0 21518 var c = start.predecessors[i];
michael@0 21519 var d;
michael@0 21520 var trueProjection = false;
michael@0 21521 if (c instanceof Projection) {
michael@0 21522 d = c.project();
michael@0 21523 trueProjection = c.type === Projection.Type.TRUE;
michael@0 21524 } else {
michael@0 21525 d = c;
michael@0 21526 }
michael@0 21527 if (d instanceof Region) {
michael@0 21528 d = new Jump(c);
michael@0 21529 d = new Projection(d, Projection.Type.TRUE);
michael@0 21530 start.predecessors[i] = d;
michael@0 21531 d = d.project();
michael@0 21532 trueProjection = true;
michael@0 21533 }
michael@0 21534 buildEnd(d);
michael@0 21535 var controlBlock = d.control.block;
michael@0 21536 if (d instanceof Switch) {
michael@0 21537 true;
michael@0 21538 controlBlock.pushSuccessorAt(block, c.selector.value, true);
michael@0 21539 } else if (trueProjection && controlBlock.successors.length > 0) {
michael@0 21540 controlBlock.pushSuccessor(block, true);
michael@0 21541 controlBlock.hasFlippedSuccessors = true;
michael@0 21542 } else {
michael@0 21543 controlBlock.pushSuccessor(block, true);
michael@0 21544 }
michael@0 21545 }
michael@0 21546 }
michael@0 21547 buildEnd(dfg.exit);
michael@0 21548 cfg.splitCriticalEdges();
michael@0 21549 cfg.exit = dfg.exit.control.block;
michael@0 21550 cfg.computeDominators(true);
michael@0 21551 return cfg;
michael@0 21552 };
michael@0 21553 constructor.prototype.buildRootAndExit = function buildRootAndExit() {
michael@0 21554 true;
michael@0 21555 if (this.blocks[0].predecessors.length > 0) {
michael@0 21556 this.root = new Block(this.nextBlockID++);
michael@0 21557 this.blocks.push(this.root);
michael@0 21558 this.root.pushSuccessor(this.blocks[0], true);
michael@0 21559 } else {
michael@0 21560 this.root = this.blocks[0];
michael@0 21561 }
michael@0 21562 var exitBlocks = [];
michael@0 21563 for (var i = 0; i < this.blocks.length; i++) {
michael@0 21564 var block = this.blocks[i];
michael@0 21565 if (block.successors.length === 0) {
michael@0 21566 exitBlocks.push(block);
michael@0 21567 }
michael@0 21568 }
michael@0 21569 if (exitBlocks.length === 0) {
michael@0 21570 unexpected('Must have an exit block.');
michael@0 21571 } else if (exitBlocks.length === 1 && exitBlocks[0] !== this.root) {
michael@0 21572 this.exit = exitBlocks[0];
michael@0 21573 } else {
michael@0 21574 this.exit = new Block(this.nextBlockID++);
michael@0 21575 this.blocks.push(this.exit);
michael@0 21576 for (var i = 0; i < exitBlocks.length; i++) {
michael@0 21577 exitBlocks[i].pushSuccessor(this.exit, true);
michael@0 21578 }
michael@0 21579 }
michael@0 21580 true;
michael@0 21581 true;
michael@0 21582 };
michael@0 21583 constructor.prototype.fromString = function (list, rootName) {
michael@0 21584 var cfg = this;
michael@0 21585 var names = cfg.blockNames || (cfg.blockNames = {});
michael@0 21586 var blocks = cfg.blocks;
michael@0 21587 var sets = list.replace(/\ /g, '').split(',');
michael@0 21588 sets.forEach(function (set) {
michael@0 21589 var edgeList = set.split('->');
michael@0 21590 var last = null;
michael@0 21591 for (var i = 0; i < edgeList.length; i++) {
michael@0 21592 var next = edgeList[i];
michael@0 21593 if (last) {
michael@0 21594 buildEdge(last, next);
michael@0 21595 } else {
michael@0 21596 buildBlock(next);
michael@0 21597 }
michael@0 21598 last = next;
michael@0 21599 }
michael@0 21600 });
michael@0 21601 function buildBlock(name) {
michael@0 21602 var block = names[name];
michael@0 21603 if (block) {
michael@0 21604 return block;
michael@0 21605 }
michael@0 21606 names[name] = block = new Block(cfg.nextBlockID++);
michael@0 21607 block.name = name;
michael@0 21608 blocks.push(block);
michael@0 21609 return block;
michael@0 21610 }
michael@0 21611 function buildEdge(from, to) {
michael@0 21612 buildBlock(from).pushSuccessor(buildBlock(to), true);
michael@0 21613 }
michael@0 21614 true;
michael@0 21615 this.root = names[rootName];
michael@0 21616 };
michael@0 21617 constructor.prototype.buildBlock = function (start, end) {
michael@0 21618 var block = new Block(this.nextBlockID++, start, end);
michael@0 21619 this.blocks.push(block);
michael@0 21620 return block;
michael@0 21621 };
michael@0 21622 constructor.prototype.createBlockSet = function () {
michael@0 21623 if (!this.setConstructor) {
michael@0 21624 this.setConstructor = BitSetFunctor(this.blocks.length);
michael@0 21625 }
michael@0 21626 return new this.setConstructor();
michael@0 21627 };
michael@0 21628 constructor.prototype.computeReversePostOrder = function computeReversePostOrder() {
michael@0 21629 if (this.order) {
michael@0 21630 return this.order;
michael@0 21631 }
michael@0 21632 var order = this.order = [];
michael@0 21633 this.depthFirstSearch(null, order.push.bind(order));
michael@0 21634 order.reverse();
michael@0 21635 for (var i = 0; i < order.length; i++) {
michael@0 21636 order[i].rpo = i;
michael@0 21637 }
michael@0 21638 return order;
michael@0 21639 };
michael@0 21640 constructor.prototype.depthFirstSearch = function depthFirstSearch(preFn, postFn) {
michael@0 21641 var visited = this.createBlockSet();
michael@0 21642 function visit(node) {
michael@0 21643 visited.set(node.id);
michael@0 21644 if (preFn)
michael@0 21645 preFn(node);
michael@0 21646 var successors = node.successors;
michael@0 21647 for (var i = 0, j = successors.length; i < j; i++) {
michael@0 21648 var s = successors[i];
michael@0 21649 if (!visited.get(s.id)) {
michael@0 21650 visit(s);
michael@0 21651 }
michael@0 21652 }
michael@0 21653 if (postFn)
michael@0 21654 postFn(node);
michael@0 21655 }
michael@0 21656 visit(this.root);
michael@0 21657 };
michael@0 21658 constructor.prototype.computeDominators = function (apply) {
michael@0 21659 true;
michael@0 21660 var dom = new Int32Array(this.blocks.length);
michael@0 21661 for (var i = 0; i < dom.length; i++) {
michael@0 21662 dom[i] = -1;
michael@0 21663 }
michael@0 21664 var map = this.createBlockSet();
michael@0 21665 function computeCommonDominator(a, b) {
michael@0 21666 map.clearAll();
michael@0 21667 while (a >= 0) {
michael@0 21668 map.set(a);
michael@0 21669 a = dom[a];
michael@0 21670 }
michael@0 21671 while (b >= 0 && !map.get(b)) {
michael@0 21672 b = dom[b];
michael@0 21673 }
michael@0 21674 return b;
michael@0 21675 }
michael@0 21676 function computeDominator(blockID, parentID) {
michael@0 21677 if (dom[blockID] < 0) {
michael@0 21678 dom[blockID] = parentID;
michael@0 21679 } else {
michael@0 21680 dom[blockID] = computeCommonDominator(dom[blockID], parentID);
michael@0 21681 }
michael@0 21682 }
michael@0 21683 this.depthFirstSearch(function visit(block) {
michael@0 21684 var s = block.successors;
michael@0 21685 for (var i = 0, j = s.length; i < j; i++) {
michael@0 21686 computeDominator(s[i].id, block.id);
michael@0 21687 }
michael@0 21688 });
michael@0 21689 if (apply) {
michael@0 21690 for (var i = 0, j = this.blocks.length; i < j; i++) {
michael@0 21691 this.blocks[i].dominator = this.blocks[dom[i]];
michael@0 21692 }
michael@0 21693 function computeDominatorDepth(block) {
michael@0 21694 var dominatorDepth;
michael@0 21695 if (block.dominatorDepth !== undefined) {
michael@0 21696 return block.dominatorDepth;
michael@0 21697 } else if (!block.dominator) {
michael@0 21698 dominatorDepth = 0;
michael@0 21699 } else {
michael@0 21700 dominatorDepth = computeDominatorDepth(block.dominator) + 1;
michael@0 21701 }
michael@0 21702 return block.dominatorDepth = dominatorDepth;
michael@0 21703 }
michael@0 21704 for (var i = 0, j = this.blocks.length; i < j; i++) {
michael@0 21705 computeDominatorDepth(this.blocks[i]);
michael@0 21706 }
michael@0 21707 }
michael@0 21708 return dom;
michael@0 21709 };
michael@0 21710 constructor.prototype.computeLoops = function computeLoops() {
michael@0 21711 var active = this.createBlockSet();
michael@0 21712 var visited = this.createBlockSet();
michael@0 21713 var nextLoop = 0;
michael@0 21714 function makeLoopHeader(block) {
michael@0 21715 if (!block.isLoopHeader) {
michael@0 21716 block.isLoopHeader = true;
michael@0 21717 block.loops = 1 << nextLoop;
michael@0 21718 nextLoop += 1;
michael@0 21719 }
michael@0 21720 }
michael@0 21721 function visit(block) {
michael@0 21722 if (visited.get(block.id)) {
michael@0 21723 if (active.get(block.id)) {
michael@0 21724 makeLoopHeader(block);
michael@0 21725 }
michael@0 21726 return block.loops;
michael@0 21727 }
michael@0 21728 visited.set(block.id);
michael@0 21729 active.set(block.id);
michael@0 21730 var loops = 0;
michael@0 21731 for (var i = 0, j = block.successors.length; i < j; i++) {
michael@0 21732 loops |= visit(block.successors[i]);
michael@0 21733 }
michael@0 21734 if (block.isLoopHeader) {
michael@0 21735 loops &= ~block.loops;
michael@0 21736 }
michael@0 21737 block.loops = loops;
michael@0 21738 active.clear(block.id);
michael@0 21739 return loops;
michael@0 21740 }
michael@0 21741 var loop = visit(this.root);
michael@0 21742 };
michael@0 21743 function followProjection(node) {
michael@0 21744 return node instanceof Projection ? node.project() : node;
michael@0 21745 }
michael@0 21746 var Uses = function () {
michael@0 21747 function constructor() {
michael@0 21748 this.entries = [];
michael@0 21749 }
michael@0 21750 constructor.prototype.addUse = function addUse(def, use) {
michael@0 21751 var entry = this.entries[def.id];
michael@0 21752 if (!entry) {
michael@0 21753 entry = this.entries[def.id] = {
michael@0 21754 def: def,
michael@0 21755 uses: []
michael@0 21756 };
michael@0 21757 }
michael@0 21758 entry.uses.pushUnique(use);
michael@0 21759 };
michael@0 21760 constructor.prototype.trace = function (writer) {
michael@0 21761 writer.enter('> Uses');
michael@0 21762 this.entries.forEach(function (entry) {
michael@0 21763 writer.writeLn(entry.def.id + ' -> [' + entry.uses.map(toID).join(', ') + '] ' + entry.def);
michael@0 21764 });
michael@0 21765 writer.leave('<');
michael@0 21766 };
michael@0 21767 constructor.prototype.replace = function (def, value) {
michael@0 21768 var entry = this.entries[def.id];
michael@0 21769 if (entry.uses.length === 0) {
michael@0 21770 return false;
michael@0 21771 }
michael@0 21772 var count = 0;
michael@0 21773 entry.uses.forEach(function (use) {
michael@0 21774 count += use.replaceInput(def, value);
michael@0 21775 });
michael@0 21776 true;
michael@0 21777 entry.uses = [];
michael@0 21778 return true;
michael@0 21779 };
michael@0 21780 function updateUses(def, value) {
michael@0 21781 debug && writer.writeLn('Update ' + def + ' with ' + value);
michael@0 21782 var entry = useEntries[def.id];
michael@0 21783 if (entry.uses.length === 0) {
michael@0 21784 return false;
michael@0 21785 }
michael@0 21786 debug && writer.writeLn('Replacing: ' + def.id + ' in [' + entry.uses.map(toID).join(', ') + '] with ' + value.id);
michael@0 21787 var count = 0;
michael@0 21788 entry.uses.forEach(function (use) {
michael@0 21789 count += use.replaceInput(def, value);
michael@0 21790 });
michael@0 21791 true;
michael@0 21792 entry.uses = [];
michael@0 21793 return true;
michael@0 21794 }
michael@0 21795 return constructor;
michael@0 21796 }();
michael@0 21797 constructor.prototype.computeUses = function computeUses() {
michael@0 21798 Timer.start('computeUses');
michael@0 21799 var writer = debug && new IndentingWriter();
michael@0 21800 debug && writer.enter('> Compute Uses');
michael@0 21801 var dfg = this.dfg;
michael@0 21802 var uses = new Uses();
michael@0 21803 dfg.forEachInPreOrderDepthFirstSearch(function (use) {
michael@0 21804 use.visitInputs(function (def) {
michael@0 21805 uses.addUse(def, use);
michael@0 21806 });
michael@0 21807 });
michael@0 21808 if (debug) {
michael@0 21809 writer.enter('> Uses');
michael@0 21810 uses.entries.forEach(function (entry) {
michael@0 21811 writer.writeLn(entry.def.id + ' -> [' + entry.uses.map(toID).join(', ') + '] ' + entry.def);
michael@0 21812 });
michael@0 21813 writer.leave('<');
michael@0 21814 writer.leave('<');
michael@0 21815 }
michael@0 21816 Timer.stop();
michael@0 21817 return uses;
michael@0 21818 };
michael@0 21819 constructor.prototype.verify = function verify() {
michael@0 21820 var writer = debug && new IndentingWriter();
michael@0 21821 debug && writer.enter('> Verify');
michael@0 21822 var order = this.computeReversePostOrder();
michael@0 21823 order.forEach(function (block) {
michael@0 21824 if (block.phis) {
michael@0 21825 block.phis.forEach(function (phi) {
michael@0 21826 true;
michael@0 21827 true;
michael@0 21828 });
michael@0 21829 }
michael@0 21830 });
michael@0 21831 debug && writer.leave('<');
michael@0 21832 };
michael@0 21833 constructor.prototype.optimizePhis = function optimizePhis() {
michael@0 21834 var writer = debug && new IndentingWriter();
michael@0 21835 debug && writer.enter('> Optimize Phis');
michael@0 21836 var phis = [];
michael@0 21837 var useEntries = this.computeUses().entries;
michael@0 21838 useEntries.forEach(function (entry) {
michael@0 21839 if (isPhi(entry.def)) {
michael@0 21840 phis.push(entry.def);
michael@0 21841 }
michael@0 21842 });
michael@0 21843 debug && writer.writeLn('Trying to optimize ' + phis.length + ' phis.');
michael@0 21844 function updateUses(def, value) {
michael@0 21845 debug && writer.writeLn('Update ' + def + ' with ' + value);
michael@0 21846 var entry = useEntries[def.id];
michael@0 21847 if (entry.uses.length === 0) {
michael@0 21848 return false;
michael@0 21849 }
michael@0 21850 debug && writer.writeLn('Replacing: ' + def.id + ' in [' + entry.uses.map(toID).join(', ') + '] with ' + value.id);
michael@0 21851 var count = 0;
michael@0 21852 var entryUses = entry.uses;
michael@0 21853 for (var i = 0, j = entryUses.length; i < j; i++) {
michael@0 21854 count += entryUses[i].replaceInput(def, value);
michael@0 21855 }
michael@0 21856 true;
michael@0 21857 entry.uses = [];
michael@0 21858 return true;
michael@0 21859 }
michael@0 21860 function simplify(phi, args) {
michael@0 21861 args = args.unique();
michael@0 21862 if (args.length === 1) {
michael@0 21863 return args[0];
michael@0 21864 } else {
michael@0 21865 if (args.length === 2) {
michael@0 21866 if (args[0] === phi) {
michael@0 21867 return args[1];
michael@0 21868 } else if (args[1] === phi) {
michael@0 21869 return args[0];
michael@0 21870 }
michael@0 21871 return phi;
michael@0 21872 }
michael@0 21873 }
michael@0 21874 return phi;
michael@0 21875 }
michael@0 21876 var count = 0;
michael@0 21877 var iterations = 0;
michael@0 21878 var changed = true;
michael@0 21879 while (changed) {
michael@0 21880 iterations++;
michael@0 21881 changed = false;
michael@0 21882 phis.forEach(function (phi) {
michael@0 21883 var value = simplify(phi, phi.args);
michael@0 21884 if (value !== phi) {
michael@0 21885 if (updateUses(phi, value)) {
michael@0 21886 changed = true;
michael@0 21887 count++;
michael@0 21888 }
michael@0 21889 }
michael@0 21890 });
michael@0 21891 }
michael@0 21892 if (debug) {
michael@0 21893 writer.writeLn('Simplified ' + count + ' phis, in ' + iterations + ' iterations.');
michael@0 21894 writer.leave('<');
michael@0 21895 }
michael@0 21896 };
michael@0 21897 constructor.prototype.splitCriticalEdges = function splitCriticalEdges() {
michael@0 21898 var writer = debug && new IndentingWriter();
michael@0 21899 var blocks = this.blocks;
michael@0 21900 var criticalEdges = [];
michael@0 21901 debug && writer.enter('> Splitting Critical Edges');
michael@0 21902 for (var i = 0; i < blocks.length; i++) {
michael@0 21903 var successors = blocks[i].successors;
michael@0 21904 if (successors.length > 1) {
michael@0 21905 for (var j = 0; j < successors.length; j++) {
michael@0 21906 if (successors[j].predecessors.length > 1) {
michael@0 21907 criticalEdges.push({
michael@0 21908 from: blocks[i],
michael@0 21909 to: successors[j]
michael@0 21910 });
michael@0 21911 }
michael@0 21912 }
michael@0 21913 }
michael@0 21914 }
michael@0 21915 var criticalEdgeCount = criticalEdges.length;
michael@0 21916 if (criticalEdgeCount && debug) {
michael@0 21917 writer.writeLn('Splitting: ' + criticalEdgeCount);
michael@0 21918 this.trace(writer);
michael@0 21919 }
michael@0 21920 var edge;
michael@0 21921 while (edge = criticalEdges.pop()) {
michael@0 21922 var fromIndex = edge.from.successors.indexOf(edge.to);
michael@0 21923 var toIndex = edge.to.predecessors.indexOf(edge.from);
michael@0 21924 true;
michael@0 21925 debug && writer.writeLn('Splitting critical edge: ' + edge.from + ' -> ' + edge.to);
michael@0 21926 var toBlock = edge.to;
michael@0 21927 var toRegion = toBlock.region;
michael@0 21928 var control = toRegion.predecessors[toIndex];
michael@0 21929 var region = new Region(control);
michael@0 21930 var jump = new Jump(region);
michael@0 21931 var block = this.buildBlock(region, jump);
michael@0 21932 toRegion.predecessors[toIndex] = new Projection(jump, Projection.Type.TRUE);
michael@0 21933 var fromBlock = edge.from;
michael@0 21934 fromBlock.successors[fromIndex] = block;
michael@0 21935 block.pushPredecessor(fromBlock);
michael@0 21936 block.pushSuccessor(toBlock);
michael@0 21937 toBlock.predecessors[toIndex] = block;
michael@0 21938 }
michael@0 21939 if (criticalEdgeCount && debug) {
michael@0 21940 this.trace(writer);
michael@0 21941 }
michael@0 21942 if (criticalEdgeCount && !true) {
michael@0 21943 true;
michael@0 21944 }
michael@0 21945 debug && writer.leave('<');
michael@0 21946 return criticalEdgeCount;
michael@0 21947 };
michael@0 21948 constructor.prototype.allocateVariables = function allocateVariables() {
michael@0 21949 var writer = debug && new IndentingWriter();
michael@0 21950 debug && writer.enter('> Allocating Virtual Registers');
michael@0 21951 var order = this.computeReversePostOrder();
michael@0 21952 function allocate(node) {
michael@0 21953 if (isProjection(node, Projection.Type.STORE)) {
michael@0 21954 return;
michael@0 21955 }
michael@0 21956 if (node instanceof SetProperty) {
michael@0 21957 return;
michael@0 21958 }
michael@0 21959 if (node instanceof Value) {
michael@0 21960 node.variable = new Variable('v' + node.id);
michael@0 21961 debug && writer.writeLn('Allocated: ' + node.variable + ' to ' + node);
michael@0 21962 }
michael@0 21963 }
michael@0 21964 order.forEach(function (block) {
michael@0 21965 block.nodes.forEach(allocate);
michael@0 21966 if (block.phis) {
michael@0 21967 block.phis.forEach(allocate);
michael@0 21968 }
michael@0 21969 });
michael@0 21970 var blockMoves = [];
michael@0 21971 for (var i = 0; i < order.length; i++) {
michael@0 21972 var block = order[i];
michael@0 21973 var phis = block.phis;
michael@0 21974 var predecessors = block.predecessors;
michael@0 21975 if (phis) {
michael@0 21976 for (var j = 0; j < phis.length; j++) {
michael@0 21977 var phi = phis[j];
michael@0 21978 debug && writer.writeLn('Emitting moves for: ' + phi);
michael@0 21979 var arguments = phi.args;
michael@0 21980 true;
michael@0 21981 for (var k = 0; k < predecessors.length; k++) {
michael@0 21982 var predecessor = predecessors[k];
michael@0 21983 var argument = arguments[k];
michael@0 21984 if (argument.abstract || isProjection(argument, Projection.Type.STORE)) {
michael@0 21985 continue;
michael@0 21986 }
michael@0 21987 var moves = blockMoves[predecessor.id] || (blockMoves[predecessor.id] = []);
michael@0 21988 argument = argument.variable || argument;
michael@0 21989 if (phi.variable !== argument) {
michael@0 21990 moves.push(new Move(phi.variable, argument));
michael@0 21991 }
michael@0 21992 }
michael@0 21993 }
michael@0 21994 }
michael@0 21995 }
michael@0 21996 var blocks = this.blocks;
michael@0 21997 blockMoves.forEach(function (moves, blockID) {
michael@0 21998 var block = blocks[blockID];
michael@0 21999 var temporary = 0;
michael@0 22000 debug && writer.writeLn(block + ' Moves: ' + moves);
michael@0 22001 while (moves.length) {
michael@0 22002 for (var i = 0; i < moves.length; i++) {
michael@0 22003 var move = moves[i];
michael@0 22004 for (var j = 0; j < moves.length; j++) {
michael@0 22005 if (i === j) {
michael@0 22006 continue;
michael@0 22007 }
michael@0 22008 if (moves[j].from === move.to) {
michael@0 22009 move = null;
michael@0 22010 break;
michael@0 22011 }
michael@0 22012 }
michael@0 22013 if (move) {
michael@0 22014 moves.splice(i--, 1);
michael@0 22015 block.append(move);
michael@0 22016 }
michael@0 22017 }
michael@0 22018 if (moves.length) {
michael@0 22019 debug && writer.writeLn('Breaking Cycle');
michael@0 22020 var move = moves[0];
michael@0 22021 var temp = new Variable('t' + temporary++);
michael@0 22022 blocks[blockID].append(new Move(temp, move.to));
michael@0 22023 for (var i = 1; i < moves.length; i++) {
michael@0 22024 if (moves[i].from === move.to) {
michael@0 22025 moves[i].from = temp;
michael@0 22026 }
michael@0 22027 }
michael@0 22028 }
michael@0 22029 }
michael@0 22030 });
michael@0 22031 debug && writer.leave('<');
michael@0 22032 };
michael@0 22033 constructor.prototype.scheduleEarly = function scheduleEarly() {
michael@0 22034 var debugScheduler = false;
michael@0 22035 var writer = debugScheduler && new IndentingWriter();
michael@0 22036 debugScheduler && writer.enter('> Schedule Early');
michael@0 22037 var cfg = this;
michael@0 22038 var dfg = this.dfg;
michael@0 22039 var scheduled = [];
michael@0 22040 var roots = [];
michael@0 22041 dfg.forEachInPreOrderDepthFirstSearch(function (node) {
michael@0 22042 if (node instanceof Region || node instanceof Jump) {
michael@0 22043 return;
michael@0 22044 }
michael@0 22045 if (node.control) {
michael@0 22046 roots.push(node);
michael@0 22047 }
michael@0 22048 if (isPhi(node)) {
michael@0 22049 node.args.forEach(function (input) {
michael@0 22050 if (shouldFloat(input)) {
michael@0 22051 input.mustNotFloat = true;
michael@0 22052 }
michael@0 22053 });
michael@0 22054 }
michael@0 22055 }, true);
michael@0 22056 if (debugScheduler) {
michael@0 22057 roots.forEach(function (node) {
michael@0 22058 print('Root: ' + node);
michael@0 22059 });
michael@0 22060 }
michael@0 22061 for (var i = 0; i < roots.length; i++) {
michael@0 22062 var root = roots[i];
michael@0 22063 if (root instanceof Phi) {
michael@0 22064 var block = root.control.block;
michael@0 22065 (block.phis || (block.phis = [])).push(root);
michael@0 22066 }
michael@0 22067 if (root.control) {
michael@0 22068 schedule(root);
michael@0 22069 }
michael@0 22070 }
michael@0 22071 function isScheduled(node) {
michael@0 22072 return scheduled[node.id];
michael@0 22073 }
michael@0 22074 function shouldFloat(node) {
michael@0 22075 if (node.mustNotFloat || node.shouldNotFloat) {
michael@0 22076 return false;
michael@0 22077 }
michael@0 22078 if (node.mustFloat || node.shouldFloat) {
michael@0 22079 return true;
michael@0 22080 }
michael@0 22081 if (node instanceof Parameter || node instanceof This || node instanceof Arguments) {
michael@0 22082 return true;
michael@0 22083 }
michael@0 22084 return node instanceof Binary || node instanceof Unary || node instanceof Parameter;
michael@0 22085 }
michael@0 22086 function append(node) {
michael@0 22087 true;
michael@0 22088 scheduled[node.id] = true;
michael@0 22089 true;
michael@0 22090 if (shouldFloat(node)) {
michael@0 22091 } else {
michael@0 22092 node.control.block.append(node);
michael@0 22093 }
michael@0 22094 }
michael@0 22095 function scheduleIn(node, region) {
michael@0 22096 true;
michael@0 22097 true;
michael@0 22098 true;
michael@0 22099 debugScheduler && writer.writeLn('Scheduled: ' + node + ' in ' + region);
michael@0 22100 node.control = region;
michael@0 22101 append(node);
michael@0 22102 }
michael@0 22103 function schedule(node) {
michael@0 22104 debugScheduler && writer.enter('> Schedule: ' + node);
michael@0 22105 var inputs = [];
michael@0 22106 node.visitInputs(function (input) {
michael@0 22107 if (isConstant(input)) {
michael@0 22108 {
michael@0 22109 return;
michael@0 22110 }
michael@0 22111 }
michael@0 22112 if (isValue(input)) {
michael@0 22113 inputs.push(followProjection(input));
michael@0 22114 }
michael@0 22115 });
michael@0 22116 debugScheduler && writer.writeLn('Inputs: [' + inputs.map(toID) + '], length: ' + inputs.length);
michael@0 22117 for (var i = 0; i < inputs.length; i++) {
michael@0 22118 var input = inputs[i];
michael@0 22119 if (isNotPhi(input) && !isScheduled(input)) {
michael@0 22120 schedule(input);
michael@0 22121 }
michael@0 22122 }
michael@0 22123 if (node.control) {
michael@0 22124 if (node instanceof End || node instanceof Phi || node instanceof Start || isScheduled(node)) {
michael@0 22125 } else {
michael@0 22126 append(node);
michael@0 22127 }
michael@0 22128 } else {
michael@0 22129 if (inputs.length) {
michael@0 22130 var x = inputs[0].control;
michael@0 22131 for (var i = 1; i < inputs.length; i++) {
michael@0 22132 var y = inputs[i].control;
michael@0 22133 if (x.block.dominatorDepth < y.block.dominatorDepth) {
michael@0 22134 x = y;
michael@0 22135 }
michael@0 22136 }
michael@0 22137 scheduleIn(node, x);
michael@0 22138 } else {
michael@0 22139 scheduleIn(node, cfg.root.region);
michael@0 22140 }
michael@0 22141 }
michael@0 22142 debugScheduler && writer.leave('<');
michael@0 22143 }
michael@0 22144 debugScheduler && writer.leave('<');
michael@0 22145 roots.forEach(function (node) {
michael@0 22146 node = followProjection(node);
michael@0 22147 if (node === dfg.start || node instanceof Region) {
michael@0 22148 return;
michael@0 22149 }
michael@0 22150 true;
michael@0 22151 });
michael@0 22152 };
michael@0 22153 constructor.prototype.trace = function (writer) {
michael@0 22154 var visited = [];
michael@0 22155 var blocks = [];
michael@0 22156 function next(block) {
michael@0 22157 if (!visited[block.id]) {
michael@0 22158 visited[block.id] = true;
michael@0 22159 blocks.push(block);
michael@0 22160 block.visitSuccessors(next);
michael@0 22161 }
michael@0 22162 }
michael@0 22163 var root = this.root;
michael@0 22164 var exit = this.exit;
michael@0 22165 next(root);
michael@0 22166 function colorOf(block) {
michael@0 22167 return 'black';
michael@0 22168 }
michael@0 22169 function styleOf(block) {
michael@0 22170 return 'filled';
michael@0 22171 }
michael@0 22172 function shapeOf(block) {
michael@0 22173 true;
michael@0 22174 if (block === root) {
michael@0 22175 return 'house';
michael@0 22176 } else if (block === exit) {
michael@0 22177 return 'invhouse';
michael@0 22178 }
michael@0 22179 return 'box';
michael@0 22180 }
michael@0 22181 writer.writeLn('');
michael@0 22182 writer.enter('digraph CFG {');
michael@0 22183 writer.writeLn('graph [bgcolor = gray10];');
michael@0 22184 writer.writeLn('edge [fontname = Consolas, fontsize = 11, color = white, fontcolor = white];');
michael@0 22185 writer.writeLn('node [shape = box, fontname = Consolas, fontsize = 11, color = white, fontcolor = white, style = filled];');
michael@0 22186 writer.writeLn('rankdir = TB;');
michael@0 22187 blocks.forEach(function (block) {
michael@0 22188 var loopInfo = '';
michael@0 22189 var blockInfo = '';
michael@0 22190 var intervalInfo = '';
michael@0 22191 if (block.loops !== undefined) {
michael@0 22192 }
michael@0 22193 if (block.name !== undefined) {
michael@0 22194 blockInfo += ' ' + block.name;
michael@0 22195 }
michael@0 22196 if (block.rpo !== undefined) {
michael@0 22197 blockInfo += ' O: ' + block.rpo;
michael@0 22198 }
michael@0 22199 writer.writeLn('B' + block.id + ' [label = "B' + block.id + blockInfo + loopInfo + '", fillcolor = "' + colorOf(block) + '", shape=' + shapeOf(block) + ', style=' + styleOf(block) + '];');
michael@0 22200 });
michael@0 22201 blocks.forEach(function (block) {
michael@0 22202 block.visitSuccessors(function (successor) {
michael@0 22203 writer.writeLn('B' + block.id + ' -> ' + 'B' + successor.id);
michael@0 22204 });
michael@0 22205 if (block.dominator) {
michael@0 22206 writer.writeLn('B' + block.id + ' -> ' + 'B' + block.dominator.id + ' [color = orange];');
michael@0 22207 }
michael@0 22208 if (block.follow) {
michael@0 22209 writer.writeLn('B' + block.id + ' -> ' + 'B' + block.follow.id + ' [color = purple];');
michael@0 22210 }
michael@0 22211 });
michael@0 22212 writer.leave('}');
michael@0 22213 writer.writeLn('');
michael@0 22214 };
michael@0 22215 return constructor;
michael@0 22216 }();
michael@0 22217 var PeepholeOptimizer = function () {
michael@0 22218 function constructor() {
michael@0 22219 }
michael@0 22220 function foldUnary(node, truthy) {
michael@0 22221 true;
michael@0 22222 if (isConstant(node.argument)) {
michael@0 22223 return new Constant(node.operator.evaluate(node.argument.value));
michael@0 22224 }
michael@0 22225 if (truthy) {
michael@0 22226 var argument = fold(node.argument, true);
michael@0 22227 if (node.operator === Operator.TRUE) {
michael@0 22228 return argument;
michael@0 22229 }
michael@0 22230 if (argument instanceof Unary) {
michael@0 22231 if (node.operator === Operator.FALSE && argument.operator === Operator.FALSE) {
michael@0 22232 return argument.argument;
michael@0 22233 }
michael@0 22234 } else {
michael@0 22235 return new Unary(node.operator, argument);
michael@0 22236 }
michael@0 22237 }
michael@0 22238 return node;
michael@0 22239 }
michael@0 22240 function foldBinary(node, truthy) {
michael@0 22241 true;
michael@0 22242 if (isConstant(node.left) && isConstant(node.right)) {
michael@0 22243 return new Constant(node.operator.evaluate(node.left.value, node.right.value));
michael@0 22244 }
michael@0 22245 return node;
michael@0 22246 }
michael@0 22247 function fold(node, truthy) {
michael@0 22248 if (node instanceof Unary) {
michael@0 22249 return foldUnary(node, truthy);
michael@0 22250 } else if (node instanceof Binary) {
michael@0 22251 return foldBinary(node, truthy);
michael@0 22252 }
michael@0 22253 return node;
michael@0 22254 }
michael@0 22255 constructor.prototype.tryFold = fold;
michael@0 22256 return constructor;
michael@0 22257 }();
michael@0 22258 exports.isConstant = isConstant;
michael@0 22259 exports.Block = Block;
michael@0 22260 exports.Node = Node;
michael@0 22261 exports.Start = Start;
michael@0 22262 exports.Null = Null;
michael@0 22263 exports.Undefined = Undefined;
michael@0 22264 exports.This = This;
michael@0 22265 exports.Throw = Throw;
michael@0 22266 exports.Arguments = Arguments;
michael@0 22267 exports.ASGlobal = ASGlobal;
michael@0 22268 exports.Projection = Projection;
michael@0 22269 exports.Region = Region;
michael@0 22270 exports.Latch = Latch;
michael@0 22271 exports.Binary = Binary;
michael@0 22272 exports.Unary = Unary;
michael@0 22273 exports.Constant = Constant;
michael@0 22274 exports.ASFindProperty = ASFindProperty;
michael@0 22275 exports.GlobalProperty = GlobalProperty;
michael@0 22276 exports.GetProperty = GetProperty;
michael@0 22277 exports.SetProperty = SetProperty;
michael@0 22278 exports.CallProperty = CallProperty;
michael@0 22279 exports.ASCallProperty = ASCallProperty;
michael@0 22280 exports.ASCallSuper = ASCallSuper;
michael@0 22281 exports.ASGetProperty = ASGetProperty;
michael@0 22282 exports.ASGetSuper = ASGetSuper;
michael@0 22283 exports.ASHasProperty = ASHasProperty;
michael@0 22284 exports.ASDeleteProperty = ASDeleteProperty;
michael@0 22285 exports.ASGetDescendants = ASGetDescendants;
michael@0 22286 exports.ASSetProperty = ASSetProperty;
michael@0 22287 exports.ASSetSuper = ASSetSuper;
michael@0 22288 exports.ASGetSlot = ASGetSlot;
michael@0 22289 exports.ASSetSlot = ASSetSlot;
michael@0 22290 exports.Call = Call;
michael@0 22291 exports.ASNew = ASNew;
michael@0 22292 exports.Phi = Phi;
michael@0 22293 exports.Stop = Stop;
michael@0 22294 exports.If = If;
michael@0 22295 exports.Switch = Switch;
michael@0 22296 exports.End = End;
michael@0 22297 exports.Jump = Jump;
michael@0 22298 exports.ASScope = ASScope;
michael@0 22299 exports.Operator = Operator;
michael@0 22300 exports.Variable = Variable;
michael@0 22301 exports.Move = Move;
michael@0 22302 exports.Copy = Copy;
michael@0 22303 exports.Parameter = Parameter;
michael@0 22304 exports.NewArray = NewArray;
michael@0 22305 exports.NewObject = NewObject;
michael@0 22306 exports.ASNewActivation = ASNewActivation;
michael@0 22307 exports.KeyValuePair = KeyValuePair;
michael@0 22308 exports.ASMultiname = ASMultiname;
michael@0 22309 exports.DFG = DFG;
michael@0 22310 exports.CFG = CFG;
michael@0 22311 exports.Flags = Flags;
michael@0 22312 exports.PeepholeOptimizer = PeepholeOptimizer;
michael@0 22313 }(typeof exports === 'undefined' ? IR = {} : exports));
michael@0 22314 var c4Options = systemOptions.register(new OptionSet('C4 Options'));
michael@0 22315 var enableC4 = c4Options.register(new Option('c4', 'c4', 'boolean', false, 'Enable the C4 compiler.'));
michael@0 22316 var c4TraceLevel = c4Options.register(new Option('tc4', 'tc4', 'number', 0, 'Compiler Trace Level'));
michael@0 22317 var enableRegisterAllocator = c4Options.register(new Option('ra', 'ra', 'boolean', false, 'Enable register allocator.'));
michael@0 22318 var getPublicQualifiedName = Multiname.getPublicQualifiedName;
michael@0 22319 var createName = function createName(namespaces, name) {
michael@0 22320 if (isNumeric(name) || isObject(name)) {
michael@0 22321 return name;
michael@0 22322 }
michael@0 22323 return new Multiname(namespaces, name);
michael@0 22324 };
michael@0 22325 (function (exports) {
michael@0 22326 var Node = IR.Node;
michael@0 22327 var Start = IR.Start;
michael@0 22328 var Null = IR.Null;
michael@0 22329 var Undefined = IR.Undefined;
michael@0 22330 var This = IR.This;
michael@0 22331 var Projection = IR.Projection;
michael@0 22332 var Region = IR.Region;
michael@0 22333 var Binary = IR.Binary;
michael@0 22334 var Unary = IR.Unary;
michael@0 22335 var Constant = IR.Constant;
michael@0 22336 var Call = IR.Call;
michael@0 22337 var Phi = IR.Phi;
michael@0 22338 var Stop = IR.Stop;
michael@0 22339 var Operator = IR.Operator;
michael@0 22340 var Parameter = IR.Parameter;
michael@0 22341 var NewArray = IR.NewArray;
michael@0 22342 var NewObject = IR.NewObject;
michael@0 22343 var KeyValuePair = IR.KeyValuePair;
michael@0 22344 var isConstant = IR.isConstant;
michael@0 22345 var DFG = IR.DFG;
michael@0 22346 var CFG = IR.CFG;
michael@0 22347 var writer = new IndentingWriter();
michael@0 22348 var peepholeOptimizer = new IR.PeepholeOptimizer();
michael@0 22349 var USE_TYPE_OF_DEFAULT_ARGUMENT_CHECKING = false;
michael@0 22350 var State = function () {
michael@0 22351 var nextID = 0;
michael@0 22352 function constructor(index) {
michael@0 22353 this.id = nextID += 1;
michael@0 22354 this.index = index;
michael@0 22355 this.local = [];
michael@0 22356 this.stack = [];
michael@0 22357 this.scope = [];
michael@0 22358 this.store = Undefined;
michael@0 22359 this.loads = [];
michael@0 22360 this.saved = Undefined;
michael@0 22361 }
michael@0 22362 constructor.prototype.clone = function clone(index) {
michael@0 22363 var s = new State();
michael@0 22364 s.index = index !== undefined ? index : this.index;
michael@0 22365 s.local = this.local.slice(0);
michael@0 22366 s.stack = this.stack.slice(0);
michael@0 22367 s.scope = this.scope.slice(0);
michael@0 22368 s.loads = this.loads.slice(0);
michael@0 22369 s.saved = this.saved;
michael@0 22370 s.store = this.store;
michael@0 22371 return s;
michael@0 22372 };
michael@0 22373 constructor.prototype.matches = function matches(other) {
michael@0 22374 return this.stack.length === other.stack.length && this.scope.length === other.scope.length && this.local.length === other.local.length;
michael@0 22375 };
michael@0 22376 constructor.prototype.makeLoopPhis = function makeLoopPhis(control) {
michael@0 22377 var s = new State();
michael@0 22378 true;
michael@0 22379 function makePhi(x) {
michael@0 22380 var phi = new Phi(control, x);
michael@0 22381 phi.isLoop = true;
michael@0 22382 return phi;
michael@0 22383 }
michael@0 22384 s.index = this.index;
michael@0 22385 s.local = this.local.map(makePhi);
michael@0 22386 s.stack = this.stack.map(makePhi);
michael@0 22387 s.scope = this.scope.map(makePhi);
michael@0 22388 s.loads = this.loads.slice(0);
michael@0 22389 s.saved = this.saved;
michael@0 22390 s.store = makePhi(this.store);
michael@0 22391 return s;
michael@0 22392 };
michael@0 22393 constructor.prototype.optimize = function optimize() {
michael@0 22394 function optimize(x) {
michael@0 22395 if (x instanceof Phi && !x.isLoop) {
michael@0 22396 var args = x.args.unique();
michael@0 22397 if (args.length === 1) {
michael@0 22398 x.seal();
michael@0 22399 Counter.count('Builder: OptimizedPhi');
michael@0 22400 return args[0];
michael@0 22401 }
michael@0 22402 }
michael@0 22403 return x;
michael@0 22404 }
michael@0 22405 this.local = this.local.map(optimize);
michael@0 22406 this.stack = this.stack.map(optimize);
michael@0 22407 this.scope = this.scope.map(optimize);
michael@0 22408 this.saved = optimize(this.saved);
michael@0 22409 this.store = optimize(this.store);
michael@0 22410 };
michael@0 22411 function mergeValue(control, a, b) {
michael@0 22412 var phi = a instanceof Phi && a.control === control ? a : new Phi(control, a);
michael@0 22413 phi.pushValue(b);
michael@0 22414 return phi;
michael@0 22415 }
michael@0 22416 function mergeValues(control, a, b) {
michael@0 22417 for (var i = 0; i < a.length; i++) {
michael@0 22418 a[i] = mergeValue(control, a[i], b[i]);
michael@0 22419 }
michael@0 22420 }
michael@0 22421 constructor.prototype.merge = function merge(control, other) {
michael@0 22422 true;
michael@0 22423 true;
michael@0 22424 mergeValues(control, this.local, other.local);
michael@0 22425 mergeValues(control, this.stack, other.stack);
michael@0 22426 mergeValues(control, this.scope, other.scope);
michael@0 22427 this.store = mergeValue(control, this.store, other.store);
michael@0 22428 this.store.abstract = true;
michael@0 22429 };
michael@0 22430 constructor.prototype.trace = function trace(writer) {
michael@0 22431 writer.writeLn(this.toString());
michael@0 22432 };
michael@0 22433 function toBriefString(x) {
michael@0 22434 if (x instanceof Node) {
michael@0 22435 return x.toString(true);
michael@0 22436 }
michael@0 22437 return x;
michael@0 22438 }
michael@0 22439 constructor.prototype.toString = function () {
michael@0 22440 return '<' + String(this.id + ' @ ' + this.index).padRight(' ', 10) + (' M: ' + toBriefString(this.store)).padRight(' ', 14) + (' X: ' + toBriefString(this.saved)).padRight(' ', 14) + (' $: ' + this.scope.map(toBriefString).join(', ')).padRight(' ', 20) + (' L: ' + this.local.map(toBriefString).join(', ')).padRight(' ', 40) + (' S: ' + this.stack.map(toBriefString).join(', ')).padRight(' ', 60);
michael@0 22441 };
michael@0 22442 return constructor;
michael@0 22443 }();
michael@0 22444 function isNumericConstant(node) {
michael@0 22445 return node instanceof Constant && isNumeric(node.value);
michael@0 22446 }
michael@0 22447 function isStringConstant(node) {
michael@0 22448 return node instanceof Constant && isString(node.value);
michael@0 22449 }
michael@0 22450 function isMultinameConstant(node) {
michael@0 22451 return node instanceof Constant && node.value instanceof Multiname;
michael@0 22452 }
michael@0 22453 function hasNumericType(node) {
michael@0 22454 if (isNumericConstant(node)) {
michael@0 22455 return true;
michael@0 22456 }
michael@0 22457 return node.ty && node.ty.isNumeric();
michael@0 22458 }
michael@0 22459 function typesAreEqual(a, b) {
michael@0 22460 if (hasNumericType(a) && hasNumericType(b) || hasStringType(a) && hasStringType(b)) {
michael@0 22461 return true;
michael@0 22462 }
michael@0 22463 return false;
michael@0 22464 }
michael@0 22465 function hasStringType(node) {
michael@0 22466 if (isStringConstant(node)) {
michael@0 22467 return true;
michael@0 22468 }
michael@0 22469 return node.ty && node.ty.isString();
michael@0 22470 }
michael@0 22471 function constant(value) {
michael@0 22472 return new Constant(value);
michael@0 22473 }
michael@0 22474 function qualifiedNameConstant(name) {
michael@0 22475 return constant(Multiname.getQualifiedName(name));
michael@0 22476 }
michael@0 22477 function getJSPropertyWithState(state, object, path) {
michael@0 22478 true;
michael@0 22479 var names = path.split('.');
michael@0 22480 var node = object;
michael@0 22481 for (var i = 0; i < names.length; i++) {
michael@0 22482 node = new IR.GetProperty(null, state.store, node, constant(names[i]));
michael@0 22483 node.shouldFloat = true;
michael@0 22484 state.loads.push(node);
michael@0 22485 }
michael@0 22486 return node;
michael@0 22487 }
michael@0 22488 function globalProperty(name) {
michael@0 22489 var node = new IR.GlobalProperty(name);
michael@0 22490 node.mustFloat = true;
michael@0 22491 return node;
michael@0 22492 }
michael@0 22493 function warn(message) {
michael@0 22494 }
michael@0 22495 function unary(operator, argument) {
michael@0 22496 var node = new Unary(operator, argument);
michael@0 22497 if (peepholeOptimizer) {
michael@0 22498 node = peepholeOptimizer.tryFold(node);
michael@0 22499 }
michael@0 22500 return node;
michael@0 22501 }
michael@0 22502 function binary(operator, left, right) {
michael@0 22503 var node = new Binary(operator, left, right);
michael@0 22504 if (left.ty && left.ty !== Type.Any && left.ty === right.ty) {
michael@0 22505 if (operator === Operator.EQ) {
michael@0 22506 node.operator = Operator.SEQ;
michael@0 22507 } else if (operator === Operator.NE) {
michael@0 22508 node.operator = Operator.SNE;
michael@0 22509 }
michael@0 22510 }
michael@0 22511 if (peepholeOptimizer) {
michael@0 22512 node = peepholeOptimizer.tryFold(node);
michael@0 22513 }
michael@0 22514 return node;
michael@0 22515 }
michael@0 22516 function coerceInt(value) {
michael@0 22517 return binary(Operator.OR, value, constant(0));
michael@0 22518 }
michael@0 22519 function coerceUint(value) {
michael@0 22520 return binary(Operator.URSH, value, constant(0));
michael@0 22521 }
michael@0 22522 function coerceNumber(value) {
michael@0 22523 if (hasNumericType(value)) {
michael@0 22524 return value;
michael@0 22525 }
michael@0 22526 return unary(Operator.PLUS, value);
michael@0 22527 }
michael@0 22528 function coerceBoolean(value) {
michael@0 22529 return unary(Operator.FALSE, unary(Operator.FALSE, value));
michael@0 22530 }
michael@0 22531 function shouldNotFloat(node) {
michael@0 22532 node.shouldNotFloat = true;
michael@0 22533 return node;
michael@0 22534 }
michael@0 22535 function shouldFloat(node) {
michael@0 22536 true;
michael@0 22537 node.shouldFloat = true;
michael@0 22538 return node;
michael@0 22539 }
michael@0 22540 function mustFloat(node) {
michael@0 22541 node.mustFloat = true;
michael@0 22542 return node;
michael@0 22543 }
michael@0 22544 function callPure(callee, object, args) {
michael@0 22545 return new Call(null, null, callee, object, args, IR.Flags.PRISTINE);
michael@0 22546 }
michael@0 22547 function callGlobalProperty(name, value) {
michael@0 22548 return callPure(globalProperty(name), null, [
michael@0 22549 value
michael@0 22550 ]);
michael@0 22551 }
michael@0 22552 function convertString(value) {
michael@0 22553 if (isStringConstant(value)) {
michael@0 22554 return value;
michael@0 22555 }
michael@0 22556 return callPure(globalProperty('String'), null, [
michael@0 22557 value
michael@0 22558 ]);
michael@0 22559 }
michael@0 22560 function coerceString(value) {
michael@0 22561 if (isStringConstant(value)) {
michael@0 22562 return value;
michael@0 22563 }
michael@0 22564 return callPure(globalProperty('asCoerceString'), null, [
michael@0 22565 value
michael@0 22566 ]);
michael@0 22567 }
michael@0 22568 var coerceObject = callGlobalProperty.bind(null, 'asCoerceObject');
michael@0 22569 var coercers = createEmptyObject();
michael@0 22570 coercers[Multiname.Int] = coerceInt;
michael@0 22571 coercers[Multiname.Uint] = coerceUint;
michael@0 22572 coercers[Multiname.Number] = coerceNumber;
michael@0 22573 coercers[Multiname.String] = coerceString;
michael@0 22574 coercers[Multiname.Object] = coerceObject;
michael@0 22575 coercers[Multiname.Boolean] = coerceBoolean;
michael@0 22576 function getCoercerForType(multiname) {
michael@0 22577 true;
michael@0 22578 return coercers[Multiname.getQualifiedName(multiname)];
michael@0 22579 }
michael@0 22580 var callableConstructors = createEmptyObject();
michael@0 22581 callableConstructors[Multiname.Int] = coerceInt;
michael@0 22582 callableConstructors[Multiname.Uint] = coerceUint;
michael@0 22583 callableConstructors[Multiname.Number] = callGlobalProperty.bind(null, 'Number');
michael@0 22584 callableConstructors[Multiname.String] = callGlobalProperty.bind(null, 'String');
michael@0 22585 callableConstructors[Multiname.Object] = callGlobalProperty.bind(null, 'Object');
michael@0 22586 callableConstructors[Multiname.Boolean] = callGlobalProperty.bind(null, 'Boolean');
michael@0 22587 function getCallableConstructorForType(multiname) {
michael@0 22588 true;
michael@0 22589 return callableConstructors[Multiname.getQualifiedName(multiname)];
michael@0 22590 }
michael@0 22591 var Builder = function () {
michael@0 22592 function builder(methodInfo, scope, hasDynamicScope) {
michael@0 22593 true;
michael@0 22594 this.abc = methodInfo.abc;
michael@0 22595 this.scope = scope;
michael@0 22596 this.methodInfo = methodInfo;
michael@0 22597 this.hasDynamicScope = hasDynamicScope;
michael@0 22598 }
michael@0 22599 builder.prototype.buildStart = function (start) {
michael@0 22600 var mi = this.methodInfo;
michael@0 22601 var state = start.entryState = new State(0);
michael@0 22602 state.local.push(new This(start));
michael@0 22603 var parameterIndexOffset = this.hasDynamicScope ? 1 : 0;
michael@0 22604 var parameterCount = mi.parameters.length;
michael@0 22605 for (var i = 0; i < parameterCount; i++) {
michael@0 22606 state.local.push(new Parameter(start, parameterIndexOffset + i, mi.parameters[i].name));
michael@0 22607 }
michael@0 22608 for (var i = parameterCount; i < mi.localCount; i++) {
michael@0 22609 state.local.push(Undefined);
michael@0 22610 }
michael@0 22611 state.store = new Projection(start, Projection.Type.STORE);
michael@0 22612 if (this.hasDynamicScope) {
michael@0 22613 start.scope = new Parameter(start, 0, SAVED_SCOPE_NAME);
michael@0 22614 } else {
michael@0 22615 start.scope = new Constant(this.scope);
michael@0 22616 }
michael@0 22617 state.saved = new Projection(start, Projection.Type.SCOPE);
michael@0 22618 start.domain = new Constant(this.domain);
michael@0 22619 var args = new IR.Arguments(start);
michael@0 22620 if (mi.needsRest() || mi.needsArguments()) {
michael@0 22621 var offset = constant(parameterIndexOffset + (mi.needsRest() ? parameterCount : 0));
michael@0 22622 state.local[parameterCount + 1] = new Call(start, state.store, globalProperty('sliceArguments'), null, [
michael@0 22623 args,
michael@0 22624 offset
michael@0 22625 ], IR.Flags.PRISTINE);
michael@0 22626 }
michael@0 22627 var argumentsLength = getJSPropertyWithState(state, args, 'length');
michael@0 22628 for (var i = 0; i < parameterCount; i++) {
michael@0 22629 var parameter = mi.parameters[i];
michael@0 22630 var index = i + 1;
michael@0 22631 var local = state.local[index];
michael@0 22632 if (parameter.value !== undefined) {
michael@0 22633 var condition;
michael@0 22634 if (USE_TYPE_OF_DEFAULT_ARGUMENT_CHECKING) {
michael@0 22635 condition = new IR.Binary(Operator.SEQ, new IR.Unary(Operator.TYPE_OF, local), constant('undefined'));
michael@0 22636 } else {
michael@0 22637 condition = new IR.Binary(Operator.LT, argumentsLength, constant(parameterIndexOffset + i + 1));
michael@0 22638 }
michael@0 22639 local = new IR.Latch(null, condition, constant(parameter.value), local);
michael@0 22640 }
michael@0 22641 if (parameter.type && !parameter.type.isAnyName()) {
michael@0 22642 var coercer = getCoercerForType(parameter.type);
michael@0 22643 if (coercer) {
michael@0 22644 local = coercer(local);
michael@0 22645 } else if (c4CoerceNonPrimitiveParameters) {
michael@0 22646 local = new Call(start, state.store, globalProperty('asCoerceByMultiname'), null, [
michael@0 22647 constant(this.abc.applicationDomain),
michael@0 22648 constant(parameter.type),
michael@0 22649 local
michael@0 22650 ], true);
michael@0 22651 }
michael@0 22652 }
michael@0 22653 state.local[index] = local;
michael@0 22654 }
michael@0 22655 return start;
michael@0 22656 };
michael@0 22657 builder.prototype.buildGraph = function buildGraph(callerRegion, callerState, inlineArguments) {
michael@0 22658 var analysis = this.methodInfo.analysis;
michael@0 22659 var blocks = analysis.blocks;
michael@0 22660 var bytecodes = analysis.bytecodes;
michael@0 22661 var methodInfo = this.methodInfo;
michael@0 22662 var ints = this.abc.constantPool.ints;
michael@0 22663 var uints = this.abc.constantPool.uints;
michael@0 22664 var doubles = this.abc.constantPool.doubles;
michael@0 22665 var strings = this.abc.constantPool.strings;
michael@0 22666 var methods = this.abc.methods;
michael@0 22667 var classes = this.abc.classes;
michael@0 22668 var multinames = this.abc.constantPool.multinames;
michael@0 22669 var domain = new Constant(this.abc.applicationDomain);
michael@0 22670 var traceBuilder = c4TraceLevel.value > 2;
michael@0 22671 var stopPoints = [];
michael@0 22672 for (var i = 0; i < blocks.length; i++) {
michael@0 22673 blocks[i].blockDominatorOrder = i;
michael@0 22674 }
michael@0 22675 var worklist = new Shumway.SortedList(function compare(a, b) {
michael@0 22676 return a.block.blockDominatorOrder - b.block.blockDominatorOrder;
michael@0 22677 });
michael@0 22678 var start = new Start(null);
michael@0 22679 this.buildStart(start);
michael@0 22680 var createFunctionCallee = globalProperty('createFunction');
michael@0 22681 worklist.push({
michael@0 22682 region: start,
michael@0 22683 block: blocks[0]
michael@0 22684 });
michael@0 22685 var next;
michael@0 22686 while (next = worklist.pop()) {
michael@0 22687 buildBlock(next.region, next.block, next.region.entryState.clone()).forEach(function (stop) {
michael@0 22688 var target = stop.target;
michael@0 22689 var region = target.region;
michael@0 22690 if (region) {
michael@0 22691 traceBuilder && writer.enter('Merging into region: ' + region + ' @ ' + target.position + ', block ' + target.bid + ' {');
michael@0 22692 traceBuilder && writer.writeLn(' R ' + region.entryState);
michael@0 22693 traceBuilder && writer.writeLn('+ I ' + stop.state);
michael@0 22694 region.entryState.merge(region, stop.state);
michael@0 22695 region.predecessors.push(stop.control);
michael@0 22696 traceBuilder && writer.writeLn(' = ' + region.entryState);
michael@0 22697 traceBuilder && writer.leave('}');
michael@0 22698 } else {
michael@0 22699 region = target.region = new Region(stop.control);
michael@0 22700 if (target.loop) {
michael@0 22701 traceBuilder && writer.writeLn('Adding PHIs to loop region.');
michael@0 22702 }
michael@0 22703 region.entryState = target.loop ? stop.state.makeLoopPhis(region) : stop.state.clone(target.position);
michael@0 22704 traceBuilder && writer.writeLn('Adding new region: ' + region + ' @ ' + target.position + ' to worklist.');
michael@0 22705 worklist.push({
michael@0 22706 region: region,
michael@0 22707 block: target
michael@0 22708 });
michael@0 22709 }
michael@0 22710 });
michael@0 22711 traceBuilder && writer.enter('Worklist: {');
michael@0 22712 worklist.forEach(function (item) {
michael@0 22713 traceBuilder && writer.writeLn(item.region + ' ' + item.block.bdo + ' ' + item.region.entryState);
michael@0 22714 });
michael@0 22715 traceBuilder && writer.leave('}');
michael@0 22716 }
michael@0 22717 traceBuilder && writer.writeLn('Done');
michael@0 22718 function buildBlock(region, block, state) {
michael@0 22719 true;
michael@0 22720 state.optimize();
michael@0 22721 var typeState = block.entryState;
michael@0 22722 if (typeState) {
michael@0 22723 traceBuilder && writer.writeLn('Type State: ' + typeState);
michael@0 22724 for (var i = 0; i < typeState.local.length; i++) {
michael@0 22725 var type = typeState.local[i];
michael@0 22726 var local = state.local[i];
michael@0 22727 if (local.ty) {
michael@0 22728 } else {
michael@0 22729 local.ty = type;
michael@0 22730 }
michael@0 22731 }
michael@0 22732 }
michael@0 22733 var local = state.local;
michael@0 22734 var stack = state.stack;
michael@0 22735 var scope = state.scope;
michael@0 22736 function savedScope() {
michael@0 22737 return state.saved;
michael@0 22738 }
michael@0 22739 function topScope(depth) {
michael@0 22740 if (depth !== undefined) {
michael@0 22741 if (depth < scope.length) {
michael@0 22742 return scope[scope.length - 1 - depth];
michael@0 22743 } else if (depth === scope.length) {
michael@0 22744 return savedScope();
michael@0 22745 } else {
michael@0 22746 var s = savedScope();
michael@0 22747 var savedScopeDepth = depth - scope.length;
michael@0 22748 for (var i = 0; i < savedScopeDepth; i++) {
michael@0 22749 s = getJSProperty(s, 'parent');
michael@0 22750 }
michael@0 22751 return s;
michael@0 22752 }
michael@0 22753 }
michael@0 22754 if (scope.length > 0) {
michael@0 22755 return scope.top();
michael@0 22756 }
michael@0 22757 return savedScope();
michael@0 22758 }
michael@0 22759 var object, receiver, index, callee, value, multiname, type, args, pristine, left, right, operator;
michael@0 22760 function push(x) {
michael@0 22761 true;
michael@0 22762 if (bc.ti) {
michael@0 22763 if (x.ty) {
michael@0 22764 } else {
michael@0 22765 x.ty = bc.ti.type;
michael@0 22766 }
michael@0 22767 }
michael@0 22768 stack.push(x);
michael@0 22769 }
michael@0 22770 function pop() {
michael@0 22771 return stack.pop();
michael@0 22772 }
michael@0 22773 function popMany(count) {
michael@0 22774 return stack.popMany(count);
michael@0 22775 }
michael@0 22776 function pushLocal(index) {
michael@0 22777 push(local[index]);
michael@0 22778 }
michael@0 22779 function popLocal(index) {
michael@0 22780 local[index] = shouldNotFloat(pop());
michael@0 22781 }
michael@0 22782 function buildMultiname(index) {
michael@0 22783 var multiname = multinames[index];
michael@0 22784 var namespaces, name, flags = multiname.flags;
michael@0 22785 if (multiname.isRuntimeName()) {
michael@0 22786 name = stack.pop();
michael@0 22787 } else {
michael@0 22788 name = constant(multiname.name);
michael@0 22789 }
michael@0 22790 if (multiname.isRuntimeNamespace()) {
michael@0 22791 namespaces = shouldFloat(new NewArray(region, [
michael@0 22792 pop()
michael@0 22793 ]));
michael@0 22794 } else {
michael@0 22795 namespaces = constant(multiname.namespaces);
michael@0 22796 }
michael@0 22797 return new IR.ASMultiname(namespaces, name, flags);
michael@0 22798 }
michael@0 22799 function simplifyName(name) {
michael@0 22800 if (isMultinameConstant(name) && Multiname.isQName(name.value)) {
michael@0 22801 return constant(Multiname.getQualifiedName(name.value));
michael@0 22802 }
michael@0 22803 return name;
michael@0 22804 }
michael@0 22805 function getGlobalScope(ti) {
michael@0 22806 if (ti && ti.object) {
michael@0 22807 return constant(ti.object);
michael@0 22808 }
michael@0 22809 return new IR.ASGlobal(null, savedScope());
michael@0 22810 }
michael@0 22811 function findProperty(multiname, strict, ti) {
michael@0 22812 var slowPath = new IR.ASFindProperty(region, state.store, topScope(), multiname, domain, strict);
michael@0 22813 if (ti) {
michael@0 22814 if (ti.object) {
michael@0 22815 if (ti.object instanceof Global && !ti.object.isExecuting()) {
michael@0 22816 warn('Can\'t optimize findProperty ' + multiname + ', global object is not yet executed or executing.');
michael@0 22817 return slowPath;
michael@0 22818 }
michael@0 22819 return constant(ti.object);
michael@0 22820 } else if (ti.scopeDepth !== undefined) {
michael@0 22821 return getScopeObject(topScope(ti.scopeDepth));
michael@0 22822 }
michael@0 22823 }
michael@0 22824 warn('Can\'t optimize findProperty ' + multiname);
michael@0 22825 return slowPath;
michael@0 22826 }
michael@0 22827 function getJSProperty(object, path) {
michael@0 22828 return getJSPropertyWithState(state, object, path);
michael@0 22829 }
michael@0 22830 function coerce(multiname, value) {
michael@0 22831 if (false && isConstant(value)) {
michael@0 22832 return constant(asCoerceByMultiname(domain.value, multiname, value.value));
michael@0 22833 } else {
michael@0 22834 var coercer = getCoercerForType(multiname);
michael@0 22835 if (coercer) {
michael@0 22836 return coercer(value);
michael@0 22837 }
michael@0 22838 }
michael@0 22839 if (c4CoerceNonPrimitive) {
michael@0 22840 return call(globalProperty('asCoerceByMultiname'), null, [
michael@0 22841 domain,
michael@0 22842 constant(multiname),
michael@0 22843 value
michael@0 22844 ]);
michael@0 22845 }
michael@0 22846 return value;
michael@0 22847 }
michael@0 22848 function getScopeObject(scope) {
michael@0 22849 if (scope instanceof IR.ASScope) {
michael@0 22850 return scope.object;
michael@0 22851 }
michael@0 22852 return getJSProperty(scope, 'object');
michael@0 22853 }
michael@0 22854 function store(node) {
michael@0 22855 state.store = new Projection(node, Projection.Type.STORE);
michael@0 22856 node.loads = state.loads.slice(0);
michael@0 22857 state.loads.length = 0;
michael@0 22858 return node;
michael@0 22859 }
michael@0 22860 function load(node) {
michael@0 22861 state.loads.push(node);
michael@0 22862 return node;
michael@0 22863 }
michael@0 22864 function resolveMultinameGlobally(multiname) {
michael@0 22865 var namespaces = multiname.namespaces;
michael@0 22866 var name = multiname.name;
michael@0 22867 if (!Shumway.AVM2.Runtime.globalMultinameAnalysis.value) {
michael@0 22868 return;
michael@0 22869 }
michael@0 22870 if (!isConstant(namespaces) || !isConstant(name) || multiname.isAttribute()) {
michael@0 22871 Counter.count('GlobalMultinameResolver: Cannot resolve runtime multiname or attribute.');
michael@0 22872 return;
michael@0 22873 }
michael@0 22874 if (isNumeric(name.value) || !isString(name.value) || !name.value) {
michael@0 22875 Counter.count('GlobalMultinameResolver: Cannot resolve numeric or any names.');
michael@0 22876 return false;
michael@0 22877 }
michael@0 22878 return GlobalMultinameResolver.resolveMultiname(new Multiname(namespaces.value, name.value, multiname.flags));
michael@0 22879 }
michael@0 22880 function callSuper(scope, object, multiname, args, ti) {
michael@0 22881 if (ti && ti.trait && ti.trait.isMethod() && ti.baseClass) {
michael@0 22882 var qn = VM_OPEN_METHOD_PREFIX + Multiname.getQualifiedName(ti.trait.name);
michael@0 22883 var callee = getJSProperty(constant(ti.baseClass), 'traitsPrototype.' + qn);
michael@0 22884 return call(callee, object, args);
michael@0 22885 }
michael@0 22886 return store(new IR.ASCallSuper(region, state.store, object, multiname, args, IR.Flags.PRISTINE, scope));
michael@0 22887 }
michael@0 22888 function getSuper(scope, object, multiname, ti) {
michael@0 22889 if (ti && ti.trait && ti.trait.isGetter() && ti.baseClass) {
michael@0 22890 var qn = VM_OPEN_GET_METHOD_PREFIX + Multiname.getQualifiedName(ti.trait.name);
michael@0 22891 var callee = getJSProperty(constant(ti.baseClass), 'traitsPrototype.' + qn);
michael@0 22892 return call(callee, object, []);
michael@0 22893 }
michael@0 22894 return store(new IR.ASGetSuper(region, state.store, object, multiname, scope));
michael@0 22895 }
michael@0 22896 function setSuper(scope, object, multiname, value, ti) {
michael@0 22897 if (ti && ti.trait && ti.trait.isSetter() && ti.baseClass) {
michael@0 22898 var qn = VM_OPEN_SET_METHOD_PREFIX + Multiname.getQualifiedName(ti.trait.name);
michael@0 22899 var callee = getJSProperty(constant(ti.baseClass), 'traitsPrototype.' + qn);
michael@0 22900 return call(callee, object, [
michael@0 22901 value
michael@0 22902 ]);
michael@0 22903 }
michael@0 22904 return store(new IR.ASSetSuper(region, state.store, object, multiname, value, scope));
michael@0 22905 }
michael@0 22906 function constructSuper(scope, object, args, ti) {
michael@0 22907 if (ti) {
michael@0 22908 if (ti.noCallSuperNeeded) {
michael@0 22909 return;
michael@0 22910 } else if (ti.baseClass) {
michael@0 22911 var callee = getJSProperty(constant(ti.baseClass), 'instanceConstructorNoInitialize');
michael@0 22912 call(callee, object, args);
michael@0 22913 return;
michael@0 22914 }
michael@0 22915 }
michael@0 22916 callee = getJSProperty(scope, 'object.baseClass.instanceConstructorNoInitialize');
michael@0 22917 call(callee, object, args);
michael@0 22918 return;
michael@0 22919 }
michael@0 22920 function callProperty(object, multiname, args, isLex, ti) {
michael@0 22921 if (ti && ti.trait) {
michael@0 22922 if (ti.trait.isMethod()) {
michael@0 22923 var openQn;
michael@0 22924 if (ti.trait.holder instanceof InstanceInfo && ti.trait.holder.isInterface()) {
michael@0 22925 openQn = Multiname.getPublicQualifiedName(Multiname.getName(ti.trait.name));
michael@0 22926 } else {
michael@0 22927 openQn = Multiname.getQualifiedName(ti.trait.name);
michael@0 22928 }
michael@0 22929 openQn = VM_OPEN_METHOD_PREFIX + openQn;
michael@0 22930 return store(new IR.CallProperty(region, state.store, object, constant(openQn), args, IR.Flags.PRISTINE));
michael@0 22931 } else if (ti.trait.isClass()) {
michael@0 22932 var constructor = getCallableConstructorForType(ti.trait.name);
michael@0 22933 if (constructor) {
michael@0 22934 return constructor(args[0]);
michael@0 22935 }
michael@0 22936 var qn = Multiname.getQualifiedName(ti.trait.name);
michael@0 22937 return store(new IR.CallProperty(region, state.store, object, constant(qn), args, 0));
michael@0 22938 }
michael@0 22939 } else if (ti && ti.propertyQName) {
michael@0 22940 return store(new IR.CallProperty(region, state.store, object, constant(ti.propertyQName), args, IR.Flags.PRISTINE));
michael@0 22941 }
michael@0 22942 var qn = resolveMultinameGlobally(multiname);
michael@0 22943 if (qn) {
michael@0 22944 return store(new IR.ASCallProperty(region, state.store, object, constant(Multiname.getQualifiedName(qn)), args, IR.Flags.PRISTINE | IR.Flags.RESOLVED, isLex));
michael@0 22945 }
michael@0 22946 return store(new IR.ASCallProperty(region, state.store, object, multiname, args, IR.Flags.PRISTINE, isLex));
michael@0 22947 }
michael@0 22948 function getProperty(object, multiname, ti, getOpenMethod) {
michael@0 22949 true;
michael@0 22950 getOpenMethod = !(!getOpenMethod);
michael@0 22951 if (ti) {
michael@0 22952 if (ti.trait) {
michael@0 22953 if (ti.trait.isConst() && ti.trait.hasDefaultValue) {
michael@0 22954 return constant(ti.trait.value);
michael@0 22955 }
michael@0 22956 var get = new IR.GetProperty(region, state.store, object, qualifiedNameConstant(ti.trait.name));
michael@0 22957 return ti.trait.isGetter() ? store(get) : load(get);
michael@0 22958 }
michael@0 22959 if (ti.propertyQName) {
michael@0 22960 return store(new IR.GetProperty(region, state.store, object, constant(ti.propertyQName)));
michael@0 22961 } else if (ti.isDirectlyReadable) {
michael@0 22962 return store(new IR.GetProperty(region, state.store, object, multiname.name));
michael@0 22963 } else if (ti.isIndexedReadable) {
michael@0 22964 return store(new IR.ASGetProperty(region, state.store, object, multiname, IR.Flags.INDEXED | (getOpenMethod ? IR.Flagas.IS_METHOD : 0)));
michael@0 22965 }
michael@0 22966 }
michael@0 22967 warn('Can\'t optimize getProperty ' + multiname);
michael@0 22968 var qn = resolveMultinameGlobally(multiname);
michael@0 22969 if (qn) {
michael@0 22970 return store(new IR.ASGetProperty(region, state.store, object, constant(Multiname.getQualifiedName(qn)), IR.Flags.RESOLVED | (getOpenMethod ? IR.Flagas.IS_METHOD : 0)));
michael@0 22971 }
michael@0 22972 Counter.count('Compiler: Slow ASGetProperty');
michael@0 22973 return store(new IR.ASGetProperty(region, state.store, object, multiname, getOpenMethod ? IR.Flagas.IS_METHOD : 0));
michael@0 22974 }
michael@0 22975 function setProperty(object, multiname, value, ti) {
michael@0 22976 true;
michael@0 22977 if (ti) {
michael@0 22978 if (ti.trait) {
michael@0 22979 var coercer = ti.trait.typeName ? getCoercerForType(ti.trait.typeName) : null;
michael@0 22980 if (coercer) {
michael@0 22981 value = coercer(value);
michael@0 22982 }
michael@0 22983 store(new IR.SetProperty(region, state.store, object, qualifiedNameConstant(ti.trait.name), value));
michael@0 22984 return;
michael@0 22985 }
michael@0 22986 if (ti.propertyQName) {
michael@0 22987 return store(new IR.SetProperty(region, state.store, object, constant(ti.propertyQName), value));
michael@0 22988 } else if (ti.isDirectlyWriteable) {
michael@0 22989 return store(new IR.SetProperty(region, state.store, object, multiname.name, value));
michael@0 22990 } else if (ti.isIndexedWriteable) {
michael@0 22991 return store(new IR.ASSetProperty(region, state.store, object, multiname, value, IR.Flags.INDEXED));
michael@0 22992 }
michael@0 22993 }
michael@0 22994 warn('Can\'t optimize setProperty ' + multiname);
michael@0 22995 var qn = resolveMultinameGlobally(multiname);
michael@0 22996 if (qn) {
michael@0 22997 }
michael@0 22998 return store(new IR.ASSetProperty(region, state.store, object, multiname, value, 0));
michael@0 22999 }
michael@0 23000 function getDescendants(object, name, ti) {
michael@0 23001 name = simplifyName(name);
michael@0 23002 return new IR.ASGetDescendants(region, state.store, object, name);
michael@0 23003 }
michael@0 23004 function getSlot(object, index, ti) {
michael@0 23005 if (ti) {
michael@0 23006 var trait = ti.trait;
michael@0 23007 if (trait) {
michael@0 23008 if (trait.isConst() && ti.trait.hasDefaultValue) {
michael@0 23009 return constant(trait.value);
michael@0 23010 }
michael@0 23011 var slotQn = Multiname.getQualifiedName(trait.name);
michael@0 23012 return store(new IR.GetProperty(region, state.store, object, constant(slotQn)));
michael@0 23013 }
michael@0 23014 }
michael@0 23015 warn('Can\'t optimize getSlot ' + index);
michael@0 23016 return store(new IR.ASGetSlot(null, state.store, object, index));
michael@0 23017 }
michael@0 23018 function setSlot(object, index, value, ti) {
michael@0 23019 if (ti) {
michael@0 23020 var trait = ti.trait;
michael@0 23021 if (trait) {
michael@0 23022 var slotQn = Multiname.getQualifiedName(trait.name);
michael@0 23023 store(new IR.SetProperty(region, state.store, object, constant(slotQn), value));
michael@0 23024 return;
michael@0 23025 }
michael@0 23026 }
michael@0 23027 warn('Can\'t optimize setSlot ' + index);
michael@0 23028 store(new IR.ASSetSlot(region, state.store, object, index, value));
michael@0 23029 }
michael@0 23030 function call(callee, object, args) {
michael@0 23031 return store(new Call(region, state.store, callee, object, args, IR.Flags.PRISTINE));
michael@0 23032 }
michael@0 23033 function callCall(callee, object, args, pristine) {
michael@0 23034 return store(new Call(region, state.store, callee, object, args, pristine ? IR.Flags.PRISTINE : 0));
michael@0 23035 }
michael@0 23036 function truthyCondition(operator) {
michael@0 23037 var right;
michael@0 23038 if (operator.isBinary()) {
michael@0 23039 right = pop();
michael@0 23040 }
michael@0 23041 var left = pop();
michael@0 23042 var node;
michael@0 23043 if (right) {
michael@0 23044 node = binary(operator, left, right);
michael@0 23045 } else {
michael@0 23046 node = unary(operator, left);
michael@0 23047 }
michael@0 23048 if (peepholeOptimizer) {
michael@0 23049 node = peepholeOptimizer.tryFold(node, true);
michael@0 23050 }
michael@0 23051 return node;
michael@0 23052 }
michael@0 23053 function negatedTruthyCondition(operator) {
michael@0 23054 var node = unary(Operator.FALSE, truthyCondition(operator));
michael@0 23055 if (peepholeOptimizer) {
michael@0 23056 node = peepholeOptimizer.tryFold(node, true);
michael@0 23057 }
michael@0 23058 return node;
michael@0 23059 }
michael@0 23060 function pushExpression(operator, toInt) {
michael@0 23061 var left, right;
michael@0 23062 if (operator.isBinary()) {
michael@0 23063 right = pop();
michael@0 23064 left = pop();
michael@0 23065 if (toInt) {
michael@0 23066 right = coerceInt(right);
michael@0 23067 left = coerceInt(left);
michael@0 23068 }
michael@0 23069 push(binary(operator, left, right));
michael@0 23070 } else {
michael@0 23071 left = pop();
michael@0 23072 if (toInt) {
michael@0 23073 left = coerceInt(left);
michael@0 23074 }
michael@0 23075 push(unary(operator, left));
michael@0 23076 }
michael@0 23077 }
michael@0 23078 var stops = null;
michael@0 23079 function buildIfStops(predicate) {
michael@0 23080 true;
michael@0 23081 var _if = new IR.If(region, predicate);
michael@0 23082 stops = [
michael@0 23083 {
michael@0 23084 control: new Projection(_if, Projection.Type.FALSE),
michael@0 23085 target: bytecodes[bc.position + 1],
michael@0 23086 state: state
michael@0 23087 },
michael@0 23088 {
michael@0 23089 control: new Projection(_if, Projection.Type.TRUE),
michael@0 23090 target: bc.target,
michael@0 23091 state: state
michael@0 23092 }
michael@0 23093 ];
michael@0 23094 }
michael@0 23095 function buildJumpStop() {
michael@0 23096 true;
michael@0 23097 stops = [
michael@0 23098 {
michael@0 23099 control: region,
michael@0 23100 target: bc.target,
michael@0 23101 state: state
michael@0 23102 }
michael@0 23103 ];
michael@0 23104 }
michael@0 23105 function buildThrowStop() {
michael@0 23106 true;
michael@0 23107 stops = [];
michael@0 23108 }
michael@0 23109 function buildReturnStop() {
michael@0 23110 true;
michael@0 23111 stops = [];
michael@0 23112 }
michael@0 23113 function buildSwitchStops(determinant) {
michael@0 23114 true;
michael@0 23115 if (bc.targets.length > 2) {
michael@0 23116 stops = [];
michael@0 23117 var _switch = new IR.Switch(region, determinant);
michael@0 23118 for (var i = 0; i < bc.targets.length; i++) {
michael@0 23119 stops.push({
michael@0 23120 control: new Projection(_switch, Projection.Type.CASE, constant(i)),
michael@0 23121 target: bc.targets[i],
michael@0 23122 state: state
michael@0 23123 });
michael@0 23124 }
michael@0 23125 } else {
michael@0 23126 true;
michael@0 23127 var predicate = binary(Operator.SEQ, determinant, constant(0));
michael@0 23128 var _if = new IR.If(region, predicate);
michael@0 23129 stops = [
michael@0 23130 {
michael@0 23131 control: new Projection(_if, Projection.Type.FALSE),
michael@0 23132 target: bc.targets[1],
michael@0 23133 state: state
michael@0 23134 },
michael@0 23135 {
michael@0 23136 control: new Projection(_if, Projection.Type.TRUE),
michael@0 23137 target: bc.targets[0],
michael@0 23138 state: state
michael@0 23139 }
michael@0 23140 ];
michael@0 23141 }
michael@0 23142 }
michael@0 23143 if (traceBuilder) {
michael@0 23144 writer.writeLn('Processing Region: ' + region + ', Block: ' + block.bid);
michael@0 23145 writer.enter(('> state: ' + region.entryState.toString()).padRight(' ', 100));
michael@0 23146 }
michael@0 23147 region.processed = true;
michael@0 23148 var bc;
michael@0 23149 for (var bci = block.position, end = block.end.position; bci <= end; bci++) {
michael@0 23150 bc = bytecodes[bci];
michael@0 23151 var op = bc.op;
michael@0 23152 state.index = bci;
michael@0 23153 switch (op) {
michael@0 23154 case 3:
michael@0 23155 store(new IR.Throw(region, pop()));
michael@0 23156 stopPoints.push({
michael@0 23157 region: region,
michael@0 23158 store: state.store,
michael@0 23159 value: Undefined
michael@0 23160 });
michael@0 23161 buildThrowStop();
michael@0 23162 break;
michael@0 23163 case 98:
michael@0 23164 pushLocal(bc.index);
michael@0 23165 break;
michael@0 23166 case 208:
michael@0 23167 case 209:
michael@0 23168 case 210:
michael@0 23169 case 211:
michael@0 23170 pushLocal(op - OP_getlocal0);
michael@0 23171 break;
michael@0 23172 case 99:
michael@0 23173 popLocal(bc.index);
michael@0 23174 break;
michael@0 23175 case 212:
michael@0 23176 case 213:
michael@0 23177 case 214:
michael@0 23178 case 215:
michael@0 23179 popLocal(op - OP_setlocal0);
michael@0 23180 break;
michael@0 23181 case 28:
michael@0 23182 scope.push(new IR.ASScope(topScope(), pop(), true));
michael@0 23183 break;
michael@0 23184 case 48:
michael@0 23185 scope.push(new IR.ASScope(topScope(), pop(), false));
michael@0 23186 break;
michael@0 23187 case 29:
michael@0 23188 scope.pop();
michael@0 23189 break;
michael@0 23190 case 100:
michael@0 23191 push(getGlobalScope(bc.ti));
michael@0 23192 break;
michael@0 23193 case 101:
michael@0 23194 push(getScopeObject(state.scope[bc.index]));
michael@0 23195 break;
michael@0 23196 case 93:
michael@0 23197 push(findProperty(buildMultiname(bc.index), true, bc.ti));
michael@0 23198 break;
michael@0 23199 case 94:
michael@0 23200 push(findProperty(buildMultiname(bc.index), false, bc.ti));
michael@0 23201 break;
michael@0 23202 case 102:
michael@0 23203 multiname = buildMultiname(bc.index);
michael@0 23204 object = pop();
michael@0 23205 push(getProperty(object, multiname, bc.ti, false));
michael@0 23206 break;
michael@0 23207 case 89:
michael@0 23208 multiname = buildMultiname(bc.index);
michael@0 23209 object = pop();
michael@0 23210 push(getDescendants(object, multiname, bc.ti));
michael@0 23211 break;
michael@0 23212 case 96:
michael@0 23213 multiname = buildMultiname(bc.index);
michael@0 23214 push(getProperty(findProperty(multiname, true, bc.ti), multiname, bc.ti, false));
michael@0 23215 break;
michael@0 23216 case 104:
michael@0 23217 case 97:
michael@0 23218 value = pop();
michael@0 23219 multiname = buildMultiname(bc.index);
michael@0 23220 object = pop();
michael@0 23221 setProperty(object, multiname, value, bc.ti);
michael@0 23222 break;
michael@0 23223 case 106:
michael@0 23224 multiname = buildMultiname(bc.index);
michael@0 23225 object = pop();
michael@0 23226 push(store(new IR.ASDeleteProperty(region, state.store, object, multiname)));
michael@0 23227 break;
michael@0 23228 case 108:
michael@0 23229 object = pop();
michael@0 23230 push(getSlot(object, constant(bc.index), bc.ti));
michael@0 23231 break;
michael@0 23232 case 109:
michael@0 23233 value = pop();
michael@0 23234 object = pop();
michael@0 23235 setSlot(object, constant(bc.index), value, bc.ti);
michael@0 23236 break;
michael@0 23237 case 4:
michael@0 23238 multiname = buildMultiname(bc.index);
michael@0 23239 object = pop();
michael@0 23240 push(getSuper(savedScope(), object, multiname, bc.ti));
michael@0 23241 break;
michael@0 23242 case 5:
michael@0 23243 value = pop();
michael@0 23244 multiname = buildMultiname(bc.index);
michael@0 23245 object = pop();
michael@0 23246 setSuper(savedScope(), object, multiname, value, bc.ti);
michael@0 23247 break;
michael@0 23248 case 241:
michael@0 23249 case 240:
michael@0 23250 break;
michael@0 23251 case 64:
michael@0 23252 push(callPure(createFunctionCallee, null, [
michael@0 23253 constant(methods[bc.index]),
michael@0 23254 topScope(),
michael@0 23255 constant(true)
michael@0 23256 ]));
michael@0 23257 break;
michael@0 23258 case 65:
michael@0 23259 args = popMany(bc.argCount);
michael@0 23260 object = pop();
michael@0 23261 callee = pop();
michael@0 23262 push(callCall(callee, object, args));
michael@0 23263 break;
michael@0 23264 case 70:
michael@0 23265 case 79:
michael@0 23266 case 76:
michael@0 23267 args = popMany(bc.argCount);
michael@0 23268 multiname = buildMultiname(bc.index);
michael@0 23269 object = pop();
michael@0 23270 value = callProperty(object, multiname, args, op === OP_callproplex, bc.ti);
michael@0 23271 if (op !== OP_callpropvoid) {
michael@0 23272 push(value);
michael@0 23273 }
michael@0 23274 break;
michael@0 23275 case 69:
michael@0 23276 case 78:
michael@0 23277 multiname = buildMultiname(bc.index);
michael@0 23278 args = popMany(bc.argCount);
michael@0 23279 object = pop();
michael@0 23280 value = callSuper(savedScope(), object, multiname, args, bc.ti);
michael@0 23281 if (op !== OP_callsupervoid) {
michael@0 23282 push(value);
michael@0 23283 }
michael@0 23284 break;
michael@0 23285 case 66:
michael@0 23286 args = popMany(bc.argCount);
michael@0 23287 object = pop();
michael@0 23288 push(store(new IR.ASNew(region, state.store, object, args)));
michael@0 23289 break;
michael@0 23290 case 73:
michael@0 23291 args = popMany(bc.argCount);
michael@0 23292 object = pop();
michael@0 23293 constructSuper(savedScope(), object, args, bc.ti);
michael@0 23294 break;
michael@0 23295 case 74:
michael@0 23296 args = popMany(bc.argCount);
michael@0 23297 multiname = buildMultiname(bc.index);
michael@0 23298 object = pop();
michael@0 23299 callee = getProperty(object, multiname, bc.ti, false);
michael@0 23300 push(store(new IR.ASNew(region, state.store, callee, args)));
michael@0 23301 break;
michael@0 23302 case 128:
michael@0 23303 if (bc.ti && bc.ti.noCoercionNeeded) {
michael@0 23304 Counter.count('Compiler: NoCoercionNeeded');
michael@0 23305 break;
michael@0 23306 } else {
michael@0 23307 Counter.count('Compiler: CoercionNeeded');
michael@0 23308 }
michael@0 23309 value = pop();
michael@0 23310 push(coerce(multinames[bc.index], value));
michael@0 23311 break;
michael@0 23312 case 131:
michael@0 23313 case 115:
michael@0 23314 push(coerceInt(pop()));
michael@0 23315 break;
michael@0 23316 case 136:
michael@0 23317 case 116:
michael@0 23318 push(coerceUint(pop()));
michael@0 23319 break;
michael@0 23320 case 132:
michael@0 23321 case 117:
michael@0 23322 push(coerceNumber(pop()));
michael@0 23323 break;
michael@0 23324 case 129:
michael@0 23325 case 118:
michael@0 23326 push(coerceBoolean(pop()));
michael@0 23327 break;
michael@0 23328 case 120:
michael@0 23329 push(call(globalProperty('checkFilter'), null, [
michael@0 23330 pop()
michael@0 23331 ]));
michael@0 23332 break;
michael@0 23333 case 130:
michael@0 23334 break;
michael@0 23335 case 133:
michael@0 23336 push(coerceString(pop()));
michael@0 23337 break;
michael@0 23338 case 112:
michael@0 23339 push(convertString(pop()));
michael@0 23340 break;
michael@0 23341 case 135:
michael@0 23342 type = pop();
michael@0 23343 if (c4AsTypeLate) {
michael@0 23344 value = pop();
michael@0 23345 push(call(globalProperty('asAsType'), null, [
michael@0 23346 type,
michael@0 23347 value
michael@0 23348 ]));
michael@0 23349 }
michael@0 23350 break;
michael@0 23351 case 72:
michael@0 23352 case 71:
michael@0 23353 value = Undefined;
michael@0 23354 if (op === OP_returnvalue) {
michael@0 23355 value = pop();
michael@0 23356 if (methodInfo.returnType) {
michael@0 23357 if (!(bc.ti && bc.ti.noCoercionNeeded)) {
michael@0 23358 value = coerce(methodInfo.returnType, value);
michael@0 23359 }
michael@0 23360 }
michael@0 23361 }
michael@0 23362 stopPoints.push({
michael@0 23363 region: region,
michael@0 23364 store: state.store,
michael@0 23365 value: value
michael@0 23366 });
michael@0 23367 buildReturnStop();
michael@0 23368 break;
michael@0 23369 case 30:
michael@0 23370 case 35:
michael@0 23371 index = pop();
michael@0 23372 object = pop();
michael@0 23373 push(new IR.CallProperty(region, state.store, object, constant(op === OP_nextname ? 'asNextName' : 'asNextValue'), [
michael@0 23374 index
michael@0 23375 ], IR.Flags.PRISTINE));
michael@0 23376 break;
michael@0 23377 case 50:
michael@0 23378 var temp = call(globalProperty('asHasNext2'), null, [
michael@0 23379 local[bc.object],
michael@0 23380 local[bc.index]
michael@0 23381 ]);
michael@0 23382 local[bc.object] = getJSProperty(temp, 'object');
michael@0 23383 push(local[bc.index] = getJSProperty(temp, 'index'));
michael@0 23384 break;
michael@0 23385 case 32:
michael@0 23386 push(Null);
michael@0 23387 break;
michael@0 23388 case 33:
michael@0 23389 push(Undefined);
michael@0 23390 break;
michael@0 23391 case 34:
michael@0 23392 notImplemented();
michael@0 23393 break;
michael@0 23394 case 36:
michael@0 23395 push(constant(bc.value));
michael@0 23396 break;
michael@0 23397 case 37:
michael@0 23398 push(constant(bc.value));
michael@0 23399 break;
michael@0 23400 case 44:
michael@0 23401 push(constant(strings[bc.index]));
michael@0 23402 break;
michael@0 23403 case 45:
michael@0 23404 push(constant(ints[bc.index]));
michael@0 23405 break;
michael@0 23406 case 46:
michael@0 23407 push(constant(uints[bc.index]));
michael@0 23408 break;
michael@0 23409 case 47:
michael@0 23410 push(constant(doubles[bc.index]));
michael@0 23411 break;
michael@0 23412 case 38:
michael@0 23413 push(constant(true));
michael@0 23414 break;
michael@0 23415 case 39:
michael@0 23416 push(constant(false));
michael@0 23417 break;
michael@0 23418 case 40:
michael@0 23419 push(constant(NaN));
michael@0 23420 break;
michael@0 23421 case 41:
michael@0 23422 pop();
michael@0 23423 break;
michael@0 23424 case 42:
michael@0 23425 value = shouldNotFloat(pop());
michael@0 23426 push(value);
michael@0 23427 push(value);
michael@0 23428 break;
michael@0 23429 case 43:
michael@0 23430 state.stack.push(pop(), pop());
michael@0 23431 break;
michael@0 23432 case 239:
michael@0 23433 case OP_debugline:
michael@0 23434 case OP_debugfile:
michael@0 23435 break;
michael@0 23436 case 12:
michael@0 23437 buildIfStops(negatedTruthyCondition(Operator.LT));
michael@0 23438 break;
michael@0 23439 case 24:
michael@0 23440 buildIfStops(truthyCondition(Operator.GE));
michael@0 23441 break;
michael@0 23442 case 13:
michael@0 23443 buildIfStops(negatedTruthyCondition(Operator.LE));
michael@0 23444 break;
michael@0 23445 case 23:
michael@0 23446 buildIfStops(truthyCondition(Operator.GT));
michael@0 23447 break;
michael@0 23448 case 14:
michael@0 23449 buildIfStops(negatedTruthyCondition(Operator.GT));
michael@0 23450 break;
michael@0 23451 case 22:
michael@0 23452 buildIfStops(truthyCondition(Operator.LE));
michael@0 23453 break;
michael@0 23454 case 15:
michael@0 23455 buildIfStops(negatedTruthyCondition(Operator.GE));
michael@0 23456 break;
michael@0 23457 case 21:
michael@0 23458 buildIfStops(truthyCondition(Operator.LT));
michael@0 23459 break;
michael@0 23460 case 16:
michael@0 23461 buildJumpStop();
michael@0 23462 break;
michael@0 23463 case 17:
michael@0 23464 buildIfStops(truthyCondition(Operator.TRUE));
michael@0 23465 break;
michael@0 23466 case 18:
michael@0 23467 buildIfStops(truthyCondition(Operator.FALSE));
michael@0 23468 break;
michael@0 23469 case 19:
michael@0 23470 buildIfStops(truthyCondition(Operator.EQ));
michael@0 23471 break;
michael@0 23472 case 20:
michael@0 23473 buildIfStops(truthyCondition(Operator.NE));
michael@0 23474 break;
michael@0 23475 case 25:
michael@0 23476 buildIfStops(truthyCondition(Operator.SEQ));
michael@0 23477 break;
michael@0 23478 case 26:
michael@0 23479 buildIfStops(truthyCondition(Operator.SNE));
michael@0 23480 break;
michael@0 23481 case 27:
michael@0 23482 buildSwitchStops(pop());
michael@0 23483 break;
michael@0 23484 case 150:
michael@0 23485 pushExpression(Operator.FALSE);
michael@0 23486 break;
michael@0 23487 case 151:
michael@0 23488 pushExpression(Operator.BITWISE_NOT);
michael@0 23489 break;
michael@0 23490 case 160:
michael@0 23491 right = pop();
michael@0 23492 left = pop();
michael@0 23493 if (typesAreEqual(left, right)) {
michael@0 23494 operator = Operator.ADD;
michael@0 23495 } else if (Shumway.AVM2.Runtime.useAsAdd) {
michael@0 23496 operator = Operator.AS_ADD;
michael@0 23497 } else {
michael@0 23498 operator = Operator.ADD;
michael@0 23499 }
michael@0 23500 push(binary(operator, left, right));
michael@0 23501 break;
michael@0 23502 case 197:
michael@0 23503 pushExpression(Operator.ADD, true);
michael@0 23504 break;
michael@0 23505 case 161:
michael@0 23506 pushExpression(Operator.SUB);
michael@0 23507 break;
michael@0 23508 case 198:
michael@0 23509 pushExpression(Operator.SUB, true);
michael@0 23510 break;
michael@0 23511 case 162:
michael@0 23512 pushExpression(Operator.MUL);
michael@0 23513 break;
michael@0 23514 case 199:
michael@0 23515 pushExpression(Operator.MUL, true);
michael@0 23516 break;
michael@0 23517 case 163:
michael@0 23518 pushExpression(Operator.DIV);
michael@0 23519 break;
michael@0 23520 case 164:
michael@0 23521 pushExpression(Operator.MOD);
michael@0 23522 break;
michael@0 23523 case 165:
michael@0 23524 pushExpression(Operator.LSH);
michael@0 23525 break;
michael@0 23526 case 166:
michael@0 23527 pushExpression(Operator.RSH);
michael@0 23528 break;
michael@0 23529 case 167:
michael@0 23530 pushExpression(Operator.URSH);
michael@0 23531 break;
michael@0 23532 case 168:
michael@0 23533 pushExpression(Operator.AND);
michael@0 23534 break;
michael@0 23535 case 169:
michael@0 23536 pushExpression(Operator.OR);
michael@0 23537 break;
michael@0 23538 case 170:
michael@0 23539 pushExpression(Operator.XOR);
michael@0 23540 break;
michael@0 23541 case 171:
michael@0 23542 pushExpression(Operator.EQ);
michael@0 23543 break;
michael@0 23544 case 172:
michael@0 23545 pushExpression(Operator.SEQ);
michael@0 23546 break;
michael@0 23547 case 173:
michael@0 23548 pushExpression(Operator.LT);
michael@0 23549 break;
michael@0 23550 case 174:
michael@0 23551 pushExpression(Operator.LE);
michael@0 23552 break;
michael@0 23553 case 175:
michael@0 23554 pushExpression(Operator.GT);
michael@0 23555 break;
michael@0 23556 case 176:
michael@0 23557 pushExpression(Operator.GE);
michael@0 23558 break;
michael@0 23559 case 144:
michael@0 23560 pushExpression(Operator.NEG);
michael@0 23561 break;
michael@0 23562 case 196:
michael@0 23563 pushExpression(Operator.NEG, true);
michael@0 23564 break;
michael@0 23565 case 145:
michael@0 23566 case 192:
michael@0 23567 case 147:
michael@0 23568 case 193:
michael@0 23569 push(constant(1));
michael@0 23570 if (op === OP_increment || op === OP_decrement) {
michael@0 23571 push(coerceNumber(pop()));
michael@0 23572 } else {
michael@0 23573 push(coerceInt(pop()));
michael@0 23574 }
michael@0 23575 if (op === OP_increment || op === OP_increment_i) {
michael@0 23576 pushExpression(Operator.ADD);
michael@0 23577 } else {
michael@0 23578 pushExpression(Operator.SUB);
michael@0 23579 }
michael@0 23580 break;
michael@0 23581 case 146:
michael@0 23582 case 194:
michael@0 23583 case 148:
michael@0 23584 case 195:
michael@0 23585 push(constant(1));
michael@0 23586 if (op === OP_inclocal || op === OP_declocal) {
michael@0 23587 push(coerceNumber(local[bc.index]));
michael@0 23588 } else {
michael@0 23589 push(coerceInt(local[bc.index]));
michael@0 23590 }
michael@0 23591 if (op === OP_inclocal || op === OP_inclocal_i) {
michael@0 23592 pushExpression(Operator.ADD);
michael@0 23593 } else {
michael@0 23594 pushExpression(Operator.SUB);
michael@0 23595 }
michael@0 23596 popLocal(bc.index);
michael@0 23597 break;
michael@0 23598 case 177:
michael@0 23599 type = pop();
michael@0 23600 value = pop();
michael@0 23601 push(call(getJSProperty(type, 'isInstanceOf'), null, [
michael@0 23602 value
michael@0 23603 ]));
michael@0 23604 break;
michael@0 23605 case 178:
michael@0 23606 value = pop();
michael@0 23607 multiname = buildMultiname(bc.index);
michael@0 23608 type = getProperty(findProperty(multiname, false), multiname);
michael@0 23609 push(call(globalProperty('asIsType'), null, [
michael@0 23610 type,
michael@0 23611 value
michael@0 23612 ]));
michael@0 23613 break;
michael@0 23614 case 179:
michael@0 23615 type = pop();
michael@0 23616 value = pop();
michael@0 23617 push(call(globalProperty('asIsType'), null, [
michael@0 23618 type,
michael@0 23619 value
michael@0 23620 ]));
michael@0 23621 break;
michael@0 23622 case 180:
michael@0 23623 object = pop();
michael@0 23624 value = pop();
michael@0 23625 multiname = new IR.ASMultiname(Undefined, value, 0);
michael@0 23626 push(store(new IR.ASHasProperty(region, state.store, object, multiname)));
michael@0 23627 break;
michael@0 23628 case 149:
michael@0 23629 push(call(globalProperty('asTypeOf'), null, [
michael@0 23630 pop()
michael@0 23631 ]));
michael@0 23632 break;
michael@0 23633 case 8:
michael@0 23634 push(Undefined);
michael@0 23635 popLocal(bc.index);
michael@0 23636 break;
michael@0 23637 case 83:
michael@0 23638 args = popMany(bc.argCount);
michael@0 23639 type = pop();
michael@0 23640 callee = globalProperty('applyType');
michael@0 23641 push(call(callee, null, [
michael@0 23642 domain,
michael@0 23643 type,
michael@0 23644 new NewArray(region, args)
michael@0 23645 ]));
michael@0 23646 break;
michael@0 23647 case 86:
michael@0 23648 args = popMany(bc.argCount);
michael@0 23649 push(new NewArray(region, args));
michael@0 23650 break;
michael@0 23651 case 85:
michael@0 23652 var properties = [];
michael@0 23653 for (var i = 0; i < bc.argCount; i++) {
michael@0 23654 var value = pop();
michael@0 23655 var key = pop();
michael@0 23656 true;
michael@0 23657 key = constant(Multiname.getPublicQualifiedName(key.value));
michael@0 23658 properties.push(new KeyValuePair(key, value));
michael@0 23659 }
michael@0 23660 push(new NewObject(region, properties));
michael@0 23661 break;
michael@0 23662 case 87:
michael@0 23663 push(new IR.ASNewActivation(constant(methodInfo)));
michael@0 23664 break;
michael@0 23665 case 88:
michael@0 23666 callee = globalProperty('createClass');
michael@0 23667 push(call(callee, null, [
michael@0 23668 constant(classes[bc.index]),
michael@0 23669 pop(),
michael@0 23670 topScope()
michael@0 23671 ]));
michael@0 23672 break;
michael@0 23673 default:
michael@0 23674 unexpected('Not Implemented: ' + bc);
michael@0 23675 }
michael@0 23676 if (op === OP_debug || op === OP_debugfile || op === OP_debugline) {
michael@0 23677 continue;
michael@0 23678 }
michael@0 23679 if (traceBuilder) {
michael@0 23680 writer.writeLn(('state: ' + state.toString()).padRight(' ', 100) + ' : ' + bci + ', ' + bc.toString(this.abc));
michael@0 23681 }
michael@0 23682 }
michael@0 23683 if (traceBuilder) {
michael@0 23684 writer.leave(('< state: ' + state.toString()).padRight(' ', 100));
michael@0 23685 }
michael@0 23686 if (!stops) {
michael@0 23687 stops = [];
michael@0 23688 if (bc.position + 1 <= bytecodes.length) {
michael@0 23689 stops.push({
michael@0 23690 control: region,
michael@0 23691 target: bytecodes[bc.position + 1],
michael@0 23692 state: state
michael@0 23693 });
michael@0 23694 }
michael@0 23695 }
michael@0 23696 return stops;
michael@0 23697 }
michael@0 23698 var stop;
michael@0 23699 if (stopPoints.length > 1) {
michael@0 23700 var stopRegion = new Region(null);
michael@0 23701 var stopValuePhi = new Phi(stopRegion, null);
michael@0 23702 var stopStorePhi = new Phi(stopRegion, null);
michael@0 23703 stopPoints.forEach(function (stopPoint) {
michael@0 23704 stopRegion.predecessors.push(stopPoint.region);
michael@0 23705 stopValuePhi.pushValue(stopPoint.value);
michael@0 23706 stopStorePhi.pushValue(stopPoint.store);
michael@0 23707 });
michael@0 23708 stop = new Stop(stopRegion, stopStorePhi, stopValuePhi);
michael@0 23709 } else {
michael@0 23710 stop = new Stop(stopPoints[0].region, stopPoints[0].store, stopPoints[0].value);
michael@0 23711 }
michael@0 23712 return new DFG(stop);
michael@0 23713 };
michael@0 23714 return builder;
michael@0 23715 }();
michael@0 23716 function buildMethod(verifier, methodInfo, scope, hasDynamicScope) {
michael@0 23717 true;
michael@0 23718 true;
michael@0 23719 true;
michael@0 23720 Counter.count('Compiler: Compiled Methods');
michael@0 23721 Timer.start('Compiler');
michael@0 23722 Timer.start('Mark Loops');
michael@0 23723 methodInfo.analysis.markLoops();
michael@0 23724 Timer.stop();
michael@0 23725 if (Shumway.AVM2.Runtime.enableVerifier.value) {
michael@0 23726 Timer.start('Verify');
michael@0 23727 verifier.verifyMethod(methodInfo, scope);
michael@0 23728 Timer.stop();
michael@0 23729 }
michael@0 23730 var traceSource = c4TraceLevel.value > 0;
michael@0 23731 var traceIR = c4TraceLevel.value > 1;
michael@0 23732 Timer.start('Build IR');
michael@0 23733 Node.startNumbering();
michael@0 23734 var dfg = new Builder(methodInfo, scope, hasDynamicScope).buildGraph();
michael@0 23735 Timer.stop();
michael@0 23736 traceIR && dfg.trace(writer);
michael@0 23737 Timer.start('Build CFG');
michael@0 23738 var cfg = dfg.buildCFG();
michael@0 23739 Timer.stop();
michael@0 23740 Timer.start('Optimize Phis');
michael@0 23741 cfg.optimizePhis();
michael@0 23742 Timer.stop();
michael@0 23743 Timer.start('Schedule Nodes');
michael@0 23744 cfg.scheduleEarly();
michael@0 23745 Timer.stop();
michael@0 23746 traceIR && cfg.trace(writer);
michael@0 23747 Timer.start('Verify IR');
michael@0 23748 cfg.verify();
michael@0 23749 Timer.stop();
michael@0 23750 Timer.start('Allocate Variables');
michael@0 23751 cfg.allocateVariables();
michael@0 23752 Timer.stop();
michael@0 23753 Timer.start('Generate Source');
michael@0 23754 var result = Backend.generate(cfg, enableRegisterAllocator.value);
michael@0 23755 Timer.stop();
michael@0 23756 traceSource && writer.writeLn(result.body);
michael@0 23757 Node.stopNumbering();
michael@0 23758 Timer.stop();
michael@0 23759 return result;
michael@0 23760 }
michael@0 23761 exports.buildMethod = buildMethod;
michael@0 23762 }(typeof exports === 'undefined' ? Builder = {} : exports));
michael@0 23763 var Compiler = new (function () {
michael@0 23764 function constructor() {
michael@0 23765 this.verifier = new Verifier();
michael@0 23766 }
michael@0 23767 constructor.prototype.compileMethod = function (methodInfo, scope, hasDynamicScope) {
michael@0 23768 return Builder.buildMethod(this.verifier, methodInfo, scope, hasDynamicScope);
michael@0 23769 };
michael@0 23770 return constructor;
michael@0 23771 }())();
michael@0 23772 (function (exports) {
michael@0 23773 var Control = function () {
michael@0 23774 var SEQ = 1;
michael@0 23775 var LOOP = 2;
michael@0 23776 var IF = 3;
michael@0 23777 var CASE = 4;
michael@0 23778 var SWITCH = 5;
michael@0 23779 var LABEL_CASE = 6;
michael@0 23780 var LABEL_SWITCH = 7;
michael@0 23781 var EXIT = 8;
michael@0 23782 var BREAK = 9;
michael@0 23783 var CONTINUE = 10;
michael@0 23784 var TRY = 11;
michael@0 23785 var CATCH = 12;
michael@0 23786 function Seq(body) {
michael@0 23787 this.kind = SEQ;
michael@0 23788 this.body = body;
michael@0 23789 }
michael@0 23790 Seq.prototype = {
michael@0 23791 trace: function (writer) {
michael@0 23792 var body = this.body;
michael@0 23793 for (var i = 0, j = body.length; i < j; i++) {
michael@0 23794 body[i].trace(writer);
michael@0 23795 }
michael@0 23796 },
michael@0 23797 first: function () {
michael@0 23798 return this.body[0];
michael@0 23799 },
michael@0 23800 slice: function (begin, end) {
michael@0 23801 return new Seq(this.body.slice(begin, end));
michael@0 23802 }
michael@0 23803 };
michael@0 23804 function Loop(body) {
michael@0 23805 this.kind = LOOP;
michael@0 23806 this.body = body;
michael@0 23807 }
michael@0 23808 Loop.prototype = {
michael@0 23809 trace: function (writer) {
michael@0 23810 writer.enter('loop {');
michael@0 23811 this.body.trace(writer);
michael@0 23812 writer.leave('}');
michael@0 23813 }
michael@0 23814 };
michael@0 23815 function If(cond, then, els, nothingThrownLabel) {
michael@0 23816 this.kind = IF;
michael@0 23817 this.cond = cond;
michael@0 23818 this.then = then;
michael@0 23819 this.else = els;
michael@0 23820 this.negated = false;
michael@0 23821 this.nothingThrownLabel = nothingThrownLabel;
michael@0 23822 }
michael@0 23823 If.prototype = {
michael@0 23824 trace: function (writer) {
michael@0 23825 this.cond.trace(writer);
michael@0 23826 if (this.nothingThrownLabel) {
michael@0 23827 writer.enter('if (label is ' + this.nothingThrownLabel + ') {');
michael@0 23828 }
michael@0 23829 writer.enter('if' + (this.negated ? ' not' : '') + ' {');
michael@0 23830 this.then && this.then.trace(writer);
michael@0 23831 if (this.else) {
michael@0 23832 writer.outdent();
michael@0 23833 writer.enter('} else {');
michael@0 23834 this.else.trace(writer);
michael@0 23835 }
michael@0 23836 writer.leave('}');
michael@0 23837 if (this.nothingThrownLabel) {
michael@0 23838 writer.leave('}');
michael@0 23839 }
michael@0 23840 }
michael@0 23841 };
michael@0 23842 function Case(index, body) {
michael@0 23843 this.kind = CASE;
michael@0 23844 this.index = index;
michael@0 23845 this.body = body;
michael@0 23846 }
michael@0 23847 Case.prototype = {
michael@0 23848 trace: function (writer) {
michael@0 23849 if (this.index >= 0) {
michael@0 23850 writer.writeLn('case ' + this.index + ':');
michael@0 23851 } else {
michael@0 23852 writer.writeLn('default:');
michael@0 23853 }
michael@0 23854 writer.indent();
michael@0 23855 this.body && this.body.trace(writer);
michael@0 23856 writer.outdent();
michael@0 23857 }
michael@0 23858 };
michael@0 23859 function Switch(determinant, cases, nothingThrownLabel) {
michael@0 23860 this.kind = SWITCH;
michael@0 23861 this.determinant = determinant;
michael@0 23862 this.cases = cases;
michael@0 23863 this.nothingThrownLabel = nothingThrownLabel;
michael@0 23864 }
michael@0 23865 Switch.prototype = {
michael@0 23866 trace: function (writer) {
michael@0 23867 if (this.nothingThrownLabel) {
michael@0 23868 writer.enter('if (label is ' + this.nothingThrownLabel + ') {');
michael@0 23869 }
michael@0 23870 this.determinant.trace(writer);
michael@0 23871 writer.writeLn('switch {');
michael@0 23872 for (var i = 0, j = this.cases.length; i < j; i++) {
michael@0 23873 this.cases[i].trace(writer);
michael@0 23874 }
michael@0 23875 writer.writeLn('}');
michael@0 23876 if (this.nothingThrownLabel) {
michael@0 23877 writer.leave('}');
michael@0 23878 }
michael@0 23879 }
michael@0 23880 };
michael@0 23881 function LabelCase(labels, body) {
michael@0 23882 this.kind = LABEL_CASE;
michael@0 23883 this.labels = labels;
michael@0 23884 this.body = body;
michael@0 23885 }
michael@0 23886 LabelCase.prototype = {
michael@0 23887 trace: function (writer) {
michael@0 23888 writer.enter('if (label is ' + this.labels.join(' or ') + ') {');
michael@0 23889 this.body && this.body.trace(writer);
michael@0 23890 writer.leave('}');
michael@0 23891 }
michael@0 23892 };
michael@0 23893 function LabelSwitch(cases) {
michael@0 23894 var labelMap = {};
michael@0 23895 for (var i = 0, j = cases.length; i < j; i++) {
michael@0 23896 var c = cases[i];
michael@0 23897 if (!c.labels) {
michael@0 23898 print(c.toSource());
michael@0 23899 }
michael@0 23900 for (var k = 0, l = c.labels.length; k < l; k++) {
michael@0 23901 labelMap[c.labels[k]] = c;
michael@0 23902 }
michael@0 23903 }
michael@0 23904 this.kind = LABEL_SWITCH;
michael@0 23905 this.cases = cases;
michael@0 23906 this.labelMap = labelMap;
michael@0 23907 }
michael@0 23908 LabelSwitch.prototype = {
michael@0 23909 trace: function (writer) {
michael@0 23910 for (var i = 0, j = this.cases.length; i < j; i++) {
michael@0 23911 this.cases[i].trace(writer);
michael@0 23912 }
michael@0 23913 }
michael@0 23914 };
michael@0 23915 function Exit(label) {
michael@0 23916 this.kind = EXIT;
michael@0 23917 this.label = label;
michael@0 23918 }
michael@0 23919 Exit.prototype = {
michael@0 23920 trace: function (writer) {
michael@0 23921 writer.writeLn('label = ' + this.label);
michael@0 23922 }
michael@0 23923 };
michael@0 23924 function Break(label, head) {
michael@0 23925 this.kind = BREAK;
michael@0 23926 this.label = label;
michael@0 23927 this.head = head;
michael@0 23928 }
michael@0 23929 Break.prototype = {
michael@0 23930 trace: function (writer) {
michael@0 23931 this.label && writer.writeLn('label = ' + this.label);
michael@0 23932 writer.writeLn('break');
michael@0 23933 }
michael@0 23934 };
michael@0 23935 function Continue(label, head) {
michael@0 23936 this.kind = CONTINUE;
michael@0 23937 this.label = label;
michael@0 23938 this.head = head;
michael@0 23939 this.necessary = true;
michael@0 23940 }
michael@0 23941 Continue.prototype = {
michael@0 23942 trace: function (writer) {
michael@0 23943 this.label && writer.writeLn('label = ' + this.label);
michael@0 23944 this.necessary && writer.writeLn('continue');
michael@0 23945 }
michael@0 23946 };
michael@0 23947 function Try(body, catches) {
michael@0 23948 this.kind = TRY;
michael@0 23949 this.body = body;
michael@0 23950 this.catches = catches;
michael@0 23951 }
michael@0 23952 Try.prototype = {
michael@0 23953 trace: function (writer) {
michael@0 23954 writer.enter('try {');
michael@0 23955 this.body.trace(writer);
michael@0 23956 writer.writeLn('label = ' + this.nothingThrownLabel);
michael@0 23957 for (var i = 0, j = this.catches.length; i < j; i++) {
michael@0 23958 this.catches[i].trace(writer);
michael@0 23959 }
michael@0 23960 writer.leave('}');
michael@0 23961 }
michael@0 23962 };
michael@0 23963 function Catch(varName, typeName, body) {
michael@0 23964 this.kind = CATCH;
michael@0 23965 this.varName = varName;
michael@0 23966 this.typeName = typeName;
michael@0 23967 this.body = body;
michael@0 23968 }
michael@0 23969 Catch.prototype = {
michael@0 23970 trace: function (writer) {
michael@0 23971 writer.outdent();
michael@0 23972 writer.enter('} catch (' + (this.varName || 'e') + (this.typeName ? ' : ' + this.typeName : '') + ') {');
michael@0 23973 this.body.trace(writer);
michael@0 23974 }
michael@0 23975 };
michael@0 23976 return {
michael@0 23977 SEQ: SEQ,
michael@0 23978 LOOP: LOOP,
michael@0 23979 IF: IF,
michael@0 23980 CASE: CASE,
michael@0 23981 SWITCH: SWITCH,
michael@0 23982 LABEL_CASE: LABEL_CASE,
michael@0 23983 LABEL_SWITCH: LABEL_SWITCH,
michael@0 23984 EXIT: EXIT,
michael@0 23985 BREAK: BREAK,
michael@0 23986 CONTINUE: CONTINUE,
michael@0 23987 TRY: TRY,
michael@0 23988 CATCH: CATCH,
michael@0 23989 Seq: Seq,
michael@0 23990 Loop: Loop,
michael@0 23991 If: If,
michael@0 23992 Case: Case,
michael@0 23993 Switch: Switch,
michael@0 23994 LabelCase: LabelCase,
michael@0 23995 LabelSwitch: LabelSwitch,
michael@0 23996 Exit: Exit,
michael@0 23997 Break: Break,
michael@0 23998 Continue: Continue,
michael@0 23999 Try: Try,
michael@0 24000 Catch: Catch
michael@0 24001 };
michael@0 24002 }();
michael@0 24003 var Analysis = function () {
michael@0 24004 function blockSetClass(length, blockById) {
michael@0 24005 var BlockSet = BitSetFunctor(length);
michael@0 24006 var ADDRESS_BITS_PER_WORD = BlockSet.ADDRESS_BITS_PER_WORD;
michael@0 24007 var BITS_PER_WORD = BlockSet.BITS_PER_WORD;
michael@0 24008 var BIT_INDEX_MASK = BlockSet.BIT_INDEX_MASK;
michael@0 24009 BlockSet.singleton = function singleton(b) {
michael@0 24010 var bs = new BlockSet();
michael@0 24011 bs.set(b.id);
michael@0 24012 bs.count = 1;
michael@0 24013 bs.dirty = 0;
michael@0 24014 return bs;
michael@0 24015 };
michael@0 24016 BlockSet.fromBlocks = function fromArray(other) {
michael@0 24017 var bs = new BlockSet();
michael@0 24018 bs.setBlocks(other);
michael@0 24019 return bs;
michael@0 24020 };
michael@0 24021 var Bsp = BlockSet.prototype;
michael@0 24022 if (BlockSet.singleword) {
michael@0 24023 Bsp.forEachBlock = function forEach(fn) {
michael@0 24024 true;
michael@0 24025 var byId = blockById;
michael@0 24026 var word = this.bits;
michael@0 24027 if (word) {
michael@0 24028 for (var k = 0; k < BITS_PER_WORD; k++) {
michael@0 24029 if (word & 1 << k) {
michael@0 24030 fn(byId[k]);
michael@0 24031 }
michael@0 24032 }
michael@0 24033 }
michael@0 24034 };
michael@0 24035 Bsp.choose = function choose() {
michael@0 24036 var byId = blockById;
michael@0 24037 var word = this.bits;
michael@0 24038 if (word) {
michael@0 24039 for (var k = 0; k < BITS_PER_WORD; k++) {
michael@0 24040 if (word & 1 << k) {
michael@0 24041 return byId[k];
michael@0 24042 }
michael@0 24043 }
michael@0 24044 }
michael@0 24045 };
michael@0 24046 Bsp.members = function members() {
michael@0 24047 var byId = blockById;
michael@0 24048 var set = [];
michael@0 24049 var word = this.bits;
michael@0 24050 if (word) {
michael@0 24051 for (var k = 0; k < BITS_PER_WORD; k++) {
michael@0 24052 if (word & 1 << k) {
michael@0 24053 set.push(byId[k]);
michael@0 24054 }
michael@0 24055 }
michael@0 24056 }
michael@0 24057 return set;
michael@0 24058 };
michael@0 24059 Bsp.setBlocks = function setBlocks(bs) {
michael@0 24060 var bits = this.bits;
michael@0 24061 for (var i = 0, j = bs.length; i < j; i++) {
michael@0 24062 var id = bs[i].id;
michael@0 24063 bits |= 1 << (id & BIT_INDEX_MASK);
michael@0 24064 }
michael@0 24065 this.bits = bits;
michael@0 24066 };
michael@0 24067 } else {
michael@0 24068 Bsp.forEachBlock = function forEach(fn) {
michael@0 24069 true;
michael@0 24070 var byId = blockById;
michael@0 24071 var bits = this.bits;
michael@0 24072 for (var i = 0, j = bits.length; i < j; i++) {
michael@0 24073 var word = bits[i];
michael@0 24074 if (word) {
michael@0 24075 for (var k = 0; k < BITS_PER_WORD; k++) {
michael@0 24076 if (word & 1 << k) {
michael@0 24077 fn(byId[i * BITS_PER_WORD + k]);
michael@0 24078 }
michael@0 24079 }
michael@0 24080 }
michael@0 24081 }
michael@0 24082 };
michael@0 24083 Bsp.choose = function choose() {
michael@0 24084 var byId = blockById;
michael@0 24085 var bits = this.bits;
michael@0 24086 for (var i = 0, j = bits.length; i < j; i++) {
michael@0 24087 var word = bits[i];
michael@0 24088 if (word) {
michael@0 24089 for (var k = 0; k < BITS_PER_WORD; k++) {
michael@0 24090 if (word & 1 << k) {
michael@0 24091 return byId[i * BITS_PER_WORD + k];
michael@0 24092 }
michael@0 24093 }
michael@0 24094 }
michael@0 24095 }
michael@0 24096 };
michael@0 24097 Bsp.members = function members() {
michael@0 24098 var byId = blockById;
michael@0 24099 var set = [];
michael@0 24100 var bits = this.bits;
michael@0 24101 for (var i = 0, j = bits.length; i < j; i++) {
michael@0 24102 var word = bits[i];
michael@0 24103 if (word) {
michael@0 24104 for (var k = 0; k < BITS_PER_WORD; k++) {
michael@0 24105 if (word & 1 << k) {
michael@0 24106 set.push(byId[i * BITS_PER_WORD + k]);
michael@0 24107 }
michael@0 24108 }
michael@0 24109 }
michael@0 24110 }
michael@0 24111 return set;
michael@0 24112 };
michael@0 24113 Bsp.setBlocks = function setBlocks(bs) {
michael@0 24114 var bits = this.bits;
michael@0 24115 for (var i = 0, j = bs.length; i < j; i++) {
michael@0 24116 var id = bs[i].id;
michael@0 24117 bits[id >> ADDRESS_BITS_PER_WORD] |= 1 << (id & BIT_INDEX_MASK);
michael@0 24118 }
michael@0 24119 };
michael@0 24120 }
michael@0 24121 return BlockSet;
michael@0 24122 }
michael@0 24123 function Analysis(cfg, options) {
michael@0 24124 this.options = options || {};
michael@0 24125 this.BlockSet = blockSetClass(cfg.blocks.length, cfg.blocks);
michael@0 24126 this.hasExceptions = false;
michael@0 24127 this.normalizeReachableBlocks(cfg.root);
michael@0 24128 }
michael@0 24129 Analysis.prototype = {
michael@0 24130 normalizeReachableBlocks: function normalizeReachableBlocks(root) {
michael@0 24131 true;
michael@0 24132 var ONCE = 1;
michael@0 24133 var BUNCH_OF_TIMES = 2;
michael@0 24134 var BlockSet = this.BlockSet;
michael@0 24135 var blocks = [];
michael@0 24136 var visited = {};
michael@0 24137 var ancestors = {};
michael@0 24138 var worklist = [
michael@0 24139 root
michael@0 24140 ];
michael@0 24141 var node;
michael@0 24142 ancestors[root.id] = true;
michael@0 24143 while (node = worklist.top()) {
michael@0 24144 if (visited[node.id]) {
michael@0 24145 if (visited[node.id] === ONCE) {
michael@0 24146 visited[node.id] = BUNCH_OF_TIMES;
michael@0 24147 blocks.push(node);
michael@0 24148 }
michael@0 24149 ancestors[node.id] = false;
michael@0 24150 worklist.pop();
michael@0 24151 continue;
michael@0 24152 }
michael@0 24153 visited[node.id] = ONCE;
michael@0 24154 ancestors[node.id] = true;
michael@0 24155 var successors = node.successors;
michael@0 24156 for (var i = 0, j = successors.length; i < j; i++) {
michael@0 24157 var s = successors[i];
michael@0 24158 if (ancestors[s.id]) {
michael@0 24159 if (!node.spbacks) {
michael@0 24160 node.spbacks = new BlockSet();
michael@0 24161 }
michael@0 24162 node.spbacks.set(s.id);
michael@0 24163 }
michael@0 24164 !visited[s.id] && worklist.push(s);
michael@0 24165 }
michael@0 24166 }
michael@0 24167 this.blocks = blocks.reverse();
michael@0 24168 },
michael@0 24169 computeDominance: function computeDominance() {
michael@0 24170 function intersectDominators(doms, b1, b2) {
michael@0 24171 var finger1 = b1;
michael@0 24172 var finger2 = b2;
michael@0 24173 while (finger1 !== finger2) {
michael@0 24174 while (finger1 > finger2) {
michael@0 24175 finger1 = doms[finger1];
michael@0 24176 }
michael@0 24177 while (finger2 > finger1) {
michael@0 24178 finger2 = doms[finger2];
michael@0 24179 }
michael@0 24180 }
michael@0 24181 return finger1;
michael@0 24182 }
michael@0 24183 var blocks = this.blocks;
michael@0 24184 var n = blocks.length;
michael@0 24185 var doms = new Array(n);
michael@0 24186 doms[0] = 0;
michael@0 24187 var rpo = [];
michael@0 24188 for (var b = 0; b < n; b++) {
michael@0 24189 rpo[blocks[b].id] = b;
michael@0 24190 blocks[b].dominatees = [];
michael@0 24191 }
michael@0 24192 var changed = true;
michael@0 24193 while (changed) {
michael@0 24194 changed = false;
michael@0 24195 for (var b = 1; b < n; b++) {
michael@0 24196 var predecessors = blocks[b].predecessors;
michael@0 24197 var j = predecessors.length;
michael@0 24198 var newIdom = rpo[predecessors[0].id];
michael@0 24199 if (!(newIdom in doms)) {
michael@0 24200 for (var i = 1; i < j; i++) {
michael@0 24201 newIdom = rpo[predecessors[i].id];
michael@0 24202 if (newIdom in doms) {
michael@0 24203 break;
michael@0 24204 }
michael@0 24205 }
michael@0 24206 }
michael@0 24207 true;
michael@0 24208 for (var i = 0; i < j; i++) {
michael@0 24209 var p = rpo[predecessors[i].id];
michael@0 24210 if (p === newIdom) {
michael@0 24211 continue;
michael@0 24212 }
michael@0 24213 if (p in doms) {
michael@0 24214 newIdom = intersectDominators(doms, p, newIdom);
michael@0 24215 }
michael@0 24216 }
michael@0 24217 if (doms[b] !== newIdom) {
michael@0 24218 doms[b] = newIdom;
michael@0 24219 changed = true;
michael@0 24220 }
michael@0 24221 }
michael@0 24222 }
michael@0 24223 blocks[0].dominator = blocks[0];
michael@0 24224 var block;
michael@0 24225 for (var b = 1; b < n; b++) {
michael@0 24226 block = blocks[b];
michael@0 24227 var idom = blocks[doms[b]];
michael@0 24228 block.dominator = idom;
michael@0 24229 idom.dominatees.push(block);
michael@0 24230 block.npredecessors = block.predecessors.length;
michael@0 24231 }
michael@0 24232 var worklist = [
michael@0 24233 blocks[0]
michael@0 24234 ];
michael@0 24235 blocks[0].level || (blocks[0].level = 0);
michael@0 24236 while (block = worklist.shift()) {
michael@0 24237 var dominatees = block.dominatees;
michael@0 24238 for (var i = 0, j = dominatees.length; i < j; i++) {
michael@0 24239 dominatees[i].level = block.level + 1;
michael@0 24240 }
michael@0 24241 worklist.push.apply(worklist, dominatees);
michael@0 24242 }
michael@0 24243 },
michael@0 24244 computeFrontiers: function computeFrontiers() {
michael@0 24245 var BlockSet = this.BlockSet;
michael@0 24246 var blocks = this.blocks;
michael@0 24247 for (var b = 0, n = blocks.length; b < n; b++) {
michael@0 24248 blocks[b].frontier = new BlockSet();
michael@0 24249 }
michael@0 24250 for (var b = 1, n = blocks.length; b < n; b++) {
michael@0 24251 var block = blocks[b];
michael@0 24252 var predecessors = block.predecessors;
michael@0 24253 if (predecessors.length >= 2) {
michael@0 24254 var idom = block.dominator;
michael@0 24255 for (var i = 0, j = predecessors.length; i < j; i++) {
michael@0 24256 var runner = predecessors[i];
michael@0 24257 while (runner !== idom) {
michael@0 24258 runner.frontier.set(block.id);
michael@0 24259 runner = runner.dominator;
michael@0 24260 }
michael@0 24261 }
michael@0 24262 }
michael@0 24263 }
michael@0 24264 },
michael@0 24265 analyzeControlFlow: function analyzeControlFlow() {
michael@0 24266 this.computeDominance();
michael@0 24267 this.analyzedControlFlow = true;
michael@0 24268 return true;
michael@0 24269 },
michael@0 24270 markLoops: function markLoops() {
michael@0 24271 if (!this.analyzedControlFlow && !this.analyzeControlFlow()) {
michael@0 24272 return false;
michael@0 24273 }
michael@0 24274 var BlockSet = this.BlockSet;
michael@0 24275 function findSCCs(root) {
michael@0 24276 var preorderId = 1;
michael@0 24277 var preorder = {};
michael@0 24278 var assigned = {};
michael@0 24279 var unconnectedNodes = [];
michael@0 24280 var pendingNodes = [];
michael@0 24281 var sccs = [];
michael@0 24282 var level = root.level + 1;
michael@0 24283 var worklist = [
michael@0 24284 root
michael@0 24285 ];
michael@0 24286 var node;
michael@0 24287 var u, s;
michael@0 24288 while (node = worklist.top()) {
michael@0 24289 if (preorder[node.id]) {
michael@0 24290 if (pendingNodes.peek() === node) {
michael@0 24291 pendingNodes.pop();
michael@0 24292 var scc = [];
michael@0 24293 do {
michael@0 24294 u = unconnectedNodes.pop();
michael@0 24295 assigned[u.id] = true;
michael@0 24296 scc.push(u);
michael@0 24297 } while (u !== node);
michael@0 24298 if (scc.length > 1 || u.spbacks && u.spbacks.get(u.id)) {
michael@0 24299 sccs.push(scc);
michael@0 24300 }
michael@0 24301 }
michael@0 24302 worklist.pop();
michael@0 24303 continue;
michael@0 24304 }
michael@0 24305 preorder[node.id] = preorderId++;
michael@0 24306 unconnectedNodes.push(node);
michael@0 24307 pendingNodes.push(node);
michael@0 24308 var successors = node.successors;
michael@0 24309 for (var i = 0, j = successors.length; i < j; i++) {
michael@0 24310 s = successors[i];
michael@0 24311 if (s.level < level) {
michael@0 24312 continue;
michael@0 24313 }
michael@0 24314 var sid = s.id;
michael@0 24315 if (!preorder[sid]) {
michael@0 24316 worklist.push(s);
michael@0 24317 } else if (!assigned[sid]) {
michael@0 24318 while (preorder[pendingNodes.peek().id] > preorder[sid]) {
michael@0 24319 pendingNodes.pop();
michael@0 24320 }
michael@0 24321 }
michael@0 24322 }
michael@0 24323 }
michael@0 24324 return sccs;
michael@0 24325 }
michael@0 24326 function findLoopHeads(blocks) {
michael@0 24327 var heads = new BlockSet();
michael@0 24328 for (var i = 0, j = blocks.length; i < j; i++) {
michael@0 24329 var block = blocks[i];
michael@0 24330 var spbacks = block.spbacks;
michael@0 24331 if (!spbacks) {
michael@0 24332 continue;
michael@0 24333 }
michael@0 24334 var successors = block.successors;
michael@0 24335 for (var k = 0, l = successors.length; k < l; k++) {
michael@0 24336 var s = successors[k];
michael@0 24337 if (spbacks.get(s.id)) {
michael@0 24338 heads.set(s.dominator.id);
michael@0 24339 }
michael@0 24340 }
michael@0 24341 }
michael@0 24342 return heads.members();
michael@0 24343 }
michael@0 24344 function LoopInfo(scc, loopId) {
michael@0 24345 var body = new BlockSet();
michael@0 24346 body.setBlocks(scc);
michael@0 24347 body.recount();
michael@0 24348 this.id = loopId;
michael@0 24349 this.body = body;
michael@0 24350 this.exit = new BlockSet();
michael@0 24351 this.save = {};
michael@0 24352 this.head = new BlockSet();
michael@0 24353 this.npredecessors = 0;
michael@0 24354 }
michael@0 24355 var heads = findLoopHeads(this.blocks);
michael@0 24356 if (heads.length <= 0) {
michael@0 24357 this.markedLoops = true;
michael@0 24358 return true;
michael@0 24359 }
michael@0 24360 var worklist = heads.sort(function (a, b) {
michael@0 24361 return a.level - b.level;
michael@0 24362 });
michael@0 24363 var loopId = 0;
michael@0 24364 for (var n = worklist.length - 1; n >= 0; n--) {
michael@0 24365 var top = worklist[n];
michael@0 24366 var sccs = findSCCs(top);
michael@0 24367 if (sccs.length === 0) {
michael@0 24368 continue;
michael@0 24369 }
michael@0 24370 for (var i = 0, j = sccs.length; i < j; i++) {
michael@0 24371 var scc = sccs[i];
michael@0 24372 var loop = new LoopInfo(scc, loopId++);
michael@0 24373 for (var k = 0, l = scc.length; k < l; k++) {
michael@0 24374 var h = scc[k];
michael@0 24375 if (h.level === top.level + 1 && !h.loop) {
michael@0 24376 h.loop = loop;
michael@0 24377 loop.head.set(h.id);
michael@0 24378 var predecessors = h.predecessors;
michael@0 24379 for (var pi = 0, pj = predecessors.length; pi < pj; pi++) {
michael@0 24380 loop.body.get(predecessors[pi].id) && h.npredecessors--;
michael@0 24381 }
michael@0 24382 loop.npredecessors += h.npredecessors;
michael@0 24383 }
michael@0 24384 }
michael@0 24385 for (var k = 0, l = scc.length; k < l; k++) {
michael@0 24386 var h = scc[k];
michael@0 24387 if (h.level === top.level + 1) {
michael@0 24388 h.npredecessors = loop.npredecessors;
michael@0 24389 }
michael@0 24390 }
michael@0 24391 loop.head.recount();
michael@0 24392 }
michael@0 24393 }
michael@0 24394 this.markedLoops = true;
michael@0 24395 return true;
michael@0 24396 },
michael@0 24397 induceControlTree: function induceControlTree() {
michael@0 24398 var hasExceptions = this.hasExceptions;
michael@0 24399 var BlockSet = this.BlockSet;
michael@0 24400 function maybe(exit, save) {
michael@0 24401 exit.recount();
michael@0 24402 if (exit.count === 0) {
michael@0 24403 return null;
michael@0 24404 }
michael@0 24405 exit.save = save;
michael@0 24406 return exit;
michael@0 24407 }
michael@0 24408 var exceptionId = this.blocks.length;
michael@0 24409 function induce(head, exit, save, loop, inLoopHead, lookupSwitch, fallthrough) {
michael@0 24410 var v = [];
michael@0 24411 while (head) {
michael@0 24412 if (head.count > 1) {
michael@0 24413 var exit2 = new BlockSet();
michael@0 24414 var save2 = {};
michael@0 24415 var cases = [];
michael@0 24416 var heads = head.members();
michael@0 24417 for (var i = 0, j = heads.length; i < j; i++) {
michael@0 24418 var h = heads[i];
michael@0 24419 var bid = h.id;
michael@0 24420 var c;
michael@0 24421 if (h.loop && head.contains(h.loop.head)) {
michael@0 24422 var loop2 = h.loop;
michael@0 24423 if (!loop2.induced) {
michael@0 24424 var lheads = loop2.head.members();
michael@0 24425 var lheadsave = 0;
michael@0 24426 for (k = 0, l = lheads.length; k < l; k++) {
michael@0 24427 lheadsave += head.save[lheads[k].id];
michael@0 24428 }
michael@0 24429 if (h.npredecessors - lheadsave > 0) {
michael@0 24430 h.npredecessors -= head.save[bid];
michael@0 24431 h.save = head.save[bid];
michael@0 24432 c = induce(h, exit2, save2, loop);
michael@0 24433 cases.push(new Control.LabelCase([
michael@0 24434 bid
michael@0 24435 ], c));
michael@0 24436 } else {
michael@0 24437 for (k = 0, l = lheads.length; k < l; k++) {
michael@0 24438 var lh = lheads[k];
michael@0 24439 lh.npredecessors -= lheadsave;
michael@0 24440 lh.save = lheadsave;
michael@0 24441 }
michael@0 24442 c = induce(h, exit2, save2, loop);
michael@0 24443 cases.push(new Control.LabelCase(loop2.head.toArray(), c));
michael@0 24444 loop2.induced = true;
michael@0 24445 }
michael@0 24446 }
michael@0 24447 } else {
michael@0 24448 h.npredecessors -= head.save[bid];
michael@0 24449 h.save = head.save[bid];
michael@0 24450 c = induce(h, exit2, save2, loop);
michael@0 24451 cases.push(new Control.LabelCase([
michael@0 24452 bid
michael@0 24453 ], c));
michael@0 24454 }
michael@0 24455 }
michael@0 24456 var pruned = [];
michael@0 24457 var k = 0;
michael@0 24458 var c;
michael@0 24459 for (var i = 0, j = cases.length; i < j; i++) {
michael@0 24460 c = cases[i];
michael@0 24461 var labels = c.labels;
michael@0 24462 var lk = 0;
michael@0 24463 for (var ln = 0, nlabels = labels.length; ln < nlabels; ln++) {
michael@0 24464 var bid = labels[ln];
michael@0 24465 if (exit2.get(bid) && heads[i].npredecessors - head.save[bid] > 0) {
michael@0 24466 pruned.push(bid);
michael@0 24467 } else {
michael@0 24468 labels[lk++] = bid;
michael@0 24469 }
michael@0 24470 }
michael@0 24471 labels.length = lk;
michael@0 24472 if (labels.length > 0) {
michael@0 24473 cases[k++] = c;
michael@0 24474 }
michael@0 24475 }
michael@0 24476 cases.length = k;
michael@0 24477 if (cases.length === 0) {
michael@0 24478 for (var i = 0, j = pruned.length; i < j; i++) {
michael@0 24479 var bid = pruned[i];
michael@0 24480 save[bid] = (save[bid] || 0) + head.save[bid];
michael@0 24481 exit.set(bid);
michael@0 24482 }
michael@0 24483 break;
michael@0 24484 }
michael@0 24485 v.push(new Control.LabelSwitch(cases));
michael@0 24486 head = maybe(exit2, save2);
michael@0 24487 continue;
michael@0 24488 }
michael@0 24489 var h, bid, c;
michael@0 24490 if (head.count === 1) {
michael@0 24491 h = head.choose();
michael@0 24492 bid = h.id;
michael@0 24493 h.npredecessors -= head.save[bid];
michael@0 24494 h.save = head.save[bid];
michael@0 24495 } else {
michael@0 24496 h = head;
michael@0 24497 bid = h.id;
michael@0 24498 }
michael@0 24499 if (inLoopHead) {
michael@0 24500 inLoopHead = false;
michael@0 24501 } else {
michael@0 24502 if (loop && !loop.body.get(bid)) {
michael@0 24503 h.npredecessors += h.save;
michael@0 24504 loop.exit.set(bid);
michael@0 24505 loop.save[bid] = (loop.save[bid] || 0) + h.save;
michael@0 24506 v.push(new Control.Break(bid, loop));
michael@0 24507 break;
michael@0 24508 }
michael@0 24509 if (loop && h.loop === loop) {
michael@0 24510 h.npredecessors += h.save;
michael@0 24511 v.push(new Control.Continue(bid, loop));
michael@0 24512 break;
michael@0 24513 }
michael@0 24514 if (h === fallthrough) {
michael@0 24515 break;
michael@0 24516 }
michael@0 24517 if (h.npredecessors > 0) {
michael@0 24518 h.npredecessors += h.save;
michael@0 24519 save[bid] = (save[bid] || 0) + h.save;
michael@0 24520 exit.set(bid);
michael@0 24521 v.push(lookupSwitch ? new Control.Break(bid, lookupSwitch) : new Control.Exit(bid));
michael@0 24522 break;
michael@0 24523 }
michael@0 24524 if (h.loop) {
michael@0 24525 var l = h.loop;
michael@0 24526 var body;
michael@0 24527 if (l.head.count === 1) {
michael@0 24528 body = induce(l.head.choose(), null, null, l, true);
michael@0 24529 } else {
michael@0 24530 var lcases = [];
michael@0 24531 var lheads = l.head.members();
michael@0 24532 for (var i = 0, j = lheads.length; i < j; i++) {
michael@0 24533 var lh = lheads[i];
michael@0 24534 var lbid = lh.id;
michael@0 24535 var c = induce(lh, null, null, l, true);
michael@0 24536 lcases.push(new Control.LabelCase([
michael@0 24537 lbid
michael@0 24538 ], c));
michael@0 24539 }
michael@0 24540 body = new Control.LabelSwitch(lcases);
michael@0 24541 }
michael@0 24542 v.push(new Control.Loop(body));
michael@0 24543 head = maybe(l.exit, l.save);
michael@0 24544 continue;
michael@0 24545 }
michael@0 24546 }
michael@0 24547 var sv;
michael@0 24548 var successors;
michael@0 24549 var exit2 = new BlockSet();
michael@0 24550 var save2 = {};
michael@0 24551 if (hasExceptions && h.hasCatches) {
michael@0 24552 var allsuccessors = h.successors;
michael@0 24553 var catchsuccessors = [];
michael@0 24554 successors = [];
michael@0 24555 for (var i = 0, j = allsuccessors.length; i < j; i++) {
michael@0 24556 var s = allsuccessors[i];
michael@0 24557 (s.exception ? catchsuccessors : successors).push(s);
michael@0 24558 }
michael@0 24559 var catches = [];
michael@0 24560 for (var i = 0, j = catchsuccessors.length; i < j; i++) {
michael@0 24561 var t = catchsuccessors[i];
michael@0 24562 t.npredecessors -= 1;
michael@0 24563 t.save = 1;
michael@0 24564 var c = induce(t, exit2, save2, loop);
michael@0 24565 var ex = t.exception;
michael@0 24566 catches.push(new Control.Catch(ex.varName, ex.typeName, c));
michael@0 24567 }
michael@0 24568 sv = new Control.Try(h, catches);
michael@0 24569 } else {
michael@0 24570 successors = h.successors;
michael@0 24571 sv = h;
michael@0 24572 }
michael@0 24573 if (successors.length > 2) {
michael@0 24574 var cases = [];
michael@0 24575 var targets = successors;
michael@0 24576 for (var i = targets.length - 1; i >= 0; i--) {
michael@0 24577 var t = targets[i];
michael@0 24578 t.npredecessors -= 1;
michael@0 24579 t.save = 1;
michael@0 24580 c = induce(t, exit2, save2, loop, null, h, targets[i + 1]);
michael@0 24581 cases.unshift(new Control.Case(i, c));
michael@0 24582 }
michael@0 24583 cases.top().index = undefined;
michael@0 24584 if (hasExceptions && h.hasCatches) {
michael@0 24585 sv.nothingThrownLabel = exceptionId;
michael@0 24586 sv = new Control.Switch(sv, cases, exceptionId++);
michael@0 24587 } else {
michael@0 24588 sv = new Control.Switch(sv, cases);
michael@0 24589 }
michael@0 24590 head = maybe(exit2, save2);
michael@0 24591 } else if (successors.length === 2) {
michael@0 24592 var branch1 = h.hasFlippedSuccessors ? successors[1] : successors[0];
michael@0 24593 var branch2 = h.hasFlippedSuccessors ? successors[0] : successors[1];
michael@0 24594 branch1.npredecessors -= 1;
michael@0 24595 branch1.save = 1;
michael@0 24596 var c1 = induce(branch1, exit2, save2, loop);
michael@0 24597 branch2.npredecessors -= 1;
michael@0 24598 branch2.save = 1;
michael@0 24599 var c2 = induce(branch2, exit2, save2, loop);
michael@0 24600 if (hasExceptions && h.hasCatches) {
michael@0 24601 sv.nothingThrownLabel = exceptionId;
michael@0 24602 sv = new Control.If(sv, c1, c2, exceptionId++);
michael@0 24603 } else {
michael@0 24604 sv = new Control.If(sv, c1, c2);
michael@0 24605 }
michael@0 24606 head = maybe(exit2, save2);
michael@0 24607 } else {
michael@0 24608 c = successors[0];
michael@0 24609 if (c) {
michael@0 24610 if (hasExceptions && h.hasCatches) {
michael@0 24611 sv.nothingThrownLabel = c.id;
michael@0 24612 save2[c.id] = (save2[c.id] || 0) + 1;
michael@0 24613 exit2.set(c.id);
michael@0 24614 head = maybe(exit2, save2);
michael@0 24615 } else {
michael@0 24616 c.npredecessors -= 1;
michael@0 24617 c.save = 1;
michael@0 24618 head = c;
michael@0 24619 }
michael@0 24620 } else {
michael@0 24621 if (hasExceptions && h.hasCatches) {
michael@0 24622 sv.nothingThrownLabel = -1;
michael@0 24623 head = maybe(exit2, save2);
michael@0 24624 } else {
michael@0 24625 head = c;
michael@0 24626 }
michael@0 24627 }
michael@0 24628 }
michael@0 24629 v.push(sv);
michael@0 24630 }
michael@0 24631 if (v.length > 1) {
michael@0 24632 return new Control.Seq(v);
michael@0 24633 }
michael@0 24634 return v[0];
michael@0 24635 }
michael@0 24636 var root = this.blocks[0];
michael@0 24637 this.controlTree = induce(root, new BlockSet(), {});
michael@0 24638 },
michael@0 24639 restructureControlFlow: function restructureControlFlow() {
michael@0 24640 Timer.start('Restructure Control Flow');
michael@0 24641 if (!this.markedLoops && !this.markLoops()) {
michael@0 24642 Timer.stop();
michael@0 24643 return false;
michael@0 24644 }
michael@0 24645 this.induceControlTree();
michael@0 24646 this.restructuredControlFlow = true;
michael@0 24647 Timer.stop();
michael@0 24648 return true;
michael@0 24649 },
michael@0 24650 trace: function (writer) {
michael@0 24651 function bid(node) {
michael@0 24652 return node.id;
michael@0 24653 }
michael@0 24654 function traceBlock(block) {
michael@0 24655 if (!block.dominator) {
michael@0 24656 writer.enter('block unreachable {');
michael@0 24657 } else {
michael@0 24658 writer.enter('block ' + block.id + (block.successors.length > 0 ? ' -> ' + block.successors.map(bid).join(',') : '') + ' {');
michael@0 24659 writer.writeLn('npredecessors'.padRight(' ', 10) + block.npredecessors);
michael@0 24660 writer.writeLn('idom'.padRight(' ', 10) + block.dominator.id);
michael@0 24661 writer.writeLn('domcs'.padRight(' ', 10) + block.dominatees.map(bid).join(','));
michael@0 24662 if (block.frontier) {
michael@0 24663 writer.writeLn('frontier'.padRight(' ', 10) + '{' + block.frontier.toArray().join(',') + '}');
michael@0 24664 }
michael@0 24665 writer.writeLn('level'.padRight(' ', 10) + block.level);
michael@0 24666 }
michael@0 24667 if (block.loop) {
michael@0 24668 writer.writeLn('loop'.padRight(' ', 10) + '{' + block.loop.body.toArray().join(',') + '}');
michael@0 24669 writer.writeLn(' id'.padRight(' ', 10) + block.loop.id);
michael@0 24670 writer.writeLn(' head'.padRight(' ', 10) + '{' + block.loop.head.toArray().join(',') + '}');
michael@0 24671 writer.writeLn(' exit'.padRight(' ', 10) + '{' + block.loop.exit.toArray().join(',') + '}');
michael@0 24672 writer.writeLn(' npredecessors'.padRight(' ', 10) + block.loop.npredecessors);
michael@0 24673 }
michael@0 24674 writer.writeLn('');
michael@0 24675 if (block.position >= 0) {
michael@0 24676 for (var bci = block.position; bci <= block.end.position; bci++) {
michael@0 24677 writer.writeLn(('' + bci).padRight(' ', 5) + bytecodes[bci]);
michael@0 24678 }
michael@0 24679 } else {
michael@0 24680 writer.writeLn('abstract');
michael@0 24681 }
michael@0 24682 writer.leave('}');
michael@0 24683 }
michael@0 24684 var bytecodes = this.bytecodes;
michael@0 24685 writer.enter('analysis {');
michael@0 24686 writer.enter('cfg {');
michael@0 24687 this.blocks.forEach(traceBlock);
michael@0 24688 writer.leave('}');
michael@0 24689 if (this.controlTree) {
michael@0 24690 writer.enter('control-tree {');
michael@0 24691 this.controlTree.trace(writer);
michael@0 24692 writer.leave('}');
michael@0 24693 }
michael@0 24694 writer.leave('}');
michael@0 24695 },
michael@0 24696 traceCFG: makeVizTrace([
michael@0 24697 {
michael@0 24698 fn: function (n) {
michael@0 24699 return n.successors || [];
michael@0 24700 },
michael@0 24701 style: ''
michael@0 24702 }
michael@0 24703 ], [
michael@0 24704 {
michael@0 24705 fn: function (n) {
michael@0 24706 return n.predecessors || [];
michael@0 24707 },
michael@0 24708 style: ''
michael@0 24709 }
michael@0 24710 ]),
michael@0 24711 traceDJ: makeVizTrace([
michael@0 24712 {
michael@0 24713 fn: function (n) {
michael@0 24714 return n.dominatees || [];
michael@0 24715 },
michael@0 24716 style: 'style=dashed'
michael@0 24717 },
michael@0 24718 {
michael@0 24719 fn: function (n) {
michael@0 24720 var crosses = new this.BlockSet();
michael@0 24721 crosses.setBlocks(n.successors);
michael@0 24722 crosses.subtract(this.BlockSet.fromBlocks(n.dominatees));
michael@0 24723 n.spbacks && crosses.subtract(n.spbacks);
michael@0 24724 return crosses.members();
michael@0 24725 },
michael@0 24726 style: ''
michael@0 24727 },
michael@0 24728 {
michael@0 24729 fn: function (n) {
michael@0 24730 return n.spbacks ? n.spbacks.members() : [];
michael@0 24731 },
michael@0 24732 style: 'style=bold'
michael@0 24733 }
michael@0 24734 ], [
michael@0 24735 {
michael@0 24736 fn: function (n) {
michael@0 24737 return n.predecessors || [];
michael@0 24738 },
michael@0 24739 style: ''
michael@0 24740 }
michael@0 24741 ], function (idFn, writer) {
michael@0 24742 var root = this.bytecodes[0];
michael@0 24743 var worklist = [
michael@0 24744 root
michael@0 24745 ];
michael@0 24746 var n;
michael@0 24747 var level = root.level;
michael@0 24748 var currentLevel = [];
michael@0 24749 while (n = worklist.shift()) {
michael@0 24750 if (level != n.level) {
michael@0 24751 writer.writeLn('{rank=same; ' + currentLevel.map(function (n) {
michael@0 24752 return 'block_' + idFn(n);
michael@0 24753 }).join(' ') + '}');
michael@0 24754 currentLevel.length = 0;
michael@0 24755 level = n.level;
michael@0 24756 }
michael@0 24757 currentLevel.push(n);
michael@0 24758 worklist.push.apply(worklist, n.dominatees);
michael@0 24759 }
michael@0 24760 })
michael@0 24761 };
michael@0 24762 function makeVizTrace(successorFns, predecessorFns, postHook) {
michael@0 24763 return function (writer, name, prefix) {
michael@0 24764 function idFn(n) {
michael@0 24765 return prefix + n.id;
michael@0 24766 }
michael@0 24767 var analysis = this;
michael@0 24768 function bindToThis(x) {
michael@0 24769 x.fn = x.fn.bind(analysis);
michael@0 24770 }
michael@0 24771 prefix = prefix || '';
michael@0 24772 var bytecodes = this.bytecodes;
michael@0 24773 if (!bytecodes) {
michael@0 24774 return;
michael@0 24775 }
michael@0 24776 successorFns.forEach(bindToThis);
michael@0 24777 predecessorFns.forEach(bindToThis);
michael@0 24778 writeGraphViz(writer, name.toString(), bytecodes[0], idFn, function (n) {
michael@0 24779 return n.successors || [];
michael@0 24780 }, successorFns, predecessorFns, function (n) {
michael@0 24781 var str = 'Block: ' + n.id + '\\l';
michael@0 24782 return str;
michael@0 24783 }, postHook && postHook.bind(this, idFn));
michael@0 24784 };
michael@0 24785 }
michael@0 24786 return Analysis;
michael@0 24787 }();
michael@0 24788 exports.Control = Control;
michael@0 24789 exports.analyze = function (cfg) {
michael@0 24790 var analysis = new Analysis(cfg);
michael@0 24791 analysis.restructureControlFlow();
michael@0 24792 return analysis.controlTree;
michael@0 24793 };
michael@0 24794 }(typeof exports === 'undefined' ? Looper = {} : exports));
michael@0 24795 (function (exports) {
michael@0 24796 var TRACE_REGISTER_ALLOCATOR = false;
michael@0 24797 var T = estransform;
michael@0 24798 var Node = T.Node;
michael@0 24799 var Identifier = T.Identifier;
michael@0 24800 var VariableDeclaration = T.VariableDeclaration;
michael@0 24801 var VariableDeclarator = T.VariableDeclarator;
michael@0 24802 var AssignmentExpression = T.AssignmentExpression;
michael@0 24803 var MemberExpression = T.MemberExpression;
michael@0 24804 var IfStatement = T.IfStatement;
michael@0 24805 var WhileStatement = T.WhileStatement;
michael@0 24806 var FunctionDeclaration = T.FunctionDeclaration;
michael@0 24807 var writer = new IndentingWriter();
michael@0 24808 var LinearScan = function () {
michael@0 24809 function Interval(id, start, end) {
michael@0 24810 this.id = id;
michael@0 24811 this.start = start;
michael@0 24812 this.end = end;
michael@0 24813 }
michael@0 24814 Interval.prototype.toString = function () {
michael@0 24815 return '[' + this.start + ',' + this.end + ']';
michael@0 24816 };
michael@0 24817 function linearScan(intervals, maxRegisters) {
michael@0 24818 this.intervals = intervals.slice(0);
michael@0 24819 this.maxRegisters = maxRegisters;
michael@0 24820 }
michael@0 24821 linearScan.prototype.allocate = function () {
michael@0 24822 var intervals = this.intervals;
michael@0 24823 this.intervals.sort(function (a, b) {
michael@0 24824 return a.start - b.start;
michael@0 24825 });
michael@0 24826 var active = new SortedList(function (a, b) {
michael@0 24827 return a.end - b.end;
michael@0 24828 });
michael@0 24829 var maxRegisters = this.maxRegisters;
michael@0 24830 var freeRegisters = [];
michael@0 24831 for (var i = maxRegisters - 1; i >= 0; i--) {
michael@0 24832 freeRegisters.push('R' + i);
michael@0 24833 }
michael@0 24834 intervals.forEach(function (i) {
michael@0 24835 expireOldIntervals(i);
michael@0 24836 if (active.length === maxRegisters) {
michael@0 24837 notImplemented('Cannot Spill');
michael@0 24838 } else {
michael@0 24839 i.register = freeRegisters.pop();
michael@0 24840 TRACE_REGISTER_ALLOCATOR && writer.writeLn('Allocate: ' + i + ' ' + i.id + ' -> ' + i.register);
michael@0 24841 active.push(i);
michael@0 24842 }
michael@0 24843 });
michael@0 24844 function expireOldIntervals(i) {
michael@0 24845 active.forEach(function (j) {
michael@0 24846 if (j.end >= i.start) {
michael@0 24847 return SortedList.RETURN;
michael@0 24848 }
michael@0 24849 freeRegisters.push(j.register);
michael@0 24850 TRACE_REGISTER_ALLOCATOR && writer.writeLn('Release: ' + j + ' -> ' + j.register);
michael@0 24851 return SortedList.DELETE;
michael@0 24852 });
michael@0 24853 }
michael@0 24854 };
michael@0 24855 linearScan.Interval = Interval;
michael@0 24856 return linearScan;
michael@0 24857 }();
michael@0 24858 function allocateRegisters(program) {
michael@0 24859 var scan = T.makePass('scan', 'scanNode');
michael@0 24860 var label = 0;
michael@0 24861 Node.prototype.scan = function (o) {
michael@0 24862 this.position = label++;
michael@0 24863 return scan.apply(this, o);
michael@0 24864 };
michael@0 24865 var variables = [];
michael@0 24866 var variableIndexMap = {};
michael@0 24867 var identifiers = [];
michael@0 24868 FunctionDeclaration.prototype.scan = function () {
michael@0 24869 this.params.forEach(function (identifier) {
michael@0 24870 if (!(identifier.name in variableIndexMap)) {
michael@0 24871 variableIndexMap[identifier.name] = variables.length;
michael@0 24872 variables.push(identifier.name);
michael@0 24873 }
michael@0 24874 });
michael@0 24875 this.body.scan();
michael@0 24876 return this;
michael@0 24877 };
michael@0 24878 VariableDeclarator.prototype.scan = function () {
michael@0 24879 this.position = label++;
michael@0 24880 if (!(this.id.name in variableIndexMap)) {
michael@0 24881 variableIndexMap[this.id.name] = variables.length;
michael@0 24882 variables.push(this.id.name);
michael@0 24883 }
michael@0 24884 return this;
michael@0 24885 };
michael@0 24886 AssignmentExpression.prototype.scan = function (o) {
michael@0 24887 this.left.scan(o);
michael@0 24888 this.right.scan(o);
michael@0 24889 this.position = label++;
michael@0 24890 return this;
michael@0 24891 };
michael@0 24892 WhileStatement.prototype.scan = function (o) {
michael@0 24893 this.position = label++;
michael@0 24894 this.test.scan(o);
michael@0 24895 this.body.scan(o);
michael@0 24896 this.afterPosition = label++;
michael@0 24897 return this;
michael@0 24898 };
michael@0 24899 program.scan();
michael@0 24900 TRACE_REGISTER_ALLOCATOR && writer.writeLn('Local Variables: ' + variables);
michael@0 24901 var Set = BitSetFunctor(variables.length);
michael@0 24902 var Range = BitSetFunctor(label);
michael@0 24903 var ranges = [];
michael@0 24904 for (var i = 0; i < variables.length; i++) {
michael@0 24905 ranges.push(new Range());
michael@0 24906 }
michael@0 24907 function fill(range) {
michael@0 24908 var start = -1;
michael@0 24909 for (var i = 0; i < range.length; i++) {
michael@0 24910 if (range.get(i)) {
michael@0 24911 start = i;
michael@0 24912 break;
michael@0 24913 }
michael@0 24914 }
michael@0 24915 for (var i = range.length - 1; i >= 0; i--) {
michael@0 24916 if (range.get(i)) {
michael@0 24917 end = i;
michael@0 24918 break;
michael@0 24919 }
michael@0 24920 }
michael@0 24921 for (var i = start; i < end; i++) {
michael@0 24922 range.set(i);
michael@0 24923 }
michael@0 24924 }
michael@0 24925 function getRange(range) {
michael@0 24926 var start = -1, end = -1;
michael@0 24927 for (var i = 0; i < range.length; i++) {
michael@0 24928 if (range.get(i)) {
michael@0 24929 start = i;
michael@0 24930 break;
michael@0 24931 }
michael@0 24932 }
michael@0 24933 for (var i = range.length - 1; i >= 0; i--) {
michael@0 24934 if (range.get(i)) {
michael@0 24935 end = i;
michael@0 24936 break;
michael@0 24937 }
michael@0 24938 }
michael@0 24939 return [
michael@0 24940 start,
michael@0 24941 end
michael@0 24942 ];
michael@0 24943 }
michael@0 24944 function use(set, name, position) {
michael@0 24945 var index = variableIndexMap[name];
michael@0 24946 ranges[index].set(position);
michael@0 24947 set.set(index);
michael@0 24948 }
michael@0 24949 function def(set, name, position) {
michael@0 24950 var index = variableIndexMap[name];
michael@0 24951 ranges[index].set(position);
michael@0 24952 set.clear(index);
michael@0 24953 }
michael@0 24954 Node.prototype.markLiveness = T.makePass('markLiveness', 'markLivenessNode', true);
michael@0 24955 Identifier.prototype.markLiveness = function (o) {
michael@0 24956 var name = this.name;
michael@0 24957 if (name === 'undefined') {
michael@0 24958 return this;
michael@0 24959 }
michael@0 24960 if (o && o.isProperty) {
michael@0 24961 return this;
michael@0 24962 }
michael@0 24963 if (!(name in variableIndexMap)) {
michael@0 24964 return this;
michael@0 24965 }
michael@0 24966 identifiers.push(this);
michael@0 24967 var live = o.live;
michael@0 24968 use(live, name, this.position);
michael@0 24969 return this;
michael@0 24970 };
michael@0 24971 VariableDeclarator.prototype.markLiveness = function (o) {
michael@0 24972 var live = o.live;
michael@0 24973 identifiers.push(this.id);
michael@0 24974 return this;
michael@0 24975 };
michael@0 24976 IfStatement.prototype.markLiveness = function (o) {
michael@0 24977 var a = o.live.clone();
michael@0 24978 var b = o.live.clone();
michael@0 24979 this.alternate && this.alternate.markLiveness({
michael@0 24980 live: a
michael@0 24981 });
michael@0 24982 this.consequent && this.consequent.markLiveness({
michael@0 24983 live: b
michael@0 24984 });
michael@0 24985 o.live.assign(a);
michael@0 24986 o.live._union(b);
michael@0 24987 this.test.markLiveness(o);
michael@0 24988 return this;
michael@0 24989 };
michael@0 24990 WhileStatement.prototype.markLiveness = function (o) {
michael@0 24991 var a = o.live.clone();
michael@0 24992 TRACE_REGISTER_ALLOCATOR && writer.writeLn('END OF LOOP: ' + a);
michael@0 24993 var afterPosition = this.afterPosition;
michael@0 24994 do {
michael@0 24995 var b = a.clone();
michael@0 24996 this.body.markLiveness({
michael@0 24997 live: a
michael@0 24998 });
michael@0 24999 this.test.markLiveness({
michael@0 25000 live: a
michael@0 25001 });
michael@0 25002 TRACE_REGISTER_ALLOCATOR && writer.writeLn('TOP OF LOOP: ' + a);
michael@0 25003 var iterate = !b.equals(a);
michael@0 25004 if (iterate) {
michael@0 25005 TRACE_REGISTER_ALLOCATOR && writer.writeLn('ITERATE');
michael@0 25006 a.forEach(function (i) {
michael@0 25007 ranges[i].set(afterPosition);
michael@0 25008 });
michael@0 25009 }
michael@0 25010 } while (iterate);
michael@0 25011 o.live.assign(a);
michael@0 25012 return this;
michael@0 25013 };
michael@0 25014 AssignmentExpression.prototype.markLiveness = function (o) {
michael@0 25015 this.right.markLiveness(o);
michael@0 25016 if (this.left instanceof Identifier) {
michael@0 25017 def(o.live, this.left.name, this.position);
michael@0 25018 identifiers.push(this.left);
michael@0 25019 } else {
michael@0 25020 this.left.markLiveness(o);
michael@0 25021 }
michael@0 25022 return this;
michael@0 25023 };
michael@0 25024 MemberExpression.prototype.markLiveness = function (o) {
michael@0 25025 if (this.computed || !(this.property instanceof Identifier)) {
michael@0 25026 this.property.markLiveness(o);
michael@0 25027 }
michael@0 25028 this.object.markLiveness(o);
michael@0 25029 return this;
michael@0 25030 };
michael@0 25031 program.markLiveness({
michael@0 25032 live: new Set()
michael@0 25033 });
michael@0 25034 var intervals = [];
michael@0 25035 for (var i = 0; i < ranges.length; i++) {
michael@0 25036 var r = getRange(ranges[i]);
michael@0 25037 intervals.push(new LinearScan.Interval(i, r[0], r[1]));
michael@0 25038 }
michael@0 25039 var allocator = new LinearScan(intervals, 1024);
michael@0 25040 allocator.allocate();
michael@0 25041 var map = createEmptyObject();
michael@0 25042 for (var i = 0; i < variables.length; i++) {
michael@0 25043 map[variables[i]] = intervals[i].register;
michael@0 25044 }
michael@0 25045 if (true) {
michael@0 25046 for (var i = 0; i < identifiers.length; i++) {
michael@0 25047 if (identifiers[i].patched) {
michael@0 25048 continue;
michael@0 25049 }
michael@0 25050 identifiers[i].name = map[identifiers[i].name];
michael@0 25051 identifiers[i].patched = true;
michael@0 25052 }
michael@0 25053 }
michael@0 25054 if (TRACE_REGISTER_ALLOCATOR) {
michael@0 25055 for (var i = 0; i < ranges.length; i++) {
michael@0 25056 fill(ranges[i]);
michael@0 25057 writer.writeLn(String(i).padLeft(' ', 3) + ' ' + variables[i].padRight(' ', 5) + ': ' + ranges[i].toBitString('=', ' ') + ' ' + intervals[i].register);
michael@0 25058 }
michael@0 25059 }
michael@0 25060 return program;
michael@0 25061 }
michael@0 25062 Transform.transform = function (program) {
michael@0 25063 allocateRegisters(program);
michael@0 25064 };
michael@0 25065 }(typeof exports === 'undefined' ? Transform = {} : exports));
michael@0 25066 (function (exports) {
michael@0 25067 var T = estransform;
michael@0 25068 var Literal = T.Literal;
michael@0 25069 var Identifier = T.Identifier;
michael@0 25070 var VariableDeclaration = T.VariableDeclaration;
michael@0 25071 var VariableDeclarator = T.VariableDeclarator;
michael@0 25072 var MemberExpression = T.MemberExpression;
michael@0 25073 var BinaryExpression = T.BinaryExpression;
michael@0 25074 var CallExpression = T.CallExpression;
michael@0 25075 var AssignmentExpression = T.AssignmentExpression;
michael@0 25076 var ExpressionStatement = T.ExpressionStatement;
michael@0 25077 var ReturnStatement = T.ReturnStatement;
michael@0 25078 var FunctionDeclaration = T.FunctionDeclaration;
michael@0 25079 var ConditionalExpression = T.ConditionalExpression;
michael@0 25080 var ObjectExpression = T.ObjectExpression;
michael@0 25081 var ArrayExpression = T.ArrayExpression;
michael@0 25082 var UnaryExpression = T.UnaryExpression;
michael@0 25083 var NewExpression = T.NewExpression;
michael@0 25084 var Property = T.Property;
michael@0 25085 var BlockStatement = T.BlockStatement;
michael@0 25086 var ThisExpression = T.ThisExpression;
michael@0 25087 var ThrowStatement = T.ThrowStatement;
michael@0 25088 var IfStatement = T.IfStatement;
michael@0 25089 var WhileStatement = T.WhileStatement;
michael@0 25090 var BreakStatement = T.BreakStatement;
michael@0 25091 var ContinueStatement = T.ContinueStatement;
michael@0 25092 var SwitchStatement = T.SwitchStatement;
michael@0 25093 var SwitchCase = T.SwitchCase;
michael@0 25094 var Block = IR.Block;
michael@0 25095 var Operator = IR.Operator;
michael@0 25096 var Projection = IR.Projection;
michael@0 25097 var Start = IR.Start;
michael@0 25098 var Control = Looper.Control;
michael@0 25099 var Variable = IR.Variable;
michael@0 25100 Control.Break.prototype.compile = function (cx, state) {
michael@0 25101 return cx.compileBreak(this, state);
michael@0 25102 };
michael@0 25103 Control.Continue.prototype.compile = function (cx, state) {
michael@0 25104 return cx.compileContinue(this, state);
michael@0 25105 };
michael@0 25106 Control.Exit.prototype.compile = function (cx, state) {
michael@0 25107 return cx.compileExit(this, state);
michael@0 25108 };
michael@0 25109 Control.LabelSwitch.prototype.compile = function (cx, state) {
michael@0 25110 return cx.compileLabelSwitch(this, state);
michael@0 25111 };
michael@0 25112 Control.Seq.prototype.compile = function (cx, state) {
michael@0 25113 return cx.compileSequence(this, state);
michael@0 25114 };
michael@0 25115 Block.prototype.compile = function (cx, state) {
michael@0 25116 return cx.compileBlock(this, state);
michael@0 25117 };
michael@0 25118 Control.Loop.prototype.compile = function (cx, state) {
michael@0 25119 return cx.compileLoop(this, state);
michael@0 25120 };
michael@0 25121 Control.Switch.prototype.compile = function (cx, state) {
michael@0 25122 return cx.compileSwitch(this, state);
michael@0 25123 };
michael@0 25124 Control.If.prototype.compile = function (cx, state) {
michael@0 25125 return cx.compileIf(this, state);
michael@0 25126 };
michael@0 25127 Control.Try.prototype.compile = function (cx, state) {
michael@0 25128 return cx.compileTry(this, state);
michael@0 25129 };
michael@0 25130 function constant(value) {
michael@0 25131 if (typeof value === 'string' || value === null || value === true || value === false) {
michael@0 25132 return new Literal(value);
michael@0 25133 } else if (value === undefined) {
michael@0 25134 return new Identifier('undefined');
michael@0 25135 } else if (typeof value === 'object' || typeof value === 'function') {
michael@0 25136 return new Identifier(objectConstantName(value));
michael@0 25137 } else if (typeof value === 'number' && isNaN(value)) {
michael@0 25138 return new Identifier('NaN');
michael@0 25139 } else if (value === Infinity) {
michael@0 25140 return new Identifier('Infinity');
michael@0 25141 } else if (value === -Infinity) {
michael@0 25142 return new UnaryExpression('-', new Identifier('Infinity'));
michael@0 25143 } else if (typeof value === 'number' && 1 / value < 0) {
michael@0 25144 return new UnaryExpression('-', new Literal(Math.abs(value)));
michael@0 25145 } else if (typeof value === 'number') {
michael@0 25146 return new Literal(value);
michael@0 25147 } else {
michael@0 25148 unexpected('Cannot emit constant for value: ', value);
michael@0 25149 }
michael@0 25150 }
michael@0 25151 function id(name) {
michael@0 25152 true;
michael@0 25153 return new Identifier(name);
michael@0 25154 }
michael@0 25155 function isIdentifierStart(c) {
michael@0 25156 return c === '$' || c === '_' || c === '\\' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z';
michael@0 25157 }
michael@0 25158 function isIdentifierPart(c) {
michael@0 25159 return c === '$' || c === '_' || c === '\\' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9';
michael@0 25160 }
michael@0 25161 function isIdentifierName(s) {
michael@0 25162 if (!isIdentifierStart(s[0])) {
michael@0 25163 return false;
michael@0 25164 }
michael@0 25165 for (var i = 1; i < s.length; i++) {
michael@0 25166 if (!isIdentifierPart(s[i])) {
michael@0 25167 return false;
michael@0 25168 }
michael@0 25169 }
michael@0 25170 return true;
michael@0 25171 }
michael@0 25172 function property(obj) {
michael@0 25173 for (var i = 1; i < arguments.length; i++) {
michael@0 25174 var x = arguments[i];
michael@0 25175 if (typeof x === 'string') {
michael@0 25176 if (isIdentifierName(x)) {
michael@0 25177 obj = new MemberExpression(obj, new Identifier(x), false);
michael@0 25178 } else {
michael@0 25179 obj = new MemberExpression(obj, new Literal(x), true);
michael@0 25180 }
michael@0 25181 } else if (x instanceof Literal && isIdentifierName(x.value)) {
michael@0 25182 obj = new MemberExpression(obj, new Identifier(x.value), false);
michael@0 25183 } else {
michael@0 25184 obj = new MemberExpression(obj, x, true);
michael@0 25185 }
michael@0 25186 }
michael@0 25187 return obj;
michael@0 25188 }
michael@0 25189 function call(callee, args) {
michael@0 25190 true;
michael@0 25191 true;
michael@0 25192 return new CallExpression(callee, args);
michael@0 25193 }
michael@0 25194 function callCall(callee, object, args) {
michael@0 25195 return call(property(callee, 'call'), [
michael@0 25196 object
michael@0 25197 ].concat(args));
michael@0 25198 }
michael@0 25199 function assignment(left, right) {
michael@0 25200 true;
michael@0 25201 return new AssignmentExpression(left, '=', right);
michael@0 25202 }
michael@0 25203 function variableDeclaration(declarations) {
michael@0 25204 return new VariableDeclaration('var', declarations);
michael@0 25205 }
michael@0 25206 function negate(node) {
michael@0 25207 if (node instanceof Constant) {
michael@0 25208 if (node.value === true || node.value === false) {
michael@0 25209 return constant(!node.value);
michael@0 25210 }
michael@0 25211 } else if (node instanceof Identifier) {
michael@0 25212 return new UnaryExpression(Operator.FALSE.name, node);
michael@0 25213 }
michael@0 25214 true;
michael@0 25215 var left = node instanceof BinaryExpression ? node.left : node.argument;
michael@0 25216 var right = node.right;
michael@0 25217 var operator = Operator.fromName(node.operator);
michael@0 25218 if (operator === Operator.EQ && right instanceof Literal && right.value === false) {
michael@0 25219 return left;
michael@0 25220 }
michael@0 25221 if (operator === Operator.FALSE) {
michael@0 25222 return left;
michael@0 25223 }
michael@0 25224 if (operator.not) {
michael@0 25225 if (node instanceof BinaryExpression) {
michael@0 25226 return new BinaryExpression(operator.not.name, left, right);
michael@0 25227 } else {
michael@0 25228 return new UnaryExpression(operator.not.name, left);
michael@0 25229 }
michael@0 25230 }
michael@0 25231 return new UnaryExpression(Operator.FALSE.name, node);
michael@0 25232 }
michael@0 25233 function Context() {
michael@0 25234 this.label = new Variable('$L');
michael@0 25235 this.variables = [];
michael@0 25236 this.parameters = [];
michael@0 25237 }
michael@0 25238 Context.prototype.useVariable = function (variable) {
michael@0 25239 true;
michael@0 25240 return this.variables.pushUnique(variable);
michael@0 25241 };
michael@0 25242 Context.prototype.useParameter = function (parameter) {
michael@0 25243 return this.parameters[parameter.index] = parameter;
michael@0 25244 };
michael@0 25245 Context.prototype.compileLabelBody = function compileLabelBody(node) {
michael@0 25246 var body = [];
michael@0 25247 if (node.label !== undefined) {
michael@0 25248 this.useVariable(this.label);
michael@0 25249 body.push(new ExpressionStatement(assignment(id(this.label.name), new Literal(node.label))));
michael@0 25250 }
michael@0 25251 return body;
michael@0 25252 };
michael@0 25253 Context.prototype.compileBreak = function compileBreak(node) {
michael@0 25254 var body = this.compileLabelBody(node);
michael@0 25255 body.push(new BreakStatement(null));
michael@0 25256 return new BlockStatement(body);
michael@0 25257 };
michael@0 25258 Context.prototype.compileContinue = function compileContinue(node) {
michael@0 25259 var body = this.compileLabelBody(node);
michael@0 25260 body.push(new ContinueStatement(null));
michael@0 25261 return new BlockStatement(body);
michael@0 25262 };
michael@0 25263 Context.prototype.compileExit = function compileExit(node) {
michael@0 25264 return new BlockStatement(this.compileLabelBody(node));
michael@0 25265 };
michael@0 25266 Context.prototype.compileIf = function compileIf(node) {
michael@0 25267 var cr = node.cond.compile(this);
michael@0 25268 var tr = null, er = null;
michael@0 25269 if (node.then) {
michael@0 25270 tr = node.then.compile(this);
michael@0 25271 }
michael@0 25272 if (node.else) {
michael@0 25273 er = node.else.compile(this);
michael@0 25274 }
michael@0 25275 var condition = compileValue(cr.end.predicate, this);
michael@0 25276 condition = node.negated ? negate(condition) : condition;
michael@0 25277 cr.body.push(new IfStatement(condition, tr || new BlockStatement([]), er || null));
michael@0 25278 return cr;
michael@0 25279 };
michael@0 25280 Context.prototype.compileSwitch = function compileSwitch(node) {
michael@0 25281 var dr = node.determinant.compile(this);
michael@0 25282 var cases = [];
michael@0 25283 node.cases.forEach(function (x) {
michael@0 25284 var br;
michael@0 25285 if (x.body) {
michael@0 25286 br = x.body.compile(this);
michael@0 25287 }
michael@0 25288 var test = typeof x.index === 'number' ? new Literal(x.index) : undefined;
michael@0 25289 cases.push(new SwitchCase(test, br ? [
michael@0 25290 br
michael@0 25291 ] : []));
michael@0 25292 }, this);
michael@0 25293 var determinant = compileValue(dr.end.determinant, this);
michael@0 25294 dr.body.push(new SwitchStatement(determinant, cases, false));
michael@0 25295 return dr;
michael@0 25296 };
michael@0 25297 Context.prototype.compileLabelSwitch = function compileLabelSwitch(node) {
michael@0 25298 var statement = null;
michael@0 25299 var labelName = id(this.label.name);
michael@0 25300 function compileLabelTest(labelID) {
michael@0 25301 true;
michael@0 25302 return new BinaryExpression('===', labelName, new Literal(labelID));
michael@0 25303 }
michael@0 25304 for (var i = node.cases.length - 1; i >= 0; i--) {
michael@0 25305 var c = node.cases[i];
michael@0 25306 var labels = c.labels;
michael@0 25307 var labelTest = compileLabelTest(labels[0]);
michael@0 25308 for (var j = 1; j < labels.length; j++) {
michael@0 25309 labelTest = new BinaryExpression('||', labelTest, compileLabelTest(labels[j]));
michael@0 25310 }
michael@0 25311 statement = new IfStatement(labelTest, c.body ? c.body.compile(this) : new BlockStatement(), statement);
michael@0 25312 }
michael@0 25313 return statement;
michael@0 25314 };
michael@0 25315 Context.prototype.compileLoop = function compileLoop(node) {
michael@0 25316 var br = node.body.compile(this);
michael@0 25317 return new WhileStatement(constant(true), br);
michael@0 25318 };
michael@0 25319 Context.prototype.compileSequence = function compileSequence(node) {
michael@0 25320 var cx = this;
michael@0 25321 var body = [];
michael@0 25322 node.body.forEach(function (x) {
michael@0 25323 var result = x.compile(cx);
michael@0 25324 if (result instanceof BlockStatement) {
michael@0 25325 body = body.concat(result.body);
michael@0 25326 } else {
michael@0 25327 body.push(result);
michael@0 25328 }
michael@0 25329 });
michael@0 25330 return new BlockStatement(body);
michael@0 25331 };
michael@0 25332 Context.prototype.compileBlock = function compileBlock(block) {
michael@0 25333 var body = [];
michael@0 25334 for (var i = 1; i < block.nodes.length - 1; i++) {
michael@0 25335 var node = block.nodes[i];
michael@0 25336 var statement;
michael@0 25337 var to;
michael@0 25338 var from;
michael@0 25339 if (node instanceof IR.Throw) {
michael@0 25340 statement = compileValue(node, this, true);
michael@0 25341 } else {
michael@0 25342 if (node instanceof IR.Move) {
michael@0 25343 to = id(node.to.name);
michael@0 25344 this.useVariable(node.to);
michael@0 25345 from = compileValue(node.from, this);
michael@0 25346 } else {
michael@0 25347 if (node.variable) {
michael@0 25348 to = id(node.variable.name);
michael@0 25349 this.useVariable(node.variable);
michael@0 25350 } else {
michael@0 25351 to = null;
michael@0 25352 }
michael@0 25353 from = compileValue(node, this, true);
michael@0 25354 }
michael@0 25355 if (to) {
michael@0 25356 statement = new ExpressionStatement(assignment(to, from));
michael@0 25357 } else {
michael@0 25358 statement = new ExpressionStatement(from);
michael@0 25359 }
michael@0 25360 }
michael@0 25361 body.push(statement);
michael@0 25362 }
michael@0 25363 var end = block.nodes.last();
michael@0 25364 if (end instanceof IR.Stop) {
michael@0 25365 body.push(new ReturnStatement(compileValue(end.argument, this)));
michael@0 25366 }
michael@0 25367 var result = new BlockStatement(body);
michael@0 25368 result.end = block.nodes.last();
michael@0 25369 true;
michael@0 25370 return result;
michael@0 25371 };
michael@0 25372 function compileValue(value, cx, noVariable) {
michael@0 25373 true;
michael@0 25374 true;
michael@0 25375 true;
michael@0 25376 true;
michael@0 25377 if (noVariable || !value.variable) {
michael@0 25378 var node = value.compile(cx);
michael@0 25379 return node;
michael@0 25380 }
michael@0 25381 true;
michael@0 25382 return id(value.variable.name);
michael@0 25383 }
michael@0 25384 function compileMultiname(name, cx) {
michael@0 25385 return [
michael@0 25386 compileValue(name.namespaces, cx),
michael@0 25387 compileValue(name.name, cx),
michael@0 25388 constant(name.flags)
michael@0 25389 ];
michael@0 25390 }
michael@0 25391 function isArray(array) {
michael@0 25392 return array instanceof Array;
michael@0 25393 }
michael@0 25394 function compileValues(values, cx) {
michael@0 25395 true;
michael@0 25396 return values.map(function (value) {
michael@0 25397 return compileValue(value, cx);
michael@0 25398 });
michael@0 25399 }
michael@0 25400 IR.Parameter.prototype.compile = function (cx) {
michael@0 25401 cx.useParameter(this);
michael@0 25402 return id(this.name);
michael@0 25403 };
michael@0 25404 IR.Constant.prototype.compile = function (cx) {
michael@0 25405 return constant(this.value);
michael@0 25406 };
michael@0 25407 IR.Variable.prototype.compile = function (cx) {
michael@0 25408 return id(this.name);
michael@0 25409 };
michael@0 25410 IR.Phi.prototype.compile = function (cx) {
michael@0 25411 true;
michael@0 25412 return compileValue(this.variable, cx);
michael@0 25413 };
michael@0 25414 IR.ASScope.prototype.compile = function (cx) {
michael@0 25415 var parent = compileValue(this.parent, cx);
michael@0 25416 var object = compileValue(this.object, cx);
michael@0 25417 var isWith = new Literal(this.isWith);
michael@0 25418 return new NewExpression(id('Scope'), [
michael@0 25419 parent,
michael@0 25420 object,
michael@0 25421 isWith
michael@0 25422 ]);
michael@0 25423 };
michael@0 25424 IR.ASFindProperty.prototype.compile = function (cx) {
michael@0 25425 var scope = compileValue(this.scope, cx);
michael@0 25426 var name = compileMultiname(this.name, cx);
michael@0 25427 var domain = compileValue(this.domain, cx);
michael@0 25428 var strict = new Literal(this.strict);
michael@0 25429 return call(property(scope, 'findScopeProperty'), name.concat([
michael@0 25430 domain,
michael@0 25431 strict
michael@0 25432 ]));
michael@0 25433 };
michael@0 25434 IR.ASGetProperty.prototype.compile = function (cx) {
michael@0 25435 var object = compileValue(this.object, cx);
michael@0 25436 if (this.flags & IR.Flags.INDEXED) {
michael@0 25437 true;
michael@0 25438 return call(property(object, 'asGetNumericProperty'), [
michael@0 25439 compileValue(this.name.name, cx)
michael@0 25440 ]);
michael@0 25441 } else if (this.flags & IR.Flags.RESOLVED) {
michael@0 25442 return call(property(object, 'asGetResolvedStringProperty'), [
michael@0 25443 compileValue(this.name, cx)
michael@0 25444 ]);
michael@0 25445 }
michael@0 25446 var name = compileMultiname(this.name, cx);
michael@0 25447 var isMethod = new Literal(this.flags & IR.Flags.IS_METHOD);
michael@0 25448 return call(property(object, 'asGetProperty'), name.concat(isMethod));
michael@0 25449 };
michael@0 25450 IR.ASGetSuper.prototype.compile = function (cx) {
michael@0 25451 var scope = compileValue(this.scope, cx);
michael@0 25452 var object = compileValue(this.object, cx);
michael@0 25453 var name = compileMultiname(this.name, cx);
michael@0 25454 return call(property(object, 'asGetSuper'), [
michael@0 25455 scope
michael@0 25456 ].concat(name));
michael@0 25457 };
michael@0 25458 IR.Latch.prototype.compile = function (cx) {
michael@0 25459 return new ConditionalExpression(compileValue(this.condition, cx), compileValue(this.left, cx), compileValue(this.right, cx));
michael@0 25460 };
michael@0 25461 IR.Unary.prototype.compile = function (cx) {
michael@0 25462 return new UnaryExpression(this.operator.name, compileValue(this.argument, cx));
michael@0 25463 };
michael@0 25464 IR.Copy.prototype.compile = function (cx) {
michael@0 25465 return compileValue(this.argument, cx);
michael@0 25466 };
michael@0 25467 IR.Binary.prototype.compile = function (cx) {
michael@0 25468 var left = compileValue(this.left, cx);
michael@0 25469 var right = compileValue(this.right, cx);
michael@0 25470 if (this.operator === Operator.AS_ADD) {
michael@0 25471 return call(id('asAdd'), [
michael@0 25472 left,
michael@0 25473 right
michael@0 25474 ]);
michael@0 25475 }
michael@0 25476 return new BinaryExpression(this.operator.name, left, right);
michael@0 25477 };
michael@0 25478 IR.CallProperty.prototype.compile = function (cx) {
michael@0 25479 var object = compileValue(this.object, cx);
michael@0 25480 var name = compileValue(this.name, cx);
michael@0 25481 var callee = property(object, name);
michael@0 25482 var args = this.args.map(function (arg) {
michael@0 25483 return compileValue(arg, cx);
michael@0 25484 });
michael@0 25485 if (this.flags & IR.Flags.PRISTINE) {
michael@0 25486 return call(callee, args);
michael@0 25487 } else {
michael@0 25488 return callCall(callee, object, args);
michael@0 25489 }
michael@0 25490 };
michael@0 25491 IR.ASCallProperty.prototype.compile = function (cx) {
michael@0 25492 var object = compileValue(this.object, cx);
michael@0 25493 var args = this.args.map(function (arg) {
michael@0 25494 return compileValue(arg, cx);
michael@0 25495 });
michael@0 25496 if (this.flags & IR.Flags.RESOLVED) {
michael@0 25497 return call(property(object, 'asCallResolvedStringProperty'), [
michael@0 25498 compileValue(this.name, cx),
michael@0 25499 new Literal(this.isLex),
michael@0 25500 new ArrayExpression(args)
michael@0 25501 ]);
michael@0 25502 }
michael@0 25503 var name = compileMultiname(this.name, cx);
michael@0 25504 return call(property(object, 'asCallProperty'), name.concat([
michael@0 25505 new Literal(this.isLex),
michael@0 25506 new ArrayExpression(args)
michael@0 25507 ]));
michael@0 25508 };
michael@0 25509 IR.ASCallSuper.prototype.compile = function (cx) {
michael@0 25510 var scope = compileValue(this.scope, cx);
michael@0 25511 var object = compileValue(this.object, cx);
michael@0 25512 var args = this.args.map(function (arg) {
michael@0 25513 return compileValue(arg, cx);
michael@0 25514 });
michael@0 25515 var name = compileMultiname(this.name, cx);
michael@0 25516 return call(property(object, 'asCallSuper'), [
michael@0 25517 scope
michael@0 25518 ].concat(name).concat(new ArrayExpression(args)));
michael@0 25519 };
michael@0 25520 IR.Call.prototype.compile = function (cx) {
michael@0 25521 var args = this.args.map(function (arg) {
michael@0 25522 return compileValue(arg, cx);
michael@0 25523 });
michael@0 25524 var callee = compileValue(this.callee, cx);
michael@0 25525 var object;
michael@0 25526 if (this.object) {
michael@0 25527 object = compileValue(this.object, cx);
michael@0 25528 } else {
michael@0 25529 object = new Literal(null);
michael@0 25530 }
michael@0 25531 if (false && this.pristine && (this.callee instanceof IR.GetProperty && this.callee.object === this.object) || this.object === null) {
michael@0 25532 return call(callee, args);
michael@0 25533 } else {
michael@0 25534 return callCall(callee, object, args);
michael@0 25535 }
michael@0 25536 };
michael@0 25537 IR.ASNew.prototype.compile = function (cx) {
michael@0 25538 var args = this.args.map(function (arg) {
michael@0 25539 return compileValue(arg, cx);
michael@0 25540 });
michael@0 25541 var callee = compileValue(this.callee, cx);
michael@0 25542 callee = property(callee, 'instanceConstructor');
michael@0 25543 return new NewExpression(callee, args);
michael@0 25544 };
michael@0 25545 IR.This.prototype.compile = function (cx) {
michael@0 25546 return new ThisExpression();
michael@0 25547 };
michael@0 25548 IR.Throw.prototype.compile = function (cx) {
michael@0 25549 var argument = compileValue(this.argument, cx);
michael@0 25550 return new ThrowStatement(argument);
michael@0 25551 };
michael@0 25552 IR.Arguments.prototype.compile = function (cx) {
michael@0 25553 return id('arguments');
michael@0 25554 };
michael@0 25555 IR.ASGlobal.prototype.compile = function (cx) {
michael@0 25556 var scope = compileValue(this.scope, cx);
michael@0 25557 return property(scope, 'global', 'object');
michael@0 25558 };
michael@0 25559 IR.ASSetProperty.prototype.compile = function (cx) {
michael@0 25560 var object = compileValue(this.object, cx);
michael@0 25561 var value = compileValue(this.value, cx);
michael@0 25562 if (this.flags & IR.Flags.INDEXED) {
michael@0 25563 return call(property(object, 'asSetNumericProperty'), [
michael@0 25564 compileValue(this.name.name, cx),
michael@0 25565 value
michael@0 25566 ]);
michael@0 25567 }
michael@0 25568 var name = compileMultiname(this.name, cx);
michael@0 25569 return call(property(object, 'asSetProperty'), name.concat(value));
michael@0 25570 };
michael@0 25571 IR.ASSetSuper.prototype.compile = function (cx) {
michael@0 25572 var scope = compileValue(this.scope, cx);
michael@0 25573 var object = compileValue(this.object, cx);
michael@0 25574 var name = compileMultiname(this.name, cx);
michael@0 25575 var value = compileValue(this.value, cx);
michael@0 25576 return call(property(object, 'asSetSuper'), [
michael@0 25577 scope
michael@0 25578 ].concat(name).concat([
michael@0 25579 value
michael@0 25580 ]));
michael@0 25581 };
michael@0 25582 IR.ASDeleteProperty.prototype.compile = function (cx) {
michael@0 25583 var object = compileValue(this.object, cx);
michael@0 25584 var name = compileMultiname(this.name, cx);
michael@0 25585 return call(property(object, 'asDeleteProperty'), name);
michael@0 25586 };
michael@0 25587 IR.ASHasProperty.prototype.compile = function (cx) {
michael@0 25588 var object = compileValue(this.object, cx);
michael@0 25589 var name = compileMultiname(this.name, cx);
michael@0 25590 return call(property(object, 'asHasProperty'), name);
michael@0 25591 };
michael@0 25592 IR.GlobalProperty.prototype.compile = function (cx) {
michael@0 25593 return id(this.name);
michael@0 25594 };
michael@0 25595 IR.GetProperty.prototype.compile = function (cx) {
michael@0 25596 var object = compileValue(this.object, cx);
michael@0 25597 var name = compileValue(this.name, cx);
michael@0 25598 return property(object, name);
michael@0 25599 };
michael@0 25600 IR.SetProperty.prototype.compile = function (cx) {
michael@0 25601 var object = compileValue(this.object, cx);
michael@0 25602 var name = compileValue(this.name, cx);
michael@0 25603 var value = compileValue(this.value, cx);
michael@0 25604 return assignment(property(object, name), value);
michael@0 25605 };
michael@0 25606 IR.ASGetDescendants.prototype.compile = function (cx) {
michael@0 25607 var object = compileValue(this.object, cx);
michael@0 25608 var name = compileValue(this.name, cx);
michael@0 25609 return call(id('getDescendants'), [
michael@0 25610 object,
michael@0 25611 name
michael@0 25612 ]);
michael@0 25613 };
michael@0 25614 IR.ASSetSlot.prototype.compile = function (cx) {
michael@0 25615 var object = compileValue(this.object, cx);
michael@0 25616 var name = compileValue(this.name, cx);
michael@0 25617 var value = compileValue(this.value, cx);
michael@0 25618 return call(id('asSetSlot'), [
michael@0 25619 object,
michael@0 25620 name,
michael@0 25621 value
michael@0 25622 ]);
michael@0 25623 };
michael@0 25624 IR.ASGetSlot.prototype.compile = function (cx) {
michael@0 25625 var object = compileValue(this.object, cx);
michael@0 25626 var name = compileValue(this.name, cx);
michael@0 25627 return call(id('asGetSlot'), [
michael@0 25628 object,
michael@0 25629 name
michael@0 25630 ]);
michael@0 25631 };
michael@0 25632 IR.Projection.prototype.compile = function (cx) {
michael@0 25633 true;
michael@0 25634 true;
michael@0 25635 return compileValue(this.argument.scope, cx);
michael@0 25636 };
michael@0 25637 IR.NewArray.prototype.compile = function (cx) {
michael@0 25638 return new ArrayExpression(compileValues(this.elements, cx));
michael@0 25639 };
michael@0 25640 IR.NewObject.prototype.compile = function (cx) {
michael@0 25641 var properties = this.properties.map(function (property) {
michael@0 25642 var key = compileValue(property.key, cx);
michael@0 25643 var value = compileValue(property.value, cx);
michael@0 25644 return new Property(key, value, 'init');
michael@0 25645 });
michael@0 25646 return new ObjectExpression(properties);
michael@0 25647 };
michael@0 25648 IR.ASNewActivation.prototype.compile = function (cx) {
michael@0 25649 var methodInfo = compileValue(this.methodInfo, cx);
michael@0 25650 return call(id('asCreateActivation'), [
michael@0 25651 methodInfo
michael@0 25652 ]);
michael@0 25653 };
michael@0 25654 IR.ASMultiname.prototype.compile = function (cx) {
michael@0 25655 var namespaces = compileValue(this.namespaces, cx);
michael@0 25656 var name = compileValue(this.name, cx);
michael@0 25657 return call(id('createName'), [
michael@0 25658 namespaces,
michael@0 25659 name
michael@0 25660 ]);
michael@0 25661 };
michael@0 25662 function generateSource(node) {
michael@0 25663 return escodegen.generate(node, {
michael@0 25664 base: '',
michael@0 25665 indent: ' ',
michael@0 25666 comment: true,
michael@0 25667 format: {
michael@0 25668 compact: false
michael@0 25669 }
michael@0 25670 });
michael@0 25671 }
michael@0 25672 function generate(cfg, useRegisterAllocator) {
michael@0 25673 Timer.start('Looper');
michael@0 25674 var root = Looper.analyze(cfg);
michael@0 25675 Timer.stop();
michael@0 25676 var writer = new IndentingWriter();
michael@0 25677 var cx = new Context();
michael@0 25678 Timer.start('Construct AST');
michael@0 25679 var code = root.compile(cx);
michael@0 25680 Timer.stop();
michael@0 25681 var parameters = [];
michael@0 25682 for (var i = 0; i < cx.parameters.length; i++) {
michael@0 25683 var name = cx.parameters[i] ? cx.parameters[i].name : '_' + i;
michael@0 25684 parameters.push(id(name));
michael@0 25685 }
michael@0 25686 if (cx.variables.length) {
michael@0 25687 Counter.count('Backend: Locals', cx.variables.length);
michael@0 25688 var variables = variableDeclaration(cx.variables.map(function (variable) {
michael@0 25689 return new VariableDeclarator(id(variable.name));
michael@0 25690 }));
michael@0 25691 code.body.unshift(variables);
michael@0 25692 }
michael@0 25693 var node = new FunctionDeclaration(id('fn'), parameters, code);
michael@0 25694 if (useRegisterAllocator) {
michael@0 25695 if (c4TraceLevel.value > 0) {
michael@0 25696 writer.writeLn('=== BEFORE ===============================');
michael@0 25697 writer.writeLn(generateSource(node));
michael@0 25698 writer.writeLn('=== TRANSFORMING =========================');
michael@0 25699 }
michael@0 25700 Transform.transform(node);
michael@0 25701 if (c4TraceLevel.value > 0) {
michael@0 25702 writer.writeLn('=== AFTER ================================');
michael@0 25703 writer.writeLn(generateSource(node));
michael@0 25704 writer.writeLn('==========================================');
michael@0 25705 }
michael@0 25706 var body = generateSource(code);
michael@0 25707 return {
michael@0 25708 parameters: parameters.map(function (p) {
michael@0 25709 return p.name;
michael@0 25710 }),
michael@0 25711 body: body
michael@0 25712 };
michael@0 25713 }
michael@0 25714 Timer.start('Serialize AST');
michael@0 25715 var source = generateSource(code);
michael@0 25716 Timer.stop();
michael@0 25717 return {
michael@0 25718 parameters: parameters.map(function (p) {
michael@0 25719 return p.name;
michael@0 25720 }),
michael@0 25721 body: source
michael@0 25722 };
michael@0 25723 }
michael@0 25724 Backend.generate = generate;
michael@0 25725 }(typeof exports === 'undefined' ? Backend = {} : exports));
michael@0 25726 var Shumway;
michael@0 25727 (function (Shumway) {
michael@0 25728 (function (AVM2) {
michael@0 25729 (function (Runtime) {
michael@0 25730 var Multiname = Shumway.AVM2.ABC.Multiname;
michael@0 25731 var Namespace = Shumway.AVM2.ABC.Namespace;
michael@0 25732 var ClassInfo = Shumway.AVM2.ABC.ClassInfo;
michael@0 25733 var InstanceInfo = Shumway.AVM2.ABC.InstanceInfo;
michael@0 25734 var Trait = Shumway.AVM2.ABC.Trait;
michael@0 25735 var IndentingWriter = Shumway.IndentingWriter;
michael@0 25736 var createMap = Shumway.ObjectUtilities.createMap;
michael@0 25737 var defineNonEnumerableGetterOrSetter = Shumway.ObjectUtilities.defineNonEnumerableGetterOrSetter;
michael@0 25738 var defineNonEnumerableProperty = Shumway.ObjectUtilities.defineNonEnumerableProperty;
michael@0 25739 var defineReadOnlyProperty = Shumway.ObjectUtilities.defineReadOnlyProperty;
michael@0 25740 var bindSafely = Shumway.FunctionUtilities.bindSafely;
michael@0 25741 var vmNextTrampolineId = 1;
michael@0 25742 var vmNextMemoizerId = 1;
michael@0 25743 function getMethodOverrideKey(methodInfo) {
michael@0 25744 var key;
michael@0 25745 if (methodInfo.holder instanceof ClassInfo) {
michael@0 25746 key = 'static ' + methodInfo.holder.instanceInfo.name.getOriginalName() + '::' + methodInfo.name.getOriginalName();
michael@0 25747 } else if (methodInfo.holder instanceof InstanceInfo) {
michael@0 25748 key = methodInfo.holder.name.getOriginalName() + '::' + methodInfo.name.getOriginalName();
michael@0 25749 } else {
michael@0 25750 key = methodInfo.name.getOriginalName();
michael@0 25751 }
michael@0 25752 return key;
michael@0 25753 }
michael@0 25754 Runtime.getMethodOverrideKey = getMethodOverrideKey;
michael@0 25755 function checkMethodOverrides(methodInfo) {
michael@0 25756 if (methodInfo.name) {
michael@0 25757 var key = getMethodOverrideKey(methodInfo);
michael@0 25758 if (key in Shumway.AVM2.Runtime.VM_METHOD_OVERRIDES) {
michael@0 25759 Shumway.Debug.warning('Overriding Method: ' + key);
michael@0 25760 return Shumway.AVM2.Runtime.VM_METHOD_OVERRIDES[key];
michael@0 25761 }
michael@0 25762 }
michael@0 25763 }
michael@0 25764 Runtime.checkMethodOverrides = checkMethodOverrides;
michael@0 25765 function makeTrampoline(forward, parameterLength, description) {
michael@0 25766 true;
michael@0 25767 return function trampolineContext() {
michael@0 25768 var target = null;
michael@0 25769 var trampoline = function execute() {
michael@0 25770 if (Shumway.AVM2.Runtime.traceExecution.value >= 3) {
michael@0 25771 log('Trampolining');
michael@0 25772 }
michael@0 25773 Counter.count('Executing Trampoline');
michael@0 25774 Shumway.AVM2.Runtime.traceCallExecution.value > 1 && callWriter.writeLn('Trampoline: ' + description);
michael@0 25775 if (!target) {
michael@0 25776 target = forward(trampoline);
michael@0 25777 true;
michael@0 25778 }
michael@0 25779 return target.apply(this, arguments);
michael@0 25780 };
michael@0 25781 trampoline.trigger = function trigger() {
michael@0 25782 Counter.count('Triggering Trampoline');
michael@0 25783 if (!target) {
michael@0 25784 target = forward(trampoline);
michael@0 25785 true;
michael@0 25786 }
michael@0 25787 };
michael@0 25788 trampoline.isTrampoline = true;
michael@0 25789 trampoline.debugName = 'Trampoline #' + vmNextTrampolineId++;
michael@0 25790 defineReadOnlyProperty(trampoline, Shumway.AVM2.Runtime.VM_LENGTH, parameterLength);
michael@0 25791 return trampoline;
michael@0 25792 }();
michael@0 25793 }
michael@0 25794 Runtime.makeTrampoline = makeTrampoline;
michael@0 25795 function makeMemoizer(qn, target) {
michael@0 25796 function memoizer() {
michael@0 25797 Counter.count('Runtime: Memoizing');
michael@0 25798 if (Shumway.AVM2.Runtime.traceExecution.value >= 3) {
michael@0 25799 log('Memoizing: ' + qn);
michael@0 25800 }
michael@0 25801 Shumway.AVM2.Runtime.traceCallExecution.value > 1 && callWriter.writeLn('Memoizing: ' + qn);
michael@0 25802 if (Shumway.AVM2.Runtime.isNativePrototype(this)) {
michael@0 25803 Counter.count('Runtime: Method Closures');
michael@0 25804 return bindSafely(target.value, this);
michael@0 25805 }
michael@0 25806 if (isTrampoline(target.value)) {
michael@0 25807 target.value.trigger();
michael@0 25808 }
michael@0 25809 true;
michael@0 25810 var mc = null;
michael@0 25811 if (Shumway.AVM2.Runtime.isClass(this)) {
michael@0 25812 Counter.count('Runtime: Static Method Closures');
michael@0 25813 mc = bindSafely(target.value, this);
michael@0 25814 defineReadOnlyProperty(this, qn, mc);
michael@0 25815 return mc;
michael@0 25816 }
michael@0 25817 if (Object.prototype.hasOwnProperty.call(this, qn)) {
michael@0 25818 var pd = Object.getOwnPropertyDescriptor(this, qn);
michael@0 25819 if (pd.get) {
michael@0 25820 Counter.count('Runtime: Method Closures');
michael@0 25821 return bindSafely(target.value, this);
michael@0 25822 }
michael@0 25823 Counter.count('Runtime: Unpatched Memoizer');
michael@0 25824 return this[qn];
michael@0 25825 }
michael@0 25826 mc = bindSafely(target.value, this);
michael@0 25827 mc.methodInfo = target.value.methodInfo;
michael@0 25828 defineReadOnlyProperty(mc, Multiname.getPublicQualifiedName('prototype'), null);
michael@0 25829 defineReadOnlyProperty(this, qn, mc);
michael@0 25830 return mc;
michael@0 25831 }
michael@0 25832 var m = memoizer;
michael@0 25833 Counter.count('Runtime: Memoizers');
michael@0 25834 m.isMemoizer = true;
michael@0 25835 m.debugName = 'Memoizer #' + vmNextMemoizerId++;
michael@0 25836 return m;
michael@0 25837 }
michael@0 25838 Runtime.makeMemoizer = makeMemoizer;
michael@0 25839 function isTrampoline(fn) {
michael@0 25840 true;
michael@0 25841 return fn.isTrampoline;
michael@0 25842 }
michael@0 25843 Runtime.isTrampoline = isTrampoline;
michael@0 25844 function isMemoizer(fn) {
michael@0 25845 true;
michael@0 25846 return fn.isMemoizer;
michael@0 25847 }
michael@0 25848 Runtime.isMemoizer = isMemoizer;
michael@0 25849 }(AVM2.Runtime || (AVM2.Runtime = {})));
michael@0 25850 var Runtime = AVM2.Runtime;
michael@0 25851 }(Shumway.AVM2 || (Shumway.AVM2 = {})));
michael@0 25852 var AVM2 = Shumway.AVM2;
michael@0 25853 }(Shumway || (Shumway = {})));
michael@0 25854 var __extends = this.__extends || function (d, b) {
michael@0 25855 for (var p in b)
michael@0 25856 if (b.hasOwnProperty(p))
michael@0 25857 d[p] = b[p];
michael@0 25858 function __() {
michael@0 25859 this.constructor = d;
michael@0 25860 }
michael@0 25861 __.prototype = b.prototype;
michael@0 25862 d.prototype = new __();
michael@0 25863 };
michael@0 25864 var Shumway;
michael@0 25865 (function (Shumway) {
michael@0 25866 (function (AVM2) {
michael@0 25867 (function (Runtime) {
michael@0 25868 var Multiname = Shumway.AVM2.ABC.Multiname;
michael@0 25869 var Namespace = Shumway.AVM2.ABC.Namespace;
michael@0 25870 var MethodInfo = Shumway.AVM2.ABC.MethodInfo;
michael@0 25871 var ClassInfo = Shumway.AVM2.ABC.ClassInfo;
michael@0 25872 var InstanceInfo = Shumway.AVM2.ABC.InstanceInfo;
michael@0 25873 var ScriptInfo = Shumway.AVM2.ABC.ScriptInfo;
michael@0 25874 var Trait = Shumway.AVM2.ABC.Trait;
michael@0 25875 var IndentingWriter = Shumway.IndentingWriter;
michael@0 25876 var hasOwnProperty = Shumway.ObjectUtilities.hasOwnProperty;
michael@0 25877 var createMap = Shumway.ObjectUtilities.createMap;
michael@0 25878 var cloneObject = Shumway.ObjectUtilities.cloneObject;
michael@0 25879 var copyProperties = Shumway.ObjectUtilities.copyProperties;
michael@0 25880 var createEmptyObject = Shumway.ObjectUtilities.createEmptyObject;
michael@0 25881 var bindSafely = Shumway.FunctionUtilities.bindSafely;
michael@0 25882 var defineNonEnumerableGetterOrSetter = Shumway.ObjectUtilities.defineNonEnumerableGetterOrSetter;
michael@0 25883 var defineNonEnumerableProperty = Shumway.ObjectUtilities.defineNonEnumerableProperty;
michael@0 25884 var defineReadOnlyProperty = Shumway.ObjectUtilities.defineReadOnlyProperty;
michael@0 25885 var defineNonEnumerableGetter = Shumway.ObjectUtilities.defineNonEnumerableGetter;
michael@0 25886 var makeForwardingGetter = Shumway.FunctionUtilities.makeForwardingGetter;
michael@0 25887 var makeForwardingSetter = Shumway.FunctionUtilities.makeForwardingSetter;
michael@0 25888 var Binding = function () {
michael@0 25889 function Binding(trait) {
michael@0 25890 this.trait = trait;
michael@0 25891 }
michael@0 25892 Binding.getKey = function (qn, trait) {
michael@0 25893 var key = qn;
michael@0 25894 if (trait.isGetter()) {
michael@0 25895 key = Binding.GET_PREFIX + qn;
michael@0 25896 } else if (trait.isSetter()) {
michael@0 25897 key = Binding.SET_PREFIX + qn;
michael@0 25898 }
michael@0 25899 return key;
michael@0 25900 };
michael@0 25901 Binding.prototype.toString = function () {
michael@0 25902 return String(this.trait);
michael@0 25903 };
michael@0 25904 Binding.SET_PREFIX = 'set ';
michael@0 25905 Binding.GET_PREFIX = 'get ';
michael@0 25906 Binding.KEY_PREFIX_LENGTH = 4;
michael@0 25907 return Binding;
michael@0 25908 }();
michael@0 25909 Runtime.Binding = Binding;
michael@0 25910 var SlotInfo = function () {
michael@0 25911 function SlotInfo(name, isConst, type, trait) {
michael@0 25912 this.name = name;
michael@0 25913 this.isConst = isConst;
michael@0 25914 this.type = type;
michael@0 25915 this.trait = trait;
michael@0 25916 }
michael@0 25917 return SlotInfo;
michael@0 25918 }();
michael@0 25919 Runtime.SlotInfo = SlotInfo;
michael@0 25920 var SlotInfoMap = function () {
michael@0 25921 function SlotInfoMap() {
michael@0 25922 this.byID = createMap();
michael@0 25923 this.byQN = createMap();
michael@0 25924 }
michael@0 25925 return SlotInfoMap;
michael@0 25926 }();
michael@0 25927 Runtime.SlotInfoMap = SlotInfoMap;
michael@0 25928 var Bindings = function () {
michael@0 25929 function Bindings() {
michael@0 25930 this.map = createMap();
michael@0 25931 this.slots = [];
michael@0 25932 this.nextSlotId = 1;
michael@0 25933 }
michael@0 25934 Bindings.prototype.assignNextSlot = function (trait) {
michael@0 25935 true;
michael@0 25936 true;
michael@0 25937 if (!trait.slotId) {
michael@0 25938 trait.slotId = this.nextSlotId++;
michael@0 25939 } else {
michael@0 25940 this.nextSlotId = trait.slotId + 1;
michael@0 25941 }
michael@0 25942 true;
michael@0 25943 this.slots[trait.slotId] = trait;
michael@0 25944 };
michael@0 25945 Bindings.prototype.trace = function (writer) {
michael@0 25946 writer.enter('Bindings');
michael@0 25947 for (var key in this.map) {
michael@0 25948 var binding = this.map[key];
michael@0 25949 writer.writeLn(binding.trait.kindName() + ': ' + key + ' -> ' + binding);
michael@0 25950 }
michael@0 25951 writer.leaveAndEnter('Slots');
michael@0 25952 writer.writeArray(this.slots);
michael@0 25953 writer.outdent();
michael@0 25954 };
michael@0 25955 Bindings.prototype.applyTo = function (domain, object) {
michael@0 25956 true;
michael@0 25957 true;
michael@0 25958 true;
michael@0 25959 defineNonEnumerableProperty(object, Shumway.AVM2.Runtime.VM_SLOTS, new SlotInfoMap());
michael@0 25960 defineNonEnumerableProperty(object, Shumway.AVM2.Runtime.VM_BINDINGS, []);
michael@0 25961 defineNonEnumerableProperty(object, Shumway.AVM2.Runtime.VM_OPEN_METHODS, createMap());
michael@0 25962 defineNonEnumerableProperty(object, 'bindings', this);
michael@0 25963 defineNonEnumerableProperty(object, 'resolutionMap', []);
michael@0 25964 traitsWriter && traitsWriter.greenLn('Applying Traits');
michael@0 25965 for (var key in this.map) {
michael@0 25966 var binding = this.map[key];
michael@0 25967 var trait = binding.trait;
michael@0 25968 var qn = Multiname.getQualifiedName(trait.name);
michael@0 25969 if (trait.isSlot() || trait.isConst() || trait.isClass()) {
michael@0 25970 var defaultValue = undefined;
michael@0 25971 if (trait.isSlot() || trait.isConst()) {
michael@0 25972 if (trait.hasDefaultValue) {
michael@0 25973 defaultValue = trait.value;
michael@0 25974 } else if (trait.typeName) {
michael@0 25975 defaultValue = domain.findClassInfo(trait.typeName).defaultValue;
michael@0 25976 }
michael@0 25977 }
michael@0 25978 if (key !== qn) {
michael@0 25979 traitsWriter && traitsWriter.yellowLn('Binding Trait: ' + key + ' -> ' + qn);
michael@0 25980 defineNonEnumerableGetter(object, key, makeForwardingGetter(qn));
michael@0 25981 object.asBindings.pushUnique(key);
michael@0 25982 } else {
michael@0 25983 traitsWriter && traitsWriter.greenLn('Applying Trait ' + trait.kindName() + ': ' + trait);
michael@0 25984 defineNonEnumerableProperty(object, qn, defaultValue);
michael@0 25985 object.asBindings.pushUnique(qn);
michael@0 25986 var slotInfo = new SlotInfo(qn, trait.isConst(), trait.typeName ? domain.getProperty(trait.typeName, false, false) : null, trait);
michael@0 25987 object.asSlots.byID[trait.slotId] = slotInfo;
michael@0 25988 object.asSlots.byQN[qn] = slotInfo;
michael@0 25989 }
michael@0 25990 } else if (trait.isMethod() || trait.isGetter() || trait.isSetter()) {
michael@0 25991 if (trait.isGetter() || trait.isSetter()) {
michael@0 25992 key = key.substring(Binding.KEY_PREFIX_LENGTH);
michael@0 25993 }
michael@0 25994 if (key !== qn) {
michael@0 25995 traitsWriter && traitsWriter.yellowLn('Binding Trait: ' + key + ' -> ' + qn);
michael@0 25996 } else {
michael@0 25997 traitsWriter && traitsWriter.greenLn('Applying Trait ' + trait.kindName() + ': ' + trait);
michael@0 25998 }
michael@0 25999 object.asBindings.pushUnique(key);
michael@0 26000 if (this instanceof ScriptBindings) {
michael@0 26001 Shumway.AVM2.Runtime.applyNonMemoizedMethodTrait(key, trait, object, binding.scope, binding.natives);
michael@0 26002 } else {
michael@0 26003 Shumway.AVM2.Runtime.applyMemoizedMethodTrait(key, trait, object, binding.scope, binding.natives);
michael@0 26004 }
michael@0 26005 }
michael@0 26006 }
michael@0 26007 };
michael@0 26008 return Bindings;
michael@0 26009 }();
michael@0 26010 Runtime.Bindings = Bindings;
michael@0 26011 var ActivationBindings = function (_super) {
michael@0 26012 __extends(ActivationBindings, _super);
michael@0 26013 function ActivationBindings(methodInfo) {
michael@0 26014 _super.call(this);
michael@0 26015 true;
michael@0 26016 this.methodInfo = methodInfo;
michael@0 26017 var traits = methodInfo.traits;
michael@0 26018 for (var i = 0; i < traits.length; i++) {
michael@0 26019 var trait = traits[i];
michael@0 26020 true;
michael@0 26021 var key = Multiname.getQualifiedName(trait.name);
michael@0 26022 this.map[key] = new Binding(trait);
michael@0 26023 this.assignNextSlot(trait);
michael@0 26024 }
michael@0 26025 }
michael@0 26026 return ActivationBindings;
michael@0 26027 }(Bindings);
michael@0 26028 Runtime.ActivationBindings = ActivationBindings;
michael@0 26029 var CatchBindings = function (_super) {
michael@0 26030 __extends(CatchBindings, _super);
michael@0 26031 function CatchBindings(scope, trait) {
michael@0 26032 _super.call(this);
michael@0 26033 var key = Multiname.getQualifiedName(trait.name);
michael@0 26034 this.map[key] = new Binding(trait);
michael@0 26035 true;
michael@0 26036 this.assignNextSlot(trait);
michael@0 26037 }
michael@0 26038 return CatchBindings;
michael@0 26039 }(Bindings);
michael@0 26040 Runtime.CatchBindings = CatchBindings;
michael@0 26041 var ScriptBindings = function (_super) {
michael@0 26042 __extends(ScriptBindings, _super);
michael@0 26043 function ScriptBindings(scriptInfo, scope) {
michael@0 26044 _super.call(this);
michael@0 26045 this.scope = scope;
michael@0 26046 this.scriptInfo = scriptInfo;
michael@0 26047 var traits = scriptInfo.traits;
michael@0 26048 for (var i = 0; i < traits.length; i++) {
michael@0 26049 var trait = traits[i];
michael@0 26050 var name = Multiname.getQualifiedName(trait.name);
michael@0 26051 var key = Binding.getKey(name, trait);
michael@0 26052 var binding = this.map[key] = new Binding(trait);
michael@0 26053 if (trait.isSlot() || trait.isConst() || trait.isClass()) {
michael@0 26054 this.assignNextSlot(trait);
michael@0 26055 }
michael@0 26056 if (trait.isClass()) {
michael@0 26057 if (trait.metadata && trait.metadata.native) {
michael@0 26058 trait.classInfo.native = trait.metadata.native;
michael@0 26059 }
michael@0 26060 }
michael@0 26061 if (trait.isMethod() || trait.isGetter() || trait.isSetter()) {
michael@0 26062 binding.scope = this.scope;
michael@0 26063 }
michael@0 26064 }
michael@0 26065 }
michael@0 26066 return ScriptBindings;
michael@0 26067 }(Bindings);
michael@0 26068 Runtime.ScriptBindings = ScriptBindings;
michael@0 26069 var ClassBindings = function (_super) {
michael@0 26070 __extends(ClassBindings, _super);
michael@0 26071 function ClassBindings(classInfo, scope, natives) {
michael@0 26072 _super.call(this);
michael@0 26073 this.scope = scope;
michael@0 26074 this.natives = natives;
michael@0 26075 this.classInfo = classInfo;
michael@0 26076 var traits = classInfo.traits;
michael@0 26077 for (var i = 0; i < traits.length; i++) {
michael@0 26078 var trait = traits[i];
michael@0 26079 var name = Multiname.getQualifiedName(trait.name);
michael@0 26080 var key = Binding.getKey(name, trait);
michael@0 26081 var binding = this.map[key] = new Binding(trait);
michael@0 26082 if (trait.isSlot() || trait.isConst()) {
michael@0 26083 this.assignNextSlot(trait);
michael@0 26084 }
michael@0 26085 if (trait.isMethod() || trait.isGetter() || trait.isSetter()) {
michael@0 26086 binding.scope = this.scope;
michael@0 26087 binding.natives = this.natives;
michael@0 26088 }
michael@0 26089 }
michael@0 26090 }
michael@0 26091 return ClassBindings;
michael@0 26092 }(Bindings);
michael@0 26093 Runtime.ClassBindings = ClassBindings;
michael@0 26094 var InstanceBindings = function (_super) {
michael@0 26095 __extends(InstanceBindings, _super);
michael@0 26096 function InstanceBindings(parent, instanceInfo, scope, natives) {
michael@0 26097 _super.call(this);
michael@0 26098 this.scope = scope;
michael@0 26099 this.natives = natives;
michael@0 26100 this.parent = parent;
michael@0 26101 this.instanceInfo = instanceInfo;
michael@0 26102 this.implementedInterfaces = parent ? cloneObject(parent.implementedInterfaces) : createEmptyObject();
michael@0 26103 if (parent) {
michael@0 26104 this.slots = parent.slots.slice();
michael@0 26105 this.nextSlotId = parent.nextSlotId;
michael@0 26106 }
michael@0 26107 this.extend(parent);
michael@0 26108 }
michael@0 26109 InstanceBindings.prototype.extend = function (parent) {
michael@0 26110 var ii = this.instanceInfo, ib;
michael@0 26111 var map = this.map;
michael@0 26112 var name, key, trait, binding, protectedName, protectedKey;
michael@0 26113 if (parent) {
michael@0 26114 for (key in parent.map) {
michael@0 26115 binding = parent.map[key];
michael@0 26116 trait = binding.trait;
michael@0 26117 map[key] = binding;
michael@0 26118 if (trait.isProtected()) {
michael@0 26119 protectedName = Multiname.getQualifiedName(new Multiname([
michael@0 26120 ii.protectedNs
michael@0 26121 ], trait.name.getName()));
michael@0 26122 protectedKey = Binding.getKey(protectedName, trait);
michael@0 26123 map[protectedKey] = binding;
michael@0 26124 }
michael@0 26125 }
michael@0 26126 }
michael@0 26127 function writeOrOverwriteBinding(object, key, binding) {
michael@0 26128 var trait = binding.trait;
michael@0 26129 var oldBinding = object[key];
michael@0 26130 if (oldBinding) {
michael@0 26131 var oldTrait = oldBinding.trait;
michael@0 26132 true;
michael@0 26133 true;
michael@0 26134 } else {
michael@0 26135 true;
michael@0 26136 }
michael@0 26137 object[key] = binding;
michael@0 26138 }
michael@0 26139 function overwriteProtectedBinding(object, key, binding) {
michael@0 26140 if (key in object) {
michael@0 26141 object[key] = binding;
michael@0 26142 }
michael@0 26143 }
michael@0 26144 var traits = ii.traits;
michael@0 26145 for (var i = 0; i < traits.length; i++) {
michael@0 26146 trait = traits[i];
michael@0 26147 name = Multiname.getQualifiedName(trait.name);
michael@0 26148 key = Binding.getKey(name, trait);
michael@0 26149 binding = new Binding(trait);
michael@0 26150 writeOrOverwriteBinding(map, key, binding);
michael@0 26151 if (trait.isProtected()) {
michael@0 26152 ib = this.parent;
michael@0 26153 while (ib) {
michael@0 26154 protectedName = Multiname.getQualifiedName(new Multiname([
michael@0 26155 ib.instanceInfo.protectedNs
michael@0 26156 ], trait.name.getName()));
michael@0 26157 protectedKey = Binding.getKey(protectedName, trait);
michael@0 26158 overwriteProtectedBinding(map, protectedKey, binding);
michael@0 26159 ib = ib.parent;
michael@0 26160 }
michael@0 26161 }
michael@0 26162 if (trait.isSlot() || trait.isConst()) {
michael@0 26163 this.assignNextSlot(trait);
michael@0 26164 }
michael@0 26165 if (trait.isMethod() || trait.isGetter() || trait.isSetter()) {
michael@0 26166 binding.scope = this.scope;
michael@0 26167 binding.natives = this.natives;
michael@0 26168 }
michael@0 26169 }
michael@0 26170 var domain = ii.abc.applicationDomain;
michael@0 26171 var interfaces = ii.interfaces;
michael@0 26172 for (var i = 0; i < interfaces.length; i++) {
michael@0 26173 var interface = domain.getProperty(interfaces[i], true, true);
michael@0 26174 true;
michael@0 26175 copyProperties(this.implementedInterfaces, interface.interfaceBindings.implementedInterfaces);
michael@0 26176 this.implementedInterfaces[Multiname.getQualifiedName(interface.name)] = interface;
michael@0 26177 }
michael@0 26178 for (var interfaceName in this.implementedInterfaces) {
michael@0 26179 var interface = this.implementedInterfaces[interfaceName];
michael@0 26180 ib = interface.interfaceBindings;
michael@0 26181 for (var interfaceKey in ib.map) {
michael@0 26182 var interfaceBinding = ib.map[interfaceKey];
michael@0 26183 if (ii.isInterface()) {
michael@0 26184 map[interfaceKey] = interfaceBinding;
michael@0 26185 } else {
michael@0 26186 name = Multiname.getPublicQualifiedName(interfaceBinding.trait.name.getName());
michael@0 26187 key = Binding.getKey(name, interfaceBinding.trait);
michael@0 26188 map[interfaceKey] = map[key];
michael@0 26189 }
michael@0 26190 }
michael@0 26191 }
michael@0 26192 };
michael@0 26193 InstanceBindings.prototype.toString = function () {
michael@0 26194 return this.instanceInfo.toString();
michael@0 26195 };
michael@0 26196 return InstanceBindings;
michael@0 26197 }(Bindings);
michael@0 26198 Runtime.InstanceBindings = InstanceBindings;
michael@0 26199 var traitsWriter = null;
michael@0 26200 }(AVM2.Runtime || (AVM2.Runtime = {})));
michael@0 26201 var Runtime = AVM2.Runtime;
michael@0 26202 }(Shumway.AVM2 || (Shumway.AVM2 = {})));
michael@0 26203 var AVM2 = Shumway.AVM2;
michael@0 26204 }(Shumway || (Shumway = {})));
michael@0 26205 var Binding = Shumway.AVM2.Runtime.Binding;
michael@0 26206 var Bindings = Shumway.AVM2.Runtime.Bindings;
michael@0 26207 var ActivationBindings = Shumway.AVM2.Runtime.ActivationBindings;
michael@0 26208 var CatchBindings = Shumway.AVM2.Runtime.CatchBindings;
michael@0 26209 var ScriptBindings = Shumway.AVM2.Runtime.ScriptBindings;
michael@0 26210 var ClassBindings = Shumway.AVM2.Runtime.ClassBindings;
michael@0 26211 var InstanceBindings = Shumway.AVM2.Runtime.InstanceBindings;
michael@0 26212 var Shumway;
michael@0 26213 (function (Shumway) {
michael@0 26214 (function (AVM2) {
michael@0 26215 (function (Runtime) {
michael@0 26216 var Multiname = Shumway.AVM2.ABC.Multiname;
michael@0 26217 var Namespace = Shumway.AVM2.ABC.Namespace;
michael@0 26218 var MethodInfo = Shumway.AVM2.ABC.MethodInfo;
michael@0 26219 var ClassInfo = Shumway.AVM2.ABC.ClassInfo;
michael@0 26220 var InstanceInfo = Shumway.AVM2.ABC.InstanceInfo;
michael@0 26221 var InstanceBindings = Shumway.AVM2.Runtime.InstanceBindings;
michael@0 26222 var ClassBindings = Shumway.AVM2.Runtime.ClassBindings;
michael@0 26223 var defineNonEnumerableGetterOrSetter = Shumway.ObjectUtilities.defineNonEnumerableGetterOrSetter;
michael@0 26224 var defineNonEnumerableProperty = Shumway.ObjectUtilities.defineNonEnumerableProperty;
michael@0 26225 var defineReadOnlyProperty = Shumway.ObjectUtilities.defineReadOnlyProperty;
michael@0 26226 var defineNonEnumerableGetter = Shumway.ObjectUtilities.defineNonEnumerableGetter;
michael@0 26227 var createEmptyObject = Shumway.ObjectUtilities.createEmptyObject;
michael@0 26228 var toKeyValueArray = Shumway.ObjectUtilities.toKeyValueArray;
michael@0 26229 var boxValue = Shumway.ObjectUtilities.boxValue;
michael@0 26230 function makeCacheKey(namespaces, name, flags) {
michael@0 26231 if (!namespaces) {
michael@0 26232 return name;
michael@0 26233 } else if (namespaces.length > 1) {
michael@0 26234 return namespaces.runtimeId + '$' + name;
michael@0 26235 } else {
michael@0 26236 return namespaces[0].qualifiedName + '$' + name;
michael@0 26237 }
michael@0 26238 }
michael@0 26239 var Scope = function () {
michael@0 26240 function Scope(parent, object, isWith) {
michael@0 26241 if (typeof isWith === 'undefined') {
michael@0 26242 isWith = false;
michael@0 26243 }
michael@0 26244 this.parent = parent;
michael@0 26245 this.object = boxValue(object);
michael@0 26246 true;
michael@0 26247 this.global = parent ? parent.global : this;
michael@0 26248 this.isWith = isWith;
michael@0 26249 this.cache = createEmptyObject();
michael@0 26250 }
michael@0 26251 Scope.prototype.findDepth = function (object) {
michael@0 26252 var current = this;
michael@0 26253 var depth = 0;
michael@0 26254 while (current) {
michael@0 26255 if (current.object === object) {
michael@0 26256 return depth;
michael@0 26257 }
michael@0 26258 depth++;
michael@0 26259 current = current.parent;
michael@0 26260 }
michael@0 26261 return -1;
michael@0 26262 };
michael@0 26263 Scope.prototype.getScopeObjects = function () {
michael@0 26264 var objects = [];
michael@0 26265 var current = this;
michael@0 26266 while (current) {
michael@0 26267 objects.unshift(current.object);
michael@0 26268 current = current.parent;
michael@0 26269 }
michael@0 26270 return objects;
michael@0 26271 };
michael@0 26272 Scope.prototype.findScopeProperty = function (namespaces, name, flags, domain, strict, scopeOnly) {
michael@0 26273 Counter.count('findScopeProperty');
michael@0 26274 var object;
michael@0 26275 var key = makeCacheKey(namespaces, name, flags);
michael@0 26276 if (!scopeOnly && (object = this.cache[key])) {
michael@0 26277 return object;
michael@0 26278 }
michael@0 26279 if (this.object.asHasProperty(namespaces, name, flags, true)) {
michael@0 26280 return this.isWith ? this.object : this.cache[key] = this.object;
michael@0 26281 }
michael@0 26282 if (this.parent) {
michael@0 26283 return this.cache[key] = this.parent.findScopeProperty(namespaces, name, flags, domain, strict, scopeOnly);
michael@0 26284 }
michael@0 26285 if (scopeOnly)
michael@0 26286 return null;
michael@0 26287 if (object = domain.findDomainProperty(new Multiname(namespaces, name, flags), strict, true)) {
michael@0 26288 return object;
michael@0 26289 }
michael@0 26290 if (strict) {
michael@0 26291 Shumway.Debug.unexpected('Cannot find property ' + name);
michael@0 26292 }
michael@0 26293 return this.global.object;
michael@0 26294 };
michael@0 26295 return Scope;
michael@0 26296 }();
michael@0 26297 Runtime.Scope = Scope;
michael@0 26298 function bindFreeMethodScope(methodInfo, scope) {
michael@0 26299 var fn = methodInfo.freeMethod;
michael@0 26300 if (methodInfo.lastBoundMethod && methodInfo.lastBoundMethod.scope === scope) {
michael@0 26301 return methodInfo.lastBoundMethod.boundMethod;
michael@0 26302 }
michael@0 26303 true;
michael@0 26304 var boundMethod;
michael@0 26305 var asGlobal = scope.global.object;
michael@0 26306 if (!methodInfo.hasOptional() && !methodInfo.needsArguments() && !methodInfo.needsRest()) {
michael@0 26307 switch (methodInfo.parameters.length) {
michael@0 26308 case 0:
michael@0 26309 boundMethod = function () {
michael@0 26310 return fn.call(this === jsGlobal ? asGlobal : this, scope);
michael@0 26311 };
michael@0 26312 break;
michael@0 26313 case 1:
michael@0 26314 boundMethod = function (x) {
michael@0 26315 return fn.call(this === jsGlobal ? asGlobal : this, scope, x);
michael@0 26316 };
michael@0 26317 break;
michael@0 26318 case 2:
michael@0 26319 boundMethod = function (x, y) {
michael@0 26320 return fn.call(this === jsGlobal ? asGlobal : this, scope, x, y);
michael@0 26321 };
michael@0 26322 break;
michael@0 26323 case 3:
michael@0 26324 boundMethod = function (x, y, z) {
michael@0 26325 return fn.call(this === jsGlobal ? asGlobal : this, scope, x, y, z);
michael@0 26326 };
michael@0 26327 break;
michael@0 26328 default:
michael@0 26329 break;
michael@0 26330 }
michael@0 26331 }
michael@0 26332 if (!boundMethod) {
michael@0 26333 Counter.count('Bind Scope - Slow Path');
michael@0 26334 boundMethod = function () {
michael@0 26335 Array.prototype.unshift.call(arguments, scope);
michael@0 26336 var global = this === jsGlobal ? scope.global.object : this;
michael@0 26337 return fn.apply(global, arguments);
michael@0 26338 };
michael@0 26339 }
michael@0 26340 boundMethod.methodInfo = methodInfo;
michael@0 26341 boundMethod.instanceConstructor = boundMethod;
michael@0 26342 methodInfo.lastBoundMethod = {
michael@0 26343 scope: scope,
michael@0 26344 boundMethod: boundMethod
michael@0 26345 };
michael@0 26346 return boundMethod;
michael@0 26347 }
michael@0 26348 Runtime.bindFreeMethodScope = bindFreeMethodScope;
michael@0 26349 }(AVM2.Runtime || (AVM2.Runtime = {})));
michael@0 26350 var Runtime = AVM2.Runtime;
michael@0 26351 }(Shumway.AVM2 || (Shumway.AVM2 = {})));
michael@0 26352 var AVM2 = Shumway.AVM2;
michael@0 26353 }(Shumway || (Shumway = {})));
michael@0 26354 var playerglobalLoadedPromise;
michael@0 26355 var playerglobal;
michael@0 26356 var Shumway;
michael@0 26357 (function (Shumway) {
michael@0 26358 (function (AVM2) {
michael@0 26359 (function (Runtime) {
michael@0 26360 var AbcFile = Shumway.AVM2.ABC.AbcFile;
michael@0 26361 var Multiname = Shumway.AVM2.ABC.Multiname;
michael@0 26362 var Namespace = Shumway.AVM2.ABC.Namespace;
michael@0 26363 var MethodInfo = Shumway.AVM2.ABC.MethodInfo;
michael@0 26364 var ClassInfo = Shumway.AVM2.ABC.ClassInfo;
michael@0 26365 var InstanceInfo = Shumway.AVM2.ABC.InstanceInfo;
michael@0 26366 var ScriptInfo = Shumway.AVM2.ABC.ScriptInfo;
michael@0 26367 var createEmptyObject = Shumway.ObjectUtilities.createEmptyObject;
michael@0 26368 var IndentingWriter = Shumway.IndentingWriter;
michael@0 26369 (function (EXECUTION_MODE) {
michael@0 26370 EXECUTION_MODE[EXECUTION_MODE['INTERPRET'] = 1] = 'INTERPRET';
michael@0 26371 EXECUTION_MODE[EXECUTION_MODE['COMPILE'] = 2] = 'COMPILE';
michael@0 26372 }(Runtime.EXECUTION_MODE || (Runtime.EXECUTION_MODE = {})));
michael@0 26373 var EXECUTION_MODE = Runtime.EXECUTION_MODE;
michael@0 26374 function createNewCompartment() {
michael@0 26375 return newGlobal('new-compartment');
michael@0 26376 }
michael@0 26377 function executeScript(script) {
michael@0 26378 var abc = script.abc;
michael@0 26379 true;
michael@0 26380 var global = new Shumway.AVM2.Runtime.Global(script);
michael@0 26381 if (abc.applicationDomain.allowNatives) {
michael@0 26382 global[Multiname.getPublicQualifiedName('unsafeJSNative')] = getNative;
michael@0 26383 }
michael@0 26384 script.executing = true;
michael@0 26385 var scope = new Shumway.AVM2.Runtime.Scope(null, script.global);
michael@0 26386 createFunction(script.init, scope).call(script.global, false);
michael@0 26387 script.executed = true;
michael@0 26388 }
michael@0 26389 Runtime.executeScript = executeScript;
michael@0 26390 function ensureScriptIsExecuted(script, reason) {
michael@0 26391 if (typeof reason === 'undefined') {
michael@0 26392 reason = '';
michael@0 26393 }
michael@0 26394 if (!script.executed && !script.executing) {
michael@0 26395 if (Shumway.AVM2.Runtime.traceExecution.value >= 2) {
michael@0 26396 log('Executing Script For: ' + reason);
michael@0 26397 }
michael@0 26398 executeScript(script);
michael@0 26399 }
michael@0 26400 }
michael@0 26401 Runtime.ensureScriptIsExecuted = ensureScriptIsExecuted;
michael@0 26402 (function (Glue) {
michael@0 26403 Glue[Glue['PUBLIC_PROPERTIES'] = 1] = 'PUBLIC_PROPERTIES';
michael@0 26404 Glue[Glue['PUBLIC_METHODS'] = 2] = 'PUBLIC_METHODS';
michael@0 26405 Glue[Glue['ALL'] = 1 | 2] = 'ALL';
michael@0 26406 }(Runtime.Glue || (Runtime.Glue = {})));
michael@0 26407 var Glue = Runtime.Glue;
michael@0 26408 function grabAbc(abcName) {
michael@0 26409 var entry = playerglobal.scripts[abcName];
michael@0 26410 if (!entry) {
michael@0 26411 return null;
michael@0 26412 }
michael@0 26413 var offset = entry.offset;
michael@0 26414 var length = entry.length;
michael@0 26415 return new AbcFile(new Uint8Array(playerglobal.abcs, offset, length), abcName);
michael@0 26416 }
michael@0 26417 function findDefiningAbc(mn) {
michael@0 26418 if (!playerglobal) {
michael@0 26419 return null;
michael@0 26420 }
michael@0 26421 for (var i = 0; i < mn.namespaces.length; i++) {
michael@0 26422 var name = mn.namespaces[i].uri + ':' + mn.name;
michael@0 26423 var abcName = playerglobal.map[name];
michael@0 26424 if (abcName) {
michael@0 26425 break;
michael@0 26426 }
michael@0 26427 }
michael@0 26428 if (abcName) {
michael@0 26429 return grabAbc(abcName);
michael@0 26430 }
michael@0 26431 return null;
michael@0 26432 }
michael@0 26433 function promiseFile(path, responseType) {
michael@0 26434 return new Promise(function (resolve, reject) {
michael@0 26435 var xhr = new XMLHttpRequest();
michael@0 26436 xhr.open('GET', path);
michael@0 26437 xhr.responseType = responseType;
michael@0 26438 xhr.onload = function () {
michael@0 26439 if (xhr.response) {
michael@0 26440 resolve(xhr.response);
michael@0 26441 } else {
michael@0 26442 reject('Unable to load ' + path + ': ' + xhr.statusText);
michael@0 26443 }
michael@0 26444 };
michael@0 26445 xhr.send();
michael@0 26446 });
michael@0 26447 }
michael@0 26448 var AVM2 = function () {
michael@0 26449 function AVM2(sysMode, appMode, loadAVM1) {
michael@0 26450 this.systemDomain = new ApplicationDomain(this, null, sysMode, true);
michael@0 26451 this.applicationDomain = new ApplicationDomain(this, this.systemDomain, appMode, false);
michael@0 26452 this.findDefiningAbc = findDefiningAbc;
michael@0 26453 this.loadAVM1 = loadAVM1;
michael@0 26454 this.isAVM1Loaded = false;
michael@0 26455 this.exception = {
michael@0 26456 value: undefined
michael@0 26457 };
michael@0 26458 this.exceptions = [];
michael@0 26459 }
michael@0 26460 AVM2.initialize = function (sysMode, appMode, loadAVM1) {
michael@0 26461 AVM2.instance = new AVM2(sysMode, appMode, loadAVM1);
michael@0 26462 };
michael@0 26463 AVM2.currentAbc = function () {
michael@0 26464 var caller = arguments.callee;
michael@0 26465 var maxDepth = 20;
michael@0 26466 var abc = null;
michael@0 26467 for (var i = 0; i < maxDepth && caller; i++) {
michael@0 26468 var mi = caller.methodInfo;
michael@0 26469 if (mi) {
michael@0 26470 abc = mi.abc;
michael@0 26471 break;
michael@0 26472 }
michael@0 26473 caller = caller.caller;
michael@0 26474 }
michael@0 26475 return abc;
michael@0 26476 };
michael@0 26477 AVM2.currentDomain = function () {
michael@0 26478 var abc = AVM2.currentAbc();
michael@0 26479 return abc.applicationDomain;
michael@0 26480 };
michael@0 26481 AVM2.isPlayerglobalLoaded = function () {
michael@0 26482 return !(!playerglobal);
michael@0 26483 };
michael@0 26484 AVM2.loadPlayerglobal = function (abcsPath, catalogPath) {
michael@0 26485 if (playerglobalLoadedPromise) {
michael@0 26486 return Promise.reject('Playerglobal is already loaded');
michael@0 26487 }
michael@0 26488 playerglobalLoadedPromise = Promise.all([
michael@0 26489 promiseFile(abcsPath, 'arraybuffer'),
michael@0 26490 promiseFile(catalogPath, 'json')
michael@0 26491 ]).then(function (result) {
michael@0 26492 playerglobal = {
michael@0 26493 abcs: result[0],
michael@0 26494 map: Object.create(null),
michael@0 26495 scripts: Object.create(null)
michael@0 26496 };
michael@0 26497 var catalog = result[1];
michael@0 26498 for (var i = 0; i < catalog.length; i++) {
michael@0 26499 var abc = catalog[i];
michael@0 26500 playerglobal.scripts[abc.name] = abc;
michael@0 26501 if (typeof abc.defs === 'string') {
michael@0 26502 playerglobal.map[abc.defs] = abc.name;
michael@0 26503 } else {
michael@0 26504 for (var j = 0; j < abc.defs.length; j++) {
michael@0 26505 var def = abc.defs[j];
michael@0 26506 playerglobal.map[def] = abc.name;
michael@0 26507 }
michael@0 26508 }
michael@0 26509 }
michael@0 26510 }, function (e) {
michael@0 26511 console.error(e);
michael@0 26512 });
michael@0 26513 return playerglobalLoadedPromise;
michael@0 26514 };
michael@0 26515 AVM2.prototype.notifyConstruct = function (instanceConstructor, args) {
michael@0 26516 };
michael@0 26517 AVM2.getStackTrace = function () {
michael@0 26518 Shumway.Debug.notImplemented('getStackTrace');
michael@0 26519 };
michael@0 26520 return AVM2;
michael@0 26521 }();
michael@0 26522 Runtime.AVM2 = AVM2;
michael@0 26523 var ApplicationDomain = function () {
michael@0 26524 function ApplicationDomain(vm, base, mode, allowNatives) {
michael@0 26525 true;
michael@0 26526 true;
michael@0 26527 this.vm = vm;
michael@0 26528 this.abcs = [];
michael@0 26529 this.loadedAbcs = {};
michael@0 26530 this.loadedClasses = [];
michael@0 26531 this.classCache = createEmptyObject();
michael@0 26532 this.scriptCache = createEmptyObject();
michael@0 26533 this.classInfoCache = createEmptyObject();
michael@0 26534 this.base = base;
michael@0 26535 this.allowNatives = allowNatives;
michael@0 26536 this.mode = mode;
michael@0 26537 this.onMessage = new Callback();
michael@0 26538 if (base) {
michael@0 26539 this.system = base.system;
michael@0 26540 } else {
michael@0 26541 this.system = this;
michael@0 26542 }
michael@0 26543 }
michael@0 26544 ApplicationDomain.passthroughCallable = function (f) {
michael@0 26545 return {
michael@0 26546 call: function ($this) {
michael@0 26547 Array.prototype.shift.call(arguments);
michael@0 26548 return f.apply($this, arguments);
michael@0 26549 },
michael@0 26550 apply: function ($this, args) {
michael@0 26551 return f.apply($this, args);
michael@0 26552 }
michael@0 26553 };
michael@0 26554 };
michael@0 26555 ApplicationDomain.coerceCallable = function (type) {
michael@0 26556 return {
michael@0 26557 call: function ($this, value) {
michael@0 26558 return Shumway.AVM2.Runtime.asCoerce(type, value);
michael@0 26559 },
michael@0 26560 apply: function ($this, args) {
michael@0 26561 return Shumway.AVM2.Runtime.asCoerce(type, args[0]);
michael@0 26562 }
michael@0 26563 };
michael@0 26564 };
michael@0 26565 ApplicationDomain.constructingCallable = function (instanceConstructor) {
michael@0 26566 return {
michael@0 26567 call: function (self) {
michael@0 26568 return new (Function.bind.apply(instanceConstructor, arguments))();
michael@0 26569 },
michael@0 26570 apply: function (self, args) {
michael@0 26571 return new (Function.bind.apply(instanceConstructor, [
michael@0 26572 self
michael@0 26573 ].concat(args)))();
michael@0 26574 }
michael@0 26575 };
michael@0 26576 };
michael@0 26577 ApplicationDomain.prototype.getType = function (multiname) {
michael@0 26578 return this.getProperty(multiname, true, true);
michael@0 26579 };
michael@0 26580 ApplicationDomain.prototype.getProperty = function (multiname, strict, execute) {
michael@0 26581 var resolved = this.findDefiningScript(multiname, execute);
michael@0 26582 if (resolved) {
michael@0 26583 if (!resolved.script.executing) {
michael@0 26584 return undefined;
michael@0 26585 }
michael@0 26586 return resolved.script.global[Multiname.getQualifiedName(resolved.trait.name)];
michael@0 26587 }
michael@0 26588 if (strict) {
michael@0 26589 return Shumway.Debug.unexpected('Cannot find property ' + multiname);
michael@0 26590 }
michael@0 26591 return undefined;
michael@0 26592 };
michael@0 26593 ApplicationDomain.prototype.getClass = function (simpleName) {
michael@0 26594 var cache = this.classCache;
michael@0 26595 var c = cache[simpleName];
michael@0 26596 if (!c) {
michael@0 26597 c = cache[simpleName] = this.getProperty(Multiname.fromSimpleName(simpleName), true, true);
michael@0 26598 }
michael@0 26599 true;
michael@0 26600 return c;
michael@0 26601 };
michael@0 26602 ApplicationDomain.prototype.findClass = function (simpleName) {
michael@0 26603 if (simpleName in this.classCache) {
michael@0 26604 return true;
michael@0 26605 }
michael@0 26606 return this.findDomainProperty(Multiname.fromSimpleName(simpleName), false, true);
michael@0 26607 };
michael@0 26608 ApplicationDomain.prototype.findDomainProperty = function (multiname, strict, execute) {
michael@0 26609 if (Shumway.AVM2.Runtime.traceDomain.value) {
michael@0 26610 log('ApplicationDomain.findDomainProperty: ' + multiname);
michael@0 26611 }
michael@0 26612 var resolved = this.findDefiningScript(multiname, execute);
michael@0 26613 if (resolved) {
michael@0 26614 return resolved.script.global;
michael@0 26615 }
michael@0 26616 if (strict) {
michael@0 26617 return Shumway.Debug.unexpected('Cannot find property ' + multiname);
michael@0 26618 } else {
michael@0 26619 return undefined;
michael@0 26620 }
michael@0 26621 return undefined;
michael@0 26622 };
michael@0 26623 ApplicationDomain.prototype.findClassInfo = function (mn) {
michael@0 26624 var originalQn;
michael@0 26625 if (Multiname.isQName(mn)) {
michael@0 26626 originalQn = Multiname.getQualifiedName(mn);
michael@0 26627 var ci = this.classInfoCache[originalQn];
michael@0 26628 if (ci) {
michael@0 26629 return ci;
michael@0 26630 }
michael@0 26631 } else {
michael@0 26632 var ci = this.classInfoCache[mn.runtimeId];
michael@0 26633 if (ci) {
michael@0 26634 return ci;
michael@0 26635 }
michael@0 26636 }
michael@0 26637 if (this.base) {
michael@0 26638 ci = this.base.findClassInfo(mn);
michael@0 26639 if (ci) {
michael@0 26640 return ci;
michael@0 26641 }
michael@0 26642 }
michael@0 26643 var abcs = this.abcs;
michael@0 26644 for (var i = 0; i < abcs.length; i++) {
michael@0 26645 var abc = abcs[i];
michael@0 26646 var scripts = abc.scripts;
michael@0 26647 for (var j = 0; j < scripts.length; j++) {
michael@0 26648 var script = scripts[j];
michael@0 26649 var traits = script.traits;
michael@0 26650 for (var k = 0; k < traits.length; k++) {
michael@0 26651 var trait = traits[k];
michael@0 26652 if (trait.isClass()) {
michael@0 26653 var traitName = Multiname.getQualifiedName(trait.name);
michael@0 26654 if (originalQn) {
michael@0 26655 if (traitName === originalQn) {
michael@0 26656 return this.classInfoCache[originalQn] = trait.classInfo;
michael@0 26657 }
michael@0 26658 } else {
michael@0 26659 for (var m = 0, n = mn.namespaces.length; m < n; m++) {
michael@0 26660 var qn = mn.getQName(m);
michael@0 26661 if (traitName === Multiname.getQualifiedName(qn)) {
michael@0 26662 return this.classInfoCache[qn] = trait.classInfo;
michael@0 26663 }
michael@0 26664 }
michael@0 26665 }
michael@0 26666 }
michael@0 26667 }
michael@0 26668 }
michael@0 26669 }
michael@0 26670 if (!this.base && this.vm.findDefiningAbc) {
michael@0 26671 var abc = this.vm.findDefiningAbc(mn);
michael@0 26672 if (abc !== null && !this.loadedAbcs[abc.name]) {
michael@0 26673 this.loadedAbcs[abc.name] = true;
michael@0 26674 this.loadAbc(abc);
michael@0 26675 return this.findClassInfo(mn);
michael@0 26676 }
michael@0 26677 }
michael@0 26678 return undefined;
michael@0 26679 };
michael@0 26680 ApplicationDomain.prototype.installNative = function (name, func) {
michael@0 26681 natives[name] = function () {
michael@0 26682 return func;
michael@0 26683 };
michael@0 26684 };
michael@0 26685 ApplicationDomain.prototype.findDefiningScript = function (mn, execute) {
michael@0 26686 var resolved = this.scriptCache[mn.runtimeId];
michael@0 26687 if (resolved && (resolved.script.executed || !execute)) {
michael@0 26688 return resolved;
michael@0 26689 }
michael@0 26690 if (this.base) {
michael@0 26691 resolved = this.base.findDefiningScript(mn, execute);
michael@0 26692 if (resolved) {
michael@0 26693 return resolved;
michael@0 26694 }
michael@0 26695 }
michael@0 26696 Counter.count('ApplicationDomain: findDefiningScript');
michael@0 26697 var abcs = this.abcs;
michael@0 26698 for (var i = 0; i < abcs.length; i++) {
michael@0 26699 var abc = abcs[i];
michael@0 26700 var scripts = abc.scripts;
michael@0 26701 for (var j = 0; j < scripts.length; j++) {
michael@0 26702 var script = scripts[j];
michael@0 26703 var traits = script.traits;
michael@0 26704 if (mn instanceof Multiname) {
michael@0 26705 for (var k = 0; k < traits.length; k++) {
michael@0 26706 var trait = traits[k];
michael@0 26707 if (mn.hasQName(trait.name)) {
michael@0 26708 if (execute) {
michael@0 26709 ensureScriptIsExecuted(script, String(trait.name));
michael@0 26710 }
michael@0 26711 return this.scriptCache[mn.runtimeId] = {
michael@0 26712 script: script,
michael@0 26713 trait: trait
michael@0 26714 };
michael@0 26715 }
michael@0 26716 }
michael@0 26717 } else {
michael@0 26718 Shumway.Debug.unexpected();
michael@0 26719 }
michael@0 26720 }
michael@0 26721 }
michael@0 26722 if (!this.base && this.vm.findDefiningAbc) {
michael@0 26723 var abc = this.vm.findDefiningAbc(mn);
michael@0 26724 if (abc !== null && !this.loadedAbcs[abc.name]) {
michael@0 26725 this.loadedAbcs[abc.name] = true;
michael@0 26726 this.loadAbc(abc);
michael@0 26727 return this.findDefiningScript(mn, execute);
michael@0 26728 }
michael@0 26729 }
michael@0 26730 return undefined;
michael@0 26731 };
michael@0 26732 ApplicationDomain.prototype.compileAbc = function (abc, writer) {
michael@0 26733 compileAbc(abc, writer);
michael@0 26734 };
michael@0 26735 ApplicationDomain.prototype.executeAbc = function (abc) {
michael@0 26736 this.loadAbc(abc);
michael@0 26737 executeScript(abc.lastScript);
michael@0 26738 };
michael@0 26739 ApplicationDomain.prototype.loadAbc = function (abc) {
michael@0 26740 if (Shumway.AVM2.Runtime.traceExecution.value) {
michael@0 26741 log('Loading: ' + abc.name);
michael@0 26742 }
michael@0 26743 abc.applicationDomain = this;
michael@0 26744 GlobalMultinameResolver.loadAbc(abc);
michael@0 26745 this.abcs.push(abc);
michael@0 26746 if (!this.base) {
michael@0 26747 Type.initializeTypes(this);
michael@0 26748 }
michael@0 26749 };
michael@0 26750 ApplicationDomain.prototype.broadcastMessage = function (type, message, origin) {
michael@0 26751 if (debug) {
michael@0 26752 Timer.start('broadcast: ' + type);
michael@0 26753 }
michael@0 26754 try {
michael@0 26755 this.onMessage.notify1(type, {
michael@0 26756 data: message,
michael@0 26757 origin: origin,
michael@0 26758 source: this
michael@0 26759 });
michael@0 26760 } catch (e) {
michael@0 26761 avm2.exceptions.push({
michael@0 26762 source: type,
michael@0 26763 message: e.message,
michael@0 26764 stack: e.stack
michael@0 26765 });
michael@0 26766 throw e;
michael@0 26767 }
michael@0 26768 if (debug) {
michael@0 26769 Timer.stop();
michael@0 26770 }
michael@0 26771 };
michael@0 26772 ApplicationDomain.prototype.traceLoadedClasses = function (lastOnly) {
michael@0 26773 var writer = new IndentingWriter();
michael@0 26774 lastOnly || writer.enter('Loaded Classes And Interfaces');
michael@0 26775 var classes = lastOnly ? [
michael@0 26776 this.loadedClasses.last()
michael@0 26777 ] : this.loadedClasses;
michael@0 26778 classes.forEach(function (cls) {
michael@0 26779 if (cls !== Shumway.AVM2.Runtime.Class) {
michael@0 26780 cls.trace(writer);
michael@0 26781 }
michael@0 26782 });
michael@0 26783 lastOnly || writer.leave('');
michael@0 26784 };
michael@0 26785 return ApplicationDomain;
michael@0 26786 }();
michael@0 26787 Runtime.ApplicationDomain = ApplicationDomain;
michael@0 26788 var SecurityDomain = function () {
michael@0 26789 function SecurityDomain() {
michael@0 26790 this.compartment = createNewCompartment();
michael@0 26791 this.compartment.homePath = homePath;
michael@0 26792 this.compartment.release = true;
michael@0 26793 this.compartment.eval(snarf('compartment.js'));
michael@0 26794 }
michael@0 26795 SecurityDomain.prototype.initializeShell = function (sysMode, appMode) {
michael@0 26796 var compartment = this.compartment;
michael@0 26797 compartment.AVM2.initialize(sysMode, appMode);
michael@0 26798 compartment.AVM2.instance.systemDomain.executeAbc(compartment.grabAbc(homePath + 'src/avm2/generated/builtin/builtin.abc'));
michael@0 26799 compartment.AVM2.instance.systemDomain.executeAbc(compartment.grabAbc(homePath + 'src/avm2/generated/shell/shell.abc'));
michael@0 26800 this.systemDomain = compartment.AVM2.instance.systemDomain;
michael@0 26801 this.applicationDomain = compartment.AVM2.instance.applicationDomain;
michael@0 26802 };
michael@0 26803 return SecurityDomain;
michael@0 26804 }();
michael@0 26805 Runtime.SecurityDomain = SecurityDomain;
michael@0 26806 }(AVM2.Runtime || (AVM2.Runtime = {})));
michael@0 26807 var Runtime = AVM2.Runtime;
michael@0 26808 }(Shumway.AVM2 || (Shumway.AVM2 = {})));
michael@0 26809 var AVM2 = Shumway.AVM2;
michael@0 26810 }(Shumway || (Shumway = {})));
michael@0 26811 var Glue = Shumway.AVM2.Runtime.Glue;
michael@0 26812 var ApplicationDomain = Shumway.AVM2.Runtime.ApplicationDomain;
michael@0 26813 var AVM2 = Shumway.AVM2.Runtime.AVM2;
michael@0 26814 var EXECUTION_MODE = Shumway.AVM2.Runtime.EXECUTION_MODE;
michael@0 26815 var ApplicationDomain = Shumway.AVM2.Runtime.ApplicationDomain;
michael@0 26816 var AVM2 = Shumway.AVM2.Runtime.AVM2;
michael@0 26817 var EXECUTION_MODE = Shumway.AVM2.Runtime.EXECUTION_MODE;
michael@0 26818 var Shumway;
michael@0 26819 (function (Shumway) {
michael@0 26820 (function (AVM2) {
michael@0 26821 (function (Runtime) {
michael@0 26822 var Multiname = Shumway.AVM2.ABC.Multiname;
michael@0 26823 var Namespace = Shumway.AVM2.ABC.Namespace;
michael@0 26824 var ClassInfo = Shumway.AVM2.ABC.ClassInfo;
michael@0 26825 var InstanceInfo = Shumway.AVM2.ABC.InstanceInfo;
michael@0 26826 var InstanceBindings = Shumway.AVM2.Runtime.InstanceBindings;
michael@0 26827 var ClassBindings = Shumway.AVM2.Runtime.ClassBindings;
michael@0 26828 var defineNonEnumerableGetterOrSetter = Shumway.ObjectUtilities.defineNonEnumerableGetterOrSetter;
michael@0 26829 var defineNonEnumerableProperty = Shumway.ObjectUtilities.defineNonEnumerableProperty;
michael@0 26830 var defineReadOnlyProperty = Shumway.ObjectUtilities.defineReadOnlyProperty;
michael@0 26831 var defineNonEnumerableGetter = Shumway.ObjectUtilities.defineNonEnumerableGetter;
michael@0 26832 var createEmptyObject = Shumway.ObjectUtilities.createEmptyObject;
michael@0 26833 var toKeyValueArray = Shumway.ObjectUtilities.toKeyValueArray;
michael@0 26834 var Interface = function () {
michael@0 26835 function Interface(classInfo) {
michael@0 26836 var ii = classInfo.instanceInfo;
michael@0 26837 true;
michael@0 26838 this.name = ii.name;
michael@0 26839 this.classInfo = classInfo;
michael@0 26840 }
michael@0 26841 Interface.createInterface = function (classInfo) {
michael@0 26842 var ii = classInfo.instanceInfo;
michael@0 26843 true;
michael@0 26844 if (Shumway.AVM2.Runtime.traceExecution.value) {
michael@0 26845 var str = 'Creating Interface ' + ii.name;
michael@0 26846 if (ii.interfaces.length) {
michael@0 26847 str += ' implements ' + ii.interfaces.map(function (name) {
michael@0 26848 return name.getName();
michael@0 26849 }).join(', ');
michael@0 26850 }
michael@0 26851 log(str);
michael@0 26852 }
michael@0 26853 var cls = new Interface(classInfo);
michael@0 26854 cls.interfaceBindings = new InstanceBindings(null, ii, null, null);
michael@0 26855 return cls;
michael@0 26856 };
michael@0 26857 Interface.prototype.toString = function () {
michael@0 26858 return '[interface ' + this.name + ']';
michael@0 26859 };
michael@0 26860 Interface.prototype.isInstance = function (value) {
michael@0 26861 if (value === null || typeof value !== 'object') {
michael@0 26862 return false;
michael@0 26863 }
michael@0 26864 true;
michael@0 26865 var qualifiedName = Multiname.getQualifiedName(this.name);
michael@0 26866 return value.class.implementedInterfaces[qualifiedName] !== undefined;
michael@0 26867 };
michael@0 26868 Interface.prototype.trace = function (writer) {
michael@0 26869 writer.enter('interface ' + this.name.getName());
michael@0 26870 writer.enter('interfaceBindings: ');
michael@0 26871 this.interfaceBindings.trace(writer);
michael@0 26872 writer.outdent();
michael@0 26873 writer.outdent();
michael@0 26874 writer.leave('}');
michael@0 26875 };
michael@0 26876 Interface.prototype.call = function (self, x) {
michael@0 26877 return x;
michael@0 26878 };
michael@0 26879 Interface.prototype.apply = function (self, args) {
michael@0 26880 return args[0];
michael@0 26881 };
michael@0 26882 return Interface;
michael@0 26883 }();
michael@0 26884 Runtime.Interface = Interface;
michael@0 26885 function setDefaultProperties(cls) {
michael@0 26886 defineNonEnumerableProperty(cls.dynamicPrototype, Multiname.getPublicQualifiedName('constructor'), cls);
michael@0 26887 defineReadOnlyProperty(cls.traitsPrototype, 'class', cls);
michael@0 26888 defineReadOnlyProperty(cls.instanceConstructor, 'class', cls);
michael@0 26889 }
michael@0 26890 Runtime.setDefaultProperties = setDefaultProperties;
michael@0 26891 var Class = function () {
michael@0 26892 function Class(name, instanceConstructor, callable) {
michael@0 26893 this.debugName = name;
michael@0 26894 if (instanceConstructor) {
michael@0 26895 true;
michael@0 26896 this.instanceConstructor = instanceConstructor;
michael@0 26897 this.instanceConstructorNoInitialize = instanceConstructor;
michael@0 26898 this.hasInitialize = 0;
michael@0 26899 this.instanceConstructor.class = this;
michael@0 26900 }
michael@0 26901 if (!callable) {
michael@0 26902 callable = Shumway.AVM2.Runtime.ApplicationDomain.coerceCallable(this);
michael@0 26903 } else if (callable === Shumway.AVM2.Runtime.ApplicationDomain.coerceCallable) {
michael@0 26904 callable = Shumway.AVM2.Runtime.ApplicationDomain.coerceCallable(this);
michael@0 26905 }
michael@0 26906 defineNonEnumerableProperty(this, 'call', callable.call);
michael@0 26907 defineNonEnumerableProperty(this, 'apply', callable.apply);
michael@0 26908 }
michael@0 26909 Class.createClass = function (classInfo, baseClass, scope) {
michael@0 26910 var ci = classInfo;
michael@0 26911 var ii = ci.instanceInfo;
michael@0 26912 var domain = ci.abc.applicationDomain;
michael@0 26913 var className = Multiname.getName(ii.name);
michael@0 26914 var isNativeClass = ci.native;
michael@0 26915 if (isNativeClass) {
michael@0 26916 var buildClass = getNative(ci.native.cls);
michael@0 26917 if (!buildClass) {
michael@0 26918 Shumway.Debug.unexpected('No native for ' + ci.native.cls);
michael@0 26919 }
michael@0 26920 if (!baseClass) {
michael@0 26921 scope = new Scope(scope, Class);
michael@0 26922 }
michael@0 26923 }
michael@0 26924 var classScope = new Scope(scope, null);
michael@0 26925 var instanceConstructor = createFunction(ii.init, classScope, false);
michael@0 26926 var cls;
michael@0 26927 if (isNativeClass) {
michael@0 26928 cls = buildClass(domain, classScope, instanceConstructor, baseClass);
michael@0 26929 } else {
michael@0 26930 cls = new Class(className, instanceConstructor);
michael@0 26931 }
michael@0 26932 cls.className = className;
michael@0 26933 cls.classInfo = classInfo;
michael@0 26934 cls.scope = classScope;
michael@0 26935 classScope.object = cls;
michael@0 26936 var classNatives;
michael@0 26937 var instanceNatives;
michael@0 26938 if (isNativeClass) {
michael@0 26939 if (cls.native) {
michael@0 26940 classNatives = cls.native.static;
michael@0 26941 instanceNatives = cls.native.instance;
michael@0 26942 }
michael@0 26943 } else {
michael@0 26944 cls.extend(baseClass);
michael@0 26945 }
michael@0 26946 cls.classBindings = new ClassBindings(classInfo, classScope, classNatives);
michael@0 26947 cls.classBindings.applyTo(domain, cls);
michael@0 26948 defineReadOnlyProperty(cls, Shumway.AVM2.Runtime.VM_IS_CLASS, true);
michael@0 26949 cls.instanceBindings = new InstanceBindings(baseClass ? baseClass.instanceBindings : null, ii, classScope, instanceNatives);
michael@0 26950 if (cls.instanceConstructor) {
michael@0 26951 cls.instanceBindings.applyTo(domain, cls.traitsPrototype);
michael@0 26952 }
michael@0 26953 cls.implementedInterfaces = cls.instanceBindings.implementedInterfaces;
michael@0 26954 return cls;
michael@0 26955 };
michael@0 26956 Class.prototype.setSymbol = function (props) {
michael@0 26957 this.instanceConstructor.prototype.symbol = props;
michael@0 26958 };
michael@0 26959 Class.prototype.getSymbol = function () {
michael@0 26960 return this.instanceConstructor.prototype.symbol;
michael@0 26961 };
michael@0 26962 Class.prototype.initializeInstance = function (obj) {
michael@0 26963 var c = this;
michael@0 26964 var initializes = [];
michael@0 26965 while (c) {
michael@0 26966 if (c.hasInitialize & Class.OWN_INITIALIZE) {
michael@0 26967 initializes.push(c.instanceConstructor.prototype.initialize);
michael@0 26968 }
michael@0 26969 c = c.baseClass;
michael@0 26970 }
michael@0 26971 var s;
michael@0 26972 while (s = initializes.pop()) {
michael@0 26973 s.call(obj);
michael@0 26974 }
michael@0 26975 Counter.count('Initialize Instance ' + obj.class);
michael@0 26976 };
michael@0 26977 Class.prototype.createInstance = function (args) {
michael@0 26978 var o = Object.create(this.instanceConstructor.prototype);
michael@0 26979 this.instanceConstructor.apply(o, args);
michael@0 26980 return o;
michael@0 26981 };
michael@0 26982 Class.prototype.createAsSymbol = function (props) {
michael@0 26983 var o = Object.create(this.instanceConstructor.prototype);
michael@0 26984 if (o.symbol) {
michael@0 26985 var symbol = Object.create(o.symbol);
michael@0 26986 for (var prop in props) {
michael@0 26987 symbol[prop] = props[prop];
michael@0 26988 }
michael@0 26989 o.symbol = symbol;
michael@0 26990 } else {
michael@0 26991 o.symbol = props;
michael@0 26992 }
michael@0 26993 return o;
michael@0 26994 };
michael@0 26995 Class.prototype.extendNative = function (baseClass, native) {
michael@0 26996 this.baseClass = baseClass;
michael@0 26997 this.dynamicPrototype = Object.getPrototypeOf(native.prototype);
michael@0 26998 this.instanceConstructor.prototype = this.traitsPrototype = native.prototype;
michael@0 26999 setDefaultProperties(this);
michael@0 27000 };
michael@0 27001 Class.prototype.extendWrapper = function (baseClass, wrapper) {
michael@0 27002 true;
michael@0 27003 this.baseClass = baseClass;
michael@0 27004 this.dynamicPrototype = Object.create(baseClass.dynamicPrototype);
michael@0 27005 var traitsPrototype = Object.create(this.dynamicPrototype, Shumway.ObjectUtilities.getOwnPropertyDescriptors(wrapper.prototype));
michael@0 27006 this.instanceConstructor.prototype = this.traitsPrototype = traitsPrototype;
michael@0 27007 setDefaultProperties(this);
michael@0 27008 };
michael@0 27009 Class.prototype.extendBuiltin = function (baseClass) {
michael@0 27010 true;
michael@0 27011 this.baseClass = baseClass;
michael@0 27012 this.dynamicPrototype = this.traitsPrototype = this.instanceConstructor.prototype;
michael@0 27013 setDefaultProperties(this);
michael@0 27014 };
michael@0 27015 Class.prototype.extend = function (baseClass) {
michael@0 27016 true;
michael@0 27017 this.baseClass = baseClass;
michael@0 27018 this.dynamicPrototype = Object.create(baseClass.dynamicPrototype);
michael@0 27019 if (baseClass.hasInitialize) {
michael@0 27020 var instanceConstructorNoInitialize = this.instanceConstructor;
michael@0 27021 var self = this;
michael@0 27022 this.instanceConstructor = function () {
michael@0 27023 self.initializeInstance(this);
michael@0 27024 instanceConstructorNoInitialize.apply(this, arguments);
michael@0 27025 };
michael@0 27026 defineReadOnlyProperty(this.instanceConstructor, 'class', instanceConstructorNoInitialize.class);
michael@0 27027 this.hasInitialize |= Class.SUPER_INITIALIZE;
michael@0 27028 }
michael@0 27029 this.instanceConstructor.prototype = this.traitsPrototype = Object.create(this.dynamicPrototype);
michael@0 27030 setDefaultProperties(this);
michael@0 27031 };
michael@0 27032 Class.prototype.setDefaultProperties = function () {
michael@0 27033 setDefaultProperties(this);
michael@0 27034 };
michael@0 27035 Class.prototype.link = function (definition) {
michael@0 27036 true;
michael@0 27037 true;
michael@0 27038 if (definition.initialize) {
michael@0 27039 if (!this.hasInitialize) {
michael@0 27040 var instanceConstructorNoInitialize = this.instanceConstructor;
michael@0 27041 var self = this;
michael@0 27042 this.instanceConstructor = function () {
michael@0 27043 self.initializeInstance(this);
michael@0 27044 instanceConstructorNoInitialize.apply(this, arguments);
michael@0 27045 };
michael@0 27046 defineReadOnlyProperty(this.instanceConstructor, 'class', instanceConstructorNoInitialize.class);
michael@0 27047 this.instanceConstructor.prototype = instanceConstructorNoInitialize.prototype;
michael@0 27048 }
michael@0 27049 this.hasInitialize |= Class.OWN_INITIALIZE;
michael@0 27050 }
michael@0 27051 var dynamicPrototype = this.dynamicPrototype;
michael@0 27052 var keys = Object.keys(definition);
michael@0 27053 for (var i = 0; i < keys.length; i++) {
michael@0 27054 var propertyName = keys[i];
michael@0 27055 Object.defineProperty(dynamicPrototype, propertyName, Object.getOwnPropertyDescriptor(definition, propertyName));
michael@0 27056 }
michael@0 27057 function glueProperties(obj, properties) {
michael@0 27058 var keys = Object.keys(properties);
michael@0 27059 for (var i = 0; i < keys.length; i++) {
michael@0 27060 var propertyName = keys[i];
michael@0 27061 var propertyGlue = properties[propertyName];
michael@0 27062 var propertySimpleName;
michael@0 27063 var glueOpenMethod = false;
michael@0 27064 if (propertyGlue.indexOf('open ') >= 0) {
michael@0 27065 propertySimpleName = propertyGlue.substring(5);
michael@0 27066 glueOpenMethod = true;
michael@0 27067 } else {
michael@0 27068 propertySimpleName = propertyGlue;
michael@0 27069 }
michael@0 27070 true;
michael@0 27071 var qn = Multiname.getQualifiedName(Multiname.fromSimpleName(propertySimpleName));
michael@0 27072 if (glueOpenMethod) {
michael@0 27073 qn = Shumway.AVM2.Runtime.VM_OPEN_METHOD_PREFIX + qn;
michael@0 27074 }
michael@0 27075 true;
michael@0 27076 var descriptor = Object.getOwnPropertyDescriptor(obj, qn);
michael@0 27077 if (descriptor && descriptor.get) {
michael@0 27078 Object.defineProperty(obj, propertyName, descriptor);
michael@0 27079 } else {
michael@0 27080 Object.defineProperty(obj, propertyName, {
michael@0 27081 get: new Function('', 'return this.' + qn),
michael@0 27082 set: new Function('v', 'this.' + qn + ' = v')
michael@0 27083 });
michael@0 27084 }
michael@0 27085 }
michael@0 27086 }
michael@0 27087 function generatePropertiesFromTraits(traits) {
michael@0 27088 var properties = createEmptyObject();
michael@0 27089 traits.forEach(function (trait) {
michael@0 27090 var ns = trait.name.getNamespace();
michael@0 27091 if (!ns.isPublic()) {
michael@0 27092 return;
michael@0 27093 }
michael@0 27094 properties[trait.name.getName()] = (trait.isMethod() ? 'open ' : '') + 'public ' + trait.name.getName();
michael@0 27095 });
michael@0 27096 return properties;
michael@0 27097 }
michael@0 27098 var glue = definition.__glue__;
michael@0 27099 if (!glue) {
michael@0 27100 return;
michael@0 27101 }
michael@0 27102 if (glue.script) {
michael@0 27103 if (glue.script.instance) {
michael@0 27104 if (Shumway.isNumber(glue.script.instance)) {
michael@0 27105 true;
michael@0 27106 glueProperties(dynamicPrototype, generatePropertiesFromTraits(this.classInfo.instanceInfo.traits));
michael@0 27107 } else {
michael@0 27108 glueProperties(dynamicPrototype, glue.script.instance);
michael@0 27109 }
michael@0 27110 }
michael@0 27111 if (glue.script.static) {
michael@0 27112 if (Shumway.isNumber(glue.script.static)) {
michael@0 27113 true;
michael@0 27114 glueProperties(this, generatePropertiesFromTraits(this.classInfo.traits));
michael@0 27115 } else {
michael@0 27116 glueProperties(this, glue.script.static);
michael@0 27117 }
michael@0 27118 }
michael@0 27119 }
michael@0 27120 };
michael@0 27121 Class.prototype.linkNatives = function (definition) {
michael@0 27122 var glue = definition.__glue__;
michael@0 27123 this.native = glue.native;
michael@0 27124 };
michael@0 27125 Class.prototype.verify = function () {
michael@0 27126 var instanceConstructor = this.instanceConstructor;
michael@0 27127 var tP = this.traitsPrototype;
michael@0 27128 var dP = this.dynamicPrototype;
michael@0 27129 true;
michael@0 27130 true;
michael@0 27131 true;
michael@0 27132 true;
michael@0 27133 if (tP !== Object.prototype) {
michael@0 27134 }
michael@0 27135 true;
michael@0 27136 };
michael@0 27137 Class.prototype.coerce = function (value) {
michael@0 27138 return value;
michael@0 27139 };
michael@0 27140 Class.prototype.isInstanceOf = function (value) {
michael@0 27141 return this.isInstance(value);
michael@0 27142 };
michael@0 27143 Class.prototype.isInstance = function (value) {
michael@0 27144 if (value === null || typeof value !== 'object') {
michael@0 27145 return false;
michael@0 27146 }
michael@0 27147 return this.dynamicPrototype.isPrototypeOf(value);
michael@0 27148 };
michael@0 27149 Class.prototype.trace = function (writer) {
michael@0 27150 var description = this.debugName + (this.baseClass ? ' extends ' + this.baseClass.debugName : '');
michael@0 27151 writer.enter('class ' + description + ' {');
michael@0 27152 writer.writeLn('scope: ' + this.scope);
michael@0 27153 writer.writeLn('baseClass: ' + this.baseClass);
michael@0 27154 writer.writeLn('classInfo: ' + this.classInfo);
michael@0 27155 writer.writeLn('dynamicPrototype: ' + this.dynamicPrototype);
michael@0 27156 writer.writeLn('traitsPrototype: ' + this.traitsPrototype);
michael@0 27157 writer.writeLn('dynamicPrototype === traitsPrototype: ' + (this.dynamicPrototype === this.traitsPrototype));
michael@0 27158 writer.writeLn('instanceConstructor: ' + this.instanceConstructor);
michael@0 27159 writer.writeLn('instanceConstructorNoInitialize: ' + this.instanceConstructorNoInitialize);
michael@0 27160 writer.writeLn('instanceConstructor === instanceConstructorNoInitialize: ' + (this.instanceConstructor === this.instanceConstructorNoInitialize));
michael@0 27161 var traitsPrototype = this.traitsPrototype;
michael@0 27162 writer.enter('traitsPrototype: ');
michael@0 27163 if (traitsPrototype) {
michael@0 27164 writer.enter('VM_SLOTS: ');
michael@0 27165 writer.writeArray(traitsPrototype.asSlots.byID.map(function (slot) {
michael@0 27166 return slot.trait;
michael@0 27167 }));
michael@0 27168 writer.outdent();
michael@0 27169 writer.enter('VM_BINDINGS: ');
michael@0 27170 writer.writeArray(traitsPrototype.asBindings.map(function (binding) {
michael@0 27171 var pd = Object.getOwnPropertyDescriptor(traitsPrototype, binding);
michael@0 27172 var str = binding;
michael@0 27173 if (pd.get || pd.set) {
michael@0 27174 if (pd.get) {
michael@0 27175 str += ' getter: ' + debugName(pd.get);
michael@0 27176 }
michael@0 27177 if (pd.set) {
michael@0 27178 str += ' setter: ' + debugName(pd.set);
michael@0 27179 }
michael@0 27180 } else {
michael@0 27181 str += ' value: ' + debugName(pd.value);
michael@0 27182 }
michael@0 27183 return str;
michael@0 27184 }));
michael@0 27185 writer.outdent();
michael@0 27186 writer.enter('VM_OPEN_METHODS: ');
michael@0 27187 writer.writeArray(toKeyValueArray(traitsPrototype.asOpenMethods).map(function (pair) {
michael@0 27188 return pair[0] + ': ' + debugName(pair[1]);
michael@0 27189 }));
michael@0 27190 writer.outdent();
michael@0 27191 }
michael@0 27192 writer.enter('classBindings: ');
michael@0 27193 this.classBindings.trace(writer);
michael@0 27194 writer.outdent();
michael@0 27195 writer.enter('instanceBindings: ');
michael@0 27196 this.instanceBindings.trace(writer);
michael@0 27197 writer.outdent();
michael@0 27198 writer.outdent();
michael@0 27199 writer.writeLn('call: ' + this.call);
michael@0 27200 writer.writeLn('apply: ' + this.apply);
michael@0 27201 writer.leave('}');
michael@0 27202 };
michael@0 27203 Class.prototype.toString = function () {
michael@0 27204 return '[class ' + this.classInfo.instanceInfo.name.name + ']';
michael@0 27205 };
michael@0 27206 Class.OWN_INITIALIZE = 1;
michael@0 27207 Class.SUPER_INITIALIZE = 2;
michael@0 27208 return Class;
michael@0 27209 }();
michael@0 27210 Runtime.Class = Class;
michael@0 27211 var callable = Shumway.AVM2.Runtime.ApplicationDomain.coerceCallable(Class);
michael@0 27212 defineNonEnumerableProperty(Class, 'call', callable.call);
michael@0 27213 defineNonEnumerableProperty(Class, 'apply', callable.apply);
michael@0 27214 Class.instanceConstructor = Class;
michael@0 27215 Class.toString = Class.prototype.toString;
michael@0 27216 Class.native = {
michael@0 27217 instance: {
michael@0 27218 prototype: {
michael@0 27219 get: function () {
michael@0 27220 return this.dynamicPrototype;
michael@0 27221 }
michael@0 27222 }
michael@0 27223 }
michael@0 27224 };
michael@0 27225 }(AVM2.Runtime || (AVM2.Runtime = {})));
michael@0 27226 var Runtime = AVM2.Runtime;
michael@0 27227 }(Shumway.AVM2 || (Shumway.AVM2 = {})));
michael@0 27228 var AVM2 = Shumway.AVM2;
michael@0 27229 }(Shumway || (Shumway = {})));
michael@0 27230 var Interface = Shumway.AVM2.Runtime.Interface;
michael@0 27231 var Class = Shumway.AVM2.Runtime.Class;
michael@0 27232 var Binding = Shumway.AVM2.Runtime.Binding;
michael@0 27233 var Bindings = Shumway.AVM2.Runtime.Bindings;
michael@0 27234 var ActivationBindings = Shumway.AVM2.Runtime.ActivationBindings;
michael@0 27235 var CatchBindings = Shumway.AVM2.Runtime.CatchBindings;
michael@0 27236 var ScriptBindings = Shumway.AVM2.Runtime.ScriptBindings;
michael@0 27237 var ClassBindings = Shumway.AVM2.Runtime.ClassBindings;
michael@0 27238 var InstanceBindings = Shumway.AVM2.Runtime.InstanceBindings;
michael@0 27239 var Interface = Shumway.AVM2.Runtime.Interface;
michael@0 27240 var Class = Shumway.AVM2.Runtime.Class;
michael@0 27241 var XRegExp = function (undefined) {
michael@0 27242 var REGEX_DATA = 'xregexp', self, features = {
michael@0 27243 astral: false,
michael@0 27244 natives: false
michael@0 27245 }, nativ = {
michael@0 27246 exec: RegExp.prototype.exec,
michael@0 27247 test: RegExp.prototype.test,
michael@0 27248 match: String.prototype.match,
michael@0 27249 replace: String.prototype.replace,
michael@0 27250 split: String.prototype.split
michael@0 27251 }, fixed = {}, cache = {}, patternCache = {}, tokens = [], defaultScope = 'default', classScope = 'class', nativeTokens = {
michael@0 27252 'default': /\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9]\d*|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S])|\(\?[:=!]|[?*+]\?|{\d+(?:,\d*)?}\??|[\s\S]/,
michael@0 27253 'class': /\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S])|[\s\S]/
michael@0 27254 }, replacementToken = /\$(?:{([\w$]+)}|([\d$&`']))/g, correctExecNpcg = nativ.exec.call(/()??/, '')[1] === undefined, hasNativeY = RegExp.prototype.sticky !== undefined, registeredFlags = {
michael@0 27255 g: true,
michael@0 27256 i: true,
michael@0 27257 m: true,
michael@0 27258 y: hasNativeY
michael@0 27259 }, toString = {}.toString, add;
michael@0 27260 function augment(regex, captureNames, addProto) {
michael@0 27261 var p;
michael@0 27262 if (addProto) {
michael@0 27263 if (regex.__proto__) {
michael@0 27264 regex.__proto__ = self.prototype;
michael@0 27265 } else {
michael@0 27266 for (p in self.prototype) {
michael@0 27267 regex[p] = self.prototype[p];
michael@0 27268 }
michael@0 27269 }
michael@0 27270 }
michael@0 27271 regex[REGEX_DATA] = {
michael@0 27272 captureNames: captureNames
michael@0 27273 };
michael@0 27274 return regex;
michael@0 27275 }
michael@0 27276 function clipDuplicates(str) {
michael@0 27277 return nativ.replace.call(str, /([\s\S])(?=[\s\S]*\1)/g, '');
michael@0 27278 }
michael@0 27279 function copy(regex, options) {
michael@0 27280 if (!self.isRegExp(regex)) {
michael@0 27281 throw new TypeError('Type RegExp expected');
michael@0 27282 }
michael@0 27283 var flags = nativ.exec.call(/\/([a-z]*)$/i, String(regex))[1];
michael@0 27284 options = options || {};
michael@0 27285 if (options.add) {
michael@0 27286 flags = clipDuplicates(flags + options.add);
michael@0 27287 }
michael@0 27288 if (options.remove) {
michael@0 27289 flags = nativ.replace.call(flags, new RegExp('[' + options.remove + ']+', 'g'), '');
michael@0 27290 }
michael@0 27291 regex = augment(new RegExp(regex.source, flags), hasNamedCapture(regex) ? regex[REGEX_DATA].captureNames.slice(0) : null, options.addProto);
michael@0 27292 return regex;
michael@0 27293 }
michael@0 27294 function getBaseProps() {
michael@0 27295 return {
michael@0 27296 captureNames: null
michael@0 27297 };
michael@0 27298 }
michael@0 27299 function hasNamedCapture(regex) {
michael@0 27300 return !(!(regex[REGEX_DATA] && regex[REGEX_DATA].captureNames));
michael@0 27301 }
michael@0 27302 function indexOf(array, value) {
michael@0 27303 if (Array.prototype.indexOf) {
michael@0 27304 return array.indexOf(value);
michael@0 27305 }
michael@0 27306 var len = array.length, i;
michael@0 27307 for (i = 0; i < len; ++i) {
michael@0 27308 if (array[i] === value) {
michael@0 27309 return i;
michael@0 27310 }
michael@0 27311 }
michael@0 27312 return -1;
michael@0 27313 }
michael@0 27314 function isType(value, type) {
michael@0 27315 return toString.call(value) === '[object ' + type + ']';
michael@0 27316 }
michael@0 27317 function isQuantifierNext(pattern, pos, flags) {
michael@0 27318 return nativ.test.call(flags.indexOf('x') > -1 ? /^(?:\s+|#.*|\(\?#[^)]*\))*(?:[?*+]|{\d+(?:,\d*)?})/ : /^(?:\(\?#[^)]*\))*(?:[?*+]|{\d+(?:,\d*)?})/, pattern.slice(pos));
michael@0 27319 }
michael@0 27320 function prepareFlags(pattern, flags) {
michael@0 27321 var i;
michael@0 27322 if (clipDuplicates(flags) !== flags) {
michael@0 27323 throw new SyntaxError('Invalid duplicate regex flag ' + flags);
michael@0 27324 }
michael@0 27325 pattern = nativ.replace.call(pattern, /^\(\?([\w$]+)\)/, function ($0, $1) {
michael@0 27326 if (nativ.test.call(/[gy]/, $1)) {
michael@0 27327 throw new SyntaxError('Cannot use flag g or y in mode modifier ' + $0);
michael@0 27328 }
michael@0 27329 flags = clipDuplicates(flags + $1);
michael@0 27330 return '';
michael@0 27331 });
michael@0 27332 for (i = 0; i < flags.length; ++i) {
michael@0 27333 if (!registeredFlags[flags.charAt(i)]) {
michael@0 27334 throw new SyntaxError('Unknown regex flag ' + flags.charAt(i));
michael@0 27335 }
michael@0 27336 }
michael@0 27337 return {
michael@0 27338 pattern: pattern,
michael@0 27339 flags: flags
michael@0 27340 };
michael@0 27341 }
michael@0 27342 function prepareOptions(value) {
michael@0 27343 value = value || {};
michael@0 27344 if (isType(value, 'String')) {
michael@0 27345 value = self.forEach(value, /[^\s,]+/, function (match) {
michael@0 27346 this[match] = true;
michael@0 27347 }, {});
michael@0 27348 }
michael@0 27349 return value;
michael@0 27350 }
michael@0 27351 function registerFlag(flag) {
michael@0 27352 if (!/^[\w$]$/.test(flag)) {
michael@0 27353 throw new Error('Flag must be a single character A-Za-z0-9_$');
michael@0 27354 }
michael@0 27355 registeredFlags[flag] = true;
michael@0 27356 }
michael@0 27357 function runTokens(pattern, flags, pos, scope, context) {
michael@0 27358 var i = tokens.length, result = null, match, t;
michael@0 27359 while (i--) {
michael@0 27360 t = tokens[i];
michael@0 27361 if ((t.scope === scope || t.scope === 'all') && (!t.flag || flags.indexOf(t.flag) > -1)) {
michael@0 27362 match = self.exec(pattern, t.regex, pos, 'sticky');
michael@0 27363 if (match) {
michael@0 27364 result = {
michael@0 27365 matchLength: match[0].length,
michael@0 27366 output: t.handler.call(context, match, scope, flags),
michael@0 27367 reparse: t.reparse
michael@0 27368 };
michael@0 27369 break;
michael@0 27370 }
michael@0 27371 }
michael@0 27372 }
michael@0 27373 return result;
michael@0 27374 }
michael@0 27375 function setAstral(on) {
michael@0 27376 self.cache.flush('patterns');
michael@0 27377 features.astral = on;
michael@0 27378 }
michael@0 27379 function setNatives(on) {
michael@0 27380 RegExp.prototype.exec = (on ? fixed : nativ).exec;
michael@0 27381 RegExp.prototype.test = (on ? fixed : nativ).test;
michael@0 27382 String.prototype.match = (on ? fixed : nativ).match;
michael@0 27383 String.prototype.replace = (on ? fixed : nativ).replace;
michael@0 27384 String.prototype.split = (on ? fixed : nativ).split;
michael@0 27385 features.natives = on;
michael@0 27386 }
michael@0 27387 function toObject(value) {
michael@0 27388 if (value == null) {
michael@0 27389 throw new TypeError('Cannot convert null or undefined to object');
michael@0 27390 }
michael@0 27391 return value;
michael@0 27392 }
michael@0 27393 self = function (pattern, flags) {
michael@0 27394 var context = {
michael@0 27395 hasNamedCapture: false,
michael@0 27396 captureNames: []
michael@0 27397 }, scope = defaultScope, output = '', pos = 0, result, token, key;
michael@0 27398 if (self.isRegExp(pattern)) {
michael@0 27399 if (flags !== undefined) {
michael@0 27400 throw new TypeError('Cannot supply flags when copying a RegExp');
michael@0 27401 }
michael@0 27402 return copy(pattern, {
michael@0 27403 addProto: true
michael@0 27404 });
michael@0 27405 }
michael@0 27406 pattern = pattern === undefined ? '' : String(pattern);
michael@0 27407 flags = flags === undefined ? '' : String(flags);
michael@0 27408 key = pattern + '***' + flags;
michael@0 27409 if (!patternCache[key]) {
michael@0 27410 result = prepareFlags(pattern, flags);
michael@0 27411 pattern = result.pattern;
michael@0 27412 flags = result.flags;
michael@0 27413 while (pos < pattern.length) {
michael@0 27414 do {
michael@0 27415 result = runTokens(pattern, flags, pos, scope, context);
michael@0 27416 if (result && result.reparse) {
michael@0 27417 pattern = pattern.slice(0, pos) + result.output + pattern.slice(pos + result.matchLength);
michael@0 27418 }
michael@0 27419 } while (result && result.reparse);
michael@0 27420 if (result) {
michael@0 27421 output += result.output;
michael@0 27422 pos += result.matchLength || 1;
michael@0 27423 } else {
michael@0 27424 token = self.exec(pattern, nativeTokens[scope], pos, 'sticky')[0];
michael@0 27425 output += token;
michael@0 27426 pos += token.length;
michael@0 27427 if (token === '[' && scope === defaultScope) {
michael@0 27428 scope = classScope;
michael@0 27429 } else if (token === ']' && scope === classScope) {
michael@0 27430 scope = defaultScope;
michael@0 27431 }
michael@0 27432 }
michael@0 27433 }
michael@0 27434 patternCache[key] = {
michael@0 27435 pattern: nativ.replace.call(output, /\(\?:\)(?=\(\?:\))|^\(\?:\)|\(\?:\)$/g, ''),
michael@0 27436 flags: nativ.replace.call(flags, /[^gimy]+/g, ''),
michael@0 27437 captures: context.hasNamedCapture ? context.captureNames : null
michael@0 27438 };
michael@0 27439 }
michael@0 27440 key = patternCache[key];
michael@0 27441 return augment(new RegExp(key.pattern, key.flags), key.captures, true);
michael@0 27442 };
michael@0 27443 self.prototype = new RegExp();
michael@0 27444 self.version = '3.0.0-pre';
michael@0 27445 self.addToken = function (regex, handler, options) {
michael@0 27446 options = options || {};
michael@0 27447 var optionalFlags = options.optionalFlags, i;
michael@0 27448 if (options.flag) {
michael@0 27449 registerFlag(options.flag);
michael@0 27450 }
michael@0 27451 if (optionalFlags) {
michael@0 27452 optionalFlags = nativ.split.call(optionalFlags, '');
michael@0 27453 for (i = 0; i < optionalFlags.length; ++i) {
michael@0 27454 registerFlag(optionalFlags[i]);
michael@0 27455 }
michael@0 27456 }
michael@0 27457 tokens.push({
michael@0 27458 regex: copy(regex, {
michael@0 27459 add: 'g' + (hasNativeY ? 'y' : '')
michael@0 27460 }),
michael@0 27461 handler: handler,
michael@0 27462 scope: options.scope || defaultScope,
michael@0 27463 flag: options.flag,
michael@0 27464 reparse: options.reparse
michael@0 27465 });
michael@0 27466 self.cache.flush('patterns');
michael@0 27467 };
michael@0 27468 self.cache = function (pattern, flags) {
michael@0 27469 var key = pattern + '***' + (flags || '');
michael@0 27470 return cache[key] || (cache[key] = self(pattern, flags));
michael@0 27471 };
michael@0 27472 self.cache.flush = function (cacheName) {
michael@0 27473 if (cacheName === 'patterns') {
michael@0 27474 patternCache = {};
michael@0 27475 } else {
michael@0 27476 cache = {};
michael@0 27477 }
michael@0 27478 };
michael@0 27479 self.escape = function (str) {
michael@0 27480 return nativ.replace.call(toObject(str), /[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
michael@0 27481 };
michael@0 27482 self.exec = function (str, regex, pos, sticky) {
michael@0 27483 var cacheFlags = 'g', match, r2;
michael@0 27484 if (hasNativeY && (sticky || regex.sticky && sticky !== false)) {
michael@0 27485 cacheFlags += 'y';
michael@0 27486 }
michael@0 27487 regex[REGEX_DATA] = regex[REGEX_DATA] || getBaseProps();
michael@0 27488 r2 = regex[REGEX_DATA][cacheFlags] || (regex[REGEX_DATA][cacheFlags] = copy(regex, {
michael@0 27489 add: cacheFlags,
michael@0 27490 remove: sticky === false ? 'y' : ''
michael@0 27491 }));
michael@0 27492 r2.lastIndex = pos = pos || 0;
michael@0 27493 match = fixed.exec.call(r2, str);
michael@0 27494 if (sticky && match && match.index !== pos) {
michael@0 27495 match = null;
michael@0 27496 }
michael@0 27497 if (regex.global) {
michael@0 27498 regex.lastIndex = match ? r2.lastIndex : 0;
michael@0 27499 }
michael@0 27500 return match;
michael@0 27501 };
michael@0 27502 self.forEach = function (str, regex, callback, context) {
michael@0 27503 var pos = 0, i = -1, match;
michael@0 27504 while (match = self.exec(str, regex, pos)) {
michael@0 27505 callback.call(context, match, ++i, str, regex);
michael@0 27506 pos = match.index + (match[0].length || 1);
michael@0 27507 }
michael@0 27508 return context;
michael@0 27509 };
michael@0 27510 self.globalize = function (regex) {
michael@0 27511 return copy(regex, {
michael@0 27512 add: 'g',
michael@0 27513 addProto: true
michael@0 27514 });
michael@0 27515 };
michael@0 27516 self.install = function (options) {
michael@0 27517 options = prepareOptions(options);
michael@0 27518 if (!features.astral && options.astral) {
michael@0 27519 setAstral(true);
michael@0 27520 }
michael@0 27521 if (!features.natives && options.natives) {
michael@0 27522 setNatives(true);
michael@0 27523 }
michael@0 27524 };
michael@0 27525 self.isInstalled = function (feature) {
michael@0 27526 return !(!features[feature]);
michael@0 27527 };
michael@0 27528 self.isRegExp = function (value) {
michael@0 27529 return toString.call(value) === '[object RegExp]';
michael@0 27530 };
michael@0 27531 self.match = function (str, regex, scope) {
michael@0 27532 var global = regex.global && scope !== 'one' || scope === 'all', cacheFlags = (global ? 'g' : '') + (regex.sticky ? 'y' : ''), result, r2;
michael@0 27533 regex[REGEX_DATA] = regex[REGEX_DATA] || getBaseProps();
michael@0 27534 r2 = regex[REGEX_DATA][cacheFlags || 'noGY'] || (regex[REGEX_DATA][cacheFlags || 'noGY'] = copy(regex, {
michael@0 27535 add: cacheFlags,
michael@0 27536 remove: scope === 'one' ? 'g' : ''
michael@0 27537 }));
michael@0 27538 result = nativ.match.call(toObject(str), r2);
michael@0 27539 if (regex.global) {
michael@0 27540 regex.lastIndex = scope === 'one' && result ? result.index + result[0].length : 0;
michael@0 27541 }
michael@0 27542 return global ? result || [] : result && result[0];
michael@0 27543 };
michael@0 27544 self.matchChain = function (str, chain) {
michael@0 27545 return function recurseChain(values, level) {
michael@0 27546 var item = chain[level].regex ? chain[level] : {
michael@0 27547 regex: chain[level]
michael@0 27548 }, matches = [], addMatch = function (match) {
michael@0 27549 if (item.backref) {
michael@0 27550 if (!(match.hasOwnProperty(item.backref) || +item.backref < match.length)) {
michael@0 27551 throw new ReferenceError('Backreference to undefined group: ' + item.backref);
michael@0 27552 }
michael@0 27553 matches.push(match[item.backref] || '');
michael@0 27554 } else {
michael@0 27555 matches.push(match[0]);
michael@0 27556 }
michael@0 27557 }, i;
michael@0 27558 for (i = 0; i < values.length; ++i) {
michael@0 27559 self.forEach(values[i], item.regex, addMatch);
michael@0 27560 }
michael@0 27561 return level === chain.length - 1 || !matches.length ? matches : recurseChain(matches, level + 1);
michael@0 27562 }([
michael@0 27563 str
michael@0 27564 ], 0);
michael@0 27565 };
michael@0 27566 self.replace = function (str, search, replacement, scope) {
michael@0 27567 var isRegex = self.isRegExp(search), global = search.global && scope !== 'one' || scope === 'all', cacheFlags = (global ? 'g' : '') + (search.sticky ? 'y' : ''), s2 = search, result;
michael@0 27568 if (isRegex) {
michael@0 27569 search[REGEX_DATA] = search[REGEX_DATA] || getBaseProps();
michael@0 27570 s2 = search[REGEX_DATA][cacheFlags || 'noGY'] || (search[REGEX_DATA][cacheFlags || 'noGY'] = copy(search, {
michael@0 27571 add: cacheFlags,
michael@0 27572 remove: scope === 'one' ? 'g' : ''
michael@0 27573 }));
michael@0 27574 } else if (global) {
michael@0 27575 s2 = new RegExp(self.escape(String(search)), 'g');
michael@0 27576 }
michael@0 27577 result = fixed.replace.call(toObject(str), s2, replacement);
michael@0 27578 if (isRegex && search.global) {
michael@0 27579 search.lastIndex = 0;
michael@0 27580 }
michael@0 27581 return result;
michael@0 27582 };
michael@0 27583 self.replaceEach = function (str, replacements) {
michael@0 27584 var i, r;
michael@0 27585 for (i = 0; i < replacements.length; ++i) {
michael@0 27586 r = replacements[i];
michael@0 27587 str = self.replace(str, r[0], r[1], r[2]);
michael@0 27588 }
michael@0 27589 return str;
michael@0 27590 };
michael@0 27591 self.split = function (str, separator, limit) {
michael@0 27592 return fixed.split.call(toObject(str), separator, limit);
michael@0 27593 };
michael@0 27594 self.test = function (str, regex, pos, sticky) {
michael@0 27595 return !(!self.exec(str, regex, pos, sticky));
michael@0 27596 };
michael@0 27597 self.uninstall = function (options) {
michael@0 27598 options = prepareOptions(options);
michael@0 27599 if (features.astral && options.astral) {
michael@0 27600 setAstral(false);
michael@0 27601 }
michael@0 27602 if (features.natives && options.natives) {
michael@0 27603 setNatives(false);
michael@0 27604 }
michael@0 27605 };
michael@0 27606 self.union = function (patterns, flags) {
michael@0 27607 var parts = /(\()(?!\?)|\\([1-9]\d*)|\\[\s\S]|\[(?:[^\\\]]|\\[\s\S])*]/g, output = [], numCaptures = 0, numPriorCaptures, captureNames, pattern, rewrite = function (match, paren, backref) {
michael@0 27608 var name = captureNames[numCaptures - numPriorCaptures];
michael@0 27609 if (paren) {
michael@0 27610 ++numCaptures;
michael@0 27611 if (name) {
michael@0 27612 return '(?<' + name + '>';
michael@0 27613 }
michael@0 27614 } else if (backref) {
michael@0 27615 return '\\' + (+backref + numPriorCaptures);
michael@0 27616 }
michael@0 27617 return match;
michael@0 27618 }, i;
michael@0 27619 if (!(isType(patterns, 'Array') && patterns.length)) {
michael@0 27620 throw new TypeError('Must provide a nonempty array of patterns to merge');
michael@0 27621 }
michael@0 27622 for (i = 0; i < patterns.length; ++i) {
michael@0 27623 pattern = patterns[i];
michael@0 27624 if (self.isRegExp(pattern)) {
michael@0 27625 numPriorCaptures = numCaptures;
michael@0 27626 captureNames = pattern[REGEX_DATA] && pattern[REGEX_DATA].captureNames || [];
michael@0 27627 output.push(nativ.replace.call(self(pattern.source).source, parts, rewrite));
michael@0 27628 } else {
michael@0 27629 output.push(self.escape(pattern));
michael@0 27630 }
michael@0 27631 }
michael@0 27632 return self(output.join('|'), flags);
michael@0 27633 };
michael@0 27634 fixed.exec = function (str) {
michael@0 27635 var origLastIndex = this.lastIndex, match = nativ.exec.apply(this, arguments), name, r2, i;
michael@0 27636 if (match) {
michael@0 27637 if (!correctExecNpcg && match.length > 1 && indexOf(match, '') > -1) {
michael@0 27638 r2 = copy(this, {
michael@0 27639 remove: 'g'
michael@0 27640 });
michael@0 27641 nativ.replace.call(String(str).slice(match.index), r2, function () {
michael@0 27642 var len = arguments.length, i;
michael@0 27643 for (i = 1; i < len - 2; ++i) {
michael@0 27644 if (arguments[i] === undefined) {
michael@0 27645 match[i] = undefined;
michael@0 27646 }
michael@0 27647 }
michael@0 27648 });
michael@0 27649 }
michael@0 27650 if (this[REGEX_DATA] && this[REGEX_DATA].captureNames) {
michael@0 27651 for (i = 1; i < match.length; ++i) {
michael@0 27652 name = this[REGEX_DATA].captureNames[i - 1];
michael@0 27653 if (name) {
michael@0 27654 match[name] = match[i];
michael@0 27655 }
michael@0 27656 }
michael@0 27657 }
michael@0 27658 if (this.global && !match[0].length && this.lastIndex > match.index) {
michael@0 27659 this.lastIndex = match.index;
michael@0 27660 }
michael@0 27661 }
michael@0 27662 if (!this.global) {
michael@0 27663 this.lastIndex = origLastIndex;
michael@0 27664 }
michael@0 27665 return match;
michael@0 27666 };
michael@0 27667 fixed.test = function (str) {
michael@0 27668 return !(!fixed.exec.call(this, str));
michael@0 27669 };
michael@0 27670 fixed.match = function (regex) {
michael@0 27671 var result;
michael@0 27672 if (!self.isRegExp(regex)) {
michael@0 27673 regex = new RegExp(regex);
michael@0 27674 } else if (regex.global) {
michael@0 27675 result = nativ.match.apply(this, arguments);
michael@0 27676 regex.lastIndex = 0;
michael@0 27677 return result;
michael@0 27678 }
michael@0 27679 return fixed.exec.call(regex, toObject(this));
michael@0 27680 };
michael@0 27681 fixed.replace = function (search, replacement) {
michael@0 27682 var isRegex = self.isRegExp(search), origLastIndex, captureNames, result;
michael@0 27683 if (isRegex) {
michael@0 27684 if (search[REGEX_DATA]) {
michael@0 27685 captureNames = search[REGEX_DATA].captureNames;
michael@0 27686 }
michael@0 27687 origLastIndex = search.lastIndex;
michael@0 27688 } else {
michael@0 27689 search += '';
michael@0 27690 }
michael@0 27691 if (isType(replacement, 'Function')) {
michael@0 27692 result = nativ.replace.call(String(this), search, function () {
michael@0 27693 var args = arguments, i;
michael@0 27694 if (captureNames) {
michael@0 27695 args[0] = new String(args[0]);
michael@0 27696 for (i = 0; i < captureNames.length; ++i) {
michael@0 27697 if (captureNames[i]) {
michael@0 27698 args[0][captureNames[i]] = args[i + 1];
michael@0 27699 }
michael@0 27700 }
michael@0 27701 }
michael@0 27702 if (isRegex && search.global) {
michael@0 27703 search.lastIndex = args[args.length - 2] + args[0].length;
michael@0 27704 }
michael@0 27705 return replacement.apply(undefined, args);
michael@0 27706 });
michael@0 27707 } else {
michael@0 27708 result = nativ.replace.call(this == null ? this : String(this), search, function () {
michael@0 27709 var args = arguments;
michael@0 27710 return nativ.replace.call(String(replacement), replacementToken, function ($0, $1, $2) {
michael@0 27711 var n;
michael@0 27712 if ($1) {
michael@0 27713 n = +$1;
michael@0 27714 if (n <= args.length - 3) {
michael@0 27715 return args[n] || '';
michael@0 27716 }
michael@0 27717 n = captureNames ? indexOf(captureNames, $1) : -1;
michael@0 27718 if (n < 0) {
michael@0 27719 throw new SyntaxError('Backreference to undefined group ' + $0);
michael@0 27720 }
michael@0 27721 return args[n + 1] || '';
michael@0 27722 }
michael@0 27723 if ($2 === '$') {
michael@0 27724 return '$';
michael@0 27725 }
michael@0 27726 if ($2 === '&' || +$2 === 0) {
michael@0 27727 return args[0];
michael@0 27728 }
michael@0 27729 if ($2 === '`') {
michael@0 27730 return args[args.length - 1].slice(0, args[args.length - 2]);
michael@0 27731 }
michael@0 27732 if ($2 === '\'') {
michael@0 27733 return args[args.length - 1].slice(args[args.length - 2] + args[0].length);
michael@0 27734 }
michael@0 27735 $2 = +$2;
michael@0 27736 if (!isNaN($2)) {
michael@0 27737 if ($2 > args.length - 3) {
michael@0 27738 throw new SyntaxError('Backreference to undefined group ' + $0);
michael@0 27739 }
michael@0 27740 return args[$2] || '';
michael@0 27741 }
michael@0 27742 throw new SyntaxError('Invalid token ' + $0);
michael@0 27743 });
michael@0 27744 });
michael@0 27745 }
michael@0 27746 if (isRegex) {
michael@0 27747 if (search.global) {
michael@0 27748 search.lastIndex = 0;
michael@0 27749 } else {
michael@0 27750 search.lastIndex = origLastIndex;
michael@0 27751 }
michael@0 27752 }
michael@0 27753 return result;
michael@0 27754 };
michael@0 27755 fixed.split = function (separator, limit) {
michael@0 27756 if (!self.isRegExp(separator)) {
michael@0 27757 return nativ.split.apply(this, arguments);
michael@0 27758 }
michael@0 27759 var str = String(this), output = [], origLastIndex = separator.lastIndex, lastLastIndex = 0, lastLength;
michael@0 27760 limit = (limit === undefined ? -1 : limit) >>> 0;
michael@0 27761 self.forEach(str, separator, function (match) {
michael@0 27762 if (match.index + match[0].length > lastLastIndex) {
michael@0 27763 output.push(str.slice(lastLastIndex, match.index));
michael@0 27764 if (match.length > 1 && match.index < str.length) {
michael@0 27765 Array.prototype.push.apply(output, match.slice(1));
michael@0 27766 }
michael@0 27767 lastLength = match[0].length;
michael@0 27768 lastLastIndex = match.index + lastLength;
michael@0 27769 }
michael@0 27770 });
michael@0 27771 if (lastLastIndex === str.length) {
michael@0 27772 if (!nativ.test.call(separator, '') || lastLength) {
michael@0 27773 output.push('');
michael@0 27774 }
michael@0 27775 } else {
michael@0 27776 output.push(str.slice(lastLastIndex));
michael@0 27777 }
michael@0 27778 separator.lastIndex = origLastIndex;
michael@0 27779 return output.length > limit ? output.slice(0, limit) : output;
michael@0 27780 };
michael@0 27781 add = self.addToken;
michael@0 27782 add(/\\([ABCE-RTUVXYZaeg-mopqyz]|c(?![A-Za-z])|u(?![\dA-Fa-f]{4})|x(?![\dA-Fa-f]{2}))/, function (match, scope) {
michael@0 27783 if (match[1] === 'B' && scope === defaultScope) {
michael@0 27784 return match[0];
michael@0 27785 }
michael@0 27786 throw new SyntaxError('Invalid escape ' + match[0]);
michael@0 27787 }, {
michael@0 27788 scope: 'all'
michael@0 27789 });
michael@0 27790 add(/\[(\^?)]/, function (match) {
michael@0 27791 return match[1] ? '[\\s\\S]' : '\\b\\B';
michael@0 27792 });
michael@0 27793 add(/\(\?#[^)]*\)/, function (match, scope, flags) {
michael@0 27794 return isQuantifierNext(match.input, match.index + match[0].length, flags) ? '' : '(?:)';
michael@0 27795 });
michael@0 27796 add(/\s+|#.*/, function (match, scope, flags) {
michael@0 27797 return isQuantifierNext(match.input, match.index + match[0].length, flags) ? '' : '(?:)';
michael@0 27798 }, {
michael@0 27799 flag: 'x'
michael@0 27800 });
michael@0 27801 add(/\./, function () {
michael@0 27802 return '[\\s\\S]';
michael@0 27803 }, {
michael@0 27804 flag: 's'
michael@0 27805 });
michael@0 27806 add(/\\k<([\w$]+)>/, function (match) {
michael@0 27807 var index = isNaN(match[1]) ? indexOf(this.captureNames, match[1]) + 1 : +match[1], endIndex = match.index + match[0].length;
michael@0 27808 if (!index || index > this.captureNames.length) {
michael@0 27809 throw new SyntaxError('Backreference to undefined group ' + match[0]);
michael@0 27810 }
michael@0 27811 return '\\' + index + (endIndex === match.input.length || isNaN(match.input.charAt(endIndex)) ? '' : '(?:)');
michael@0 27812 });
michael@0 27813 add(/\\(\d+)/, function (match, scope) {
michael@0 27814 if (!(scope === defaultScope && /^[1-9]/.test(match[1]) && +match[1] <= this.captureNames.length) && match[1] !== '0') {
michael@0 27815 throw new SyntaxError('Cannot use octal escape or backreference to undefined group ' + match[0]);
michael@0 27816 }
michael@0 27817 return match[0];
michael@0 27818 }, {
michael@0 27819 scope: 'all'
michael@0 27820 });
michael@0 27821 add(/\(\?P?<([\w$]+)>/, function (match) {
michael@0 27822 if (!isNaN(match[1])) {
michael@0 27823 throw new SyntaxError('Cannot use integer as capture name ' + match[0]);
michael@0 27824 }
michael@0 27825 if (match[1] === 'length' || match[1] === '__proto__') {
michael@0 27826 throw new SyntaxError('Cannot use reserved word as capture name ' + match[0]);
michael@0 27827 }
michael@0 27828 if (indexOf(this.captureNames, match[1]) > -1) {
michael@0 27829 throw new SyntaxError('Cannot use same name for multiple groups ' + match[0]);
michael@0 27830 }
michael@0 27831 this.captureNames.push(match[1]);
michael@0 27832 this.hasNamedCapture = true;
michael@0 27833 return '(';
michael@0 27834 });
michael@0 27835 add(/\((?!\?)/, function (match, scope, flags) {
michael@0 27836 if (flags.indexOf('n') > -1) {
michael@0 27837 return '(?:';
michael@0 27838 }
michael@0 27839 this.captureNames.push(null);
michael@0 27840 return '(';
michael@0 27841 }, {
michael@0 27842 optionalFlags: 'n'
michael@0 27843 });
michael@0 27844 return self;
michael@0 27845 }();
michael@0 27846 var Namespace = Shumway.AVM2.ABC.Namespace;
michael@0 27847 var Shumway;
michael@0 27848 (function (Shumway) {
michael@0 27849 (function (AVM2) {
michael@0 27850 (function (Runtime) {
michael@0 27851 var Option = Shumway.Options.Option;
michael@0 27852 var OptionSet = Shumway.Options.OptionSet;
michael@0 27853 var runtimeOptions = systemOptions.register(new OptionSet('Runtime Options'));
michael@0 27854 var traceScope = runtimeOptions.register(new Option('ts', 'traceScope', 'boolean', false, 'trace scope execution'));
michael@0 27855 Runtime.traceExecution = runtimeOptions.register(new Option('tx', 'traceExecution', 'number', 0, 'trace script execution'));
michael@0 27856 Runtime.traceCallExecution = runtimeOptions.register(new Option('txc', 'traceCallExecution', 'number', 0, 'trace call execution'));
michael@0 27857 var functionBreak = runtimeOptions.register(new Option('fb', 'functionBreak', 'number', -1, 'Inserts a debugBreak at function index #.'));
michael@0 27858 var compileOnly = runtimeOptions.register(new Option('co', 'compileOnly', 'number', -1, 'Compiles only function number.'));
michael@0 27859 var compileUntil = runtimeOptions.register(new Option('cu', 'compileUntil', 'number', -1, 'Compiles only until a function number.'));
michael@0 27860 Runtime.debuggerMode = runtimeOptions.register(new Option('dm', 'debuggerMode', 'boolean', false, 'matches avm2 debugger build semantics'));
michael@0 27861 Runtime.enableVerifier = runtimeOptions.register(new Option('verify', 'verify', 'boolean', false, 'Enable verifier.'));
michael@0 27862 Runtime.globalMultinameAnalysis = runtimeOptions.register(new Option('ga', 'globalMultinameAnalysis', 'boolean', false, 'Global multiname analysis.'));
michael@0 27863 var traceInlineCaching = runtimeOptions.register(new Option('tic', 'traceInlineCaching', 'boolean', false, 'Trace inline caching execution.'));
michael@0 27864 Runtime.codeCaching = runtimeOptions.register(new Option('cc', 'codeCaching', 'boolean', false, 'Enable code caching.'));
michael@0 27865 var compilerEnableExceptions = runtimeOptions.register(new Option('cex', 'exceptions', 'boolean', false, 'Compile functions with catch blocks.'));
michael@0 27866 var compilerMaximumMethodSize = runtimeOptions.register(new Option('cmms', 'maximumMethodSize', 'number', 4 * 1024, 'Compiler maximum method size.'));
michael@0 27867 Runtime.traceClasses = runtimeOptions.register(new Option('tc', 'traceClasses', 'boolean', false, 'trace class creation'));
michael@0 27868 Runtime.traceDomain = runtimeOptions.register(new Option('td', 'traceDomain', 'boolean', false, 'trace domain property access'));
michael@0 27869 Runtime.sealConstTraits = false;
michael@0 27870 Runtime.useAsAdd = true;
michael@0 27871 var useSurrogates = true;
michael@0 27872 var callCounter = new Shumway.Metrics.Counter(true);
michael@0 27873 var Multiname = Shumway.AVM2.ABC.Multiname;
michael@0 27874 var Namespace = Shumway.AVM2.ABC.Namespace;
michael@0 27875 var MethodInfo = Shumway.AVM2.ABC.MethodInfo;
michael@0 27876 var ClassInfo = Shumway.AVM2.ABC.ClassInfo;
michael@0 27877 var InstanceInfo = Shumway.AVM2.ABC.InstanceInfo;
michael@0 27878 var ScriptInfo = Shumway.AVM2.ABC.ScriptInfo;
michael@0 27879 var SORT = Shumway.AVM2.ABC.SORT;
michael@0 27880 var Trait = Shumway.AVM2.ABC.Trait;
michael@0 27881 var IndentingWriter = Shumway.IndentingWriter;
michael@0 27882 var hasOwnProperty = Shumway.ObjectUtilities.hasOwnProperty;
michael@0 27883 var createMap = Shumway.ObjectUtilities.createMap;
michael@0 27884 var cloneObject = Shumway.ObjectUtilities.cloneObject;
michael@0 27885 var copyProperties = Shumway.ObjectUtilities.copyProperties;
michael@0 27886 var createEmptyObject = Shumway.ObjectUtilities.createEmptyObject;
michael@0 27887 var boxValue = Shumway.ObjectUtilities.boxValue;
michael@0 27888 var bindSafely = Shumway.FunctionUtilities.bindSafely;
michael@0 27889 var defineNonEnumerableGetterOrSetter = Shumway.ObjectUtilities.defineNonEnumerableGetterOrSetter;
michael@0 27890 var defineNonEnumerableProperty = Shumway.ObjectUtilities.defineNonEnumerableProperty;
michael@0 27891 var defineReadOnlyProperty = Shumway.ObjectUtilities.defineReadOnlyProperty;
michael@0 27892 var defineNonEnumerableGetter = Shumway.ObjectUtilities.defineNonEnumerableGetter;
michael@0 27893 var makeForwardingGetter = Shumway.FunctionUtilities.makeForwardingGetter;
michael@0 27894 var makeForwardingSetter = Shumway.FunctionUtilities.makeForwardingSetter;
michael@0 27895 var toSafeString = Shumway.StringUtilities.toSafeString;
michael@0 27896 var toSafeArrayString = Shumway.StringUtilities.toSafeArrayString;
michael@0 27897 var TRAIT = Shumway.AVM2.ABC.TRAIT;
michael@0 27898 Runtime.VM_SLOTS = 'asSlots';
michael@0 27899 Runtime.VM_LENGTH = 'asLength';
michael@0 27900 Runtime.VM_BINDINGS = 'asBindings';
michael@0 27901 Runtime.VM_NATIVE_PROTOTYPE_FLAG = 'asIsNative';
michael@0 27902 Runtime.VM_OPEN_METHODS = 'asOpenMethods';
michael@0 27903 Runtime.VM_IS_CLASS = 'asIsClass';
michael@0 27904 Runtime.VM_IS_PROXY = 'asIsProxy';
michael@0 27905 Runtime.VM_CALL_PROXY = 'asCallProxy';
michael@0 27906 Runtime.VM_OPEN_METHOD_PREFIX = 'm';
michael@0 27907 Runtime.VM_MEMOIZER_PREFIX = 'z';
michael@0 27908 Runtime.VM_OPEN_SET_METHOD_PREFIX = 's';
michael@0 27909 Runtime.VM_OPEN_GET_METHOD_PREFIX = 'g';
michael@0 27910 Runtime.VM_NATIVE_BUILTIN_ORIGINALS = 'asOriginals';
michael@0 27911 Runtime.VM_METHOD_OVERRIDES = createEmptyObject();
michael@0 27912 var vmNextInterpreterFunctionId = 1;
michael@0 27913 var vmNextCompiledFunctionId = 1;
michael@0 27914 var totalFunctionCount = 0;
michael@0 27915 var compiledFunctionCount = 0;
michael@0 27916 var compilationCount = 0;
michael@0 27917 function isClass(object) {
michael@0 27918 true;
michael@0 27919 return Object.hasOwnProperty.call(object, Runtime.VM_IS_CLASS);
michael@0 27920 }
michael@0 27921 Runtime.isClass = isClass;
michael@0 27922 function isNativePrototype(object) {
michael@0 27923 return Object.prototype.hasOwnProperty.call(object, Runtime.VM_NATIVE_PROTOTYPE_FLAG);
michael@0 27924 }
michael@0 27925 Runtime.isNativePrototype = isNativePrototype;
michael@0 27926 var traitsWriter = null;
michael@0 27927 var callWriter = null;
michael@0 27928 function patch(patchTargets, value) {
michael@0 27929 true;
michael@0 27930 for (var i = 0; i < patchTargets.length; i++) {
michael@0 27931 var patchTarget = patchTargets[i];
michael@0 27932 if (Runtime.traceExecution.value >= 3) {
michael@0 27933 var str = 'Patching: ';
michael@0 27934 if (patchTarget.name) {
michael@0 27935 str += patchTarget.name;
michael@0 27936 } else if (patchTarget.get) {
michael@0 27937 str += 'get ' + patchTarget.get;
michael@0 27938 } else if (patchTarget.set) {
michael@0 27939 str += 'set ' + patchTarget.set;
michael@0 27940 }
michael@0 27941 traitsWriter && traitsWriter.redLn(str);
michael@0 27942 }
michael@0 27943 if (patchTarget.get) {
michael@0 27944 defineNonEnumerableGetterOrSetter(patchTarget.object, patchTarget.get, value, true);
michael@0 27945 } else if (patchTarget.set) {
michael@0 27946 defineNonEnumerableGetterOrSetter(patchTarget.object, patchTarget.set, value, false);
michael@0 27947 } else {
michael@0 27948 defineNonEnumerableProperty(patchTarget.object, patchTarget.name, value);
michael@0 27949 }
michael@0 27950 }
michael@0 27951 }
michael@0 27952 Runtime.patch = patch;
michael@0 27953 function applyNonMemoizedMethodTrait(qn, trait, object, scope, natives) {
michael@0 27954 true;
michael@0 27955 if (trait.isMethod()) {
michael@0 27956 var trampoline = Shumway.AVM2.Runtime.makeTrampoline(function (self) {
michael@0 27957 var fn = getTraitFunction(trait, scope, natives);
michael@0 27958 patch(self.patchTargets, fn);
michael@0 27959 return fn;
michael@0 27960 }, trait.methodInfo.parameters.length);
michael@0 27961 trampoline.patchTargets = [
michael@0 27962 {
michael@0 27963 object: object,
michael@0 27964 name: qn
michael@0 27965 },
michael@0 27966 {
michael@0 27967 object: object,
michael@0 27968 name: Runtime.VM_OPEN_METHOD_PREFIX + qn
michael@0 27969 }
michael@0 27970 ];
michael@0 27971 var closure = bindSafely(trampoline, object);
michael@0 27972 defineReadOnlyProperty(closure, Runtime.VM_LENGTH, trampoline.asLength);
michael@0 27973 defineReadOnlyProperty(closure, Multiname.getPublicQualifiedName('prototype'), null);
michael@0 27974 defineNonEnumerableProperty(object, qn, closure);
michael@0 27975 defineNonEnumerableProperty(object, Runtime.VM_OPEN_METHOD_PREFIX + qn, closure);
michael@0 27976 } else if (trait.isGetter() || trait.isSetter()) {
michael@0 27977 var trampoline = Shumway.AVM2.Runtime.makeTrampoline(function (self) {
michael@0 27978 var fn = getTraitFunction(trait, scope, natives);
michael@0 27979 patch(self.patchTargets, fn);
michael@0 27980 return fn;
michael@0 27981 }, trait.isSetter() ? 1 : 0);
michael@0 27982 if (trait.isGetter()) {
michael@0 27983 trampoline.patchTargets = [
michael@0 27984 {
michael@0 27985 object: object,
michael@0 27986 get: qn
michael@0 27987 }
michael@0 27988 ];
michael@0 27989 } else {
michael@0 27990 trampoline.patchTargets = [
michael@0 27991 {
michael@0 27992 object: object,
michael@0 27993 set: qn
michael@0 27994 }
michael@0 27995 ];
michael@0 27996 }
michael@0 27997 defineNonEnumerableGetterOrSetter(object, qn, trampoline, trait.isGetter());
michael@0 27998 } else {
michael@0 27999 Shumway.Debug.unexpected(trait);
michael@0 28000 }
michael@0 28001 }
michael@0 28002 Runtime.applyNonMemoizedMethodTrait = applyNonMemoizedMethodTrait;
michael@0 28003 function applyMemoizedMethodTrait(qn, trait, object, scope, natives) {
michael@0 28004 true;
michael@0 28005 if (trait.isMethod()) {
michael@0 28006 var memoizerTarget = {
michael@0 28007 value: null
michael@0 28008 };
michael@0 28009 var trampoline = Shumway.AVM2.Runtime.makeTrampoline(function (self) {
michael@0 28010 var fn = getTraitFunction(trait, scope, natives);
michael@0 28011 patch(self.patchTargets, fn);
michael@0 28012 return fn;
michael@0 28013 }, trait.methodInfo.parameters.length, String(trait.name));
michael@0 28014 memoizerTarget.value = trampoline;
michael@0 28015 var openMethods = object.asOpenMethods;
michael@0 28016 openMethods[qn] = trampoline;
michael@0 28017 defineNonEnumerableProperty(object, Runtime.VM_OPEN_METHOD_PREFIX + qn, trampoline);
michael@0 28018 defineNonEnumerableGetter(object, qn, Shumway.AVM2.Runtime.makeMemoizer(qn, memoizerTarget));
michael@0 28019 trampoline.patchTargets = [
michael@0 28020 {
michael@0 28021 object: memoizerTarget,
michael@0 28022 name: 'value'
michael@0 28023 },
michael@0 28024 {
michael@0 28025 object: openMethods,
michael@0 28026 name: qn
michael@0 28027 },
michael@0 28028 {
michael@0 28029 object: object,
michael@0 28030 name: Runtime.VM_OPEN_METHOD_PREFIX + qn
michael@0 28031 }
michael@0 28032 ];
michael@0 28033 } else if (trait.isGetter() || trait.isSetter()) {
michael@0 28034 var trampoline = Shumway.AVM2.Runtime.makeTrampoline(function (self) {
michael@0 28035 var fn = getTraitFunction(trait, scope, natives);
michael@0 28036 patch(self.patchTargets, fn);
michael@0 28037 return fn;
michael@0 28038 }, 0, String(trait.name));
michael@0 28039 if (trait.isGetter()) {
michael@0 28040 defineNonEnumerableProperty(object, Runtime.VM_OPEN_GET_METHOD_PREFIX + qn, trampoline);
michael@0 28041 trampoline.patchTargets = [
michael@0 28042 {
michael@0 28043 object: object,
michael@0 28044 get: qn
michael@0 28045 },
michael@0 28046 {
michael@0 28047 object: object,
michael@0 28048 name: Runtime.VM_OPEN_GET_METHOD_PREFIX + qn
michael@0 28049 }
michael@0 28050 ];
michael@0 28051 } else {
michael@0 28052 defineNonEnumerableProperty(object, Runtime.VM_OPEN_SET_METHOD_PREFIX + qn, trampoline);
michael@0 28053 trampoline.patchTargets = [
michael@0 28054 {
michael@0 28055 object: object,
michael@0 28056 set: qn
michael@0 28057 },
michael@0 28058 {
michael@0 28059 object: object,
michael@0 28060 name: Runtime.VM_OPEN_SET_METHOD_PREFIX + qn
michael@0 28061 }
michael@0 28062 ];
michael@0 28063 }
michael@0 28064 defineNonEnumerableGetterOrSetter(object, qn, trampoline, trait.isGetter());
michael@0 28065 }
michael@0 28066 }
michael@0 28067 Runtime.applyMemoizedMethodTrait = applyMemoizedMethodTrait;
michael@0 28068 function getNamespaceResolutionMap(namespaces) {
michael@0 28069 var self = this;
michael@0 28070 var map = self.resolutionMap[namespaces.runtimeId];
michael@0 28071 if (map)
michael@0 28072 return map;
michael@0 28073 map = self.resolutionMap[namespaces.runtimeId] = Shumway.ObjectUtilities.createMap();
michael@0 28074 var bindings = self.bindings;
michael@0 28075 for (var key in bindings.map) {
michael@0 28076 var multiname = key;
michael@0 28077 var trait = bindings.map[key].trait;
michael@0 28078 if (trait.isGetter() || trait.isSetter()) {
michael@0 28079 multiname = multiname.substring(Shumway.AVM2.Runtime.Binding.KEY_PREFIX_LENGTH);
michael@0 28080 }
michael@0 28081 multiname = Multiname.fromQualifiedName(multiname);
michael@0 28082 if (multiname.getNamespace().inNamespaceSet(namespaces)) {
michael@0 28083 map[multiname.getName()] = Multiname.getQualifiedName(trait.name);
michael@0 28084 }
michael@0 28085 }
michael@0 28086 return map;
michael@0 28087 }
michael@0 28088 Runtime.getNamespaceResolutionMap = getNamespaceResolutionMap;
michael@0 28089 function resolveMultinameProperty(namespaces, name, flags) {
michael@0 28090 var self = this;
michael@0 28091 if (typeof name === 'object') {
michael@0 28092 name = String(name);
michael@0 28093 }
michael@0 28094 if (Shumway.isNumeric(name)) {
michael@0 28095 return Shumway.toNumber(name);
michael@0 28096 }
michael@0 28097 if (!namespaces) {
michael@0 28098 return Multiname.getPublicQualifiedName(name);
michael@0 28099 }
michael@0 28100 if (namespaces.length > 1) {
michael@0 28101 var resolved = self.getNamespaceResolutionMap(namespaces)[name];
michael@0 28102 if (resolved)
michael@0 28103 return resolved;
michael@0 28104 return Multiname.getPublicQualifiedName(name);
michael@0 28105 } else {
michael@0 28106 return Multiname.qualifyName(namespaces[0], name);
michael@0 28107 }
michael@0 28108 }
michael@0 28109 Runtime.resolveMultinameProperty = resolveMultinameProperty;
michael@0 28110 function asGetPublicProperty(name) {
michael@0 28111 var self = this;
michael@0 28112 return self.asGetProperty(undefined, name, 0);
michael@0 28113 }
michael@0 28114 Runtime.asGetPublicProperty = asGetPublicProperty;
michael@0 28115 function asGetProperty(namespaces, name, flags) {
michael@0 28116 var self = this;
michael@0 28117 var resolved = self.resolveMultinameProperty(namespaces, name, flags);
michael@0 28118 if (self.asGetNumericProperty && Multiname.isNumeric(resolved)) {
michael@0 28119 return self.asGetNumericProperty(resolved);
michael@0 28120 }
michael@0 28121 return self[resolved];
michael@0 28122 }
michael@0 28123 Runtime.asGetProperty = asGetProperty;
michael@0 28124 function asGetPropertyLikelyNumeric(namespaces, name, flags) {
michael@0 28125 var self = this;
michael@0 28126 if (typeof name === 'number') {
michael@0 28127 return self.asGetNumericProperty(name);
michael@0 28128 }
michael@0 28129 return asGetProperty.call(self, namespaces, name, flags);
michael@0 28130 }
michael@0 28131 Runtime.asGetPropertyLikelyNumeric = asGetPropertyLikelyNumeric;
michael@0 28132 function asGetResolvedStringProperty(resolved) {
michael@0 28133 true;
michael@0 28134 return this[resolved];
michael@0 28135 }
michael@0 28136 Runtime.asGetResolvedStringProperty = asGetResolvedStringProperty;
michael@0 28137 function asCallResolvedStringProperty(resolved, isLex, args) {
michael@0 28138 var self = this;
michael@0 28139 var receiver = isLex ? null : this;
michael@0 28140 var openMethods = self.asOpenMethods;
michael@0 28141 var method;
michael@0 28142 if (receiver && openMethods && openMethods[resolved]) {
michael@0 28143 method = openMethods[resolved];
michael@0 28144 } else {
michael@0 28145 method = self[resolved];
michael@0 28146 }
michael@0 28147 return method.apply(receiver, args);
michael@0 28148 }
michael@0 28149 Runtime.asCallResolvedStringProperty = asCallResolvedStringProperty;
michael@0 28150 function asGetResolvedStringPropertyFallback(resolved) {
michael@0 28151 var self = this;
michael@0 28152 var name = Multiname.getNameFromPublicQualifiedName(resolved);
michael@0 28153 return self.asGetProperty([
michael@0 28154 Namespace.PUBLIC
michael@0 28155 ], name, 0);
michael@0 28156 }
michael@0 28157 Runtime.asGetResolvedStringPropertyFallback = asGetResolvedStringPropertyFallback;
michael@0 28158 function asSetPublicProperty(name, value) {
michael@0 28159 var self = this;
michael@0 28160 return self.asSetProperty(undefined, name, 0, value);
michael@0 28161 }
michael@0 28162 Runtime.asSetPublicProperty = asSetPublicProperty;
michael@0 28163 function asSetProperty(namespaces, name, flags, value) {
michael@0 28164 var self = this;
michael@0 28165 if (typeof name === 'object') {
michael@0 28166 name = String(name);
michael@0 28167 }
michael@0 28168 var resolved = self.resolveMultinameProperty(namespaces, name, flags);
michael@0 28169 if (self.asSetNumericProperty && Multiname.isNumeric(resolved)) {
michael@0 28170 return self.asSetNumericProperty(resolved, value);
michael@0 28171 }
michael@0 28172 var slotInfo = self.asSlots.byQN[resolved];
michael@0 28173 if (slotInfo) {
michael@0 28174 if (slotInfo.isConst) {
michael@0 28175 }
michael@0 28176 var type = slotInfo.type;
michael@0 28177 if (type && type.coerce) {
michael@0 28178 value = type.coerce(value);
michael@0 28179 }
michael@0 28180 }
michael@0 28181 self[resolved] = value;
michael@0 28182 }
michael@0 28183 Runtime.asSetProperty = asSetProperty;
michael@0 28184 function asSetPropertyLikelyNumeric(namespaces, name, flags, value) {
michael@0 28185 var self = this;
michael@0 28186 if (typeof name === 'number') {
michael@0 28187 self.asSetNumericProperty(name, value);
michael@0 28188 return;
michael@0 28189 }
michael@0 28190 return asSetProperty.call(self, namespaces, name, flags, value);
michael@0 28191 }
michael@0 28192 Runtime.asSetPropertyLikelyNumeric = asSetPropertyLikelyNumeric;
michael@0 28193 function asDefinePublicProperty(name, descriptor) {
michael@0 28194 var self = this;
michael@0 28195 return self.asDefineProperty(undefined, name, 0, descriptor);
michael@0 28196 }
michael@0 28197 Runtime.asDefinePublicProperty = asDefinePublicProperty;
michael@0 28198 function asDefineProperty(namespaces, name, flags, descriptor) {
michael@0 28199 var self = this;
michael@0 28200 if (typeof name === 'object') {
michael@0 28201 name = String(name);
michael@0 28202 }
michael@0 28203 var resolved = self.resolveMultinameProperty(namespaces, name, flags);
michael@0 28204 Object.defineProperty(self, resolved, descriptor);
michael@0 28205 }
michael@0 28206 Runtime.asDefineProperty = asDefineProperty;
michael@0 28207 function asCallPublicProperty(name, args) {
michael@0 28208 var self = this;
michael@0 28209 return self.asCallProperty(undefined, name, 0, false, args);
michael@0 28210 }
michael@0 28211 Runtime.asCallPublicProperty = asCallPublicProperty;
michael@0 28212 function asCallProperty(namespaces, name, flags, isLex, args) {
michael@0 28213 var self = this;
michael@0 28214 if (Runtime.traceCallExecution.value) {
michael@0 28215 var receiverClassName = self.class ? self.class.className + ' ' : '';
michael@0 28216 callWriter.enter('call ' + receiverClassName + name + '(' + toSafeArrayString(args) + ') #' + callCounter.count(name));
michael@0 28217 }
michael@0 28218 var receiver = isLex ? null : self;
michael@0 28219 var result;
michael@0 28220 if (isProxyObject(self)) {
michael@0 28221 result = self[Runtime.VM_CALL_PROXY](new Multiname(namespaces, name, flags), receiver, args);
michael@0 28222 } else {
michael@0 28223 var method;
michael@0 28224 var resolved = self.resolveMultinameProperty(namespaces, name, flags);
michael@0 28225 if (self.asGetNumericProperty && Multiname.isNumeric(resolved)) {
michael@0 28226 method = self.asGetNumericProperty(resolved);
michael@0 28227 } else {
michael@0 28228 var openMethods = self.asOpenMethods;
michael@0 28229 if (receiver && openMethods && openMethods[resolved]) {
michael@0 28230 method = openMethods[resolved];
michael@0 28231 } else {
michael@0 28232 method = self[resolved];
michael@0 28233 }
michael@0 28234 }
michael@0 28235 result = method.apply(receiver, args);
michael@0 28236 }
michael@0 28237 Runtime.traceCallExecution.value > 0 && callWriter.leave('return ' + toSafeString(result));
michael@0 28238 return result;
michael@0 28239 }
michael@0 28240 Runtime.asCallProperty = asCallProperty;
michael@0 28241 function asCallSuper(scope, namespaces, name, flags, args) {
michael@0 28242 var self = this;
michael@0 28243 if (Runtime.traceCallExecution.value) {
michael@0 28244 var receiverClassName = self.class ? self.class.className + ' ' : '';
michael@0 28245 callWriter.enter('call super ' + receiverClassName + name + '(' + toSafeArrayString(args) + ') #' + callCounter.count(name));
michael@0 28246 }
michael@0 28247 var baseClass = scope.object.baseClass;
michael@0 28248 var resolved = baseClass.traitsPrototype.resolveMultinameProperty(namespaces, name, flags);
michael@0 28249 var openMethods = baseClass.traitsPrototype.asOpenMethods;
michael@0 28250 var method = openMethods[resolved];
michael@0 28251 var result = method.apply(this, args);
michael@0 28252 Runtime.traceCallExecution.value > 0 && callWriter.leave('return ' + toSafeString(result));
michael@0 28253 return result;
michael@0 28254 }
michael@0 28255 Runtime.asCallSuper = asCallSuper;
michael@0 28256 function asSetSuper(scope, namespaces, name, flags, value) {
michael@0 28257 var self = this;
michael@0 28258 if (Runtime.traceCallExecution.value) {
michael@0 28259 var receiverClassName = self.class ? self.class.className + ' ' : '';
michael@0 28260 callWriter.enter('set super ' + receiverClassName + name + '(' + toSafeString(value) + ') #' + callCounter.count(name));
michael@0 28261 }
michael@0 28262 var baseClass = scope.object.baseClass;
michael@0 28263 var resolved = baseClass.traitsPrototype.resolveMultinameProperty(namespaces, name, flags);
michael@0 28264 if (self.asSlots.byQN[resolved]) {
michael@0 28265 this.asSetProperty(namespaces, name, flags, value);
michael@0 28266 } else {
michael@0 28267 baseClass.traitsPrototype[Runtime.VM_OPEN_SET_METHOD_PREFIX + resolved].call(this, value);
michael@0 28268 }
michael@0 28269 Runtime.traceCallExecution.value > 0 && callWriter.leave('');
michael@0 28270 }
michael@0 28271 Runtime.asSetSuper = asSetSuper;
michael@0 28272 function asGetSuper(scope, namespaces, name, flags) {
michael@0 28273 var self = this;
michael@0 28274 if (Runtime.traceCallExecution.value) {
michael@0 28275 var receiver = self.class ? self.class.className + ' ' : '';
michael@0 28276 callWriter.enter('get super ' + receiver + name + ' #' + callCounter.count(name));
michael@0 28277 }
michael@0 28278 var baseClass = scope.object.baseClass;
michael@0 28279 var resolved = baseClass.traitsPrototype.resolveMultinameProperty(namespaces, name, flags);
michael@0 28280 var result;
michael@0 28281 if (self.asSlots.byQN[resolved]) {
michael@0 28282 result = this.asGetProperty(namespaces, name, flags);
michael@0 28283 } else {
michael@0 28284 result = baseClass.traitsPrototype[Runtime.VM_OPEN_GET_METHOD_PREFIX + resolved].call(this);
michael@0 28285 }
michael@0 28286 Runtime.traceCallExecution.value > 0 && callWriter.leave('return ' + toSafeString(result));
michael@0 28287 return result;
michael@0 28288 }
michael@0 28289 Runtime.asGetSuper = asGetSuper;
michael@0 28290 function construct(cls, args) {
michael@0 28291 if (cls.classInfo) {
michael@0 28292 var qn = Multiname.getQualifiedName(cls.classInfo.instanceInfo.name);
michael@0 28293 if (qn === Multiname.String) {
michael@0 28294 return String.apply(null, args);
michael@0 28295 }
michael@0 28296 if (qn === Multiname.Boolean) {
michael@0 28297 return Boolean.apply(null, args);
michael@0 28298 }
michael@0 28299 if (qn === Multiname.Number) {
michael@0 28300 return Number.apply(null, args);
michael@0 28301 }
michael@0 28302 }
michael@0 28303 var c = cls.instanceConstructor;
michael@0 28304 var a = args;
michael@0 28305 switch (args.length) {
michael@0 28306 case 0:
michael@0 28307 return new c();
michael@0 28308 case 1:
michael@0 28309 return new c(a[0]);
michael@0 28310 case 2:
michael@0 28311 return new c(a[0], a[1]);
michael@0 28312 case 3:
michael@0 28313 return new c(a[0], a[1], a[2]);
michael@0 28314 case 4:
michael@0 28315 return new c(a[0], a[1], a[2], a[3]);
michael@0 28316 case 5:
michael@0 28317 return new c(a[0], a[1], a[2], a[3], a[4]);
michael@0 28318 case 6:
michael@0 28319 return new c(a[0], a[1], a[2], a[3], a[4], a[5]);
michael@0 28320 case 7:
michael@0 28321 return new c(a[0], a[1], a[2], a[3], a[4], a[5], a[6]);
michael@0 28322 case 8:
michael@0 28323 return new c(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
michael@0 28324 case 9:
michael@0 28325 return new c(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]);
michael@0 28326 case 10:
michael@0 28327 return new c(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]);
michael@0 28328 }
michael@0 28329 var applyArguments = [];
michael@0 28330 for (var i = 0; i < args.length; i++) {
michael@0 28331 applyArguments[i + 1] = args[i];
michael@0 28332 }
michael@0 28333 return new (Function.bind.apply(c, applyArguments))();
michael@0 28334 }
michael@0 28335 Runtime.construct = construct;
michael@0 28336 function asConstructProperty(namespaces, name, flags, args) {
michael@0 28337 var self = this;
michael@0 28338 var constructor = self.asGetProperty(namespaces, name, flags);
michael@0 28339 if (Runtime.traceCallExecution.value) {
michael@0 28340 callWriter.enter('construct ' + name + '(' + toSafeArrayString(args) + ') #' + callCounter.count(name));
michael@0 28341 }
michael@0 28342 var result = construct(constructor, args);
michael@0 28343 Runtime.traceCallExecution.value > 0 && callWriter.leave('return ' + toSafeString(result));
michael@0 28344 return result;
michael@0 28345 }
michael@0 28346 Runtime.asConstructProperty = asConstructProperty;
michael@0 28347 function nonProxyingHasProperty(object, name) {
michael@0 28348 return name in object;
michael@0 28349 }
michael@0 28350 Runtime.nonProxyingHasProperty = nonProxyingHasProperty;
michael@0 28351 function asHasProperty(namespaces, name, flags, nonProxy) {
michael@0 28352 var self = this;
michael@0 28353 if (self.hasProperty) {
michael@0 28354 return self.hasProperty(namespaces, name, flags);
michael@0 28355 }
michael@0 28356 if (nonProxy) {
michael@0 28357 return nonProxyingHasProperty(self, self.resolveMultinameProperty(namespaces, name, flags));
michael@0 28358 } else {
michael@0 28359 return self.resolveMultinameProperty(namespaces, name, flags) in this;
michael@0 28360 }
michael@0 28361 }
michael@0 28362 Runtime.asHasProperty = asHasProperty;
michael@0 28363 function asDeleteProperty(namespaces, name, flags) {
michael@0 28364 var self = this;
michael@0 28365 if (self.asHasTraitProperty(namespaces, name, flags)) {
michael@0 28366 return false;
michael@0 28367 }
michael@0 28368 var resolved = self.resolveMultinameProperty(namespaces, name, flags);
michael@0 28369 return delete self[resolved];
michael@0 28370 }
michael@0 28371 Runtime.asDeleteProperty = asDeleteProperty;
michael@0 28372 function asHasTraitProperty(namespaces, name, flags) {
michael@0 28373 var self = this;
michael@0 28374 var resolved = self.resolveMultinameProperty(namespaces, name, flags);
michael@0 28375 return self.asBindings.indexOf(resolved) >= 0;
michael@0 28376 }
michael@0 28377 Runtime.asHasTraitProperty = asHasTraitProperty;
michael@0 28378 function asGetNumericProperty(i) {
michael@0 28379 return this[i];
michael@0 28380 }
michael@0 28381 Runtime.asGetNumericProperty = asGetNumericProperty;
michael@0 28382 function asSetNumericProperty(i, v) {
michael@0 28383 this[i] = v;
michael@0 28384 }
michael@0 28385 Runtime.asSetNumericProperty = asSetNumericProperty;
michael@0 28386 function asGetDescendants(namespaces, name, flags) {
michael@0 28387 Shumway.Debug.notImplemented('asGetDescendants');
michael@0 28388 }
michael@0 28389 Runtime.asGetDescendants = asGetDescendants;
michael@0 28390 function asNextNameIndex(index) {
michael@0 28391 var self = this;
michael@0 28392 if (index === 0) {
michael@0 28393 defineNonEnumerableProperty(self, 'asEnumerableKeys', self.asGetEnumerableKeys());
michael@0 28394 }
michael@0 28395 var asEnumerableKeys = self.asEnumerableKeys;
michael@0 28396 while (index < asEnumerableKeys.length) {
michael@0 28397 if (self.asHasProperty(undefined, asEnumerableKeys[index], 0)) {
michael@0 28398 return index + 1;
michael@0 28399 }
michael@0 28400 index++;
michael@0 28401 }
michael@0 28402 return 0;
michael@0 28403 }
michael@0 28404 Runtime.asNextNameIndex = asNextNameIndex;
michael@0 28405 function asNextName(index) {
michael@0 28406 var self = this;
michael@0 28407 var asEnumerableKeys = self.asEnumerableKeys;
michael@0 28408 true;
michael@0 28409 return asEnumerableKeys[index - 1];
michael@0 28410 }
michael@0 28411 Runtime.asNextName = asNextName;
michael@0 28412 function asNextValue(index) {
michael@0 28413 return this.asGetPublicProperty(this.asNextName(index));
michael@0 28414 }
michael@0 28415 Runtime.asNextValue = asNextValue;
michael@0 28416 function asGetEnumerableKeys() {
michael@0 28417 var self = this;
michael@0 28418 var boxedValue = self.valueOf();
michael@0 28419 if (typeof boxedValue === 'string' || typeof boxedValue === 'number') {
michael@0 28420 return [];
michael@0 28421 }
michael@0 28422 var keys = Object.keys(this);
michael@0 28423 var result = [];
michael@0 28424 for (var i = 0; i < keys.length; i++) {
michael@0 28425 var key = keys[i];
michael@0 28426 if (Shumway.isNumeric(key)) {
michael@0 28427 result.push(key);
michael@0 28428 } else {
michael@0 28429 var name = Multiname.stripPublicQualifier(key);
michael@0 28430 if (name !== undefined) {
michael@0 28431 result.push(name);
michael@0 28432 }
michael@0 28433 }
michael@0 28434 }
michael@0 28435 return result;
michael@0 28436 }
michael@0 28437 Runtime.asGetEnumerableKeys = asGetEnumerableKeys;
michael@0 28438 function asTypeOf(x) {
michael@0 28439 if (x) {
michael@0 28440 if (x.constructor === String) {
michael@0 28441 return 'string';
michael@0 28442 } else if (x.constructor === Number) {
michael@0 28443 return 'number';
michael@0 28444 } else if (x.constructor === Boolean) {
michael@0 28445 return 'boolean';
michael@0 28446 } else if (x instanceof XML || x instanceof XMLList) {
michael@0 28447 return 'xml';
michael@0 28448 }
michael@0 28449 }
michael@0 28450 return typeof x;
michael@0 28451 }
michael@0 28452 Runtime.asTypeOf = asTypeOf;
michael@0 28453 function publicizeProperties(object) {
michael@0 28454 var keys = Object.keys(object);
michael@0 28455 for (var i = 0; i < keys.length; i++) {
michael@0 28456 var k = keys[i];
michael@0 28457 if (!Multiname.isPublicQualifiedName(k)) {
michael@0 28458 var v = object[k];
michael@0 28459 object[Multiname.getPublicQualifiedName(k)] = v;
michael@0 28460 delete object[k];
michael@0 28461 }
michael@0 28462 }
michael@0 28463 }
michael@0 28464 Runtime.publicizeProperties = publicizeProperties;
michael@0 28465 function asGetSlot(object, index) {
michael@0 28466 return object[object.asSlots.byID[index].name];
michael@0 28467 }
michael@0 28468 Runtime.asGetSlot = asGetSlot;
michael@0 28469 function asSetSlot(object, index, value) {
michael@0 28470 var slotInfo = object.asSlots.byID[index];
michael@0 28471 if (slotInfo.const) {
michael@0 28472 return;
michael@0 28473 }
michael@0 28474 var name = slotInfo.name;
michael@0 28475 var type = slotInfo.type;
michael@0 28476 if (type && type.coerce) {
michael@0 28477 object[name] = type.coerce(value);
michael@0 28478 } else {
michael@0 28479 object[name] = value;
michael@0 28480 }
michael@0 28481 }
michael@0 28482 Runtime.asSetSlot = asSetSlot;
michael@0 28483 function throwError(name, error) {
michael@0 28484 if (true) {
michael@0 28485 var message = Shumway.AVM2.formatErrorMessage.apply(null, Array.prototype.slice.call(arguments, 1));
michael@0 28486 throwErrorFromVM(Shumway.AVM2.Runtime.AVM2.currentDomain(), name, message, error.code);
michael@0 28487 } else {
michael@0 28488 throwErrorFromVM(Shumway.AVM2.Runtime.AVM2.currentDomain(), name, Shumway.AVM2.getErrorMessage(error.code), error.code);
michael@0 28489 }
michael@0 28490 }
michael@0 28491 Runtime.throwError = throwError;
michael@0 28492 function throwErrorFromVM(domain, errorClass, message, id) {
michael@0 28493 var error = new (domain.getClass(errorClass)).instanceConstructor(message, id);
michael@0 28494 throw error;
michael@0 28495 }
michael@0 28496 Runtime.throwErrorFromVM = throwErrorFromVM;
michael@0 28497 function translateError(domain, error) {
michael@0 28498 if (error instanceof Error) {
michael@0 28499 var type = domain.getClass(error.name);
michael@0 28500 if (type) {
michael@0 28501 return new type.instanceConstructor(Shumway.AVM2.translateErrorMessage(error));
michael@0 28502 }
michael@0 28503 Shumway.Debug.unexpected('Can\'t translate error: ' + error);
michael@0 28504 }
michael@0 28505 return error;
michael@0 28506 }
michael@0 28507 Runtime.translateError = translateError;
michael@0 28508 function asIsInstanceOf(type, value) {
michael@0 28509 return type.isInstanceOf(value);
michael@0 28510 }
michael@0 28511 Runtime.asIsInstanceOf = asIsInstanceOf;
michael@0 28512 function asIsType(type, value) {
michael@0 28513 return type.isInstance(value);
michael@0 28514 }
michael@0 28515 Runtime.asIsType = asIsType;
michael@0 28516 function asAsType(type, value) {
michael@0 28517 return asIsType(type, value) ? value : null;
michael@0 28518 }
michael@0 28519 Runtime.asAsType = asAsType;
michael@0 28520 function asCoerceByMultiname(domain, multiname, value) {
michael@0 28521 true;
michael@0 28522 switch (Multiname.getQualifiedName(multiname)) {
michael@0 28523 case Multiname.Int:
michael@0 28524 return asCoerceInt(value);
michael@0 28525 case Multiname.Uint:
michael@0 28526 return asCoerceUint(value);
michael@0 28527 case Multiname.String:
michael@0 28528 return asCoerceString(value);
michael@0 28529 case Multiname.Number:
michael@0 28530 return asCoerceNumber(value);
michael@0 28531 case Multiname.Boolean:
michael@0 28532 return asCoerceBoolean(value);
michael@0 28533 case Multiname.Object:
michael@0 28534 return asCoerceObject(value);
michael@0 28535 }
michael@0 28536 return asCoerce(domain.getType(multiname), value);
michael@0 28537 }
michael@0 28538 Runtime.asCoerceByMultiname = asCoerceByMultiname;
michael@0 28539 function asCoerce(type, value) {
michael@0 28540 if (type.coerce) {
michael@0 28541 return type.coerce(value);
michael@0 28542 }
michael@0 28543 if (Shumway.isNullOrUndefined(value)) {
michael@0 28544 return null;
michael@0 28545 }
michael@0 28546 if (type.isInstance(value)) {
michael@0 28547 return value;
michael@0 28548 } else {
michael@0 28549 true;
michael@0 28550 }
michael@0 28551 }
michael@0 28552 Runtime.asCoerce = asCoerce;
michael@0 28553 function asCoerceString(x) {
michael@0 28554 if (typeof x === 'string') {
michael@0 28555 return x;
michael@0 28556 } else if (x == undefined) {
michael@0 28557 return null;
michael@0 28558 }
michael@0 28559 return x + '';
michael@0 28560 }
michael@0 28561 Runtime.asCoerceString = asCoerceString;
michael@0 28562 function asCoerceInt(x) {
michael@0 28563 return x | 0;
michael@0 28564 }
michael@0 28565 Runtime.asCoerceInt = asCoerceInt;
michael@0 28566 function asCoerceUint(x) {
michael@0 28567 return x >>> 0;
michael@0 28568 }
michael@0 28569 Runtime.asCoerceUint = asCoerceUint;
michael@0 28570 function asCoerceNumber(x) {
michael@0 28571 return +x;
michael@0 28572 }
michael@0 28573 Runtime.asCoerceNumber = asCoerceNumber;
michael@0 28574 function asCoerceBoolean(x) {
michael@0 28575 return !(!x);
michael@0 28576 }
michael@0 28577 Runtime.asCoerceBoolean = asCoerceBoolean;
michael@0 28578 function asCoerceObject(x) {
michael@0 28579 if (x == undefined) {
michael@0 28580 return null;
michael@0 28581 }
michael@0 28582 if (typeof x === 'string' || typeof x === 'number') {
michael@0 28583 return x;
michael@0 28584 }
michael@0 28585 return Object(x);
michael@0 28586 }
michael@0 28587 Runtime.asCoerceObject = asCoerceObject;
michael@0 28588 function asDefaultCompareFunction(a, b) {
michael@0 28589 return String(a).localeCompare(String(b));
michael@0 28590 }
michael@0 28591 Runtime.asDefaultCompareFunction = asDefaultCompareFunction;
michael@0 28592 function asCompare(a, b, options, compareFunction) {
michael@0 28593 true;
michael@0 28594 true;
michael@0 28595 var result = 0;
michael@0 28596 if (!compareFunction) {
michael@0 28597 compareFunction = asDefaultCompareFunction;
michael@0 28598 }
michael@0 28599 if (options & 1) {
michael@0 28600 a = String(a).toLowerCase();
michael@0 28601 b = String(b).toLowerCase();
michael@0 28602 }
michael@0 28603 if (options & 16) {
michael@0 28604 a = Shumway.toNumber(a);
michael@0 28605 b = Shumway.toNumber(b);
michael@0 28606 result = a < b ? -1 : a > b ? 1 : 0;
michael@0 28607 } else {
michael@0 28608 result = compareFunction(a, b);
michael@0 28609 }
michael@0 28610 if (options & 2) {
michael@0 28611 result *= -1;
michael@0 28612 }
michael@0 28613 return result;
michael@0 28614 }
michael@0 28615 Runtime.asCompare = asCompare;
michael@0 28616 function asAdd(l, r) {
michael@0 28617 if (typeof l === 'string' || typeof r === 'string') {
michael@0 28618 return String(l) + String(r);
michael@0 28619 }
michael@0 28620 return l + r;
michael@0 28621 }
michael@0 28622 Runtime.asAdd = asAdd;
michael@0 28623 function asHasNext2(object, index) {
michael@0 28624 if (Shumway.isNullOrUndefined(object)) {
michael@0 28625 return {
michael@0 28626 index: 0,
michael@0 28627 object: null
michael@0 28628 };
michael@0 28629 }
michael@0 28630 object = boxValue(object);
michael@0 28631 var nextIndex = object.asNextNameIndex(index);
michael@0 28632 if (nextIndex > 0) {
michael@0 28633 return {
michael@0 28634 index: nextIndex,
michael@0 28635 object: object
michael@0 28636 };
michael@0 28637 }
michael@0 28638 while (true) {
michael@0 28639 var object = Object.getPrototypeOf(object);
michael@0 28640 if (!object) {
michael@0 28641 return {
michael@0 28642 index: 0,
michael@0 28643 object: null
michael@0 28644 };
michael@0 28645 }
michael@0 28646 nextIndex = object.asNextNameIndex(0);
michael@0 28647 if (nextIndex > 0) {
michael@0 28648 return {
michael@0 28649 index: nextIndex,
michael@0 28650 object: object
michael@0 28651 };
michael@0 28652 }
michael@0 28653 }
michael@0 28654 return {
michael@0 28655 index: 0,
michael@0 28656 object: null
michael@0 28657 };
michael@0 28658 }
michael@0 28659 Runtime.asHasNext2 = asHasNext2;
michael@0 28660 function getDescendants(object, mn) {
michael@0 28661 if (!isXMLType(object)) {
michael@0 28662 throw 'Not XML object in getDescendants';
michael@0 28663 }
michael@0 28664 return object.descendants(mn);
michael@0 28665 }
michael@0 28666 Runtime.getDescendants = getDescendants;
michael@0 28667 function checkFilter(value) {
michael@0 28668 if (!value.class || !isXMLType(value)) {
michael@0 28669 throw 'TypeError operand of childFilter not of XML type';
michael@0 28670 }
michael@0 28671 return value;
michael@0 28672 }
michael@0 28673 Runtime.checkFilter = checkFilter;
michael@0 28674 function initializeGlobalObject(global) {
michael@0 28675 var VM_NATIVE_BUILTIN_SURROGATES = [
michael@0 28676 {
michael@0 28677 name: 'Object',
michael@0 28678 methods: [
michael@0 28679 'toString',
michael@0 28680 'valueOf'
michael@0 28681 ]
michael@0 28682 },
michael@0 28683 {
michael@0 28684 name: 'Function',
michael@0 28685 methods: [
michael@0 28686 'toString',
michael@0 28687 'valueOf'
michael@0 28688 ]
michael@0 28689 }
michael@0 28690 ];
michael@0 28691 var originals = global[Runtime.VM_NATIVE_BUILTIN_ORIGINALS] = createEmptyObject();
michael@0 28692 VM_NATIVE_BUILTIN_SURROGATES.forEach(function (surrogate) {
michael@0 28693 var object = global[surrogate.name];
michael@0 28694 originals[surrogate.name] = createEmptyObject();
michael@0 28695 surrogate.methods.forEach(function (originalFunctionName) {
michael@0 28696 var originalFunction;
michael@0 28697 if (object.prototype.hasOwnProperty(originalFunctionName)) {
michael@0 28698 originalFunction = object.prototype[originalFunctionName];
michael@0 28699 } else {
michael@0 28700 originalFunction = originals['Object'][originalFunctionName];
michael@0 28701 }
michael@0 28702 originals[surrogate.name][originalFunctionName] = originalFunction;
michael@0 28703 var overrideFunctionName = Multiname.getPublicQualifiedName(originalFunctionName);
michael@0 28704 if (useSurrogates) {
michael@0 28705 global[surrogate.name].prototype[originalFunctionName] = function surrogate() {
michael@0 28706 if (this[overrideFunctionName]) {
michael@0 28707 return this[overrideFunctionName]();
michael@0 28708 }
michael@0 28709 return originalFunction.call(this);
michael@0 28710 };
michael@0 28711 }
michael@0 28712 });
michael@0 28713 });
michael@0 28714 [
michael@0 28715 'Object',
michael@0 28716 'Number',
michael@0 28717 'Boolean',
michael@0 28718 'String',
michael@0 28719 'Array',
michael@0 28720 'Date',
michael@0 28721 'RegExp'
michael@0 28722 ].forEach(function (name) {
michael@0 28723 defineReadOnlyProperty(global[name].prototype, Runtime.VM_NATIVE_PROTOTYPE_FLAG, true);
michael@0 28724 });
michael@0 28725 defineNonEnumerableProperty(global.Object.prototype, 'getNamespaceResolutionMap', getNamespaceResolutionMap);
michael@0 28726 defineNonEnumerableProperty(global.Object.prototype, 'resolveMultinameProperty', resolveMultinameProperty);
michael@0 28727 defineNonEnumerableProperty(global.Object.prototype, 'asGetProperty', asGetProperty);
michael@0 28728 defineNonEnumerableProperty(global.Object.prototype, 'asGetPublicProperty', asGetPublicProperty);
michael@0 28729 defineNonEnumerableProperty(global.Object.prototype, 'asGetResolvedStringProperty', asGetResolvedStringProperty);
michael@0 28730 defineNonEnumerableProperty(global.Object.prototype, 'asSetProperty', asSetProperty);
michael@0 28731 defineNonEnumerableProperty(global.Object.prototype, 'asSetPublicProperty', asSetPublicProperty);
michael@0 28732 defineNonEnumerableProperty(global.Object.prototype, 'asDefineProperty', asDefineProperty);
michael@0 28733 defineNonEnumerableProperty(global.Object.prototype, 'asDefinePublicProperty', asDefinePublicProperty);
michael@0 28734 defineNonEnumerableProperty(global.Object.prototype, 'asCallProperty', asCallProperty);
michael@0 28735 defineNonEnumerableProperty(global.Object.prototype, 'asCallSuper', asCallSuper);
michael@0 28736 defineNonEnumerableProperty(global.Object.prototype, 'asGetSuper', asGetSuper);
michael@0 28737 defineNonEnumerableProperty(global.Object.prototype, 'asSetSuper', asSetSuper);
michael@0 28738 defineNonEnumerableProperty(global.Object.prototype, 'asCallPublicProperty', asCallPublicProperty);
michael@0 28739 defineNonEnumerableProperty(global.Object.prototype, 'asCallResolvedStringProperty', asCallResolvedStringProperty);
michael@0 28740 defineNonEnumerableProperty(global.Object.prototype, 'asConstructProperty', asConstructProperty);
michael@0 28741 defineNonEnumerableProperty(global.Object.prototype, 'asHasProperty', asHasProperty);
michael@0 28742 defineNonEnumerableProperty(global.Object.prototype, 'asHasTraitProperty', asHasTraitProperty);
michael@0 28743 defineNonEnumerableProperty(global.Object.prototype, 'asDeleteProperty', asDeleteProperty);
michael@0 28744 defineNonEnumerableProperty(global.Object.prototype, 'asNextName', asNextName);
michael@0 28745 defineNonEnumerableProperty(global.Object.prototype, 'asNextValue', asNextValue);
michael@0 28746 defineNonEnumerableProperty(global.Object.prototype, 'asNextNameIndex', asNextNameIndex);
michael@0 28747 defineNonEnumerableProperty(global.Object.prototype, 'asGetEnumerableKeys', asGetEnumerableKeys);
michael@0 28748 [
michael@0 28749 'Array',
michael@0 28750 'Int8Array',
michael@0 28751 'Uint8Array',
michael@0 28752 'Uint8ClampedArray',
michael@0 28753 'Int16Array',
michael@0 28754 'Uint16Array',
michael@0 28755 'Int32Array',
michael@0 28756 'Uint32Array',
michael@0 28757 'Float32Array',
michael@0 28758 'Float64Array'
michael@0 28759 ].forEach(function (name) {
michael@0 28760 if (!(name in global)) {
michael@0 28761 log(name + ' was not found in globals');
michael@0 28762 return;
michael@0 28763 }
michael@0 28764 defineNonEnumerableProperty(global[name].prototype, 'asGetNumericProperty', asGetNumericProperty);
michael@0 28765 defineNonEnumerableProperty(global[name].prototype, 'asSetNumericProperty', asSetNumericProperty);
michael@0 28766 defineNonEnumerableProperty(global[name].prototype, 'asGetProperty', asGetPropertyLikelyNumeric);
michael@0 28767 defineNonEnumerableProperty(global[name].prototype, 'asSetProperty', asSetPropertyLikelyNumeric);
michael@0 28768 });
michael@0 28769 global.Array.prototype.asGetProperty = function (namespaces, name, flags) {
michael@0 28770 if (typeof name === 'number') {
michael@0 28771 return this[name];
michael@0 28772 }
michael@0 28773 return asGetProperty.call(this, namespaces, name, flags);
michael@0 28774 };
michael@0 28775 global.Array.prototype.asSetProperty = function (namespaces, name, flags, value) {
michael@0 28776 if (typeof name === 'number') {
michael@0 28777 this[name] = value;
michael@0 28778 return;
michael@0 28779 }
michael@0 28780 return asSetProperty.call(this, namespaces, name, flags, value);
michael@0 28781 };
michael@0 28782 }
michael@0 28783 Runtime.initializeGlobalObject = initializeGlobalObject;
michael@0 28784 function nameInTraits(object, qn) {
michael@0 28785 if (object.hasOwnProperty(Runtime.VM_BINDINGS) && object.hasOwnProperty(qn)) {
michael@0 28786 return true;
michael@0 28787 }
michael@0 28788 var proto = Object.getPrototypeOf(object);
michael@0 28789 return proto.hasOwnProperty(Runtime.VM_BINDINGS) && proto.hasOwnProperty(qn);
michael@0 28790 }
michael@0 28791 Runtime.nameInTraits = nameInTraits;
michael@0 28792 function CatchScopeObject(domain, trait) {
michael@0 28793 if (trait) {
michael@0 28794 new Shumway.AVM2.Runtime.CatchBindings(new Shumway.AVM2.Runtime.Scope(null, this), trait).applyTo(domain, this);
michael@0 28795 }
michael@0 28796 }
michael@0 28797 Runtime.CatchScopeObject = CatchScopeObject;
michael@0 28798 var Global = function () {
michael@0 28799 function Global(script) {
michael@0 28800 this.scriptInfo = script;
michael@0 28801 script.global = this;
michael@0 28802 this.scriptBindings = new Shumway.AVM2.Runtime.ScriptBindings(script, new Shumway.AVM2.Runtime.Scope(null, this, false));
michael@0 28803 this.scriptBindings.applyTo(script.abc.applicationDomain, this);
michael@0 28804 script.loaded = true;
michael@0 28805 }
michael@0 28806 Global.prototype.toString = function () {
michael@0 28807 return '[object global]';
michael@0 28808 };
michael@0 28809 Global.prototype.isExecuted = function () {
michael@0 28810 return this.scriptInfo.executed;
michael@0 28811 };
michael@0 28812 Global.prototype.isExecuting = function () {
michael@0 28813 return this.scriptInfo.executing;
michael@0 28814 };
michael@0 28815 Global.prototype.ensureExecuted = function () {
michael@0 28816 Shumway.AVM2.Runtime.ensureScriptIsExecuted(this.scriptInfo);
michael@0 28817 };
michael@0 28818 return Global;
michael@0 28819 }();
michael@0 28820 Runtime.Global = Global;
michael@0 28821 defineNonEnumerableProperty(Global.prototype, Multiname.getPublicQualifiedName('toString'), function () {
michael@0 28822 return this.toString();
michael@0 28823 });
michael@0 28824 var LazyInitializer = function () {
michael@0 28825 function LazyInitializer(target) {
michael@0 28826 this.target = target;
michael@0 28827 }
michael@0 28828 LazyInitializer.create = function (target) {
michael@0 28829 if (target.asLazyInitializer) {
michael@0 28830 return target.asLazyInitializer;
michael@0 28831 }
michael@0 28832 return target.asLazyInitializer = new LazyInitializer(target);
michael@0 28833 };
michael@0 28834 LazyInitializer.prototype.getName = function () {
michael@0 28835 if (this.name) {
michael@0 28836 return this.name;
michael@0 28837 }
michael@0 28838 var target = this.target, initialize;
michael@0 28839 if (this.target instanceof ScriptInfo) {
michael@0 28840 var scriptInfo = target;
michael@0 28841 this.name = '$' + Shumway.StringUtilities.variableLengthEncodeInt32(scriptInfo.hash);
michael@0 28842 initialize = function () {
michael@0 28843 Shumway.AVM2.Runtime.ensureScriptIsExecuted(target, 'Lazy Initializer');
michael@0 28844 return scriptInfo.global;
michael@0 28845 };
michael@0 28846 } else if (this.target instanceof ClassInfo) {
michael@0 28847 var classInfo = target;
michael@0 28848 this.name = '$' + Shumway.StringUtilities.variableLengthEncodeInt32(classInfo.hash);
michael@0 28849 initialize = function () {
michael@0 28850 if (classInfo.classObject) {
michael@0 28851 return classInfo.classObject;
michael@0 28852 }
michael@0 28853 return classInfo.abc.applicationDomain.getProperty(classInfo.instanceInfo.name);
michael@0 28854 };
michael@0 28855 } else {
michael@0 28856 Shumway.Debug.notImplemented(String(target));
michael@0 28857 }
michael@0 28858 var name = this.name;
michael@0 28859 Object.defineProperty(LazyInitializer._holder, name, {
michael@0 28860 get: function () {
michael@0 28861 var value = initialize();
michael@0 28862 Object.defineProperty(LazyInitializer._holder, name, {
michael@0 28863 value: value,
michael@0 28864 writable: true
michael@0 28865 });
michael@0 28866 return value;
michael@0 28867 },
michael@0 28868 configurable: true
michael@0 28869 });
michael@0 28870 return name;
michael@0 28871 };
michael@0 28872 LazyInitializer._holder = jsGlobal;
michael@0 28873 return LazyInitializer;
michael@0 28874 }();
michael@0 28875 Runtime.LazyInitializer = LazyInitializer;
michael@0 28876 function forEachPublicProperty(object, fn, self) {
michael@0 28877 if (!object.asBindings) {
michael@0 28878 for (var key in object) {
michael@0 28879 fn.call(self, key, object[key]);
michael@0 28880 }
michael@0 28881 return;
michael@0 28882 }
michael@0 28883 for (var key in object) {
michael@0 28884 if (Shumway.isNumeric(key)) {
michael@0 28885 fn.call(self, key, object[key]);
michael@0 28886 } else if (Multiname.isPublicQualifiedName(key) && object.asBindings.indexOf(key) < 0) {
michael@0 28887 var name = Multiname.stripPublicQualifier(key);
michael@0 28888 fn.call(self, name, object[key]);
michael@0 28889 }
michael@0 28890 }
michael@0 28891 }
michael@0 28892 Runtime.forEachPublicProperty = forEachPublicProperty;
michael@0 28893 function wrapJSObject(object) {
michael@0 28894 var wrapper = Object.create(object);
michael@0 28895 for (var i in object) {
michael@0 28896 Object.defineProperty(wrapper, Multiname.getPublicQualifiedName(i), function (object, i) {
michael@0 28897 return {
michael@0 28898 get: function () {
michael@0 28899 return object[i];
michael@0 28900 },
michael@0 28901 set: function (value) {
michael@0 28902 object[i] = value;
michael@0 28903 },
michael@0 28904 enumerable: true
michael@0 28905 };
michael@0 28906 }(object, i));
michael@0 28907 }
michael@0 28908 return wrapper;
michael@0 28909 }
michael@0 28910 Runtime.wrapJSObject = wrapJSObject;
michael@0 28911 function asCreateActivation(methodInfo) {
michael@0 28912 return Object.create(methodInfo.activationPrototype);
michael@0 28913 }
michael@0 28914 Runtime.asCreateActivation = asCreateActivation;
michael@0 28915 var GlobalMultinameResolver = function () {
michael@0 28916 function GlobalMultinameResolver() {
michael@0 28917 }
michael@0 28918 GlobalMultinameResolver.updateTraits = function (traits) {
michael@0 28919 for (var i = 0; i < traits.length; i++) {
michael@0 28920 var trait = traits[i];
michael@0 28921 var name = trait.name.name;
michael@0 28922 var namespace = trait.name.getNamespace();
michael@0 28923 if (!namespace.isDynamic()) {
michael@0 28924 GlobalMultinameResolver.hasNonDynamicNamespaces[name] = true;
michael@0 28925 if (GlobalMultinameResolver.wasResolved[name]) {
michael@0 28926 Shumway.Debug.notImplemented('We have to the undo the optimization, ' + name + ' can now bind to ' + namespace);
michael@0 28927 }
michael@0 28928 }
michael@0 28929 }
michael@0 28930 };
michael@0 28931 GlobalMultinameResolver.loadAbc = function (abc) {
michael@0 28932 if (!Runtime.globalMultinameAnalysis.value) {
michael@0 28933 return;
michael@0 28934 }
michael@0 28935 var scripts = abc.scripts;
michael@0 28936 var classes = abc.classes;
michael@0 28937 var methods = abc.methods;
michael@0 28938 for (var i = 0; i < scripts.length; i++) {
michael@0 28939 GlobalMultinameResolver.updateTraits(scripts[i].traits);
michael@0 28940 }
michael@0 28941 for (var i = 0; i < classes.length; i++) {
michael@0 28942 GlobalMultinameResolver.updateTraits(classes[i].traits);
michael@0 28943 GlobalMultinameResolver.updateTraits(classes[i].instanceInfo.traits);
michael@0 28944 }
michael@0 28945 for (var i = 0; i < methods.length; i++) {
michael@0 28946 if (methods[i].traits) {
michael@0 28947 GlobalMultinameResolver.updateTraits(methods[i].traits);
michael@0 28948 }
michael@0 28949 }
michael@0 28950 };
michael@0 28951 GlobalMultinameResolver.resolveMultiname = function (multiname) {
michael@0 28952 var name = multiname.name;
michael@0 28953 if (GlobalMultinameResolver.hasNonDynamicNamespaces[name]) {
michael@0 28954 return;
michael@0 28955 }
michael@0 28956 GlobalMultinameResolver.wasResolved[name] = true;
michael@0 28957 return new Multiname([
michael@0 28958 Namespace.PUBLIC
michael@0 28959 ], multiname.name);
michael@0 28960 };
michael@0 28961 GlobalMultinameResolver.hasNonDynamicNamespaces = createEmptyObject();
michael@0 28962 GlobalMultinameResolver.wasResolved = createEmptyObject();
michael@0 28963 return GlobalMultinameResolver;
michael@0 28964 }();
michael@0 28965 Runtime.GlobalMultinameResolver = GlobalMultinameResolver;
michael@0 28966 var ActivationInfo = function () {
michael@0 28967 function ActivationInfo(methodInfo) {
michael@0 28968 this.methodInfo = methodInfo;
michael@0 28969 }
michael@0 28970 return ActivationInfo;
michael@0 28971 }();
michael@0 28972 Runtime.ActivationInfo = ActivationInfo;
michael@0 28973 function sliceArguments(args, offset) {
michael@0 28974 if (typeof offset === 'undefined') {
michael@0 28975 offset = 0;
michael@0 28976 }
michael@0 28977 return Array.prototype.slice.call(args, offset);
michael@0 28978 }
michael@0 28979 Runtime.sliceArguments = sliceArguments;
michael@0 28980 function canCompile(mi) {
michael@0 28981 if (!mi.hasBody) {
michael@0 28982 return false;
michael@0 28983 }
michael@0 28984 if (mi.hasExceptions() && !compilerEnableExceptions.value) {
michael@0 28985 return false;
michael@0 28986 } else if (mi.code.length > compilerMaximumMethodSize.value) {
michael@0 28987 return false;
michael@0 28988 }
michael@0 28989 return true;
michael@0 28990 }
michael@0 28991 Runtime.canCompile = canCompile;
michael@0 28992 function shouldCompile(mi) {
michael@0 28993 if (!canCompile(mi)) {
michael@0 28994 return false;
michael@0 28995 }
michael@0 28996 if (mi.isClassInitializer || mi.isScriptInitializer) {
michael@0 28997 return false;
michael@0 28998 }
michael@0 28999 return true;
michael@0 29000 }
michael@0 29001 Runtime.shouldCompile = shouldCompile;
michael@0 29002 function forceCompile(mi) {
michael@0 29003 if (mi.hasExceptions()) {
michael@0 29004 return false;
michael@0 29005 }
michael@0 29006 var holder = mi.holder;
michael@0 29007 if (holder instanceof ClassInfo) {
michael@0 29008 holder = holder.instanceInfo;
michael@0 29009 }
michael@0 29010 if (holder instanceof InstanceInfo) {
michael@0 29011 var packageName = holder.name.namespaces[0].uri;
michael@0 29012 switch (packageName) {
michael@0 29013 case 'flash.geom':
michael@0 29014 case 'flash.events':
michael@0 29015 return true;
michael@0 29016 default:
michael@0 29017 break;
michael@0 29018 }
michael@0 29019 var className = holder.name.getOriginalName();
michael@0 29020 switch (className) {
michael@0 29021 case 'com.google.youtube.model.VideoData':
michael@0 29022 return true;
michael@0 29023 }
michael@0 29024 }
michael@0 29025 return false;
michael@0 29026 }
michael@0 29027 Runtime.forceCompile = forceCompile;
michael@0 29028 Runtime.CODE_CACHE = createEmptyObject();
michael@0 29029 function searchCodeCache(methodInfo) {
michael@0 29030 if (!Runtime.codeCaching.value) {
michael@0 29031 return;
michael@0 29032 }
michael@0 29033 var cacheInfo = Runtime.CODE_CACHE[methodInfo.abc.hash];
michael@0 29034 if (!cacheInfo) {
michael@0 29035 warn('Cannot Find Code Cache For ABC, name: ' + methodInfo.abc.name + ', hash: ' + methodInfo.abc.hash);
michael@0 29036 Counter.count('Code Cache ABC Miss');
michael@0 29037 return;
michael@0 29038 }
michael@0 29039 if (!cacheInfo.isInitialized) {
michael@0 29040 methodInfo.abc.scripts.forEach(function (scriptInfo) {
michael@0 29041 LazyInitializer.create(scriptInfo).getName();
michael@0 29042 });
michael@0 29043 methodInfo.abc.classes.forEach(function (classInfo) {
michael@0 29044 LazyInitializer.create(classInfo).getName();
michael@0 29045 });
michael@0 29046 cacheInfo.isInitialized = true;
michael@0 29047 }
michael@0 29048 var method = cacheInfo.methods[methodInfo.index];
michael@0 29049 if (!method) {
michael@0 29050 if (methodInfo.isInstanceInitializer || methodInfo.isClassInitializer) {
michael@0 29051 Counter.count('Code Cache Query On Initializer');
michael@0 29052 } else {
michael@0 29053 Counter.count('Code Cache MISS ON OTHER');
michael@0 29054 warn('Shouldn\'t MISS: ' + methodInfo + ' ' + methodInfo.debugName);
michael@0 29055 }
michael@0 29056 Counter.count('Code Cache Miss');
michael@0 29057 return;
michael@0 29058 }
michael@0 29059 log('Linking CC: ' + methodInfo);
michael@0 29060 Counter.count('Code Cache Hit');
michael@0 29061 return method;
michael@0 29062 }
michael@0 29063 Runtime.searchCodeCache = searchCodeCache;
michael@0 29064 function createInterpretedFunction(methodInfo, scope, hasDynamicScope) {
michael@0 29065 var mi = methodInfo;
michael@0 29066 var hasDefaults = false;
michael@0 29067 var defaults = mi.parameters.map(function (p) {
michael@0 29068 if (p.value !== undefined) {
michael@0 29069 hasDefaults = true;
michael@0 29070 }
michael@0 29071 return p.value;
michael@0 29072 });
michael@0 29073 var fn;
michael@0 29074 if (hasDynamicScope) {
michael@0 29075 fn = function (scope) {
michael@0 29076 var global = this === jsGlobal ? scope.global.object : this;
michael@0 29077 var args = sliceArguments(arguments, 1);
michael@0 29078 if (hasDefaults && args.length < defaults.length) {
michael@0 29079 args = args.concat(defaults.slice(args.length - defaults.length));
michael@0 29080 }
michael@0 29081 return Shumway.AVM2.Interpreter.interpretMethod(global, methodInfo, scope, args);
michael@0 29082 };
michael@0 29083 } else {
michael@0 29084 fn = function () {
michael@0 29085 var global = this === jsGlobal ? scope.global.object : this;
michael@0 29086 var args = sliceArguments(arguments);
michael@0 29087 if (hasDefaults && args.length < defaults.length) {
michael@0 29088 args = args.concat(defaults.slice(arguments.length - defaults.length));
michael@0 29089 }
michael@0 29090 return Shumway.AVM2.Interpreter.interpretMethod(global, methodInfo, scope, args);
michael@0 29091 };
michael@0 29092 }
michael@0 29093 fn.instanceConstructor = fn;
michael@0 29094 fn.debugName = 'Interpreter Function #' + vmNextInterpreterFunctionId++;
michael@0 29095 return fn;
michael@0 29096 }
michael@0 29097 Runtime.createInterpretedFunction = createInterpretedFunction;
michael@0 29098 function debugName(value) {
michael@0 29099 if (Shumway.isFunction(value)) {
michael@0 29100 return value.debugName;
michael@0 29101 }
michael@0 29102 return value;
michael@0 29103 }
michael@0 29104 Runtime.debugName = debugName;
michael@0 29105 function createCompiledFunction(methodInfo, scope, hasDynamicScope, breakpoint, deferCompilation) {
michael@0 29106 var mi = methodInfo;
michael@0 29107 var cached = searchCodeCache(mi);
michael@0 29108 if (!cached) {
michael@0 29109 var result = Compiler.compileMethod(mi, scope, hasDynamicScope);
michael@0 29110 var parameters = result.parameters;
michael@0 29111 var body = result.body;
michael@0 29112 }
michael@0 29113 var fnName = mi.name ? Multiname.getQualifiedName(mi.name) : 'fn' + compiledFunctionCount;
michael@0 29114 if (mi.holder) {
michael@0 29115 var fnNamePrefix = '';
michael@0 29116 if (mi.holder instanceof ClassInfo) {
michael@0 29117 fnNamePrefix = 'static$' + mi.holder.instanceInfo.name.getName();
michael@0 29118 } else if (mi.holder instanceof InstanceInfo) {
michael@0 29119 fnNamePrefix = mi.holder.name.getName();
michael@0 29120 } else if (mi.holder instanceof ScriptInfo) {
michael@0 29121 fnNamePrefix = 'script';
michael@0 29122 }
michael@0 29123 fnName = fnNamePrefix + '$' + fnName;
michael@0 29124 }
michael@0 29125 fnName = Shumway.StringUtilities.escapeString(fnName);
michael@0 29126 if (mi.verified) {
michael@0 29127 fnName += '$V';
michael@0 29128 }
michael@0 29129 if (compiledFunctionCount == functionBreak.value || breakpoint) {
michael@0 29130 body = '{ debugger; \n' + body + '}';
michael@0 29131 }
michael@0 29132 if (!cached) {
michael@0 29133 var fnSource = 'function ' + fnName + ' (' + parameters.join(', ') + ') ' + body;
michael@0 29134 }
michael@0 29135 if (traceLevel.value > 1) {
michael@0 29136 mi.trace(new IndentingWriter(), mi.abc);
michael@0 29137 }
michael@0 29138 mi.debugTrace = function () {
michael@0 29139 mi.trace(new IndentingWriter(), mi.abc);
michael@0 29140 };
michael@0 29141 if (traceLevel.value > 0) {
michael@0 29142 log(fnSource);
michael@0 29143 }
michael@0 29144 var fn = cached || new Function('return ' + fnSource)();
michael@0 29145 fn.debugName = 'Compiled Function #' + vmNextCompiledFunctionId++;
michael@0 29146 return fn;
michael@0 29147 }
michael@0 29148 Runtime.createCompiledFunction = createCompiledFunction;
michael@0 29149 function createFunction(mi, scope, hasDynamicScope, breakpoint) {
michael@0 29150 if (typeof breakpoint === 'undefined') {
michael@0 29151 breakpoint = false;
michael@0 29152 }
michael@0 29153 true;
michael@0 29154 if (mi.freeMethod) {
michael@0 29155 if (hasDynamicScope) {
michael@0 29156 return Shumway.AVM2.Runtime.bindFreeMethodScope(mi, scope);
michael@0 29157 }
michael@0 29158 return mi.freeMethod;
michael@0 29159 }
michael@0 29160 var fn;
michael@0 29161 if (fn = Shumway.AVM2.Runtime.checkMethodOverrides(mi)) {
michael@0 29162 true;
michael@0 29163 return fn;
michael@0 29164 }
michael@0 29165 ensureFunctionIsInitialized(mi);
michael@0 29166 totalFunctionCount++;
michael@0 29167 var useInterpreter = false;
michael@0 29168 if ((mi.abc.applicationDomain.mode === 1 || !shouldCompile(mi)) && !forceCompile(mi)) {
michael@0 29169 useInterpreter = true;
michael@0 29170 }
michael@0 29171 if (compileOnly.value >= 0) {
michael@0 29172 if (Number(compileOnly.value) !== totalFunctionCount) {
michael@0 29173 log('Compile Only Skipping ' + totalFunctionCount);
michael@0 29174 useInterpreter = true;
michael@0 29175 }
michael@0 29176 }
michael@0 29177 if (compileUntil.value >= 0) {
michael@0 29178 if (totalFunctionCount > 1000) {
michael@0 29179 log(Shumway.Debug.backtrace());
michael@0 29180 log(Shumway.AVM2.Runtime.AVM2.getStackTrace());
michael@0 29181 }
michael@0 29182 if (totalFunctionCount > compileUntil.value) {
michael@0 29183 log('Compile Until Skipping ' + totalFunctionCount);
michael@0 29184 useInterpreter = true;
michael@0 29185 }
michael@0 29186 }
michael@0 29187 if (useInterpreter) {
michael@0 29188 mi.freeMethod = createInterpretedFunction(mi, scope, hasDynamicScope);
michael@0 29189 } else {
michael@0 29190 compiledFunctionCount++;
michael@0 29191 if (compileOnly.value >= 0 || compileUntil.value >= 0) {
michael@0 29192 log('Compiling ' + totalFunctionCount);
michael@0 29193 }
michael@0 29194 mi.freeMethod = createCompiledFunction(mi, scope, hasDynamicScope, breakpoint, mi.isInstanceInitializer);
michael@0 29195 }
michael@0 29196 mi.freeMethod.methodInfo = mi;
michael@0 29197 if (hasDynamicScope) {
michael@0 29198 return Shumway.AVM2.Runtime.bindFreeMethodScope(mi, scope);
michael@0 29199 }
michael@0 29200 return mi.freeMethod;
michael@0 29201 }
michael@0 29202 Runtime.createFunction = createFunction;
michael@0 29203 function ensureFunctionIsInitialized(methodInfo) {
michael@0 29204 var mi = methodInfo;
michael@0 29205 if (!mi.analysis) {
michael@0 29206 mi.analysis = new Analysis(mi);
michael@0 29207 if (mi.needsActivation()) {
michael@0 29208 mi.activationPrototype = new ActivationInfo(mi);
michael@0 29209 new Shumway.AVM2.Runtime.ActivationBindings(mi).applyTo(mi.abc.applicationDomain, mi.activationPrototype);
michael@0 29210 }
michael@0 29211 var exceptions = mi.exceptions;
michael@0 29212 for (var i = 0, j = exceptions.length; i < j; i++) {
michael@0 29213 var handler = exceptions[i];
michael@0 29214 if (handler.varName) {
michael@0 29215 var varTrait = Object.create(Trait.prototype);
michael@0 29216 varTrait.kind = 0;
michael@0 29217 varTrait.name = handler.varName;
michael@0 29218 varTrait.typeName = handler.typeName;
michael@0 29219 varTrait.holder = mi;
michael@0 29220 handler.scopeObject = new CatchScopeObject(mi.abc.applicationDomain, varTrait);
michael@0 29221 } else {
michael@0 29222 handler.scopeObject = new CatchScopeObject(undefined, undefined);
michael@0 29223 }
michael@0 29224 }
michael@0 29225 }
michael@0 29226 }
michael@0 29227 Runtime.ensureFunctionIsInitialized = ensureFunctionIsInitialized;
michael@0 29228 function getTraitFunction(trait, scope, natives) {
michael@0 29229 true;
michael@0 29230 true;
michael@0 29231 var mi = trait.methodInfo;
michael@0 29232 var fn;
michael@0 29233 if (mi.isNative()) {
michael@0 29234 var md = trait.metadata;
michael@0 29235 if (md && md.native) {
michael@0 29236 var nativeName = md.native.value[0].value;
michael@0 29237 var makeNativeFunction = getNative(nativeName);
michael@0 29238 fn = makeNativeFunction && makeNativeFunction(null, scope);
michael@0 29239 } else if (md && md.unsafeJSNative) {
michael@0 29240 fn = getNative(md.unsafeJSNative.value[0].value);
michael@0 29241 } else if (natives) {
michael@0 29242 var k = Multiname.getName(mi.name);
michael@0 29243 if (trait.isGetter()) {
michael@0 29244 fn = natives[k] ? natives[k].get : undefined;
michael@0 29245 } else if (trait.isSetter()) {
michael@0 29246 fn = natives[k] ? natives[k].set : undefined;
michael@0 29247 } else {
michael@0 29248 fn = natives[k];
michael@0 29249 }
michael@0 29250 }
michael@0 29251 if (!fn) {
michael@0 29252 Shumway.Debug.warning('No native method for: ' + trait.kindName() + ' ' + mi.holder.name + '::' + Multiname.getQualifiedName(mi.name));
michael@0 29253 return function (mi) {
michael@0 29254 return function () {
michael@0 29255 Shumway.Debug.warning('Calling undefined native method: ' + trait.kindName() + ' ' + mi.holder.name + '::' + Multiname.getQualifiedName(mi.name));
michael@0 29256 };
michael@0 29257 }(mi);
michael@0 29258 }
michael@0 29259 } else {
michael@0 29260 if (Runtime.traceExecution.value >= 2) {
michael@0 29261 log('Creating Function For Trait: ' + trait.holder + ' ' + trait);
michael@0 29262 }
michael@0 29263 fn = createFunction(mi, scope, false, false);
michael@0 29264 true;
michael@0 29265 }
michael@0 29266 if (Runtime.traceExecution.value >= 3) {
michael@0 29267 log('Made Function: ' + Multiname.getQualifiedName(mi.name));
michael@0 29268 }
michael@0 29269 return fn;
michael@0 29270 }
michael@0 29271 Runtime.getTraitFunction = getTraitFunction;
michael@0 29272 function createClass(classInfo, baseClass, scope) {
michael@0 29273 true;
michael@0 29274 var ci = classInfo;
michael@0 29275 var ii = ci.instanceInfo;
michael@0 29276 var domain = ci.abc.applicationDomain;
michael@0 29277 var className = Multiname.getName(ii.name);
michael@0 29278 if (Runtime.traceExecution.value) {
michael@0 29279 log('Creating ' + (ii.isInterface() ? 'Interface' : 'Class') + ': ' + className + (ci.native ? ' replaced with native ' + ci.native.cls : ''));
michael@0 29280 }
michael@0 29281 var cls;
michael@0 29282 if (ii.isInterface()) {
michael@0 29283 cls = Shumway.AVM2.Runtime.Interface.createInterface(classInfo);
michael@0 29284 } else {
michael@0 29285 cls = Shumway.AVM2.Runtime.Class.createClass(classInfo, baseClass, scope);
michael@0 29286 }
michael@0 29287 if (Runtime.traceClasses.value) {
michael@0 29288 domain.loadedClasses.push(cls);
michael@0 29289 domain.traceLoadedClasses(true);
michael@0 29290 }
michael@0 29291 if (ii.isInterface()) {
michael@0 29292 return cls;
michael@0 29293 }
michael@0 29294 domain.onMessage.notify1('classCreated', cls);
michael@0 29295 if (cls.instanceConstructor && cls !== Shumway.AVM2.Runtime.Class) {
michael@0 29296 cls.verify();
michael@0 29297 }
michael@0 29298 if (baseClass && (Multiname.getQualifiedName(baseClass.classInfo.instanceInfo.name.name) === 'Proxy' || baseClass.isProxy)) {
michael@0 29299 installProxyClassWrapper(cls);
michael@0 29300 cls.isProxy = true;
michael@0 29301 }
michael@0 29302 classInfo.classObject = cls;
michael@0 29303 createFunction(classInfo.init, scope, false, false).call(cls);
michael@0 29304 if (Runtime.sealConstTraits) {
michael@0 29305 this.sealConstantTraits(cls, ci.traits);
michael@0 29306 }
michael@0 29307 return cls;
michael@0 29308 }
michael@0 29309 Runtime.createClass = createClass;
michael@0 29310 function sealConstantTraits(object, traits) {
michael@0 29311 for (var i = 0, j = traits.length; i < j; i++) {
michael@0 29312 var trait = traits[i];
michael@0 29313 if (trait.isConst()) {
michael@0 29314 var qn = Multiname.getQualifiedName(trait.name);
michael@0 29315 var value = object[qn];
michael@0 29316 (function (qn, value) {
michael@0 29317 Object.defineProperty(object, qn, {
michael@0 29318 configurable: false,
michael@0 29319 enumerable: false,
michael@0 29320 get: function () {
michael@0 29321 return value;
michael@0 29322 },
michael@0 29323 set: function () {
michael@0 29324 throwErrorFromVM(Shumway.AVM2.Runtime.AVM2.currentDomain(), 'ReferenceError', 'Illegal write to read-only property ' + qn + '.', 0);
michael@0 29325 }
michael@0 29326 });
michael@0 29327 }(qn, value));
michael@0 29328 }
michael@0 29329 }
michael@0 29330 }
michael@0 29331 Runtime.sealConstantTraits = sealConstantTraits;
michael@0 29332 function applyType(domain, factory, types) {
michael@0 29333 var factoryClassName = factory.classInfo.instanceInfo.name.name;
michael@0 29334 if (factoryClassName === 'Vector') {
michael@0 29335 true;
michael@0 29336 var type = types[0];
michael@0 29337 var typeClassName;
michael@0 29338 if (!Shumway.isNullOrUndefined(type)) {
michael@0 29339 typeClassName = type.classInfo.instanceInfo.name.name.toLowerCase();
michael@0 29340 switch (typeClassName) {
michael@0 29341 case 'int':
michael@0 29342 case 'uint':
michael@0 29343 case 'double':
michael@0 29344 case 'object':
michael@0 29345 return domain.getClass('packageInternal __AS3__.vec.Vector$' + typeClassName);
michael@0 29346 }
michael@0 29347 }
michael@0 29348 return domain.getClass('packageInternal __AS3__.vec.Vector$object').applyType(type);
michael@0 29349 } else {
michael@0 29350 return Shumway.Debug.notImplemented(factoryClassName);
michael@0 29351 }
michael@0 29352 }
michael@0 29353 Runtime.applyType = applyType;
michael@0 29354 }(AVM2.Runtime || (AVM2.Runtime = {})));
michael@0 29355 var Runtime = AVM2.Runtime;
michael@0 29356 }(Shumway.AVM2 || (Shumway.AVM2 = {})));
michael@0 29357 var AVM2 = Shumway.AVM2;
michael@0 29358 }(Shumway || (Shumway = {})));
michael@0 29359 var CC = Shumway.AVM2.Runtime.CODE_CACHE;
michael@0 29360 var VM_LENGTH = Shumway.AVM2.Runtime.VM_LENGTH;
michael@0 29361 var VM_IS_PROXY = Shumway.AVM2.Runtime.VM_IS_PROXY;
michael@0 29362 var VM_CALL_PROXY = Shumway.AVM2.Runtime.VM_CALL_PROXY;
michael@0 29363 var VM_NATIVE_BUILTIN_ORIGINALS = Shumway.AVM2.Runtime.VM_NATIVE_BUILTIN_ORIGINALS;
michael@0 29364 var VM_OPEN_METHOD_PREFIX = 'm';
michael@0 29365 var VM_OPEN_SET_METHOD_PREFIX = 's';
michael@0 29366 var VM_OPEN_GET_METHOD_PREFIX = 'g';
michael@0 29367 var SAVED_SCOPE_NAME = '$SS';
michael@0 29368 var originalStringReplace = String.prototype.replace;
michael@0 29369 XRegExp.install({
michael@0 29370 natives: true
michael@0 29371 });
michael@0 29372 var callWriter = new IndentingWriter(false, function (str) {
michael@0 29373 print(str);
michael@0 29374 });
michael@0 29375 var objectIDs = 0;
michael@0 29376 var OBJECT_NAME = 'Object Name';
michael@0 29377 function objectConstantName(object) {
michael@0 29378 true;
michael@0 29379 if (object.hasOwnProperty(OBJECT_NAME)) {
michael@0 29380 return object[OBJECT_NAME];
michael@0 29381 }
michael@0 29382 if (object instanceof LazyInitializer) {
michael@0 29383 return object.getName();
michael@0 29384 }
michael@0 29385 var name, id = objectIDs++;
michael@0 29386 if (object instanceof Global) {
michael@0 29387 name = '$G' + id;
michael@0 29388 } else if (object instanceof Multiname) {
michael@0 29389 name = '$M' + id;
michael@0 29390 } else if (isClass(object)) {
michael@0 29391 name = '$C' + id;
michael@0 29392 } else {
michael@0 29393 name = '$O' + id;
michael@0 29394 }
michael@0 29395 Object.defineProperty(object, OBJECT_NAME, {
michael@0 29396 value: name,
michael@0 29397 writable: false,
michael@0 29398 enumerable: false
michael@0 29399 });
michael@0 29400 jsGlobal[name] = object;
michael@0 29401 return name;
michael@0 29402 }
michael@0 29403 var isClass = Shumway.AVM2.Runtime.isClass;
michael@0 29404 var isTrampoline = Shumway.AVM2.Runtime.isTrampoline;
michael@0 29405 var isMemoizer = Shumway.AVM2.Runtime.isMemoizer;
michael@0 29406 var LazyInitializer = Shumway.AVM2.Runtime.LazyInitializer;
michael@0 29407 var getNamespaceResolutionMap = Shumway.AVM2.Runtime.getNamespaceResolutionMap;
michael@0 29408 var resolveMultinameProperty = Shumway.AVM2.Runtime.resolveMultinameProperty;
michael@0 29409 var asGetPublicProperty = Shumway.AVM2.Runtime.asGetPublicProperty;
michael@0 29410 var asGetProperty = Shumway.AVM2.Runtime.asGetProperty;
michael@0 29411 var asGetPropertyLikelyNumeric = Shumway.AVM2.Runtime.asGetPropertyLikelyNumeric;
michael@0 29412 var asGetResolvedStringProperty = Shumway.AVM2.Runtime.asGetResolvedStringProperty;
michael@0 29413 var asCallResolvedStringProperty = Shumway.AVM2.Runtime.asCallResolvedStringProperty;
michael@0 29414 var asGetResolvedStringPropertyFallback = Shumway.AVM2.Runtime.asGetResolvedStringPropertyFallback;
michael@0 29415 var asSetPublicProperty = Shumway.AVM2.Runtime.asSetPublicProperty;
michael@0 29416 var asSetProperty = Shumway.AVM2.Runtime.asSetProperty;
michael@0 29417 var asSetPropertyLikelyNumeric = Shumway.AVM2.Runtime.asSetPropertyLikelyNumeric;
michael@0 29418 var asDefinePublicProperty = Shumway.AVM2.Runtime.asDefinePublicProperty;
michael@0 29419 var asDefineProperty = Shumway.AVM2.Runtime.asDefineProperty;
michael@0 29420 var asCallPublicProperty = Shumway.AVM2.Runtime.asCallPublicProperty;
michael@0 29421 var asCallProperty = Shumway.AVM2.Runtime.asCallProperty;
michael@0 29422 var asCallSuper = Shumway.AVM2.Runtime.asCallSuper;
michael@0 29423 var asSetSuper = Shumway.AVM2.Runtime.asSetSuper;
michael@0 29424 var asGetSuper = Shumway.AVM2.Runtime.asGetSuper;
michael@0 29425 var construct = Shumway.AVM2.Runtime.construct;
michael@0 29426 var asConstructProperty = Shumway.AVM2.Runtime.asConstructProperty;
michael@0 29427 var asHasProperty = Shumway.AVM2.Runtime.asHasProperty;
michael@0 29428 var asDeleteProperty = Shumway.AVM2.Runtime.asDeleteProperty;
michael@0 29429 var asGetNumericProperty = Shumway.AVM2.Runtime.asGetNumericProperty;
michael@0 29430 var asSetNumericProperty = Shumway.AVM2.Runtime.asSetNumericProperty;
michael@0 29431 var asGetDescendants = Shumway.AVM2.Runtime.asGetDescendants;
michael@0 29432 var asNextNameIndex = Shumway.AVM2.Runtime.asNextNameIndex;
michael@0 29433 var asNextName = Shumway.AVM2.Runtime.asNextName;
michael@0 29434 var asNextValue = Shumway.AVM2.Runtime.asNextValue;
michael@0 29435 var asGetEnumerableKeys = Shumway.AVM2.Runtime.asGetEnumerableKeys;
michael@0 29436 var initializeGlobalObject = Shumway.AVM2.Runtime.initializeGlobalObject;
michael@0 29437 initializeGlobalObject(jsGlobal);
michael@0 29438 var asTypeOf = Shumway.AVM2.Runtime.asTypeOf;
michael@0 29439 var publicizeProperties = Shumway.AVM2.Runtime.publicizeProperties;
michael@0 29440 var asGetSlot = Shumway.AVM2.Runtime.asGetSlot;
michael@0 29441 var asSetSlot = Shumway.AVM2.Runtime.asSetSlot;
michael@0 29442 var asHasNext2 = Shumway.AVM2.Runtime.asHasNext2;
michael@0 29443 var getDescendants = Shumway.AVM2.Runtime.getDescendants;
michael@0 29444 var checkFilter = Shumway.AVM2.Runtime.checkFilter;
michael@0 29445 var ActivationInfo = Shumway.AVM2.Runtime.ActivationInfo;
michael@0 29446 var ScopeStack = Shumway.AVM2.Runtime.ScopeStack;
michael@0 29447 var Scope = Shumway.AVM2.Runtime.Scope;
michael@0 29448 var bindFreeMethodScope = Shumway.AVM2.Runtime.bindFreeMethodScope;
michael@0 29449 var nameInTraits = Shumway.AVM2.Runtime.nameInTraits;
michael@0 29450 function resolveMultiname(object, mn, traitsOnly) {
michael@0 29451 return object.resolveMultinameProperty(mn.namespaces, mn.name, mn.flags);
michael@0 29452 }
michael@0 29453 var sliceArguments = Shumway.AVM2.Runtime.sliceArguments;
michael@0 29454 var nonProxyingHasProperty = Shumway.AVM2.Runtime.nonProxyingHasProperty;
michael@0 29455 var forEachPublicProperty = Shumway.AVM2.Runtime.forEachPublicProperty;
michael@0 29456 var wrapJSObject = Shumway.AVM2.Runtime.wrapJSObject;
michael@0 29457 var asCreateActivation = Shumway.AVM2.Runtime.asCreateActivation;
michael@0 29458 var CatchScopeObject = Shumway.AVM2.Runtime.CatchScopeObject;
michael@0 29459 var Global = Shumway.AVM2.Runtime.Global;
michael@0 29460 var canCompile = Shumway.AVM2.Runtime.canCompile;
michael@0 29461 var shouldCompile = Shumway.AVM2.Runtime.shouldCompile;
michael@0 29462 var forceCompile = Shumway.AVM2.Runtime.forceCompile;
michael@0 29463 var createInterpretedFunction = Shumway.AVM2.Runtime.createInterpretedFunction;
michael@0 29464 var debugName = Shumway.AVM2.Runtime.debugName;
michael@0 29465 var createCompiledFunction = Shumway.AVM2.Runtime.createCompiledFunction;
michael@0 29466 var getMethodOverrideKey = Shumway.AVM2.Runtime.getMethodOverrideKey;
michael@0 29467 var checkMethodOverrides = Shumway.AVM2.Runtime.checkMethodOverrides;
michael@0 29468 var makeTrampoline = Shumway.AVM2.Runtime.makeTrampoline;
michael@0 29469 var makeMemoizer = Shumway.AVM2.Runtime.makeMemoizer;
michael@0 29470 var createFunction = Shumway.AVM2.Runtime.createFunction;
michael@0 29471 var ensureFunctionIsInitialized = Shumway.AVM2.Runtime.ensureFunctionIsInitialized;
michael@0 29472 var getTraitFunction = Shumway.AVM2.Runtime.getTraitFunction;
michael@0 29473 var createClass = Shumway.AVM2.Runtime.createClass;
michael@0 29474 var sealConstantTraits = Shumway.AVM2.Runtime.sealConstantTraits;
michael@0 29475 var applyType = Shumway.AVM2.Runtime.applyType;
michael@0 29476 var throwError = Shumway.AVM2.Runtime.throwError;
michael@0 29477 var throwErrorFromVM = Shumway.AVM2.Runtime.throwErrorFromVM;
michael@0 29478 var translateError = Shumway.AVM2.Runtime.translateError;
michael@0 29479 var asIsInstanceOf = Shumway.AVM2.Runtime.asIsInstanceOf;
michael@0 29480 var asIsType = Shumway.AVM2.Runtime.asIsType;
michael@0 29481 var asAsType = Shumway.AVM2.Runtime.asAsType;
michael@0 29482 var asCoerceByMultiname = Shumway.AVM2.Runtime.asCoerceByMultiname;
michael@0 29483 var asCoerce = Shumway.AVM2.Runtime.asCoerce;
michael@0 29484 var asCoerceString = Shumway.AVM2.Runtime.asCoerceString;
michael@0 29485 var asCoerceInt = Shumway.AVM2.Runtime.asCoerceInt;
michael@0 29486 var asCoerceUint = Shumway.AVM2.Runtime.asCoerceUint;
michael@0 29487 var asCoerceNumber = Shumway.AVM2.Runtime.asCoerceNumber;
michael@0 29488 var asCoerceBoolean = Shumway.AVM2.Runtime.asCoerceBoolean;
michael@0 29489 var asCoerceObject = Shumway.AVM2.Runtime.asCoerceObject;
michael@0 29490 var asDefaultCompareFunction = Shumway.AVM2.Runtime.asDefaultCompareFunction;
michael@0 29491 var asCompare = Shumway.AVM2.Runtime.asCompare;
michael@0 29492 var asAdd = Shumway.AVM2.Runtime.asAdd;
michael@0 29493 var GlobalMultinameResolver = Shumway.AVM2.Runtime.GlobalMultinameResolver;
michael@0 29494 var Shumway;
michael@0 29495 (function (Shumway) {
michael@0 29496 (function (AVM2) {
michael@0 29497 (function (Runtime) {
michael@0 29498 Shumway.AVM2.Runtime.VM_METHOD_OVERRIDES['static mochi.as3.MochiServices::connect'] = function () {
michael@0 29499 return;
michael@0 29500 };
michael@0 29501 Shumway.AVM2.Runtime.VM_METHOD_OVERRIDES['static MochiBot::track'] = function () {
michael@0 29502 return;
michael@0 29503 };
michael@0 29504 Shumway.AVM2.Runtime.VM_METHOD_OVERRIDES['com.midasplayer.debug.DebugLog::trace'] = function (msg) {
michael@0 29505 log(msg);
michael@0 29506 };
michael@0 29507 Shumway.AVM2.Runtime.VM_METHOD_OVERRIDES['com.midasplayer.engine.comm.DebugGameComm::getGameData'] = function () {
michael@0 29508 return '<gamedata randomseed="554884453" version="1">\n<musicOn>true</musicOn>\n<soundOn>true</soundOn>\n<isShortGame>false</isShortGame>\n<booster_1>0</booster_1>\n<booster_2>0</booster_2>\n<booster_3>0</booster_3>\n<booster_4>0</booster_4>\n<booster_5>0</booster_5>\n<bestScore>0</bestScore>\n<bestChain>0</bestChain>\n<bestLevel>0</bestLevel>\n<bestCrushed>0</bestCrushed>\n<bestMixed>0</bestMixed>\n<text id="outro.crushed">Candy crushed</text>\n<text id="outro.bestever">best ever</text>\n<text id="outro.trophy.two">scored {0} in one game</text>\n<text id="outro.combo_color_color">All Clear Created</text>\n<text id="outro.trophy.one">crushed {0} candy in one game</text>\n<text id="outro.score">Score</text>\n<text id="outro.opengame">Please register to play the full game</text>\n<text id="outro.chain">Longest chain</text>\n<text id="outro.time">Game ends in {0} seconds</text>\n<text id="outro.combo_color_line">Super Stripes Created</text>\n<text id="game.nomoves">No more moves!</text>\n<text id="outro.combo_wrapper_line">Mega-Candy Created</text>\n<text id="intro.time">Game starts in {0} seconds</text>\n<text id="outro.now">now</text>\n<text id="outro.level">Level reached</text>\n<text id="outro.title">Game Over</text>\n<text id="intro.info1">Match 3 Candy of the same colour to crush them. Matching 4 or 5 in different formations generates special sweets that are extra tasty.</text>\n<text id="intro.info2">You can also combine the special sweets for additional effects by switching them with each other. Try these combinations for a taste you will not forget: </text>\n<text id="outro.combo_color_wrapper">Double Colour Bombs Created</text>\n<text id="outro.trophy.three">made {0} combined candy in one game</text>\n<text id="intro.title">Play like this:</text>\n</gamedata>';
michael@0 29509 };
michael@0 29510 Shumway.AVM2.Runtime.VM_METHOD_OVERRIDES['com.antkarlov.Preloader::com.antkarlov:Preloader.isUrl'] = function () {
michael@0 29511 return true;
michael@0 29512 };
michael@0 29513 Shumway.AVM2.Runtime.VM_METHOD_OVERRIDES['static com.demonsters.debugger.MonsterDebugger::initialize'] = function () {
michael@0 29514 };
michael@0 29515 Shumway.AVM2.Runtime.VM_METHOD_OVERRIDES['com.spilgames.api.core.tracking.TrackConfig::getTrackers'] = function () {
michael@0 29516 return [];
michael@0 29517 };
michael@0 29518 Shumway.AVM2.Runtime.VM_METHOD_OVERRIDES['com.spilgames.api.components.TextFields.AutoFitTextFieldEx::com.spilgames.api.components.TextFields:AutoFitTextFieldEx.updateProperties'] = Shumway.AVM2.Runtime.VM_METHOD_OVERRIDES['com.spilgames.api.components.TextFields.AutoFitTextFieldEx::com.spilgames.api.components.TextFields:AutoFitTextFieldEx.updateTextSize'] = function () {
michael@0 29519 };
michael@0 29520 }(AVM2.Runtime || (AVM2.Runtime = {})));
michael@0 29521 var Runtime = AVM2.Runtime;
michael@0 29522 }(Shumway.AVM2 || (Shumway.AVM2 = {})));
michael@0 29523 var AVM2 = Shumway.AVM2;
michael@0 29524 }(Shumway || (Shumway = {})));
michael@0 29525 var checkArguments = true;
michael@0 29526 function asCheckVectorSetNumericProperty(i, length, fixed) {
michael@0 29527 if (i < 0 || i > length || i === length && fixed || !isNumeric(i)) {
michael@0 29528 throwError('RangeError', Errors.OutOfRangeError, i, length);
michael@0 29529 }
michael@0 29530 }
michael@0 29531 function asCheckVectorGetNumericProperty(i, length) {
michael@0 29532 if (i < 0 || i >= length || !isNumeric(i)) {
michael@0 29533 throwError('RangeError', Errors.OutOfRangeError, i, length);
michael@0 29534 }
michael@0 29535 }
michael@0 29536 var TypedArrayVector = function () {
michael@0 29537 var EXTRA_CAPACITY = 4;
michael@0 29538 var INITIAL_CAPACITY = 10;
michael@0 29539 var DEFAULT_VALUE = 0;
michael@0 29540 function vector(length, fixed) {
michael@0 29541 length = length | 0;
michael@0 29542 this._fixed = !(!fixed);
michael@0 29543 this._buffer = new Int32Array(Math.max(INITIAL_CAPACITY, length + EXTRA_CAPACITY));
michael@0 29544 this._offset = 0;
michael@0 29545 this._length = length;
michael@0 29546 }
michael@0 29547 vector.callable = function (object) {
michael@0 29548 if (object instanceof vector) {
michael@0 29549 return object;
michael@0 29550 }
michael@0 29551 var length = object.asGetProperty(undefined, 'length');
michael@0 29552 if (length !== undefined) {
michael@0 29553 var v = new vector(length, false);
michael@0 29554 for (var i = 0; i < length; i++) {
michael@0 29555 v.asSetNumericProperty(i, object.asGetPublicProperty(i));
michael@0 29556 }
michael@0 29557 return v;
michael@0 29558 }
michael@0 29559 unexpected();
michael@0 29560 };
michael@0 29561 vector.prototype.internalToString = function () {
michael@0 29562 var str = '';
michael@0 29563 var start = this._offset;
michael@0 29564 var end = start + this._length;
michael@0 29565 for (var i = 0; i < this._buffer.length; i++) {
michael@0 29566 if (i === start) {
michael@0 29567 str += '[';
michael@0 29568 }
michael@0 29569 if (i === end) {
michael@0 29570 str += ']';
michael@0 29571 }
michael@0 29572 str += this._buffer[i];
michael@0 29573 if (i < this._buffer.length - 1) {
michael@0 29574 str += ',';
michael@0 29575 }
michael@0 29576 }
michael@0 29577 if (this._offset + this._length === this._buffer.length) {
michael@0 29578 str += ']';
michael@0 29579 }
michael@0 29580 return str + ': offset: ' + this._offset + ', length: ' + this._length + ', capacity: ' + this._buffer.length;
michael@0 29581 };
michael@0 29582 vector.prototype.toString = function () {
michael@0 29583 var str = '';
michael@0 29584 for (var i = 0; i < this._length; i++) {
michael@0 29585 str += this._buffer[this._offset + i];
michael@0 29586 if (i < this._length - 1) {
michael@0 29587 str += ',';
michael@0 29588 }
michael@0 29589 }
michael@0 29590 return str;
michael@0 29591 };
michael@0 29592 vector.prototype._view = function () {
michael@0 29593 return this._buffer.subarray(this._offset, this._offset + this._length);
michael@0 29594 };
michael@0 29595 vector.prototype._ensureCapacity = function (length) {
michael@0 29596 var minCapacity = this._offset + length;
michael@0 29597 if (minCapacity < this._buffer.length) {
michael@0 29598 return;
michael@0 29599 }
michael@0 29600 if (length <= this._buffer.length) {
michael@0 29601 var offset = this._buffer.length - length >> 2;
michael@0 29602 this._buffer.set(this._view(), offset);
michael@0 29603 this._offset = offset;
michael@0 29604 return;
michael@0 29605 }
michael@0 29606 var oldCapacity = this._buffer.length;
michael@0 29607 var newCapacity = oldCapacity * 3 >> 2;
michael@0 29608 if (newCapacity < minCapacity) {
michael@0 29609 newCapacity = minCapacity;
michael@0 29610 }
michael@0 29611 var buffer = new Int32Array(newCapacity);
michael@0 29612 buffer.set(this._buffer, 0);
michael@0 29613 this._buffer = buffer;
michael@0 29614 };
michael@0 29615 vector.prototype.concat = function () {
michael@0 29616 notImplemented('TypedArrayVector.concat');
michael@0 29617 };
michael@0 29618 vector.prototype.every = function (callback, thisObject) {
michael@0 29619 for (var i = 0; i < this._length; i++) {
michael@0 29620 if (!callback.call(thisObject, this.asGetNumericProperty(i), i, this)) {
michael@0 29621 return false;
michael@0 29622 }
michael@0 29623 }
michael@0 29624 return true;
michael@0 29625 };
michael@0 29626 vector.prototype.filter = function (callback, thisObject) {
michael@0 29627 var v = new vector();
michael@0 29628 for (var i = 0; i < this._length; i++) {
michael@0 29629 if (callback.call(thisObject, this.asGetNumericProperty(i), i, this)) {
michael@0 29630 v.push(this.asGetNumericProperty(i));
michael@0 29631 }
michael@0 29632 }
michael@0 29633 return v;
michael@0 29634 };
michael@0 29635 vector.prototype.some = function (callback, thisObject) {
michael@0 29636 if (arguments.length !== 2) {
michael@0 29637 throwError('ArgumentError', Errors.WrongArgumentCountError);
michael@0 29638 } else if (!isFunction(callback)) {
michael@0 29639 throwError('ArgumentError', Errors.CheckTypeFailedError);
michael@0 29640 }
michael@0 29641 for (var i = 0; i < this._length; i++) {
michael@0 29642 if (callback.call(thisObject, this.asGetNumericProperty(i), i, this)) {
michael@0 29643 return true;
michael@0 29644 }
michael@0 29645 }
michael@0 29646 return false;
michael@0 29647 };
michael@0 29648 vector.prototype.forEach = function (callback, thisObject) {
michael@0 29649 for (var i = 0; i < this._length; i++) {
michael@0 29650 callback.call(thisObject, this.asGetNumericProperty(i), i, this);
michael@0 29651 }
michael@0 29652 };
michael@0 29653 vector.prototype.join = function (sep) {
michael@0 29654 notImplemented('TypedArrayVector.join');
michael@0 29655 };
michael@0 29656 vector.prototype.indexOf = function (searchElement, fromIndex) {
michael@0 29657 notImplemented('TypedArrayVector.indexOf');
michael@0 29658 };
michael@0 29659 vector.prototype.lastIndexOf = function (searchElement, fromIndex) {
michael@0 29660 notImplemented('TypedArrayVector.lastIndexOf');
michael@0 29661 };
michael@0 29662 vector.prototype.map = function (callback, thisObject) {
michael@0 29663 if (!isFunction(callback)) {
michael@0 29664 throwError('ArgumentError', Errors.CheckTypeFailedError);
michael@0 29665 }
michael@0 29666 var v = new vector();
michael@0 29667 for (var i = 0; i < this._length; i++) {
michael@0 29668 v.push(callback.call(thisObject, this.asGetNumericProperty(i), i, this));
michael@0 29669 }
michael@0 29670 return v;
michael@0 29671 };
michael@0 29672 vector.prototype.push = function () {
michael@0 29673 this._checkFixed();
michael@0 29674 this._ensureCapacity(this._length + arguments.length);
michael@0 29675 for (var i = 0; i < arguments.length; i++) {
michael@0 29676 this._buffer[this._offset + this._length++] = arguments[i];
michael@0 29677 }
michael@0 29678 };
michael@0 29679 vector.prototype.pop = function () {
michael@0 29680 this._checkFixed();
michael@0 29681 if (this._length === 0) {
michael@0 29682 return DEFAULT_VALUE;
michael@0 29683 }
michael@0 29684 this._length--;
michael@0 29685 return this._buffer[this._offset + this._length];
michael@0 29686 };
michael@0 29687 vector.prototype.reverse = function () {
michael@0 29688 var l = this._offset;
michael@0 29689 var r = this._offset + this._length - 1;
michael@0 29690 var b = this._buffer;
michael@0 29691 while (l < r) {
michael@0 29692 var t = b[l];
michael@0 29693 b[l] = b[r];
michael@0 29694 b[r] = t;
michael@0 29695 l++;
michael@0 29696 r--;
michael@0 29697 }
michael@0 29698 };
michael@0 29699 vector.CASEINSENSITIVE = 1;
michael@0 29700 vector.DESCENDING = 2;
michael@0 29701 vector.UNIQUESORT = 4;
michael@0 29702 vector.RETURNINDEXEDARRAY = 8;
michael@0 29703 vector.NUMERIC = 16;
michael@0 29704 function defaultCompareFunction(a, b) {
michael@0 29705 return String(a).localeCompare(String(b));
michael@0 29706 }
michael@0 29707 function compare(a, b, options, compareFunction) {
michael@0 29708 assertNotImplemented(!(options & vector.CASEINSENSITIVE), 'CASEINSENSITIVE');
michael@0 29709 assertNotImplemented(!(options & vector.UNIQUESORT), 'UNIQUESORT');
michael@0 29710 assertNotImplemented(!(options & vector.RETURNINDEXEDARRAY), 'RETURNINDEXEDARRAY');
michael@0 29711 var result = 0;
michael@0 29712 if (!compareFunction) {
michael@0 29713 compareFunction = defaultCompareFunction;
michael@0 29714 }
michael@0 29715 if (options & vector.NUMERIC) {
michael@0 29716 a = toNumber(a);
michael@0 29717 b = toNumber(b);
michael@0 29718 result = a < b ? -1 : a > b ? 1 : 0;
michael@0 29719 } else {
michael@0 29720 result = compareFunction(a, b);
michael@0 29721 }
michael@0 29722 if (options & vector.DESCENDING) {
michael@0 29723 result *= -1;
michael@0 29724 }
michael@0 29725 return result;
michael@0 29726 }
michael@0 29727 function _sort(a) {
michael@0 29728 var stack = [];
michael@0 29729 var sp = -1;
michael@0 29730 var l = 0;
michael@0 29731 var r = a.length - 1;
michael@0 29732 var i, j, swap, temp;
michael@0 29733 while (true) {
michael@0 29734 if (r - l <= 100) {
michael@0 29735 for (j = l + 1; j <= r; j++) {
michael@0 29736 swap = a[j];
michael@0 29737 i = j - 1;
michael@0 29738 while (i >= l && a[i] > swap) {
michael@0 29739 a[i + 1] = a[i--];
michael@0 29740 }
michael@0 29741 a[i + 1] = swap;
michael@0 29742 }
michael@0 29743 if (sp == -1) {
michael@0 29744 break;
michael@0 29745 }
michael@0 29746 r = stack[sp--];
michael@0 29747 l = stack[sp--];
michael@0 29748 } else {
michael@0 29749 var median = l + r >> 1;
michael@0 29750 i = l + 1;
michael@0 29751 j = r;
michael@0 29752 swap = a[median];
michael@0 29753 a[median] = a[i];
michael@0 29754 a[i] = swap;
michael@0 29755 if (a[l] > a[r]) {
michael@0 29756 swap = a[l];
michael@0 29757 a[l] = a[r];
michael@0 29758 a[r] = swap;
michael@0 29759 }
michael@0 29760 if (a[i] > a[r]) {
michael@0 29761 swap = a[i];
michael@0 29762 a[i] = a[r];
michael@0 29763 a[r] = swap;
michael@0 29764 }
michael@0 29765 if (a[l] > a[i]) {
michael@0 29766 swap = a[l];
michael@0 29767 a[l] = a[i];
michael@0 29768 a[i] = swap;
michael@0 29769 }
michael@0 29770 temp = a[i];
michael@0 29771 while (true) {
michael@0 29772 do {
michael@0 29773 i++;
michael@0 29774 } while (a[i] < temp);
michael@0 29775 do {
michael@0 29776 j--;
michael@0 29777 } while (a[j] > temp);
michael@0 29778 if (j < i) {
michael@0 29779 break;
michael@0 29780 }
michael@0 29781 swap = a[i];
michael@0 29782 a[i] = a[j];
michael@0 29783 a[j] = swap;
michael@0 29784 }
michael@0 29785 a[l + 1] = a[j];
michael@0 29786 a[j] = temp;
michael@0 29787 if (r - i + 1 >= j - l) {
michael@0 29788 stack[++sp] = i;
michael@0 29789 stack[++sp] = r;
michael@0 29790 r = j - 1;
michael@0 29791 } else {
michael@0 29792 stack[++sp] = l;
michael@0 29793 stack[++sp] = j - 1;
michael@0 29794 l = i;
michael@0 29795 }
michael@0 29796 }
michael@0 29797 }
michael@0 29798 return a;
michael@0 29799 }
michael@0 29800 vector.prototype._sortNumeric = function (descending) {
michael@0 29801 _sort(this._view());
michael@0 29802 if (descending) {
michael@0 29803 this.reverse();
michael@0 29804 }
michael@0 29805 };
michael@0 29806 vector.prototype.sort = function () {
michael@0 29807 if (arguments.length === 0) {
michael@0 29808 return Array.prototype.sort.call(this._view());
michael@0 29809 }
michael@0 29810 var compareFunction, options = 0;
michael@0 29811 if (arguments[0] instanceof Function) {
michael@0 29812 compareFunction = arguments[0];
michael@0 29813 } else if (isNumber(arguments[0])) {
michael@0 29814 options = arguments[0];
michael@0 29815 }
michael@0 29816 if (isNumber(arguments[1])) {
michael@0 29817 options = arguments[1];
michael@0 29818 }
michael@0 29819 if (options & TypedArrayVector.NUMERIC) {
michael@0 29820 return this._sortNumeric(options & vector.DESCENDING);
michael@0 29821 }
michael@0 29822 Array.prototype.sort.call(this._view(), function (a, b) {
michael@0 29823 return compare(a, b, options, compareFunction);
michael@0 29824 });
michael@0 29825 };
michael@0 29826 vector.prototype.asGetNumericProperty = function (i) {
michael@0 29827 checkArguments && asCheckVectorGetNumericProperty(i, this._length);
michael@0 29828 return this._buffer[this._offset + i];
michael@0 29829 };
michael@0 29830 vector.prototype.asSetNumericProperty = function (i, v) {
michael@0 29831 checkArguments && asCheckVectorSetNumericProperty(i, this._length, this._fixed);
michael@0 29832 if (i === this._length) {
michael@0 29833 this._ensureCapacity(this._length + 1);
michael@0 29834 this._length++;
michael@0 29835 }
michael@0 29836 this._buffer[this._offset + i] = v;
michael@0 29837 };
michael@0 29838 vector.prototype.shift = function () {
michael@0 29839 this._checkFixed();
michael@0 29840 if (this._length === 0) {
michael@0 29841 return 0;
michael@0 29842 }
michael@0 29843 this._length--;
michael@0 29844 return this._buffer[this._offset++];
michael@0 29845 };
michael@0 29846 vector.prototype._checkFixed = function () {
michael@0 29847 if (this._fixed) {
michael@0 29848 throwError('RangeError', Errors.VectorFixedError);
michael@0 29849 }
michael@0 29850 };
michael@0 29851 vector.prototype._slide = function (distance) {
michael@0 29852 this._buffer.set(this._view(), this._offset + distance);
michael@0 29853 this._offset += distance;
michael@0 29854 };
michael@0 29855 vector.prototype.unshift = function () {
michael@0 29856 this._checkFixed();
michael@0 29857 if (!arguments.length) {
michael@0 29858 return;
michael@0 29859 }
michael@0 29860 this._ensureCapacity(this._length + arguments.length);
michael@0 29861 this._slide(arguments.length);
michael@0 29862 this._offset -= arguments.length;
michael@0 29863 this._length += arguments.length;
michael@0 29864 for (var i = 0; i < arguments.length; i++) {
michael@0 29865 this._buffer[this._offset + i] = arguments[i];
michael@0 29866 }
michael@0 29867 };
michael@0 29868 vector.prototype.asGetEnumerableKeys = function () {
michael@0 29869 if (vector.prototype === this) {
michael@0 29870 return Object.prototype.asGetEnumerableKeys.call(this);
michael@0 29871 }
michael@0 29872 var keys = [];
michael@0 29873 for (var i = 0; i < this._length; i++) {
michael@0 29874 keys.push(i);
michael@0 29875 }
michael@0 29876 return keys;
michael@0 29877 };
michael@0 29878 vector.prototype.asHasProperty = function (namespaces, name, flags) {
michael@0 29879 if (vector.prototype === this || !isNumeric(name)) {
michael@0 29880 return Object.prototype.asHasProperty.call(this, namespaces, name, flags);
michael@0 29881 }
michael@0 29882 var index = toNumber(name);
michael@0 29883 return index >= 0 && index < this._length;
michael@0 29884 };
michael@0 29885 Object.defineProperty(vector.prototype, 'length', {
michael@0 29886 get: function () {
michael@0 29887 return this._length;
michael@0 29888 },
michael@0 29889 set: function (length) {
michael@0 29890 length = length >>> 0;
michael@0 29891 if (length > this._length) {
michael@0 29892 this._ensureCapacity(length);
michael@0 29893 for (var i = this._offset + this._length, j = this._offset + length; i < j; i++) {
michael@0 29894 this._buffer[i] = DEFAULT_VALUE;
michael@0 29895 }
michael@0 29896 }
michael@0 29897 this._length = length;
michael@0 29898 }
michael@0 29899 });
michael@0 29900 vector.prototype._spliceHelper = function (index, insertCount, deleteCount, args, offset) {
michael@0 29901 insertCount = clamp(insertCount, 0, args.length - offset);
michael@0 29902 deleteCount = clamp(deleteCount, 0, this._length - index);
michael@0 29903 this._ensureCapacity(this._length - deleteCount + insertCount);
michael@0 29904 var right = this._offset + index + deleteCount;
michael@0 29905 var slice = this._buffer.subarray(right, right + this._length - index - deleteCount);
michael@0 29906 this._buffer.set(slice, this._offset + index + insertCount);
michael@0 29907 this._length += insertCount - deleteCount;
michael@0 29908 for (var i = 0; i < insertCount; i++) {
michael@0 29909 this._buffer[this._offset + index + i] = args.asGetNumericProperty(offset + i);
michael@0 29910 }
michael@0 29911 };
michael@0 29912 vector.prototype.asGetEnumerableKeys = function () {
michael@0 29913 if (vector.prototype === this) {
michael@0 29914 return Object.prototype.asGetEnumerableKeys.call(this);
michael@0 29915 }
michael@0 29916 var keys = [];
michael@0 29917 for (var i = 0; i < this._length; i++) {
michael@0 29918 keys.push(i);
michael@0 29919 }
michael@0 29920 return keys;
michael@0 29921 };
michael@0 29922 return vector;
michael@0 29923 }();
michael@0 29924 var typedArrayVectorTemplate = 'var EXTRA_CAPACITY=4,INITIAL_CAPACITY=10,DEFAULT_VALUE=0;function vector(a,b){a|=0;this._fixed=!!b;this._buffer=new Int32Array(Math.max(INITIAL_CAPACITY,a+EXTRA_CAPACITY));this._offset=0;this._length=a}vector.callable=function(a){if(a instanceof vector)return a;var b=a.asGetProperty(void 0,"length");if(void 0!==b){for(var c=new vector(b,!1),d=0;d<b;d++)c.asSetNumericProperty(d,a.asGetPublicProperty(d));return c}unexpected()}; vector.prototype.internalToString=function(){for(var a="",b=this._offset,c=b+this._length,d=0;d<this._buffer.length;d++)d===b&&(a+="["),d===c&&(a+="]"),a+=this._buffer[d],d<this._buffer.length-1&&(a+=",");this._offset+this._length===this._buffer.length&&(a+="]");return a+": offset: "+this._offset+", length: "+this._length+", capacity: "+this._buffer.length};vector.prototype.toString=function(){for(var a="",b=0;b<this._length;b++)a+=this._buffer[this._offset+b],b<this._length-1&&(a+=",");return a}; vector.prototype._view=function(){return this._buffer.subarray(this._offset,this._offset+this._length)};vector.prototype._ensureCapacity=function(a){var b=this._offset+a;b<this._buffer.length||(a<=this._buffer.length?(b=this._buffer.length-a>>2,this._buffer.set(this._view(),b),this._offset=b):(a=3*this._buffer.length>>2,a<b&&(a=b),b=new Int32Array(a),b.set(this._buffer,0),this._buffer=b))}; vector.prototype.every=function(a,b){for(var c=0;c<this._length;c++)if(!a.call(b,this.asGetNumericProperty(c),c,this))return!1;return!0};vector.prototype.filter=function(a,b){for(var c=new vector,d=0;d<this._length;d++)a.call(b,this.asGetNumericProperty(d),d,this)&&c.push(this.asGetNumericProperty(d));return c}; vector.prototype.some=function(a,b){2!==arguments.length?throwError("ArgumentError",Errors.WrongArgumentCountError):isFunction(a)||throwError("ArgumentError",Errors.CheckTypeFailedError);for(var c=0;c<this._length;c++)if(a.call(b,this.asGetNumericProperty(c),c,this))return!0;return!1};vector.prototype.forEach=function(a,b){for(var c=0;c<this._length;c++)a.call(b,this.asGetNumericProperty(c),c,this)};vector.prototype.join=function(a){notImplemented("TypedArrayVector.join")}; vector.prototype.indexOf=function(a,b){notImplemented("TypedArrayVector.indexOf")};vector.prototype.lastIndexOf=function(a,b){notImplemented("TypedArrayVector.lastIndexOf")};vector.prototype.map=function(a,b){isFunction(a)||throwError("ArgumentError",Errors.CheckTypeFailedError);for(var c=new vector,d=0;d<this._length;d++)c.push(a.call(b,this.asGetNumericProperty(d),d,this));return c}; vector.prototype.push=function(){this._checkFixed();this._ensureCapacity(this._length+arguments.length);for(var a=0;a<arguments.length;a++)this._buffer[this._offset+this._length++]=arguments[a]};vector.prototype.pop=function(){this._checkFixed();if(0===this._length)return DEFAULT_VALUE;this._length--;return this._buffer[this._offset+this._length]};vector.prototype.reverse=function(){for(var a=this._offset,b=this._offset+this._length-1,c=this._buffer;a<b;){var d=c[a];c[a]=c[b];c[b]=d;a++;b--}}; vector.CASEINSENSITIVE=1;vector.DESCENDING=2;vector.UNIQUESORT=4;vector.RETURNINDEXEDARRAY=8;vector.NUMERIC=16;function defaultCompareFunction(a,b){return String(a).localeCompare(String(b))} function compare(a,b,c,d){assertNotImplemented(!(c&vector.CASEINSENSITIVE),"CASEINSENSITIVE");assertNotImplemented(!(c&vector.UNIQUESORT),"UNIQUESORT");assertNotImplemented(!(c&vector.RETURNINDEXEDARRAY),"RETURNINDEXEDARRAY");var f=0;d||(d=defaultCompareFunction);c&vector.NUMERIC?(a=toNumber(a),b=toNumber(b),f=a<b?-1:a>b?1:0):f=d(a,b);c&vector.DESCENDING&&(f*=-1);return f} function _sort(a){for(var b=[],c=-1,d=0,f=a.length-1,e,g,h,k;;)if(100>=f-d){for(g=d+1;g<=f;g++){h=a[g];for(e=g-1;e>=d&&a[e]>h;)a[e+1]=a[e--];a[e+1]=h}if(-1==c)break;f=b[c--];d=b[c--]}else{k=d+f>>1;e=d+1;g=f;h=a[k];a[k]=a[e];a[e]=h;a[d]>a[f]&&(h=a[d],a[d]=a[f],a[f]=h);a[e]>a[f]&&(h=a[e],a[e]=a[f],a[f]=h);a[d]>a[e]&&(h=a[d],a[d]=a[e],a[e]=h);for(k=a[e];;){do e++;while(a[e]<k);do g--;while(a[g]>k);if(g<e)break;h=a[e];a[e]=a[g];a[g]=h}a[d+1]=a[g];a[g]=k;f-e+1>=g-d?(b[++c]=e,b[++c]=f,f=g-1):(b[++c]=d, b[++c]=g-1,d=e)}return a}vector.prototype._sortNumeric=function(a){_sort(this._view());a&&this.reverse()};vector.prototype.sort=function(){if(0===arguments.length)return Array.prototype.sort.call(this._view());var a,b=0;arguments[0]instanceof Function?a=arguments[0]:isNumber(arguments[0])&&(b=arguments[0]);isNumber(arguments[1])&&(b=arguments[1]);if(b&TypedArrayVector.NUMERIC)return this._sortNumeric(b&vector.DESCENDING);Array.prototype.sort.call(this._view(),function(c,d){return compare(c,d,b,a)})}; vector.prototype.asGetNumericProperty=function(a){checkArguments&&asCheckVectorGetNumericProperty(a,this._length);return this._buffer[this._offset+a]};vector.prototype.asSetNumericProperty=function(a,b){checkArguments&&asCheckVectorSetNumericProperty(a,this._length,this._fixed);a===this._length&&(this._ensureCapacity(this._length+1),this._length++);this._buffer[this._offset+a]=b};vector.prototype.shift=function(){this._checkFixed();if(0===this._length)return 0;this._length--;return this._buffer[this._offset++]}; vector.prototype._checkFixed=function(){this._fixed&&throwError("RangeError",Errors.VectorFixedError)};vector.prototype._slide=function(a){this._buffer.set(this._view(),this._offset+a);this._offset+=a};vector.prototype.unshift=function(){this._checkFixed();if(arguments.length){this._ensureCapacity(this._length+arguments.length);this._slide(arguments.length);this._offset-=arguments.length;this._length+=arguments.length;for(var a=0;a<arguments.length;a++)this._buffer[this._offset+a]=arguments[a]}}; vector.prototype.asGetEnumerableKeys=function(){if(vector.prototype===this)return Object.prototype.asGetEnumerableKeys.call(this);for(var a=[],b=0;b<this._length;b++)a.push(b);return a};vector.prototype.asHasProperty=function(a,b,c){if(vector.prototype===this||!isNumeric(b))return Object.prototype.asHasProperty.call(this,a,b,c);a=toNumber(b);return 0<=a&&a<this._length}; Object.defineProperty(vector.prototype,"length",{get:function(){return this._length},set:function(a){a>>>=0;if(a>this._length){this._ensureCapacity(a);for(var b=this._offset+this._length,c=this._offset+a;b<c;b++)this._buffer[b]=DEFAULT_VALUE}this._length=a}}); vector.prototype._spliceHelper=function(a,b,c,d,f){debugger;b=clamp(b,0,d.length-f);c=clamp(c,0,this._length-a);this._ensureCapacity(this._length-c+b);var e=this._offset+a+c,e=this._buffer.subarray(e,e+this._length-a-c);this._buffer.set(e,this._offset+a+b);this._length+=b-c;for(c=0;c<b;c++)this._buffer[this._offset+a+c]=d.asGetNumericProperty(f+c)}; vector.prototype.asGetEnumerableKeys=function(){if(vector.prototype===this)return Object.prototype.asGetEnumerableKeys.call(this);for(var a=[],b=0;b<this._length;b++)a.push(b);return a};';
michael@0 29925 var Int32Vector = TypedArrayVector;
michael@0 29926 var Uint32Vector = new Function(originalStringReplace.call(typedArrayVectorTemplate, /Int32Array/g, 'Uint32Array') + ' return vector;')();
michael@0 29927 var Float64Vector = new Function(originalStringReplace.call(typedArrayVectorTemplate, /Int32Array/g, 'Float64Array') + ' return vector;')();
michael@0 29928 Int32Vector.prototype.asGetProperty = function (namespaces, name, flags) {
michael@0 29929 if (typeof name === 'number') {
michael@0 29930 return this.asGetNumericProperty(name);
michael@0 29931 }
michael@0 29932 return asGetProperty.call(this, namespaces, name, flags);
michael@0 29933 };
michael@0 29934 Int32Vector.prototype.asSetProperty = function (namespaces, name, flags, value) {
michael@0 29935 if (typeof name === 'number') {
michael@0 29936 this.asSetNumericProperty(name, value);
michael@0 29937 return;
michael@0 29938 }
michael@0 29939 return asSetProperty.call(this, namespaces, name, flags, value);
michael@0 29940 };
michael@0 29941 Uint32Vector.prototype.asGetProperty = function (namespaces, name, flags) {
michael@0 29942 if (typeof name === 'number') {
michael@0 29943 return this.asGetNumericProperty(name);
michael@0 29944 }
michael@0 29945 return asGetProperty.call(this, namespaces, name, flags);
michael@0 29946 };
michael@0 29947 Uint32Vector.prototype.asSetProperty = function (namespaces, name, flags, value) {
michael@0 29948 if (typeof name === 'number') {
michael@0 29949 this.asSetNumericProperty(name, value);
michael@0 29950 return;
michael@0 29951 }
michael@0 29952 return asSetProperty.call(this, namespaces, name, flags, value);
michael@0 29953 };
michael@0 29954 Float64Vector.prototype.asGetProperty = function (namespaces, name, flags) {
michael@0 29955 if (typeof name === 'number') {
michael@0 29956 return this.asGetNumericProperty(name);
michael@0 29957 }
michael@0 29958 return asGetProperty.call(this, namespaces, name, flags);
michael@0 29959 };
michael@0 29960 Float64Vector.prototype.asSetProperty = function (namespaces, name, flags, value) {
michael@0 29961 if (typeof name === 'number') {
michael@0 29962 this.asSetNumericProperty(name, value);
michael@0 29963 return;
michael@0 29964 }
michael@0 29965 return asSetProperty.call(this, namespaces, name, flags, value);
michael@0 29966 };
michael@0 29967 var GenericVector = function () {
michael@0 29968 function vector(length, fixed, type) {
michael@0 29969 length = length | 0;
michael@0 29970 this._fixed = !(!fixed);
michael@0 29971 this._buffer = new Array(length);
michael@0 29972 this._type = type;
michael@0 29973 this._defaultValue = type ? type.defaultValue : null;
michael@0 29974 this._fill(0, length, this._defaultValue);
michael@0 29975 }
michael@0 29976 vector.applyType = function applyType(type) {
michael@0 29977 function parameterizedVector(length, fixed) {
michael@0 29978 vector.call(this, length, fixed, type);
michael@0 29979 }
michael@0 29980 parameterizedVector.prototype = Object.create(vector.prototype);
michael@0 29981 parameterizedVector.callable = vector.callable;
michael@0 29982 return parameterizedVector;
michael@0 29983 };
michael@0 29984 vector.callable = function (object) {
michael@0 29985 if (object instanceof vector) {
michael@0 29986 return object;
michael@0 29987 }
michael@0 29988 var length = object.asGetProperty(undefined, 'length');
michael@0 29989 if (length !== undefined) {
michael@0 29990 var v = new vector(length, false);
michael@0 29991 for (var i = 0; i < length; i++) {
michael@0 29992 v.asSetNumericProperty(i, object.asGetPublicProperty(i));
michael@0 29993 }
michael@0 29994 return v;
michael@0 29995 }
michael@0 29996 unexpected();
michael@0 29997 };
michael@0 29998 vector.prototype._fill = function (index, length, value) {
michael@0 29999 for (var i = 0; i < length; i++) {
michael@0 30000 this._buffer[index + i] = value;
michael@0 30001 }
michael@0 30002 };
michael@0 30003 vector.prototype.toString = function () {
michael@0 30004 var str = '';
michael@0 30005 for (var i = 0; i < this._buffer.length; i++) {
michael@0 30006 str += this._buffer[i];
michael@0 30007 if (i < this._buffer.length - 1) {
michael@0 30008 str += ',';
michael@0 30009 }
michael@0 30010 }
michael@0 30011 return str;
michael@0 30012 };
michael@0 30013 vector.prototype.every = function (callback, thisObject) {
michael@0 30014 for (var i = 0; i < this._buffer.length; i++) {
michael@0 30015 if (!callback.call(thisObject, this.asGetNumericProperty(i), i, this)) {
michael@0 30016 return false;
michael@0 30017 }
michael@0 30018 }
michael@0 30019 return true;
michael@0 30020 };
michael@0 30021 vector.prototype.filter = function (callback, thisObject) {
michael@0 30022 var v = new vector();
michael@0 30023 for (var i = 0; i < this._buffer.length; i++) {
michael@0 30024 if (callback.call(thisObject, this.asGetNumericProperty(i), i, this)) {
michael@0 30025 v.push(this.asGetNumericProperty(i));
michael@0 30026 }
michael@0 30027 }
michael@0 30028 return v;
michael@0 30029 };
michael@0 30030 vector.prototype.some = function (callback, thisObject) {
michael@0 30031 if (arguments.length !== 2) {
michael@0 30032 throwError('ArgumentError', Errors.WrongArgumentCountError);
michael@0 30033 } else if (!isFunction(callback)) {
michael@0 30034 throwError('ArgumentError', Errors.CheckTypeFailedError);
michael@0 30035 }
michael@0 30036 for (var i = 0; i < this._buffer.length; i++) {
michael@0 30037 if (callback.call(thisObject, this.asGetNumericProperty(i), i, this)) {
michael@0 30038 return true;
michael@0 30039 }
michael@0 30040 }
michael@0 30041 return false;
michael@0 30042 };
michael@0 30043 vector.prototype.forEach = function (callback, thisObject) {
michael@0 30044 if (!isFunction(callback)) {
michael@0 30045 throwError('ArgumentError', Errors.CheckTypeFailedError);
michael@0 30046 }
michael@0 30047 for (var i = 0; i < this._buffer.length; i++) {
michael@0 30048 callback.call(thisObject, this.asGetNumericProperty(i), i, this);
michael@0 30049 }
michael@0 30050 };
michael@0 30051 vector.prototype.map = function (callback, thisObject) {
michael@0 30052 if (!isFunction(callback)) {
michael@0 30053 throwError('ArgumentError', Errors.CheckTypeFailedError);
michael@0 30054 }
michael@0 30055 var v = new vector();
michael@0 30056 for (var i = 0; i < this._buffer.length; i++) {
michael@0 30057 v.push(callback.call(thisObject, this.asGetNumericProperty(i), i, this));
michael@0 30058 }
michael@0 30059 return v;
michael@0 30060 };
michael@0 30061 vector.prototype.push = function () {
michael@0 30062 this._checkFixed();
michael@0 30063 for (var i = 0; i < arguments.length; i++) {
michael@0 30064 this._buffer.push(this._coerce(arguments[i]));
michael@0 30065 }
michael@0 30066 };
michael@0 30067 vector.prototype.pop = function () {
michael@0 30068 this._checkFixed();
michael@0 30069 if (this._buffer.length === 0) {
michael@0 30070 return undefined;
michael@0 30071 }
michael@0 30072 return this._buffer.pop();
michael@0 30073 };
michael@0 30074 vector.prototype.reverse = function () {
michael@0 30075 this._buffer.reverse();
michael@0 30076 };
michael@0 30077 vector.CASEINSENSITIVE = 1;
michael@0 30078 vector.DESCENDING = 2;
michael@0 30079 vector.UNIQUESORT = 4;
michael@0 30080 vector.RETURNINDEXEDARRAY = 8;
michael@0 30081 vector.NUMERIC = 16;
michael@0 30082 function defaultCompareFunction(a, b) {
michael@0 30083 return String(a).localeCompare(String(b));
michael@0 30084 }
michael@0 30085 function compare(a, b, options, compareFunction) {
michael@0 30086 assertNotImplemented(!(options & CASEINSENSITIVE), 'CASEINSENSITIVE');
michael@0 30087 assertNotImplemented(!(options & UNIQUESORT), 'UNIQUESORT');
michael@0 30088 assertNotImplemented(!(options & RETURNINDEXEDARRAY), 'RETURNINDEXEDARRAY');
michael@0 30089 var result = 0;
michael@0 30090 if (!compareFunction) {
michael@0 30091 compareFunction = defaultCompareFunction;
michael@0 30092 }
michael@0 30093 if (options & NUMERIC) {
michael@0 30094 a = toNumber(a);
michael@0 30095 b = toNumber(b);
michael@0 30096 result = a < b ? -1 : a > b ? 1 : 0;
michael@0 30097 } else {
michael@0 30098 result = compareFunction(a, b);
michael@0 30099 }
michael@0 30100 if (options & DESCENDING) {
michael@0 30101 result *= -1;
michael@0 30102 }
michael@0 30103 return result;
michael@0 30104 }
michael@0 30105 vector.prototype.sort = function (comparator) {
michael@0 30106 return this._buffer.sort(comparator);
michael@0 30107 };
michael@0 30108 vector.prototype.asGetNumericProperty = function (i) {
michael@0 30109 checkArguments && asCheckVectorGetNumericProperty(i, this._buffer.length);
michael@0 30110 return this._buffer[i];
michael@0 30111 };
michael@0 30112 vector.prototype._coerce = function (v) {
michael@0 30113 if (this._type) {
michael@0 30114 return this._type.coerce(v);
michael@0 30115 } else if (v === undefined) {
michael@0 30116 return null;
michael@0 30117 }
michael@0 30118 return v;
michael@0 30119 };
michael@0 30120 vector.prototype.asSetNumericProperty = function (i, v) {
michael@0 30121 checkArguments && asCheckVectorSetNumericProperty(i, this._buffer.length, this._fixed);
michael@0 30122 this._buffer[i] = this._coerce(v);
michael@0 30123 };
michael@0 30124 vector.prototype.shift = function () {
michael@0 30125 this._checkFixed();
michael@0 30126 if (this._buffer.length === 0) {
michael@0 30127 return undefined;
michael@0 30128 }
michael@0 30129 return this._buffer.shift();
michael@0 30130 };
michael@0 30131 vector.prototype._checkFixed = function () {
michael@0 30132 if (this._fixed) {
michael@0 30133 throwError('RangeError', Errors.VectorFixedError);
michael@0 30134 }
michael@0 30135 };
michael@0 30136 vector.prototype.unshift = function () {
michael@0 30137 if (!arguments.length) {
michael@0 30138 return;
michael@0 30139 }
michael@0 30140 this._checkFixed();
michael@0 30141 var items = [];
michael@0 30142 for (var i = 0; i < arguments.length; i++) {
michael@0 30143 items.push(this._coerce(arguments[i]));
michael@0 30144 }
michael@0 30145 this._buffer.unshift.apply(this._buffer, items);
michael@0 30146 };
michael@0 30147 Object.defineProperty(vector.prototype, 'length', {
michael@0 30148 get: function () {
michael@0 30149 return this._buffer.length;
michael@0 30150 },
michael@0 30151 set: function (length) {
michael@0 30152 length = length >>> 0;
michael@0 30153 if (length > this._buffer.length) {
michael@0 30154 for (var i = this._buffer.length; i < length; i++) {
michael@0 30155 this._buffer[i] = this._defaultValue;
michael@0 30156 }
michael@0 30157 } else {
michael@0 30158 this._buffer.length = length;
michael@0 30159 }
michael@0 30160 true;
michael@0 30161 }
michael@0 30162 });
michael@0 30163 vector.prototype._spliceHelper = function (index, insertCount, deleteCount, args, offset) {
michael@0 30164 insertCount = clamp(insertCount, 0, args.length - offset);
michael@0 30165 deleteCount = clamp(deleteCount, 0, this._buffer.length - index);
michael@0 30166 var items = [];
michael@0 30167 for (var i = 0; i < insertCount; i++) {
michael@0 30168 items.push(this._coerce(args.asGetNumericProperty(offset + i)));
michael@0 30169 }
michael@0 30170 this._buffer.splice.apply(this._buffer, [
michael@0 30171 index,
michael@0 30172 deleteCount
michael@0 30173 ].concat(items));
michael@0 30174 };
michael@0 30175 vector.prototype.asGetEnumerableKeys = function () {
michael@0 30176 if (vector.prototype === this) {
michael@0 30177 return Object.prototype.asGetEnumerableKeys.call(this);
michael@0 30178 }
michael@0 30179 var keys = [];
michael@0 30180 for (var i = 0; i < this._buffer.length; i++) {
michael@0 30181 keys.push(i);
michael@0 30182 }
michael@0 30183 return keys;
michael@0 30184 };
michael@0 30185 vector.prototype.asHasProperty = function (namespaces, name, flags) {
michael@0 30186 if (vector.prototype === this || !isNumeric(name)) {
michael@0 30187 return Object.prototype.asHasProperty.call(this, namespaces, name, flags);
michael@0 30188 }
michael@0 30189 var index = toNumber(name);
michael@0 30190 return index >= 0 && index < this._buffer.length;
michael@0 30191 };
michael@0 30192 return vector;
michael@0 30193 }();
michael@0 30194 GenericVector.prototype.asGetProperty = function (namespaces, name, flags) {
michael@0 30195 if (typeof name === 'number') {
michael@0 30196 return this.asGetNumericProperty(name);
michael@0 30197 }
michael@0 30198 return asGetProperty.call(this, namespaces, name, flags);
michael@0 30199 };
michael@0 30200 GenericVector.prototype.asSetProperty = function (namespaces, name, flags, value) {
michael@0 30201 if (typeof name === 'number') {
michael@0 30202 this.asSetNumericProperty(name, value);
michael@0 30203 return;
michael@0 30204 }
michael@0 30205 return asSetProperty.call(this, namespaces, name, flags, value);
michael@0 30206 };
michael@0 30207 function arraySort(o, args) {
michael@0 30208 if (args.length === 0) {
michael@0 30209 return o.sort();
michael@0 30210 }
michael@0 30211 var compareFunction, options = 0;
michael@0 30212 if (args[0] instanceof Function) {
michael@0 30213 compareFunction = args[0];
michael@0 30214 } else if (isNumber(args[0])) {
michael@0 30215 options = args[0];
michael@0 30216 }
michael@0 30217 if (isNumber(args[1])) {
michael@0 30218 options = args[1];
michael@0 30219 }
michael@0 30220 o.sort(function (a, b) {
michael@0 30221 return asCompare(a, b, options, compareFunction);
michael@0 30222 });
michael@0 30223 return o;
michael@0 30224 }
michael@0 30225 function ArrayClass(domain, scope, instanceConstructor, baseClass) {
michael@0 30226 var c = new Class('Array', Array, ApplicationDomain.passthroughCallable(Array));
michael@0 30227 c.extendBuiltin(baseClass);
michael@0 30228 var CACHE_NUMERIC_COMPARATORS = true;
michael@0 30229 var numericComparatorCache = createEmptyObject();
michael@0 30230 c.native = {
michael@0 30231 static: {
michael@0 30232 _pop: function _pop(o) {
michael@0 30233 return o.pop();
michael@0 30234 },
michael@0 30235 _reverse: function _reverse(o) {
michael@0 30236 return o.reverse();
michael@0 30237 },
michael@0 30238 _concat: function _concat(o, args) {
michael@0 30239 return o.concat.apply(o, args);
michael@0 30240 },
michael@0 30241 _shift: function _shift(o) {
michael@0 30242 return o.shift();
michael@0 30243 },
michael@0 30244 _slice: function _slice(o, A, B) {
michael@0 30245 return o.slice(A, B);
michael@0 30246 },
michael@0 30247 _unshift: function _unshift(o, args) {
michael@0 30248 return o.unshift.apply(o, args);
michael@0 30249 },
michael@0 30250 _splice: function _splice(o, args) {
michael@0 30251 return o.splice.apply(o, args);
michael@0 30252 },
michael@0 30253 _sort: function _sort(o, args) {
michael@0 30254 if (args.length === 0) {
michael@0 30255 return o.sort();
michael@0 30256 }
michael@0 30257 var compareFunction, options = 0;
michael@0 30258 if (args[0] instanceof Function) {
michael@0 30259 compareFunction = args[0];
michael@0 30260 } else if (isNumber(args[0])) {
michael@0 30261 options = args[0];
michael@0 30262 }
michael@0 30263 if (isNumber(args[1])) {
michael@0 30264 options = args[1];
michael@0 30265 }
michael@0 30266 o.sort(function (a, b) {
michael@0 30267 return asCompare(a, b, options, compareFunction);
michael@0 30268 });
michael@0 30269 return o;
michael@0 30270 },
michael@0 30271 _sortOn: function _sortOn(o, names, options) {
michael@0 30272 if (isString(names)) {
michael@0 30273 names = [
michael@0 30274 names
michael@0 30275 ];
michael@0 30276 }
michael@0 30277 if (isNumber(options)) {
michael@0 30278 options = [
michael@0 30279 options
michael@0 30280 ];
michael@0 30281 }
michael@0 30282 for (var i = names.length - 1; i >= 0; i--) {
michael@0 30283 var key = Multiname.getPublicQualifiedName(names[i]);
michael@0 30284 if (CACHE_NUMERIC_COMPARATORS && options[i] & SORT_NUMERIC) {
michael@0 30285 var str = 'var x = toNumber(a.' + key + '), y = toNumber(b.' + key + ');';
michael@0 30286 if (options[i] & SORT_DESCENDING) {
michael@0 30287 str += 'return x < y ? 1 : (x > y ? -1 : 0);';
michael@0 30288 } else {
michael@0 30289 str += 'return x < y ? -1 : (x > y ? 1 : 0);';
michael@0 30290 }
michael@0 30291 var numericComparator = numericComparatorCache[str];
michael@0 30292 if (!numericComparator) {
michael@0 30293 numericComparator = numericComparatorCache[str] = new Function('a', 'b', str);
michael@0 30294 }
michael@0 30295 o.sort(numericComparator);
michael@0 30296 } else {
michael@0 30297 o.sort(function (a, b) {
michael@0 30298 return asCompare(a[key], b[key], options[i] | 0);
michael@0 30299 });
michael@0 30300 }
michael@0 30301 }
michael@0 30302 return o;
michael@0 30303 },
michael@0 30304 _indexOf: function _indexOf(o, searchElement, fromIndex) {
michael@0 30305 return o.indexOf(searchElement, fromIndex);
michael@0 30306 },
michael@0 30307 _lastIndexOf: function _lastIndexOf(o, searchElement, fromIndex) {
michael@0 30308 return o.lastIndexOf(searchElement, fromIndex);
michael@0 30309 },
michael@0 30310 _every: function _every(o, callback, thisObject) {
michael@0 30311 for (var i = 0; i < o.length; i++) {
michael@0 30312 if (callback.call(thisObject, o[i], i, o) !== true) {
michael@0 30313 return false;
michael@0 30314 }
michael@0 30315 }
michael@0 30316 return false;
michael@0 30317 },
michael@0 30318 _filter: function _filter(o, callback, thisObject) {
michael@0 30319 var result = [];
michael@0 30320 for (var i = 0; i < o.length; i++) {
michael@0 30321 if (callback.call(thisObject, o[i], i, o) === true) {
michael@0 30322 result.push(o[i]);
michael@0 30323 }
michael@0 30324 }
michael@0 30325 return result;
michael@0 30326 },
michael@0 30327 _forEach: function _forEach(o, callback, thisObject) {
michael@0 30328 return o.forEach(callback, thisObject);
michael@0 30329 },
michael@0 30330 _map: function _map(o, callback, thisObject) {
michael@0 30331 return o.map(callback, thisObject);
michael@0 30332 },
michael@0 30333 _some: function _some(o, callback, thisObject) {
michael@0 30334 return o.some(callback, thisObject);
michael@0 30335 }
michael@0 30336 },
michael@0 30337 instance: {
michael@0 30338 pop: Array.prototype.pop,
michael@0 30339 push: Array.prototype.push,
michael@0 30340 unshift: Array.prototype.unshift,
michael@0 30341 length: {
michael@0 30342 get: function length() {
michael@0 30343 return this.length;
michael@0 30344 },
michael@0 30345 set: function length(newLength) {
michael@0 30346 this.length = newLength;
michael@0 30347 }
michael@0 30348 }
michael@0 30349 }
michael@0 30350 };
michael@0 30351 c.coerce = function (value) {
michael@0 30352 return value;
michael@0 30353 };
michael@0 30354 c.isInstanceOf = function (value) {
michael@0 30355 return true;
michael@0 30356 };
michael@0 30357 return c;
michael@0 30358 }
michael@0 30359 var XMLClass, XMLListClass, QNameClass, ASXML, XML, ASXMLList, XMLList;
michael@0 30360 var isXMLType, isXMLName, XMLParser;
michael@0 30361 (function () {
michael@0 30362 function XMLEncoder(ancestorNamespaces, indentLevel, prettyPrinting) {
michael@0 30363 function visit(node, encode) {
michael@0 30364 if (node.isXML) {
michael@0 30365 switch (node.kind) {
michael@0 30366 case 'element':
michael@0 30367 return encode.element(node);
michael@0 30368 case 'attribute':
michael@0 30369 return encode.attribute(node);
michael@0 30370 case 'text':
michael@0 30371 return encode.text(node);
michael@0 30372 case 'cdata':
michael@0 30373 return encode.cdata(node);
michael@0 30374 case 'comment':
michael@0 30375 return encode.comment(node);
michael@0 30376 case 'processing-instruction':
michael@0 30377 return encode.pi(node);
michael@0 30378 }
michael@0 30379 } else if (node.isXMLList) {
michael@0 30380 return encode.list(node);
michael@0 30381 } else {
michael@0 30382 throw 'Not implemented';
michael@0 30383 }
michael@0 30384 }
michael@0 30385 function encode(node, encoder) {
michael@0 30386 return visit(node, {
michael@0 30387 element: function (n) {
michael@0 30388 var s, a;
michael@0 30389 var ns = n.name.mn.namespaces[0];
michael@0 30390 var prefix = ns.prefix ? ns.prefix + ':' : '';
michael@0 30391 s = '<' + prefix + n.name.localName;
michael@0 30392 var namespaceDeclarations = [];
michael@0 30393 if (ns.prefix || ns.uri) {
michael@0 30394 namespaceDeclarations.push(ns);
michael@0 30395 }
michael@0 30396 if (prefix) {
michael@0 30397 namespaceDeclarations[ns.prefix] = true;
michael@0 30398 }
michael@0 30399 var t = n;
michael@0 30400 while (t) {
michael@0 30401 for (var i = 0; i < t.inScopeNamespaces.length; i++) {
michael@0 30402 ns = t.inScopeNamespaces[i];
michael@0 30403 if (!namespaceDeclarations[ns.prefix]) {
michael@0 30404 namespaceDeclarations.push(ns);
michael@0 30405 namespaceDeclarations[ns.prefix] = true;
michael@0 30406 }
michael@0 30407 }
michael@0 30408 t = t.parent;
michael@0 30409 }
michael@0 30410 for (var i = 0; i < namespaceDeclarations.length; i++) {
michael@0 30411 a = namespaceDeclarations[i];
michael@0 30412 if (a.prefix) {
michael@0 30413 s += ' xmlns:' + a.prefix + '="' + a.uri + '"';
michael@0 30414 } else {
michael@0 30415 s += ' xmlns="' + a.uri + '"';
michael@0 30416 }
michael@0 30417 }
michael@0 30418 for (var i = 0; i < n.attributes.length; i++) {
michael@0 30419 a = n.attributes[i];
michael@0 30420 var ns = n.name.uri;
michael@0 30421 var prefix = n.prefix ? ns.prefix + ':' : '';
michael@0 30422 var name = prefix + a.name.localName;
michael@0 30423 s += ' ' + name + '="' + a.value + '"';
michael@0 30424 }
michael@0 30425 if (n.children.length) {
michael@0 30426 s += '>';
michael@0 30427 for (var i = 0; i < n.children.length; i++) {
michael@0 30428 s += visit(n.children[i], this);
michael@0 30429 }
michael@0 30430 s += '</' + prefix + n.name.mn.name + '>';
michael@0 30431 } else {
michael@0 30432 s += '/>';
michael@0 30433 }
michael@0 30434 return s;
michael@0 30435 },
michael@0 30436 text: function (text) {
michael@0 30437 return escapeAttributeValue(text.value);
michael@0 30438 },
michael@0 30439 attribute: function (n) {
michael@0 30440 return escapeAttributeValue(n.value);
michael@0 30441 },
michael@0 30442 cdata: function (n) {
michael@0 30443 },
michael@0 30444 comment: function (n) {
michael@0 30445 },
michael@0 30446 pi: function (n) {
michael@0 30447 },
michael@0 30448 doctype: function (n) {
michael@0 30449 },
michael@0 30450 list: function (n) {
michael@0 30451 var s = '';
michael@0 30452 for (var i = 0; i < n.children.length; i++) {
michael@0 30453 if (i > 0) {
michael@0 30454 s += '\n';
michael@0 30455 }
michael@0 30456 s += toXMLString(n.children[i], []);
michael@0 30457 }
michael@0 30458 return s;
michael@0 30459 }
michael@0 30460 });
michael@0 30461 }
michael@0 30462 this.encode = encode;
michael@0 30463 }
michael@0 30464 function escapeAttributeValue(v) {
michael@0 30465 return v.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;');
michael@0 30466 }
michael@0 30467 XMLParser = function XMLParser() {
michael@0 30468 function parseXml(s, sink) {
michael@0 30469 var i = 0, scopes = [
michael@0 30470 {
michael@0 30471 space: 'default',
michael@0 30472 xmlns: '',
michael@0 30473 namespaces: {
michael@0 30474 'xmlns': 'http://www.w3.org/2000/xmlns/',
michael@0 30475 'xml': 'http://www.w3.org/XML/1998/namespace'
michael@0 30476 }
michael@0 30477 }
michael@0 30478 ];
michael@0 30479 function trim(s) {
michael@0 30480 return s.replace(/^\s+/, '').replace(/\s+$/, '');
michael@0 30481 }
michael@0 30482 function resolveEntities(s) {
michael@0 30483 return s.replace(/&([^;]+);/g, function (all, entity) {
michael@0 30484 if (entity.substring(0, 2) === '#x') {
michael@0 30485 return String.fromCharCode(parseInt(entity.substring(2), 16));
michael@0 30486 } else if (entity.substring(0, 1) === '#') {
michael@0 30487 return String.fromCharCode(parseInt(entity.substring(1), 10));
michael@0 30488 }
michael@0 30489 switch (entity) {
michael@0 30490 case 'lt':
michael@0 30491 return '<';
michael@0 30492 case 'gt':
michael@0 30493 return '>';
michael@0 30494 case 'amp':
michael@0 30495 return '&';
michael@0 30496 }
michael@0 30497 throw 'Unknown entity: ' + entity;
michael@0 30498 });
michael@0 30499 }
michael@0 30500 function isWhitespacePreserved() {
michael@0 30501 for (var j = scopes.length - 1; j >= 0; --j) {
michael@0 30502 if (scopes[j].space === 'preserve') {
michael@0 30503 return true;
michael@0 30504 }
michael@0 30505 }
michael@0 30506 return false;
michael@0 30507 }
michael@0 30508 function lookupDefaultNs() {
michael@0 30509 for (var j = scopes.length - 1; j >= 0; --j) {
michael@0 30510 if (scopes[j].hasOwnProperty('xmlns')) {
michael@0 30511 return scopes[j].xmlns;
michael@0 30512 }
michael@0 30513 }
michael@0 30514 }
michael@0 30515 function lookupNs(prefix) {
michael@0 30516 for (var j = scopes.length - 1; j >= 0; --j) {
michael@0 30517 if (scopes[j].namespaces.hasOwnProperty(prefix)) {
michael@0 30518 return scopes[j].namespaces[prefix];
michael@0 30519 }
michael@0 30520 }
michael@0 30521 throw 'Unknown namespace: ' + prefix;
michael@0 30522 }
michael@0 30523 function getName(name, resolveDefaultNs) {
michael@0 30524 var j = name.indexOf(':');
michael@0 30525 if (j >= 0) {
michael@0 30526 var namespace = lookupNs(name.substring(0, j));
michael@0 30527 var prefix = name.substring(0, j);
michael@0 30528 var localName = name.substring(j + 1);
michael@0 30529 return {
michael@0 30530 name: namespace + '::' + localName,
michael@0 30531 localName: localName,
michael@0 30532 prefix: prefix,
michael@0 30533 namespace: namespace
michael@0 30534 };
michael@0 30535 } else if (resolveDefaultNs) {
michael@0 30536 return {
michael@0 30537 name: name,
michael@0 30538 localName: name,
michael@0 30539 prefix: '',
michael@0 30540 namespace: lookupDefaultNs()
michael@0 30541 };
michael@0 30542 } else {
michael@0 30543 return {
michael@0 30544 name: name,
michael@0 30545 localName: name,
michael@0 30546 prefix: '',
michael@0 30547 namespace: ''
michael@0 30548 };
michael@0 30549 }
michael@0 30550 }
michael@0 30551 var whitespaceMap = {
michael@0 30552 '10': true,
michael@0 30553 '13': true,
michael@0 30554 '9': true,
michael@0 30555 '32': true
michael@0 30556 };
michael@0 30557 function isWhitespace(s, index) {
michael@0 30558 return s.charCodeAt(index) in whitespaceMap;
michael@0 30559 }
michael@0 30560 function parseContent(s, start) {
michael@0 30561 var pos = start, name, attributes = [];
michael@0 30562 function skipWs() {
michael@0 30563 while (pos < s.length && isWhitespace(s, pos)) {
michael@0 30564 ++pos;
michael@0 30565 }
michael@0 30566 }
michael@0 30567 while (pos < s.length && !isWhitespace(s, pos) && s.charAt(pos) !== '>' && s.charAt(pos) !== '/') {
michael@0 30568 ++pos;
michael@0 30569 }
michael@0 30570 name = s.substring(start, pos);
michael@0 30571 skipWs();
michael@0 30572 while (pos < s.length && s.charAt(pos) !== '>' && s.charAt(pos) !== '/' && s.charAt(pos) !== '?') {
michael@0 30573 skipWs();
michael@0 30574 var attrName = '', attrValue = '';
michael@0 30575 while (pos < s.length && !isWhitespace(s, pos) && s.charAt(pos) !== '=') {
michael@0 30576 attrName += s.charAt(pos);
michael@0 30577 ++pos;
michael@0 30578 }
michael@0 30579 skipWs();
michael@0 30580 if (s.charAt(pos) !== '=')
michael@0 30581 throw '\'=\' expected';
michael@0 30582 ++pos;
michael@0 30583 skipWs();
michael@0 30584 var attrEndChar = s.charAt(pos);
michael@0 30585 if (attrEndChar !== '"' && attrEndChar !== '\'')
michael@0 30586 throw 'Quote expected';
michael@0 30587 var attrEndIndex = s.indexOf(attrEndChar, ++pos);
michael@0 30588 if (attrEndIndex < 0)
michael@0 30589 throw new 'Unexpected EOF[6]'();
michael@0 30590 attrValue = s.substring(pos, attrEndIndex);
michael@0 30591 attributes.push({
michael@0 30592 name: attrName,
michael@0 30593 value: resolveEntities(attrValue)
michael@0 30594 });
michael@0 30595 pos = attrEndIndex + 1;
michael@0 30596 skipWs();
michael@0 30597 }
michael@0 30598 return {
michael@0 30599 name: name,
michael@0 30600 attributes: attributes,
michael@0 30601 parsed: pos - start
michael@0 30602 };
michael@0 30603 }
michael@0 30604 while (i < s.length) {
michael@0 30605 var ch = s.charAt(i);
michael@0 30606 var j = i;
michael@0 30607 if (ch === '<') {
michael@0 30608 ++j;
michael@0 30609 var ch2 = s.charAt(j), q, name;
michael@0 30610 switch (ch2) {
michael@0 30611 case '/':
michael@0 30612 ++j;
michael@0 30613 q = s.indexOf('>', j);
michael@0 30614 if (q < 0) {
michael@0 30615 throw 'Unexpected EOF[1]';
michael@0 30616 }
michael@0 30617 name = getName(s.substring(j, q), true);
michael@0 30618 sink.endElement(name);
michael@0 30619 scopes.pop();
michael@0 30620 j = q + 1;
michael@0 30621 break;
michael@0 30622 case '?':
michael@0 30623 ++j;
michael@0 30624 var content = parseContent(s, j);
michael@0 30625 if (s.substring(j + content.parsed, j + content.parsed + 2) != '?>') {
michael@0 30626 throw 'Unexpected EOF[2]';
michael@0 30627 }
michael@0 30628 sink.pi(content.name, content.attributes);
michael@0 30629 j += content.parsed + 2;
michael@0 30630 break;
michael@0 30631 case '!':
michael@0 30632 if (s.substring(j + 1, j + 3) === '--') {
michael@0 30633 q = s.indexOf('-->', j + 3);
michael@0 30634 if (q < 0) {
michael@0 30635 throw 'Unexpected EOF[3]';
michael@0 30636 }
michael@0 30637 sink.comment(s.substring(j + 3, q));
michael@0 30638 j = q + 3;
michael@0 30639 } else if (s.substring(j + 1, j + 8) === '[CDATA[') {
michael@0 30640 q = s.indexOf(']]>', j + 8);
michael@0 30641 if (q < 0) {
michael@0 30642 throw 'Unexpected EOF[4]';
michael@0 30643 }
michael@0 30644 sink.cdata(s.substring(j + 8, q));
michael@0 30645 j = q + 3;
michael@0 30646 } else if (s.substring(j + 1, j + 8) === 'DOCTYPE') {
michael@0 30647 var q2 = s.indexOf('[', j + 8), complexDoctype = false;
michael@0 30648 q = s.indexOf('>', j + 8);
michael@0 30649 if (q < 0) {
michael@0 30650 throw 'Unexpected EOF[5]';
michael@0 30651 }
michael@0 30652 if (q2 > 0 && q > q2) {
michael@0 30653 q = s.indexOf(']>', j + 8);
michael@0 30654 if (q < 0) {
michael@0 30655 throw 'Unexpected EOF[7]';
michael@0 30656 }
michael@0 30657 complexDoctype = true;
michael@0 30658 }
michael@0 30659 var doctypeContent = s.substring(j + 8, q + (complexDoctype ? 1 : 0));
michael@0 30660 sink.doctype(doctypeContent);
michael@0 30661 j = q + (complexDoctype ? 2 : 1);
michael@0 30662 } else {
michael@0 30663 throw 'Unknown !tag';
michael@0 30664 }
michael@0 30665 break;
michael@0 30666 default:
michael@0 30667 var content = parseContent(s, j);
michael@0 30668 var isClosed = false;
michael@0 30669 if (s.substring(j + content.parsed, j + content.parsed + 2) === '/>') {
michael@0 30670 isClosed = true;
michael@0 30671 } else if (s.substring(j + content.parsed, j + content.parsed + 1) !== '>') {
michael@0 30672 throw 'Unexpected EOF[2]';
michael@0 30673 }
michael@0 30674 var scope = {
michael@0 30675 namespaces: []
michael@0 30676 };
michael@0 30677 var contentAttributes = content.attributes;
michael@0 30678 for (q = 0; q < contentAttributes.length; ++q) {
michael@0 30679 var attribute = contentAttributes[q];
michael@0 30680 var attributeName = attribute.name;
michael@0 30681 if (attributeName.substring(0, 6) === 'xmlns:') {
michael@0 30682 var prefix = attributeName.substring(6);
michael@0 30683 var uri = attribute.value;
michael@0 30684 scope.namespaces[prefix] = trim(uri);
michael@0 30685 scope.namespaces.push({
michael@0 30686 uri: uri,
michael@0 30687 prefix: prefix
michael@0 30688 });
michael@0 30689 delete contentAttributes[q];
michael@0 30690 } else if (attributeName === 'xmlns') {
michael@0 30691 var uri = attribute.value;
michael@0 30692 scope.namespaces['xmlns'] = trim(uri);
michael@0 30693 scope.namespaces.push({
michael@0 30694 uri: uri,
michael@0 30695 prefix: ''
michael@0 30696 });
michael@0 30697 delete contentAttributes[q];
michael@0 30698 } else if (attributeName.substring(0, 4) === 'xml:') {
michael@0 30699 scope[attributeName.substring(4)] = trim(attribute.value);
michael@0 30700 } else if (attributeName.substring(0, 3) === 'xml') {
michael@0 30701 throw 'Invalid xml attribute';
michael@0 30702 } else {
michael@0 30703 }
michael@0 30704 }
michael@0 30705 scopes.push(scope);
michael@0 30706 var attributes = [];
michael@0 30707 for (q = 0; q < contentAttributes.length; ++q) {
michael@0 30708 attribute = contentAttributes[q];
michael@0 30709 if (attribute) {
michael@0 30710 attributes.push({
michael@0 30711 name: getName(attribute.name, false),
michael@0 30712 value: attribute.value
michael@0 30713 });
michael@0 30714 }
michael@0 30715 }
michael@0 30716 sink.beginElement(getName(content.name, true), attributes, scope, isClosed);
michael@0 30717 j += content.parsed + (isClosed ? 2 : 1);
michael@0 30718 if (isClosed)
michael@0 30719 scopes.pop();
michael@0 30720 break;
michael@0 30721 }
michael@0 30722 } else {
michael@0 30723 do {
michael@0 30724 if (++j >= s.length)
michael@0 30725 break;
michael@0 30726 } while (s.charAt(j) !== '<');
michael@0 30727 var text = s.substring(i, j);
michael@0 30728 var isWs = text.replace(/^\s+/, '').length === 0;
michael@0 30729 if (!isWs || isWhitespacePreserved()) {
michael@0 30730 sink.text(resolveEntities(text), isWs);
michael@0 30731 }
michael@0 30732 }
michael@0 30733 i = j;
michael@0 30734 }
michael@0 30735 }
michael@0 30736 this.parseFromString = function (s, mimeType) {
michael@0 30737 var currentElement = new XML('element', '', '', '');
michael@0 30738 var elementsStack = [];
michael@0 30739 parseXml(s, {
michael@0 30740 beginElement: function (name, attrs, scope, isEmpty) {
michael@0 30741 var parent = currentElement;
michael@0 30742 elementsStack.push(parent);
michael@0 30743 currentElement = createNode('element', name.namespace, name.localName, name.prefix);
michael@0 30744 for (var i = 0; i < attrs.length; ++i) {
michael@0 30745 var rawAttr = attrs[i];
michael@0 30746 var attr = createNode('attribute', rawAttr.name.namespace, rawAttr.name.localName, rawAttr.name.prefix);
michael@0 30747 attr.value = rawAttr.value;
michael@0 30748 currentElement.attributes.push(attr);
michael@0 30749 }
michael@0 30750 var namespaces = scope.namespaces;
michael@0 30751 for (var i = 0; i < namespaces.length; ++i) {
michael@0 30752 var rawNs = namespaces[i];
michael@0 30753 var ns = ASNamespace.createNamespace(rawNs.uri, rawNs.prefix);
michael@0 30754 currentElement.inScopeNamespaces.push(ns);
michael@0 30755 }
michael@0 30756 parent.insert(parent.length(), currentElement);
michael@0 30757 if (isEmpty) {
michael@0 30758 currentElement = elementsStack.pop();
michael@0 30759 }
michael@0 30760 },
michael@0 30761 endElement: function (name) {
michael@0 30762 currentElement = elementsStack.pop();
michael@0 30763 },
michael@0 30764 text: function (text, isWhitespace) {
michael@0 30765 var node = createNode('text', '', '');
michael@0 30766 node.value = text;
michael@0 30767 currentElement.insert(currentElement.length(), node);
michael@0 30768 },
michael@0 30769 cdata: function (text) {
michael@0 30770 var node = createNode('text', '', '');
michael@0 30771 node.value = text;
michael@0 30772 currentElement.insert(currentElement.length(), node);
michael@0 30773 },
michael@0 30774 comment: function (text) {
michael@0 30775 },
michael@0 30776 pi: function (name, attrs) {
michael@0 30777 },
michael@0 30778 doctype: function (text) {
michael@0 30779 }
michael@0 30780 });
michael@0 30781 return currentElement;
michael@0 30782 };
michael@0 30783 function createNode(kind, uri, name, prefix) {
michael@0 30784 return new XML(kind, uri, name, prefix);
michael@0 30785 }
michael@0 30786 };
michael@0 30787 var xmlParser = new XMLParser();
michael@0 30788 isXMLType = function isXMLType(val) {
michael@0 30789 return val.isXML || val.isXMLList;
michael@0 30790 };
michael@0 30791 function toString(node) {
michael@0 30792 if (typeof node === 'object' && node !== null) {
michael@0 30793 switch (node.kind) {
michael@0 30794 case 'text':
michael@0 30795 case 'attribute':
michael@0 30796 return node.value;
michael@0 30797 default:
michael@0 30798 if (node.hasSimpleContent()) {
michael@0 30799 var str = '';
michael@0 30800 node.children.forEach(function (v, i) {
michael@0 30801 str += toString(v);
michael@0 30802 });
michael@0 30803 return str;
michael@0 30804 }
michael@0 30805 return toXMLString(node);
michael@0 30806 }
michael@0 30807 } else {
michael@0 30808 return String(node);
michael@0 30809 }
michael@0 30810 }
michael@0 30811 function toXMLString(node, ancestorNamespaces, indentLevel) {
michael@0 30812 return new XMLEncoder(ancestorNamespaces, indentLevel, true).encode(node);
michael@0 30813 }
michael@0 30814 function toXML(v) {
michael@0 30815 if (v === null) {
michael@0 30816 throw new TypeError(formatErrorMessage(Errors.ConvertNullToObjectError));
michael@0 30817 } else if (v === undefined) {
michael@0 30818 throw new TypeError(formatErrorMessage(Errors.ConvertUndefinedToObjectError));
michael@0 30819 } else if (v.isXML) {
michael@0 30820 return v;
michael@0 30821 } else if (v.isXMLList) {
michael@0 30822 if (v.length() === 1) {
michael@0 30823 return v.children[0];
michael@0 30824 }
michael@0 30825 throw new TypeError(formatErrorMessage(Errors.XMLMarkupMustBeWellFormed));
michael@0 30826 } else {
michael@0 30827 var x = xmlParser.parseFromString(String(v));
michael@0 30828 if (x.length() === 0) {
michael@0 30829 var x = new XML('text');
michael@0 30830 return x;
michael@0 30831 } else if (x.length() === 1) {
michael@0 30832 x.children[0].parent = null;
michael@0 30833 return x.children[0];
michael@0 30834 }
michael@0 30835 throw 'SyntaxError in ToXML';
michael@0 30836 }
michael@0 30837 }
michael@0 30838 var defaultNamespace = '';
michael@0 30839 function toXMLList(value) {
michael@0 30840 if (value === null) {
michael@0 30841 throw new TypeError(formatErrorMessage(Errors.ConvertNullToObjectError));
michael@0 30842 } else if (value === undefined) {
michael@0 30843 throw new TypeError(formatErrorMessage(Errors.ConvertUndefinedToObjectError));
michael@0 30844 } else if (value instanceof XML) {
michael@0 30845 var xl = new XMLList(value.parent, value.name);
michael@0 30846 xl.append(value);
michael@0 30847 return xl;
michael@0 30848 } else if (value instanceof XMLList) {
michael@0 30849 return value;
michael@0 30850 } else {
michael@0 30851 var s = '<parent xmlns=\'' + defaultNamespace + '\'>' + String(value) + '</parent>';
michael@0 30852 var x = new ASXML(s);
michael@0 30853 var xl = new XMLList();
michael@0 30854 for (var i = 0; i < x.length(); i++) {
michael@0 30855 var v = x.children[i];
michael@0 30856 v.parent = null;
michael@0 30857 xl.append(v);
michael@0 30858 }
michael@0 30859 return xl;
michael@0 30860 }
michael@0 30861 }
michael@0 30862 function toAttributeName(v) {
michael@0 30863 if (v === undefined || v === null || typeof v === 'boolean' || typeof v === 'number') {
michael@0 30864 throw 'TypeError: invalid operand to ToAttributeName()';
michael@0 30865 } else if (isXMLType(v)) {
michael@0 30866 v = toString(v);
michael@0 30867 } else if (v instanceof Object && v !== null) {
michael@0 30868 if (v instanceof QName) {
michael@0 30869 return new QName(v.uri, v.localName, true);
michael@0 30870 }
michael@0 30871 v = toString(v);
michael@0 30872 }
michael@0 30873 if (typeof v === 'string') {
michael@0 30874 var ns = new ASNamespace();
michael@0 30875 var qn = new QName(ns, v, true);
michael@0 30876 } else {
michael@0 30877 }
michael@0 30878 return qn;
michael@0 30879 }
michael@0 30880 function toXMLName(mn) {
michael@0 30881 return new QName(mn);
michael@0 30882 }
michael@0 30883 function getDefaultNamespace(scope) {
michael@0 30884 while (scope) {
michael@0 30885 var obj = scope.object;
michael@0 30886 if (obj.defaultNamepsace !== undefined) {
michael@0 30887 return obj.defaultNamespace;
michael@0 30888 }
michael@0 30889 scope = scope.parent;
michael@0 30890 }
michael@0 30891 var ns = ASNamespace.createNamespace('', '');
michael@0 30892 return ns;
michael@0 30893 }
michael@0 30894 isXMLName = function isXMLName(v) {
michael@0 30895 try {
michael@0 30896 var qn = new QName(v);
michael@0 30897 } catch (e) {
michael@0 30898 return false;
michael@0 30899 }
michael@0 30900 return true;
michael@0 30901 };
michael@0 30902 function asGetProperty(namespaces, name, flags, isMethod) {
michael@0 30903 var mn = isNumeric(name) ? toNumber(name) : name instanceof QName ? name.mn : new Multiname(namespaces ? namespaces : [
michael@0 30904 ASNamespace.PUBLIC
michael@0 30905 ], name, flags);
michael@0 30906 return this.getProperty(mn, isMethod);
michael@0 30907 }
michael@0 30908 function asSetProperty(namespaces, name, flags, value) {
michael@0 30909 var mn = isNumeric(name) ? toNumber(name) : name instanceof QName ? name.mn : new Multiname(namespaces ? namespaces : [
michael@0 30910 ASNamespace.PUBLIC
michael@0 30911 ], name, flags);
michael@0 30912 this.setProperty(mn, value);
michael@0 30913 }
michael@0 30914 function asHasProperty(namespaces, name, flags) {
michael@0 30915 var mn = isNumeric(name) ? toNumber(name) : name instanceof QName ? name.mn : new Multiname(namespaces ? namespaces : [
michael@0 30916 ASNamespace.PUBLIC
michael@0 30917 ], name, flags);
michael@0 30918 return this.hasProperty(mn);
michael@0 30919 }
michael@0 30920 function asCallProperty(namespaces, name, flags, isLex, args) {
michael@0 30921 var receiver = isLex ? null : this;
michael@0 30922 var property = this.asGetProperty(namespaces, name, flags, true);
michael@0 30923 if (!property) {
michael@0 30924 return this.toString().asCallProperty(namespaces ? namespaces : [
michael@0 30925 ASNamespace.PUBLIC
michael@0 30926 ], name, flags, isLex, args);
michael@0 30927 }
michael@0 30928 return property.apply(receiver, args);
michael@0 30929 }
michael@0 30930 var ATTR_NAME = 1;
michael@0 30931 var ELEM_NAME = 2;
michael@0 30932 var ANY_NAME = 4;
michael@0 30933 var ANY_NAMESPACE = 8;
michael@0 30934 function nameKind(mn) {
michael@0 30935 var flags = 0;
michael@0 30936 if (mn.isAttribute()) {
michael@0 30937 flags |= ATTR_NAME;
michael@0 30938 } else {
michael@0 30939 flags |= ELEM_NAME;
michael@0 30940 }
michael@0 30941 if (mn.isAnyName()) {
michael@0 30942 flags |= ANY_NAME;
michael@0 30943 }
michael@0 30944 if (mn.isAnyNamespace()) {
michael@0 30945 flags |= ANY_NAMESPACE;
michael@0 30946 }
michael@0 30947 return flags;
michael@0 30948 }
michael@0 30949 XMLClass = function XMLClass(runtime, scope, instanceConstructor, baseClass) {
michael@0 30950 var FLAG_IGNORE_COMMENTS = 1;
michael@0 30951 var FLAG_IGNORE_PROCESSING_INSTRUCTIONS = 2;
michael@0 30952 var FLAG_IGNORE_WHITESPACE = 4;
michael@0 30953 var FLAG_PRETTY_PRINTING = 8;
michael@0 30954 ASXML = function (value) {
michael@0 30955 if (!(this instanceof ASXML)) {
michael@0 30956 if (value instanceof ASXML) {
michael@0 30957 return value;
michael@0 30958 }
michael@0 30959 return new ASXML(value);
michael@0 30960 }
michael@0 30961 if (value === null || value === undefined) {
michael@0 30962 value = '';
michael@0 30963 }
michael@0 30964 var x = toXML(value);
michael@0 30965 if (isXMLType(value)) {
michael@0 30966 x = x.deepCopy();
michael@0 30967 }
michael@0 30968 return x;
michael@0 30969 };
michael@0 30970 XML = function (kind, uri, name, prefix) {
michael@0 30971 if (kind === undefined) {
michael@0 30972 kind = 'text';
michael@0 30973 }
michael@0 30974 if (uri === undefined) {
michael@0 30975 uri = '';
michael@0 30976 }
michael@0 30977 if (name === undefined) {
michael@0 30978 name = '';
michael@0 30979 }
michael@0 30980 this.init(kind, uri, name, prefix);
michael@0 30981 };
michael@0 30982 var c = new Class('XML', ASXML, ApplicationDomain.passthroughCallable(ASXML));
michael@0 30983 c.flags = FLAG_IGNORE_COMMENTS | FLAG_IGNORE_PROCESSING_INSTRUCTIONS | FLAG_IGNORE_WHITESPACE | FLAG_PRETTY_PRINTING;
michael@0 30984 c.prettyIndent = 2;
michael@0 30985 c.extend(baseClass);
michael@0 30986 var Xp = XML.prototype = ASXML.prototype;
michael@0 30987 Xp.init = function init(kind, uri, name, prefix) {
michael@0 30988 this.name = new QName(new Multiname([
michael@0 30989 new ASNamespace(prefix, uri)
michael@0 30990 ], name));
michael@0 30991 this.kind = kind;
michael@0 30992 this.parent = null;
michael@0 30993 this.inScopeNamespaces = [];
michael@0 30994 switch (kind) {
michael@0 30995 case 'element':
michael@0 30996 this.attributes = [];
michael@0 30997 this.children = [];
michael@0 30998 break;
michael@0 30999 case 'attribute':
michael@0 31000 case 'text':
michael@0 31001 this.value = '';
michael@0 31002 break;
michael@0 31003 default:
michael@0 31004 break;
michael@0 31005 }
michael@0 31006 return this;
michael@0 31007 };
michael@0 31008 Xp.length = function () {
michael@0 31009 if (!this.children) {
michael@0 31010 return 0;
michael@0 31011 }
michael@0 31012 return this.children.length;
michael@0 31013 };
michael@0 31014 Xp.canHandleProperties = true;
michael@0 31015 Xp.deepCopy = function () {
michael@0 31016 return new ASXML(toXMLString(this));
michael@0 31017 };
michael@0 31018 Xp.resolveValue = function resolveValue() {
michael@0 31019 return this;
michael@0 31020 };
michael@0 31021 Xp.hasSimpleContent = function hasSimpleContent() {
michael@0 31022 if (this.kind === 'comment' || this.kind === 'processing-instruction') {
michael@0 31023 return false;
michael@0 31024 }
michael@0 31025 var result = true;
michael@0 31026 if (this.children) {
michael@0 31027 this.children.forEach(function (v) {
michael@0 31028 if (v.kind === 'element') {
michael@0 31029 result = false;
michael@0 31030 }
michael@0 31031 });
michael@0 31032 }
michael@0 31033 return result;
michael@0 31034 };
michael@0 31035 Xp.asGetEnumerableKeys = function asGetEnumerableKeys() {
michael@0 31036 if (Xp === this) {
michael@0 31037 return Object.prototype.asGetEnumerableKeys.call(this);
michael@0 31038 }
michael@0 31039 var keys = [];
michael@0 31040 this.children.forEach(function (v, i) {
michael@0 31041 keys.push(v.name);
michael@0 31042 });
michael@0 31043 return keys;
michael@0 31044 };
michael@0 31045 function setAttribute(node, name, value) {
michael@0 31046 if (node.nodeType === Node.DOCUMENT_NODE) {
michael@0 31047 node.childNodes[0].setAttribute(name, value);
michael@0 31048 } else if (node.nodeType === Node.ELEMENT_NODE) {
michael@0 31049 node.setAttribute(name, value);
michael@0 31050 } else {
michael@0 31051 throw 'error or unhandled case in setAttribute';
michael@0 31052 }
michael@0 31053 }
michael@0 31054 Xp.setProperty = function (p, v) {
michael@0 31055 var x, i, c, n;
michael@0 31056 x = this;
michael@0 31057 if (p === p >>> 0) {
michael@0 31058 throw 'TypeError in XML.prototype.setProperty(): invalid property name ' + p;
michael@0 31059 }
michael@0 31060 if (x.kind === 'text' || x.kind === 'comment' || x.kind === 'processing-instruction' || x.kind === 'attribute') {
michael@0 31061 return;
michael@0 31062 }
michael@0 31063 if (!v || !v.isXML && !v.isXMLList || v.kind === 'text' || v.kind === 'attribute') {
michael@0 31064 c = toString(v);
michael@0 31065 } else {
michael@0 31066 c = v.deepCopy();
michael@0 31067 }
michael@0 31068 n = toXMLName(p);
michael@0 31069 if (n.isAttr) {
michael@0 31070 if (!this.attributes) {
michael@0 31071 return;
michael@0 31072 }
michael@0 31073 this.attributes.forEach(function (v, i, o) {
michael@0 31074 if (v.name === n.localName) {
michael@0 31075 delete o[i];
michael@0 31076 }
michael@0 31077 });
michael@0 31078 var a = new XML('attribute', n.uri, n.localName);
michael@0 31079 a.value = v;
michael@0 31080 a.parent = this;
michael@0 31081 this.attributes.push(a);
michael@0 31082 return;
michael@0 31083 }
michael@0 31084 var isValidName = isXMLName(n);
michael@0 31085 if (!isValidName && n.localName !== '*') {
michael@0 31086 return;
michael@0 31087 }
michael@0 31088 var i = undefined;
michael@0 31089 var primitiveAssign = !isXMLType(c) && n.localName !== '*';
michael@0 31090 for (var k = x.length() - 1; k >= 0; k--) {
michael@0 31091 if ((n.isAny || x.children[k].kind === 'element' && x.children[k].name.localName === n.localName) && (n.uri === null || x.children[k].kind === 'element' && x.children[k].name.uri === n.uri)) {
michael@0 31092 if (i !== undefined) {
michael@0 31093 x.deleteByIndex(String(i));
michael@0 31094 }
michael@0 31095 i = k;
michael@0 31096 }
michael@0 31097 }
michael@0 31098 if (i === undefined) {
michael@0 31099 i = x.length();
michael@0 31100 if (primitiveAssign) {
michael@0 31101 if (n.uri === null) {
michael@0 31102 var name = new QName(getDefaultNamespace(scope), n);
michael@0 31103 } else {
michael@0 31104 var name = new QName(n);
michael@0 31105 }
michael@0 31106 var y = new XML('element', name.uri, name.localName, name.prefix);
michael@0 31107 y.parent = x;
michael@0 31108 var ns = name.getNamespace();
michael@0 31109 x.replace(String(i), y);
michael@0 31110 y.addInScopeNamespace(ns);
michael@0 31111 }
michael@0 31112 }
michael@0 31113 if (primitiveAssign) {
michael@0 31114 x.children[i].children = [];
michael@0 31115 var s = toString(c);
michael@0 31116 if (s !== '') {
michael@0 31117 x.children[i].replace('0', s);
michael@0 31118 }
michael@0 31119 } else {
michael@0 31120 x.replace(String(i), c);
michael@0 31121 }
michael@0 31122 return;
michael@0 31123 };
michael@0 31124 Xp.asGetProperty = asGetProperty;
michael@0 31125 Xp.asGetResolvedStringProperty = asGetResolvedStringPropertyFallback;
michael@0 31126 Xp.asSetProperty = asSetProperty;
michael@0 31127 Xp.asHasProperty = asHasProperty;
michael@0 31128 Xp.asCallProperty = asCallProperty;
michael@0 31129 Xp.getProperty = function (mn, isMethod) {
michael@0 31130 if (isMethod) {
michael@0 31131 var resolved = Multiname.isQName(mn) ? mn : this.resolveMultinameProperty(mn.namespaces, mn.name, mn.flags);
michael@0 31132 return this[Multiname.getQualifiedName(resolved)];
michael@0 31133 }
michael@0 31134 if (!Multiname.isQName(mn) && isNumeric(mn)) {
michael@0 31135 if (Number(0) === 0) {
michael@0 31136 return this;
michael@0 31137 }
michael@0 31138 return null;
michael@0 31139 }
michael@0 31140 var x = this;
michael@0 31141 var name = toXMLName(mn);
michael@0 31142 var xl = new XMLList(x, name);
michael@0 31143 var flags = nameKind(name.mn);
michael@0 31144 var anyName = flags & ANY_NAME;
michael@0 31145 var anyNamespace = flags & ANY_NAMESPACE;
michael@0 31146 if (flags & ATTR_NAME) {
michael@0 31147 if (x.attributes) {
michael@0 31148 x.attributes.forEach(function (v, i) {
michael@0 31149 if ((anyName || v.name.localName === name.localName) && (anyNamespace || v.name.uri === name.uri)) {
michael@0 31150 xl.append(v);
michael@0 31151 }
michael@0 31152 });
michael@0 31153 }
michael@0 31154 } else {
michael@0 31155 x.children.forEach(function (v, i) {
michael@0 31156 if ((anyName || v.kind === 'element' && v.name.localName === name.localName) && (anyNamespace || v.kind === 'element' && v.name.uri === name.uri)) {
michael@0 31157 xl.append(v);
michael@0 31158 }
michael@0 31159 });
michael@0 31160 }
michael@0 31161 return xl;
michael@0 31162 };
michael@0 31163 Xp.hasProperty = function (mn, isMethod) {
michael@0 31164 if (isMethod) {
michael@0 31165 var resolved = Multiname.isQName(mn) ? mn : this.resolveMultinameProperty(mn.namespaces, mn.name, mn.flags);
michael@0 31166 return !(!this[Multiname.getQualifiedName(resolved)]);
michael@0 31167 }
michael@0 31168 if (!Multiname.isQName(mn) && isNumeric(mn)) {
michael@0 31169 if (Number(0) === 0) {
michael@0 31170 return true;
michael@0 31171 }
michael@0 31172 return false;
michael@0 31173 }
michael@0 31174 var name = toXMLName(mn);
michael@0 31175 var flags = nameKind(name.mn);
michael@0 31176 var anyName = flags & ANY_NAME;
michael@0 31177 var anyNamespace = flags & ANY_NAMESPACE;
michael@0 31178 if (flags & ATTR_NAME) {
michael@0 31179 return this.attributes.some(function (v, i) {
michael@0 31180 if ((anyName || v.name.localName === name.localName) && (anyNamespace || v.name.uri === name.uri)) {
michael@0 31181 return true;
michael@0 31182 }
michael@0 31183 });
michael@0 31184 if (x.attributes) {
michael@0 31185 x.attributes.forEach(function (v, i) {
michael@0 31186 if ((anyName || v.name.localName === name.localName) && (anyNamespace || v.name.uri === name.uri)) {
michael@0 31187 xl.append(v);
michael@0 31188 }
michael@0 31189 });
michael@0 31190 }
michael@0 31191 } else {
michael@0 31192 if (this.children.some(function (v, i) {
michael@0 31193 if ((anyName || v.kind === 'element' && v.name.localName === name.localName) && (anyNamespace || v.kind === 'element' && v.name.uri === name.uri)) {
michael@0 31194 return true;
michael@0 31195 }
michael@0 31196 })) {
michael@0 31197 return true;
michael@0 31198 }
michael@0 31199 var resolved = Multiname.isQName(mn) ? mn : this.resolveMultinameProperty(mn.namespaces, mn.name, mn.flags);
michael@0 31200 return !(!this[Multiname.getQualifiedName(resolved)]);
michael@0 31201 }
michael@0 31202 };
michael@0 31203 Xp.delete = function (key, isMethod) {
michael@0 31204 notImplemented('XML.[[Delete]]');
michael@0 31205 };
michael@0 31206 Xp.deleteByIndex = function (p) {
michael@0 31207 var x = this;
michael@0 31208 var i = p >>> 0;
michael@0 31209 if (String(i) !== String(p)) {
michael@0 31210 throw 'TypeError in XML.prototype.deleteByIndex(): invalid index ' + p;
michael@0 31211 }
michael@0 31212 if (p < x.length()) {
michael@0 31213 if (x.children[p]) {
michael@0 31214 x.children[p].parent = null;
michael@0 31215 delete x.children[p];
michael@0 31216 for (q = i + 1; q < x.length(); q++) {
michael@0 31217 x.children[q - 1] = x.children[q];
michael@0 31218 }
michael@0 31219 x.children.length = x.children.length - 1;
michael@0 31220 }
michael@0 31221 }
michael@0 31222 };
michael@0 31223 Xp.isXML = true;
michael@0 31224 Xp.insert = function insert(p, v) {
michael@0 31225 var x, s, i, n;
michael@0 31226 x = this;
michael@0 31227 if (x.kind === 'text' || x.kind === 'comment' || x.kind === 'processing-instruction' || x.kind === 'attribute') {
michael@0 31228 return;
michael@0 31229 }
michael@0 31230 i = p >>> 0;
michael@0 31231 if (String(p) !== String(i)) {
michael@0 31232 throw 'TypeError in XML.prototype.insert(): invalid property name ' + p;
michael@0 31233 }
michael@0 31234 if (x.kind === 'element') {
michael@0 31235 var a = x;
michael@0 31236 while (a) {
michael@0 31237 if (a === v) {
michael@0 31238 throw 'Error in XML.prototype.insert()';
michael@0 31239 }
michael@0 31240 a = a.parent;
michael@0 31241 }
michael@0 31242 }
michael@0 31243 if (x.isXMLList) {
michael@0 31244 n = x.length();
michael@0 31245 if (n === 0) {
michael@0 31246 return;
michael@0 31247 }
michael@0 31248 } else {
michael@0 31249 n = 1;
michael@0 31250 }
michael@0 31251 for (var j = x.length() - 1; j >= i; j--) {
michael@0 31252 x[j + n] = x[j];
michael@0 31253 }
michael@0 31254 if (x.isXMLList) {
michael@0 31255 n = v.length();
michael@0 31256 for (var j = 0; j < n; j++) {
michael@0 31257 v.children[j].parent = x;
michael@0 31258 x[i + j] = v[j];
michael@0 31259 }
michael@0 31260 } else {
michael@0 31261 v.parent = x;
michael@0 31262 x.children[i] = v;
michael@0 31263 }
michael@0 31264 };
michael@0 31265 Xp.replace = function (p, v) {
michael@0 31266 var x, s;
michael@0 31267 x = this;
michael@0 31268 if (x.kind === 'text' || x.kind === 'comment' || x.kind === 'processing-instruction' || x.kind === 'attribute') {
michael@0 31269 return;
michael@0 31270 }
michael@0 31271 var i = p >>> 0;
michael@0 31272 if (String(p) !== String(i)) {
michael@0 31273 throw 'TypeError in XML.prototype.replace(): invalid name ' + p;
michael@0 31274 }
michael@0 31275 if (i >= x.length()) {
michael@0 31276 p = String(x.length());
michael@0 31277 }
michael@0 31278 if (v.kind === 'element') {
michael@0 31279 var a = x;
michael@0 31280 while (a) {
michael@0 31281 if (a === v) {
michael@0 31282 throw 'Error in XML.prototype.replace()';
michael@0 31283 }
michael@0 31284 a = a.parent;
michael@0 31285 }
michael@0 31286 }
michael@0 31287 if (v.kind === 'element' || v.kind === 'text' || v.kind === 'comment' || v.kind === 'processing-instruction') {
michael@0 31288 v.parent = x;
michael@0 31289 if (x[p]) {
michael@0 31290 x.children[p].parent = null;
michael@0 31291 }
michael@0 31292 x.children[p] = v;
michael@0 31293 } else if (x.isXMLList) {
michael@0 31294 x.deleteByIndex(p);
michael@0 31295 x.insert(p, v);
michael@0 31296 } else {
michael@0 31297 s = toString(v);
michael@0 31298 t = new XML();
michael@0 31299 t.parent = x;
michael@0 31300 t.value = s;
michael@0 31301 if (x[p]) {
michael@0 31302 x.children[p].parent = null;
michael@0 31303 }
michael@0 31304 x.children[p] = t;
michael@0 31305 }
michael@0 31306 };
michael@0 31307 Xp.addInScopeNamespace = function (ns) {
michael@0 31308 var x, s;
michael@0 31309 x = this;
michael@0 31310 if (x.kind === 'text' || x.kind === 'comment' || x.kind === 'processing-instruction' || x.kind === 'attribute') {
michael@0 31311 return;
michael@0 31312 }
michael@0 31313 if (ns.prefix !== undefined) {
michael@0 31314 if (ns.prefix === '' && x.name.uri === '') {
michael@0 31315 return;
michael@0 31316 }
michael@0 31317 var match = null;
michael@0 31318 x.inScopeNamespaces.forEach(function (v, i) {
michael@0 31319 if (v.prefix === ns.prefix) {
michael@0 31320 match = v;
michael@0 31321 }
michael@0 31322 });
michael@0 31323 if (match !== null && match.uri !== ns.uri) {
michael@0 31324 x.inScopeNamespaces.forEach(function (v, i) {
michael@0 31325 if (v.prefix === match.prefix) {
michael@0 31326 x.inScopeNamespaces[i] = ns;
michael@0 31327 }
michael@0 31328 });
michael@0 31329 }
michael@0 31330 if (x.name.prefix === ns.prefix) {
michael@0 31331 x.name.prefix = undefined;
michael@0 31332 }
michael@0 31333 x.attributes.forEach(function (v, i) {
michael@0 31334 if (v.name.prefix === ns.name.prefix) {
michael@0 31335 v.name.prefix = undefined;
michael@0 31336 }
michael@0 31337 });
michael@0 31338 }
michael@0 31339 };
michael@0 31340 Xp.descendants = function (name) {
michael@0 31341 name = toXMLName(name);
michael@0 31342 var x = this;
michael@0 31343 var xl = new XMLList();
michael@0 31344 if (x.kind !== 'element') {
michael@0 31345 return xl;
michael@0 31346 }
michael@0 31347 if (name.isAttr) {
michael@0 31348 this.attributes.forEach(function (v, i) {
michael@0 31349 if (name.isAny || name.localName === v.name.localName) {
michael@0 31350 xl.append(v);
michael@0 31351 }
michael@0 31352 });
michael@0 31353 } else {
michael@0 31354 this.children.forEach(function (v, i) {
michael@0 31355 if (name.isAny || name.localName === v.name.localName) {
michael@0 31356 xl.append(v);
michael@0 31357 }
michael@0 31358 });
michael@0 31359 }
michael@0 31360 this.children.forEach(function (v, i) {
michael@0 31361 xl.append(v.descendants(name));
michael@0 31362 });
michael@0 31363 return xl;
michael@0 31364 };
michael@0 31365 Xp.comments = function () {
michael@0 31366 var x = this;
michael@0 31367 var xl = new XMLList(x, null);
michael@0 31368 x.children.forEach(function (v, i) {
michael@0 31369 if (v.kind === 'comment') {
michael@0 31370 xl.append(v);
michael@0 31371 }
michael@0 31372 });
michael@0 31373 return xl;
michael@0 31374 };
michael@0 31375 Xp.text = function () {
michael@0 31376 var x = this;
michael@0 31377 var xl = new XMLList(x, null);
michael@0 31378 x.children.forEach(function (v, i) {
michael@0 31379 if (v.kind === 'text') {
michael@0 31380 xl.append(v);
michael@0 31381 }
michael@0 31382 });
michael@0 31383 return xl;
michael@0 31384 };
michael@0 31385 c.native = {
michael@0 31386 static: {
michael@0 31387 ignoreComments: {
michael@0 31388 get: function ignoreComments() {
michael@0 31389 return getBitFlags(c.flags, FLAG_IGNORE_COMMENTS);
michael@0 31390 },
michael@0 31391 set: function ignoreComments(newIgnore) {
michael@0 31392 c.flags = setBitFlags(c.flags, FLAG_IGNORE_COMMENTS, newIgnore);
michael@0 31393 }
michael@0 31394 },
michael@0 31395 ignoreProcessingInstructions: {
michael@0 31396 get: function ignoreProcessingInstructions() {
michael@0 31397 return getBitFlags(c.flags, FLAG_IGNORE_PROCESSING_INSTRUCTIONS);
michael@0 31398 },
michael@0 31399 set: function ignoreProcessingInstructions(newIgnore) {
michael@0 31400 c.flags = setBitFlags(c.flags, FLAG_IGNORE_PROCESSING_INSTRUCTIONS, newIgnore);
michael@0 31401 }
michael@0 31402 },
michael@0 31403 ignoreWhitespace: {
michael@0 31404 get: function ignoreWhitespace() {
michael@0 31405 return getBitFlags(c.flags, FLAG_IGNORE_WHITESPACE);
michael@0 31406 },
michael@0 31407 set: function ignoreWhitespace(newIgnore) {
michael@0 31408 c.flags = setBitFlags(c.flags, FLAG_IGNORE_WHITESPACE, newIgnore);
michael@0 31409 }
michael@0 31410 },
michael@0 31411 prettyPrinting: {
michael@0 31412 get: function prettyPrinting() {
michael@0 31413 return getBitFlags(c.flags, FLAG_PRETTY_PRINTING);
michael@0 31414 },
michael@0 31415 set: function prettyPrinting(newPretty) {
michael@0 31416 c.flags = setBitFlags(c.flags, FLAG_PRETTY_PRINTING, newPretty);
michael@0 31417 }
michael@0 31418 },
michael@0 31419 prettyIndent: {
michael@0 31420 get: function prettyIndent() {
michael@0 31421 return c.prettyIndent;
michael@0 31422 },
michael@0 31423 set: function prettyIndent(newIndent) {
michael@0 31424 c.prettyIndent = newIndent;
michael@0 31425 }
michael@0 31426 }
michael@0 31427 },
michael@0 31428 instance: {
michael@0 31429 toString: function () {
michael@0 31430 return toString(this);
michael@0 31431 },
michael@0 31432 hasOwnProperty: function hasOwnProperty(P) {
michael@0 31433 somewhatImplemented('XML.hasOwnProperty');
michael@0 31434 return this.hasProperty(P);
michael@0 31435 },
michael@0 31436 propertyIsEnumerable: function propertyIsEnumerable(P) {
michael@0 31437 notImplemented('XML.propertyIsEnumerable');
michael@0 31438 },
michael@0 31439 addNamespace: function addNamespace(ns) {
michael@0 31440 notImplemented('XML.addNamespace');
michael@0 31441 },
michael@0 31442 appendChild: function appendChild(child) {
michael@0 31443 var children = this.getProperty('*');
michael@0 31444 children.setProperty(children.length(), child);
michael@0 31445 return this;
michael@0 31446 },
michael@0 31447 attribute: function attribute(name) {
michael@0 31448 return this.getProperty(toAttributeName(name));
michael@0 31449 },
michael@0 31450 attributes: function attributes() {
michael@0 31451 return this.getProperty(toAttributeName('*'));
michael@0 31452 },
michael@0 31453 child: function child(name) {
michael@0 31454 return this.getProperty(name);
michael@0 31455 },
michael@0 31456 childIndex: function childIndex() {
michael@0 31457 notImplemented('XML.childIndex');
michael@0 31458 },
michael@0 31459 children: function children() {
michael@0 31460 var list = new XMLList();
michael@0 31461 Array.prototype.push.apply(list.children, this.children);
michael@0 31462 return list;
michael@0 31463 },
michael@0 31464 comments: function comments() {
michael@0 31465 return this.comments();
michael@0 31466 },
michael@0 31467 contains: function contains(value) {
michael@0 31468 notImplemented('XML.contains');
michael@0 31469 },
michael@0 31470 copy: function copy() {
michael@0 31471 return this.deepCopy();
michael@0 31472 },
michael@0 31473 descendants: function descendants(name) {
michael@0 31474 if (name === undefined) {
michael@0 31475 name = '*';
michael@0 31476 }
michael@0 31477 return this.descendants(name);
michael@0 31478 },
michael@0 31479 elements: function elements(name) {
michael@0 31480 var x = this;
michael@0 31481 var any = false;
michael@0 31482 if (name === undefined) {
michael@0 31483 name = '*';
michael@0 31484 any = true;
michael@0 31485 }
michael@0 31486 var name = toXMLName(name);
michael@0 31487 var xl = new XMLList(this.parent, name);
michael@0 31488 x.children.forEach(function (v, i) {
michael@0 31489 if (v.kind === 'element' && (any || v.name.localName === name.localName) && (name.uri === null || v.kind === 'element' && v.name.uri === name.uri)) {
michael@0 31490 xl.append(v);
michael@0 31491 }
michael@0 31492 });
michael@0 31493 return xl;
michael@0 31494 },
michael@0 31495 hasComplexContent: function hasComplexContent() {
michael@0 31496 notImplemented('XML.hasComplexContent');
michael@0 31497 },
michael@0 31498 hasSimpleContent: function hasSimpleContent() {
michael@0 31499 return this.hasSimpleContent();
michael@0 31500 },
michael@0 31501 inScopeNamespaces: function inScopeNamespaces() {
michael@0 31502 notImplemented('XML.inScopeNamespaces');
michael@0 31503 },
michael@0 31504 insertChildAfter: function insertChildAfter(child1, child2) {
michael@0 31505 notImplemented('XML.insertChildAfter');
michael@0 31506 },
michael@0 31507 insertChildBefore: function insertChildBefore(child1, child2) {
michael@0 31508 notImplemented('XML.insertChildBefore');
michael@0 31509 },
michael@0 31510 localName: function localName() {
michael@0 31511 return this.name.localName;
michael@0 31512 },
michael@0 31513 name: function name() {
michael@0 31514 return this.name;
michael@0 31515 },
michael@0 31516 _namespace: function _namespace(prefix, argc) {
michael@0 31517 somewhatImplemented('XML._namespace()');
michael@0 31518 return this.name.uri;
michael@0 31519 },
michael@0 31520 namespaceDeclarations: function namespaceDeclarations() {
michael@0 31521 return new XMLList();
michael@0 31522 },
michael@0 31523 nodeKind: function nodeKind() {
michael@0 31524 return this.kind;
michael@0 31525 },
michael@0 31526 normalize: function normalize() {
michael@0 31527 notImplemented('XML.normalize');
michael@0 31528 },
michael@0 31529 parent: function parent() {
michael@0 31530 notImplemented('XML.parent');
michael@0 31531 },
michael@0 31532 processingInstructions: function processingInstructions(name) {
michael@0 31533 notImplemented('XML.processingInstructions');
michael@0 31534 },
michael@0 31535 prependChild: function prependChild(value) {
michael@0 31536 notImplemented('XML.prependChild');
michael@0 31537 },
michael@0 31538 removeNamespace: function removeNamespace(ns) {
michael@0 31539 notImplemented('XML.removeNamespace');
michael@0 31540 },
michael@0 31541 replace: function replace(propertyName, value) {
michael@0 31542 var c, x, s, i;
michael@0 31543 x = this;
michael@0 31544 if (x.kind === 'text' || x.kind === 'comment' || x.kind === 'processing-instruction' || x.kind === 'attribute') {
michael@0 31545 return x;
michael@0 31546 }
michael@0 31547 if (!isXMLType(value)) {
michael@0 31548 c = value.toString();
michael@0 31549 } else {
michael@0 31550 c = value.deepCopy();
michael@0 31551 }
michael@0 31552 var i = propertyName >>> 0;
michael@0 31553 if (String(propertyName) === String(i)) {
michael@0 31554 x.replace(propertyName, c);
michael@0 31555 return x;
michael@0 31556 }
michael@0 31557 n = new QName(propertyName);
michael@0 31558 i = undefined;
michael@0 31559 for (k = x.length() - 1; k >= 0; k--) {
michael@0 31560 var v = x.children[k];
michael@0 31561 if (n.isAny || v.kind === 'element' && v.name.localName === n.localName && (n.uri === null || v.kind === 'element' && v.name.uri === n.uri)) {
michael@0 31562 if (i !== undefined) {
michael@0 31563 x.deleteByIndex(String(i));
michael@0 31564 }
michael@0 31565 i = k;
michael@0 31566 }
michael@0 31567 }
michael@0 31568 if (i !== undefined) {
michael@0 31569 x.replace(i.toString(), c);
michael@0 31570 }
michael@0 31571 return x;
michael@0 31572 },
michael@0 31573 setChildren: function setChildren(value) {
michael@0 31574 notImplemented('XML.setChildren');
michael@0 31575 },
michael@0 31576 setLocalName: function setLocalName(name) {
michael@0 31577 notImplemented('XML.setLocalName');
michael@0 31578 },
michael@0 31579 setName: function setName(name) {
michael@0 31580 notImplemented('XML.setName');
michael@0 31581 },
michael@0 31582 setNamespace: function setNamespace(ns) {
michael@0 31583 notImplemented('XML.setNamespace');
michael@0 31584 },
michael@0 31585 text: function text() {
michael@0 31586 return this.text();
michael@0 31587 },
michael@0 31588 toXMLString: function () {
michael@0 31589 return toXMLString(this);
michael@0 31590 },
michael@0 31591 notification: function notification() {
michael@0 31592 notImplemented('XML.notification');
michael@0 31593 },
michael@0 31594 setNotification: function setNotification(f) {
michael@0 31595 notImplemented('XML.setNotification');
michael@0 31596 }
michael@0 31597 }
michael@0 31598 };
michael@0 31599 return c;
michael@0 31600 };
michael@0 31601 XMLListClass = function XMLListClass(runtime, scope, instanceConstructor, baseClass) {
michael@0 31602 ASXMLList = function (value) {
michael@0 31603 if (!(this instanceof ASXMLList)) {
michael@0 31604 return callXMLList(value);
michael@0 31605 }
michael@0 31606 return constructXMLList(value);
michael@0 31607 };
michael@0 31608 function callXMLList(v) {
michael@0 31609 if (v === null || v === undefined) {
michael@0 31610 v = '';
michael@0 31611 }
michael@0 31612 return toXMLList(v);
michael@0 31613 }
michael@0 31614 function constructXMLList(val) {
michael@0 31615 if (val === null || val === undefined) {
michael@0 31616 val = '';
michael@0 31617 }
michael@0 31618 if (val.isXMLList) {
michael@0 31619 var xl = new XMLList();
michael@0 31620 xl.append(val);
michael@0 31621 return xl;
michael@0 31622 }
michael@0 31623 return toXMLList(val);
michael@0 31624 }
michael@0 31625 XMLList = function (targetObject, targetProperty) {
michael@0 31626 this.targetObject = targetObject ? targetObject : null;
michael@0 31627 this.targetProperty = targetProperty ? targetProperty : null;
michael@0 31628 this.children = [];
michael@0 31629 };
michael@0 31630 var c = new Class('XMLList', ASXMLList, ApplicationDomain.passthroughCallable(ASXMLList));
michael@0 31631 c.extend(baseClass);
michael@0 31632 var XLp = XMLList.prototype = ASXMLList.prototype;
michael@0 31633 XLp.canHandleProperties = true;
michael@0 31634 XLp.hasSimpleContent = function hasSimpleContent() {
michael@0 31635 if (this.length() === 0) {
michael@0 31636 return true;
michael@0 31637 } else if (this.length() === 1) {
michael@0 31638 return toXML(this).hasSimpleContent();
michael@0 31639 }
michael@0 31640 var result = true;
michael@0 31641 this.children.forEach(function (v) {
michael@0 31642 if (v.kind === 'element') {
michael@0 31643 result = false;
michael@0 31644 }
michael@0 31645 });
michael@0 31646 return result;
michael@0 31647 };
michael@0 31648 XLp.asGetProperty = asGetProperty;
michael@0 31649 XLp.asGetResolvedStringProperty = asGetResolvedStringPropertyFallback;
michael@0 31650 XLp.asSetProperty = asSetProperty;
michael@0 31651 XLp.asHasProperty = asHasProperty;
michael@0 31652 XLp.asCallProperty = asCallProperty;
michael@0 31653 XLp.setProperty = function (mn, v, isMethod) {
michael@0 31654 var x, i, r;
michael@0 31655 x = this;
michael@0 31656 i = mn >>> 0;
michael@0 31657 if (String(mn) === String(i)) {
michael@0 31658 var targetObject = this.targetObject;
michael@0 31659 var targetProperty = this.targetProperty;
michael@0 31660 if (targetObject !== null) {
michael@0 31661 r = targetObject.resolveValue();
michael@0 31662 if (r === null) {
michael@0 31663 return;
michael@0 31664 }
michael@0 31665 } else {
michael@0 31666 r = null;
michael@0 31667 }
michael@0 31668 if (i >= x.length()) {
michael@0 31669 if (r && r.isXMLList) {
michael@0 31670 if (r.length !== 1) {
michael@0 31671 return;
michael@0 31672 } else {
michael@0 31673 r = r.children[0];
michael@0 31674 }
michael@0 31675 }
michael@0 31676 if (r && r.kind !== 'element') {
michael@0 31677 return;
michael@0 31678 }
michael@0 31679 var y = new XML();
michael@0 31680 y.parent = r;
michael@0 31681 y.name = x.targetProperty;
michael@0 31682 if (targetProperty === null || targetProperty.localName === '*') {
michael@0 31683 y.name = null;
michael@0 31684 y.kind = 'text';
michael@0 31685 } else if (targetProperty.isAttr) {
michael@0 31686 var attributeExists = r.getProperty(y.name);
michael@0 31687 if (attributeExists.length() > 0) {
michael@0 31688 return;
michael@0 31689 }
michael@0 31690 r.kind = 'attribute';
michael@0 31691 } else {
michael@0 31692 y.kind = 'element';
michael@0 31693 }
michael@0 31694 i = x.length();
michael@0 31695 if (y.kind !== 'attribute') {
michael@0 31696 if (r !== null) {
michael@0 31697 if (i > 0) {
michael@0 31698 var j = 0;
michael@0 31699 while (j < r.length() - 1 && r.children[j] !== x.children[i - 1]) {
michael@0 31700 j++;
michael@0 31701 }
michael@0 31702 } else {
michael@0 31703 var j = r.length() - 1;
michael@0 31704 }
michael@0 31705 r.insert(String(j + 1), y);
michael@0 31706 }
michael@0 31707 if (v.isXML) {
michael@0 31708 y.name = v.name;
michael@0 31709 } else if (v.isXMLList) {
michael@0 31710 y.name = v.targetProperty;
michael@0 31711 }
michael@0 31712 }
michael@0 31713 x.append(y);
michael@0 31714 }
michael@0 31715 if (!v.isXML && !v.isXMLList || v.kind === 'text' || v.kind === 'attribute') {
michael@0 31716 v = toString(v);
michael@0 31717 }
michael@0 31718 if (x.children[i].kind === 'attribute') {
michael@0 31719 var z = toAttributeName(x.children[i].name);
michael@0 31720 x.children[i].parent.setProperty(z, v);
michael@0 31721 var attr = x.children[i].parent.getProperty(z);
michael@0 31722 x.children[i] = attr.children[0];
michael@0 31723 } else if (v.isXMLList) {
michael@0 31724 var c = v.deepCopy();
michael@0 31725 var parent = x.children[i].parent;
michael@0 31726 if (parent !== null) {
michael@0 31727 var q;
michael@0 31728 parent.children.some(function (v, p) {
michael@0 31729 if (v == x.children[i]) {
michael@0 31730 q = p;
michael@0 31731 return true;
michael@0 31732 }
michael@0 31733 });
michael@0 31734 parent.replace(q, c);
michael@0 31735 c.children.forEach(function (v, j) {
michael@0 31736 c.children[j] = parent.children[q >>> 0 + j];
michael@0 31737 });
michael@0 31738 }
michael@0 31739 if (c.length() === 0) {
michael@0 31740 for (var j = x + 1; j < x.length() - 1; j++) {
michael@0 31741 x.children[String(j - 1)] = x.children[j];
michael@0 31742 }
michael@0 31743 } else {
michael@0 31744 for (var j = x.length() - 1; j >= i + 1; j--) {
michael@0 31745 x.children[String(j + c.length() - 1)] = x.children[j];
michael@0 31746 }
michael@0 31747 }
michael@0 31748 for (var j = 0; j < c.length(); j++) {
michael@0 31749 x.children[i + j] = c.children[j];
michael@0 31750 }
michael@0 31751 } else if (v.isXML || (k = x.children[i].kind) === 'text' || k === 'comment' || k === 'processing-instruction') {
michael@0 31752 var parent = x.children[i].parent;
michael@0 31753 if (parent !== null) {
michael@0 31754 var q;
michael@0 31755 parent.children.some(function (v, p) {
michael@0 31756 if (v == x.children[i]) {
michael@0 31757 q = p;
michael@0 31758 return true;
michael@0 31759 }
michael@0 31760 });
michael@0 31761 parent.replace(q, v);
michael@0 31762 var v = parent.children[q];
michael@0 31763 }
michael@0 31764 if (typeof v === 'string') {
michael@0 31765 var t = new XML('text');
michael@0 31766 t.parent = x;
michael@0 31767 t.value = v;
michael@0 31768 x.children[i] = t;
michael@0 31769 } else {
michael@0 31770 x.children[i] = v;
michael@0 31771 }
michael@0 31772 } else {
michael@0 31773 x.children[i].setProperty('*', v);
michael@0 31774 }
michael@0 31775 } else if (x.length() <= 1) {
michael@0 31776 if (x.length() === 0) {
michael@0 31777 r = x.resolveValue();
michael@0 31778 if (r === null || r.length() !== 1) {
michael@0 31779 return;
michael@0 31780 }
michael@0 31781 x.append(r);
michael@0 31782 }
michael@0 31783 x.children[0].setProperty(mn, v);
michael@0 31784 }
michael@0 31785 };
michael@0 31786 XLp.getProperty = function (mn, isMethod) {
michael@0 31787 if (isMethod) {
michael@0 31788 var resolved = Multiname.isQName(mn) ? mn : this.resolveMultinameProperty(mn.namespaces, mn.name, mn.flags);
michael@0 31789 return this[Multiname.getQualifiedName(resolved)];
michael@0 31790 }
michael@0 31791 var x = this;
michael@0 31792 var i = mn >>> 0;
michael@0 31793 if (String(mn) === String(i)) {
michael@0 31794 return x.children[mn];
michael@0 31795 }
michael@0 31796 var name = toXMLName(mn);
michael@0 31797 var xl = new XMLList(this, name);
michael@0 31798 x.children.forEach(function (v, i) {
michael@0 31799 var xl2;
michael@0 31800 if (v.kind === 'element') {
michael@0 31801 xl2 = v.getProperty(mn);
michael@0 31802 if (xl2.length() > 0) {
michael@0 31803 xl.append(xl2);
michael@0 31804 }
michael@0 31805 }
michael@0 31806 });
michael@0 31807 return xl;
michael@0 31808 };
michael@0 31809 XLp.hasProperty = function (mn, isMethod) {
michael@0 31810 if (isMethod) {
michael@0 31811 var resolved = Multiname.isQName(mn) ? mn : this.resolveMultinameProperty(mn.namespaces, mn.name, mn.flags);
michael@0 31812 return !(!this[Multiname.getQualifiedName(resolved)]);
michael@0 31813 }
michael@0 31814 var x = this;
michael@0 31815 var i = mn >>> 0;
michael@0 31816 if (String(mn) === String(i)) {
michael@0 31817 return !(!x.children[mn]);
michael@0 31818 }
michael@0 31819 var name = toXMLName(mn);
michael@0 31820 return this.children.some(function (v, i) {
michael@0 31821 var xl2 = v.getProperty(mn);
michael@0 31822 if (xl2.length() > 0) {
michael@0 31823 return true;
michael@0 31824 }
michael@0 31825 });
michael@0 31826 };
michael@0 31827 XLp.delete = function (key, isMethod) {
michael@0 31828 };
michael@0 31829 XLp.append = function (val) {
michael@0 31830 if (val.isXMLList) {
michael@0 31831 this.targetObject = val.targetObject;
michael@0 31832 this.targetProperty = val.targetProperty;
michael@0 31833 if (val.length() === 0) {
michael@0 31834 return;
michael@0 31835 }
michael@0 31836 for (var i = 0; i < val.length(); i++) {
michael@0 31837 this.children.push(val.children[i]);
michael@0 31838 }
michael@0 31839 } else if (val.isXML) {
michael@0 31840 this.children.push(val);
michael@0 31841 }
michael@0 31842 };
michael@0 31843 XLp.length = function () {
michael@0 31844 return this.children.length;
michael@0 31845 };
michael@0 31846 XLp.resolve = function () {
michael@0 31847 var base = this.targetObject.resolveValue();
michael@0 31848 if (base === null) {
michael@0 31849 return null;
michael@0 31850 }
michael@0 31851 var target = this.targetObject.getProperty(this.targetProperty);
michael@0 31852 if (base.length === 0) {
michael@0 31853 notImplemented('XMLList.resolve');
michael@0 31854 base.setProperty(this.targetProperty, '');
michael@0 31855 target = base.getProperty(this.targetProperty);
michael@0 31856 return target;
michael@0 31857 }
michael@0 31858 };
michael@0 31859 XLp.deepCopy = function () {
michael@0 31860 var xl = new XMLList();
michael@0 31861 this.children.forEach(function (v, i) {
michael@0 31862 xl.children[i] = v.deepCopy();
michael@0 31863 });
michael@0 31864 return xl;
michael@0 31865 };
michael@0 31866 XLp.descendants = function (name) {
michael@0 31867 var xl = new XMLList(null);
michael@0 31868 this.children.forEach(function (v, i) {
michael@0 31869 if (v.kind === 'element') {
michael@0 31870 xl.append(v.descendants(name));
michael@0 31871 }
michael@0 31872 });
michael@0 31873 return xl;
michael@0 31874 };
michael@0 31875 XLp.resolveValue = function resolveValue() {
michael@0 31876 if (this.length() > 0) {
michael@0 31877 return this;
michael@0 31878 }
michael@0 31879 var x = this;
michael@0 31880 var name = x.name;
michael@0 31881 var targetObject = x.targetObject;
michael@0 31882 var targetProperty = x.targetProperty;
michael@0 31883 if (targetObject === null || targetProperty === null || name.isAttr || name.isAny) {
michael@0 31884 return null;
michael@0 31885 }
michael@0 31886 var base = targetObject.resolveValue();
michael@0 31887 if (base === null) {
michael@0 31888 return null;
michael@0 31889 }
michael@0 31890 var target = base.getProperty(targetProperty);
michael@0 31891 if (target.length() === 0) {
michael@0 31892 if (base.isXMLList && base.length() > 1) {
michael@0 31893 return null;
michael@0 31894 }
michael@0 31895 base.setProperty(targetProperty, '');
michael@0 31896 target = base.getProperty(targetProperty);
michael@0 31897 }
michael@0 31898 return target;
michael@0 31899 };
michael@0 31900 XLp.asGetEnumerableKeys = function asGetEnumerableKeys() {
michael@0 31901 if (XLp === this) {
michael@0 31902 return Object.prototype.asGetEnumerableKeys.call(this);
michael@0 31903 }
michael@0 31904 var keys = [];
michael@0 31905 this.children.forEach(function (v, i) {
michael@0 31906 keys.push(i);
michael@0 31907 });
michael@0 31908 return keys;
michael@0 31909 };
michael@0 31910 c.native = {
michael@0 31911 instance: {
michael@0 31912 init: function () {
michael@0 31913 }
michael@0 31914 }
michael@0 31915 };
michael@0 31916 XLp.isXMLList = true;
michael@0 31917 c.native = {
michael@0 31918 static: {},
michael@0 31919 instance: {
michael@0 31920 toString: function () {
michael@0 31921 return toString(this);
michael@0 31922 },
michael@0 31923 hasOwnProperty: function hasOwnProperty(P) {
michael@0 31924 somewhatImplemented('XMLList.hasOwnProperty');
michael@0 31925 return this.hasProperty(P);
michael@0 31926 },
michael@0 31927 propertyIsEnumerable: function propertyIsEnumerable(P) {
michael@0 31928 notImplemented('XMLList.propertyIsEnumerable');
michael@0 31929 },
michael@0 31930 attribute: function attribute(name) {
michael@0 31931 return this.getProperty(toAttributeName(name));
michael@0 31932 },
michael@0 31933 attributes: function attributes() {
michael@0 31934 return this.getProperty(toAttributeName('*'));
michael@0 31935 },
michael@0 31936 child: function child(propertyName) {
michael@0 31937 notImplemented('XMLList.child');
michael@0 31938 },
michael@0 31939 children: function children() {
michael@0 31940 var list = new XMLList();
michael@0 31941 for (var i = 0; i < this.children.length; i++) {
michael@0 31942 var child = this.children[i];
michael@0 31943 Array.prototype.push.apply(list.children, child.children);
michael@0 31944 }
michael@0 31945 return list;
michael@0 31946 },
michael@0 31947 comments: function comments() {
michael@0 31948 var x = this;
michael@0 31949 var xl = new XMLList(x, null);
michael@0 31950 x.children.forEach(function (v, i) {
michael@0 31951 if (v.kind === 'element') {
michael@0 31952 xl.append(v.comments());
michael@0 31953 }
michael@0 31954 });
michael@0 31955 return xl;
michael@0 31956 },
michael@0 31957 contains: function contains(value) {
michael@0 31958 for (var i = 0; i < this.children.length; i++) {
michael@0 31959 if (this.children[i] === value) {
michael@0 31960 return true;
michael@0 31961 }
michael@0 31962 }
michael@0 31963 return false;
michael@0 31964 },
michael@0 31965 copy: function copy() {
michael@0 31966 return this.deepCopy();
michael@0 31967 },
michael@0 31968 descendants: function descendants(name) {
michael@0 31969 return this.descendants(name === undefined ? '*' : name);
michael@0 31970 },
michael@0 31971 elements: function elements(name) {
michael@0 31972 var x = this;
michael@0 31973 var any = false;
michael@0 31974 if (name === undefined) {
michael@0 31975 name = '*';
michael@0 31976 any = true;
michael@0 31977 }
michael@0 31978 var name = toXMLName(name);
michael@0 31979 var xl = new XMLList(x, name);
michael@0 31980 x.children.forEach(function (v, i) {
michael@0 31981 if (v.kind === 'element') {
michael@0 31982 xl.append(v.comments());
michael@0 31983 }
michael@0 31984 });
michael@0 31985 return xl;
michael@0 31986 },
michael@0 31987 hasComplexContent: function hasComplexContent() {
michael@0 31988 notImplemented('XMLList.hasComplexContent');
michael@0 31989 },
michael@0 31990 hasSimpleContent: function hasSimpleContent() {
michael@0 31991 return this.hasSimpleContent();
michael@0 31992 },
michael@0 31993 length: function length() {
michael@0 31994 return this.children.length;
michael@0 31995 },
michael@0 31996 name: function name() {
michael@0 31997 return toXML(this).name;
michael@0 31998 },
michael@0 31999 normalize: function normalize() {
michael@0 32000 notImplemented('XMLList.normalize');
michael@0 32001 },
michael@0 32002 parent: function parent() {
michael@0 32003 notImplemented('XMLList.parent');
michael@0 32004 },
michael@0 32005 processingInstructions: function processingInstructions(name) {
michael@0 32006 notImplemented('XMLList.processingInstructions');
michael@0 32007 },
michael@0 32008 text: function text() {
michael@0 32009 var x = this;
michael@0 32010 var xl = new XMLList(x, null);
michael@0 32011 x.children.forEach(function (v, i) {
michael@0 32012 if (v.kind === 'text' || v.kind === 'element') {
michael@0 32013 xl.append(v.text());
michael@0 32014 }
michael@0 32015 });
michael@0 32016 return xl;
michael@0 32017 },
michael@0 32018 toXMLString: function () {
michael@0 32019 return toXMLString(this);
michael@0 32020 },
michael@0 32021 addNamespace: function addNamespace(ns) {
michael@0 32022 notImplemented('XMLList.addNamespace');
michael@0 32023 },
michael@0 32024 appendChild: function appendChild(child) {
michael@0 32025 toXML(this).appendChild(child);
michael@0 32026 return this;
michael@0 32027 },
michael@0 32028 childIndex: function childIndex() {
michael@0 32029 notImplemented('XMLList.childIndex');
michael@0 32030 },
michael@0 32031 inScopeNamespaces: function inScopeNamespaces() {
michael@0 32032 notImplemented('XMLList.inScopeNamespaces');
michael@0 32033 },
michael@0 32034 insertChildAfter: function insertChildAfter(child1, child2) {
michael@0 32035 notImplemented('XMLList.insertChildAfter');
michael@0 32036 },
michael@0 32037 insertChildBefore: function insertChildBefore(child1, child2) {
michael@0 32038 notImplemented('XMLList.insertChildBefore');
michael@0 32039 },
michael@0 32040 nodeKind: function nodeKind() {
michael@0 32041 return toXML(this).kind;
michael@0 32042 },
michael@0 32043 _namespace: function _namespace(prefix, argc) {
michael@0 32044 notImplemented('XMLList._namespace');
michael@0 32045 },
michael@0 32046 localName: function localName() {
michael@0 32047 notImplemented('XMLList.localName');
michael@0 32048 },
michael@0 32049 namespaceDeclarations: function namespaceDeclarations() {
michael@0 32050 somewhatImplemented('XMLList.prototype.namespaceDeclarations()');
michael@0 32051 return new XMLList();
michael@0 32052 },
michael@0 32053 prependChild: function prependChild(value) {
michael@0 32054 notImplemented('XMLList.prependChild');
michael@0 32055 },
michael@0 32056 removeNamespace: function removeNamespace(ns) {
michael@0 32057 notImplemented('XMLList.removeNamespace');
michael@0 32058 },
michael@0 32059 replace: function replace(propertyName, value) {
michael@0 32060 toXML(this).replace(propertyName, value);
michael@0 32061 return this;
michael@0 32062 },
michael@0 32063 setChildren: function setChildren(value) {
michael@0 32064 notImplemented('XMLList.setChildren');
michael@0 32065 },
michael@0 32066 setLocalName: function setLocalName(name) {
michael@0 32067 notImplemented('XMLList.setLocalName');
michael@0 32068 },
michael@0 32069 setName: function setName(name) {
michael@0 32070 notImplemented('XMLList.setName');
michael@0 32071 },
michael@0 32072 setNamespace: function setNamespace(ns) {
michael@0 32073 notImplemented('XMLList.setNamespace');
michael@0 32074 }
michael@0 32075 }
michael@0 32076 };
michael@0 32077 return c;
michael@0 32078 };
michael@0 32079 QNameClass = function QNameClass(runtime, scope, instanceConstructor, baseClass) {
michael@0 32080 QName = function QName(ns, name, isAttr) {
michael@0 32081 if (!(this instanceof QName)) {
michael@0 32082 if (name === undefined && ns instanceof QName) {
michael@0 32083 return ns;
michael@0 32084 } else {
michael@0 32085 return new QName(ns, name);
michael@0 32086 }
michael@0 32087 }
michael@0 32088 if (name === undefined) {
michael@0 32089 name = ns;
michael@0 32090 ns = undefined;
michael@0 32091 }
michael@0 32092 if (typeof ns === 'string' || ns instanceof QName) {
michael@0 32093 ns = new ASNamespace(ns);
michael@0 32094 }
michael@0 32095 var mn;
michael@0 32096 if (name instanceof QName) {
michael@0 32097 if (ns === undefined) {
michael@0 32098 mn = name.mn;
michael@0 32099 } else {
michael@0 32100 mn = new Multiname([
michael@0 32101 ns
michael@0 32102 ], name.mn.getName());
michael@0 32103 }
michael@0 32104 } else if (name instanceof Multiname) {
michael@0 32105 if (ns === undefined) {
michael@0 32106 if (name.isQName() || name.isAnyName() || name.isAnyNamespace()) {
michael@0 32107 mn = name;
michael@0 32108 } else {
michael@0 32109 mn = new Multiname([
michael@0 32110 getDefaultNamespace(scope)
michael@0 32111 ], name.getName(), name.flags);
michael@0 32112 }
michael@0 32113 } else {
michael@0 32114 mn = new Multiname([
michael@0 32115 ns
michael@0 32116 ], name.getName(), name.flags);
michael@0 32117 }
michael@0 32118 } else if (name === '*') {
michael@0 32119 mn = new Multiname([], null, isAttr ? Multiname.ATTRIBUTE : 0);
michael@0 32120 } else if (name === '@*') {
michael@0 32121 mn = new Multiname([], null, Multiname.ATTRIBUTE);
michael@0 32122 } else {
michael@0 32123 ns = ns === undefined ? getDefaultNamespace(scope) : ns;
michael@0 32124 if (name === undefined) {
michael@0 32125 mn = new Multiname([
michael@0 32126 ns
michael@0 32127 ], '');
michael@0 32128 } else {
michael@0 32129 mn = new Multiname([
michael@0 32130 ns
michael@0 32131 ], toString(name), isAttr ? Multiname.ATTRIBUTE : 0);
michael@0 32132 }
michael@0 32133 }
michael@0 32134 this.mn = mn;
michael@0 32135 this.isAny = mn.isAnyName();
michael@0 32136 this.isAnyNamespace = mn.isAnyNamespace();
michael@0 32137 this.isAttr = mn.isAttribute();
michael@0 32138 };
michael@0 32139 var c = new Class('QName', QName, ApplicationDomain.passthroughCallable(QName));
michael@0 32140 c.extend(baseClass);
michael@0 32141 QNp = QName.prototype;
michael@0 32142 defineNonEnumerableGetter(QNp, 'localName', function () {
michael@0 32143 if (!this._localName) {
michael@0 32144 this._localName = this.isAny ? '*' : this.mn.getName();
michael@0 32145 }
michael@0 32146 return this._localName;
michael@0 32147 });
michael@0 32148 defineNonEnumerableGetter(QNp, 'uri', function () {
michael@0 32149 if (!this._uri) {
michael@0 32150 var ns = this.mn.namespaces[0];
michael@0 32151 this._uri = ns && ns.uri ? ns.uri : this.isAny || this.isAnyNamespace ? null : '';
michael@0 32152 }
michael@0 32153 return this._uri;
michael@0 32154 });
michael@0 32155 defineNonEnumerableGetter(QNp, 'prefix', function () {
michael@0 32156 return this.mn.namespaces[0].prefix;
michael@0 32157 });
michael@0 32158 defineNonEnumerableSetter(QNp, 'prefix', function (prefix) {
michael@0 32159 this.mn.namespaces[0].prefix = prefix;
michael@0 32160 });
michael@0 32161 QNp.getNamespace = function (isns) {
michael@0 32162 if (this.uri === null) {
michael@0 32163 throw 'TypeError in QName.prototype.getNamespace()';
michael@0 32164 }
michael@0 32165 if (!isns) {
michael@0 32166 isns = [];
michael@0 32167 }
michael@0 32168 var ns;
michael@0 32169 for (var i = 0; i < isns.length; i++) {
michael@0 32170 if (this.uri === isns[i].uri) {
michael@0 32171 ns = isns[i];
michael@0 32172 }
michael@0 32173 }
michael@0 32174 if (!ns) {
michael@0 32175 ns = ASNamespace.createNamespace(this.uri);
michael@0 32176 }
michael@0 32177 return ns;
michael@0 32178 };
michael@0 32179 c.native = {
michael@0 32180 static: {},
michael@0 32181 instance: {
michael@0 32182 localName: {
michael@0 32183 get: function localName() {
michael@0 32184 return this.localName;
michael@0 32185 }
michael@0 32186 },
michael@0 32187 uri: {
michael@0 32188 get: function uri() {
michael@0 32189 return this.uri;
michael@0 32190 }
michael@0 32191 }
michael@0 32192 }
michael@0 32193 };
michael@0 32194 return c;
michael@0 32195 };
michael@0 32196 }());
michael@0 32197 var AMFUtils = function AMFUtilsClosure() {
michael@0 32198 var AMF0_NUMBER_MARKER = 0;
michael@0 32199 var AMF0_BOOLEAN_MARKER = 1;
michael@0 32200 var AMF0_STRING_MARKER = 2;
michael@0 32201 var AMF0_OBJECT_MARKER = 3;
michael@0 32202 var AMF0_NULL_MARKER = 5;
michael@0 32203 var AMF0_UNDEFINED_MARKER = 6;
michael@0 32204 var AMF0_REFERENCE_MARKER = 7;
michael@0 32205 var AMF0_ECMA_ARRAY_MARKER = 8;
michael@0 32206 var AMF0_OBJECT_END_MARKER = 9;
michael@0 32207 var AMF0_STRICT_ARRAY_MARKER = 10;
michael@0 32208 var AMF0_DATE_MARKER = 11;
michael@0 32209 var AMF0_LONG_STRING_MARKER = 12;
michael@0 32210 var AMF0_XML_MARKER = 15;
michael@0 32211 var AMF0_TYPED_OBJECT_MARKER = 16;
michael@0 32212 var AMF0_AVMPLUS_MARKER = 17;
michael@0 32213 function writeString(ba, s) {
michael@0 32214 if (s.length > 65535) {
michael@0 32215 throw 'AMF short string exceeded';
michael@0 32216 }
michael@0 32217 if (!s.length) {
michael@0 32218 ba.writeByte(0);
michael@0 32219 ba.writeByte(0);
michael@0 32220 return;
michael@0 32221 }
michael@0 32222 var bytes = utf8decode(s);
michael@0 32223 ba.writeByte(bytes.length >> 8 & 255);
michael@0 32224 ba.writeByte(bytes.length & 255);
michael@0 32225 for (var i = 0; i < bytes.length; i++) {
michael@0 32226 ba.writeByte(bytes[i]);
michael@0 32227 }
michael@0 32228 }
michael@0 32229 function readString(ba) {
michael@0 32230 var byteLength = ba.readByte() << 8 | ba.readByte();
michael@0 32231 if (!byteLength) {
michael@0 32232 return '';
michael@0 32233 }
michael@0 32234 var buffer = new Uint8Array(byteLength);
michael@0 32235 for (var i = 0; i < byteLength; i++) {
michael@0 32236 buffer[i] = ba.readByte();
michael@0 32237 }
michael@0 32238 return utf8encode(buffer);
michael@0 32239 }
michael@0 32240 function writeDouble(ba, value) {
michael@0 32241 var buffer = new ArrayBuffer(8);
michael@0 32242 var view = new DataView(buffer);
michael@0 32243 view.setFloat64(0, value, false);
michael@0 32244 for (var i = 0; i < buffer.byteLength; i++) {
michael@0 32245 ba.writeByte(view.getUint8(i));
michael@0 32246 }
michael@0 32247 }
michael@0 32248 function readDouble(ba) {
michael@0 32249 var buffer = new ArrayBuffer(8);
michael@0 32250 var view = new DataView(buffer);
michael@0 32251 for (var i = 0; i < buffer.byteLength; i++) {
michael@0 32252 view.setUint8(i, ba.readByte());
michael@0 32253 }
michael@0 32254 return view.getFloat64(0, false);
michael@0 32255 }
michael@0 32256 function setAvmProperty(obj, propertyName, value) {
michael@0 32257 obj.asSetPublicProperty(propertyName, value);
michael@0 32258 }
michael@0 32259 var amf0 = {
michael@0 32260 write: function (ba, obj) {
michael@0 32261 switch (typeof obj) {
michael@0 32262 case 'boolean':
michael@0 32263 ba.writeByte(AMF0_BOOLEAN_MARKER);
michael@0 32264 ba.writeByte(obj ? 1 : 0);
michael@0 32265 break;
michael@0 32266 case 'number':
michael@0 32267 ba.writeByte(AMF0_NUMBER_MARKER);
michael@0 32268 writeDouble(ba, obj);
michael@0 32269 break;
michael@0 32270 case 'undefined':
michael@0 32271 ba.writeByte(AMF0_UNDEFINED_MARKER);
michael@0 32272 break;
michael@0 32273 case 'string':
michael@0 32274 ba.writeByte(AMF0_STRING_MARKER);
michael@0 32275 writeString(ba, obj);
michael@0 32276 break;
michael@0 32277 case 'object':
michael@0 32278 if (obj === null) {
michael@0 32279 ba.writeByte(AMF0_NULL_MARKER);
michael@0 32280 } else if (Array.isArray(obj)) {
michael@0 32281 ba.writeByte(AMF0_ECMA_ARRAY_MARKER);
michael@0 32282 ba.writeByte(obj.length >>> 24 & 255);
michael@0 32283 ba.writeByte(obj.length >> 16 & 255);
michael@0 32284 ba.writeByte(obj.length >> 8 & 255);
michael@0 32285 ba.writeByte(obj.length & 255);
michael@0 32286 forEachPublicProperty(obj, function (key, value) {
michael@0 32287 writeString(ba, key);
michael@0 32288 this.write(ba, value);
michael@0 32289 }, this);
michael@0 32290 ba.writeByte(0);
michael@0 32291 ba.writeByte(0);
michael@0 32292 ba.writeByte(AMF0_OBJECT_END_MARKER);
michael@0 32293 } else {
michael@0 32294 ba.writeByte(AMF0_OBJECT_MARKER);
michael@0 32295 forEachPublicProperty(obj, function (key, value) {
michael@0 32296 writeString(ba, key);
michael@0 32297 this.write(ba, value);
michael@0 32298 }, this);
michael@0 32299 ba.writeByte(0);
michael@0 32300 ba.writeByte(0);
michael@0 32301 ba.writeByte(AMF0_OBJECT_END_MARKER);
michael@0 32302 }
michael@0 32303 return;
michael@0 32304 }
michael@0 32305 },
michael@0 32306 read: function (ba) {
michael@0 32307 var marker = ba.readByte();
michael@0 32308 switch (marker) {
michael@0 32309 case AMF0_NUMBER_MARKER:
michael@0 32310 return readDouble(ba);
michael@0 32311 case AMF0_BOOLEAN_MARKER:
michael@0 32312 return !(!ba.readByte());
michael@0 32313 case AMF0_STRING_MARKER:
michael@0 32314 return readString(ba);
michael@0 32315 case AMF0_OBJECT_MARKER:
michael@0 32316 var obj = {};
michael@0 32317 while (true) {
michael@0 32318 var key = readString(ba);
michael@0 32319 if (!key.length)
michael@0 32320 break;
michael@0 32321 setAvmProperty(obj, key, this.read(ba));
michael@0 32322 }
michael@0 32323 if (ba.readByte() !== AMF0_OBJECT_END_MARKER) {
michael@0 32324 throw 'AMF0 End marker is not found';
michael@0 32325 }
michael@0 32326 return obj;
michael@0 32327 case AMF0_NULL_MARKER:
michael@0 32328 return null;
michael@0 32329 case AMF0_UNDEFINED_MARKER:
michael@0 32330 return undefined;
michael@0 32331 case AMF0_ECMA_ARRAY_MARKER:
michael@0 32332 var obj = [];
michael@0 32333 obj.length = ba.readByte() << 24 | ba.readByte() << 16 | ba.readByte() << 8 | ba.readByte();
michael@0 32334 while (true) {
michael@0 32335 var key = readString(ba);
michael@0 32336 if (!key.length)
michael@0 32337 break;
michael@0 32338 setAvmProperty(obj, key, this.read(ba));
michael@0 32339 }
michael@0 32340 if (ba.readByte() !== AMF0_OBJECT_END_MARKER) {
michael@0 32341 throw 'AMF0 End marker is not found';
michael@0 32342 }
michael@0 32343 return obj;
michael@0 32344 case AMF0_STRICT_ARRAY_MARKER:
michael@0 32345 var obj = [];
michael@0 32346 obj.length = ba.readByte() << 24 | ba.readByte() << 16 | ba.readByte() << 8 | ba.readByte();
michael@0 32347 for (var i = 0; i < obj.length; i++) {
michael@0 32348 obj[i] = this.read(ba);
michael@0 32349 }
michael@0 32350 return obj;
michael@0 32351 case AMF0_AVMPLUS_MARKER:
michael@0 32352 return readAmf3Data(ba, {});
michael@0 32353 default:
michael@0 32354 throw 'AMF0 Unknown marker ' + marker;
michael@0 32355 }
michael@0 32356 }
michael@0 32357 };
michael@0 32358 var AMF3_UNDEFINED_MARKER = 0;
michael@0 32359 var AMF3_NULL_MARKER = 1;
michael@0 32360 var AMF3_FALSE_MARKER = 2;
michael@0 32361 var AMF3_TRUE_MARKER = 3;
michael@0 32362 var AMF3_INTEGER_MARKER = 4;
michael@0 32363 var AMF3_DOUBLE_MARKER = 5;
michael@0 32364 var AMF3_STRING_MARKER = 6;
michael@0 32365 var AMF3_XML_DOC_MARKER = 7;
michael@0 32366 var AMF3_DATE_MARKER = 8;
michael@0 32367 var AMF3_ARRAY_MARKER = 9;
michael@0 32368 var AMF3_OBJECT_MARKER = 10;
michael@0 32369 var AMF3_XML_MARKER = 11;
michael@0 32370 var AMF3_BYTEARRAY_MARKER = 12;
michael@0 32371 var AMF3_VECTOR_INT_MARKER = 13;
michael@0 32372 var AMF3_VECTOR_UINT_MARKER = 14;
michael@0 32373 var AMF3_VECTOR_DOUBLE_MARKER = 15;
michael@0 32374 var AMF3_VECTOR_OBJECT_MARKER = 16;
michael@0 32375 var AMF3_DICTIONARY_MARKER = 17;
michael@0 32376 function readU29(ba) {
michael@0 32377 var b1 = ba.readByte();
michael@0 32378 if ((b1 & 128) === 0) {
michael@0 32379 return b1;
michael@0 32380 }
michael@0 32381 var b2 = ba.readByte();
michael@0 32382 if ((b2 & 128) === 0) {
michael@0 32383 return (b1 & 127) << 7 | b2;
michael@0 32384 }
michael@0 32385 var b3 = ba.readByte();
michael@0 32386 if ((b3 & 128) === 0) {
michael@0 32387 return (b1 & 127) << 14 | (b2 & 127) << 7 | b3;
michael@0 32388 }
michael@0 32389 var b4 = ba.readByte();
michael@0 32390 return (b1 & 127) << 22 | (b2 & 127) << 15 | (b3 & 127) << 8 | b4;
michael@0 32391 }
michael@0 32392 function writeU29(ba, value) {
michael@0 32393 if ((value & 4294967168) === 0) {
michael@0 32394 ba.writeByte(value & 127);
michael@0 32395 } else if ((value & 4294950912) === 0) {
michael@0 32396 ba.writeByte(128 | value >> 7 & 127);
michael@0 32397 ba.writeByte(value & 127);
michael@0 32398 } else if ((value & 4292870144) === 0) {
michael@0 32399 ba.writeByte(128 | value >> 14 & 127);
michael@0 32400 ba.writeByte(128 | value >> 7 & 127);
michael@0 32401 ba.writeByte(value & 127);
michael@0 32402 } else if ((value & 3221225472) === 0) {
michael@0 32403 ba.writeByte(128 | value >> 22 & 127);
michael@0 32404 ba.writeByte(128 | value >> 15 & 127);
michael@0 32405 ba.writeByte(128 | value >> 8 & 127);
michael@0 32406 ba.writeByte(value & 255);
michael@0 32407 } else {
michael@0 32408 throw 'AMF3 U29 range';
michael@0 32409 }
michael@0 32410 }
michael@0 32411 function readUTF8vr(ba, caches) {
michael@0 32412 var u29s = readU29(ba);
michael@0 32413 if (u29s === 1) {
michael@0 32414 return '';
michael@0 32415 }
michael@0 32416 var stringsCache = caches.stringsCache || (caches.stringsCache = []);
michael@0 32417 if ((u29s & 1) === 0) {
michael@0 32418 return stringsCache[u29s >> 1];
michael@0 32419 }
michael@0 32420 var byteLength = u29s >> 1;
michael@0 32421 var buffer = new Uint8Array(byteLength);
michael@0 32422 for (var i = 0; i < byteLength; i++) {
michael@0 32423 buffer[i] = ba.readByte();
michael@0 32424 }
michael@0 32425 var value = utf8encode(buffer);
michael@0 32426 stringsCache.push(value);
michael@0 32427 return value;
michael@0 32428 }
michael@0 32429 function writeUTF8vr(ba, value, caches) {
michael@0 32430 if (value === '') {
michael@0 32431 ba.writeByte(1);
michael@0 32432 return;
michael@0 32433 }
michael@0 32434 var stringsCache = caches.stringsCache || (caches.stringsCache = []);
michael@0 32435 var index = stringsCache.indexOf(value);
michael@0 32436 if (index >= 0) {
michael@0 32437 writeU29(ba, index << 1);
michael@0 32438 return;
michael@0 32439 }
michael@0 32440 stringsCache.push(value);
michael@0 32441 var bytes = utf8decode(value);
michael@0 32442 writeU29(ba, 1 | bytes.length << 1);
michael@0 32443 for (var i = 0; i < bytes.length; i++) {
michael@0 32444 ba.writeByte(bytes[i]);
michael@0 32445 }
michael@0 32446 }
michael@0 32447 function readAmf3Data(ba, caches) {
michael@0 32448 var marker = ba.readByte();
michael@0 32449 switch (marker) {
michael@0 32450 case AMF3_NULL_MARKER:
michael@0 32451 return null;
michael@0 32452 case AMF3_UNDEFINED_MARKER:
michael@0 32453 return undefined;
michael@0 32454 case AMF3_FALSE_MARKER:
michael@0 32455 return false;
michael@0 32456 case AMF3_TRUE_MARKER:
michael@0 32457 return true;
michael@0 32458 case AMF3_INTEGER_MARKER:
michael@0 32459 return readU29(ba);
michael@0 32460 case AMF3_DOUBLE_MARKER:
michael@0 32461 return readDouble(ba);
michael@0 32462 case AMF3_STRING_MARKER:
michael@0 32463 return readUTF8vr(ba, caches);
michael@0 32464 case AMF3_DATE_MARKER:
michael@0 32465 return new Date(readDouble(ba));
michael@0 32466 case AMF3_OBJECT_MARKER:
michael@0 32467 var u29o = readU29(ba);
michael@0 32468 if ((u29o & 1) === 0) {
michael@0 32469 return caches.objectsCache[u29o >> 1];
michael@0 32470 }
michael@0 32471 if ((u29o & 4) !== 0) {
michael@0 32472 throw 'AMF3 Traits-Ext is not supported';
michael@0 32473 }
michael@0 32474 var traits, objectClass;
michael@0 32475 if ((u29o & 2) === 0) {
michael@0 32476 traits = caches.traitsCache[u29o >> 2];
michael@0 32477 objectClass = traits.class;
michael@0 32478 } else {
michael@0 32479 traits = {};
michael@0 32480 var aliasName = readUTF8vr(ba, caches);
michael@0 32481 traits.className = aliasName;
michael@0 32482 objectClass = aliasName && aliasesCache.names[aliasName];
michael@0 32483 traits.class = objectClass;
michael@0 32484 traits.isDynamic = (u29o & 8) !== 0;
michael@0 32485 traits.members = [];
michael@0 32486 var slots = objectClass && objectClass.instanceBindings.slots;
michael@0 32487 for (var i = 0, j = u29o >> 4; i < j; i++) {
michael@0 32488 var traitName = readUTF8vr(ba, caches);
michael@0 32489 var slot = null;
michael@0 32490 for (var j = 1; slots && j < slots.length; j++) {
michael@0 32491 if (slots[j].name.name === traitName) {
michael@0 32492 slot = slots[j];
michael@0 32493 break;
michael@0 32494 }
michael@0 32495 }
michael@0 32496 traits.members.push(slot ? Multiname.getQualifiedName(slot.name) : Multiname.getPublicQualifiedName(traitName));
michael@0 32497 }
michael@0 32498 (caches.traitsCache || (caches.traitsCache = [])).push(traits);
michael@0 32499 }
michael@0 32500 var obj = objectClass ? objectClass.createInstance() : {};
michael@0 32501 (caches.objectsCache || (caches.objectsCache = [])).push(obj);
michael@0 32502 for (var i = 0; i < traits.members.length; i++) {
michael@0 32503 var value = readAmf3Data(ba, caches);
michael@0 32504 obj[traits.members[i]] = value;
michael@0 32505 }
michael@0 32506 if (traits.isDynamic) {
michael@0 32507 while (true) {
michael@0 32508 var key = readUTF8vr(ba, caches);
michael@0 32509 if (!key.length)
michael@0 32510 break;
michael@0 32511 var value = readAmf3Data(ba, caches);
michael@0 32512 setAvmProperty(obj, key, value);
michael@0 32513 }
michael@0 32514 }
michael@0 32515 return obj;
michael@0 32516 case AMF3_ARRAY_MARKER:
michael@0 32517 var u29o = readU29(ba);
michael@0 32518 if ((u29o & 1) === 0) {
michael@0 32519 return caches.objectsCache[u29o >> 1];
michael@0 32520 }
michael@0 32521 var obj = [];
michael@0 32522 (caches.objectsCache || (caches.objectsCache = [])).push(obj);
michael@0 32523 var densePortionLength = u29o >> 1;
michael@0 32524 while (true) {
michael@0 32525 var key = readUTF8vr(ba, caches);
michael@0 32526 if (!key.length)
michael@0 32527 break;
michael@0 32528 var value = readAmf3Data(ba, caches);
michael@0 32529 setAvmProperty(obj, key, value);
michael@0 32530 }
michael@0 32531 for (var i = 0; i < densePortionLength; i++) {
michael@0 32532 var value = readAmf3Data(ba, caches);
michael@0 32533 setAvmProperty(obj, i, value);
michael@0 32534 }
michael@0 32535 return obj;
michael@0 32536 default:
michael@0 32537 throw 'AMF3 Unknown marker ' + marker;
michael@0 32538 }
michael@0 32539 }
michael@0 32540 function writeCachedReference(ba, obj, caches) {
michael@0 32541 var objectsCache = caches.objectsCache || (caches.objectsCache = []);
michael@0 32542 var index = objectsCache.indexOf(obj);
michael@0 32543 if (index < 0) {
michael@0 32544 objectsCache.push(obj);
michael@0 32545 return false;
michael@0 32546 }
michael@0 32547 writeU29(ba, index << 1);
michael@0 32548 return true;
michael@0 32549 }
michael@0 32550 function writeAmf3Data(ba, obj, caches) {
michael@0 32551 switch (typeof obj) {
michael@0 32552 case 'boolean':
michael@0 32553 ba.writeByte(obj ? AMF3_TRUE_MARKER : AMF3_FALSE_MARKER);
michael@0 32554 break;
michael@0 32555 case 'number':
michael@0 32556 if (obj === (obj | 0)) {
michael@0 32557 ba.writeByte(AMF3_INTEGER_MARKER);
michael@0 32558 writeU29(ba, obj);
michael@0 32559 } else {
michael@0 32560 ba.writeByte(AMF3_DOUBLE_MARKER);
michael@0 32561 writeDouble(ba, obj);
michael@0 32562 }
michael@0 32563 break;
michael@0 32564 case 'undefined':
michael@0 32565 ba.writeByte(AMF3_UNDEFINED_MARKER);
michael@0 32566 break;
michael@0 32567 case 'string':
michael@0 32568 ba.writeByte(AMF3_STRING_MARKER);
michael@0 32569 writeUTF8vr(ba, obj, caches);
michael@0 32570 break;
michael@0 32571 case 'object':
michael@0 32572 if (obj === null) {
michael@0 32573 ba.writeByte(AMF3_NULL_MARKER);
michael@0 32574 } else if (Array.isArray(obj)) {
michael@0 32575 ba.writeByte(AMF3_ARRAY_MARKER);
michael@0 32576 if (writeCachedReference(ba, obj, caches))
michael@0 32577 break;
michael@0 32578 var densePortionLength = 0;
michael@0 32579 while (densePortionLength in obj) {
michael@0 32580 ++densePortionLength;
michael@0 32581 }
michael@0 32582 writeU29(ba, densePortionLength << 1 | 1);
michael@0 32583 forEachPublicProperty(obj, function (i, value) {
michael@0 32584 if (isNumeric(i) && i >= 0 && i < densePortionLength) {
michael@0 32585 return;
michael@0 32586 }
michael@0 32587 writeUTF8vr(ba, i, caches);
michael@0 32588 writeAmf3Data(ba, value, caches);
michael@0 32589 });
michael@0 32590 writeUTF8vr(ba, '', caches);
michael@0 32591 for (var j = 0; j < densePortionLength; j++) {
michael@0 32592 writeAmf3Data(ba, obj[j], caches);
michael@0 32593 }
michael@0 32594 } else if (obj instanceof Date) {
michael@0 32595 ba.writeByte(AMF3_DATE_MARKER);
michael@0 32596 if (writeCachedReference(ba, obj, caches))
michael@0 32597 break;
michael@0 32598 writeU29(ba, 1);
michael@0 32599 writeDouble(ba, obj.valueOf());
michael@0 32600 } else {
michael@0 32601 ba.writeByte(AMF3_OBJECT_MARKER);
michael@0 32602 if (writeCachedReference(ba, obj, caches))
michael@0 32603 break;
michael@0 32604 var isDynamic = true;
michael@0 32605 var objectClass = obj.class;
michael@0 32606 if (objectClass) {
michael@0 32607 isDynamic = !objectClass.classInfo.instanceInfo.isSealed();
michael@0 32608 var aliasName = aliasesCache.classes.get(objectClass) || '';
michael@0 32609 var traits, traitsCount;
michael@0 32610 var traitsCache = caches.traitsCache || (caches.traitsCache = []);
michael@0 32611 var traitsInfos = caches.traitsInfos || (caches.traitsInfos = []);
michael@0 32612 var traitsRef = traitsCache.indexOf(objectClass);
michael@0 32613 if (traitsRef < 0) {
michael@0 32614 var slots = objectClass.instanceBindings.slots;
michael@0 32615 traits = [];
michael@0 32616 var traitsNames = [];
michael@0 32617 for (var i = 1; i < slots.length; i++) {
michael@0 32618 var slot = slots[i];
michael@0 32619 if (!slot.name.getNamespace().isPublic()) {
michael@0 32620 continue;
michael@0 32621 }
michael@0 32622 traits.push(Multiname.getQualifiedName(slot.name));
michael@0 32623 traitsNames.push(slot.name.name);
michael@0 32624 }
michael@0 32625 traitsCache.push(objectClass);
michael@0 32626 traitsInfos.push(traits);
michael@0 32627 traitsCount = traitsNames.length;
michael@0 32628 writeU29(ba, (isDynamic ? 11 : 3) + (traitsCount << 4));
michael@0 32629 writeUTF8vr(ba, aliasName, caches);
michael@0 32630 for (var i = 0; i < traitsCount; i++) {
michael@0 32631 writeUTF8vr(ba, traitsNames[i], caches);
michael@0 32632 }
michael@0 32633 } else {
michael@0 32634 traits = traitsInfos[traitsRef];
michael@0 32635 traitsCount = traits.length;
michael@0 32636 writeU29(ba, 1 + (traitsRef << 2));
michael@0 32637 }
michael@0 32638 for (var i = 0; i < traitsCount; i++) {
michael@0 32639 writeAmf3Data(ba, obj[traits[i]], caches);
michael@0 32640 }
michael@0 32641 } else {
michael@0 32642 writeU29(ba, 11);
michael@0 32643 writeUTF8vr(ba, '', caches);
michael@0 32644 }
michael@0 32645 if (isDynamic) {
michael@0 32646 forEachPublicProperty(obj, function (i, value) {
michael@0 32647 writeUTF8vr(ba, i, caches);
michael@0 32648 writeAmf3Data(ba, value, caches);
michael@0 32649 });
michael@0 32650 writeUTF8vr(ba, '', caches);
michael@0 32651 }
michael@0 32652 }
michael@0 32653 return;
michael@0 32654 }
michael@0 32655 }
michael@0 32656 var aliasesCache = {
michael@0 32657 classes: new WeakMap(),
michael@0 32658 names: Object.create(null)
michael@0 32659 };
michael@0 32660 var amf3 = {
michael@0 32661 write: function (ba, obj) {
michael@0 32662 writeAmf3Data(ba, obj, {});
michael@0 32663 },
michael@0 32664 read: function (ba) {
michael@0 32665 return readAmf3Data(ba, {});
michael@0 32666 }
michael@0 32667 };
michael@0 32668 return {
michael@0 32669 encodings: [
michael@0 32670 amf0,
michael@0 32671 null,
michael@0 32672 null,
michael@0 32673 amf3
michael@0 32674 ],
michael@0 32675 aliasesCache: aliasesCache
michael@0 32676 };
michael@0 32677 }();
michael@0 32678 function ProxyClass(runtime, scope, instanceConstructor, baseClass) {
michael@0 32679 function ProxyConstructor() {
michael@0 32680 somewhatImplemented('Proxy');
michael@0 32681 }
michael@0 32682 var c = new Class('Proxy', ProxyConstructor, ApplicationDomain.coerceCallable(ProxyConstructor));
michael@0 32683 c.extendBuiltin(baseClass);
michael@0 32684 return c;
michael@0 32685 }
michael@0 32686 var proxyTrapQns = {
michael@0 32687 'getProperty': null,
michael@0 32688 'setProperty': null,
michael@0 32689 'hasProperty': null,
michael@0 32690 'callProperty': null
michael@0 32691 };
michael@0 32692 for (var name in proxyTrapQns) {
michael@0 32693 proxyTrapQns[name] = VM_OPEN_METHOD_PREFIX + Multiname.getQualifiedName(new Multiname([
michael@0 32694 ASNamespace.PROXY
michael@0 32695 ], name));
michael@0 32696 }
michael@0 32697 function isProxyObject(obj) {
michael@0 32698 return obj[VM_IS_PROXY];
michael@0 32699 }
michael@0 32700 function nameFromQualifiedName(qn) {
michael@0 32701 if (isNumeric(qn)) {
michael@0 32702 return qn;
michael@0 32703 }
michael@0 32704 var mn = Multiname.fromQualifiedName(qn);
michael@0 32705 if (mn === undefined) {
michael@0 32706 return undefined;
michael@0 32707 }
michael@0 32708 return mn.name;
michael@0 32709 }
michael@0 32710 function hasNonProxyingCaller() {
michael@0 32711 var caller = arguments.callee;
michael@0 32712 var maxDepth = 5;
michael@0 32713 var domain;
michael@0 32714 for (var i = 0; i < maxDepth && caller; i++) {
michael@0 32715 if (caller === nonProxyingHasProperty) {
michael@0 32716 return true;
michael@0 32717 }
michael@0 32718 caller = caller.caller;
michael@0 32719 }
michael@0 32720 return false;
michael@0 32721 }
michael@0 32722 function installProxyClassWrapper(cls) {
michael@0 32723 var TRACE_PROXY = false;
michael@0 32724 if (TRACE_PROXY) {
michael@0 32725 print('proxy wrapping, class: ' + cls);
michael@0 32726 }
michael@0 32727 var instanceConstructor = cls.instanceConstructor;
michael@0 32728 function construct() {
michael@0 32729 if (TRACE_PROXY) {
michael@0 32730 print('proxy create, class: ' + cls);
michael@0 32731 }
michael@0 32732 var target = Object.create(instanceConstructor.prototype);
michael@0 32733 var proxy = Proxy.create({
michael@0 32734 get: function (o, qn) {
michael@0 32735 if (qn === VM_IS_PROXY) {
michael@0 32736 TRACE_PROXY && print('proxy check');
michael@0 32737 return true;
michael@0 32738 }
michael@0 32739 if (qn === VM_CALL_PROXY) {
michael@0 32740 TRACE_PROXY && print('proxy get caller');
michael@0 32741 return function apply(mn, receiver, args) {
michael@0 32742 receiver = receiver ? target : null;
michael@0 32743 if (TRACE_PROXY) {
michael@0 32744 print('proxy call, class: ' + target.class + ', mn: ' + mn + 'hasNonProxyingCallerr: ' + hasNonProxyingCaller());
michael@0 32745 }
michael@0 32746 var resolved = Multiname.isQName(mn) ? mn : target.resolveMultinameProperty(mn.namespaces, mn.name, mn.flags);
michael@0 32747 var qn = resolved ? Multiname.getQualifiedName(resolved) : Multiname.getPublicQualifiedName(mn.name);
michael@0 32748 if (!nameInTraits(target, qn)) {
michael@0 32749 return target[proxyTrapQns.callProperty](mn.name, args);
michael@0 32750 }
michael@0 32751 if (TRACE_PROXY) {
michael@0 32752 TRACE_PROXY && print('> proxy pass through ' + resolved);
michael@0 32753 }
michael@0 32754 if (target.asOpenMethods && target.asOpenMethods[qn]) {
michael@0 32755 return target.asOpenMethods[qn].apply(o, args);
michael@0 32756 }
michael@0 32757 return undefined;
michael@0 32758 };
michael@0 32759 }
michael@0 32760 if (TRACE_PROXY) {
michael@0 32761 print('proxy get, class: ' + target.class + ', qn: ' + qn + 'hasNonProxyingCallerr: ' + hasNonProxyingCaller());
michael@0 32762 }
michael@0 32763 if (!hasNonProxyingCaller()) {
michael@0 32764 var name = nameFromQualifiedName(qn);
michael@0 32765 if (name !== undefined && !nameInTraits(target, qn)) {
michael@0 32766 return target[proxyTrapQns.getProperty](name);
michael@0 32767 }
michael@0 32768 }
michael@0 32769 if (target.asOpenMethods && target.asOpenMethods[qn]) {
michael@0 32770 return bindSafely(target.asOpenMethods[qn], o);
michael@0 32771 }
michael@0 32772 TRACE_PROXY && print('> proxy pass through ' + qn);
michael@0 32773 return target[qn];
michael@0 32774 },
michael@0 32775 set: function (o, qn, value) {
michael@0 32776 if (TRACE_PROXY) {
michael@0 32777 print('proxy set, class: ' + target.class + ', qn: ' + qn + 'hasNonProxyingCallerr: ' + hasNonProxyingCaller());
michael@0 32778 }
michael@0 32779 if (!hasNonProxyingCaller()) {
michael@0 32780 var name = nameFromQualifiedName(qn);
michael@0 32781 if (name !== undefined && !nameInTraits(target, qn)) {
michael@0 32782 target[proxyTrapQns.setProperty](name, value);
michael@0 32783 return;
michael@0 32784 }
michael@0 32785 }
michael@0 32786 TRACE_PROXY && print('> proxy pass through ' + qn);
michael@0 32787 target[qn] = value;
michael@0 32788 },
michael@0 32789 has: function (qn) {
michael@0 32790 if (TRACE_PROXY) {
michael@0 32791 print('proxy has, class: ' + target.class + ', qn: ' + qn + 'hasNonProxyingCallerr: ' + hasNonProxyingCaller());
michael@0 32792 }
michael@0 32793 if (!hasNonProxyingCaller()) {
michael@0 32794 var name = nameFromQualifiedName(qn);
michael@0 32795 if (name !== undefined && !nameInTraits(target, qn)) {
michael@0 32796 return target[proxyTrapQns.hasProperty](name);
michael@0 32797 }
michael@0 32798 }
michael@0 32799 return qn in target;
michael@0 32800 },
michael@0 32801 hasOwn: function (qn) {
michael@0 32802 if (TRACE_PROXY) {
michael@0 32803 print('proxy hasOwn, class: ' + target.class + ', qn: ' + qn + 'hasNonProxyingCallerr: ' + hasNonProxyingCaller());
michael@0 32804 }
michael@0 32805 if (!hasNonProxyingCaller()) {
michael@0 32806 var name = nameFromQualifiedName(qn);
michael@0 32807 if (name !== undefined && !nameInTraits(target, qn)) {
michael@0 32808 return target[proxyTrapQns.hasProperty](name);
michael@0 32809 }
michael@0 32810 }
michael@0 32811 TRACE_PROXY && print('> proxy pass through ' + qn);
michael@0 32812 return !(!Object.getOwnPropertyDescriptor(target, qn));
michael@0 32813 },
michael@0 32814 enumerate: function () {
michael@0 32815 notImplemented('enumerate');
michael@0 32816 },
michael@0 32817 keys: function () {
michael@0 32818 notImplemented('keys');
michael@0 32819 }
michael@0 32820 }, instanceConstructor.prototype);
michael@0 32821 instanceConstructor.apply(proxy, sliceArguments(arguments, 0));
michael@0 32822 return proxy;
michael@0 32823 }
michael@0 32824 cls.instanceConstructor = construct;
michael@0 32825 }
michael@0 32826 function DictionaryClass(domain, scope, instanceConstructor, baseClass) {
michael@0 32827 function ASDictionary(weakKeys) {
michael@0 32828 this.weakKeys = weakKeys;
michael@0 32829 this.map = new WeakMap();
michael@0 32830 if (!weakKeys) {
michael@0 32831 this.keys = [];
michael@0 32832 }
michael@0 32833 this.primitiveMap = createEmptyObject();
michael@0 32834 }
michael@0 32835 var c = new Class('Dictionary', ASDictionary, ApplicationDomain.passthroughCallable(ASDictionary));
michael@0 32836 c.extendNative(baseClass, ASDictionary);
michael@0 32837 function makePrimitiveKey(key) {
michael@0 32838 if (typeof key === 'string' || typeof key === 'number') {
michael@0 32839 return key;
michael@0 32840 }
michael@0 32841 return undefined;
michael@0 32842 }
michael@0 32843 var prototype = ASDictionary.prototype;
michael@0 32844 defineNonEnumerableProperty(prototype, 'asGetProperty', function asGetProperty(namespaces, name, flags, isMethod) {
michael@0 32845 var key = makePrimitiveKey(name);
michael@0 32846 if (key !== undefined) {
michael@0 32847 return this.primitiveMap[key];
michael@0 32848 }
michael@0 32849 return this.map.get(Object(name));
michael@0 32850 });
michael@0 32851 defineNonEnumerableProperty(prototype, 'asGetResolvedStringProperty', asGetResolvedStringPropertyFallback);
michael@0 32852 defineNonEnumerableProperty(prototype, 'asSetProperty', function asSetProperty(namespaces, name, flags, value) {
michael@0 32853 var key = makePrimitiveKey(name);
michael@0 32854 if (key !== undefined) {
michael@0 32855 this.primitiveMap[key] = value;
michael@0 32856 return;
michael@0 32857 }
michael@0 32858 this.map.set(Object(name), value);
michael@0 32859 if (!this.weakKeys && this.keys.indexOf(name) < 0) {
michael@0 32860 this.keys.push(name);
michael@0 32861 }
michael@0 32862 });
michael@0 32863 defineNonEnumerableProperty(prototype, 'asCallProperty', function asCallProperty(namespaces, name, flags, isLex, args) {
michael@0 32864 notImplemented('asCallProperty');
michael@0 32865 });
michael@0 32866 defineNonEnumerableProperty(prototype, 'asHasProperty', function asHasProperty(namespaces, name, flags, nonProxy) {
michael@0 32867 var key = makePrimitiveKey(name);
michael@0 32868 if (key !== undefined) {
michael@0 32869 return key in this.primitiveMap;
michael@0 32870 }
michael@0 32871 return this.map.has(Object(name));
michael@0 32872 });
michael@0 32873 defineNonEnumerableProperty(prototype, 'asDeleteProperty', function asDeleteProperty(namespaces, name, flags) {
michael@0 32874 var key = makePrimitiveKey(name);
michael@0 32875 if (key !== undefined) {
michael@0 32876 delete this.primitiveMap[key];
michael@0 32877 }
michael@0 32878 this.map.delete(Object(name));
michael@0 32879 var i;
michael@0 32880 if (!this.weakKeys && (i = this.keys.indexOf(name)) >= 0) {
michael@0 32881 this.keys.splice(i, 1);
michael@0 32882 }
michael@0 32883 return true;
michael@0 32884 });
michael@0 32885 defineNonEnumerableProperty(prototype, 'asGetEnumerableKeys', function () {
michael@0 32886 if (prototype === this) {
michael@0 32887 return Object.prototype.asGetEnumerableKeys.call(this);
michael@0 32888 }
michael@0 32889 var primitiveMapKeys = [];
michael@0 32890 for (var k in this.primitiveMap) {
michael@0 32891 primitiveMapKeys.push(k);
michael@0 32892 }
michael@0 32893 if (this.weakKeys) {
michael@0 32894 return primitiveMapKeys;
michael@0 32895 }
michael@0 32896 return primitiveMapKeys.concat(this.keys);
michael@0 32897 });
michael@0 32898 c.native = {
michael@0 32899 instance: {
michael@0 32900 init: function () {
michael@0 32901 }
michael@0 32902 }
michael@0 32903 };
michael@0 32904 return c;
michael@0 32905 }
michael@0 32906 function debugBreak(message) {
michael@0 32907 debugger;
michael@0 32908 print('\x1b[91mdebugBreak: ' + message + '\x1b[0m');
michael@0 32909 }
michael@0 32910 var NativeASNamespace;
michael@0 32911 var natives = function () {
michael@0 32912 var C = ApplicationDomain.passthroughCallable;
michael@0 32913 var CC = ApplicationDomain.constructingCallable;
michael@0 32914 function ObjectClass(applicationDomain, scope, instanceConstructor, baseClass) {
michael@0 32915 var c = new Class('Object', Object, C(Object));
michael@0 32916 c.native = {
michael@0 32917 instance: {
michael@0 32918 isPrototypeOf: Object.prototype.isPrototypeOf,
michael@0 32919 hasOwnProperty: function (name) {
michael@0 32920 if (name === undefined) {
michael@0 32921 return false;
michael@0 32922 }
michael@0 32923 name = Multiname.getPublicQualifiedName(name);
michael@0 32924 if (Object.prototype.hasOwnProperty.call(this, name)) {
michael@0 32925 return true;
michael@0 32926 }
michael@0 32927 return Object.getPrototypeOf(this).hasOwnProperty(name);
michael@0 32928 },
michael@0 32929 propertyIsEnumerable: function (name) {
michael@0 32930 if (name === undefined) {
michael@0 32931 return false;
michael@0 32932 }
michael@0 32933 name = Multiname.getPublicQualifiedName(name);
michael@0 32934 return Object.prototype.propertyIsEnumerable.call(this, name);
michael@0 32935 }
michael@0 32936 },
michael@0 32937 static: {
michael@0 32938 _setPropertyIsEnumerable: function _setPropertyIsEnumerable(obj, name, isEnum) {
michael@0 32939 name = Multiname.getPublicQualifiedName(name);
michael@0 32940 var descriptor = Object.getOwnPropertyDescriptor(obj, name);
michael@0 32941 descriptor.enumerable = false;
michael@0 32942 Object.defineProperty(obj, name, descriptor);
michael@0 32943 }
michael@0 32944 }
michael@0 32945 };
michael@0 32946 c.dynamicPrototype = c.traitsPrototype = Object.prototype;
michael@0 32947 c.setDefaultProperties();
michael@0 32948 c.defaultValue = null;
michael@0 32949 c.coerce = function (value) {
michael@0 32950 return asCoerceObject(value);
michael@0 32951 };
michael@0 32952 c.isInstanceOf = function (value) {
michael@0 32953 if (value === null) {
michael@0 32954 return false;
michael@0 32955 }
michael@0 32956 return true;
michael@0 32957 };
michael@0 32958 c.isInstance = function (value) {
michael@0 32959 if (value === null || value === undefined) {
michael@0 32960 return false;
michael@0 32961 }
michael@0 32962 return true;
michael@0 32963 };
michael@0 32964 return c;
michael@0 32965 }
michael@0 32966 function ClassClass(runtime, scope, instanceConstructor, baseClass) {
michael@0 32967 var c = Class;
michael@0 32968 c.debugName = 'Class';
michael@0 32969 c.prototype.extendBuiltin.call(c, baseClass);
michael@0 32970 c.coerce = function (value) {
michael@0 32971 return value;
michael@0 32972 };
michael@0 32973 c.isInstanceOf = function (value) {
michael@0 32974 return true;
michael@0 32975 };
michael@0 32976 c.isInstance = function (value) {
michael@0 32977 return value instanceof c.instanceConstructor;
michael@0 32978 };
michael@0 32979 return c;
michael@0 32980 }
michael@0 32981 function BooleanClass(runtime, scope, instanceConstructor, baseClass) {
michael@0 32982 var c = new Class('Boolean', Boolean, C(Boolean));
michael@0 32983 c.extendBuiltin(baseClass);
michael@0 32984 c.native = {
michael@0 32985 instance: {
michael@0 32986 toString: Boolean.prototype.toString,
michael@0 32987 valueOf: Boolean.prototype.valueOf
michael@0 32988 }
michael@0 32989 };
michael@0 32990 c.coerce = Boolean;
michael@0 32991 c.isInstanceOf = function (value) {
michael@0 32992 return typeof value === 'boolean' || value instanceof Boolean;
michael@0 32993 };
michael@0 32994 c.isInstance = function (value) {
michael@0 32995 if (typeof value === 'boolean' || value instanceof Boolean) {
michael@0 32996 return true;
michael@0 32997 }
michael@0 32998 return false;
michael@0 32999 };
michael@0 33000 return c;
michael@0 33001 }
michael@0 33002 function FunctionClass(runtime, scope, instanceConstructor, baseClass) {
michael@0 33003 var c = new Class('Function', Function, C(Function));
michael@0 33004 c.extendBuiltin(baseClass);
michael@0 33005 c.native = {
michael@0 33006 instance: {
michael@0 33007 prototype: {
michael@0 33008 get: function () {
michael@0 33009 return this.prototype;
michael@0 33010 },
michael@0 33011 set: function (p) {
michael@0 33012 this.prototype = p;
michael@0 33013 }
michael@0 33014 },
michael@0 33015 length: {
michael@0 33016 get: function () {
michael@0 33017 if (this.hasOwnProperty(VM_LENGTH)) {
michael@0 33018 return this.asLength;
michael@0 33019 }
michael@0 33020 return this.length;
michael@0 33021 }
michael@0 33022 },
michael@0 33023 call: Function.prototype.call,
michael@0 33024 apply: Function.prototype.apply
michael@0 33025 }
michael@0 33026 };
michael@0 33027 c.coerce = function (value) {
michael@0 33028 return value;
michael@0 33029 };
michael@0 33030 c.isInstanceOf = function (value) {
michael@0 33031 return typeof value === 'function';
michael@0 33032 };
michael@0 33033 c.isInstance = function (value) {
michael@0 33034 return typeof value === 'function';
michael@0 33035 };
michael@0 33036 return c;
michael@0 33037 }
michael@0 33038 function MethodClosure($this, fn) {
michael@0 33039 var bound = bindSafely(fn, $this);
michael@0 33040 defineNonEnumerableProperty(this, 'call', bound.call.bind(bound));
michael@0 33041 defineNonEnumerableProperty(this, 'apply', bound.apply.bind(bound));
michael@0 33042 }
michael@0 33043 MethodClosure.prototype = {
michael@0 33044 toString: function () {
michael@0 33045 return 'function Function() {}';
michael@0 33046 }
michael@0 33047 };
michael@0 33048 function MethodClosureClass(runtime, scope, instanceConstructor, baseClass) {
michael@0 33049 var c = new Class('MethodClosure', MethodClosure);
michael@0 33050 c.extendBuiltin(baseClass);
michael@0 33051 return c;
michael@0 33052 }
michael@0 33053 function StringClass(runtime, scope, instanceConstructor, baseClass) {
michael@0 33054 var c = new Class('String', String, C(String));
michael@0 33055 c.extendBuiltin(baseClass);
michael@0 33056 var Sp = String.prototype;
michael@0 33057 c.native = {
michael@0 33058 instance: {
michael@0 33059 length: {
michael@0 33060 get: function () {
michael@0 33061 return this.length;
michael@0 33062 }
michael@0 33063 },
michael@0 33064 indexOf: Sp.indexOf,
michael@0 33065 lastIndexOf: Sp.lastIndexOf,
michael@0 33066 charAt: Sp.charAt,
michael@0 33067 charCodeAt: Sp.charCodeAt,
michael@0 33068 concat: Sp.concat,
michael@0 33069 localeCompare: Sp.localeCompare,
michael@0 33070 match: function (re) {
michael@0 33071 if (re === void 0 || re === null) {
michael@0 33072 return null;
michael@0 33073 } else {
michael@0 33074 if (re instanceof RegExp && re.global) {
michael@0 33075 var matches = [], m;
michael@0 33076 while (m = re.exec(this)) {
michael@0 33077 matches.push(m[0]);
michael@0 33078 }
michael@0 33079 return matches;
michael@0 33080 }
michael@0 33081 if (!(re instanceof RegExp) && !(typeof re === 'string')) {
michael@0 33082 re = String(re);
michael@0 33083 }
michael@0 33084 return this.match(re);
michael@0 33085 }
michael@0 33086 },
michael@0 33087 replace: Sp.replace,
michael@0 33088 search: function (re) {
michael@0 33089 if (re === void 0) {
michael@0 33090 return -1;
michael@0 33091 } else {
michael@0 33092 return this.search(re);
michael@0 33093 }
michael@0 33094 },
michael@0 33095 slice: Sp.slice,
michael@0 33096 split: Sp.split,
michael@0 33097 substr: Sp.substr,
michael@0 33098 substring: Sp.substring,
michael@0 33099 toLowerCase: Sp.toLowerCase,
michael@0 33100 toLocaleLowerCase: Sp.toLocaleLowerCase,
michael@0 33101 toUpperCase: function () {
michael@0 33102 var str = Sp.toUpperCase.apply(this);
michael@0 33103 var str = str.replace(/\u039C/g, String.fromCharCode(181));
michael@0 33104 return str;
michael@0 33105 },
michael@0 33106 toLocaleUpperCase: function () {
michael@0 33107 var str = Sp.toLocaleUpperCase.apply(this);
michael@0 33108 var str = str.replace(/\u039C/g, String.fromCharCode(181));
michael@0 33109 return str;
michael@0 33110 },
michael@0 33111 toString: Sp.toString,
michael@0 33112 valueOf: Sp.valueOf
michael@0 33113 },
michael@0 33114 static: String
michael@0 33115 };
michael@0 33116 c.isInstance = function (value) {
michael@0 33117 return value !== null && value !== undefined && typeof value.valueOf() === 'string';
michael@0 33118 };
michael@0 33119 c.coerce = function (value) {
michael@0 33120 if (value === null || value === undefined) {
michael@0 33121 return null;
michael@0 33122 }
michael@0 33123 return String(value);
michael@0 33124 };
michael@0 33125 c.isInstanceOf = function (value) {
michael@0 33126 return Object(value) instanceof String;
michael@0 33127 };
michael@0 33128 c.isInstance = function (value) {
michael@0 33129 return Object(value) instanceof String;
michael@0 33130 };
michael@0 33131 return c;
michael@0 33132 }
michael@0 33133 function VectorClass(domain, scope, instanceConstructor, baseClass) {
michael@0 33134 return createVectorClass(undefined, baseClass);
michael@0 33135 }
michael@0 33136 function ObjectVectorClass(domain, scope, instanceConstructor, baseClass) {
michael@0 33137 return createVectorClass(domain.getClass('Object'), baseClass);
michael@0 33138 }
michael@0 33139 function IntVectorClass(domain, scope, instanceConstructor, baseClass) {
michael@0 33140 return createVectorClass(domain.getClass('int'), baseClass);
michael@0 33141 }
michael@0 33142 function UIntVectorClass(domain, scope, instanceConstructor, baseClass) {
michael@0 33143 return createVectorClass(domain.getClass('uint'), baseClass);
michael@0 33144 }
michael@0 33145 function DoubleVectorClass(domain, scope, instanceConstructor, baseClass) {
michael@0 33146 return createVectorClass(domain.getClass('Number'), baseClass);
michael@0 33147 }
michael@0 33148 function createVectorClass(type, baseClass) {
michael@0 33149 var V;
michael@0 33150 if (type) {
michael@0 33151 var className = 'Vector$' + type.classInfo.instanceInfo.name.name;
michael@0 33152 switch (className) {
michael@0 33153 case 'Vector$int':
michael@0 33154 V = Int32Vector;
michael@0 33155 break;
michael@0 33156 case 'Vector$uint':
michael@0 33157 V = Uint32Vector;
michael@0 33158 break;
michael@0 33159 case 'Vector$Number':
michael@0 33160 V = Float64Vector;
michael@0 33161 break;
michael@0 33162 case 'Vector$Object':
michael@0 33163 V = GenericVector;
michael@0 33164 break;
michael@0 33165 default:
michael@0 33166 unexpected();
michael@0 33167 break;
michael@0 33168 }
michael@0 33169 } else {
michael@0 33170 V = GenericVector.applyType(null);
michael@0 33171 }
michael@0 33172 var Vp = V.prototype;
michael@0 33173 var cls = new Class(className, V, C(V.callable));
michael@0 33174 if (V === GenericVector) {
michael@0 33175 cls.applyType = function (type) {
michael@0 33176 return cls;
michael@0 33177 };
michael@0 33178 }
michael@0 33179 cls.extendWrapper(baseClass, V);
michael@0 33180 cls.native = {
michael@0 33181 instance: {
michael@0 33182 fixed: {
michael@0 33183 get: function () {
michael@0 33184 return this._fixed;
michael@0 33185 },
michael@0 33186 set: function (v) {
michael@0 33187 this._fixed = v;
michael@0 33188 }
michael@0 33189 },
michael@0 33190 length: {
michael@0 33191 get: function () {
michael@0 33192 return this.length;
michael@0 33193 },
michael@0 33194 set: function setLength(length) {
michael@0 33195 this.length = length;
michael@0 33196 }
michael@0 33197 },
michael@0 33198 push: Vp.push,
michael@0 33199 pop: Vp.pop,
michael@0 33200 shift: Vp.shift,
michael@0 33201 unshift: Vp.unshift,
michael@0 33202 _reverse: Vp.reverse,
michael@0 33203 _filter: Vp.filter,
michael@0 33204 _map: Vp.map,
michael@0 33205 newThisType: function newThisType() {
michael@0 33206 return new cls.instanceConstructor();
michael@0 33207 },
michael@0 33208 _spliceHelper: function _spliceHelper(insertPoint, insertCount, deleteCount, args, offset) {
michael@0 33209 return this._spliceHelper(insertPoint, insertCount, deleteCount, args, offset);
michael@0 33210 }
michael@0 33211 },
michael@0 33212 static: {
michael@0 33213 _some: function (o, callback, thisObject) {
michael@0 33214 return o.some(callback, thisObject);
michael@0 33215 },
michael@0 33216 _every: function (o, callback, thisObject) {
michael@0 33217 return o.every(callback, thisObject);
michael@0 33218 },
michael@0 33219 _forEach: function (o, callback, thisObject) {
michael@0 33220 return o.forEach(callback, thisObject);
michael@0 33221 },
michael@0 33222 _sort: arraySort
michael@0 33223 }
michael@0 33224 };
michael@0 33225 cls.vectorType = type;
michael@0 33226 cls.coerce = function (value) {
michael@0 33227 return value;
michael@0 33228 };
michael@0 33229 cls.isInstanceOf = function (value) {
michael@0 33230 return true;
michael@0 33231 };
michael@0 33232 cls.isInstance = function (value) {
michael@0 33233 if (value === null || typeof value !== 'object') {
michael@0 33234 return false;
michael@0 33235 }
michael@0 33236 if (!this.instanceConstructor.vectorType && value.class.vectorType) {
michael@0 33237 return true;
michael@0 33238 }
michael@0 33239 return this.instanceConstructor.prototype.isPrototypeOf(value);
michael@0 33240 };
michael@0 33241 return cls;
michael@0 33242 }
michael@0 33243 function NumberClass(runtime, scope, instanceConstructor, baseClass) {
michael@0 33244 var c = new Class('Number', Number, C(Number));
michael@0 33245 c.extendBuiltin(baseClass);
michael@0 33246 c.native = {
michael@0 33247 instance: Number.prototype
michael@0 33248 };
michael@0 33249 c.defaultValue = Number(0);
michael@0 33250 c.isInstance = function (value) {
michael@0 33251 return value !== null && value !== undefined && typeof value.valueOf() === 'number';
michael@0 33252 };
michael@0 33253 c.coerce = Number;
michael@0 33254 c.isInstanceOf = function (value) {
michael@0 33255 return Object(value) instanceof Number;
michael@0 33256 };
michael@0 33257 c.isInstance = function (value) {
michael@0 33258 return Object(value) instanceof Number;
michael@0 33259 };
michael@0 33260 return c;
michael@0 33261 }
michael@0 33262 function Int(x) {
michael@0 33263 return x | 0;
michael@0 33264 }
michael@0 33265 function boxedInt(x) {
michael@0 33266 return Object(x | 0);
michael@0 33267 }
michael@0 33268 function intClass(runtime, scope, instanceConstructor, baseClass) {
michael@0 33269 var c = new Class('int', boxedInt, C(Int));
michael@0 33270 c.extendBuiltin(baseClass);
michael@0 33271 c.defaultValue = 0;
michael@0 33272 c.coerce = Int;
michael@0 33273 c.isInstanceOf = function (value) {
michael@0 33274 return false;
michael@0 33275 };
michael@0 33276 c.isInstance = function (value) {
michael@0 33277 if (value instanceof Number) {
michael@0 33278 value = value.valueOf();
michael@0 33279 }
michael@0 33280 return (value | 0) === value;
michael@0 33281 };
michael@0 33282 return c;
michael@0 33283 }
michael@0 33284 function Uint(x) {
michael@0 33285 return x >>> 0;
michael@0 33286 }
michael@0 33287 function boxedUint(x) {
michael@0 33288 return Object(x >>> 0);
michael@0 33289 }
michael@0 33290 function uintClass(runtime, scope, instanceConstructor, baseClass) {
michael@0 33291 var c = new Class('uint', boxedUint, C(Uint));
michael@0 33292 c.extend(baseClass);
michael@0 33293 c.defaultValue = 0;
michael@0 33294 c.isInstanceOf = function (value) {
michael@0 33295 return false;
michael@0 33296 };
michael@0 33297 c.isInstance = function (value) {
michael@0 33298 if (value instanceof Number) {
michael@0 33299 value = value.valueOf();
michael@0 33300 }
michael@0 33301 return value >>> 0 === value;
michael@0 33302 };
michael@0 33303 c.coerce = Uint;
michael@0 33304 return c;
michael@0 33305 }
michael@0 33306 function MathClass(runtime, scope, instanceConstructor, baseClass) {
michael@0 33307 var c = new Class('Math');
michael@0 33308 c.native = {
michael@0 33309 static: Math
michael@0 33310 };
michael@0 33311 return c;
michael@0 33312 }
michael@0 33313 function DateClass(runtime, scope, instanceConstructor, baseClass) {
michael@0 33314 var c = new Class('Date', Date, C(Date));
michael@0 33315 c.extendBuiltin(baseClass);
michael@0 33316 c.native = {
michael@0 33317 instance: Date.prototype,
michael@0 33318 static: Date
michael@0 33319 };
michael@0 33320 return c;
michael@0 33321 }
michael@0 33322 function makeErrorClass(name) {
michael@0 33323 var ErrorDefinition = {
michael@0 33324 __glue__: {
michael@0 33325 script: {
michael@0 33326 instance: {
michael@0 33327 message: 'public message',
michael@0 33328 name: 'public name'
michael@0 33329 }
michael@0 33330 },
michael@0 33331 native: {
michael@0 33332 instance: {
michael@0 33333 getStackTrace: function () {
michael@0 33334 somewhatImplemented('Error.getStackTrace()');
michael@0 33335 return AVM2.getStackTrace();
michael@0 33336 }
michael@0 33337 },
michael@0 33338 static: {
michael@0 33339 getErrorMessage: getErrorMessage
michael@0 33340 }
michael@0 33341 }
michael@0 33342 }
michael@0 33343 };
michael@0 33344 return function (runtime, scope, instanceConstructor, baseClass) {
michael@0 33345 var c = new Class(name, instanceConstructor);
michael@0 33346 c.extend(baseClass);
michael@0 33347 if (name === 'Error') {
michael@0 33348 c.link(ErrorDefinition);
michael@0 33349 c.linkNatives(ErrorDefinition);
michael@0 33350 }
michael@0 33351 return c;
michael@0 33352 };
michael@0 33353 }
michael@0 33354 function RegExpClass(runtime, scope, instanceConstructor, baseClass) {
michael@0 33355 var c = new Class('RegExp', XRegExp, C(XRegExp));
michael@0 33356 c.extendBuiltin(baseClass);
michael@0 33357 RegExpClass.exec = function exec() {
michael@0 33358 var result = this.exec.apply(this, arguments);
michael@0 33359 if (!result) {
michael@0 33360 return result;
michael@0 33361 }
michael@0 33362 var keys = Object.keys(result);
michael@0 33363 for (var i = 0; i < keys.length; i++) {
michael@0 33364 var k = keys[i];
michael@0 33365 if (!isNumeric(k)) {
michael@0 33366 if (result[k] === undefined) {
michael@0 33367 result[k] = '';
michael@0 33368 }
michael@0 33369 }
michael@0 33370 }
michael@0 33371 publicizeProperties(result);
michael@0 33372 return result;
michael@0 33373 };
michael@0 33374 RegExpClass.test = function test() {
michael@0 33375 return this.exec.apply(this, arguments) !== null;
michael@0 33376 };
michael@0 33377 c.native = {
michael@0 33378 instance: {
michael@0 33379 global: {
michael@0 33380 get: function () {
michael@0 33381 return this.global;
michael@0 33382 }
michael@0 33383 },
michael@0 33384 source: {
michael@0 33385 get: function () {
michael@0 33386 return this.source;
michael@0 33387 }
michael@0 33388 },
michael@0 33389 ignoreCase: {
michael@0 33390 get: function () {
michael@0 33391 return this.ignoreCase;
michael@0 33392 }
michael@0 33393 },
michael@0 33394 multiline: {
michael@0 33395 get: function () {
michael@0 33396 return this.multiline;
michael@0 33397 }
michael@0 33398 },
michael@0 33399 lastIndex: {
michael@0 33400 get: function () {
michael@0 33401 return this.lastIndex;
michael@0 33402 },
michael@0 33403 set: function (i) {
michael@0 33404 this.lastIndex = i;
michael@0 33405 }
michael@0 33406 },
michael@0 33407 dotall: {
michael@0 33408 get: function () {
michael@0 33409 return this.dotall;
michael@0 33410 }
michael@0 33411 },
michael@0 33412 extended: {
michael@0 33413 get: function () {
michael@0 33414 return this.extended;
michael@0 33415 }
michael@0 33416 },
michael@0 33417 exec: RegExpClass.exec,
michael@0 33418 test: RegExpClass.test
michael@0 33419 }
michael@0 33420 };
michael@0 33421 return c;
michael@0 33422 }
michael@0 33423 function NamespaceClass(runtime, scope, instanceConstructor, baseClass) {
michael@0 33424 NativeASNamespace = function NativeASNamespace(prefixValue, uriValue) {
michael@0 33425 if (uriValue === undefined) {
michael@0 33426 uriValue = prefixValue;
michael@0 33427 prefixValue = undefined;
michael@0 33428 }
michael@0 33429 var prefix, uri;
michael@0 33430 if (prefixValue === undefined) {
michael@0 33431 if (uriValue === undefined) {
michael@0 33432 prefix = '';
michael@0 33433 uri = '';
michael@0 33434 } else if (typeof uriValue === 'object') {
michael@0 33435 prefix = uriValue.prefix;
michael@0 33436 if (uriValue instanceof ASNamespace) {
michael@0 33437 uri = uriValue.uri;
michael@0 33438 } else if (uriValue instanceof QName) {
michael@0 33439 uri = uriValue.uri;
michael@0 33440 }
michael@0 33441 } else {
michael@0 33442 uri = uriValue + '';
michael@0 33443 if (uri === '') {
michael@0 33444 prefix = '';
michael@0 33445 } else {
michael@0 33446 prefix = undefined;
michael@0 33447 }
michael@0 33448 }
michael@0 33449 } else {
michael@0 33450 if (typeof uriValue === 'object' && uriValue instanceof QName && uriValue.uri !== null) {
michael@0 33451 uri = uriValue.uri;
michael@0 33452 } else {
michael@0 33453 uri = uriValue + '';
michael@0 33454 }
michael@0 33455 if (uri === '') {
michael@0 33456 if (prefixValue === undefined || prefixValue + '' === '') {
michael@0 33457 prefix = '';
michael@0 33458 } else {
michael@0 33459 throw 'type error';
michael@0 33460 }
michael@0 33461 } else if (prefixValue === undefined || prefixValue === '') {
michael@0 33462 prefix = undefined;
michael@0 33463 } else if (false && !isXMLName(prefixValue)) {
michael@0 33464 prefix = undefined;
michael@0 33465 } else {
michael@0 33466 prefix = prefixValue + '';
michael@0 33467 }
michael@0 33468 }
michael@0 33469 return ASNamespace.createNamespace(uri, prefix);
michael@0 33470 };
michael@0 33471 var c = new Class('Namespace', NativeASNamespace, C(NativeASNamespace));
michael@0 33472 c.extendNative(baseClass, ASNamespace);
michael@0 33473 var Np = ASNamespace.prototype;
michael@0 33474 c.native = {
michael@0 33475 instance: {
michael@0 33476 prefix: {
michael@0 33477 get: Np.getPrefix
michael@0 33478 },
michael@0 33479 uri: {
michael@0 33480 get: Np.getURI
michael@0 33481 }
michael@0 33482 }
michael@0 33483 };
michael@0 33484 return c;
michael@0 33485 }
michael@0 33486 function JSONClass(runtime, scope, instanceConstructor, baseClass) {
michael@0 33487 function transformJSValueToAS(value) {
michael@0 33488 if (typeof value !== 'object') {
michael@0 33489 return value;
michael@0 33490 }
michael@0 33491 var keys = Object.keys(value);
michael@0 33492 var result = value instanceof Array ? [] : {};
michael@0 33493 for (var i = 0; i < keys.length; i++) {
michael@0 33494 result.asSetPublicProperty(keys[i], transformJSValueToAS(value[keys[i]]));
michael@0 33495 }
michael@0 33496 return result;
michael@0 33497 }
michael@0 33498 function transformASValueToJS(value) {
michael@0 33499 if (typeof value !== 'object') {
michael@0 33500 return value;
michael@0 33501 }
michael@0 33502 var keys = Object.keys(value);
michael@0 33503 var result = value instanceof Array ? [] : {};
michael@0 33504 for (var i = 0; i < keys.length; i++) {
michael@0 33505 var key = keys[i];
michael@0 33506 var jsKey = key;
michael@0 33507 if (!isNumeric(key)) {
michael@0 33508 jsKey = Multiname.getNameFromPublicQualifiedName(key);
michael@0 33509 }
michael@0 33510 result[jsKey] = transformASValueToJS(value[key]);
michael@0 33511 }
michael@0 33512 return result;
michael@0 33513 }
michael@0 33514 function ASJSON() {
michael@0 33515 }
michael@0 33516 var c = new Class('JSON', ASJSON, C(ASJSON));
michael@0 33517 c.extend(baseClass);
michael@0 33518 c.native = {
michael@0 33519 static: {
michael@0 33520 parseCore: function parseCore(text) {
michael@0 33521 return transformJSValueToAS(JSON.parse(text));
michael@0 33522 },
michael@0 33523 stringifySpecializedToString: function stringifySpecializedToString(value, replacerArray, replacerFunction, gap) {
michael@0 33524 return JSON.stringify(transformASValueToJS(value), replacerFunction, gap);
michael@0 33525 }
michael@0 33526 }
michael@0 33527 };
michael@0 33528 return c;
michael@0 33529 }
michael@0 33530 function CapabilitiesClass(runtime, scope, instanceConstructor, baseClass) {
michael@0 33531 function Capabilities() {
michael@0 33532 }
michael@0 33533 var c = new Class('Capabilities', Capabilities, C(Capabilities));
michael@0 33534 c.extend(baseClass);
michael@0 33535 c.native = {
michael@0 33536 static: {
michael@0 33537 playerType: {
michael@0 33538 get: function () {
michael@0 33539 return 'AVMPlus';
michael@0 33540 }
michael@0 33541 }
michael@0 33542 }
michael@0 33543 };
michael@0 33544 return c;
michael@0 33545 }
michael@0 33546 function FileClass(runtime, scope, instanceConstructor, baseClass) {
michael@0 33547 function File() {
michael@0 33548 }
michael@0 33549 var c = new Class('File', File, C(File));
michael@0 33550 c.extend(baseClass);
michael@0 33551 c.native = {
michael@0 33552 static: {
michael@0 33553 exists: function (filename) {
michael@0 33554 notImplemented('File.exists');
michael@0 33555 return false;
michael@0 33556 },
michael@0 33557 read: function (filename) {
michael@0 33558 return snarf(filename);
michael@0 33559 },
michael@0 33560 write: function (filename, data) {
michael@0 33561 notImplemented('File.write');
michael@0 33562 return true;
michael@0 33563 },
michael@0 33564 readByteArray: function (filename) {
michael@0 33565 var ByteArrayClass = AVM2.currentDomain().getClass('flash.utils.ByteArray');
michael@0 33566 var data = ByteArrayClass.createInstance();
michael@0 33567 data.writeRawBytes(snarf(filename, 'binary'));
michael@0 33568 return data;
michael@0 33569 },
michael@0 33570 writeByteArray: function (filename, bytes) {
michael@0 33571 write('bin/' + filename, bytes.getBytes());
michael@0 33572 return true;
michael@0 33573 }
michael@0 33574 }
michael@0 33575 };
michael@0 33576 return c;
michael@0 33577 }
michael@0 33578 function ShumwayClass(runtime, scope, instanceConstructor, baseClass) {
michael@0 33579 function Shumway() {
michael@0 33580 }
michael@0 33581 var c = new Class('Shumway', Shumway, C(Shumway));
michael@0 33582 c.extend(baseClass);
michael@0 33583 c.native = {
michael@0 33584 static: {
michael@0 33585 info: function (x) {
michael@0 33586 console.info(x);
michael@0 33587 },
michael@0 33588 json: function (x) {
michael@0 33589 return JSON.stringify(x);
michael@0 33590 },
michael@0 33591 eval: function (x) {
michael@0 33592 return eval(x);
michael@0 33593 },
michael@0 33594 debugger: function (x) {
michael@0 33595 debugger;
michael@0 33596 }
michael@0 33597 }
michael@0 33598 };
michael@0 33599 return c;
michael@0 33600 }
michael@0 33601 function constant(x) {
michael@0 33602 return function () {
michael@0 33603 return x;
michael@0 33604 };
michael@0 33605 }
michael@0 33606 function ByteArrayClass(runtime, scope, instanceConstructor, baseClass) {
michael@0 33607 var BA = function () {
michael@0 33608 ByteArray.call(this);
michael@0 33609 };
michael@0 33610 var BAp = BA.prototype = Object.create(ByteArray.prototype);
michael@0 33611 var c = new Class('ByteArray', BA, C(BA));
michael@0 33612 c.extendBuiltin(baseClass);
michael@0 33613 BAp.asGetNumericProperty = function (i) {
michael@0 33614 if (i >= this.length) {
michael@0 33615 return undefined;
michael@0 33616 }
michael@0 33617 return this.uint8v[i];
michael@0 33618 };
michael@0 33619 BAp.asSetNumericProperty = function (i, v) {
michael@0 33620 var len = i + 1;
michael@0 33621 this.ensureCapacity(len);
michael@0 33622 this.uint8v[i] = v;
michael@0 33623 if (len > this.length) {
michael@0 33624 this.length = len;
michael@0 33625 }
michael@0 33626 };
michael@0 33627 BAp.readUTF = function readUTF() {
michael@0 33628 return this.readUTFBytes(this.readShort());
michael@0 33629 };
michael@0 33630 BAp.readUTFBytes = function readUTFBytes(length) {
michael@0 33631 var pos = this.position;
michael@0 33632 if (pos + length > this.length) {
michael@0 33633 throwEOFError();
michael@0 33634 }
michael@0 33635 this.position += length;
michael@0 33636 return utf8encode(new Int8Array(this.a, pos, length));
michael@0 33637 };
michael@0 33638 BAp.writeUTF = function writeUTF(str) {
michael@0 33639 var bytes = utf8decode(str);
michael@0 33640 this.writeShort(bytes.length);
michael@0 33641 this.writeRawBytes(bytes);
michael@0 33642 };
michael@0 33643 BAp.writeUTFBytes = function writeUTFBytes(str) {
michael@0 33644 var bytes = utf8decode(str);
michael@0 33645 this.writeRawBytes(bytes);
michael@0 33646 };
michael@0 33647 BAp.toString = function toString() {
michael@0 33648 return utf8encode(new Int8Array(this.a, 0, this.length));
michael@0 33649 };
michael@0 33650 c.native = {
michael@0 33651 instance: {
michael@0 33652 length: {
michael@0 33653 get: function () {
michael@0 33654 return this.length;
michael@0 33655 },
michael@0 33656 set: function setLength(length) {
michael@0 33657 var cap = this.a.byteLength;
michael@0 33658 if (length > cap) {
michael@0 33659 this.ensureCapacity(length);
michael@0 33660 }
michael@0 33661 this.length = length;
michael@0 33662 this.position = clamp(this.position, 0, this.length);
michael@0 33663 }
michael@0 33664 },
michael@0 33665 bytesAvailable: {
michael@0 33666 get: function () {
michael@0 33667 return this.length - this.position;
michael@0 33668 }
michael@0 33669 },
michael@0 33670 position: {
michael@0 33671 get: function () {
michael@0 33672 return this.position;
michael@0 33673 },
michael@0 33674 set: function (p) {
michael@0 33675 this.position = p;
michael@0 33676 }
michael@0 33677 },
michael@0 33678 endian: {
michael@0 33679 get: function () {
michael@0 33680 return this.le ? 'littleEndian' : 'bigEndian';
michael@0 33681 },
michael@0 33682 set: function (e) {
michael@0 33683 this.le = e === 'littleEndian';
michael@0 33684 }
michael@0 33685 },
michael@0 33686 objectEncoding: {
michael@0 33687 get: function () {
michael@0 33688 return this.objectEncoding;
michael@0 33689 },
michael@0 33690 set: function (v) {
michael@0 33691 this.objectEncoding = v;
michael@0 33692 }
michael@0 33693 },
michael@0 33694 writeBytes: BAp.writeBytes,
michael@0 33695 writeBoolean: BAp.writeBoolean,
michael@0 33696 writeByte: BAp.writeByte,
michael@0 33697 writeShort: BAp.writeShort,
michael@0 33698 writeInt: BAp.writeInt,
michael@0 33699 writeUnsignedInt: BAp.writeUnsignedInt,
michael@0 33700 writeFloat: BAp.writeFloat,
michael@0 33701 writeDouble: BAp.writeDouble,
michael@0 33702 writeMultiByte: BAp.writeMultiByte,
michael@0 33703 writeObject: function writeObject(v) {
michael@0 33704 return AMFUtils.encodings[this.objectEncoding].write(this, v);
michael@0 33705 },
michael@0 33706 writeUTF: BAp.writeUTF,
michael@0 33707 writeUTFBytes: BAp.writeUTFBytes,
michael@0 33708 readBoolean: BAp.readBoolean,
michael@0 33709 readByte: BAp.readByte,
michael@0 33710 readBytes: BAp.readBytes,
michael@0 33711 readUnsignedByte: BAp.readUnsignedByte,
michael@0 33712 readShort: BAp.readShort,
michael@0 33713 readUnsignedShort: BAp.readUnsignedShort,
michael@0 33714 readInt: BAp.readInt,
michael@0 33715 readUnsignedInt: BAp.readUnsignedInt,
michael@0 33716 readFloat: BAp.readFloat,
michael@0 33717 readDouble: BAp.readDouble,
michael@0 33718 readMultiByte: BAp.readMultiByte,
michael@0 33719 readObject: function readObject() {
michael@0 33720 return AMFUtils.encodings[this.objectEncoding].read(this);
michael@0 33721 },
michael@0 33722 readUTF: BAp.readUTF,
michael@0 33723 readUTFBytes: BAp.readUTFBytes,
michael@0 33724 toString: BAp.toString,
michael@0 33725 clear: BAp.clear,
michael@0 33726 _compress: BAp.compress,
michael@0 33727 _uncompress: BAp.uncompress
michael@0 33728 },
michael@0 33729 static: {
michael@0 33730 defaultObjectEncoding: {
michael@0 33731 get: function () {
michael@0 33732 return ByteArray.DEFAULT_OBJECT_ENCODING;
michael@0 33733 },
michael@0 33734 set: function (e) {
michael@0 33735 ByteArray.DEFAULT_OBJECT_ENCODING = e;
michael@0 33736 }
michael@0 33737 }
michael@0 33738 }
michael@0 33739 };
michael@0 33740 return c;
michael@0 33741 }
michael@0 33742 function DomainClass(runtime, scope, instanceConstructor, baseClass) {
michael@0 33743 var c = new Class('File', instanceConstructor, C(instanceConstructor));
michael@0 33744 c.extend(baseClass);
michael@0 33745 c.native = {
michael@0 33746 instance: {
michael@0 33747 init: function (base) {
michael@0 33748 this.base = base;
michael@0 33749 this.nativeObject = new ApplicationDomain(AVM2.instance, base ? base.nativeObject : null);
michael@0 33750 },
michael@0 33751 loadBytes: function (byteArray, swfVersion) {
michael@0 33752 this.nativeObject.executeAbc(new AbcFile(byteArray.readRawBytes()));
michael@0 33753 },
michael@0 33754 getClass: function (className) {
michael@0 33755 return this.nativeObject.getClass(className);
michael@0 33756 }
michael@0 33757 },
michael@0 33758 static: {
michael@0 33759 currentDomain: {
michael@0 33760 get: function () {
michael@0 33761 var domain = Object.create(instanceConstructor.prototype);
michael@0 33762 domain.nativeObject = AVM2.currentDomain();
michael@0 33763 return domain;
michael@0 33764 }
michael@0 33765 }
michael@0 33766 }
michael@0 33767 };
michael@0 33768 return c;
michael@0 33769 }
michael@0 33770 function SystemClass(runtime, scope, instanceConstructor, baseClass) {
michael@0 33771 var c = new Class('System', instanceConstructor, C(instanceConstructor));
michael@0 33772 c.extend(baseClass);
michael@0 33773 c.native = {
michael@0 33774 static: {
michael@0 33775 swfVersion: {
michael@0 33776 get: function () {
michael@0 33777 return 19;
michael@0 33778 }
michael@0 33779 },
michael@0 33780 apiVersion: {
michael@0 33781 get: function () {
michael@0 33782 return 26;
michael@0 33783 }
michael@0 33784 },
michael@0 33785 getArgv: function () {
michael@0 33786 return [];
michael@0 33787 },
michael@0 33788 getRunmode: function () {
michael@0 33789 return 'mixed';
michael@0 33790 }
michael@0 33791 }
michael@0 33792 };
michael@0 33793 return c;
michael@0 33794 }
michael@0 33795 function bugzilla(n) {
michael@0 33796 switch (n) {
michael@0 33797 case 574600:
michael@0 33798 return true;
michael@0 33799 }
michael@0 33800 return false;
michael@0 33801 }
michael@0 33802 return {
michael@0 33803 print: constant(print),
michael@0 33804 notImplemented: constant(notImplemented),
michael@0 33805 debugBreak: constant(debugBreak),
michael@0 33806 bugzilla: constant(bugzilla),
michael@0 33807 decodeURI: constant(decodeURI),
michael@0 33808 decodeURIComponent: constant(decodeURIComponent),
michael@0 33809 encodeURI: constant(encodeURI),
michael@0 33810 encodeURIComponent: constant(encodeURIComponent),
michael@0 33811 isNaN: constant(isNaN),
michael@0 33812 isFinite: constant(isFinite),
michael@0 33813 parseInt: constant(parseInt),
michael@0 33814 parseFloat: constant(parseFloat),
michael@0 33815 escape: constant(escape),
michael@0 33816 unescape: constant(unescape),
michael@0 33817 isXMLName: constant(typeof isXMLName !== 'undefined' ? isXMLName : function () {
michael@0 33818 notImplemented('Chrome doesn\'t support isXMLName.');
michael@0 33819 }),
michael@0 33820 Function: Function,
michael@0 33821 String: String,
michael@0 33822 Array: Array,
michael@0 33823 Number: Number,
michael@0 33824 Boolean: Boolean,
michael@0 33825 Math: Math,
michael@0 33826 Date: Date,
michael@0 33827 RegExp: RegExp,
michael@0 33828 Object: Object,
michael@0 33829 ObjectClass: ObjectClass,
michael@0 33830 Class: ClassClass,
michael@0 33831 NamespaceClass: NamespaceClass,
michael@0 33832 FunctionClass: FunctionClass,
michael@0 33833 MethodClosureClass: MethodClosureClass,
michael@0 33834 BooleanClass: BooleanClass,
michael@0 33835 StringClass: StringClass,
michael@0 33836 NumberClass: NumberClass,
michael@0 33837 intClass: intClass,
michael@0 33838 uintClass: uintClass,
michael@0 33839 ArrayClass: ArrayClass,
michael@0 33840 VectorClass: VectorClass,
michael@0 33841 ObjectVectorClass: ObjectVectorClass,
michael@0 33842 IntVectorClass: IntVectorClass,
michael@0 33843 UIntVectorClass: UIntVectorClass,
michael@0 33844 DoubleVectorClass: DoubleVectorClass,
michael@0 33845 ByteArrayClass: ByteArrayClass,
michael@0 33846 ProxyClass: ProxyClass,
michael@0 33847 ErrorClass: makeErrorClass('Error'),
michael@0 33848 DefinitionErrorClass: makeErrorClass('DefinitionError'),
michael@0 33849 EvalErrorClass: makeErrorClass('EvalError'),
michael@0 33850 RangeErrorClass: makeErrorClass('RangeError'),
michael@0 33851 ReferenceErrorClass: makeErrorClass('ReferenceError'),
michael@0 33852 SecurityErrorClass: makeErrorClass('SecurityError'),
michael@0 33853 SyntaxErrorClass: makeErrorClass('SyntaxError'),
michael@0 33854 TypeErrorClass: makeErrorClass('TypeError'),
michael@0 33855 URIErrorClass: makeErrorClass('URIError'),
michael@0 33856 VerifyErrorClass: makeErrorClass('VerifyError'),
michael@0 33857 UninitializedErrorClass: makeErrorClass('UninitializedError'),
michael@0 33858 ArgumentErrorClass: makeErrorClass('ArgumentError'),
michael@0 33859 DateClass: DateClass,
michael@0 33860 MathClass: MathClass,
michael@0 33861 RegExpClass: RegExpClass,
michael@0 33862 DictionaryClass: DictionaryClass,
michael@0 33863 XMLClass: XMLClass,
michael@0 33864 XMLListClass: XMLListClass,
michael@0 33865 QNameClass: QNameClass,
michael@0 33866 JSONClass: JSONClass,
michael@0 33867 ShumwayClass: ShumwayClass,
michael@0 33868 CapabilitiesClass: CapabilitiesClass,
michael@0 33869 FileClass: FileClass,
michael@0 33870 DomainClass: DomainClass,
michael@0 33871 SystemClass: SystemClass,
michael@0 33872 getQualifiedClassName: constant(function (value) {
michael@0 33873 if (value === null) {
michael@0 33874 return 'null';
michael@0 33875 } else if (value === undefined) {
michael@0 33876 return 'void';
michael@0 33877 }
michael@0 33878 switch (typeof value) {
michael@0 33879 case 'number':
michael@0 33880 if ((value | 0) === value) {
michael@0 33881 return 'int';
michael@0 33882 }
michael@0 33883 return 'Number';
michael@0 33884 case 'string':
michael@0 33885 return 'String';
michael@0 33886 case 'boolean':
michael@0 33887 return 'Boolean';
michael@0 33888 case 'object':
michael@0 33889 if (value instanceof Date) {
michael@0 33890 return 'Date';
michael@0 33891 }
michael@0 33892 var cls;
michael@0 33893 if (value instanceof Class) {
michael@0 33894 cls = value;
michael@0 33895 } else if (value.class) {
michael@0 33896 cls = value.class;
michael@0 33897 } else if (value.classInfo) {
michael@0 33898 cls = value;
michael@0 33899 }
michael@0 33900 if (cls) {
michael@0 33901 var name = cls.classInfo.instanceInfo.name;
michael@0 33902 var uri = name.namespaces[0].uri;
michael@0 33903 if (uri) {
michael@0 33904 return uri + '::' + name.name;
michael@0 33905 }
michael@0 33906 return name.name;
michael@0 33907 }
michael@0 33908 break;
michael@0 33909 }
michael@0 33910 return notImplemented(value + ' (' + typeof value + ')');
michael@0 33911 }),
michael@0 33912 getQualifiedSuperclassName: constant(function (value) {
michael@0 33913 switch (typeof value) {
michael@0 33914 case 'number':
michael@0 33915 case 'string':
michael@0 33916 case 'boolean':
michael@0 33917 return 'Object';
michael@0 33918 case 'function':
michael@0 33919 return 'Function';
michael@0 33920 case 'object':
michael@0 33921 if (value instanceof Date) {
michael@0 33922 return 'Object';
michael@0 33923 }
michael@0 33924 var cls;
michael@0 33925 if (value.class) {
michael@0 33926 cls = value.class;
michael@0 33927 } else if (value.classInfo) {
michael@0 33928 cls = value;
michael@0 33929 }
michael@0 33930 if (cls && cls.baseClass) {
michael@0 33931 var name = cls.baseClass.classInfo.instanceInfo.name;
michael@0 33932 var uri = name.namespaces[0].uri;
michael@0 33933 if (uri) {
michael@0 33934 return uri + '::' + name.name;
michael@0 33935 }
michael@0 33936 return name.name;
michael@0 33937 }
michael@0 33938 return 'Object';
michael@0 33939 }
michael@0 33940 return notImplemented(value + ' (superOf ' + typeof value + ')');
michael@0 33941 }),
michael@0 33942 getDefinitionByName: constant(function (name) {
michael@0 33943 var simpleName = String(name).replace('::', '.');
michael@0 33944 return AVM2.currentDomain().getClass(simpleName);
michael@0 33945 }),
michael@0 33946 describeTypeJSON: constant(describeTypeJSON),
michael@0 33947 original: jsGlobal[VM_NATIVE_BUILTIN_ORIGINALS]
michael@0 33948 };
michael@0 33949 function describeTypeJSON(o, flags) {
michael@0 33950 var Flags = {
michael@0 33951 HIDE_NSURI_METHODS: 1,
michael@0 33952 INCLUDE_BASES: 2,
michael@0 33953 INCLUDE_INTERFACES: 4,
michael@0 33954 INCLUDE_VARIABLES: 8,
michael@0 33955 INCLUDE_ACCESSORS: 16,
michael@0 33956 INCLUDE_METHODS: 32,
michael@0 33957 INCLUDE_METADATA: 64,
michael@0 33958 INCLUDE_CONSTRUCTOR: 128,
michael@0 33959 INCLUDE_TRAITS: 256,
michael@0 33960 USE_ITRAITS: 512,
michael@0 33961 HIDE_OBJECT: 1024
michael@0 33962 };
michael@0 33963 var declaredByKey = publicName('declaredBy');
michael@0 33964 var metadataKey = publicName('metadata');
michael@0 33965 var accessKey = publicName('access');
michael@0 33966 var uriKey = publicName('uri');
michael@0 33967 var nameKey = publicName('name');
michael@0 33968 var typeKey = publicName('type');
michael@0 33969 var returnTypeKey = publicName('returnType');
michael@0 33970 var valueKey = publicName('value');
michael@0 33971 var keyKey = publicName('key');
michael@0 33972 var parametersKey = publicName('parameters');
michael@0 33973 var optionalKey = publicName('optional');
michael@0 33974 var cls = o.classInfo ? o : Object.getPrototypeOf(o).class;
michael@0 33975 true;
michael@0 33976 var info = cls.classInfo;
michael@0 33977 var description = {};
michael@0 33978 description[nameKey] = unmangledQualifiedName(info.instanceInfo.name);
michael@0 33979 description[publicName('isDynamic')] = cls === o ? true : !(info.instanceInfo.flags & CONSTANT_ClassSealed);
michael@0 33980 description[publicName('isStatic')] = cls === o;
michael@0 33981 description[publicName('isFinal')] = cls === o ? true : !(info.instanceInfo.flags & CONSTANT_ClassFinal);
michael@0 33982 if (flags & Flags.INCLUDE_TRAITS) {
michael@0 33983 description[publicName('traits')] = addTraits(cls, flags);
michael@0 33984 }
michael@0 33985 var metadata = null;
michael@0 33986 if (info.metadata) {
michael@0 33987 metadata = Object.keys(info.metadata).map(function (key) {
michael@0 33988 return describeMetadata(info.metadata[key]);
michael@0 33989 });
michael@0 33990 }
michael@0 33991 description[metadataKey] = metadata;
michael@0 33992 return description;
michael@0 33993 function publicName(str) {
michael@0 33994 return Multiname.getPublicQualifiedName(str);
michael@0 33995 }
michael@0 33996 function unmangledQualifiedName(mn) {
michael@0 33997 var name = mn.name;
michael@0 33998 var namespace = mn.namespaces[0];
michael@0 33999 if (namespace && namespace.uri) {
michael@0 34000 return namespace.uri + '::' + name;
michael@0 34001 }
michael@0 34002 return name;
michael@0 34003 }
michael@0 34004 function describeMetadata(metadata) {
michael@0 34005 var result = {};
michael@0 34006 result[nameKey] = metadata.name;
michael@0 34007 result[valueKey] = metadata.value.map(function (value) {
michael@0 34008 var val = {};
michael@0 34009 val[keyKey] = value.key;
michael@0 34010 val[valueKey] = value.value;
michael@0 34011 return value;
michael@0 34012 });
michael@0 34013 return result;
michael@0 34014 }
michael@0 34015 function addTraits(cls, flags) {
michael@0 34016 var includedMembers = [
michael@0 34017 flags & Flags.INCLUDE_VARIABLES,
michael@0 34018 flags & Flags.INCLUDE_METHODS,
michael@0 34019 flags & Flags.INCLUDE_ACCESSORS,
michael@0 34020 flags & Flags.INCLUDE_ACCESSORS
michael@0 34021 ];
michael@0 34022 var includeBases = flags & Flags.INCLUDE_BASES;
michael@0 34023 var includeMetadata = flags & Flags.INCLUDE_METADATA;
michael@0 34024 var obj = {};
michael@0 34025 var basesVal = obj[publicName('bases')] = includeBases ? [] : null;
michael@0 34026 if (flags & Flags.INCLUDE_INTERFACES) {
michael@0 34027 var interfacesVal = obj[publicName('interfaces')] = [];
michael@0 34028 if (flags & Flags.USE_ITRAITS) {
michael@0 34029 for (var key in cls.implementedInterfaces) {
michael@0 34030 var ifaceName = cls.implementedInterfaces[key].name;
michael@0 34031 interfacesVal.push(unmangledQualifiedName(ifaceName));
michael@0 34032 }
michael@0 34033 }
michael@0 34034 } else {
michael@0 34035 obj[publicName('interfaces')] = null;
michael@0 34036 }
michael@0 34037 var variablesVal = obj[publicName('variables')] = flags & Flags.INCLUDE_VARIABLES ? [] : null;
michael@0 34038 var accessorsVal = obj[publicName('accessors')] = flags & Flags.INCLUDE_ACCESSORS ? [] : null;
michael@0 34039 var methodsVal = obj[publicName('methods')] = flags & Flags.INCLUDE_METHODS ? [] : null;
michael@0 34040 var encounteredAccessors = {};
michael@0 34041 var addBase = false;
michael@0 34042 while (cls) {
michael@0 34043 var className = unmangledQualifiedName(cls.classInfo.instanceInfo.name);
michael@0 34044 if (includeBases && addBase) {
michael@0 34045 basesVal.push(className);
michael@0 34046 } else {
michael@0 34047 addBase = true;
michael@0 34048 }
michael@0 34049 if (flags & Flags.USE_ITRAITS) {
michael@0 34050 describeTraits(cls.classInfo.instanceInfo.traits);
michael@0 34051 } else {
michael@0 34052 describeTraits(cls.classInfo.traits);
michael@0 34053 }
michael@0 34054 cls = cls.baseClass;
michael@0 34055 }
michael@0 34056 function describeTraits(traits) {
michael@0 34057 true;
michael@0 34058 for (var i = 0; traits && i < traits.length; i++) {
michael@0 34059 var t = traits[i];
michael@0 34060 if (!includedMembers[t.kind] || !t.name.getNamespace().isPublic() && !t.name.uri) {
michael@0 34061 continue;
michael@0 34062 }
michael@0 34063 var name = unmangledQualifiedName(t.name);
michael@0 34064 if (encounteredAccessors[name]) {
michael@0 34065 var val = encounteredAccessors[name];
michael@0 34066 val[accessKey] = 'readwrite';
michael@0 34067 if (t.kind === TRAIT_Getter) {
michael@0 34068 val[typeKey] = unmangledQualifiedName(t.methodInfo.returnType);
michael@0 34069 }
michael@0 34070 continue;
michael@0 34071 }
michael@0 34072 var val = {};
michael@0 34073 if (includeMetadata && t.metadata) {
michael@0 34074 var metadataVal = val[metadataKey] = [];
michael@0 34075 for (var key in t.metadata) {
michael@0 34076 metadataVal.push(describeMetadata(t.metadata[key]));
michael@0 34077 }
michael@0 34078 } else {
michael@0 34079 val[metadataKey] = null;
michael@0 34080 }
michael@0 34081 val[declaredByKey] = className;
michael@0 34082 val[uriKey] = t.name.uri === undefined ? null : t.name.uri;
michael@0 34083 val[nameKey] = name;
michael@0 34084 if (!t.typeName && !(t.methodInfo && t.methodInfo.returnType)) {
michael@0 34085 continue;
michael@0 34086 }
michael@0 34087 val[t.kind === TRAIT_Method ? returnTypeKey : typeKey] = unmangledQualifiedName(t.kind === TRAIT_Slot ? t.typeName : t.methodInfo.returnType);
michael@0 34088 switch (t.kind) {
michael@0 34089 case TRAIT_Slot:
michael@0 34090 val[accessKey] = 'readwrite';
michael@0 34091 variablesVal.push(val);
michael@0 34092 break;
michael@0 34093 case TRAIT_Method:
michael@0 34094 var parametersVal = val[parametersKey] = [];
michael@0 34095 var parameters = t.methodInfo.parameters;
michael@0 34096 for (var j = 0; j < parameters.length; j++) {
michael@0 34097 var param = parameters[j];
michael@0 34098 var paramVal = {};
michael@0 34099 paramVal[typeKey] = param.type ? unmangledQualifiedName(param.type) : '*';
michael@0 34100 paramVal[optionalKey] = 'value' in param;
michael@0 34101 parametersVal.push(paramVal);
michael@0 34102 }
michael@0 34103 methodsVal.push(val);
michael@0 34104 break;
michael@0 34105 case TRAIT_Getter:
michael@0 34106 case TRAIT_Setter:
michael@0 34107 val[accessKey] = t.kind === TRAIT_Getter ? 'read' : 'write';
michael@0 34108 accessorsVal.push(val);
michael@0 34109 encounteredAccessors[name] = val;
michael@0 34110 break;
michael@0 34111 default:
michael@0 34112 break;
michael@0 34113 }
michael@0 34114 }
michael@0 34115 }
michael@0 34116 return obj;
michael@0 34117 }
michael@0 34118 }
michael@0 34119 }();
michael@0 34120 function getNative(path) {
michael@0 34121 var chain = path.split('.');
michael@0 34122 var v = natives;
michael@0 34123 for (var i = 0, j = chain.length; i < j; i++) {
michael@0 34124 v = v && v[chain[i]];
michael@0 34125 }
michael@0 34126 true;
michael@0 34127 return v;
michael@0 34128 }
michael@0 34129 var disassemblerOptions = systemOptions.register(new OptionSet('Disassembler Options'));
michael@0 34130 var filter = disassemblerOptions.register(new Option('f', 'filter', 'string', 'SpciMsmNtu', '[S]ource, constant[p]ool, [c]lasses, [i]nstances, [M]etadata, [s]cripts, [m]ethods, multi[N]ames, S[t]atistics, [u]tf'));
michael@0 34131 function traceArray(writer, name, array, abc) {
michael@0 34132 if (array.length === 0) {
michael@0 34133 return;
michael@0 34134 }
michael@0 34135 writer.enter(name + ' {');
michael@0 34136 array.forEach(function (a, idx) {
michael@0 34137 a.trace(writer, abc);
michael@0 34138 });
michael@0 34139 writer.leave('}');
michael@0 34140 }
michael@0 34141 AbcFile.prototype.trace = function trace(writer) {
michael@0 34142 if (filter.value.indexOf('p') >= 0) {
michael@0 34143 this.constantPool.trace(writer);
michael@0 34144 }
michael@0 34145 if (filter.value.indexOf('N') >= 0) {
michael@0 34146 this.constantPool.traceMultinamesOnly(writer);
michael@0 34147 }
michael@0 34148 if (filter.value.indexOf('c') >= 0) {
michael@0 34149 traceArray(writer, 'classes', this.classes);
michael@0 34150 }
michael@0 34151 if (filter.value.indexOf('i') >= 0) {
michael@0 34152 traceArray(writer, 'instances', this.instances);
michael@0 34153 }
michael@0 34154 if (filter.value.indexOf('M') >= 0) {
michael@0 34155 traceArray(writer, 'metadata', this.metadata);
michael@0 34156 }
michael@0 34157 if (filter.value.indexOf('s') >= 0) {
michael@0 34158 traceArray(writer, 'scripts', this.scripts);
michael@0 34159 }
michael@0 34160 if (filter.value.indexOf('m') >= 0) {
michael@0 34161 traceArray(writer, 'methods', this.methods, this);
michael@0 34162 }
michael@0 34163 if (filter.value.indexOf('S') >= 0) {
michael@0 34164 traceSource(writer, this);
michael@0 34165 }
michael@0 34166 if (filter.value.indexOf('t') >= 0) {
michael@0 34167 traceStatistics(writer, this);
michael@0 34168 }
michael@0 34169 if (filter.value.indexOf('u') >= 0) {
michael@0 34170 print(JSON.stringify({
michael@0 34171 strings: this.constantPool.strings,
michael@0 34172 positionAfterUTFStrings: this.constantPool.positionAfterUTFStrings
michael@0 34173 }, null, 2));
michael@0 34174 }
michael@0 34175 };
michael@0 34176 ConstantPool.prototype.trace = function (writer) {
michael@0 34177 writer.enter('constantPool {');
michael@0 34178 for (var key in this) {
michael@0 34179 if (key === 'namespaces') {
michael@0 34180 writer.enter('namespaces {');
michael@0 34181 this.namespaces.forEach(function (ns, i) {
michael@0 34182 writer.writeLn(('' + i).padRight(' ', 3) + (ns ? ns.toString() : '*'));
michael@0 34183 });
michael@0 34184 writer.leave('}');
michael@0 34185 } else if (this[key] instanceof Array) {
michael@0 34186 writer.enter(key + ' ' + this[key].length + ' {');
michael@0 34187 writer.writeArray(this[key]);
michael@0 34188 writer.leave('}');
michael@0 34189 }
michael@0 34190 }
michael@0 34191 writer.leave('}');
michael@0 34192 };
michael@0 34193 ConstantPool.prototype.traceMultinamesOnly = function (writer) {
michael@0 34194 writer.writeArray(this.multinames, null, true);
michael@0 34195 };
michael@0 34196 ClassInfo.prototype.trace = function (writer) {
michael@0 34197 writer.enter('class ' + this + ' {');
michael@0 34198 traceArray(writer, 'traits', this.traits);
michael@0 34199 writer.leave('}');
michael@0 34200 };
michael@0 34201 MetaDataInfo.prototype.trace = function (writer) {
michael@0 34202 writer.enter(this + ' {');
michael@0 34203 this.value.forEach(function (item) {
michael@0 34204 writer.writeLn((item.key ? item.key + ': ' : '') + '"' + item.value + '"');
michael@0 34205 });
michael@0 34206 writer.leave('}');
michael@0 34207 };
michael@0 34208 InstanceInfo.prototype.trace = function (writer) {
michael@0 34209 writer.enter('instance ' + this + ' {');
michael@0 34210 traceArray(writer, 'traits', this.traits);
michael@0 34211 writer.leave('}');
michael@0 34212 };
michael@0 34213 ScriptInfo.prototype.trace = function (writer) {
michael@0 34214 writer.enter('script ' + this + ' {');
michael@0 34215 traceArray(writer, 'traits', this.traits);
michael@0 34216 writer.leave('}');
michael@0 34217 };
michael@0 34218 Trait.prototype.trace = function (writer) {
michael@0 34219 if (this.metadata) {
michael@0 34220 for (var key in this.metadata) {
michael@0 34221 if (this.metadata.hasOwnProperty(key)) {
michael@0 34222 this.metadata[key].trace(writer);
michael@0 34223 }
michael@0 34224 }
michael@0 34225 }
michael@0 34226 writer.writeLn(this);
michael@0 34227 };
michael@0 34228 function traceAbc(writer, abc) {
michael@0 34229 abc.trace(writer);
michael@0 34230 }
michael@0 34231 function traceOperand(operand, abc, code) {
michael@0 34232 var value = 0;
michael@0 34233 switch (operand.size) {
michael@0 34234 case 's08':
michael@0 34235 value = code.readS8();
michael@0 34236 break;
michael@0 34237 case 'u08':
michael@0 34238 value = code.readU8();
michael@0 34239 break;
michael@0 34240 case 's16':
michael@0 34241 value = code.readS16();
michael@0 34242 break;
michael@0 34243 case 's24':
michael@0 34244 value = code.readS24();
michael@0 34245 break;
michael@0 34246 case 'u30':
michael@0 34247 value = code.readU30();
michael@0 34248 break;
michael@0 34249 case 'u32':
michael@0 34250 value = code.readU32();
michael@0 34251 break;
michael@0 34252 default:
michael@0 34253 true;
michael@0 34254 break;
michael@0 34255 }
michael@0 34256 var description = '';
michael@0 34257 switch (operand.type) {
michael@0 34258 case '':
michael@0 34259 break;
michael@0 34260 case 'I':
michael@0 34261 description = abc.constantPool.ints[value];
michael@0 34262 break;
michael@0 34263 case 'U':
michael@0 34264 description = abc.constantPool.uints[value];
michael@0 34265 break;
michael@0 34266 case 'D':
michael@0 34267 description = abc.constantPool.doubles[value];
michael@0 34268 break;
michael@0 34269 case 'S':
michael@0 34270 description = abc.constantPool.strings[value];
michael@0 34271 break;
michael@0 34272 case 'N':
michael@0 34273 description = abc.constantPool.namespaces[value];
michael@0 34274 break;
michael@0 34275 case 'CI':
michael@0 34276 description = abc.classes[value];
michael@0 34277 break;
michael@0 34278 case 'M':
michael@0 34279 return abc.constantPool.multinames[value];
michael@0 34280 default:
michael@0 34281 description = '?';
michael@0 34282 break;
michael@0 34283 }
michael@0 34284 return operand.name + ':' + value + (description === '' ? '' : ' (' + description + ')');
michael@0 34285 }
michael@0 34286 function traceOperands(opcode, abc, code, rewind) {
michael@0 34287 rewind = rewind || false;
michael@0 34288 var old = code.position;
michael@0 34289 var str = '';
michael@0 34290 if (opcode.operands === null) {
michael@0 34291 str = 'null';
michael@0 34292 } else {
michael@0 34293 opcode.operands.forEach(function (op, i) {
michael@0 34294 str += traceOperand(op, abc, code);
michael@0 34295 if (i < opcode.operands.length - 1) {
michael@0 34296 str += ', ';
michael@0 34297 }
michael@0 34298 });
michael@0 34299 }
michael@0 34300 if (rewind) {
michael@0 34301 code.seek(old);
michael@0 34302 }
michael@0 34303 return str;
michael@0 34304 }
michael@0 34305 MethodInfo.prototype.trace = function trace(writer) {
michael@0 34306 var abc = this.abc;
michael@0 34307 writer.enter('method' + (this.name ? ' ' + this.name : '') + ' {');
michael@0 34308 writer.writeLn('flags: ' + getFlags(this.flags, 'NEED_ARGUMENTS|NEED_ACTIVATION|NEED_REST|HAS_OPTIONAL||NATIVE|SET_DXN|HAS_PARAM_NAMES'.split('|')));
michael@0 34309 writer.writeLn('parameters: ' + this.parameters.map(function (x) {
michael@0 34310 return (x.type ? Multiname.getQualifiedName(x.type) + '::' : '') + x.name;
michael@0 34311 }));
michael@0 34312 if (!this.code) {
michael@0 34313 writer.leave('}');
michael@0 34314 return;
michael@0 34315 }
michael@0 34316 var code = new AbcStream(this.code);
michael@0 34317 traceArray(writer, 'traits', this.traits);
michael@0 34318 writer.enter('code {');
michael@0 34319 while (code.remaining() > 0) {
michael@0 34320 var bc = code.readU8();
michael@0 34321 var opcode = opcodeTable[bc];
michael@0 34322 var str, defaultOffset, offset, count;
michael@0 34323 str = ('' + code.position).padRight(' ', 6);
michael@0 34324 switch (bc) {
michael@0 34325 case OP_lookupswitch:
michael@0 34326 str += opcode.name + ': defaultOffset: ' + code.readS24();
michael@0 34327 var caseCount = code.readU30();
michael@0 34328 str += ', caseCount: ' + caseCount;
michael@0 34329 for (var i = 0; i < caseCount + 1; i++) {
michael@0 34330 str += ' offset: ' + code.readS24();
michael@0 34331 }
michael@0 34332 writer.writeLn(str);
michael@0 34333 break;
michael@0 34334 default:
michael@0 34335 if (opcode) {
michael@0 34336 str += opcode.name.padRight(' ', 20);
michael@0 34337 if (!opcode.operands) {
michael@0 34338 true;
michael@0 34339 } else {
michael@0 34340 if (opcode.operands.length > 0) {
michael@0 34341 str += traceOperands(opcode, abc, code);
michael@0 34342 }
michael@0 34343 writer.writeLn(str);
michael@0 34344 }
michael@0 34345 } else {
michael@0 34346 true;
michael@0 34347 }
michael@0 34348 break;
michael@0 34349 }
michael@0 34350 }
michael@0 34351 writer.leave('}');
michael@0 34352 writer.leave('}');
michael@0 34353 };
michael@0 34354 var SourceTracer = function () {
michael@0 34355 function literal(value) {
michael@0 34356 if (value === undefined) {
michael@0 34357 return 'undefined';
michael@0 34358 } else if (value === null) {
michael@0 34359 return 'null';
michael@0 34360 } else if (typeof value === 'string') {
michael@0 34361 return '"' + value + '"';
michael@0 34362 } else {
michael@0 34363 return String(value);
michael@0 34364 }
michael@0 34365 }
michael@0 34366 function getSignature(mi, excludeTypesAndDefaultValues) {
michael@0 34367 return mi.parameters.map(function (x) {
michael@0 34368 var str = x.name;
michael@0 34369 if (!excludeTypesAndDefaultValues) {
michael@0 34370 if (x.type) {
michael@0 34371 str += ':' + x.type.getName();
michael@0 34372 }
michael@0 34373 if (x.value !== undefined) {
michael@0 34374 str += ' = ' + literal(x.value);
michael@0 34375 }
michael@0 34376 }
michael@0 34377 return str;
michael@0 34378 }).join(', ');
michael@0 34379 }
michael@0 34380 function SourceTracer(writer) {
michael@0 34381 this.writer = writer;
michael@0 34382 }
michael@0 34383 SourceTracer.prototype = {
michael@0 34384 traceTraits: function traceTraits(traits, isStatic, inInterfaceNamespace) {
michael@0 34385 var writer = this.writer;
michael@0 34386 var tracer = this;
michael@0 34387 traits.forEach(function (trait) {
michael@0 34388 var str;
michael@0 34389 var accessModifier = Multiname.getAccessModifier(trait.name);
michael@0 34390 var namespaceName = trait.name.namespaces[0].uri;
michael@0 34391 if (namespaceName) {
michael@0 34392 if (namespaceName === 'http://adobe.com/AS3/2006/builtin') {
michael@0 34393 namespaceName = 'AS3';
michael@0 34394 }
michael@0 34395 if (accessModifier === 'public') {
michael@0 34396 str = inInterfaceNamespace === namespaceName ? '' : namespaceName;
michael@0 34397 } else {
michael@0 34398 str = accessModifier;
michael@0 34399 }
michael@0 34400 } else {
michael@0 34401 str = accessModifier;
michael@0 34402 }
michael@0 34403 if (isStatic) {
michael@0 34404 str += ' static';
michael@0 34405 }
michael@0 34406 if (trait.isSlot() || trait.isConst()) {
michael@0 34407 tracer.traceMetadata(trait.metadata);
michael@0 34408 if (trait.isConst()) {
michael@0 34409 str += ' const';
michael@0 34410 } else {
michael@0 34411 str += ' var';
michael@0 34412 }
michael@0 34413 str += ' ' + trait.name.getName();
michael@0 34414 if (trait.typeName) {
michael@0 34415 str += ':' + trait.typeName.getName();
michael@0 34416 }
michael@0 34417 if (trait.value) {
michael@0 34418 str += ' = ' + literal(trait.value);
michael@0 34419 }
michael@0 34420 writer.writeLn(str + ';');
michael@0 34421 } else if (trait.isMethod() || trait.isGetter() || trait.isSetter()) {
michael@0 34422 tracer.traceMetadata(trait.metadata);
michael@0 34423 var mi = trait.methodInfo;
michael@0 34424 if (trait.attributes & ATTR_Override) {
michael@0 34425 str += ' override';
michael@0 34426 }
michael@0 34427 if (mi.isNative()) {
michael@0 34428 str += ' native';
michael@0 34429 }
michael@0 34430 str += ' function';
michael@0 34431 str += trait.isGetter() ? ' get' : trait.isSetter() ? ' set' : '';
michael@0 34432 str += ' ' + trait.name.getName();
michael@0 34433 str += '(' + getSignature(mi) + ')';
michael@0 34434 str += mi.returnType ? ':' + mi.returnType.getName() : '';
michael@0 34435 if (true) {
michael@0 34436 var className;
michael@0 34437 var prefix = '';
michael@0 34438 if (trait.holder instanceof ClassInfo) {
michael@0 34439 className = trait.holder.instanceInfo.name;
michael@0 34440 if (className.namespaces[0].uri) {
michael@0 34441 prefix += className.namespaces[0].uri + '::';
michael@0 34442 }
michael@0 34443 prefix += className.getName();
michael@0 34444 prefix += '$/';
michael@0 34445 } else if (trait.holder instanceof InstanceInfo) {
michael@0 34446 className = trait.holder.name;
michael@0 34447 if (className.namespaces[0].uri) {
michael@0 34448 prefix += className.namespaces[0].uri + '::';
michael@0 34449 }
michael@0 34450 prefix += className.getName();
michael@0 34451 prefix += '/';
michael@0 34452 } else {
michael@0 34453 prefix = 'global/';
michael@0 34454 }
michael@0 34455 var getSet = trait.isGetter() ? 'get ' : trait.isSetter() ? 'set ' : '';
michael@0 34456 if (!mi.isNative()) {
michael@0 34457 }
michael@0 34458 }
michael@0 34459 if (mi.isNative()) {
michael@0 34460 writer.writeLn(str + ';');
michael@0 34461 } else {
michael@0 34462 if (inInterfaceNamespace) {
michael@0 34463 writer.writeLn(str + ';');
michael@0 34464 } else {
michael@0 34465 writer.writeLn(str + ' { notImplemented("' + trait.name.getName() + '"); }');
michael@0 34466 }
michael@0 34467 }
michael@0 34468 } else if (trait.isClass()) {
michael@0 34469 var className = trait.classInfo.instanceInfo.name;
michael@0 34470 writer.enter('package ' + className.namespaces[0].uri + ' {\n');
michael@0 34471 tracer.traceMetadata(trait.metadata);
michael@0 34472 tracer.traceClass(trait.classInfo);
michael@0 34473 writer.leave('\n}');
michael@0 34474 tracer.traceClassStub(trait);
michael@0 34475 } else {
michael@0 34476 notImplemented();
michael@0 34477 }
michael@0 34478 });
michael@0 34479 },
michael@0 34480 traceClassStub2: function traceClassStub(trait) {
michael@0 34481 var writer = this.writer;
michael@0 34482 var ci = trait.classInfo;
michael@0 34483 var ii = ci.instanceInfo;
michael@0 34484 var name = ii.name.getName();
michael@0 34485 var native = trait.metadata ? trait.metadata.native : null;
michael@0 34486 if (!native) {
michael@0 34487 return false;
michael@0 34488 }
michael@0 34489 writer.writeLn('Cut and paste the following into `native.js\' and edit accordingly');
michael@0 34490 writer.writeLn('8< --------------------------------------------------------------');
michael@0 34491 writer.enter('natives.' + native.cls + ' = function ' + native.cls + '(runtime, scope, instanceConstructor, baseClass) {');
michael@0 34492 writer.writeLn('var c = new Class("' + name + '", instanceConstructor, ApplicationDomain.passthroughCallable(instanceConstructor));');
michael@0 34493 writer.writeLn('c.extend(baseClass);\n');
michael@0 34494 function traceTraits(traits, isStatic) {
michael@0 34495 var nativeMethodTraits = [];
michael@0 34496 traits.forEach(function (trait, i) {
michael@0 34497 if (trait.isMethod() || trait.isGetter() || trait.isSetter()) {
michael@0 34498 if (trait.methodInfo.isNative()) {
michael@0 34499 nativeMethodTraits.push(trait);
michael@0 34500 }
michael@0 34501 }
michael@0 34502 });
michael@0 34503 nativeMethodTraits.forEach(function (trait, i) {
michael@0 34504 var mi = trait.methodInfo;
michael@0 34505 var traitName = trait.name.getName();
michael@0 34506 writer.writeLn('// ' + traitName + ' :: ' + (mi.parameters.length ? getSignature(mi) : 'void') + ' -> ' + (mi.returnType ? mi.returnType.getName() : 'any'));
michael@0 34507 var prop;
michael@0 34508 if (trait.isGetter()) {
michael@0 34509 prop = '"get ' + traitName + '"';
michael@0 34510 } else if (trait.isSetter()) {
michael@0 34511 prop = '"set ' + traitName + '"';
michael@0 34512 } else {
michael@0 34513 prop = traitName;
michael@0 34514 }
michael@0 34515 writer.enter(prop + ': function ' + traitName + '(' + getSignature(mi, true) + ') {');
michael@0 34516 writer.writeLn(' notImplemented("' + name + '.' + traitName + '");');
michael@0 34517 writer.leave('}' + (i === nativeMethodTraits.length - 1 ? '' : ',\n'));
michael@0 34518 });
michael@0 34519 }
michael@0 34520 writer.enter('c.nativeStatics = {');
michael@0 34521 traceTraits(ci.traits, true);
michael@0 34522 writer.leave('};\n');
michael@0 34523 writer.enter('c.nativeMethods = {');
michael@0 34524 traceTraits(ii.traits);
michael@0 34525 writer.leave('};\n');
michael@0 34526 writer.writeLn('return c;');
michael@0 34527 writer.leave('};');
michael@0 34528 writer.writeLn('-------------------------------------------------------------- >8');
michael@0 34529 return true;
michael@0 34530 },
michael@0 34531 traceClassStub: function traceClassStub(trait) {
michael@0 34532 var writer = this.writer;
michael@0 34533 var ci = trait.classInfo;
michael@0 34534 var ii = ci.instanceInfo;
michael@0 34535 var className = ii.name.getName();
michael@0 34536 var native = trait.metadata ? trait.metadata.native : null;
michael@0 34537 writer.writeLn('Cut and paste the following glue and edit accordingly.');
michael@0 34538 writer.writeLn('Class ' + ii);
michael@0 34539 writer.writeLn('8< --------------------------------------------------------------');
michael@0 34540 var uri = ii.name.namespaces[0].uri;
michael@0 34541 writer.enter('var ' + className + 'Definition = (function () {');
michael@0 34542 function maxTraitNameLength(traits) {
michael@0 34543 var length = 0;
michael@0 34544 traits.forEach(function (t) {
michael@0 34545 length = Math.max(t.name.name.length, length);
michael@0 34546 });
michael@0 34547 return length;
michael@0 34548 }
michael@0 34549 function quote(s) {
michael@0 34550 return '\'' + s + '\'';
michael@0 34551 }
michael@0 34552 function filterTraits(traits, isNative) {
michael@0 34553 function isMethod(x) {
michael@0 34554 return x.isMethod() || x.isGetter() || x.isSetter();
michael@0 34555 }
michael@0 34556 return {
michael@0 34557 properties: traits.filter(function (trait) {
michael@0 34558 return !isNative && !isMethod(trait);
michael@0 34559 }),
michael@0 34560 methods: traits.filter(function (trait) {
michael@0 34561 return isMethod(trait) && isNative === trait.methodInfo.isNative();
michael@0 34562 })
michael@0 34563 };
michael@0 34564 }
michael@0 34565 function writeTraits(traits, isNative, isStatic) {
michael@0 34566 traits = filterTraits(traits, isNative);
michael@0 34567 var methods = [];
michael@0 34568 var gettersAndSetters = createEmptyObject();
michael@0 34569 traits.methods.forEach(function (trait, i) {
michael@0 34570 var traitName = trait.name.getName();
michael@0 34571 if (trait.isGetter() || trait.isSetter()) {
michael@0 34572 if (!gettersAndSetters[traitName]) {
michael@0 34573 gettersAndSetters[traitName] = [];
michael@0 34574 }
michael@0 34575 gettersAndSetters[traitName].push(trait);
michael@0 34576 } else {
michael@0 34577 methods.push(trait);
michael@0 34578 }
michael@0 34579 });
michael@0 34580 function writeTrait(trait, writeComma) {
michael@0 34581 var mi = trait.methodInfo;
michael@0 34582 var traitName = trait.name.getName();
michael@0 34583 var signature = '// (' + (mi.parameters.length ? getSignature(mi) : 'void') + ') -> ' + (mi.returnType ? mi.returnType.getName() : 'any');
michael@0 34584 var propertyName = traitName;
michael@0 34585 if (trait.isGetter()) {
michael@0 34586 propertyName = 'get';
michael@0 34587 } else if (trait.isSetter()) {
michael@0 34588 propertyName = 'set';
michael@0 34589 }
michael@0 34590 writer.enter(propertyName + ': function ' + traitName + '(' + getSignature(mi, true) + ') { ' + signature);
michael@0 34591 writer.writeLn('notImplemented("' + className + '.' + traitName + '");');
michael@0 34592 if (!isStatic) {
michael@0 34593 if (trait.isGetter()) {
michael@0 34594 writer.writeLn('return this._' + traitName + ';');
michael@0 34595 } else if (trait.isSetter()) {
michael@0 34596 writer.writeLn('this._' + traitName + ' = ' + mi.parameters[0].name + ';');
michael@0 34597 }
michael@0 34598 }
michael@0 34599 writer.leave('}' + (writeComma ? ',' : ''));
michael@0 34600 }
michael@0 34601 for (var i = 0; i < methods.length; i++) {
michael@0 34602 writeTrait(methods[i], i < methods.length - 1);
michael@0 34603 }
michael@0 34604 var keyValues = toKeyValueArray(gettersAndSetters);
michael@0 34605 for (var j = 0; j < keyValues.length; j++) {
michael@0 34606 writer.enter(keyValues[j][0] + ': {');
michael@0 34607 var list = keyValues[j][1];
michael@0 34608 for (var i = 0; i < list.length; i++) {
michael@0 34609 writeTrait(list[i], i < list.length - 1);
michael@0 34610 }
michael@0 34611 writer.leave('}' + (j < keyValues.length - 1 ? ',' : ''));
michael@0 34612 }
michael@0 34613 traits.properties.forEach(function (trait, i) {
michael@0 34614 var traitName = trait.name.getName();
michael@0 34615 var last = i === traits.properties.length - 1;
michael@0 34616 if (trait.name.getNamespace().isPublic()) {
michael@0 34617 writer.writeLn(traitName + ': ' + quote('public ' + trait.name.name) + (last ? '' : ','));
michael@0 34618 }
michael@0 34619 });
michael@0 34620 }
michael@0 34621 writer.enter('return {');
michael@0 34622 writer.writeLn('// (' + getSignature(ii.init, false) + ')');
michael@0 34623 writer.writeLn('__class__: "' + uri + '.' + className + '",');
michael@0 34624 writer.enter('initialize: function () {');
michael@0 34625 writer.leave('},');
michael@0 34626 writer.enter('__glue__: {');
michael@0 34627 writer.enter('native: {');
michael@0 34628 writer.enter('static: {');
michael@0 34629 writeTraits(ci.traits, true, true);
michael@0 34630 writer.leave('},');
michael@0 34631 writer.enter('instance: {');
michael@0 34632 writeTraits(ii.traits, true);
michael@0 34633 writer.leave('}');
michael@0 34634 writer.leave('},');
michael@0 34635 writer.enter('script: {');
michael@0 34636 writer.writeLn('instance: Glue.ALL');
michael@0 34637 writer.leave('}');
michael@0 34638 writer.leave('}');
michael@0 34639 writer.leave('};');
michael@0 34640 writer.leave('}).call(this);');
michael@0 34641 writer.writeLn('-------------------------------------------------------------- >8');
michael@0 34642 return true;
michael@0 34643 },
michael@0 34644 traceClass: function traceClass(ci) {
michael@0 34645 var writer = this.writer;
michael@0 34646 var ii = ci.instanceInfo;
michael@0 34647 var name = ii.name;
michael@0 34648 var str = Multiname.getAccessModifier(name);
michael@0 34649 if (ii.isFinal()) {
michael@0 34650 str += ' final';
michael@0 34651 }
michael@0 34652 if (!ii.isSealed()) {
michael@0 34653 str += ' dynamic';
michael@0 34654 }
michael@0 34655 str += ii.isInterface() ? ' interface ' : ' class ';
michael@0 34656 str += name.getName();
michael@0 34657 if (ii.superName && ii.superName.getName() !== 'Object') {
michael@0 34658 str += ' extends ' + ii.superName.getName();
michael@0 34659 }
michael@0 34660 if (ii.interfaces.length) {
michael@0 34661 str += ' implements ' + ii.interfaces.map(function (x) {
michael@0 34662 return x.getName();
michael@0 34663 }).join(', ');
michael@0 34664 }
michael@0 34665 writer.enter(str + ' {');
michael@0 34666 if (!ii.isInterface()) {
michael@0 34667 writer.writeLn('public function ' + name.getName() + '(' + getSignature(ii.init) + ') {}');
michael@0 34668 }
michael@0 34669 var interfaceNamespace;
michael@0 34670 if (ii.isInterface()) {
michael@0 34671 interfaceNamespace = name.namespaces[0].uri + ':' + name.name;
michael@0 34672 }
michael@0 34673 this.traceTraits(ci.traits, true, interfaceNamespace);
michael@0 34674 this.traceTraits(ii.traits, false, interfaceNamespace);
michael@0 34675 writer.leave('}');
michael@0 34676 },
michael@0 34677 traceMetadata: function traceMetadata(metadata) {
michael@0 34678 var writer = this.writer;
michael@0 34679 for (var key in metadata) {
michael@0 34680 if (metadata.hasOwnProperty(key)) {
michael@0 34681 if (key.indexOf('__') === 0) {
michael@0 34682 continue;
michael@0 34683 }
michael@0 34684 writer.writeLn('[' + key + '(' + metadata[key].value.map(function (m) {
michael@0 34685 var str = m.key ? m.key + '=' : '';
michael@0 34686 return str + '"' + m.value + '"';
michael@0 34687 }).join(', ') + ')]');
michael@0 34688 }
michael@0 34689 }
michael@0 34690 }
michael@0 34691 };
michael@0 34692 return SourceTracer;
michael@0 34693 }();
michael@0 34694 function traceSource(writer, abc) {
michael@0 34695 var tracer = new SourceTracer(writer);
michael@0 34696 abc.scripts.forEach(function (script) {
michael@0 34697 tracer.traceTraits(script.traits);
michael@0 34698 });
michael@0 34699 }
michael@0 34700 function traceStatistics(writer, abc) {
michael@0 34701 var libraryClassCounter = new Shumway.Metrics.Counter(true);
michael@0 34702 var librarySuperClassCounter = new Shumway.Metrics.Counter(true);
michael@0 34703 var libraryMethodCounter = new Shumway.Metrics.Counter(true);
michael@0 34704 var libraryProperties = new Shumway.Metrics.Counter(true);
michael@0 34705 var definedClasses = {};
michael@0 34706 var definedMethods = {};
michael@0 34707 var definedProperties = {};
michael@0 34708 abc.classes.forEach(function (x) {
michael@0 34709 var className = x.instanceInfo.name.name;
michael@0 34710 definedClasses[className] = true;
michael@0 34711 });
michael@0 34712 abc.scripts.forEach(function (s) {
michael@0 34713 s.traits.forEach(function (t) {
michael@0 34714 if (t.isClass()) {
michael@0 34715 var superClassName = t.classInfo.instanceInfo.superName ? t.classInfo.instanceInfo.superName.name : '?';
michael@0 34716 if (!(superClassName in definedClasses)) {
michael@0 34717 librarySuperClassCounter.count(superClassName);
michael@0 34718 }
michael@0 34719 t.classInfo.traits.forEach(function (st) {
michael@0 34720 if (st.isMethod()) {
michael@0 34721 definedMethods[st.name.name] = true;
michael@0 34722 } else {
michael@0 34723 definedProperties[st.name.name] = true;
michael@0 34724 }
michael@0 34725 });
michael@0 34726 t.classInfo.instanceInfo.traits.forEach(function (it) {
michael@0 34727 if (it.isMethod() && !(it.attributes & ATTR_Override)) {
michael@0 34728 definedMethods[it.name.name] = true;
michael@0 34729 } else {
michael@0 34730 definedProperties[it.name.name] = true;
michael@0 34731 }
michael@0 34732 });
michael@0 34733 }
michael@0 34734 });
michael@0 34735 });
michael@0 34736 var opCounter = new Shumway.Metrics.Counter(true);
michael@0 34737 abc.methods.forEach(function (m) {
michael@0 34738 if (!m.code) {
michael@0 34739 return;
michael@0 34740 }
michael@0 34741 function readOperand(operand) {
michael@0 34742 var value = 0;
michael@0 34743 switch (operand.size) {
michael@0 34744 case 's08':
michael@0 34745 value = code.readS8();
michael@0 34746 break;
michael@0 34747 case 'u08':
michael@0 34748 value = code.readU8();
michael@0 34749 break;
michael@0 34750 case 's16':
michael@0 34751 value = code.readS16();
michael@0 34752 break;
michael@0 34753 case 's24':
michael@0 34754 value = code.readS24();
michael@0 34755 break;
michael@0 34756 case 'u30':
michael@0 34757 value = code.readU30();
michael@0 34758 break;
michael@0 34759 case 'u32':
michael@0 34760 value = code.readU32();
michael@0 34761 break;
michael@0 34762 default:
michael@0 34763 true;
michael@0 34764 break;
michael@0 34765 }
michael@0 34766 var description = '';
michael@0 34767 switch (operand.type) {
michael@0 34768 case '':
michael@0 34769 break;
michael@0 34770 case 'I':
michael@0 34771 description = abc.constantPool.ints[value];
michael@0 34772 break;
michael@0 34773 case 'U':
michael@0 34774 description = abc.constantPool.uints[value];
michael@0 34775 break;
michael@0 34776 case 'D':
michael@0 34777 description = abc.constantPool.doubles[value];
michael@0 34778 break;
michael@0 34779 case 'S':
michael@0 34780 description = abc.constantPool.strings[value];
michael@0 34781 break;
michael@0 34782 case 'N':
michael@0 34783 description = abc.constantPool.namespaces[value];
michael@0 34784 break;
michael@0 34785 case 'CI':
michael@0 34786 description = abc.classes[value];
michael@0 34787 break;
michael@0 34788 case 'M':
michael@0 34789 description = abc.constantPool.multinames[value];
michael@0 34790 break;
michael@0 34791 default:
michael@0 34792 description = '?';
michael@0 34793 break;
michael@0 34794 }
michael@0 34795 return description;
michael@0 34796 }
michael@0 34797 var code = new AbcStream(m.code);
michael@0 34798 while (code.remaining() > 0) {
michael@0 34799 var bc = code.readU8();
michael@0 34800 var op = opcodeTable[bc];
michael@0 34801 var operands = null;
michael@0 34802 if (op) {
michael@0 34803 opCounter.count(op.name);
michael@0 34804 if (op.operands) {
michael@0 34805 operands = op.operands.map(readOperand);
michael@0 34806 }
michael@0 34807 switch (bc) {
michael@0 34808 case OP_call:
michael@0 34809 case OP_callmethod:
michael@0 34810 continue;
michael@0 34811 case OP_callproperty:
michael@0 34812 case OP_callproplex:
michael@0 34813 case OP_callpropvoid:
michael@0 34814 case OP_callstatic:
michael@0 34815 case OP_callsuper:
michael@0 34816 case OP_callsupervoid:
michael@0 34817 if (operands[0] && !(operands[0].name in definedMethods)) {
michael@0 34818 libraryMethodCounter.count(operands[0].name);
michael@0 34819 }
michael@0 34820 break;
michael@0 34821 case OP_constructprop:
michael@0 34822 if (operands[0] && !(operands[0].name in definedClasses)) {
michael@0 34823 libraryClassCounter.count(operands[0].name);
michael@0 34824 }
michael@0 34825 break;
michael@0 34826 case OP_getproperty:
michael@0 34827 case OP_setproperty:
michael@0 34828 if (operands[0] && !(operands[0].name in definedProperties)) {
michael@0 34829 libraryProperties.count(operands[0].name);
michael@0 34830 }
michael@0 34831 break;
michael@0 34832 }
michael@0 34833 }
michael@0 34834 }
michael@0 34835 });
michael@0 34836 writer.writeLn(JSON.stringify({
michael@0 34837 definedClasses: definedClasses,
michael@0 34838 definedMethods: definedMethods,
michael@0 34839 definedProperties: definedProperties,
michael@0 34840 libraryClasses: libraryClassCounter.counts,
michael@0 34841 librarySuperClasses: librarySuperClassCounter.counts,
michael@0 34842 libraryMethods: libraryMethodCounter.counts,
michael@0 34843 libraryProperties: libraryProperties.counts,
michael@0 34844 operations: opCounter.counts
michael@0 34845 }, null, 2));
michael@0 34846 }
michael@0 34847 var Shumway;
michael@0 34848 (function (Shumway) {
michael@0 34849 (function (AVM2) {
michael@0 34850 var OP = Shumway.AVM2.ABC.OP;
michael@0 34851 var Scope = Shumway.AVM2.Runtime.Scope;
michael@0 34852 var asCoerceByMultiname = Shumway.AVM2.Runtime.asCoerceByMultiname;
michael@0 34853 var asGetSlot = Shumway.AVM2.Runtime.asGetSlot;
michael@0 34854 var asSetSlot = Shumway.AVM2.Runtime.asSetSlot;
michael@0 34855 var asHasNext2 = Shumway.AVM2.Runtime.asHasNext2;
michael@0 34856 var asCoerce = Shumway.AVM2.Runtime.asCoerce;
michael@0 34857 var asCoerceString = Shumway.AVM2.Runtime.asCoerceString;
michael@0 34858 var asAsType = Shumway.AVM2.Runtime.asAsType;
michael@0 34859 var asTypeOf = Shumway.AVM2.Runtime.asTypeOf;
michael@0 34860 var asIsInstanceOf = Shumway.AVM2.Runtime.asIsInstanceOf;
michael@0 34861 var asIsType = Shumway.AVM2.Runtime.asIsType;
michael@0 34862 var applyType = Shumway.AVM2.Runtime.applyType;
michael@0 34863 var createFunction = Shumway.AVM2.Runtime.createFunction;
michael@0 34864 var createClass = Shumway.AVM2.Runtime.createClass;
michael@0 34865 var getDescendants = Shumway.AVM2.Runtime.getDescendants;
michael@0 34866 var checkFilter = Shumway.AVM2.Runtime.checkFilter;
michael@0 34867 var asAdd = Shumway.AVM2.Runtime.asAdd;
michael@0 34868 var translateError = Shumway.AVM2.Runtime.translateError;
michael@0 34869 var asCreateActivation = Shumway.AVM2.Runtime.asCreateActivation;
michael@0 34870 var sliceArguments = Shumway.AVM2.Runtime.sliceArguments;
michael@0 34871 var boxValue = Shumway.ObjectUtilities.boxValue;
michael@0 34872 var popManyInto = Shumway.ArrayUtilities.popManyInto;
michael@0 34873 var construct = Shumway.AVM2.Runtime.construct;
michael@0 34874 var Multiname = Shumway.AVM2.ABC.Multiname;
michael@0 34875 var ScopeStack = function () {
michael@0 34876 function ScopeStack(parent) {
michael@0 34877 this.parent = parent;
michael@0 34878 this.stack = [];
michael@0 34879 this.isWith = [];
michael@0 34880 }
michael@0 34881 ScopeStack.prototype.push = function (object, isWith) {
michael@0 34882 this.stack.push(object);
michael@0 34883 this.isWith.push(!(!isWith));
michael@0 34884 };
michael@0 34885 ScopeStack.prototype.get = function (index) {
michael@0 34886 return this.stack[index];
michael@0 34887 };
michael@0 34888 ScopeStack.prototype.clear = function () {
michael@0 34889 this.stack.length = 0;
michael@0 34890 this.isWith.length = 0;
michael@0 34891 };
michael@0 34892 ScopeStack.prototype.pop = function () {
michael@0 34893 this.isWith.pop();
michael@0 34894 this.stack.pop();
michael@0 34895 };
michael@0 34896 ScopeStack.prototype.topScope = function () {
michael@0 34897 if (!this.scopes) {
michael@0 34898 this.scopes = [];
michael@0 34899 }
michael@0 34900 var parent = this.parent;
michael@0 34901 for (var i = 0; i < this.stack.length; i++) {
michael@0 34902 var object = this.stack[i], isWith = this.isWith[i], scope = this.scopes[i];
michael@0 34903 if (!scope || scope.parent !== parent || scope.object !== object || scope.isWith !== isWith) {
michael@0 34904 scope = this.scopes[i] = new Scope(parent, object, isWith);
michael@0 34905 }
michael@0 34906 parent = scope;
michael@0 34907 }
michael@0 34908 return parent;
michael@0 34909 };
michael@0 34910 return ScopeStack;
michael@0 34911 }();
michael@0 34912 function popNameInto(stack, mn, out) {
michael@0 34913 out.flags = mn.flags;
michael@0 34914 if (mn.isRuntimeName()) {
michael@0 34915 out.name = stack.pop();
michael@0 34916 } else {
michael@0 34917 out.name = mn.name;
michael@0 34918 }
michael@0 34919 if (mn.isRuntimeNamespace()) {
michael@0 34920 out.namespaces = [
michael@0 34921 stack.pop()
michael@0 34922 ];
michael@0 34923 } else {
michael@0 34924 out.namespaces = mn.namespaces;
michael@0 34925 }
michael@0 34926 }
michael@0 34927 var Interpreter = function () {
michael@0 34928 function Interpreter() {
michael@0 34929 }
michael@0 34930 Interpreter.interpretMethod = function ($this, method, savedScope, methodArgs) {
michael@0 34931 true;
michael@0 34932 Counter.count('Interpret Method');
michael@0 34933 var abc = method.abc;
michael@0 34934 var ints = abc.constantPool.ints;
michael@0 34935 var uints = abc.constantPool.uints;
michael@0 34936 var doubles = abc.constantPool.doubles;
michael@0 34937 var strings = abc.constantPool.strings;
michael@0 34938 var methods = abc.methods;
michael@0 34939 var multinames = abc.constantPool.multinames;
michael@0 34940 var domain = abc.applicationDomain;
michael@0 34941 var exceptions = method.exceptions;
michael@0 34942 var locals = [
michael@0 34943 $this
michael@0 34944 ];
michael@0 34945 var stack = [], scopeStack = new ScopeStack(savedScope);
michael@0 34946 var parameterCount = method.parameters.length;
michael@0 34947 var argCount = methodArgs.length;
michael@0 34948 var value;
michael@0 34949 for (var i = 0; i < parameterCount; i++) {
michael@0 34950 var parameter = method.parameters[i];
michael@0 34951 if (i < argCount) {
michael@0 34952 value = methodArgs[i];
michael@0 34953 } else {
michael@0 34954 value = parameter.value;
michael@0 34955 }
michael@0 34956 if (parameter.type && !parameter.type.isAnyName()) {
michael@0 34957 value = asCoerceByMultiname(domain, parameter.type, value);
michael@0 34958 }
michael@0 34959 locals.push(value);
michael@0 34960 }
michael@0 34961 if (method.needsRest()) {
michael@0 34962 locals.push(sliceArguments(methodArgs, parameterCount));
michael@0 34963 } else if (method.needsArguments()) {
michael@0 34964 locals.push(sliceArguments(methodArgs, 0));
michael@0 34965 }
michael@0 34966 var bytecodes = method.analysis.bytecodes;
michael@0 34967 var object, index, multiname, result, a, b, args = [], mn = Multiname.TEMPORARY;
michael@0 34968 interpretLabel:
michael@0 34969 for (var pc = 0, end = bytecodes.length; pc < end;) {
michael@0 34970 try {
michael@0 34971 var bc = bytecodes[pc];
michael@0 34972 var op = bc.op;
michael@0 34973 switch (op | 0) {
michael@0 34974 case 3:
michael@0 34975 throw stack.pop();
michael@0 34976 case 4:
michael@0 34977 popNameInto(stack, multinames[bc.index], mn);
michael@0 34978 stack.push(stack.pop().asGetSuper(savedScope, mn.namespaces, mn.name, mn.flags));
michael@0 34979 break;
michael@0 34980 case 5:
michael@0 34981 value = stack.pop();
michael@0 34982 popNameInto(stack, multinames[bc.index], mn);
michael@0 34983 stack.pop().asSetSuper(savedScope, mn.namespaces, mn.name, mn.flags, value);
michael@0 34984 break;
michael@0 34985 case 8:
michael@0 34986 locals[bc.index] = undefined;
michael@0 34987 break;
michael@0 34988 case 12:
michael@0 34989 b = stack.pop();
michael@0 34990 a = stack.pop();
michael@0 34991 pc = !(a < b) ? bc.offset : pc + 1;
michael@0 34992 continue;
michael@0 34993 case 24:
michael@0 34994 b = stack.pop();
michael@0 34995 a = stack.pop();
michael@0 34996 pc = a >= b ? bc.offset : pc + 1;
michael@0 34997 continue;
michael@0 34998 case 13:
michael@0 34999 b = stack.pop();
michael@0 35000 a = stack.pop();
michael@0 35001 pc = !(a <= b) ? bc.offset : pc + 1;
michael@0 35002 continue;
michael@0 35003 case 23:
michael@0 35004 b = stack.pop();
michael@0 35005 a = stack.pop();
michael@0 35006 pc = a > b ? bc.offset : pc + 1;
michael@0 35007 continue;
michael@0 35008 case 14:
michael@0 35009 b = stack.pop();
michael@0 35010 a = stack.pop();
michael@0 35011 pc = !(a > b) ? bc.offset : pc + 1;
michael@0 35012 continue;
michael@0 35013 case 22:
michael@0 35014 b = stack.pop();
michael@0 35015 a = stack.pop();
michael@0 35016 pc = a <= b ? bc.offset : pc + 1;
michael@0 35017 continue;
michael@0 35018 case 15:
michael@0 35019 b = stack.pop();
michael@0 35020 a = stack.pop();
michael@0 35021 pc = !(a >= b) ? bc.offset : pc + 1;
michael@0 35022 continue;
michael@0 35023 case 21:
michael@0 35024 b = stack.pop();
michael@0 35025 a = stack.pop();
michael@0 35026 pc = a < b ? bc.offset : pc + 1;
michael@0 35027 continue;
michael@0 35028 case 16:
michael@0 35029 pc = bc.offset;
michael@0 35030 continue;
michael@0 35031 case 17:
michael@0 35032 pc = !(!stack.pop()) ? bc.offset : pc + 1;
michael@0 35033 continue;
michael@0 35034 case 18:
michael@0 35035 pc = !stack.pop() ? bc.offset : pc + 1;
michael@0 35036 continue;
michael@0 35037 case 19:
michael@0 35038 b = stack.pop();
michael@0 35039 a = stack.pop();
michael@0 35040 pc = a == b ? bc.offset : pc + 1;
michael@0 35041 continue;
michael@0 35042 case 20:
michael@0 35043 b = stack.pop();
michael@0 35044 a = stack.pop();
michael@0 35045 pc = a != b ? bc.offset : pc + 1;
michael@0 35046 continue;
michael@0 35047 case 25:
michael@0 35048 b = stack.pop();
michael@0 35049 a = stack.pop();
michael@0 35050 pc = a === b ? bc.offset : pc + 1;
michael@0 35051 continue;
michael@0 35052 case 26:
michael@0 35053 b = stack.pop();
michael@0 35054 a = stack.pop();
michael@0 35055 pc = a !== b ? bc.offset : pc + 1;
michael@0 35056 continue;
michael@0 35057 case 27:
michael@0 35058 index = stack.pop();
michael@0 35059 if (index < 0 || index >= bc.offsets.length) {
michael@0 35060 index = bc.offsets.length - 1;
michael@0 35061 }
michael@0 35062 pc = bc.offsets[index];
michael@0 35063 continue;
michael@0 35064 case 28:
michael@0 35065 scopeStack.push(boxValue(stack.pop()), true);
michael@0 35066 break;
michael@0 35067 case 29:
michael@0 35068 scopeStack.pop();
michael@0 35069 break;
michael@0 35070 case 30:
michael@0 35071 index = stack.pop();
michael@0 35072 stack[stack.length - 1] = boxValue(stack[stack.length - 1]).asNextName(index);
michael@0 35073 break;
michael@0 35074 case 35:
michael@0 35075 index = stack.pop();
michael@0 35076 stack[stack.length - 1] = boxValue(stack[stack.length - 1]).asNextValue(index);
michael@0 35077 break;
michael@0 35078 case 50:
michael@0 35079 result = asHasNext2(locals[bc.object], locals[bc.index]);
michael@0 35080 locals[bc.object] = result.object;
michael@0 35081 locals[bc.index] = result.index;
michael@0 35082 stack.push(!(!result.index));
michael@0 35083 break;
michael@0 35084 case 32:
michael@0 35085 stack.push(null);
michael@0 35086 break;
michael@0 35087 case 33:
michael@0 35088 stack.push(undefined);
michael@0 35089 break;
michael@0 35090 case 36:
michael@0 35091 case 37:
michael@0 35092 stack.push(bc.value);
michael@0 35093 break;
michael@0 35094 case 44:
michael@0 35095 stack.push(strings[bc.index]);
michael@0 35096 break;
michael@0 35097 case 45:
michael@0 35098 stack.push(ints[bc.index]);
michael@0 35099 break;
michael@0 35100 case 46:
michael@0 35101 stack.push(uints[bc.index]);
michael@0 35102 break;
michael@0 35103 case 47:
michael@0 35104 stack.push(doubles[bc.index]);
michael@0 35105 break;
michael@0 35106 case 38:
michael@0 35107 stack.push(true);
michael@0 35108 break;
michael@0 35109 case 39:
michael@0 35110 stack.push(false);
michael@0 35111 break;
michael@0 35112 case 40:
michael@0 35113 stack.push(NaN);
michael@0 35114 break;
michael@0 35115 case 41:
michael@0 35116 stack.pop();
michael@0 35117 break;
michael@0 35118 case 42:
michael@0 35119 stack.push(stack[stack.length - 1]);
michael@0 35120 break;
michael@0 35121 case 43:
michael@0 35122 object = stack[stack.length - 1];
michael@0 35123 stack[stack.length - 1] = stack[stack.length - 2];
michael@0 35124 stack[stack.length - 2] = object;
michael@0 35125 break;
michael@0 35126 case 48:
michael@0 35127 scopeStack.push(boxValue(stack.pop()), false);
michael@0 35128 break;
michael@0 35129 case 64:
michael@0 35130 stack.push(createFunction(methods[bc.index], scopeStack.topScope(), true));
michael@0 35131 break;
michael@0 35132 case 65:
michael@0 35133 popManyInto(stack, bc.argCount, args);
michael@0 35134 object = stack.pop();
michael@0 35135 stack[stack.length - 1] = stack[stack.length - 1].apply(object, args);
michael@0 35136 break;
michael@0 35137 case 66:
michael@0 35138 popManyInto(stack, bc.argCount, args);
michael@0 35139 stack[stack.length - 1] = construct(stack[stack.length - 1], args);
michael@0 35140 break;
michael@0 35141 case 71:
michael@0 35142 return;
michael@0 35143 case 72:
michael@0 35144 if (method.returnType) {
michael@0 35145 return asCoerceByMultiname(domain, method.returnType, stack.pop());
michael@0 35146 }
michael@0 35147 return stack.pop();
michael@0 35148 case 73:
michael@0 35149 popManyInto(stack, bc.argCount, args);
michael@0 35150 object = stack.pop();
michael@0 35151 savedScope.object.baseClass.instanceConstructorNoInitialize.apply(object, args);
michael@0 35152 break;
michael@0 35153 case 74:
michael@0 35154 popManyInto(stack, bc.argCount, args);
michael@0 35155 popNameInto(stack, multinames[bc.index], mn);
michael@0 35156 object = boxValue(stack[stack.length - 1]);
michael@0 35157 object = object.asConstructProperty(mn.namespaces, mn.name, mn.flags, args);
michael@0 35158 stack[stack.length - 1] = object;
michael@0 35159 break;
michael@0 35160 case 75:
michael@0 35161 Shumway.Debug.notImplemented('OP.callsuperid');
michael@0 35162 break;
michael@0 35163 case 76:
michael@0 35164 case 70:
michael@0 35165 case 79:
michael@0 35166 popManyInto(stack, bc.argCount, args);
michael@0 35167 popNameInto(stack, multinames[bc.index], mn);
michael@0 35168 result = boxValue(stack.pop()).asCallProperty(mn.namespaces, mn.name, mn.flags, op === 76, args);
michael@0 35169 if (op !== 79) {
michael@0 35170 stack.push(result);
michael@0 35171 }
michael@0 35172 break;
michael@0 35173 case 69:
michael@0 35174 case 78:
michael@0 35175 popManyInto(stack, bc.argCount, args);
michael@0 35176 popNameInto(stack, multinames[bc.index], mn);
michael@0 35177 result = stack.pop().asCallSuper(savedScope, mn.namespaces, mn.name, mn.flags, args);
michael@0 35178 if (op !== 78) {
michael@0 35179 stack.push(result);
michael@0 35180 }
michael@0 35181 break;
michael@0 35182 case 83:
michael@0 35183 popManyInto(stack, bc.argCount, args);
michael@0 35184 stack[stack.length - 1] = applyType(domain, stack[stack.length - 1], args);
michael@0 35185 break;
michael@0 35186 case 85:
michael@0 35187 object = {};
michael@0 35188 for (var i = 0; i < bc.argCount; i++) {
michael@0 35189 value = stack.pop();
michael@0 35190 object[Multiname.getPublicQualifiedName(stack.pop())] = value;
michael@0 35191 }
michael@0 35192 stack.push(object);
michael@0 35193 break;
michael@0 35194 case 86:
michael@0 35195 object = [];
michael@0 35196 popManyInto(stack, bc.argCount, args);
michael@0 35197 object.push.apply(object, args);
michael@0 35198 stack.push(object);
michael@0 35199 break;
michael@0 35200 case 87:
michael@0 35201 true;
michael@0 35202 stack.push(asCreateActivation(method));
michael@0 35203 break;
michael@0 35204 case 88:
michael@0 35205 stack[stack.length - 1] = createClass(abc.classes[bc.index], stack[stack.length - 1], scopeStack.topScope());
michael@0 35206 break;
michael@0 35207 case 89:
michael@0 35208 popNameInto(stack, multinames[bc.index], mn);
michael@0 35209 stack.push(getDescendants(stack.pop(), mn));
michael@0 35210 break;
michael@0 35211 case 90:
michael@0 35212 true;
michael@0 35213 stack.push(exceptions[bc.index].scopeObject);
michael@0 35214 break;
michael@0 35215 case 94:
michael@0 35216 case 93:
michael@0 35217 popNameInto(stack, multinames[bc.index], mn);
michael@0 35218 stack.push(scopeStack.topScope().findScopeProperty(mn.namespaces, mn.name, mn.flags, domain, op === 93, false));
michael@0 35219 break;
michael@0 35220 case 96:
michael@0 35221 multiname = multinames[bc.index];
michael@0 35222 object = scopeStack.topScope().findScopeProperty(multiname.namespaces, multiname.name, multiname.flags, domain, true, false);
michael@0 35223 stack.push(object.asGetProperty(multiname.namespaces, multiname.name, multiname.flags));
michael@0 35224 break;
michael@0 35225 case 104:
michael@0 35226 case 97:
michael@0 35227 value = stack.pop();
michael@0 35228 popNameInto(stack, multinames[bc.index], mn);
michael@0 35229 boxValue(stack.pop()).asSetProperty(mn.namespaces, mn.name, mn.flags, value);
michael@0 35230 break;
michael@0 35231 case 98:
michael@0 35232 stack.push(locals[bc.index]);
michael@0 35233 break;
michael@0 35234 case 99:
michael@0 35235 locals[bc.index] = stack.pop();
michael@0 35236 break;
michael@0 35237 case 100:
michael@0 35238 stack.push(savedScope.global.object);
michael@0 35239 break;
michael@0 35240 case 101:
michael@0 35241 stack.push(scopeStack.get(bc.index));
michael@0 35242 break;
michael@0 35243 case 102:
michael@0 35244 popNameInto(stack, multinames[bc.index], mn);
michael@0 35245 stack[stack.length - 1] = boxValue(stack[stack.length - 1]).asGetProperty(mn.namespaces, mn.name, mn.flags);
michael@0 35246 break;
michael@0 35247 case 106:
michael@0 35248 popNameInto(stack, multinames[bc.index], mn);
michael@0 35249 stack[stack.length - 1] = boxValue(stack[stack.length - 1]).asDeleteProperty(mn.namespaces, mn.name, mn.flags);
michael@0 35250 break;
michael@0 35251 case 108:
michael@0 35252 stack[stack.length - 1] = asGetSlot(stack[stack.length - 1], bc.index);
michael@0 35253 break;
michael@0 35254 case 109:
michael@0 35255 value = stack.pop();
michael@0 35256 object = stack.pop();
michael@0 35257 asSetSlot(object, bc.index, value);
michael@0 35258 break;
michael@0 35259 case 112:
michael@0 35260 stack[stack.length - 1] = stack[stack.length - 1] + '';
michael@0 35261 break;
michael@0 35262 case 131:
michael@0 35263 case 115:
michael@0 35264 stack[stack.length - 1] |= 0;
michael@0 35265 break;
michael@0 35266 case 136:
michael@0 35267 case 116:
michael@0 35268 stack[stack.length - 1] >>>= 0;
michael@0 35269 break;
michael@0 35270 case 132:
michael@0 35271 case 117:
michael@0 35272 stack[stack.length - 1] = +stack[stack.length - 1];
michael@0 35273 break;
michael@0 35274 case 129:
michael@0 35275 case 118:
michael@0 35276 stack[stack.length - 1] = !(!stack[stack.length - 1]);
michael@0 35277 break;
michael@0 35278 case 120:
michael@0 35279 stack[stack.length - 1] = checkFilter(stack[stack.length - 1]);
michael@0 35280 break;
michael@0 35281 case 128:
michael@0 35282 stack[stack.length - 1] = asCoerce(domain.getType(multinames[bc.index]), stack[stack.length - 1]);
michael@0 35283 break;
michael@0 35284 case 130:
michael@0 35285 break;
michael@0 35286 case 133:
michael@0 35287 stack[stack.length - 1] = asCoerceString(stack[stack.length - 1]);
michael@0 35288 break;
michael@0 35289 case 135:
michael@0 35290 stack[stack.length - 2] = asAsType(stack.pop(), stack[stack.length - 1]);
michael@0 35291 break;
michael@0 35292 case 137:
michael@0 35293 object = stack[stack.length - 1];
michael@0 35294 stack[stack.length - 1] = object == undefined ? null : object;
michael@0 35295 break;
michael@0 35296 case 144:
michael@0 35297 stack[stack.length - 1] = -stack[stack.length - 1];
michael@0 35298 break;
michael@0 35299 case 145:
michael@0 35300 ++stack[stack.length - 1];
michael@0 35301 break;
michael@0 35302 case 146:
michael@0 35303 ++locals[bc.index];
michael@0 35304 break;
michael@0 35305 case 147:
michael@0 35306 --stack[stack.length - 1];
michael@0 35307 break;
michael@0 35308 case 148:
michael@0 35309 --locals[bc.index];
michael@0 35310 break;
michael@0 35311 case 149:
michael@0 35312 stack[stack.length - 1] = asTypeOf(stack[stack.length - 1]);
michael@0 35313 break;
michael@0 35314 case 150:
michael@0 35315 stack[stack.length - 1] = !stack[stack.length - 1];
michael@0 35316 break;
michael@0 35317 case 151:
michael@0 35318 stack[stack.length - 1] = ~stack[stack.length - 1];
michael@0 35319 break;
michael@0 35320 case 160:
michael@0 35321 stack[stack.length - 2] = asAdd(stack[stack.length - 2], stack.pop());
michael@0 35322 break;
michael@0 35323 case 161:
michael@0 35324 stack[stack.length - 2] -= stack.pop();
michael@0 35325 break;
michael@0 35326 case 162:
michael@0 35327 stack[stack.length - 2] *= stack.pop();
michael@0 35328 break;
michael@0 35329 case 163:
michael@0 35330 stack[stack.length - 2] /= stack.pop();
michael@0 35331 break;
michael@0 35332 case 164:
michael@0 35333 stack[stack.length - 2] %= stack.pop();
michael@0 35334 break;
michael@0 35335 case 165:
michael@0 35336 stack[stack.length - 2] <<= stack.pop();
michael@0 35337 break;
michael@0 35338 case 166:
michael@0 35339 stack[stack.length - 2] >>= stack.pop();
michael@0 35340 break;
michael@0 35341 case 167:
michael@0 35342 stack[stack.length - 2] >>>= stack.pop();
michael@0 35343 break;
michael@0 35344 case 168:
michael@0 35345 stack[stack.length - 2] &= stack.pop();
michael@0 35346 break;
michael@0 35347 case 169:
michael@0 35348 stack[stack.length - 2] |= stack.pop();
michael@0 35349 break;
michael@0 35350 case 170:
michael@0 35351 stack[stack.length - 2] ^= stack.pop();
michael@0 35352 break;
michael@0 35353 case 171:
michael@0 35354 stack[stack.length - 2] = stack[stack.length - 2] == stack.pop();
michael@0 35355 break;
michael@0 35356 case 172:
michael@0 35357 stack[stack.length - 2] = stack[stack.length - 2] === stack.pop();
michael@0 35358 break;
michael@0 35359 case 173:
michael@0 35360 stack[stack.length - 2] = stack[stack.length - 2] < stack.pop();
michael@0 35361 break;
michael@0 35362 case 174:
michael@0 35363 stack[stack.length - 2] = stack[stack.length - 2] <= stack.pop();
michael@0 35364 break;
michael@0 35365 case 175:
michael@0 35366 stack[stack.length - 2] = stack[stack.length - 2] > stack.pop();
michael@0 35367 break;
michael@0 35368 case 176:
michael@0 35369 stack[stack.length - 2] = stack[stack.length - 2] >= stack.pop();
michael@0 35370 break;
michael@0 35371 case 177:
michael@0 35372 stack[stack.length - 2] = asIsInstanceOf(stack.pop(), stack[stack.length - 1]);
michael@0 35373 break;
michael@0 35374 case 178:
michael@0 35375 stack[stack.length - 1] = asIsType(domain.getType(multinames[bc.index]), stack[stack.length - 1]);
michael@0 35376 break;
michael@0 35377 case 179:
michael@0 35378 stack[stack.length - 2] = asIsType(stack.pop(), stack[stack.length - 1]);
michael@0 35379 break;
michael@0 35380 case 180:
michael@0 35381 stack[stack.length - 2] = boxValue(stack.pop()).asHasProperty(null, stack[stack.length - 1]);
michael@0 35382 break;
michael@0 35383 case 192:
michael@0 35384 stack[stack.length - 1] = (stack[stack.length - 1] | 0) + 1;
michael@0 35385 break;
michael@0 35386 case 193:
michael@0 35387 stack[stack.length - 1] = (stack[stack.length - 1] | 0) - 1;
michael@0 35388 break;
michael@0 35389 case 194:
michael@0 35390 locals[bc.index] = (locals[bc.index] | 0) + 1;
michael@0 35391 break;
michael@0 35392 case 195:
michael@0 35393 locals[bc.index] = (locals[bc.index] | 0) - 1;
michael@0 35394 break;
michael@0 35395 case 196:
michael@0 35396 stack[stack.length - 1] = ~stack[stack.length - 1];
michael@0 35397 break;
michael@0 35398 case 197:
michael@0 35399 stack[stack.length - 2] = stack[stack.length - 2] + stack.pop() | 0;
michael@0 35400 break;
michael@0 35401 case 198:
michael@0 35402 stack[stack.length - 2] = stack[stack.length - 2] - stack.pop() | 0;
michael@0 35403 break;
michael@0 35404 case 199:
michael@0 35405 stack[stack.length - 2] = stack[stack.length - 2] * stack.pop() | 0;
michael@0 35406 break;
michael@0 35407 case 208:
michael@0 35408 case 209:
michael@0 35409 case 210:
michael@0 35410 case 211:
michael@0 35411 stack.push(locals[op - 208]);
michael@0 35412 break;
michael@0 35413 case 212:
michael@0 35414 case 213:
michael@0 35415 case 214:
michael@0 35416 case 215:
michael@0 35417 locals[op - 212] = stack.pop();
michael@0 35418 break;
michael@0 35419 case 239:
michael@0 35420 case 240:
michael@0 35421 case 241:
michael@0 35422 break;
michael@0 35423 default:
michael@0 35424 Shumway.Debug.notImplemented(Shumway.AVM2.opcodeName(op));
michael@0 35425 }
michael@0 35426 pc++;
michael@0 35427 } catch (e) {
michael@0 35428 if (exceptions.length < 1) {
michael@0 35429 throw e;
michael@0 35430 }
michael@0 35431 e = translateError(domain, e);
michael@0 35432 for (var i = 0, j = exceptions.length; i < j; i++) {
michael@0 35433 var handler = exceptions[i];
michael@0 35434 if (pc >= handler.start && pc <= handler.end && (!handler.typeName || domain.getType(handler.typeName).isInstance(e))) {
michael@0 35435 stack.length = 0;
michael@0 35436 stack.push(e);
michael@0 35437 scopeStack.clear();
michael@0 35438 pc = handler.offset;
michael@0 35439 continue interpretLabel;
michael@0 35440 }
michael@0 35441 }
michael@0 35442 throw e;
michael@0 35443 }
michael@0 35444 }
michael@0 35445 };
michael@0 35446 return Interpreter;
michael@0 35447 }();
michael@0 35448 AVM2.Interpreter = Interpreter;
michael@0 35449 }(Shumway.AVM2 || (Shumway.AVM2 = {})));
michael@0 35450 var AVM2 = Shumway.AVM2;
michael@0 35451 }(Shumway || (Shumway = {})));
michael@0 35452 Shumway.AVM2.Runtime.enableVerifier.value = true;
michael@0 35453 release = true;
michael@0 35454 var avm2Root = SHUMWAY_ROOT + 'avm2/';
michael@0 35455 var builtinPath = avm2Root + 'generated/builtin/builtin.abc';
michael@0 35456 var avm1Path = avm2Root + 'generated/avm1lib/avm1lib.abc';
michael@0 35457 var BinaryFileReader = function binaryFileReader() {
michael@0 35458 function constructor(url, responseType) {
michael@0 35459 this.url = url;
michael@0 35460 this.responseType = responseType || 'arraybuffer';
michael@0 35461 }
michael@0 35462 constructor.prototype = {
michael@0 35463 readAll: function (progress, complete) {
michael@0 35464 var url = this.url;
michael@0 35465 var xhr = new XMLHttpRequest();
michael@0 35466 var async = true;
michael@0 35467 xhr.open('GET', this.url, async);
michael@0 35468 xhr.responseType = this.responseType;
michael@0 35469 if (progress) {
michael@0 35470 xhr.onprogress = function (event) {
michael@0 35471 progress(xhr.response, event.loaded, event.total);
michael@0 35472 };
michael@0 35473 }
michael@0 35474 xhr.onreadystatechange = function (event) {
michael@0 35475 if (xhr.readyState === 4) {
michael@0 35476 if (xhr.status !== 200 && xhr.status !== 0) {
michael@0 35477 unexpected('Path: ' + url + ' not found.');
michael@0 35478 complete(null, xhr.statusText);
michael@0 35479 return;
michael@0 35480 }
michael@0 35481 complete(xhr.response);
michael@0 35482 }
michael@0 35483 };
michael@0 35484 xhr.send(null);
michael@0 35485 },
michael@0 35486 readAsync: function (ondata, onerror, onopen, oncomplete, onhttpstatus) {
michael@0 35487 var xhr = new XMLHttpRequest({
michael@0 35488 mozSystem: true
michael@0 35489 });
michael@0 35490 var url = this.url;
michael@0 35491 xhr.open(this.method || 'GET', url, true);
michael@0 35492 var isNotProgressive;
michael@0 35493 try {
michael@0 35494 xhr.responseType = 'moz-chunked-arraybuffer';
michael@0 35495 isNotProgressive = xhr.responseType !== 'moz-chunked-arraybuffer';
michael@0 35496 } catch (e) {
michael@0 35497 isNotProgressive = true;
michael@0 35498 }
michael@0 35499 if (isNotProgressive) {
michael@0 35500 xhr.responseType = 'arraybuffer';
michael@0 35501 }
michael@0 35502 xhr.onprogress = function (e) {
michael@0 35503 if (isNotProgressive)
michael@0 35504 return;
michael@0 35505 ondata(new Uint8Array(xhr.response), {
michael@0 35506 loaded: e.loaded,
michael@0 35507 total: e.total
michael@0 35508 });
michael@0 35509 };
michael@0 35510 xhr.onreadystatechange = function (event) {
michael@0 35511 if (xhr.readyState === 2 && onhttpstatus) {
michael@0 35512 onhttpstatus(url, xhr.status, xhr.getAllResponseHeaders());
michael@0 35513 }
michael@0 35514 if (xhr.readyState === 4) {
michael@0 35515 if (xhr.status !== 200 && xhr.status !== 0) {
michael@0 35516 onerror(xhr.statusText);
michael@0 35517 }
michael@0 35518 if (isNotProgressive) {
michael@0 35519 var buffer = xhr.response;
michael@0 35520 ondata(new Uint8Array(buffer), {
michael@0 35521 loaded: buffer.byteLength,
michael@0 35522 total: buffer.byteLength
michael@0 35523 });
michael@0 35524 }
michael@0 35525 if (oncomplete) {
michael@0 35526 oncomplete();
michael@0 35527 }
michael@0 35528 } else if (xhr.readyState === 2 && onopen) {
michael@0 35529 onopen();
michael@0 35530 }
michael@0 35531 };
michael@0 35532 xhr.send(null);
michael@0 35533 }
michael@0 35534 };
michael@0 35535 return constructor;
michael@0 35536 }();
michael@0 35537 var libraryAbcs;
michael@0 35538 function grabAbc(abcName) {
michael@0 35539 var entry = libraryScripts[abcName];
michael@0 35540 if (entry) {
michael@0 35541 var offset = entry.offset;
michael@0 35542 var length = entry.length;
michael@0 35543 return new AbcFile(new Uint8Array(libraryAbcs, offset, length), abcName);
michael@0 35544 }
michael@0 35545 return null;
michael@0 35546 }
michael@0 35547 var avm2;
michael@0 35548 function createAVM2(builtinPath, libraryPath, avm1Path, sysMode, appMode, next) {
michael@0 35549 avm2 = new AVM2(sysMode, appMode, loadAVM1);
michael@0 35550 var builtinAbc, avm1Abc;
michael@0 35551 AVM2.loadPlayerglobal(libraryPath.abcs, libraryPath.catalog).then(function () {
michael@0 35552 new BinaryFileReader(builtinPath).readAll(null, function (buffer) {
michael@0 35553 builtinAbc = new AbcFile(new Uint8Array(buffer), 'builtin.abc');
michael@0 35554 executeAbc();
michael@0 35555 });
michael@0 35556 });
michael@0 35557 function loadAVM1(next) {
michael@0 35558 new BinaryFileReader(avm1Path).readAll(null, function (buffer) {
michael@0 35559 avm1Abc = new AbcFile(new Uint8Array(buffer), 'avm1.abc');
michael@0 35560 ;
michael@0 35561 avm2.systemDomain.executeAbc(avm1Abc);
michael@0 35562 next();
michael@0 35563 });
michael@0 35564 }
michael@0 35565 function executeAbc() {
michael@0 35566 avm2.builtinsLoaded = false;
michael@0 35567 avm2.systemDomain.onMessage.register('classCreated', Stubs.onClassCreated);
michael@0 35568 avm2.systemDomain.executeAbc(builtinAbc);
michael@0 35569 avm2.builtinsLoaded = true;
michael@0 35570 console.info(JSON.stringify(Counter.toJSON()));
michael@0 35571 console.timeEnd('Load AVM2');
michael@0 35572 next(avm2);
michael@0 35573 }
michael@0 35574 }
michael@0 35575 {
michael@0 35576 var MAX_SNAP_DRAW_SCALE_TO_CACHE = 8;
michael@0 35577 var CACHE_SNAP_DRAW_AFTER = 3;
michael@0 35578 var BitmapDefinition = function () {
michael@0 35579 function setBitmapData(value) {
michael@0 35580 if (this._bitmapData) {
michael@0 35581 this._bitmapData._changeNotificationTarget = null;
michael@0 35582 }
michael@0 35583 this._bitmapData = value;
michael@0 35584 if (this._bitmapData) {
michael@0 35585 this._bitmapData._changeNotificationTarget = this;
michael@0 35586 }
michael@0 35587 if (value) {
michael@0 35588 var canvas = value._drawable;
michael@0 35589 this._bbox = {
michael@0 35590 xMin: 0,
michael@0 35591 yMin: 0,
michael@0 35592 xMax: canvas.width * 20,
michael@0 35593 yMax: canvas.height * 20
michael@0 35594 };
michael@0 35595 } else {
michael@0 35596 this._bbox = {
michael@0 35597 xMin: 0,
michael@0 35598 yMin: 0,
michael@0 35599 xMax: 0,
michael@0 35600 yMax: 0
michael@0 35601 };
michael@0 35602 }
michael@0 35603 this._drawableChanged();
michael@0 35604 this._invalidateBounds();
michael@0 35605 this._invalidateTransform();
michael@0 35606 }
michael@0 35607 return {
michael@0 35608 __class__: 'flash.display.Bitmap',
michael@0 35609 draw: function (ctx, ratio, colorTransform) {
michael@0 35610 if (!this._bitmapData) {
michael@0 35611 return;
michael@0 35612 }
michael@0 35613 var scaledImage;
michael@0 35614 ctx.save();
michael@0 35615 if (this._pixelSnapping === 'auto' || this._pixelSnapping === 'always') {
michael@0 35616 var transform = this._getConcatenatedTransform(null, true);
michael@0 35617 var EPSILON = 0.001;
michael@0 35618 var aInt = Math.abs(Math.round(transform.a));
michael@0 35619 var dInt = Math.abs(Math.round(transform.d));
michael@0 35620 var snapPixels;
michael@0 35621 if (aInt >= 1 && aInt <= MAX_SNAP_DRAW_SCALE_TO_CACHE && dInt >= 1 && dInt <= MAX_SNAP_DRAW_SCALE_TO_CACHE && Math.abs(Math.abs(transform.a) / aInt - 1) <= EPSILON && Math.abs(Math.abs(transform.d) / dInt - 1) <= EPSILON && Math.abs(transform.b) <= EPSILON && Math.abs(transform.c) <= EPSILON) {
michael@0 35622 if (aInt === 1 && dInt === 1) {
michael@0 35623 snapPixels = true;
michael@0 35624 } else {
michael@0 35625 var sizeKey = aInt + 'x' + dInt;
michael@0 35626 if (this._snapImageCache.size !== sizeKey) {
michael@0 35627 this._snapImageCache.size = sizeKey;
michael@0 35628 this._snapImageCache.hits = 0;
michael@0 35629 this._snapImageCache.image = null;
michael@0 35630 }
michael@0 35631 if (++this._snapImageCache.hits === CACHE_SNAP_DRAW_AFTER) {
michael@0 35632 this._cacheSnapImage(sizeKey, aInt, dInt);
michael@0 35633 }
michael@0 35634 scaledImage = this._snapImageCache.image;
michael@0 35635 snapPixels = !(!scaledImage);
michael@0 35636 }
michael@0 35637 } else {
michael@0 35638 snapPixels = false;
michael@0 35639 }
michael@0 35640 if (snapPixels) {
michael@0 35641 ctx.setTransform(transform.a < 0 ? -1 : 1, 0, 0, transform.d < 0 ? -1 : 1, transform.tx / 20 | 0, transform.ty / 20 | 0);
michael@0 35642 }
michael@0 35643 }
michael@0 35644 colorTransform.setAlpha(ctx, true);
michael@0 35645 ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = this._smoothing;
michael@0 35646 ctx.drawImage(scaledImage || this._bitmapData._getDrawable(), 0, 0);
michael@0 35647 ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = false;
michael@0 35648 ctx.restore();
michael@0 35649 traceRenderer.value && frameWriter.writeLn('Bitmap.draw() snapping: ' + this._pixelSnapping + ', dimensions: ' + this._bitmapData._drawable.width + ' x ' + this._bitmapData._drawable.height);
michael@0 35650 },
michael@0 35651 _drawableChanged: function () {
michael@0 35652 this._invalidate();
michael@0 35653 this._snapImageCache.image = null;
michael@0 35654 this._snapImageCache.hints = 0;
michael@0 35655 },
michael@0 35656 _cacheSnapImage: function (sizeKey, xScale, yScale) {
michael@0 35657 Counter.count('Cache scaled image');
michael@0 35658 var original = this._bitmapData._getDrawable();
michael@0 35659 var canvas = document.createElement('canvas');
michael@0 35660 canvas.width = xScale * original.width;
michael@0 35661 canvas.height = yScale * original.height;
michael@0 35662 var ctx = canvas.getContext('2d');
michael@0 35663 ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = this._smoothing;
michael@0 35664 ctx.drawImage(original, 0, 0, original.width, original.height, 0, 0, canvas.width, canvas.height);
michael@0 35665 var cache = this._snapImageCache;
michael@0 35666 var image = document.createElement('img');
michael@0 35667 cache._tmp = [
michael@0 35668 canvas,
michael@0 35669 image
michael@0 35670 ];
michael@0 35671 if ('toBlob' in canvas) {
michael@0 35672 canvas.toBlob(function (blob) {
michael@0 35673 if (cache.size !== sizeKey) {
michael@0 35674 return;
michael@0 35675 }
michael@0 35676 image.onload = function () {
michael@0 35677 URL.revokeObjectURL(blob);
michael@0 35678 if (cache.size === sizeKey) {
michael@0 35679 cache.image = image;
michael@0 35680 }
michael@0 35681 };
michael@0 35682 image.src = URL.createObjectURL(blob);
michael@0 35683 });
michael@0 35684 } else {
michael@0 35685 image.onload = function () {
michael@0 35686 if (cache.size === sizeKey) {
michael@0 35687 cache.image = image;
michael@0 35688 }
michael@0 35689 };
michael@0 35690 image.src = canvas.toDataURL();
michael@0 35691 }
michael@0 35692 },
michael@0 35693 initialize: function () {
michael@0 35694 },
michael@0 35695 __glue__: {
michael@0 35696 native: {
michael@0 35697 static: {},
michael@0 35698 instance: {
michael@0 35699 ctor: function (bitmapData, pixelSnapping, smoothing) {
michael@0 35700 if (pixelSnapping === 'never' || pixelSnapping === 'always') {
michael@0 35701 this._pixelSnapping = pixelSnapping;
michael@0 35702 } else {
michael@0 35703 this._pixelSnapping = 'auto';
michael@0 35704 }
michael@0 35705 this._smoothing = !(!smoothing);
michael@0 35706 this._snapImageCache = {
michael@0 35707 hits: 0,
michael@0 35708 size: '',
michael@0 35709 image: null
michael@0 35710 };
michael@0 35711 if (!bitmapData && this.symbol) {
michael@0 35712 var symbol = this.symbol;
michael@0 35713 bitmapData = new flash.display.BitmapData(symbol.width, symbol.height, true, 0);
michael@0 35714 bitmapData._ctx.imageSmoothingEnabled = this._smoothing;
michael@0 35715 bitmapData._ctx.mozImageSmoothingEnabled = this._smoothing;
michael@0 35716 bitmapData._ctx.drawImage(symbol.img, 0, 0);
michael@0 35717 bitmapData._ctx.imageSmoothingEnabled = false;
michael@0 35718 bitmapData._ctx.mozImageSmoothingEnabled = false;
michael@0 35719 }
michael@0 35720 setBitmapData.call(this, bitmapData || null);
michael@0 35721 },
michael@0 35722 pixelSnapping: {
michael@0 35723 get: function pixelSnapping() {
michael@0 35724 return this._pixelSnapping;
michael@0 35725 },
michael@0 35726 set: function pixelSnapping(value) {
michael@0 35727 this._pixelSnapping = value;
michael@0 35728 }
michael@0 35729 },
michael@0 35730 smoothing: {
michael@0 35731 get: function smoothing() {
michael@0 35732 return this._smoothing;
michael@0 35733 },
michael@0 35734 set: function smoothing(value) {
michael@0 35735 this._smoothing = value;
michael@0 35736 }
michael@0 35737 },
michael@0 35738 bitmapData: {
michael@0 35739 get: function bitmapData() {
michael@0 35740 return this._bitmapData;
michael@0 35741 },
michael@0 35742 set: setBitmapData
michael@0 35743 }
michael@0 35744 }
michael@0 35745 }
michael@0 35746 }
michael@0 35747 };
michael@0 35748 }.call(this);
michael@0 35749 }
michael@0 35750 var CACHE_DRAWABLE_AFTER = 10;
michael@0 35751 var BitmapDataDefinition = function () {
michael@0 35752 function replaceRect(ctx, x, y, w, h, alpha) {
michael@0 35753 if (alpha < 255) {
michael@0 35754 ctx.clearRect(x, y, w, h);
michael@0 35755 }
michael@0 35756 if (alpha > 0) {
michael@0 35757 ctx.fillRect(x, y, w, h);
michael@0 35758 }
michael@0 35759 }
michael@0 35760 var def = {
michael@0 35761 __class__: 'flash.display.BitmapData',
michael@0 35762 initialize: function () {
michael@0 35763 this._changeNotificationTarget = null;
michael@0 35764 this._locked = false;
michael@0 35765 this._requested = 0;
michael@0 35766 this._cache = null;
michael@0 35767 if (this.symbol) {
michael@0 35768 this._img = this.symbol.img;
michael@0 35769 this._skipCopyToCanvas = this.symbol.skipCopyToCanvas;
michael@0 35770 }
michael@0 35771 },
michael@0 35772 _checkCanvas: function () {
michael@0 35773 if (this._drawable === null)
michael@0 35774 throw ArgumentError();
michael@0 35775 },
michael@0 35776 ctor: function (width, height, transparent, backgroundColor) {
michael@0 35777 if (this._img) {
michael@0 35778 width = this._img.naturalWidth || this._img.width;
michael@0 35779 height = this._img.naturalHeight || this._img.height;
michael@0 35780 } else if (isNaN(width + height) || width <= 0 || height <= 0) {
michael@0 35781 throwError('ArgumentError', Errors.ArgumentError);
michael@0 35782 }
michael@0 35783 this._transparent = transparent === undefined ? true : !(!transparent);
michael@0 35784 this._backgroundColor = backgroundColor === undefined ? 4294967295 : backgroundColor;
michael@0 35785 if (!this._transparent) {
michael@0 35786 this._backgroundColor |= 4278190080;
michael@0 35787 }
michael@0 35788 if (this._skipCopyToCanvas) {
michael@0 35789 this._drawable = this._img;
michael@0 35790 } else {
michael@0 35791 var canvas = document.createElement('canvas');
michael@0 35792 this._ctx = canvas.getContext('2d');
michael@0 35793 canvas.width = width | 0;
michael@0 35794 canvas.height = height | 0;
michael@0 35795 this._drawable = canvas;
michael@0 35796 if (!this._transparent || !this._img && this._backgroundColor) {
michael@0 35797 this.fillRect(new flash.geom.Rectangle(0, 0, width | 0, height | 0), this._backgroundColor);
michael@0 35798 }
michael@0 35799 if (this._img) {
michael@0 35800 this._ctx.drawImage(this._img, 0, 0);
michael@0 35801 }
michael@0 35802 }
michael@0 35803 },
michael@0 35804 dispose: function () {
michael@0 35805 this._ctx = null;
michael@0 35806 this._drawable.width = 0;
michael@0 35807 this._drawable.height = 0;
michael@0 35808 this._drawable = null;
michael@0 35809 },
michael@0 35810 draw: function (source, matrix, colorTransform, blendMode, clipRect, smoothing) {
michael@0 35811 this._checkCanvas();
michael@0 35812 var ctx = this._ctx;
michael@0 35813 ctx.save();
michael@0 35814 ctx.beginPath();
michael@0 35815 if (clipRect && clipRect.width > 0 && clipRect.height > 0) {
michael@0 35816 ctx.rect(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
michael@0 35817 ctx.clip();
michael@0 35818 }
michael@0 35819 if (matrix) {
michael@0 35820 ctx.transform(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty);
michael@0 35821 }
michael@0 35822 ctx.globalCompositeOperation = getBlendModeName(blendMode);
michael@0 35823 ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = !(!smoothing);
michael@0 35824 if (flash.display.BitmapData.class.isInstanceOf(source)) {
michael@0 35825 ctx.drawImage(source._drawable, 0, 0);
michael@0 35826 } else {
michael@0 35827 new RenderVisitor(source, ctx, null, true).startFragment(matrix);
michael@0 35828 }
michael@0 35829 ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = false;
michael@0 35830 ctx.restore();
michael@0 35831 this._invalidate();
michael@0 35832 },
michael@0 35833 fillRect: function (rect, color) {
michael@0 35834 this._checkCanvas();
michael@0 35835 if (!this._transparent) {
michael@0 35836 color |= 4278190080;
michael@0 35837 }
michael@0 35838 var ctx = this._ctx;
michael@0 35839 ctx.fillStyle = argbUintToStr(color);
michael@0 35840 replaceRect(ctx, rect.x, rect.y, rect.width, rect.height, color >>> 24 & 255);
michael@0 35841 this._invalidate();
michael@0 35842 },
michael@0 35843 getPixel: function (x, y) {
michael@0 35844 this._checkCanvas();
michael@0 35845 var data = this._ctx.getImageData(x, y, 1, 1).data;
michael@0 35846 return dataToRGB(data);
michael@0 35847 },
michael@0 35848 getPixel32: function (x, y) {
michael@0 35849 this._checkCanvas();
michael@0 35850 var data = this._ctx.getImageData(x, y, 1, 1).data;
michael@0 35851 return dataToARGB(data);
michael@0 35852 },
michael@0 35853 _invalidate: function (changeRect) {
michael@0 35854 if (changeRect) {
michael@0 35855 somewhatImplemented('BitmapData._invalidate(changeRect)');
michael@0 35856 }
michael@0 35857 if (this._locked) {
michael@0 35858 return;
michael@0 35859 }
michael@0 35860 if (this._changeNotificationTarget) {
michael@0 35861 this._changeNotificationTarget._drawableChanged();
michael@0 35862 }
michael@0 35863 this._requested = 0;
michael@0 35864 this._cache = null;
michael@0 35865 },
michael@0 35866 _getDrawable: function () {
michael@0 35867 if (this._img === this._drawable) {
michael@0 35868 return this._drawable;
michael@0 35869 }
michael@0 35870 this._requested++;
michael@0 35871 if (this._requested >= CACHE_DRAWABLE_AFTER) {
michael@0 35872 if (!this._cache) {
michael@0 35873 Counter.count('Cache drawable');
michael@0 35874 var img = document.createElement('img');
michael@0 35875 if ('toBlob' in this._drawable) {
michael@0 35876 this._drawable.toBlob(function (blob) {
michael@0 35877 img.src = URL.createObjectURL(blob);
michael@0 35878 img.onload = function () {
michael@0 35879 URL.revokeObjectURL(blob);
michael@0 35880 };
michael@0 35881 });
michael@0 35882 } else {
michael@0 35883 img.src = this._drawable.toDataURL();
michael@0 35884 }
michael@0 35885 this._cache = img;
michael@0 35886 }
michael@0 35887 if (this._cache.width > 0) {
michael@0 35888 return this._cache;
michael@0 35889 }
michael@0 35890 }
michael@0 35891 return this._drawable;
michael@0 35892 },
michael@0 35893 setPixel: function (x, y, color) {
michael@0 35894 this.fillRect({
michael@0 35895 x: x,
michael@0 35896 y: y,
michael@0 35897 width: 1,
michael@0 35898 height: 1
michael@0 35899 }, color | 4278190080);
michael@0 35900 this._invalidate();
michael@0 35901 },
michael@0 35902 setPixel32: function (x, y, color) {
michael@0 35903 this.fillRect({
michael@0 35904 x: x,
michael@0 35905 y: y,
michael@0 35906 width: 1,
michael@0 35907 height: 1
michael@0 35908 }, color);
michael@0 35909 this._invalidate();
michael@0 35910 },
michael@0 35911 copyPixels: function copyPixels(sourceBitmapData, sourceRect, destPoint, alphaBitmapData, alphaPoint, mergeAlpha) {
michael@0 35912 if (alphaBitmapData) {
michael@0 35913 notImplemented('BitmapData.copyPixels w/ alpha');
michael@0 35914 }
michael@0 35915 var w = sourceRect.width;
michael@0 35916 var h = sourceRect.height;
michael@0 35917 var sx = sourceRect.x;
michael@0 35918 var sy = sourceRect.y;
michael@0 35919 var dx = destPoint.x;
michael@0 35920 var dy = destPoint.y;
michael@0 35921 var offsetx = -Math.min(0, sx, dx);
michael@0 35922 var offsety = -Math.min(0, sy, dy);
michael@0 35923 var correctionw = Math.min(0, this._ctx.canvas.width - dx - w, sourceBitmapData._drawable.width - sx - w) - offsetx;
michael@0 35924 var correctionh = Math.min(0, this._ctx.canvas.height - dy - h, sourceBitmapData._drawable.height - sy - h) - offsety;
michael@0 35925 if (!mergeAlpha) {
michael@0 35926 this._ctx.clearRect(dx, dy, w, h);
michael@0 35927 }
michael@0 35928 if (w + correctionw > 0 && h + correctionh > 0) {
michael@0 35929 this._ctx.drawImage(sourceBitmapData._drawable, sx + offsetx, sy + offsety, w + correctionw, h + correctionh, dx + offsetx, dy + offsety, w + correctionw, h + correctionh);
michael@0 35930 }
michael@0 35931 this._invalidate();
michael@0 35932 },
michael@0 35933 lock: function lock() {
michael@0 35934 this._locked = true;
michael@0 35935 },
michael@0 35936 unlock: function unlock(changeRect) {
michael@0 35937 this._locked = false;
michael@0 35938 this._invalidate(changeRect);
michael@0 35939 },
michael@0 35940 clone: function () {
michael@0 35941 this._checkCanvas();
michael@0 35942 var bd = new flash.display.BitmapData(this._drawable.width, this._drawable.height, true, 0);
michael@0 35943 bd._ctx.drawImage(this._drawable, 0, 0);
michael@0 35944 return bd;
michael@0 35945 },
michael@0 35946 scroll: function (x, y) {
michael@0 35947 this._checkCanvas();
michael@0 35948 this._ctx.draw(this._drawable, x, y);
michael@0 35949 this._ctx.save();
michael@0 35950 var color = this._img ? 0 : this._backgroundColor;
michael@0 35951 if (!this._transparent) {
michael@0 35952 color |= 4278190080;
michael@0 35953 }
michael@0 35954 var alpha = color >>> 24 & 255;
michael@0 35955 this._ctx.fillStyle = argbUintToStr(color);
michael@0 35956 var w = this._drawable.width;
michael@0 35957 var h = this._drawable.height;
michael@0 35958 if (x > 0) {
michael@0 35959 replaceRect(this._ctx, 0, 0, x, h, alpha);
michael@0 35960 } else if (x < 0) {
michael@0 35961 replaceRect(this._ctx, w + x, 0, -x, h, alpha);
michael@0 35962 }
michael@0 35963 if (y > 0) {
michael@0 35964 replaceRect(this._ctx, 0, 0, w, y, alpha);
michael@0 35965 } else if (y < 0) {
michael@0 35966 replaceRect(this._ctx, h + y, w, -y, alpha);
michael@0 35967 }
michael@0 35968 this._ctx.restore();
michael@0 35969 this._invalidate();
michael@0 35970 },
michael@0 35971 get width() {
michael@0 35972 return this._drawable.width;
michael@0 35973 },
michael@0 35974 get height() {
michael@0 35975 return this._drawable.height;
michael@0 35976 }
michael@0 35977 };
michael@0 35978 var desc = Object.getOwnPropertyDescriptor;
michael@0 35979 def.__glue__ = {
michael@0 35980 native: {
michael@0 35981 instance: {
michael@0 35982 ctor: def.ctor,
michael@0 35983 fillRect: def.fillRect,
michael@0 35984 dispose: def.dispose,
michael@0 35985 getPixel: def.getPixel,
michael@0 35986 getPixel32: def.getPixel32,
michael@0 35987 setPixel: def.setPixel,
michael@0 35988 setPixel32: def.setPixel32,
michael@0 35989 copyPixels: def.copyPixels,
michael@0 35990 lock: def.lock,
michael@0 35991 unlock: def.unlock,
michael@0 35992 draw: def.draw,
michael@0 35993 clone: def.clone,
michael@0 35994 scroll: def.scroll,
michael@0 35995 width: desc(def, 'width'),
michael@0 35996 height: desc(def, 'height')
michael@0 35997 }
michael@0 35998 }
michael@0 35999 };
michael@0 36000 return def;
michael@0 36001 }.call(this);
michael@0 36002 function dataToRGB(data) {
michael@0 36003 return data[0] << 16 | data[1] << 8 | data[2];
michael@0 36004 }
michael@0 36005 function dataToARGB(data) {
michael@0 36006 return data[3] << 24 | dataToRGB(data);
michael@0 36007 }
michael@0 36008 var DisplayObjectDefinition = function () {
michael@0 36009 var blendModes;
michael@0 36010 var nextInstanceId = 1;
michael@0 36011 function generateName() {
michael@0 36012 return 'instance' + nextInstanceId++;
michael@0 36013 }
michael@0 36014 var broadcastedEvents = {
michael@0 36015 advanceFrame: false,
michael@0 36016 enterFrame: true,
michael@0 36017 constructChildren: false,
michael@0 36018 frameConstructed: true,
michael@0 36019 executeFrame: false,
michael@0 36020 exitFrame: true,
michael@0 36021 render: true
michael@0 36022 };
michael@0 36023 var point = {
michael@0 36024 x: 0,
michael@0 36025 y: 0
michael@0 36026 };
michael@0 36027 var def = {
michael@0 36028 __class__: 'flash.display.DisplayObject',
michael@0 36029 initialize: function () {
michael@0 36030 var blendModeClass = flash.display.BlendMode.class;
michael@0 36031 this._alpha = 1;
michael@0 36032 this._animated = false;
michael@0 36033 this._bbox = null;
michael@0 36034 this._bitmap = null;
michael@0 36035 this._blendMode = blendModeClass.NORMAL;
michael@0 36036 this._bounds = {
michael@0 36037 xMin: 0,
michael@0 36038 xMax: 0,
michael@0 36039 yMin: 0,
michael@0 36040 yMax: 0,
michael@0 36041 invalid: true
michael@0 36042 };
michael@0 36043 this._cacheAsBitmap = false;
michael@0 36044 this._children = [];
michael@0 36045 this._clipDepth = null;
michael@0 36046 this._currentTransform = {
michael@0 36047 a: 1,
michael@0 36048 b: 0,
michael@0 36049 c: 0,
michael@0 36050 d: 1,
michael@0 36051 tx: 0,
michael@0 36052 ty: 0
michael@0 36053 };
michael@0 36054 this._concatenatedTransform = {
michael@0 36055 a: 1,
michael@0 36056 b: 0,
michael@0 36057 c: 0,
michael@0 36058 d: 1,
michael@0 36059 tx: 0,
michael@0 36060 ty: 0,
michael@0 36061 invalid: true
michael@0 36062 };
michael@0 36063 this._current3DTransform = null;
michael@0 36064 this._cxform = null;
michael@0 36065 this._graphics = null;
michael@0 36066 this._filters = [];
michael@0 36067 this._loader = null;
michael@0 36068 this._mouseChildren = true;
michael@0 36069 this._mouseOver = false;
michael@0 36070 this._mouseX = 0;
michael@0 36071 this._mouseY = 0;
michael@0 36072 this._name = null;
michael@0 36073 this._opaqueBackground = null;
michael@0 36074 this._owned = false;
michael@0 36075 this._parent = null;
michael@0 36076 this._rotation = 0;
michael@0 36077 this._rotationCos = 1;
michael@0 36078 this._rotationSin = 0;
michael@0 36079 this._scale9Grid = null;
michael@0 36080 this._scaleX = 1;
michael@0 36081 this._scaleY = 1;
michael@0 36082 this._stage = null;
michael@0 36083 this._visible = true;
michael@0 36084 this._hidden = false;
michael@0 36085 this._wasCachedAsBitmap = false;
michael@0 36086 this._destroyed = false;
michael@0 36087 this._maskedObject = null;
michael@0 36088 this._scrollRect = null;
michael@0 36089 this._invalid = false;
michael@0 36090 this._region = null;
michael@0 36091 this._level = -1;
michael@0 36092 this._index = -1;
michael@0 36093 this._depth = -1;
michael@0 36094 this._isContainer = false;
michael@0 36095 this._invisible = false;
michael@0 36096 this._zindex = 0;
michael@0 36097 blendModes = [
michael@0 36098 blendModeClass.NORMAL,
michael@0 36099 blendModeClass.NORMAL,
michael@0 36100 blendModeClass.LAYER,
michael@0 36101 blendModeClass.MULTIPLY,
michael@0 36102 blendModeClass.SCREEN,
michael@0 36103 blendModeClass.LIGHTEN,
michael@0 36104 blendModeClass.DARKEN,
michael@0 36105 blendModeClass.DIFFERENCE,
michael@0 36106 blendModeClass.ADD,
michael@0 36107 blendModeClass.SUBTRACT,
michael@0 36108 blendModeClass.INVERT,
michael@0 36109 blendModeClass.ALPHA,
michael@0 36110 blendModeClass.ERASE,
michael@0 36111 blendModeClass.OVERLAY,
michael@0 36112 blendModeClass.HARDLIGHT,
michael@0 36113 blendModeClass.SHADER
michael@0 36114 ];
michael@0 36115 var s = this.symbol;
michael@0 36116 if (s) {
michael@0 36117 this._animated = s.animated || false;
michael@0 36118 this._bbox = s.bbox || null;
michael@0 36119 this._blendMode = this._resolveBlendMode(s.blendMode);
michael@0 36120 this._children = s.children || [];
michael@0 36121 this._clipDepth = s.clipDepth || null;
michael@0 36122 this._cxform = s.cxform || null;
michael@0 36123 this._loader = s.loader || null;
michael@0 36124 this._name = s.name || null;
michael@0 36125 this._owned = s.owned || false;
michael@0 36126 this._parent = s.parent || null;
michael@0 36127 this._level = isNaN(s.level) ? -1 : s.level;
michael@0 36128 this._index = isNaN(s.index) ? -1 : s.index;
michael@0 36129 this._depth = isNaN(s.depth) ? -1 : s.depth;
michael@0 36130 this._root = s.root || null;
michael@0 36131 this._stage = s.stage || null;
michael@0 36132 var scale9Grid = s.scale9Grid;
michael@0 36133 if (scale9Grid) {
michael@0 36134 this._scale9Grid = new flash.geom.Rectangle(scale9Grid.left, scale9Grid.top, scale9Grid.right - scale9Grid.left, scale9Grid.bottom - scale9Grid.top);
michael@0 36135 }
michael@0 36136 var matrix = s.currentTransform;
michael@0 36137 if (matrix) {
michael@0 36138 this._setTransformMatrix(matrix, false);
michael@0 36139 }
michael@0 36140 }
michael@0 36141 this._accessibilityProperties = null;
michael@0 36142 var self = this;
michael@0 36143 this._onBroadcastMessage = function (type) {
michael@0 36144 var listeners = self._listeners;
michael@0 36145 if (listeners[type]) {
michael@0 36146 self._dispatchEvent(type);
michael@0 36147 }
michael@0 36148 };
michael@0 36149 },
michael@0 36150 _addEventListener: function addEventListener(type, listener, useCapture, priority) {
michael@0 36151 if (broadcastedEvents[type] === false) {
michael@0 36152 avm2.systemDomain.onMessage.register(type, listener);
michael@0 36153 return;
michael@0 36154 }
michael@0 36155 if (type in broadcastedEvents && !this._listeners[type]) {
michael@0 36156 avm2.systemDomain.onMessage.register(type, this._onBroadcastMessage);
michael@0 36157 }
michael@0 36158 this._addEventListenerImpl(type, listener, useCapture, priority);
michael@0 36159 },
michael@0 36160 _removeEventListener: function addEventListener(type, listener, useCapture) {
michael@0 36161 if (broadcastedEvents[type] === false) {
michael@0 36162 avm2.systemDomain.onMessage.unregister(type, listener);
michael@0 36163 return;
michael@0 36164 }
michael@0 36165 this._removeEventListenerImpl(type, listener, useCapture);
michael@0 36166 if (type in broadcastedEvents && !this._listeners[type]) {
michael@0 36167 avm2.systemDomain.onMessage.unregister(type, this._onBroadcastMessage);
michael@0 36168 }
michael@0 36169 },
michael@0 36170 _resolveBlendMode: function (blendModeNumeric) {
michael@0 36171 return blendModes[blendModeNumeric] || flash.display.BlendMode.class.NORMAL;
michael@0 36172 },
michael@0 36173 _getConcatenatedTransform: function (targetCoordSpace, toDeviceSpace) {
michael@0 36174 var stage = this._stage;
michael@0 36175 if (this === this._stage) {
michael@0 36176 return toDeviceSpace ? this._concatenatedTransform : this._currentTransform;
michael@0 36177 }
michael@0 36178 if (targetCoordSpace === this._parent) {
michael@0 36179 return this._currentTransform;
michael@0 36180 }
michael@0 36181 var invalidNode = null;
michael@0 36182 var m, m2, targetCoordMatrix;
michael@0 36183 var currentNode = this;
michael@0 36184 while (currentNode !== stage) {
michael@0 36185 if (currentNode._concatenatedTransform.invalid) {
michael@0 36186 invalidNode = currentNode;
michael@0 36187 }
michael@0 36188 if (currentNode === targetCoordSpace) {
michael@0 36189 targetCoordMatrix = currentNode._concatenatedTransform;
michael@0 36190 }
michael@0 36191 currentNode = currentNode._parent;
michael@0 36192 }
michael@0 36193 if (invalidNode) {
michael@0 36194 if (this._parent === stage) {
michael@0 36195 m = this._concatenatedTransform;
michael@0 36196 m2 = this._currentTransform;
michael@0 36197 m.a = m2.a;
michael@0 36198 m.b = m2.b;
michael@0 36199 m.c = m2.c;
michael@0 36200 m.d = m2.d;
michael@0 36201 m.tx = m2.tx;
michael@0 36202 m.ty = m2.ty;
michael@0 36203 } else {
michael@0 36204 var stack = [];
michael@0 36205 var currentNode = this;
michael@0 36206 while (currentNode !== invalidNode) {
michael@0 36207 stack.push(currentNode);
michael@0 36208 currentNode = currentNode._parent;
michael@0 36209 }
michael@0 36210 var node = invalidNode;
michael@0 36211 do {
michael@0 36212 var parent = node._parent;
michael@0 36213 m = node._concatenatedTransform;
michael@0 36214 m2 = node._currentTransform;
michael@0 36215 if (parent) {
michael@0 36216 if (parent !== stage) {
michael@0 36217 var m3 = parent._concatenatedTransform;
michael@0 36218 m.a = m2.a * m3.a + m2.b * m3.c;
michael@0 36219 m.b = m2.a * m3.b + m2.b * m3.d;
michael@0 36220 m.c = m2.c * m3.a + m2.d * m3.c;
michael@0 36221 m.d = m2.d * m3.d + m2.c * m3.b;
michael@0 36222 m.tx = m2.tx * m3.a + m3.tx + m2.ty * m3.c;
michael@0 36223 m.ty = m2.ty * m3.d + m3.ty + m2.tx * m3.b;
michael@0 36224 }
michael@0 36225 } else {
michael@0 36226 m.a = m2.a;
michael@0 36227 m.b = m2.b;
michael@0 36228 m.c = m2.c;
michael@0 36229 m.d = m2.d;
michael@0 36230 m.tx = m2.tx;
michael@0 36231 m.ty = m2.ty;
michael@0 36232 }
michael@0 36233 m.invalid = false;
michael@0 36234 var nextNode = stack.pop();
michael@0 36235 var children = node._children;
michael@0 36236 for (var i = 0; i < children.length; i++) {
michael@0 36237 var child = children[i];
michael@0 36238 if (child !== nextNode) {
michael@0 36239 child._concatenatedTransform.invalid = true;
michael@0 36240 }
michael@0 36241 }
michael@0 36242 node = nextNode;
michael@0 36243 } while (node);
michael@0 36244 }
michael@0 36245 } else {
michael@0 36246 m = this._concatenatedTransform;
michael@0 36247 }
michael@0 36248 if (targetCoordSpace && targetCoordSpace !== this._stage) {
michael@0 36249 m2 = targetCoordMatrix || targetCoordSpace._getConcatenatedTransform(null, false);
michael@0 36250 var a = 1, b = 0, c = 0, d = 1, tx = 0, ty = 0;
michael@0 36251 if (m2.b || m2.c) {
michael@0 36252 var det = 1 / (m2.a * m2.d - m2.b * m2.c);
michael@0 36253 a = m2.d * det;
michael@0 36254 b = -m2.b * det;
michael@0 36255 c = -m2.c * det;
michael@0 36256 d = m2.a * det;
michael@0 36257 tx = -(a * m2.tx + c * m2.ty);
michael@0 36258 ty = -(b * m2.tx + d * m2.ty);
michael@0 36259 } else {
michael@0 36260 a = 1 / m2.a;
michael@0 36261 d = 1 / m2.d;
michael@0 36262 tx = m2.tx * -a;
michael@0 36263 ty = m2.ty * -d;
michael@0 36264 }
michael@0 36265 return {
michael@0 36266 a: a * m.a + c * m.b,
michael@0 36267 b: b * m.a + d * m.b,
michael@0 36268 c: a * m.c + c * m.d,
michael@0 36269 d: b * m.c + d * m.d,
michael@0 36270 tx: a * m.tx + c * m.ty + tx,
michael@0 36271 ty: b * m.tx + d * m.ty + ty
michael@0 36272 };
michael@0 36273 }
michael@0 36274 if (toDeviceSpace && stage) {
michael@0 36275 m2 = stage._concatenatedTransform;
michael@0 36276 return {
michael@0 36277 a: m.a * m2.a,
michael@0 36278 b: m.b * m2.d,
michael@0 36279 c: m.c * m2.a,
michael@0 36280 d: m.d * m2.d,
michael@0 36281 tx: m.tx * m2.a + m2.tx,
michael@0 36282 ty: m.ty * m2.d + m2.ty
michael@0 36283 };
michael@0 36284 }
michael@0 36285 return m;
michael@0 36286 },
michael@0 36287 _applyCurrentTransform: function (pt) {
michael@0 36288 var m = this._getConcatenatedTransform(null, false);
michael@0 36289 var x = pt.x;
michael@0 36290 var y = pt.y;
michael@0 36291 pt.x = m.a * x + m.c * y + m.tx | 0;
michael@0 36292 pt.y = m.d * y + m.b * x + m.ty | 0;
michael@0 36293 },
michael@0 36294 _applyConcatenatedInverseTransform: function (pt) {
michael@0 36295 var m = this._getConcatenatedTransform(null, false);
michael@0 36296 var det = 1 / (m.a * m.d - m.b * m.c);
michael@0 36297 var x = pt.x - m.tx;
michael@0 36298 var y = pt.y - m.ty;
michael@0 36299 pt.x = (m.d * x - m.c * y) * det | 0;
michael@0 36300 pt.y = (m.a * y - m.b * x) * det | 0;
michael@0 36301 },
michael@0 36302 _hitTest: function (use_xy, x, y, useShape, hitTestObject) {
michael@0 36303 if (use_xy) {
michael@0 36304 point.x = x;
michael@0 36305 point.y = y;
michael@0 36306 this._applyConcatenatedInverseTransform(point);
michael@0 36307 var b = this._getContentBounds();
michael@0 36308 if (!(point.x >= b.xMin && point.x < b.xMax && point.y >= b.yMin && point.y < b.yMax)) {
michael@0 36309 return false;
michael@0 36310 }
michael@0 36311 if (!useShape || !this._graphics) {
michael@0 36312 return true;
michael@0 36313 }
michael@0 36314 if (this._graphics) {
michael@0 36315 var subpaths = this._graphics._paths;
michael@0 36316 for (var i = 0, n = subpaths.length; i < n; i++) {
michael@0 36317 var path = subpaths[i];
michael@0 36318 if (path.isPointInPath(point.x, point.y)) {
michael@0 36319 return true;
michael@0 36320 }
michael@0 36321 if (path.strokeStyle) {
michael@0 36322 var strokePath = path._strokePath;
michael@0 36323 if (!strokePath) {
michael@0 36324 strokePath = path.strokePath(path.drawingStyles);
michael@0 36325 path._strokePath = strokePath;
michael@0 36326 }
michael@0 36327 if (strokePath.isPointInPath(point.x, point.y)) {
michael@0 36328 return true;
michael@0 36329 }
michael@0 36330 }
michael@0 36331 }
michael@0 36332 }
michael@0 36333 var children = this._children;
michael@0 36334 for (var i = 0, n = children.length; i < n; i++) {
michael@0 36335 var child = children[i];
michael@0 36336 if (child._hitTest && child._hitTest(true, x, y, true, null)) {
michael@0 36337 return true;
michael@0 36338 }
michael@0 36339 }
michael@0 36340 return false;
michael@0 36341 }
michael@0 36342 var b1 = this.getBounds(this._stage);
michael@0 36343 var b2 = hitTestObject.getBounds(hitTestObject._stage);
michael@0 36344 x = Math.max(b1.xMin, b2.xMin);
michael@0 36345 y = Math.max(b1.yMin, b2.yMin);
michael@0 36346 var width = Math.min(b1.xMax, b2.xMax) - x;
michael@0 36347 var height = Math.min(b1.yMax, b2.yMax) - y;
michael@0 36348 return width > 0 && height > 0;
michael@0 36349 },
michael@0 36350 _invalidate: function () {
michael@0 36351 this._invalid = true;
michael@0 36352 },
michael@0 36353 _invalidateBounds: function () {
michael@0 36354 var currentNode = this;
michael@0 36355 while (currentNode && !currentNode._bounds.invalid) {
michael@0 36356 currentNode._bounds.invalid = true;
michael@0 36357 currentNode = currentNode._parent;
michael@0 36358 }
michael@0 36359 },
michael@0 36360 _invalidateTransform: function () {
michael@0 36361 this._concatenatedTransform.invalid = true;
michael@0 36362 if (this._parent) {
michael@0 36363 this._parent._invalidateBounds();
michael@0 36364 }
michael@0 36365 },
michael@0 36366 _setTransformMatrix: function (matrix, convertToTwips) {
michael@0 36367 var a = matrix.a;
michael@0 36368 var b = matrix.b;
michael@0 36369 var c = matrix.c;
michael@0 36370 var d = matrix.d;
michael@0 36371 var tx, ty;
michael@0 36372 if (convertToTwips) {
michael@0 36373 tx = matrix.tx * 20 | 0;
michael@0 36374 ty = matrix.ty * 20 | 0;
michael@0 36375 } else {
michael@0 36376 tx = matrix.tx;
michael@0 36377 ty = matrix.ty;
michael@0 36378 }
michael@0 36379 var angle = a !== 0 ? Math.atan(b / a) : b > 0 ? Math.PI / 2 : -Math.PI / 2;
michael@0 36380 this._rotation = angle * 180 / Math.PI;
michael@0 36381 this._rotationCos = Math.cos(angle);
michael@0 36382 this._rotationSin = Math.sin(angle);
michael@0 36383 var sx = Math.sqrt(a * a + b * b);
michael@0 36384 this._scaleX = a > 0 ? sx : -sx;
michael@0 36385 var sy = Math.sqrt(d * d + c * c);
michael@0 36386 this._scaleY = d > 0 ? sy : -sy;
michael@0 36387 var transform = this._currentTransform;
michael@0 36388 transform.a = a;
michael@0 36389 transform.b = b;
michael@0 36390 transform.c = c;
michael@0 36391 transform.d = d;
michael@0 36392 transform.tx = tx;
michael@0 36393 transform.ty = ty;
michael@0 36394 this._invalidateTransform();
michael@0 36395 },
michael@0 36396 get accessibilityProperties() {
michael@0 36397 return this._accessibilityProperties;
michael@0 36398 },
michael@0 36399 set accessibilityProperties(val) {
michael@0 36400 this._accessibilityProperties = val;
michael@0 36401 },
michael@0 36402 get alpha() {
michael@0 36403 return this._alpha;
michael@0 36404 },
michael@0 36405 set alpha(val) {
michael@0 36406 if (val === this._alpha) {
michael@0 36407 return;
michael@0 36408 }
michael@0 36409 this._invalidate();
michael@0 36410 this._alpha = val;
michael@0 36411 this._animated = false;
michael@0 36412 },
michael@0 36413 get blendMode() {
michael@0 36414 return this._blendMode;
michael@0 36415 },
michael@0 36416 set blendMode(val) {
michael@0 36417 if (blendModes.indexOf(val) >= 0) {
michael@0 36418 this._blendMode = val;
michael@0 36419 } else {
michael@0 36420 throwError('ArgumentError', Errors.InvalidEnumError, 'blendMode');
michael@0 36421 }
michael@0 36422 this._animated = false;
michael@0 36423 },
michael@0 36424 get cacheAsBitmap() {
michael@0 36425 return this._cacheAsBitmap;
michael@0 36426 },
michael@0 36427 set cacheAsBitmap(val) {
michael@0 36428 this._cacheAsBitmap = this._filters.length ? true : val;
michael@0 36429 this._animated = false;
michael@0 36430 },
michael@0 36431 get filters() {
michael@0 36432 return this._filters;
michael@0 36433 },
michael@0 36434 set filters(val) {
michael@0 36435 if (val.length) {
michael@0 36436 if (!this._filters.length)
michael@0 36437 this._wasCachedAsBitmap = this._cacheAsBitmap;
michael@0 36438 this._cacheAsBitmap = true;
michael@0 36439 } else {
michael@0 36440 this._cacheAsBitmap = this._wasCachedAsBitmap;
michael@0 36441 }
michael@0 36442 this._filters = val;
michael@0 36443 this._animated = false;
michael@0 36444 },
michael@0 36445 get height() {
michael@0 36446 var bounds = this._getContentBounds();
michael@0 36447 var t = this._currentTransform;
michael@0 36448 return Math.abs(t.b) * (bounds.xMax - bounds.xMin) + Math.abs(t.d) * (bounds.yMax - bounds.yMin) | 0;
michael@0 36449 },
michael@0 36450 set height(val) {
michael@0 36451 if (val < 0) {
michael@0 36452 return;
michael@0 36453 }
michael@0 36454 var u = Math.abs(this._rotationCos);
michael@0 36455 var v = Math.abs(this._rotationSin);
michael@0 36456 var bounds = this._getContentBounds();
michael@0 36457 var baseHeight = v * (bounds.xMax - bounds.xMin) + u * (bounds.yMax - bounds.yMin);
michael@0 36458 if (!baseHeight) {
michael@0 36459 return;
michael@0 36460 }
michael@0 36461 var baseWidth = u * (bounds.xMax - bounds.xMin) + v * (bounds.yMax - bounds.yMin);
michael@0 36462 this.scaleX = this.width / baseWidth;
michael@0 36463 this.scaleY = val / baseHeight;
michael@0 36464 },
michael@0 36465 get loaderInfo() {
michael@0 36466 return this._loader && this._loader._contentLoaderInfo || this._parent.loaderInfo;
michael@0 36467 },
michael@0 36468 get mask() {
michael@0 36469 return this._mask;
michael@0 36470 },
michael@0 36471 set mask(val) {
michael@0 36472 if (this._mask === val) {
michael@0 36473 return;
michael@0 36474 }
michael@0 36475 this._invalidate();
michael@0 36476 if (val && val._maskedObject) {
michael@0 36477 val._maskedObject.mask = null;
michael@0 36478 }
michael@0 36479 this._mask = val;
michael@0 36480 if (val) {
michael@0 36481 val._maskedObject = this;
michael@0 36482 }
michael@0 36483 this._animated = false;
michael@0 36484 },
michael@0 36485 get name() {
michael@0 36486 return this._name || (this._name = generateName());
michael@0 36487 },
michael@0 36488 set name(val) {
michael@0 36489 this._name = val;
michael@0 36490 },
michael@0 36491 get mouseX() {
michael@0 36492 if (!this._stage) {
michael@0 36493 return 0;
michael@0 36494 }
michael@0 36495 point.x = this._stage._mouseX;
michael@0 36496 point.y = this._stage._mouseY;
michael@0 36497 this._applyConcatenatedInverseTransform(point);
michael@0 36498 return point.x;
michael@0 36499 },
michael@0 36500 get mouseY() {
michael@0 36501 if (!this._stage) {
michael@0 36502 return 0;
michael@0 36503 }
michael@0 36504 point.x = this._stage._mouseX;
michael@0 36505 point.y = this._stage._mouseY;
michael@0 36506 this._applyConcatenatedInverseTransform(point);
michael@0 36507 return point.y;
michael@0 36508 },
michael@0 36509 get opaqueBackground() {
michael@0 36510 return this._opaqueBackground;
michael@0 36511 },
michael@0 36512 set opaqueBackground(val) {
michael@0 36513 this._opaqueBackground = val;
michael@0 36514 this._animated = false;
michael@0 36515 },
michael@0 36516 get parent() {
michael@0 36517 return this._index > -1 ? this._parent : null;
michael@0 36518 },
michael@0 36519 get root() {
michael@0 36520 return this._stage && this._stage._root;
michael@0 36521 },
michael@0 36522 get rotation() {
michael@0 36523 return this._rotation;
michael@0 36524 },
michael@0 36525 set rotation(val) {
michael@0 36526 val %= 360;
michael@0 36527 if (val > 180) {
michael@0 36528 val -= 360;
michael@0 36529 }
michael@0 36530 if (val === this._rotation)
michael@0 36531 return;
michael@0 36532 this._invalidate();
michael@0 36533 this._invalidateTransform();
michael@0 36534 this._rotation = val;
michael@0 36535 var u, v;
michael@0 36536 switch (val) {
michael@0 36537 case 0:
michael@0 36538 case 360:
michael@0 36539 u = 1, v = 0;
michael@0 36540 break;
michael@0 36541 case 90:
michael@0 36542 case -270:
michael@0 36543 u = 0, v = 1;
michael@0 36544 break;
michael@0 36545 case 180:
michael@0 36546 case -180:
michael@0 36547 u = -1, v = 0;
michael@0 36548 break;
michael@0 36549 case 270:
michael@0 36550 case -90:
michael@0 36551 u = 0, v = -1;
michael@0 36552 break;
michael@0 36553 default:
michael@0 36554 var angle = this._rotation / 180 * Math.PI;
michael@0 36555 u = Math.cos(angle);
michael@0 36556 v = Math.sin(angle);
michael@0 36557 break;
michael@0 36558 }
michael@0 36559 this._rotationCos = u;
michael@0 36560 this._rotationSin = v;
michael@0 36561 var m = this._currentTransform;
michael@0 36562 m.a = u * this._scaleX;
michael@0 36563 m.b = v * this._scaleX;
michael@0 36564 m.c = -v * this._scaleY;
michael@0 36565 m.d = u * this._scaleY;
michael@0 36566 this._animated = false;
michael@0 36567 },
michael@0 36568 get rotationX() {
michael@0 36569 return 0;
michael@0 36570 },
michael@0 36571 set rotationX(val) {
michael@0 36572 somewhatImplemented('DisplayObject.rotationX');
michael@0 36573 },
michael@0 36574 get rotationY() {
michael@0 36575 return 0;
michael@0 36576 },
michael@0 36577 set rotationY(val) {
michael@0 36578 somewhatImplemented('DisplayObject.rotationY');
michael@0 36579 },
michael@0 36580 get rotationZ() {
michael@0 36581 return this.rotation;
michael@0 36582 },
michael@0 36583 set rotationZ(val) {
michael@0 36584 this.rotation = val;
michael@0 36585 somewhatImplemented('DisplayObject.rotationZ');
michael@0 36586 },
michael@0 36587 get stage() {
michael@0 36588 return this._stage;
michael@0 36589 },
michael@0 36590 get scaleX() {
michael@0 36591 return this._scaleX;
michael@0 36592 },
michael@0 36593 set scaleX(val) {
michael@0 36594 if (val === this._scaleX)
michael@0 36595 return;
michael@0 36596 this._invalidate();
michael@0 36597 this._invalidateTransform();
michael@0 36598 this._scaleX = val;
michael@0 36599 var m = this._currentTransform;
michael@0 36600 m.a = this._rotationCos * val;
michael@0 36601 m.b = this._rotationSin * val;
michael@0 36602 this._animated = false;
michael@0 36603 },
michael@0 36604 get scaleY() {
michael@0 36605 return this._scaleY;
michael@0 36606 },
michael@0 36607 set scaleY(val) {
michael@0 36608 if (val === this._scaleY)
michael@0 36609 return;
michael@0 36610 this._invalidate();
michael@0 36611 this._invalidateTransform();
michael@0 36612 this._scaleY = val;
michael@0 36613 var m = this._currentTransform;
michael@0 36614 m.c = -this._rotationSin * val;
michael@0 36615 m.d = this._rotationCos * val;
michael@0 36616 this._animated = false;
michael@0 36617 },
michael@0 36618 get scaleZ() {
michael@0 36619 return 1;
michael@0 36620 },
michael@0 36621 set scaleZ(val) {
michael@0 36622 somewhatImplemented('DisplayObject.scaleZ');
michael@0 36623 },
michael@0 36624 get scale9Grid() {
michael@0 36625 return this._scale9Grid;
michael@0 36626 },
michael@0 36627 set scale9Grid(val) {
michael@0 36628 somewhatImplemented('DisplayObject.scale9Grid');
michael@0 36629 this._scale9Grid = val;
michael@0 36630 this._animated = false;
michael@0 36631 },
michael@0 36632 get scrollRect() {
michael@0 36633 return this._scrollRect;
michael@0 36634 },
michael@0 36635 set scrollRect(val) {
michael@0 36636 somewhatImplemented('DisplayObject.scrollRect');
michael@0 36637 this._scrollRect = val;
michael@0 36638 },
michael@0 36639 get transform() {
michael@0 36640 return new flash.geom.Transform(this);
michael@0 36641 },
michael@0 36642 set transform(val) {
michael@0 36643 var transform = this.transform;
michael@0 36644 transform.colorTransform = val.colorTransform;
michael@0 36645 if (val.matrix3D) {
michael@0 36646 transform.matrix3D = val.matrix3D;
michael@0 36647 } else {
michael@0 36648 transform.matrix = val.matrix;
michael@0 36649 }
michael@0 36650 },
michael@0 36651 get visible() {
michael@0 36652 return this._visible;
michael@0 36653 },
michael@0 36654 set visible(val) {
michael@0 36655 if (val === this._visible)
michael@0 36656 return;
michael@0 36657 this._invalidate();
michael@0 36658 this._visible = val;
michael@0 36659 this._animated = false;
michael@0 36660 },
michael@0 36661 get width() {
michael@0 36662 var bounds = this._getContentBounds();
michael@0 36663 var t = this._currentTransform;
michael@0 36664 return Math.abs(t.a) * (bounds.xMax - bounds.xMin) + Math.abs(t.c) * (bounds.yMax - bounds.yMin) | 0;
michael@0 36665 },
michael@0 36666 set width(val) {
michael@0 36667 if (val < 0) {
michael@0 36668 return;
michael@0 36669 }
michael@0 36670 var u = Math.abs(this._rotationCos);
michael@0 36671 var v = Math.abs(this._rotationSin);
michael@0 36672 var bounds = this._getContentBounds();
michael@0 36673 var baseWidth = u * (bounds.xMax - bounds.xMin) + v * (bounds.yMax - bounds.yMin);
michael@0 36674 if (!baseWidth) {
michael@0 36675 return;
michael@0 36676 }
michael@0 36677 var baseHeight = v * (bounds.xMax - bounds.xMin) + u * (bounds.yMax - bounds.yMin);
michael@0 36678 this.scaleY = this.height / baseHeight;
michael@0 36679 this.scaleX = val / baseWidth;
michael@0 36680 },
michael@0 36681 get x() {
michael@0 36682 return this._currentTransform.tx;
michael@0 36683 },
michael@0 36684 set x(val) {
michael@0 36685 if (val === this._currentTransform.tx) {
michael@0 36686 return;
michael@0 36687 }
michael@0 36688 this._invalidate();
michael@0 36689 this._invalidateTransform();
michael@0 36690 this._currentTransform.tx = val;
michael@0 36691 this._animated = false;
michael@0 36692 },
michael@0 36693 get y() {
michael@0 36694 return this._currentTransform.ty;
michael@0 36695 },
michael@0 36696 set y(val) {
michael@0 36697 if (val === this._currentTransform.ty) {
michael@0 36698 return;
michael@0 36699 }
michael@0 36700 this._invalidate();
michael@0 36701 this._invalidateTransform();
michael@0 36702 this._currentTransform.ty = val;
michael@0 36703 this._animated = false;
michael@0 36704 },
michael@0 36705 get z() {
michael@0 36706 return 0;
michael@0 36707 },
michael@0 36708 set z(val) {
michael@0 36709 somewhatImplemented('DisplayObject.z');
michael@0 36710 },
michael@0 36711 _getContentBounds: function () {
michael@0 36712 var bounds = this._bounds;
michael@0 36713 if (bounds.invalid) {
michael@0 36714 var bbox = this._bbox;
michael@0 36715 var xMin = Number.MAX_VALUE;
michael@0 36716 var xMax = Number.MIN_VALUE;
michael@0 36717 var yMin = Number.MAX_VALUE;
michael@0 36718 var yMax = Number.MIN_VALUE;
michael@0 36719 if (bbox) {
michael@0 36720 xMin = bbox.xMin;
michael@0 36721 xMax = bbox.xMax;
michael@0 36722 yMin = bbox.yMin;
michael@0 36723 yMax = bbox.yMax;
michael@0 36724 } else {
michael@0 36725 var children = this._children;
michael@0 36726 var numChildren = children.length;
michael@0 36727 for (var i = 0; i < numChildren; i++) {
michael@0 36728 var child = children[i];
michael@0 36729 if (!flash.display.DisplayObject.class.isInstanceOf(child)) {
michael@0 36730 continue;
michael@0 36731 }
michael@0 36732 var b = child.getBounds(this);
michael@0 36733 var x1 = b.xMin;
michael@0 36734 var y1 = b.yMin;
michael@0 36735 var x2 = b.xMax;
michael@0 36736 var y2 = b.yMax;
michael@0 36737 xMin = Math.min(xMin, x1, x2);
michael@0 36738 xMax = Math.max(xMax, x1, x2);
michael@0 36739 yMin = Math.min(yMin, y1, y2);
michael@0 36740 yMax = Math.max(yMax, y1, y2);
michael@0 36741 }
michael@0 36742 if (this._graphics) {
michael@0 36743 var b = this._graphics._getBounds(true);
michael@0 36744 if (b.xMin !== b.xMax && b.yMin !== b.yMax) {
michael@0 36745 var x1 = b.xMin;
michael@0 36746 var y1 = b.yMin;
michael@0 36747 var x2 = b.xMax;
michael@0 36748 var y2 = b.yMax;
michael@0 36749 xMin = Math.min(xMin, x1, x2);
michael@0 36750 xMax = Math.max(xMax, x1, x2);
michael@0 36751 yMin = Math.min(yMin, y1, y2);
michael@0 36752 yMax = Math.max(yMax, y1, y2);
michael@0 36753 }
michael@0 36754 }
michael@0 36755 }
michael@0 36756 if (xMin === Number.MAX_VALUE) {
michael@0 36757 xMin = xMax = yMin = yMax = 0;
michael@0 36758 }
michael@0 36759 bounds.xMin = xMin;
michael@0 36760 bounds.xMax = xMax;
michael@0 36761 bounds.yMin = yMin;
michael@0 36762 bounds.yMax = yMax;
michael@0 36763 bounds.invalid = false;
michael@0 36764 }
michael@0 36765 return bounds;
michael@0 36766 },
michael@0 36767 _getRegion: function getRegion(targetCoordSpace) {
michael@0 36768 var b;
michael@0 36769 var filters = this._filters;
michael@0 36770 if (filters.length) {
michael@0 36771 var xMin = Number.MAX_VALUE;
michael@0 36772 var xMax = Number.MIN_VALUE;
michael@0 36773 var yMin = Number.MAX_VALUE;
michael@0 36774 var yMax = Number.MIN_VALUE;
michael@0 36775 if (this._graphics) {
michael@0 36776 b = this._graphics._getBounds(true);
michael@0 36777 if (b) {
michael@0 36778 xMin = b.xMin;
michael@0 36779 xMax = b.xMax;
michael@0 36780 yMin = b.yMin;
michael@0 36781 yMax = b.yMax;
michael@0 36782 }
michael@0 36783 }
michael@0 36784 var children = this._children;
michael@0 36785 for (var i = 0; i < children.length; i++) {
michael@0 36786 var child = children[i];
michael@0 36787 b = children[i]._getRegion(this);
michael@0 36788 if (b.xMin < xMin) {
michael@0 36789 xMin = b.xMin;
michael@0 36790 }
michael@0 36791 if (b.xMax > xMax) {
michael@0 36792 xMax = b.xMax;
michael@0 36793 }
michael@0 36794 if (b.yMin < yMin) {
michael@0 36795 yMin = b.yMin;
michael@0 36796 }
michael@0 36797 if (b.yMax > yMax) {
michael@0 36798 yMax = b.yMax;
michael@0 36799 }
michael@0 36800 }
michael@0 36801 if (xMin === Number.MAX_VALUE) {
michael@0 36802 return {
michael@0 36803 xMin: 0,
michael@0 36804 xMax: 0,
michael@0 36805 yMin: 0,
michael@0 36806 yMax: 0
michael@0 36807 };
michael@0 36808 }
michael@0 36809 b = {
michael@0 36810 xMin: xMin,
michael@0 36811 xMax: xMax,
michael@0 36812 yMin: yMin,
michael@0 36813 yMax: yMax
michael@0 36814 };
michael@0 36815 for (var i = 0; i < filters.length; i++) {
michael@0 36816 filters[i]._updateFilterBounds(b);
michael@0 36817 }
michael@0 36818 } else {
michael@0 36819 b = this._graphics ? this._graphics._getBounds(true) : this._getContentBounds();
michael@0 36820 }
michael@0 36821 return this._getTransformedRect(b, targetCoordSpace);
michael@0 36822 },
michael@0 36823 getBounds: function (targetCoordSpace) {
michael@0 36824 return this._getTransformedRect(this._getContentBounds(), targetCoordSpace);
michael@0 36825 },
michael@0 36826 _getTransformedRect: function (rect, targetCoordSpace) {
michael@0 36827 if (!targetCoordSpace || targetCoordSpace === this) {
michael@0 36828 return rect;
michael@0 36829 }
michael@0 36830 var xMin = rect.xMin;
michael@0 36831 var xMax = rect.xMax;
michael@0 36832 var yMin = rect.yMin;
michael@0 36833 var yMax = rect.yMax;
michael@0 36834 if (xMax - xMin === 0 || yMax - yMin === 0) {
michael@0 36835 return {
michael@0 36836 xMin: 0,
michael@0 36837 yMin: 0,
michael@0 36838 xMax: 0,
michael@0 36839 yMax: 0
michael@0 36840 };
michael@0 36841 }
michael@0 36842 var m = targetCoordSpace && !flash.display.DisplayObject.class.isInstanceOf(targetCoordSpace) ? targetCoordSpace : this._getConcatenatedTransform(targetCoordSpace, false);
michael@0 36843 var x0 = m.a * xMin + m.c * yMin + m.tx | 0;
michael@0 36844 var y0 = m.b * xMin + m.d * yMin + m.ty | 0;
michael@0 36845 var x1 = m.a * xMax + m.c * yMin + m.tx | 0;
michael@0 36846 var y1 = m.b * xMax + m.d * yMin + m.ty | 0;
michael@0 36847 var x2 = m.a * xMax + m.c * yMax + m.tx | 0;
michael@0 36848 var y2 = m.b * xMax + m.d * yMax + m.ty | 0;
michael@0 36849 var x3 = m.a * xMin + m.c * yMax + m.tx | 0;
michael@0 36850 var y3 = m.b * xMin + m.d * yMax + m.ty | 0;
michael@0 36851 var tmp = 0;
michael@0 36852 if (x0 > x1) {
michael@0 36853 tmp = x0;
michael@0 36854 x0 = x1;
michael@0 36855 x1 = tmp;
michael@0 36856 }
michael@0 36857 if (x2 > x3) {
michael@0 36858 tmp = x2;
michael@0 36859 x2 = x3;
michael@0 36860 x3 = tmp;
michael@0 36861 }
michael@0 36862 xMin = x0 < x2 ? x0 : x2;
michael@0 36863 xMax = x1 > x3 ? x1 : x3;
michael@0 36864 if (y0 > y1) {
michael@0 36865 tmp = y0;
michael@0 36866 y0 = y1;
michael@0 36867 y1 = tmp;
michael@0 36868 }
michael@0 36869 if (y2 > y3) {
michael@0 36870 tmp = y2;
michael@0 36871 y2 = y3;
michael@0 36872 y3 = tmp;
michael@0 36873 }
michael@0 36874 yMin = y0 < y2 ? y0 : y2;
michael@0 36875 yMax = y1 > y3 ? y1 : y3;
michael@0 36876 return {
michael@0 36877 xMin: xMin,
michael@0 36878 yMin: yMin,
michael@0 36879 xMax: xMax,
michael@0 36880 yMax: yMax
michael@0 36881 };
michael@0 36882 },
michael@0 36883 hitTestObject: function (obj) {
michael@0 36884 return this._hitTest(false, 0, 0, false, obj);
michael@0 36885 },
michael@0 36886 hitTestPoint: function (x, y, shapeFlag) {
michael@0 36887 return this._hitTest(true, x, y, shapeFlag, null);
michael@0 36888 },
michael@0 36889 destroy: function () {
michael@0 36890 if (this._destroyed) {
michael@0 36891 return;
michael@0 36892 }
michael@0 36893 this._destroyed = true;
michael@0 36894 this.cleanupBroadcastListeners();
michael@0 36895 },
michael@0 36896 cleanupBroadcastListeners: function () {
michael@0 36897 var listenerLists = this._listeners;
michael@0 36898 for (var type in listenerLists) {
michael@0 36899 avm2.systemDomain.onMessage.unregister(type, this._onBroadcastMessage);
michael@0 36900 }
michael@0 36901 }
michael@0 36902 };
michael@0 36903 var desc = Object.getOwnPropertyDescriptor;
michael@0 36904 def.__glue__ = {
michael@0 36905 native: {
michael@0 36906 instance: {
michael@0 36907 root: desc(def, 'root'),
michael@0 36908 stage: desc(def, 'stage'),
michael@0 36909 name: desc(def, 'name'),
michael@0 36910 parent: desc(def, 'parent'),
michael@0 36911 mask: desc(def, 'mask'),
michael@0 36912 visible: desc(def, 'visible'),
michael@0 36913 x: {
michael@0 36914 get: function x() {
michael@0 36915 return this.x / 20;
michael@0 36916 },
michael@0 36917 set: function x(value) {
michael@0 36918 this.x = value * 20 | 0;
michael@0 36919 }
michael@0 36920 },
michael@0 36921 y: {
michael@0 36922 get: function y() {
michael@0 36923 return this.y / 20;
michael@0 36924 },
michael@0 36925 set: function y(value) {
michael@0 36926 this.y = value * 20 | 0;
michael@0 36927 }
michael@0 36928 },
michael@0 36929 z: {
michael@0 36930 get: function z() {
michael@0 36931 return this.z / 20;
michael@0 36932 },
michael@0 36933 set: function z(value) {
michael@0 36934 this.z = value * 20 | 0;
michael@0 36935 }
michael@0 36936 },
michael@0 36937 scaleX: desc(def, 'scaleX'),
michael@0 36938 scaleY: desc(def, 'scaleY'),
michael@0 36939 scaleZ: desc(def, 'scaleZ'),
michael@0 36940 mouseX: {
michael@0 36941 get: function mouseX() {
michael@0 36942 return this.mouseX / 20;
michael@0 36943 },
michael@0 36944 set: function mouseX(value) {
michael@0 36945 this.mouseX = value * 20 | 0;
michael@0 36946 }
michael@0 36947 },
michael@0 36948 mouseY: {
michael@0 36949 get: function mouseY() {
michael@0 36950 return this.mouseY / 20;
michael@0 36951 },
michael@0 36952 set: function mouseY(value) {
michael@0 36953 this.mouseY = value * 20 | 0;
michael@0 36954 }
michael@0 36955 },
michael@0 36956 rotation: desc(def, 'rotation'),
michael@0 36957 rotationX: desc(def, 'rotationX'),
michael@0 36958 rotationY: desc(def, 'rotationY'),
michael@0 36959 rotationZ: desc(def, 'rotationZ'),
michael@0 36960 alpha: desc(def, 'alpha'),
michael@0 36961 width: {
michael@0 36962 get: function width() {
michael@0 36963 return this.width / 20;
michael@0 36964 },
michael@0 36965 set: function width(value) {
michael@0 36966 this.width = value * 20 | 0;
michael@0 36967 }
michael@0 36968 },
michael@0 36969 height: {
michael@0 36970 get: function height() {
michael@0 36971 return this.height / 20;
michael@0 36972 },
michael@0 36973 set: function height(value) {
michael@0 36974 this.height = value * 20 | 0;
michael@0 36975 }
michael@0 36976 },
michael@0 36977 _hitTest: function (use_xy, x, y, useShape, hitTestObject) {
michael@0 36978 x = x * 20 | 0;
michael@0 36979 y = y * 20 | 0;
michael@0 36980 return this._hitTest(use_xy, x, y, useShape, hitTestObject);
michael@0 36981 },
michael@0 36982 cacheAsBitmap: desc(def, 'cacheAsBitmap'),
michael@0 36983 opaqueBackground: desc(def, 'opaqueBackground'),
michael@0 36984 scrollRect: desc(def, 'scrollRect'),
michael@0 36985 filters: desc(def, 'filters'),
michael@0 36986 blendMode: desc(def, 'blendMode'),
michael@0 36987 transform: desc(def, 'transform'),
michael@0 36988 scale9Grid: desc(def, 'scale9Grid'),
michael@0 36989 loaderInfo: desc(def, 'loaderInfo'),
michael@0 36990 accessibilityProperties: desc(def, 'accessibilityProperties'),
michael@0 36991 globalToLocal: function (pt) {
michael@0 36992 point.x = pt.x * 20 | 0;
michael@0 36993 point.y = pt.y * 20 | 0;
michael@0 36994 this._applyConcatenatedInverseTransform(point);
michael@0 36995 return new flash.geom.Point(point.x / 20, point.y / 20);
michael@0 36996 },
michael@0 36997 localToGlobal: function (pt) {
michael@0 36998 point.x = pt.x * 20 | 0;
michael@0 36999 point.y = pt.y * 20 | 0;
michael@0 37000 this._applyCurrentTransform(point);
michael@0 37001 return new flash.geom.Point(point.x / 20, point.y / 20);
michael@0 37002 },
michael@0 37003 getBounds: function (targetCoordSpace) {
michael@0 37004 var bounds = this.getBounds(targetCoordSpace);
michael@0 37005 return new flash.geom.Rectangle(bounds.xMin / 20, bounds.yMin / 20, (bounds.xMax - bounds.xMin) / 20, (bounds.yMax - bounds.yMin) / 20);
michael@0 37006 },
michael@0 37007 getRect: function (targetCoordSpace) {
michael@0 37008 somewhatImplemented('DisplayObject.getRect');
michael@0 37009 var bounds = this.getBounds(targetCoordSpace);
michael@0 37010 return new flash.geom.Rectangle(bounds.xMin / 20, bounds.yMin / 20, (bounds.xMax - bounds.xMin) / 20, (bounds.yMax - bounds.yMin) / 20);
michael@0 37011 }
michael@0 37012 }
michael@0 37013 }
michael@0 37014 };
michael@0 37015 return def;
michael@0 37016 }.call(this);
michael@0 37017 var DisplayObjectContainerDefinition = function () {
michael@0 37018 var def = {
michael@0 37019 get mouseChildren() {
michael@0 37020 return this._mouseChildren;
michael@0 37021 },
michael@0 37022 set mouseChildren(val) {
michael@0 37023 this._mouseChildren = val;
michael@0 37024 },
michael@0 37025 get numChildren() {
michael@0 37026 return this._children.length;
michael@0 37027 },
michael@0 37028 get tabChildren() {
michael@0 37029 return this._tabChildren;
michael@0 37030 },
michael@0 37031 set tabChildren(val) {
michael@0 37032 this._tabChildren = val;
michael@0 37033 },
michael@0 37034 get textSnapshot() {
michael@0 37035 notImplemented();
michael@0 37036 },
michael@0 37037 addChild: function (child) {
michael@0 37038 return this.addChildAt(child, this._children.length);
michael@0 37039 },
michael@0 37040 addChildAt: function (child, index) {
michael@0 37041 if (child === this) {
michael@0 37042 throwError('ArgumentError', Errors.CantAddSelfError);
michael@0 37043 }
michael@0 37044 if (child._parent === this) {
michael@0 37045 return this.setChildIndex(child, index);
michael@0 37046 }
michael@0 37047 var children = this._children;
michael@0 37048 if (index < 0 || index > children.length) {
michael@0 37049 throwError('RangeError', Errors.ParamRangeError);
michael@0 37050 }
michael@0 37051 if (child._index > -1) {
michael@0 37052 var LoaderClass = avm2.systemDomain.getClass('flash.display.Loader');
michael@0 37053 if (LoaderClass.isInstanceOf(child._parent)) {
michael@0 37054 def.removeChild.call(child._parent, child);
michael@0 37055 } else {
michael@0 37056 child._parent.removeChild(child);
michael@0 37057 }
michael@0 37058 }
michael@0 37059 if (!this._sparse) {
michael@0 37060 for (var i = children.length; i && i > index; i--) {
michael@0 37061 children[i - 1]._index++;
michael@0 37062 }
michael@0 37063 }
michael@0 37064 children.splice(index, 0, child);
michael@0 37065 child._invalidateTransform();
michael@0 37066 child._owned = false;
michael@0 37067 child._parent = this;
michael@0 37068 child._stage = this._stage;
michael@0 37069 child._index = index;
michael@0 37070 child._dispatchEvent('added', undefined, true);
michael@0 37071 if (this._stage) {
michael@0 37072 this._stage._addToStage(child);
michael@0 37073 }
michael@0 37074 return child;
michael@0 37075 },
michael@0 37076 areInaccessibleObjectsUnderPoint: function (pt) {
michael@0 37077 notImplemented();
michael@0 37078 },
michael@0 37079 contains: function (child) {
michael@0 37080 return child._parent === this;
michael@0 37081 },
michael@0 37082 getChildAt: function (index) {
michael@0 37083 var children = this._children;
michael@0 37084 if (index < 0 || index > children.length) {
michael@0 37085 throwError('RangeError', Errors.ParamRangeError);
michael@0 37086 }
michael@0 37087 var child = children[index];
michael@0 37088 if (!flash.display.DisplayObject.class.isInstanceOf(child)) {
michael@0 37089 return null;
michael@0 37090 }
michael@0 37091 return child;
michael@0 37092 },
michael@0 37093 getChildByName: function (name) {
michael@0 37094 var children = this._children;
michael@0 37095 for (var i = 0, n = children.length; i < n; i++) {
michael@0 37096 var child = children[i];
michael@0 37097 if (child.name === name) {
michael@0 37098 return this.getChildAt(i);
michael@0 37099 }
michael@0 37100 }
michael@0 37101 return null;
michael@0 37102 },
michael@0 37103 getChildIndex: function (child) {
michael@0 37104 if (child._parent !== this) {
michael@0 37105 throwError('ArgumentError', Errors.NotAChildError);
michael@0 37106 }
michael@0 37107 return this._sparse ? this._children.indexOf(child) : child._index;
michael@0 37108 },
michael@0 37109 getObjectsUnderPoint: function (pt) {
michael@0 37110 notImplemented();
michael@0 37111 },
michael@0 37112 removeChild: function (child) {
michael@0 37113 if (child._parent !== this) {
michael@0 37114 throwError('ArgumentError', Errors.NotAChildError);
michael@0 37115 }
michael@0 37116 return this.removeChildAt(this.getChildIndex(child));
michael@0 37117 },
michael@0 37118 removeChildAt: function (index) {
michael@0 37119 var children = this._children;
michael@0 37120 if (index < 0 || index >= children.length) {
michael@0 37121 throwError('RangeError', Errors.ParamRangeError);
michael@0 37122 }
michael@0 37123 var child = children[index];
michael@0 37124 child._dispatchEvent('removed', undefined, true);
michael@0 37125 if (this._stage) {
michael@0 37126 this._stage._removeFromStage(child);
michael@0 37127 }
michael@0 37128 if (!this._sparse) {
michael@0 37129 for (var i = children.length; i && i > index; i--) {
michael@0 37130 children[i - 1]._index--;
michael@0 37131 }
michael@0 37132 }
michael@0 37133 children.splice(index, 1);
michael@0 37134 child._invalidateTransform();
michael@0 37135 child._owned = false;
michael@0 37136 child._parent = null;
michael@0 37137 child._index = -1;
michael@0 37138 return child;
michael@0 37139 },
michael@0 37140 setChildIndex: function (child, index) {
michael@0 37141 if (child._parent !== this) {
michael@0 37142 throwError('ArgumentError', Errors.NotAChildError);
michael@0 37143 }
michael@0 37144 var currentIndex = this.getChildIndex(child);
michael@0 37145 if (currentIndex === index) {
michael@0 37146 return;
michael@0 37147 }
michael@0 37148 var children = this._children;
michael@0 37149 if (index < 0 || index > children.length) {
michael@0 37150 throwError('RangeError', Errors.ParamRangeError);
michael@0 37151 }
michael@0 37152 children.splice(currentIndex, 1);
michael@0 37153 children.splice(index, 0, child);
michael@0 37154 if (!this._sparse) {
michael@0 37155 var i = currentIndex < index ? currentIndex : index;
michael@0 37156 while (i < children.length) {
michael@0 37157 children[i]._index = i++;
michael@0 37158 }
michael@0 37159 }
michael@0 37160 child._owned = false;
michael@0 37161 child._invalidate();
michael@0 37162 return child;
michael@0 37163 },
michael@0 37164 removeChildren: function (beginIndex, endIndex) {
michael@0 37165 beginIndex = arguments.length < 1 ? 0 : beginIndex | 0;
michael@0 37166 endIndex = arguments.length < 2 ? 2147483647 : endIndex | 0;
michael@0 37167 var numChildren = this._children.length;
michael@0 37168 if (beginIndex < 0 || endIndex < 0 || endIndex < beginIndex) {
michael@0 37169 throwError('RangeError', Errors.ParamRangeError);
michael@0 37170 }
michael@0 37171 if (numChildren === 0) {
michael@0 37172 return;
michael@0 37173 }
michael@0 37174 if (endIndex > numChildren - 1) {
michael@0 37175 endIndex = numChildren - 1;
michael@0 37176 }
michael@0 37177 var count = endIndex - beginIndex + 1;
michael@0 37178 while (count--) {
michael@0 37179 this.removeChildAt(beginIndex);
michael@0 37180 }
michael@0 37181 },
michael@0 37182 swapChildren: function (child1, child2) {
michael@0 37183 if (child1._parent !== this || child2._parent !== this) {
michael@0 37184 throwError('ArgumentError', Errors.NotAChildError);
michael@0 37185 }
michael@0 37186 this.swapChildrenAt(this.getChildIndex(child1), this.getChildIndex(child2));
michael@0 37187 },
michael@0 37188 swapChildrenAt: function (index1, index2) {
michael@0 37189 var children = this._children;
michael@0 37190 var numChildren = children.length;
michael@0 37191 if (index1 < 0 || index1 > numChildren || index2 < 0 || index2 > numChildren) {
michael@0 37192 throwError('RangeError', Errors.ParamRangeError);
michael@0 37193 }
michael@0 37194 var child1 = children[index1];
michael@0 37195 var child2 = children[index2];
michael@0 37196 children[index1] = child2;
michael@0 37197 children[index2] = child1;
michael@0 37198 child1._index = index2;
michael@0 37199 child2._index = index1;
michael@0 37200 child1._owned = false;
michael@0 37201 child2._owned = false;
michael@0 37202 child1._invalidate();
michael@0 37203 child2._invalidate();
michael@0 37204 },
michael@0 37205 destroy: function () {
michael@0 37206 if (this._destroyed) {
michael@0 37207 return;
michael@0 37208 }
michael@0 37209 this._destroyed = true;
michael@0 37210 this._children.forEach(function (child) {
michael@0 37211 if (child.destroy) {
michael@0 37212 child.destroy();
michael@0 37213 }
michael@0 37214 });
michael@0 37215 this.cleanupBroadcastListeners();
michael@0 37216 }
michael@0 37217 };
michael@0 37218 var desc = Object.getOwnPropertyDescriptor;
michael@0 37219 def.initialize = function () {
michael@0 37220 this._mouseChildren = true;
michael@0 37221 this._tabChildren = true;
michael@0 37222 this._sparse = false;
michael@0 37223 this._isContainer = true;
michael@0 37224 };
michael@0 37225 def.__glue__ = {
michael@0 37226 native: {
michael@0 37227 instance: {
michael@0 37228 numChildren: desc(def, 'numChildren'),
michael@0 37229 tabChildren: desc(def, 'tabChildren'),
michael@0 37230 mouseChildren: desc(def, 'mouseChildren'),
michael@0 37231 textSnapshot: desc(def, 'textSnapshot'),
michael@0 37232 addChild: def.addChild,
michael@0 37233 addChildAt: def.addChildAt,
michael@0 37234 removeChild: def.removeChild,
michael@0 37235 removeChildAt: def.removeChildAt,
michael@0 37236 getChildIndex: def.getChildIndex,
michael@0 37237 setChildIndex: def.setChildIndex,
michael@0 37238 getChildAt: def.getChildAt,
michael@0 37239 getChildByName: def.getChildByName,
michael@0 37240 contains: def.contains,
michael@0 37241 swapChildrenAt: def.swapChildrenAt,
michael@0 37242 swapChildren: def.swapChildren,
michael@0 37243 removeChildren: def.removeChildren
michael@0 37244 }
michael@0 37245 }
michael@0 37246 };
michael@0 37247 return def;
michael@0 37248 }.call(this);
michael@0 37249 var FrameLabelDefinition = function () {
michael@0 37250 return {
michael@0 37251 __class__: 'flash.display.FrameLabel',
michael@0 37252 initialize: function () {
michael@0 37253 },
michael@0 37254 __glue__: {
michael@0 37255 native: {
michael@0 37256 static: {},
michael@0 37257 instance: {
michael@0 37258 ctor: function ctor(name, frame) {
michael@0 37259 this._name = name;
michael@0 37260 this._frame = frame;
michael@0 37261 },
michael@0 37262 name: {
michael@0 37263 get: function name() {
michael@0 37264 return this._name;
michael@0 37265 }
michael@0 37266 },
michael@0 37267 frame: {
michael@0 37268 get: function frame() {
michael@0 37269 return this._frame;
michael@0 37270 }
michael@0 37271 }
michael@0 37272 }
michael@0 37273 }
michael@0 37274 }
michael@0 37275 };
michael@0 37276 }.call(this);
michael@0 37277 var GraphicsDefinition = function () {
michael@0 37278 var GRAPHICS_PATH_WINDING_EVEN_ODD = 'evenOdd';
michael@0 37279 var GRAPHICS_PATH_WINDING_NON_ZERO = 'nonZero';
michael@0 37280 var def = {
michael@0 37281 __class__: 'flash.display.Graphics',
michael@0 37282 initialize: function () {
michael@0 37283 this._paths = [];
michael@0 37284 this.beginPath();
michael@0 37285 this._bitmap = null;
michael@0 37286 this._parent = 0;
michael@0 37287 this.bbox = null;
michael@0 37288 this.strokeBbox = null;
michael@0 37289 },
michael@0 37290 _invalidate: function () {
michael@0 37291 this.bbox = null;
michael@0 37292 this.strokeBbox = null;
michael@0 37293 this._parent._invalidate();
michael@0 37294 this._parent._invalidateBounds();
michael@0 37295 },
michael@0 37296 beginPath: function () {
michael@0 37297 var oldPath = this._currentPath;
michael@0 37298 if (oldPath && (oldPath.commands.length === 0 || oldPath.commands.length === 1 && oldPath.commands[0] === SHAPE_MOVE_TO)) {
michael@0 37299 return;
michael@0 37300 }
michael@0 37301 var path = this._currentPath = new ShapePath(null, null);
michael@0 37302 this._paths.push(path);
michael@0 37303 if (oldPath) {
michael@0 37304 path.fillStyle = oldPath.fillStyle;
michael@0 37305 path.lineStyle = oldPath.lineStyle;
michael@0 37306 path.fillRule = oldPath.fillRule;
michael@0 37307 }
michael@0 37308 },
michael@0 37309 _drawPathObject: function (path) {
michael@0 37310 if (path.__class__ === 'flash.display.GraphicsPath')
michael@0 37311 this.drawPath(path.commands, path.data, path.winding);
michael@0 37312 else if (path.__class__ === 'flash.display.GraphicsTrianglePath')
michael@0 37313 this.drawTriangles(path.vertices, path.indices, path.uvtData, path.culling);
michael@0 37314 },
michael@0 37315 draw: function (ctx, clip, ratio, colorTransform) {
michael@0 37316 var paths = this._paths;
michael@0 37317 for (var i = 0; i < paths.length; i++) {
michael@0 37318 paths[i].draw(ctx, clip, ratio, colorTransform);
michael@0 37319 }
michael@0 37320 },
michael@0 37321 beginFill: function (color, alpha) {
michael@0 37322 if (alpha === undefined)
michael@0 37323 alpha = 1;
michael@0 37324 this.beginPath();
michael@0 37325 this._currentPath.fillStyle = alpha ? {
michael@0 37326 style: rgbIntAlphaToStr(color, alpha)
michael@0 37327 } : null;
michael@0 37328 },
michael@0 37329 beginGradientFill: function (type, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPos) {
michael@0 37330 var style = createGradientStyle(type, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPos);
michael@0 37331 this.beginPath();
michael@0 37332 this._currentPath.fillStyle = style;
michael@0 37333 },
michael@0 37334 beginBitmapFill: function (bitmap, matrix, repeat, smooth) {
michael@0 37335 this.beginPath();
michael@0 37336 repeat = repeat !== false;
michael@0 37337 this._currentPath.fillStyle = createPatternStyle(bitmap, matrix, repeat, !(!smooth));
michael@0 37338 },
michael@0 37339 clear: function () {
michael@0 37340 this._invalidate();
michael@0 37341 this._paths = [];
michael@0 37342 this._currentPath = null;
michael@0 37343 this.beginPath();
michael@0 37344 },
michael@0 37345 copyFrom: function (sourceGraphics) {
michael@0 37346 notImplemented('Graphics#copyFrom');
michael@0 37347 },
michael@0 37348 cubicCurveTo: function (cp1x, cp1y, cp2x, cp2y, x, y) {
michael@0 37349 this._invalidate();
michael@0 37350 this._currentPath.cubicCurveTo(cp1x * 20 | 0, cp1y * 20 | 0, cp2x * 20 | 0, cp2y * 20 | 0, x * 20 | 0, y * 20 | 0);
michael@0 37351 },
michael@0 37352 curveTo: function (cpx, cpy, x, y) {
michael@0 37353 this._invalidate();
michael@0 37354 this._currentPath.curveTo(cpx * 20 | 0, cpy * 20 | 0, x * 20 | 0, y * 20 | 0);
michael@0 37355 },
michael@0 37356 drawCircle: function (x, y, radius) {
michael@0 37357 var radius2 = radius * 2;
michael@0 37358 this.drawRoundRect(x - radius, y - radius, radius2, radius2, radius2, radius2);
michael@0 37359 },
michael@0 37360 drawEllipse: function (x, y, width, height) {
michael@0 37361 this.drawRoundRect(x, y, width, height, width, height);
michael@0 37362 },
michael@0 37363 drawPath: function (commands, data, winding) {
michael@0 37364 this._invalidate();
michael@0 37365 this.beginPath();
michael@0 37366 this._currentPath.fillRule = winding || GRAPHICS_PATH_WINDING_EVEN_ODD;
michael@0 37367 this._currentPath.commands = commands;
michael@0 37368 this._currentPath.data = data;
michael@0 37369 },
michael@0 37370 drawRect: function (x, y, w, h) {
michael@0 37371 if (isNaN(w + h))
michael@0 37372 throwError('ArgumentError', Errors.InvalidParamError);
michael@0 37373 this._invalidate();
michael@0 37374 this._currentPath.rect(x * 20 | 0, y * 20 | 0, w * 20 | 0, h * 20 | 0);
michael@0 37375 },
michael@0 37376 drawRoundRect: function (x, y, w, h, ellipseWidth, ellipseHeight) {
michael@0 37377 if (isNaN(w + h + ellipseWidth) || ellipseHeight !== undefined && isNaN(ellipseHeight)) {
michael@0 37378 throwError('ArgumentError', Errors.InvalidParamError);
michael@0 37379 }
michael@0 37380 this._invalidate();
michael@0 37381 if (ellipseHeight === undefined) {
michael@0 37382 ellipseHeight = ellipseWidth;
michael@0 37383 }
michael@0 37384 x = x * 20 | 0;
michael@0 37385 y = y * 20 | 0;
michael@0 37386 w = w * 20 | 0;
michael@0 37387 h = h * 20 | 0;
michael@0 37388 if (!ellipseHeight || !ellipseWidth) {
michael@0 37389 this._currentPath.rect(x, y, w, h);
michael@0 37390 return;
michael@0 37391 }
michael@0 37392 var radiusX = ellipseWidth / 2 * 20 | 0;
michael@0 37393 var radiusY = ellipseHeight / 2 * 20 | 0;
michael@0 37394 var hw = w / 2 | 0;
michael@0 37395 var hh = h / 2 | 0;
michael@0 37396 if (radiusX > hw) {
michael@0 37397 radiusX = hw;
michael@0 37398 }
michael@0 37399 if (radiusY > hh) {
michael@0 37400 radiusY = hh;
michael@0 37401 }
michael@0 37402 if (hw === radiusX && hh === radiusY) {
michael@0 37403 if (radiusX === radiusY)
michael@0 37404 this._currentPath.circle(x + radiusX, y + radiusY, radiusX);
michael@0 37405 else
michael@0 37406 this._currentPath.ellipse(x + radiusX, y + radiusY, radiusX, radiusY);
michael@0 37407 return;
michael@0 37408 }
michael@0 37409 var right = x + w;
michael@0 37410 var bottom = y + h;
michael@0 37411 var xlw = x + radiusX;
michael@0 37412 var xrw = right - radiusX;
michael@0 37413 var ytw = y + radiusY;
michael@0 37414 var ybw = bottom - radiusY;
michael@0 37415 this._currentPath.moveTo(right, ybw);
michael@0 37416 this._currentPath.curveTo(right, bottom, xrw, bottom);
michael@0 37417 this._currentPath.lineTo(xlw, bottom);
michael@0 37418 this._currentPath.curveTo(x, bottom, x, ybw);
michael@0 37419 this._currentPath.lineTo(x, ytw);
michael@0 37420 this._currentPath.curveTo(x, y, xlw, y);
michael@0 37421 this._currentPath.lineTo(xrw, y);
michael@0 37422 this._currentPath.curveTo(right, y, right, ytw);
michael@0 37423 this._currentPath.lineTo(right, ybw);
michael@0 37424 },
michael@0 37425 drawRoundRectComplex: function (x, y, w, h, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius) {
michael@0 37426 if (isNaN(w + h + topLeftRadius + topRightRadius + bottomLeftRadius + bottomRightRadius)) {
michael@0 37427 throwError('ArgumentError', Errors.InvalidParamError);
michael@0 37428 }
michael@0 37429 this._invalidate();
michael@0 37430 x = x * 20 | 0;
michael@0 37431 y = y * 20 | 0;
michael@0 37432 w = w * 20 | 0;
michael@0 37433 h = h * 20 | 0;
michael@0 37434 if (!topLeftRadius && !topRightRadius && !bottomLeftRadius && !bottomRightRadius) {
michael@0 37435 this._currentPath.rect(x, y, w, h);
michael@0 37436 return;
michael@0 37437 }
michael@0 37438 topLeftRadius = topLeftRadius * 20 | 0;
michael@0 37439 topRightRadius = topRightRadius * 20 | 0;
michael@0 37440 bottomLeftRadius = bottomLeftRadius * 20 | 0;
michael@0 37441 bottomRightRadius = bottomRightRadius * 20 | 0;
michael@0 37442 var right = x + w;
michael@0 37443 var bottom = y + h;
michael@0 37444 var xtl = x + topLeftRadius;
michael@0 37445 this._currentPath.moveTo(right, bottom - bottomRightRadius);
michael@0 37446 this._currentPath.curveTo(right, bottom, right - bottomRightRadius, bottom);
michael@0 37447 this._currentPath.lineTo(x + bottomLeftRadius, bottom);
michael@0 37448 this._currentPath.curveTo(x, bottom, x, bottom - bottomLeftRadius);
michael@0 37449 this._currentPath.lineTo(x, y + topLeftRadius);
michael@0 37450 this._currentPath.curveTo(x, y, xtl, y);
michael@0 37451 this._currentPath.lineTo(right - topRightRadius, y);
michael@0 37452 this._currentPath.curveTo(right, y, right, y + topRightRadius);
michael@0 37453 this._currentPath.lineTo(right, bottom - bottomRightRadius);
michael@0 37454 },
michael@0 37455 drawTriangles: function (vertices, indices, uvtData, cullingStr) {
michael@0 37456 if (vertices === null || vertices.length === 0) {
michael@0 37457 return;
michael@0 37458 }
michael@0 37459 var numVertices = vertices.length / 2;
michael@0 37460 var numTriangles = 0;
michael@0 37461 if (indices) {
michael@0 37462 if (indices.length % 3) {
michael@0 37463 throwError('ArgumentError', Errors.InvalidParamError);
michael@0 37464 } else {
michael@0 37465 numTriangles = indices.length / 3;
michael@0 37466 }
michael@0 37467 } else {
michael@0 37468 if (vertices.length % 6) {
michael@0 37469 throwError('ArgumentError', Errors.InvalidParamError);
michael@0 37470 } else {
michael@0 37471 numTriangles = vertices.length / 6;
michael@0 37472 }
michael@0 37473 }
michael@0 37474 var numStrides = 0;
michael@0 37475 if (uvtData) {
michael@0 37476 if (uvtData.length == numVertices * 2) {
michael@0 37477 numStrides = 2;
michael@0 37478 } else if (uvtData.length == numVertices * 3) {
michael@0 37479 numStrides = 3;
michael@0 37480 } else {
michael@0 37481 throwError('ArgumentError', Errors.InvalidParamError);
michael@0 37482 }
michael@0 37483 }
michael@0 37484 var culling = 0;
michael@0 37485 if (cullingStr === 'none') {
michael@0 37486 culling = 0;
michael@0 37487 } else if (cullingStr === 'negative') {
michael@0 37488 culling = -1;
michael@0 37489 } else if (cullingStr === 'positive') {
michael@0 37490 culling = 1;
michael@0 37491 } else {
michael@0 37492 throwError('ArgumentError', Errors.InvalidEnumError, 'culling');
michael@0 37493 }
michael@0 37494 notImplemented('Graphics#drawTriangles');
michael@0 37495 },
michael@0 37496 endFill: function () {
michael@0 37497 this.beginPath();
michael@0 37498 this._currentPath.fillStyle = null;
michael@0 37499 },
michael@0 37500 lineBitmapStyle: function (bitmap, matrix, repeat, smooth) {
michael@0 37501 this.beginPath();
michael@0 37502 this._currentPath.lineStyle = createPatternStyle(bitmap, matrix, repeat, smooth);
michael@0 37503 },
michael@0 37504 lineGradientStyle: function (type, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPos) {
michael@0 37505 var style = createGradientStyle(type, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPos);
michael@0 37506 this.beginPath();
michael@0 37507 this._currentPath.lineStyle = style;
michael@0 37508 },
michael@0 37509 lineStyle: function (width, color, alpha, pxHinting, scale, cap, joint, mlimit) {
michael@0 37510 this.beginPath();
michael@0 37511 if (width) {
michael@0 37512 if (alpha === undefined)
michael@0 37513 alpha = 1;
michael@0 37514 if (mlimit === undefined)
michael@0 37515 mlimit = 3;
michael@0 37516 this._currentPath.lineStyle = {
michael@0 37517 style: rgbIntAlphaToStr(color, alpha),
michael@0 37518 lineCap: cap || 'round',
michael@0 37519 lineJoin: cap || 'round',
michael@0 37520 width: width * 20 | 0,
michael@0 37521 miterLimit: mlimit * 2
michael@0 37522 };
michael@0 37523 } else {
michael@0 37524 this._currentPath.lineStyle = null;
michael@0 37525 }
michael@0 37526 },
michael@0 37527 lineTo: function (x, y) {
michael@0 37528 this._invalidate();
michael@0 37529 this._currentPath.lineTo(x * 20 | 0, y * 20 | 0);
michael@0 37530 },
michael@0 37531 moveTo: function (x, y) {
michael@0 37532 this._currentPath.moveTo(x * 20 | 0, y * 20 | 0);
michael@0 37533 },
michael@0 37534 _getBounds: function (includeStroke) {
michael@0 37535 var bbox = includeStroke ? this.strokeBbox : this.bbox;
michael@0 37536 if (bbox) {
michael@0 37537 return bbox;
michael@0 37538 }
michael@0 37539 var subpaths = this._paths;
michael@0 37540 var xMins = [], yMins = [], xMaxs = [], yMaxs = [];
michael@0 37541 for (var i = 0, n = subpaths.length; i < n; i++) {
michael@0 37542 var path = subpaths[i];
michael@0 37543 if (path.commands.length) {
michael@0 37544 var b = path.getBounds(includeStroke);
michael@0 37545 if (b) {
michael@0 37546 xMins.push(b.xMin);
michael@0 37547 yMins.push(b.yMin);
michael@0 37548 xMaxs.push(b.xMax);
michael@0 37549 yMaxs.push(b.yMax);
michael@0 37550 }
michael@0 37551 }
michael@0 37552 }
michael@0 37553 if (xMins.length === 0) {
michael@0 37554 bbox = {
michael@0 37555 xMin: 0,
michael@0 37556 yMin: 0,
michael@0 37557 xMax: 0,
michael@0 37558 yMax: 0
michael@0 37559 };
michael@0 37560 } else {
michael@0 37561 bbox = {
michael@0 37562 xMin: Math.min.apply(Math, xMins),
michael@0 37563 yMin: Math.min.apply(Math, yMins),
michael@0 37564 xMax: Math.max.apply(Math, xMaxs),
michael@0 37565 yMax: Math.max.apply(Math, yMaxs)
michael@0 37566 };
michael@0 37567 }
michael@0 37568 if (includeStroke) {
michael@0 37569 this.strokeBbox = bbox;
michael@0 37570 } else {
michael@0 37571 this.bbox = bbox;
michael@0 37572 }
michael@0 37573 return bbox;
michael@0 37574 }
michael@0 37575 };
michael@0 37576 def.__glue__ = {
michael@0 37577 native: {
michael@0 37578 instance: {
michael@0 37579 beginFill: def.beginFill,
michael@0 37580 beginGradientFill: def.beginGradientFill,
michael@0 37581 beginBitmapFill: def.beginBitmapFill,
michael@0 37582 beginFillObject: def.beginFillObject,
michael@0 37583 beginStrokeObject: def.beginStrokeObject,
michael@0 37584 clear: def.clear,
michael@0 37585 copyFrom: def.copyFrom,
michael@0 37586 cubicCurveTo: def.cubicCurveTo,
michael@0 37587 curveTo: def.curveTo,
michael@0 37588 drawCircle: def.drawCircle,
michael@0 37589 drawEllipse: def.drawEllipse,
michael@0 37590 drawPath: def.drawPath,
michael@0 37591 drawRect: def.drawRect,
michael@0 37592 drawRoundRect: def.drawRoundRect,
michael@0 37593 drawRoundRectComplex: def.drawRoundRectComplex,
michael@0 37594 drawTriangles: def.drawTriangles,
michael@0 37595 endFill: def.endFill,
michael@0 37596 lineBitmapStyle: def.lineBitmapStyle,
michael@0 37597 lineGradientStyle: def.lineGradientStyle,
michael@0 37598 lineStyle: def.lineStyle,
michael@0 37599 moveTo: def.moveTo,
michael@0 37600 lineTo: def.lineTo
michael@0 37601 }
michael@0 37602 }
michael@0 37603 };
michael@0 37604 return def;
michael@0 37605 }.call(this);
michael@0 37606 function createPatternStyle(bitmap, matrix, repeat, smooth) {
michael@0 37607 var repeatStyle = repeat === false ? 'no-repeat' : 'repeat';
michael@0 37608 var pattern = factoryCtx.createPattern(bitmap._drawable, repeatStyle);
michael@0 37609 var transform = matrix ? {
michael@0 37610 a: matrix.a,
michael@0 37611 b: matrix.b,
michael@0 37612 c: matrix.c,
michael@0 37613 d: matrix.d,
michael@0 37614 e: matrix.tx,
michael@0 37615 f: matrix.ty
michael@0 37616 } : {
michael@0 37617 a: 1,
michael@0 37618 b: 0,
michael@0 37619 c: 0,
michael@0 37620 d: 1,
michael@0 37621 e: 0,
michael@0 37622 f: 0
michael@0 37623 };
michael@0 37624 return {
michael@0 37625 style: pattern,
michael@0 37626 transform: transform,
michael@0 37627 smooth: smooth
michael@0 37628 };
michael@0 37629 }
michael@0 37630 function createGradientStyle(type, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPos) {
michael@0 37631 type === null || type === undefined && throwError('TypeError', Errors.NullPointerError, 'type');
michael@0 37632 colors === null || type === undefined && throwError('TypeError', Errors.NullPointerError, 'colors');
michael@0 37633 if (!(type === 'linear' || type === 'radial')) {
michael@0 37634 throwError('ArgumentError', Errors.InvalidEnumError, 'type');
michael@0 37635 }
michael@0 37636 var colorStops = [];
michael@0 37637 for (var i = 0, n = colors.length; i < n; i++) {
michael@0 37638 colorStops.push({
michael@0 37639 ratio: ratios[i] / 255,
michael@0 37640 color: rgbIntAlphaToStr(colors[i], alphas[i])
michael@0 37641 });
michael@0 37642 }
michael@0 37643 var gradientConstructor;
michael@0 37644 if (type === 'linear') {
michael@0 37645 gradientConstructor = buildLinearGradientFactory(colorStops);
michael@0 37646 } else {
michael@0 37647 gradientConstructor = buildRadialGradientFactory(focalPos || 0, colorStops);
michael@0 37648 }
michael@0 37649 var scale = 819.2;
michael@0 37650 var transform = matrix ? {
michael@0 37651 a: scale * matrix.a,
michael@0 37652 b: scale * matrix.b,
michael@0 37653 c: scale * matrix.c,
michael@0 37654 d: scale * matrix.d,
michael@0 37655 e: matrix.tx,
michael@0 37656 f: matrix.ty
michael@0 37657 } : {
michael@0 37658 a: scale,
michael@0 37659 b: 0,
michael@0 37660 c: 0,
michael@0 37661 d: scale,
michael@0 37662 e: 0,
michael@0 37663 f: 0
michael@0 37664 };
michael@0 37665 return {
michael@0 37666 style: gradientConstructor,
michael@0 37667 transform: transform
michael@0 37668 };
michael@0 37669 }
michael@0 37670 function drawGraphicsData(data) {
michael@0 37671 if (data === null) {
michael@0 37672 return;
michael@0 37673 }
michael@0 37674 for (var i = 0; i < data.length; i++) {
michael@0 37675 var item = data[i];
michael@0 37676 if (flash.display.IGraphicsPath.class.isInstanceOf(item)) {
michael@0 37677 this._drawPathObject(item);
michael@0 37678 } else if (flash.display.IGraphicsStroke.class.isInstanceOf(item)) {
michael@0 37679 this.beginStrokeObject(item);
michael@0 37680 } else if (flash.display.IGraphicsFill.class.isInstanceOf(item)) {
michael@0 37681 this.beginFillObject(item);
michael@0 37682 }
michael@0 37683 }
michael@0 37684 }
michael@0 37685 var InteractiveObjectDefinition = function () {
michael@0 37686 var def = {
michael@0 37687 initialize: function () {
michael@0 37688 this._contextMenu = null;
michael@0 37689 this._doubleClickEnabled = false;
michael@0 37690 this._focusRect = null;
michael@0 37691 this._mouseEnabled = true;
michael@0 37692 this._tabEnabled = false;
michael@0 37693 },
michael@0 37694 get accessibilityImplementation() {
michael@0 37695 return null;
michael@0 37696 },
michael@0 37697 set accessibilityImplementation(val) {
michael@0 37698 somewhatImplemented('accessibilityImplementation');
michael@0 37699 },
michael@0 37700 get contextMenu() {
michael@0 37701 somewhatImplemented('contextMenu');
michael@0 37702 return this._contextMenu;
michael@0 37703 },
michael@0 37704 set contextMenu(val) {
michael@0 37705 somewhatImplemented('contextMenu');
michael@0 37706 this._contextMenu = val;
michael@0 37707 },
michael@0 37708 get doubleClickEnabled() {
michael@0 37709 return this._doubleClickEnabled;
michael@0 37710 },
michael@0 37711 set doubleClickEnabled(val) {
michael@0 37712 this._doubleClickEnabled = val;
michael@0 37713 },
michael@0 37714 get focusRect() {
michael@0 37715 return this._focusRect;
michael@0 37716 },
michael@0 37717 set focusRect(val) {
michael@0 37718 this._focusRect = val;
michael@0 37719 },
michael@0 37720 get mouseEnabled() {
michael@0 37721 return this._mouseEnabled;
michael@0 37722 },
michael@0 37723 set mouseEnabled(val) {
michael@0 37724 this._mouseEnabled = val;
michael@0 37725 },
michael@0 37726 get needsSoftKeyboard() {
michael@0 37727 return false;
michael@0 37728 },
michael@0 37729 set needsSoftKeyboard(val) {
michael@0 37730 notImplemented();
michael@0 37731 },
michael@0 37732 get softKeyboardInputAreaOfInterest() {
michael@0 37733 return null;
michael@0 37734 },
michael@0 37735 set softKeyboardInputAreaOfInterest(val) {
michael@0 37736 notImplemented();
michael@0 37737 },
michael@0 37738 get tabEnabled() {
michael@0 37739 return this._tabEnabled;
michael@0 37740 },
michael@0 37741 set tabEnabled(val) {
michael@0 37742 var old = this._tabEnabled;
michael@0 37743 this._tabEnabled = val;
michael@0 37744 if (old !== val) {
michael@0 37745 var Event = flash.events.Event;
michael@0 37746 this._dispatchEvent(new Event('tabEnabledChange', false, false));
michael@0 37747 }
michael@0 37748 },
michael@0 37749 requestSoftKeyboard: function () {
michael@0 37750 notImplemented();
michael@0 37751 }
michael@0 37752 };
michael@0 37753 var desc = Object.getOwnPropertyDescriptor;
michael@0 37754 def.__glue__ = {
michael@0 37755 native: {
michael@0 37756 instance: {
michael@0 37757 tabEnabled: desc(def, 'tabEnabled'),
michael@0 37758 tabIndex: {
michael@0 37759 get: function tabIndex() {
michael@0 37760 return this._tabIndex;
michael@0 37761 },
michael@0 37762 set: function tabIndex(index) {
michael@0 37763 this._tabIndex = index;
michael@0 37764 }
michael@0 37765 },
michael@0 37766 focusRect: desc(def, 'focusRect'),
michael@0 37767 mouseEnabled: desc(def, 'mouseEnabled'),
michael@0 37768 doubleClickEnabled: desc(def, 'doubleClickEnabled'),
michael@0 37769 accessibilityImplementation: desc(def, 'accessibilityImplementation'),
michael@0 37770 softKeyboardInputAreaOfInterest: desc(def, 'softKeyboardInputAreaOfInterest'),
michael@0 37771 needsSoftKeyboard: desc(def, 'needsSoftKeyboard'),
michael@0 37772 contextMenu: desc(def, 'contextMenu'),
michael@0 37773 requestSoftKeyboard: def.requestSoftKeyboard
michael@0 37774 }
michael@0 37775 }
michael@0 37776 };
michael@0 37777 return def;
michael@0 37778 }.call(this);
michael@0 37779 var $RELEASE = false;
michael@0 37780 var LoaderDefinition = function () {
michael@0 37781 var WORKERS_ENABLED = true;
michael@0 37782 var LOADER_PATH = true ? 'shumway-worker.js' : 'swf/resourceloader.js';
michael@0 37783 var head = document.head;
michael@0 37784 head.insertBefore(document.createElement('style'), head.firstChild);
michael@0 37785 var style = document.styleSheets[0];
michael@0 37786 var def = {
michael@0 37787 __class__: 'flash.display.Loader',
michael@0 37788 initialize: function () {
michael@0 37789 this._contentLoaderInfo = new flash.display.LoaderInfo();
michael@0 37790 this._contentLoaderInfo._loader = this;
michael@0 37791 this._dictionary = {};
michael@0 37792 this._dictionaryResolved = {};
michael@0 37793 this._displayList = null;
michael@0 37794 this._timeline = [];
michael@0 37795 this._lastPromise = null;
michael@0 37796 this._uncaughtErrorEvents = null;
michael@0 37797 this._worker = null;
michael@0 37798 var abc = AVM2.currentAbc();
michael@0 37799 if (abc && abc.env.loader) {
michael@0 37800 this._contentLoaderInfo._loaderURL = abc.env.loader._contentLoaderInfo._url;
michael@0 37801 }
michael@0 37802 },
michael@0 37803 _commitData: function (data) {
michael@0 37804 switch (data.command) {
michael@0 37805 case 'init':
michael@0 37806 this._init(data.result);
michael@0 37807 break;
michael@0 37808 case 'progress':
michael@0 37809 this._updateProgress(data.result);
michael@0 37810 break;
michael@0 37811 case 'complete':
michael@0 37812 var frameConstructed = new Promise(function (resolve) {
michael@0 37813 avm2.systemDomain.onMessage.register('frameConstructed', function waitForFrame(type) {
michael@0 37814 if (type === 'frameConstructed') {
michael@0 37815 resolve();
michael@0 37816 avm2.systemDomain.onMessage.unregister('frameConstructed', waitForFrame);
michael@0 37817 }
michael@0 37818 });
michael@0 37819 });
michael@0 37820 this._contentLoaderInfo._dispatchEvent('parsed');
michael@0 37821 Promise.all([
michael@0 37822 frameConstructed,
michael@0 37823 this._lastPromise
michael@0 37824 ]).then(function () {
michael@0 37825 this._content._complete = true;
michael@0 37826 this._contentLoaderInfo._dispatchEvent('complete');
michael@0 37827 }.bind(this));
michael@0 37828 var stats = data.stats;
michael@0 37829 if (stats) {
michael@0 37830 TelemetryService.reportTelemetry(stats);
michael@0 37831 }
michael@0 37832 this._worker && this._worker.terminate();
michael@0 37833 break;
michael@0 37834 case 'empty':
michael@0 37835 this._lastPromise = Promise.resolve();
michael@0 37836 break;
michael@0 37837 case 'error':
michael@0 37838 this._contentLoaderInfo._dispatchEvent('ioError', flash.events.IOErrorEvent);
michael@0 37839 break;
michael@0 37840 default:
michael@0 37841 if (data.id === 0)
michael@0 37842 break;
michael@0 37843 if (data.isSymbol)
michael@0 37844 this._commitSymbol(data);
michael@0 37845 else if (data.type === 'frame')
michael@0 37846 this._commitFrame(data);
michael@0 37847 else if (data.type === 'image')
michael@0 37848 this._commitImage(data);
michael@0 37849 break;
michael@0 37850 }
michael@0 37851 },
michael@0 37852 _updateProgress: function (state) {
michael@0 37853 var loaderInfo = this._contentLoaderInfo;
michael@0 37854 loaderInfo._bytesLoaded = state.bytesLoaded || 0;
michael@0 37855 loaderInfo._bytesTotal = state.bytesTotal || 0;
michael@0 37856 var event = new flash.events.ProgressEvent('progress', false, false, loaderInfo._bytesLoaded, loaderInfo._bytesTotal);
michael@0 37857 loaderInfo._dispatchEvent(event);
michael@0 37858 },
michael@0 37859 _buildFrame: function (currentDisplayList, timeline, promiseQueue, frame, frameNum) {
michael@0 37860 var loader = this;
michael@0 37861 var dictionary = loader._dictionary;
michael@0 37862 var dictionaryResolved = loader._dictionaryResolved;
michael@0 37863 var displayList = {};
michael@0 37864 var depths = [];
michael@0 37865 var cmds = frame.depths;
michael@0 37866 if (currentDisplayList) {
michael@0 37867 var currentDepths = currentDisplayList.depths;
michael@0 37868 for (var i = 0; i < currentDepths.length; i++) {
michael@0 37869 var depth = currentDepths[i];
michael@0 37870 if (cmds[depth] === null) {
michael@0 37871 continue;
michael@0 37872 }
michael@0 37873 displayList[depth] = currentDisplayList[depth];
michael@0 37874 depths.push(depth);
michael@0 37875 }
michael@0 37876 }
michael@0 37877 for (var depth in cmds) {
michael@0 37878 var cmd = cmds[depth];
michael@0 37879 if (!cmd) {
michael@0 37880 continue;
michael@0 37881 }
michael@0 37882 if (cmd.move) {
michael@0 37883 var oldCmd = cmd;
michael@0 37884 cmd = cloneObject(currentDisplayList[depth]);
michael@0 37885 for (var prop in oldCmd) {
michael@0 37886 var val = oldCmd[prop];
michael@0 37887 if (val) {
michael@0 37888 cmd[prop] = val;
michael@0 37889 }
michael@0 37890 }
michael@0 37891 }
michael@0 37892 if (cmd.symbolId) {
michael@0 37893 var itemPromise = dictionary[cmd.symbolId];
michael@0 37894 if (itemPromise && !dictionaryResolved[cmd.symbolId]) {
michael@0 37895 promiseQueue.push(itemPromise);
michael@0 37896 }
michael@0 37897 cmd = cloneObject(cmd);
michael@0 37898 Object.defineProperty(cmd, 'symbolInfo', {
michael@0 37899 get: function (dictionaryResolved, symbolId) {
michael@0 37900 return function () {
michael@0 37901 return dictionaryResolved[symbolId];
michael@0 37902 };
michael@0 37903 }(dictionaryResolved, cmd.symbolId)
michael@0 37904 });
michael@0 37905 }
michael@0 37906 if (!displayList[depth]) {
michael@0 37907 depths.push(depth);
michael@0 37908 }
michael@0 37909 displayList[depth] = cmd;
michael@0 37910 }
michael@0 37911 depths.sort(sortNumeric);
michael@0 37912 displayList.depths = depths;
michael@0 37913 var i = frame.repeat;
michael@0 37914 while (i--) {
michael@0 37915 timeline.push(displayList);
michael@0 37916 }
michael@0 37917 return displayList;
michael@0 37918 },
michael@0 37919 _commitFrame: function (frame) {
michael@0 37920 var abcBlocks = frame.abcBlocks;
michael@0 37921 var actionBlocks = frame.actionBlocks;
michael@0 37922 var initActionBlocks = frame.initActionBlocks;
michael@0 37923 var exports = frame.exports;
michael@0 37924 var symbolClasses = frame.symbolClasses;
michael@0 37925 var sceneData = frame.sceneData;
michael@0 37926 var loader = this;
michael@0 37927 var dictionary = loader._dictionary;
michael@0 37928 var loaderInfo = loader._contentLoaderInfo;
michael@0 37929 var timeline = loader._timeline;
michael@0 37930 var frameNum = timeline.length + 1;
michael@0 37931 var framePromiseResolve;
michael@0 37932 var framePromise = new Promise(function (resolve) {
michael@0 37933 framePromiseResolve = resolve;
michael@0 37934 });
michael@0 37935 var labelName = frame.labelName;
michael@0 37936 var prevPromise = this._lastPromise;
michael@0 37937 this._lastPromise = framePromise;
michael@0 37938 var promiseQueue = [
michael@0 37939 prevPromise
michael@0 37940 ];
michael@0 37941 this._displayList = this._buildFrame(this._displayList, timeline, promiseQueue, frame, frameNum);
michael@0 37942 var framesLoaded = timeline.length;
michael@0 37943 if (frame.bgcolor)
michael@0 37944 loaderInfo._backgroundColor = frame.bgcolor;
michael@0 37945 else if (isNullOrUndefined(loaderInfo._backgroundColor))
michael@0 37946 loaderInfo._backgroundColor = {
michael@0 37947 red: 255,
michael@0 37948 green: 255,
michael@0 37949 blue: 255,
michael@0 37950 alpha: 255
michael@0 37951 };
michael@0 37952 Promise.all(promiseQueue).then(function () {
michael@0 37953 if (abcBlocks && loader._isAvm2Enabled) {
michael@0 37954 var appDomain = avm2.applicationDomain;
michael@0 37955 for (var i = 0, n = abcBlocks.length; i < n; i++) {
michael@0 37956 var abc = new AbcFile(abcBlocks[i].data, 'abc_block_' + i);
michael@0 37957 abc.env.loader = loader;
michael@0 37958 if (abcBlocks[i].flags) {
michael@0 37959 appDomain.loadAbc(abc);
michael@0 37960 } else {
michael@0 37961 appDomain.executeAbc(abc);
michael@0 37962 }
michael@0 37963 }
michael@0 37964 }
michael@0 37965 if (symbolClasses && loader._isAvm2Enabled) {
michael@0 37966 var symbolClassesPromises = [];
michael@0 37967 for (var i = 0, n = symbolClasses.length; i < n; i++) {
michael@0 37968 var asset = symbolClasses[i];
michael@0 37969 var symbolPromise = dictionary[asset.symbolId];
michael@0 37970 if (!symbolPromise)
michael@0 37971 continue;
michael@0 37972 symbolPromise.then(function (className) {
michael@0 37973 return function symbolPromiseResolved(symbolInfo) {
michael@0 37974 symbolInfo.className = className;
michael@0 37975 avm2.applicationDomain.getClass(className).setSymbol(symbolInfo.props);
michael@0 37976 };
michael@0 37977 }(asset.className));
michael@0 37978 symbolClassesPromises.push(symbolPromise);
michael@0 37979 }
michael@0 37980 return Promise.all(symbolClassesPromises);
michael@0 37981 }
michael@0 37982 if (exports && !loader._isAvm2Enabled) {
michael@0 37983 var exportPromises = [];
michael@0 37984 for (var i = 0, n = exports.length; i < n; i++) {
michael@0 37985 var asset = exports[i];
michael@0 37986 var symbolPromise = dictionary[asset.symbolId];
michael@0 37987 if (!symbolPromise)
michael@0 37988 continue;
michael@0 37989 symbolPromise.then(function (className) {
michael@0 37990 return function symbolPromiseResolved(symbolInfo) {
michael@0 37991 loader._avm1Context.addAsset(className, symbolInfo.props);
michael@0 37992 };
michael@0 37993 }(asset.className));
michael@0 37994 exportPromises.push(symbolPromise);
michael@0 37995 }
michael@0 37996 return Promise.all(exportPromises);
michael@0 37997 }
michael@0 37998 }).then(function () {
michael@0 37999 var root = loader._content;
michael@0 38000 var labelMap;
michael@0 38001 if (!root) {
michael@0 38002 var parent = loader._parent;
michael@0 38003 true;
michael@0 38004 var rootInfo = loader._dictionaryResolved[0];
michael@0 38005 var rootClass = avm2.applicationDomain.getClass(rootInfo.className);
michael@0 38006 root = rootClass.createAsSymbol({
michael@0 38007 framesLoaded: framesLoaded,
michael@0 38008 loader: loader,
michael@0 38009 parent: parent || loader,
michael@0 38010 index: parent ? 0 : -1,
michael@0 38011 level: parent ? 0 : -1,
michael@0 38012 timeline: timeline,
michael@0 38013 totalFrames: rootInfo.props.totalFrames,
michael@0 38014 stage: loader._stage,
michael@0 38015 complete: frame.complete
michael@0 38016 });
michael@0 38017 if (!loader._isAvm2Enabled) {
michael@0 38018 var avm1Context = loader._avm1Context;
michael@0 38019 var _root = root;
michael@0 38020 if (parent && parent !== loader._stage) {
michael@0 38021 var parentLoader = parent.loaderInfo._loader;
michael@0 38022 while (parentLoader._parent && parentLoader._parent !== loader._stage) {
michael@0 38023 parentLoader = parentLoader._parent.loaderInfo._loader;
michael@0 38024 }
michael@0 38025 if (parentLoader._isAvm2Enabled) {
michael@0 38026 somewhatImplemented('AVM1Movie');
michael@0 38027 this._worker && this._worker.terminate();
michael@0 38028 return;
michael@0 38029 }
michael@0 38030 _root = parentLoader._content;
michael@0 38031 }
michael@0 38032 var as2Object = _root._getAS2Object();
michael@0 38033 avm1Context.globals.asSetPublicProperty('_root', as2Object);
michael@0 38034 avm1Context.globals.asSetPublicProperty('_level0', as2Object);
michael@0 38035 avm1Context.globals.asSetPublicProperty('_level1', as2Object);
michael@0 38036 var parameters = loader.loaderInfo._parameters;
michael@0 38037 for (var paramName in parameters) {
michael@0 38038 if (!(paramName in as2Object)) {
michael@0 38039 as2Object[paramName] = parameters[paramName];
michael@0 38040 }
michael@0 38041 }
michael@0 38042 }
michael@0 38043 var isRootMovie = parent && parent == loader._stage && loader._stage._children.length === 0;
michael@0 38044 if (isRootMovie) {
michael@0 38045 parent._frameRate = loaderInfo._frameRate;
michael@0 38046 parent._stageHeight = loaderInfo._height;
michael@0 38047 parent._stageWidth = loaderInfo._width;
michael@0 38048 parent._root = root;
michael@0 38049 parent._setup();
michael@0 38050 } else {
michael@0 38051 loader._children.push(root);
michael@0 38052 }
michael@0 38053 var labels;
michael@0 38054 labelMap = root.symbol.labelMap = createEmptyObject();
michael@0 38055 if (sceneData) {
michael@0 38056 var scenes = [];
michael@0 38057 var startFrame;
michael@0 38058 var endFrame = root.symbol.totalFrames - 1;
michael@0 38059 var sd = sceneData.scenes;
michael@0 38060 var ld = sceneData.labels;
michael@0 38061 var i = sd.length;
michael@0 38062 while (i--) {
michael@0 38063 var s = sd[i];
michael@0 38064 startFrame = s.offset;
michael@0 38065 labels = [];
michael@0 38066 var j = ld.length;
michael@0 38067 while (j--) {
michael@0 38068 var lbl = ld[j];
michael@0 38069 if (lbl.frame >= startFrame && lbl.frame <= endFrame) {
michael@0 38070 labelMap[lbl.name] = lbl.frame + 1;
michael@0 38071 labels.unshift(new flash.display.FrameLabel(lbl.name, lbl.frame - startFrame + 1));
michael@0 38072 }
michael@0 38073 }
michael@0 38074 var scene = new flash.display.Scene(s.name, labels, endFrame - startFrame + 1);
michael@0 38075 scene._startFrame = startFrame + 1;
michael@0 38076 scene._endFrame = endFrame + 1;
michael@0 38077 scenes.unshift(scene);
michael@0 38078 endFrame = startFrame - 1;
michael@0 38079 }
michael@0 38080 root.symbol.scenes = scenes;
michael@0 38081 } else {
michael@0 38082 labels = [];
michael@0 38083 if (labelName) {
michael@0 38084 labelMap[labelName] = frameNum;
michael@0 38085 labels.push(new flash.display.FrameLabel(labelName, frameNum));
michael@0 38086 }
michael@0 38087 var scene = new flash.display.Scene('Scene 1', labels, root.symbol.totalFrames);
michael@0 38088 scene._startFrame = 1;
michael@0 38089 scene._endFrame = root.symbol.totalFrames;
michael@0 38090 root.symbol.scenes = [
michael@0 38091 scene
michael@0 38092 ];
michael@0 38093 }
michael@0 38094 if (loader._stage) {
michael@0 38095 loader._stage._children[0] = root;
michael@0 38096 }
michael@0 38097 rootClass.instanceConstructor.call(root);
michael@0 38098 loader._content = root;
michael@0 38099 } else {
michael@0 38100 root._framesLoaded = framesLoaded;
michael@0 38101 if (labelName && root._labelMap) {
michael@0 38102 if (root._labelMap[labelName] === undefined) {
michael@0 38103 root._labelMap[labelName] = frameNum;
michael@0 38104 for (var i = 0, n = root.symbol.scenes.length; i < n; i++) {
michael@0 38105 var scene = root.symbol.scenes[i];
michael@0 38106 if (frameNum >= scene._startFrame && frameNum <= scene._endFrame) {
michael@0 38107 scene.labels.push(new flash.display.FrameLabel(labelName, frameNum - scene._startFrame));
michael@0 38108 break;
michael@0 38109 }
michael@0 38110 }
michael@0 38111 }
michael@0 38112 }
michael@0 38113 }
michael@0 38114 if (frame.startSounds) {
michael@0 38115 root._registerStartSounds(frameNum, frame.startSounds);
michael@0 38116 }
michael@0 38117 if (frame.soundStream) {
michael@0 38118 root._initSoundStream(frame.soundStream);
michael@0 38119 }
michael@0 38120 if (frame.soundStreamBlock) {
michael@0 38121 root._addSoundStreamBlock(frameNum, frame.soundStreamBlock);
michael@0 38122 }
michael@0 38123 if (!loader._isAvm2Enabled) {
michael@0 38124 var avm1Context = loader._avm1Context;
michael@0 38125 if (initActionBlocks) {
michael@0 38126 for (var i = 0; i < initActionBlocks.length; i++) {
michael@0 38127 var spriteId = initActionBlocks[i].spriteId;
michael@0 38128 var actionsData = initActionBlocks[i].actionsData;
michael@0 38129 root.addFrameScript(frameNum - 1, function (actionsData, spriteId, state) {
michael@0 38130 if (state.executed)
michael@0 38131 return;
michael@0 38132 state.executed = true;
michael@0 38133 return executeActions(actionsData, avm1Context, this._getAS2Object());
michael@0 38134 }.bind(root, actionsData, spriteId, {
michael@0 38135 executed: false
michael@0 38136 }));
michael@0 38137 }
michael@0 38138 }
michael@0 38139 if (actionBlocks) {
michael@0 38140 for (var i = 0; i < actionBlocks.length; i++) {
michael@0 38141 var block = actionBlocks[i];
michael@0 38142 root.addFrameScript(frameNum - 1, function (block) {
michael@0 38143 return function () {
michael@0 38144 return executeActions(block, avm1Context, this._getAS2Object());
michael@0 38145 };
michael@0 38146 }(block));
michael@0 38147 }
michael@0 38148 }
michael@0 38149 }
michael@0 38150 if (frameNum === 1)
michael@0 38151 loaderInfo._dispatchEvent(new flash.events.Event('init', false, false));
michael@0 38152 framePromiseResolve(frame);
michael@0 38153 });
michael@0 38154 },
michael@0 38155 _commitImage: function (imageInfo) {
michael@0 38156 var loader = this;
michael@0 38157 var imgPromiseResolve;
michael@0 38158 var imgPromise = this._lastPromise = new Promise(function (resolve) {
michael@0 38159 imgPromiseResolve = resolve;
michael@0 38160 });
michael@0 38161 var img = new Image();
michael@0 38162 imageInfo.props.img = img;
michael@0 38163 img.onload = function () {
michael@0 38164 var Bitmap = avm2.systemDomain.getClass('flash.display.Bitmap');
michael@0 38165 var BitmapData = avm2.systemDomain.getClass('flash.display.BitmapData');
michael@0 38166 var props = imageInfo.props;
michael@0 38167 props.parent = loader._parent;
michael@0 38168 props.stage = loader._stage;
michael@0 38169 props.skipCopyToCanvas = true;
michael@0 38170 var bitmapData = BitmapData.createAsSymbol(props);
michael@0 38171 BitmapData.instanceConstructor.call(bitmapData, 0, 0, true, 4294967295);
michael@0 38172 var image = Bitmap.createAsSymbol(bitmapData);
michael@0 38173 Bitmap.instanceConstructor.call(image, bitmapData);
michael@0 38174 image._parent = loader;
michael@0 38175 loader._children.push(image);
michael@0 38176 loader._invalidateBounds();
michael@0 38177 loader._content = image;
michael@0 38178 imgPromiseResolve(imageInfo);
michael@0 38179 var loaderInfo = loader._contentLoaderInfo;
michael@0 38180 loaderInfo._width = image.width;
michael@0 38181 loaderInfo._height = image.height;
michael@0 38182 loaderInfo._dispatchEvent('init');
michael@0 38183 };
michael@0 38184 img.src = URL.createObjectURL(imageInfo.data);
michael@0 38185 imageInfo.data = null;
michael@0 38186 },
michael@0 38187 _commitSymbol: function (symbol) {
michael@0 38188 var dictionary = this._dictionary;
michael@0 38189 var dictionaryResolved = this._dictionaryResolved;
michael@0 38190 if ('updates' in symbol) {
michael@0 38191 dictionary[symbol.id].then(function (s) {
michael@0 38192 for (var i in symbol.updates) {
michael@0 38193 s.props[i] = symbol.updates[i];
michael@0 38194 }
michael@0 38195 });
michael@0 38196 return;
michael@0 38197 }
michael@0 38198 var className = 'flash.display.DisplayObject';
michael@0 38199 var dependencies = symbol.require;
michael@0 38200 var promiseQueue = [];
michael@0 38201 var props = {
michael@0 38202 symbolId: symbol.id,
michael@0 38203 loader: this
michael@0 38204 };
michael@0 38205 var symbolPromiseResolve;
michael@0 38206 var symbolPromise = new Promise(function (resolve) {
michael@0 38207 symbolPromiseResolve = resolve;
michael@0 38208 });
michael@0 38209 if (dependencies && dependencies.length) {
michael@0 38210 for (var i = 0, n = dependencies.length; i < n; i++) {
michael@0 38211 var dependencyId = dependencies[i];
michael@0 38212 var dependencyPromise = dictionary[dependencyId];
michael@0 38213 if (dependencyPromise && !dictionaryResolved[dependencyId])
michael@0 38214 promiseQueue.push(dependencyPromise);
michael@0 38215 }
michael@0 38216 }
michael@0 38217 switch (symbol.type) {
michael@0 38218 case 'button':
michael@0 38219 var states = {};
michael@0 38220 for (var stateName in symbol.states) {
michael@0 38221 var characters = [];
michael@0 38222 var displayList = {};
michael@0 38223 var state = symbol.states[stateName];
michael@0 38224 var depths = Object.keys(state);
michael@0 38225 for (var i = 0; i < depths.length; i++) {
michael@0 38226 var depth = depths[i];
michael@0 38227 var cmd = state[depth];
michael@0 38228 var characterPromise = dictionary[cmd.symbolId];
michael@0 38229 if (characterPromise && !dictionaryResolved[cmd.symbolId]) {
michael@0 38230 promiseQueue.push(characterPromise);
michael@0 38231 }
michael@0 38232 characters.push(characterPromise);
michael@0 38233 displayList[depth] = Object.create(cmd, {
michael@0 38234 symbolInfo: {
michael@0 38235 get: function (dictionaryResolved, symbolId) {
michael@0 38236 return function () {
michael@0 38237 return dictionaryResolved[symbolId];
michael@0 38238 };
michael@0 38239 }(dictionaryResolved, cmd.symbolId)
michael@0 38240 }
michael@0 38241 });
michael@0 38242 }
michael@0 38243 depths.sort(sortNumeric);
michael@0 38244 displayList.depths = depths;
michael@0 38245 states[stateName] = {
michael@0 38246 className: 'flash.display.Sprite',
michael@0 38247 props: {
michael@0 38248 loader: this,
michael@0 38249 timeline: [
michael@0 38250 displayList
michael@0 38251 ]
michael@0 38252 }
michael@0 38253 };
michael@0 38254 }
michael@0 38255 className = 'flash.display.SimpleButton';
michael@0 38256 props.states = states;
michael@0 38257 props.buttonActions = symbol.buttonActions;
michael@0 38258 break;
michael@0 38259 case 'font':
michael@0 38260 var charset = fromCharCode.apply(null, symbol.codes);
michael@0 38261 if (charset) {
michael@0 38262 style.insertRule('@font-face{font-family:"' + symbol.uniqueName + '";' + 'src:url(data:font/opentype;base64,' + btoa(symbol.data) + ')' + '}', style.cssRules.length);
michael@0 38263 if (!/Mozilla\/5.0.*?rv:(\d+).*? Gecko/.test(window.navigator.userAgent)) {
michael@0 38264 var testDiv = document.createElement('div');
michael@0 38265 testDiv.setAttribute('style', 'position: absolute; top: 0; right: 0;visibility: hidden; z-index: -500;font-family:"' + symbol.uniqueName + '";');
michael@0 38266 testDiv.textContent = 'font test';
michael@0 38267 document.body.appendChild(testDiv);
michael@0 38268 var fontPromise = new Promise(function (resolve) {
michael@0 38269 setTimeout(function () {
michael@0 38270 resolve();
michael@0 38271 document.body.removeChild(testDiv);
michael@0 38272 }, 200);
michael@0 38273 });
michael@0 38274 promiseQueue.push(fontPromise);
michael@0 38275 }
michael@0 38276 }
michael@0 38277 className = 'flash.text.Font';
michael@0 38278 props.name = symbol.name;
michael@0 38279 props.uniqueName = symbol.uniqueName;
michael@0 38280 props.charset = symbol.charset;
michael@0 38281 props.bold = symbol.bold;
michael@0 38282 props.italic = symbol.italic;
michael@0 38283 props.metrics = symbol.metrics;
michael@0 38284 this._registerFont(className, props);
michael@0 38285 break;
michael@0 38286 case 'image':
michael@0 38287 var img = new Image();
michael@0 38288 var imgPromiseResolve;
michael@0 38289 var imgPromise = new Promise(function (resolve) {
michael@0 38290 imgPromiseResolve = resolve;
michael@0 38291 });
michael@0 38292 img.onload = function () {
michael@0 38293 if (symbol.mask) {
michael@0 38294 var maskCanvas = document.createElement('canvas');
michael@0 38295 maskCanvas.width = symbol.width;
michael@0 38296 maskCanvas.height = symbol.height;
michael@0 38297 var maskContext = maskCanvas.getContext('2d');
michael@0 38298 maskContext.drawImage(img, 0, 0);
michael@0 38299 var maskImageData = maskContext.getImageData(0, 0, symbol.width, symbol.height);
michael@0 38300 var maskImageDataBytes = maskImageData.data;
michael@0 38301 var symbolMaskBytes = symbol.mask;
michael@0 38302 var length = maskImageData.width * maskImageData.height;
michael@0 38303 for (var i = 0, j = 3; i < length; i++, j += 4) {
michael@0 38304 maskImageDataBytes[j] = symbolMaskBytes[i];
michael@0 38305 }
michael@0 38306 maskContext.putImageData(maskImageData, 0, 0);
michael@0 38307 props.img = maskCanvas;
michael@0 38308 }
michael@0 38309 imgPromiseResolve();
michael@0 38310 };
michael@0 38311 img.src = URL.createObjectURL(symbol.data);
michael@0 38312 promiseQueue.push(imgPromise);
michael@0 38313 className = 'flash.display.Bitmap';
michael@0 38314 props.img = img;
michael@0 38315 props.width = symbol.width;
michael@0 38316 props.height = symbol.height;
michael@0 38317 break;
michael@0 38318 case 'label':
michael@0 38319 var drawFn = new Function('c,r,ct', symbol.data);
michael@0 38320 className = 'flash.text.StaticText';
michael@0 38321 props.bbox = symbol.bbox;
michael@0 38322 props.draw = drawFn;
michael@0 38323 break;
michael@0 38324 case 'text':
michael@0 38325 props.bbox = symbol.bbox;
michael@0 38326 props.html = symbol.html;
michael@0 38327 if (symbol.type === 'label') {
michael@0 38328 className = 'flash.text.StaticText';
michael@0 38329 } else {
michael@0 38330 className = 'flash.text.TextField';
michael@0 38331 props.tag = symbol.tag;
michael@0 38332 props.variableName = symbol.variableName;
michael@0 38333 }
michael@0 38334 break;
michael@0 38335 case 'shape':
michael@0 38336 className = symbol.morph ? 'flash.display.MorphShape' : 'flash.display.Shape';
michael@0 38337 props.bbox = symbol.bbox;
michael@0 38338 props.strokeBbox = symbol.strokeBbox;
michael@0 38339 props.paths = symbol.paths;
michael@0 38340 props.dictionaryResolved = dictionaryResolved;
michael@0 38341 break;
michael@0 38342 case 'sound':
michael@0 38343 if (!symbol.pcm && !PLAY_USING_AUDIO_TAG) {
michael@0 38344 var decodePromiseResolve;
michael@0 38345 var decodePromise = new Promise(function (resolve) {
michael@0 38346 decodePromiseResolve = resolve;
michael@0 38347 });
michael@0 38348 MP3DecoderSession.processAll(symbol.packaged.data, function (props, pcm, id3tags, error) {
michael@0 38349 props.pcm = pcm || new Uint8Array(0);
michael@0 38350 decodePromiseResolve();
michael@0 38351 if (error) {
michael@0 38352 console.error('ERROR: ' + error);
michael@0 38353 }
michael@0 38354 }.bind(null, props));
michael@0 38355 promiseQueue.push(decodePromise);
michael@0 38356 }
michael@0 38357 className = 'flash.media.Sound';
michael@0 38358 props.sampleRate = symbol.sampleRate;
michael@0 38359 props.channels = symbol.channels;
michael@0 38360 props.pcm = symbol.pcm;
michael@0 38361 props.packaged = symbol.packaged;
michael@0 38362 break;
michael@0 38363 case 'binary':
michael@0 38364 props.data = symbol.data;
michael@0 38365 break;
michael@0 38366 case 'sprite':
michael@0 38367 var displayList = null;
michael@0 38368 var frameCount = symbol.frameCount;
michael@0 38369 var labelMap = {};
michael@0 38370 var frameNum = 1;
michael@0 38371 var frames = symbol.frames;
michael@0 38372 var timeline = [];
michael@0 38373 var startSoundRegistrations = [];
michael@0 38374 for (var i = 0, n = frames.length; i < n; i++) {
michael@0 38375 var frame = frames[i];
michael@0 38376 var frameNum = timeline.length + 1;
michael@0 38377 if (frame.labelName) {
michael@0 38378 labelMap[frame.labelName] = frameNum;
michael@0 38379 }
michael@0 38380 if (frame.startSounds) {
michael@0 38381 startSoundRegistrations[frameNum] = frame.startSounds;
michael@0 38382 for (var j = 0; j < frame.startSounds.length; j++) {
michael@0 38383 var soundId = frame.startSounds[j].soundId;
michael@0 38384 var itemPromise = dictionary[soundId];
michael@0 38385 if (itemPromise && !dictionaryResolved[soundId]) {
michael@0 38386 promiseQueue.push(itemPromise);
michael@0 38387 }
michael@0 38388 }
michael@0 38389 }
michael@0 38390 displayList = this._buildFrame(displayList, timeline, promiseQueue, frame, frameNum);
michael@0 38391 }
michael@0 38392 var frameScripts = {};
michael@0 38393 if (!this._isAvm2Enabled) {
michael@0 38394 if (symbol.frameScripts) {
michael@0 38395 var data = symbol.frameScripts;
michael@0 38396 for (var i = 0; i < data.length; i += 2) {
michael@0 38397 var frameNum = data[i] + 1;
michael@0 38398 var block = data[i + 1];
michael@0 38399 var script = function (block, loader) {
michael@0 38400 return function () {
michael@0 38401 var avm1Context = loader._avm1Context;
michael@0 38402 return executeActions(block, avm1Context, this._getAS2Object());
michael@0 38403 };
michael@0 38404 }(block, this);
michael@0 38405 if (!frameScripts[frameNum])
michael@0 38406 frameScripts[frameNum] = [
michael@0 38407 script
michael@0 38408 ];
michael@0 38409 else
michael@0 38410 frameScripts[frameNum].push(script);
michael@0 38411 }
michael@0 38412 }
michael@0 38413 }
michael@0 38414 className = 'flash.display.MovieClip';
michael@0 38415 props.timeline = timeline;
michael@0 38416 props.framesLoaded = frameCount;
michael@0 38417 props.labelMap = labelMap;
michael@0 38418 props.frameScripts = frameScripts;
michael@0 38419 props.totalFrames = frameCount;
michael@0 38420 props.startSoundRegistrations = startSoundRegistrations;
michael@0 38421 break;
michael@0 38422 }
michael@0 38423 dictionary[symbol.id] = symbolPromise;
michael@0 38424 Promise.all(promiseQueue).then(function () {
michael@0 38425 var symbolInfo = {
michael@0 38426 className: className,
michael@0 38427 props: props
michael@0 38428 };
michael@0 38429 dictionaryResolved[symbol.id] = symbolInfo;
michael@0 38430 symbolPromiseResolve(symbolInfo);
michael@0 38431 });
michael@0 38432 },
michael@0 38433 _registerFont: function (className, props) {
michael@0 38434 this._vmPromise.then(function () {
michael@0 38435 var fontClass = avm2.applicationDomain.getClass(className);
michael@0 38436 var font = fontClass.createAsSymbol(props);
michael@0 38437 fontClass.instanceConstructor.call(font);
michael@0 38438 });
michael@0 38439 },
michael@0 38440 _init: function (info) {
michael@0 38441 var loader = this;
michael@0 38442 var loaderInfo = loader._contentLoaderInfo;
michael@0 38443 loaderInfo._swfVersion = info.swfVersion;
michael@0 38444 var bbox = info.bbox;
michael@0 38445 loaderInfo._width = bbox.xMax - bbox.xMin;
michael@0 38446 loaderInfo._height = bbox.yMax - bbox.yMin;
michael@0 38447 loaderInfo._frameRate = info.frameRate;
michael@0 38448 var vmPromiseResolve, vmPromiseReject;
michael@0 38449 var vmPromise = new Promise(function (resolve, reject) {
michael@0 38450 vmPromiseResolve = resolve;
michael@0 38451 vmPromiseReject = reject;
michael@0 38452 });
michael@0 38453 vmPromise.resolve = vmPromiseResolve;
michael@0 38454 vmPromise.reject = vmPromiseReject;
michael@0 38455 var documentPromise = new Promise(function (resolve) {
michael@0 38456 vmPromise.then(function () {
michael@0 38457 var rootInfo = {
michael@0 38458 className: 'flash.display.MovieClip',
michael@0 38459 props: {
michael@0 38460 totalFrames: info.frameCount
michael@0 38461 }
michael@0 38462 };
michael@0 38463 loader._dictionaryResolved[0] = rootInfo;
michael@0 38464 resolve(rootInfo);
michael@0 38465 });
michael@0 38466 });
michael@0 38467 loader._dictionary[0] = documentPromise;
michael@0 38468 loader._lastPromise = documentPromise;
michael@0 38469 loader._vmPromise = vmPromise;
michael@0 38470 loader._isAvm2Enabled = info.fileAttributes.doAbc;
michael@0 38471 this._setup();
michael@0 38472 },
michael@0 38473 _load: function (request, checkPolicyFile, applicationDomain, securityDomain, requestedContentParent, parameters, deblockingFilter, allowCodeImport, imageDecodingPolicy) {
michael@0 38474 if (flash.net.URLRequest.class.isInstanceOf(request)) {
michael@0 38475 this._contentLoaderInfo._url = request._url;
michael@0 38476 }
michael@0 38477 var worker;
michael@0 38478 if (WORKERS_ENABLED) {
michael@0 38479 worker = new Worker(SHUMWAY_ROOT + LOADER_PATH);
michael@0 38480 } else {
michael@0 38481 worker = new ResourceLoader(window);
michael@0 38482 }
michael@0 38483 var loader = this;
michael@0 38484 loader._worker = worker;
michael@0 38485 worker.onmessage = function (evt) {
michael@0 38486 if (evt.data.type === 'exception') {
michael@0 38487 avm2.exceptions.push({
michael@0 38488 source: 'parser',
michael@0 38489 message: evt.data.message,
michael@0 38490 stack: evt.data.stack
michael@0 38491 });
michael@0 38492 } else {
michael@0 38493 loader._commitData(evt.data);
michael@0 38494 }
michael@0 38495 };
michael@0 38496 if (flash.net.URLRequest.class.isInstanceOf(request)) {
michael@0 38497 var session = FileLoadingService.createSession();
michael@0 38498 session.onprogress = function (data, progress) {
michael@0 38499 worker.postMessage({
michael@0 38500 data: data,
michael@0 38501 progress: progress
michael@0 38502 });
michael@0 38503 };
michael@0 38504 session.onerror = function (error) {
michael@0 38505 loader._commitData({
michael@0 38506 command: 'error',
michael@0 38507 error: error
michael@0 38508 });
michael@0 38509 };
michael@0 38510 session.onopen = function () {
michael@0 38511 worker.postMessage('pipe:');
michael@0 38512 };
michael@0 38513 session.onclose = function () {
michael@0 38514 worker.postMessage({
michael@0 38515 data: null
michael@0 38516 });
michael@0 38517 };
michael@0 38518 session.open(request._toFileRequest());
michael@0 38519 } else {
michael@0 38520 worker.postMessage(request);
michael@0 38521 }
michael@0 38522 },
michael@0 38523 _setup: function () {
michael@0 38524 var loader = this;
michael@0 38525 var stage = loader._stage;
michael@0 38526 if (loader._isAvm2Enabled) {
michael@0 38527 var mouseClass = avm2.systemDomain.getClass('flash.ui.Mouse');
michael@0 38528 mouseClass._stage = stage;
michael@0 38529 loader._vmPromise.resolve();
michael@0 38530 return;
michael@0 38531 }
michael@0 38532 if (!avm2.loadAVM1) {
michael@0 38533 loader._vmPromise.reject('AVM1 loader is not found');
michael@0 38534 return;
michael@0 38535 }
michael@0 38536 var loaded = function () {
michael@0 38537 var loaderInfo = loader._contentLoaderInfo;
michael@0 38538 var avm1Context = new AS2Context(loaderInfo._swfVersion);
michael@0 38539 avm1Context.stage = stage;
michael@0 38540 loader._avm1Context = avm1Context;
michael@0 38541 avm1lib.AS2Key.class.$bind(stage);
michael@0 38542 avm1lib.AS2Mouse.class.$bind(stage);
michael@0 38543 stage._addEventListener('frameConstructed', avm1Context.flushPendingScripts.bind(avm1Context), false, Number.MAX_VALUE);
michael@0 38544 loader._vmPromise.resolve();
michael@0 38545 };
michael@0 38546 if (avm2.isAVM1Loaded) {
michael@0 38547 if (AS2Context.instance) {
michael@0 38548 loader._avm1Context = AS2Context.instance;
michael@0 38549 loader._vmPromise.resolve();
michael@0 38550 } else {
michael@0 38551 loaded();
michael@0 38552 }
michael@0 38553 } else {
michael@0 38554 avm2.isAVM1Loaded = true;
michael@0 38555 avm2.loadAVM1(loaded);
michael@0 38556 }
michael@0 38557 },
michael@0 38558 get contentLoaderInfo() {
michael@0 38559 return this._contentLoaderInfo;
michael@0 38560 },
michael@0 38561 get content() {
michael@0 38562 somewhatImplemented('Loader.content');
michael@0 38563 return this._content;
michael@0 38564 }
michael@0 38565 };
michael@0 38566 def.__glue__ = {
michael@0 38567 native: {
michael@0 38568 instance: {
michael@0 38569 content: Object.getOwnPropertyDescriptor(def, 'content'),
michael@0 38570 contentLoaderInfo: Object.getOwnPropertyDescriptor(def, 'contentLoaderInfo'),
michael@0 38571 _getJPEGLoaderContextdeblockingfilter: function (context) {
michael@0 38572 return 0;
michael@0 38573 },
michael@0 38574 _load: def._load,
michael@0 38575 _loadBytes: function _loadBytes(bytes, checkPolicyFile, applicationDomain, securityDomain, requestedContentParent, parameters, deblockingFilter, allowLoadBytesCodeExecution, imageDecodingPolicy) {
michael@0 38576 this._load(bytes.a, checkPolicyFile, applicationDomain, securityDomain, requestedContentParent, parameters, deblockingFilter, allowLoadBytesCodeExecution, imageDecodingPolicy);
michael@0 38577 },
michael@0 38578 _unload: function _unload(halt, gc) {
michael@0 38579 somewhatImplemented('Loader._unload, do we even need to do anything here?');
michael@0 38580 },
michael@0 38581 _close: function _close() {
michael@0 38582 somewhatImplemented('Loader._close');
michael@0 38583 },
michael@0 38584 _getUncaughtErrorEvents: function _getUncaughtErrorEvents() {
michael@0 38585 somewhatImplemented('Loader._getUncaughtErrorEvents');
michael@0 38586 return this._uncaughtErrorEvents;
michael@0 38587 },
michael@0 38588 _setUncaughtErrorEvents: function _setUncaughtErrorEvents(value) {
michael@0 38589 somewhatImplemented('Loader._setUncaughtErrorEvents');
michael@0 38590 this._uncaughtErrorEvents = value;
michael@0 38591 }
michael@0 38592 }
michael@0 38593 }
michael@0 38594 };
michael@0 38595 return def;
michael@0 38596 }.call(this);
michael@0 38597 var LoaderInfoDefinition = function () {
michael@0 38598 function dispatchEvent(event) {
michael@0 38599 notImplemented('LoaderInfo.dispatchEvent');
michael@0 38600 }
michael@0 38601 return {
michael@0 38602 __class__: 'flash.display.LoaderInfo',
michael@0 38603 initialize: function () {
michael@0 38604 this._actionScriptVersion = null;
michael@0 38605 this._backgroundColor = null;
michael@0 38606 this._bytes = null;
michael@0 38607 this._bytesLoaded = 0;
michael@0 38608 this._bytesTotal = 0;
michael@0 38609 this._content = null;
michael@0 38610 this._contentType = null;
michael@0 38611 this._frameRate = null;
michael@0 38612 this._height = null;
michael@0 38613 this._loader = null;
michael@0 38614 this._loaderURL = null;
michael@0 38615 this._swfVersion = null;
michael@0 38616 this._url = null;
michael@0 38617 this._width = null;
michael@0 38618 this._uncaughtErrorEvents = null;
michael@0 38619 },
michael@0 38620 __glue__: {
michael@0 38621 native: {
michael@0 38622 static: {
michael@0 38623 getLoaderInfoByDefinition: function getLoaderInfoByDefinition(object) {
michael@0 38624 notImplemented('LoaderInfo.getLoaderInfoByDefinition');
michael@0 38625 }
michael@0 38626 },
michael@0 38627 instance: {
michael@0 38628 _getArgs: function _getArgs() {
michael@0 38629 var params = this._parameters;
michael@0 38630 var mangled = {};
michael@0 38631 for (var k in params) {
michael@0 38632 mangled[Multiname.getPublicQualifiedName(k)] = params[k];
michael@0 38633 }
michael@0 38634 return mangled;
michael@0 38635 },
michael@0 38636 _getUncaughtErrorEvents: function _getUncaughtErrorEvents() {
michael@0 38637 somewhatImplemented('Loader._getUncaughtErrorEvents');
michael@0 38638 return this._uncaughtErrorEvents;
michael@0 38639 },
michael@0 38640 _setUncaughtErrorEvents: function _setUncaughtErrorEvents(value) {
michael@0 38641 somewhatImplemented('Loader._setUncaughtErrorEvents');
michael@0 38642 this._uncaughtErrorEvents = value;
michael@0 38643 },
michael@0 38644 loaderURL: {
michael@0 38645 get: function loaderURL() {
michael@0 38646 return this._loaderURL;
michael@0 38647 }
michael@0 38648 },
michael@0 38649 url: {
michael@0 38650 get: function url() {
michael@0 38651 return this._url;
michael@0 38652 }
michael@0 38653 },
michael@0 38654 isURLInaccessible: {
michael@0 38655 get: function isURLInaccessible() {
michael@0 38656 return this._isURLInaccessible;
michael@0 38657 }
michael@0 38658 },
michael@0 38659 bytesLoaded: {
michael@0 38660 get: function bytesLoaded() {
michael@0 38661 return this._bytesLoaded;
michael@0 38662 }
michael@0 38663 },
michael@0 38664 bytesTotal: {
michael@0 38665 get: function bytesTotal() {
michael@0 38666 return this._bytesTotal;
michael@0 38667 }
michael@0 38668 },
michael@0 38669 applicationDomain: {
michael@0 38670 get: function applicationDomain() {
michael@0 38671 return new flash.system.ApplicationDomain(avm2.applicationDomain);
michael@0 38672 }
michael@0 38673 },
michael@0 38674 swfVersion: {
michael@0 38675 get: function swfVersion() {
michael@0 38676 return this._swfVersion;
michael@0 38677 }
michael@0 38678 },
michael@0 38679 actionScriptVersion: {
michael@0 38680 get: function actionScriptVersion() {
michael@0 38681 return this._actionScriptVersion;
michael@0 38682 }
michael@0 38683 },
michael@0 38684 frameRate: {
michael@0 38685 get: function frameRate() {
michael@0 38686 return this._frameRate;
michael@0 38687 }
michael@0 38688 },
michael@0 38689 width: {
michael@0 38690 get: function width() {
michael@0 38691 return this._width;
michael@0 38692 }
michael@0 38693 },
michael@0 38694 height: {
michael@0 38695 get: function height() {
michael@0 38696 return this._height;
michael@0 38697 }
michael@0 38698 },
michael@0 38699 contentType: {
michael@0 38700 get: function contentType() {
michael@0 38701 return this._contentType;
michael@0 38702 }
michael@0 38703 },
michael@0 38704 sharedEvents: {
michael@0 38705 get: function sharedEvents() {
michael@0 38706 return this._sharedEvents;
michael@0 38707 }
michael@0 38708 },
michael@0 38709 parentSandboxBridge: {
michael@0 38710 get: function parentSandboxBridge() {
michael@0 38711 return this._parentSandboxBridge;
michael@0 38712 },
michael@0 38713 set: function parentSandboxBridge(door) {
michael@0 38714 this._parentSandboxBridge = door;
michael@0 38715 }
michael@0 38716 },
michael@0 38717 childSandboxBridge: {
michael@0 38718 get: function childSandboxBridge() {
michael@0 38719 return this._childSandboxBridge;
michael@0 38720 },
michael@0 38721 set: function childSandboxBridge(door) {
michael@0 38722 this._childSandboxBridge = door;
michael@0 38723 }
michael@0 38724 },
michael@0 38725 sameDomain: {
michael@0 38726 get: function sameDomain() {
michael@0 38727 return this._sameDomain;
michael@0 38728 }
michael@0 38729 },
michael@0 38730 childAllowsParent: {
michael@0 38731 get: function childAllowsParent() {
michael@0 38732 return this._childAllowsParent;
michael@0 38733 }
michael@0 38734 },
michael@0 38735 parentAllowsChild: {
michael@0 38736 get: function parentAllowsChild() {
michael@0 38737 return this._parentAllowsChild;
michael@0 38738 }
michael@0 38739 },
michael@0 38740 loader: {
michael@0 38741 get: function loader() {
michael@0 38742 return this._loader;
michael@0 38743 }
michael@0 38744 },
michael@0 38745 content: {
michael@0 38746 get: function content() {
michael@0 38747 return this._loader._content;
michael@0 38748 }
michael@0 38749 },
michael@0 38750 bytes: {
michael@0 38751 get: function bytes() {
michael@0 38752 return this._bytes;
michael@0 38753 }
michael@0 38754 }
michael@0 38755 }
michael@0 38756 },
michael@0 38757 script: {
michael@0 38758 instance: scriptProperties('public', [
michael@0 38759 'swfVersion',
michael@0 38760 'bytesTotal',
michael@0 38761 'bytesLoaded',
michael@0 38762 'parameters',
michael@0 38763 'uncaughtErrorEvent'
michael@0 38764 ])
michael@0 38765 }
michael@0 38766 }
michael@0 38767 };
michael@0 38768 }.call(this);
michael@0 38769 var MorphShapeDefinition = function () {
michael@0 38770 var def = {
michael@0 38771 __class__: 'flash.display.MorphShape',
michael@0 38772 initialize: function () {
michael@0 38773 var graphics = this._graphics = new flash.display.Graphics();
michael@0 38774 var s = this.symbol;
michael@0 38775 if (s && s.paths) {
michael@0 38776 graphics._paths = s.paths;
michael@0 38777 graphics.bbox = s.bbox;
michael@0 38778 graphics.strokeBbox = s.strokeBbox;
michael@0 38779 if (this._stage && this._stage._quality === 'low' && !graphics._bitmap)
michael@0 38780 graphics._cacheAsBitmap(this._bbox);
michael@0 38781 }
michael@0 38782 }
michael@0 38783 };
michael@0 38784 def.__glue__ = {
michael@0 38785 native: {
michael@0 38786 instance: {
michael@0 38787 graphics: {
michael@0 38788 get: function () {
michael@0 38789 return this._graphics;
michael@0 38790 }
michael@0 38791 }
michael@0 38792 }
michael@0 38793 }
michael@0 38794 };
michael@0 38795 return def;
michael@0 38796 }.call(this);
michael@0 38797 var MovieClipDefinition = function () {
michael@0 38798 var def = {
michael@0 38799 __class__: 'flash.display.MovieClip',
michael@0 38800 initialize: function () {
michael@0 38801 this._playHead = 1;
michael@0 38802 this._currentFrame = 1;
michael@0 38803 this._currentFrameLabel = null;
michael@0 38804 this._currentLabel = null;
michael@0 38805 this._currentScene = 0;
michael@0 38806 this._enabled = true;
michael@0 38807 this._frameScripts = {};
michael@0 38808 this._framesLoaded = 1;
michael@0 38809 this._isPlaying = false;
michael@0 38810 this._labelMap = {};
michael@0 38811 this._sceneFrameMap = {};
michael@0 38812 this._sceneMap = {};
michael@0 38813 this._scenes = null;
michael@0 38814 this._timeline = null;
michael@0 38815 this._totalFrames = 1;
michael@0 38816 this._startSoundRegistrations = [];
michael@0 38817 this._allowFrameNavigation = true;
michael@0 38818 this._complete = true;
michael@0 38819 var s = this.symbol;
michael@0 38820 if (s) {
michael@0 38821 this._timeline = s.timeline || null;
michael@0 38822 this._framesLoaded = s.framesLoaded || 1;
michael@0 38823 this._labelMap = Object.create(s.labelMap || null);
michael@0 38824 this._frameScripts = Object.create(s.frameScripts || null);
michael@0 38825 this._totalFrames = s.totalFrames || 1;
michael@0 38826 this._startSoundRegistrations = s.startSoundRegistrations || [];
michael@0 38827 this._scenes = s.scenes || null;
michael@0 38828 this._complete = s.complete === false ? false : true;
michael@0 38829 var map = this._labelMap;
michael@0 38830 for (var name in map) {
michael@0 38831 var frame = map[name];
michael@0 38832 if (frame == 1) {
michael@0 38833 this._currentFrameLabel = this._currentLabel = name;
michael@0 38834 }
michael@0 38835 }
michael@0 38836 }
michael@0 38837 this._enterFrame(1);
michael@0 38838 var self = this;
michael@0 38839 this._onExecuteFrame = function onExecuteFrame() {
michael@0 38840 self._removeEventListener('executeFrame', onExecuteFrame);
michael@0 38841 self._allowFrameNavigation = false;
michael@0 38842 self._callFrame(self._currentFrame);
michael@0 38843 self._allowFrameNavigation = true;
michael@0 38844 if (self._playHead !== self._currentFrame) {
michael@0 38845 self._gotoFrame(self._playHead, true);
michael@0 38846 }
michael@0 38847 self._postConstructChildren();
michael@0 38848 };
michael@0 38849 this._addEventListener('executeFrame', this._onExecuteFrame);
michael@0 38850 if (this._complete && this._totalFrames <= 1) {
michael@0 38851 return this;
michael@0 38852 }
michael@0 38853 this._onAdvanceFrame = function onAdvanceFrame() {
michael@0 38854 var frameNum = self._playHead + 1;
michael@0 38855 if (self._complete && frameNum > self._totalFrames) {
michael@0 38856 frameNum = 1;
michael@0 38857 } else if (frameNum > self._framesLoaded) {
michael@0 38858 return;
michael@0 38859 }
michael@0 38860 self._updateDisplayList(frameNum);
michael@0 38861 if (self._sparse) {
michael@0 38862 self._addEventListener('constructChildren', self._onConstructChildren);
michael@0 38863 }
michael@0 38864 self._startSounds(frameNum);
michael@0 38865 self._enterFrame(frameNum);
michael@0 38866 if (frameNum in self._frameScripts) {
michael@0 38867 self._addEventListener('executeFrame', self._onExecuteFrame);
michael@0 38868 }
michael@0 38869 };
michael@0 38870 this._onConstructChildren = function onConstructChildren() {
michael@0 38871 self._removeEventListener('constructChildren', onConstructChildren);
michael@0 38872 self._constructChildren();
michael@0 38873 };
michael@0 38874 this.play();
michael@0 38875 },
michael@0 38876 _updateDisplayList: function (nextFrameNum) {
michael@0 38877 this._destructChildren(nextFrameNum);
michael@0 38878 this._declareChildren(nextFrameNum);
michael@0 38879 },
michael@0 38880 _declareChildren: function declareChildren(nextFrameNum) {
michael@0 38881 var currentFrame = this._currentFrame;
michael@0 38882 if (nextFrameNum === currentFrame) {
michael@0 38883 return;
michael@0 38884 }
michael@0 38885 var timeline = this._timeline;
michael@0 38886 var nextDisplayList = timeline[nextFrameNum - 1];
michael@0 38887 if (nextDisplayList === timeline[currentFrame - 1]) {
michael@0 38888 return;
michael@0 38889 }
michael@0 38890 var prevDisplayListItem = null;
michael@0 38891 var currentDisplayListItem = this._currentDisplayList;
michael@0 38892 var children = this._children;
michael@0 38893 var depths = nextDisplayList.depths;
michael@0 38894 var index = children.length;
michael@0 38895 var i = depths.length;
michael@0 38896 while (i--) {
michael@0 38897 var depth = depths[i], depthInt = depth | 0;
michael@0 38898 while (currentDisplayListItem && currentDisplayListItem.depth > depthInt) {
michael@0 38899 prevDisplayListItem = currentDisplayListItem;
michael@0 38900 currentDisplayListItem = currentDisplayListItem.next;
michael@0 38901 }
michael@0 38902 var currentChild = null;
michael@0 38903 if (currentDisplayListItem && currentDisplayListItem.depth === depthInt) {
michael@0 38904 currentChild = currentDisplayListItem.obj;
michael@0 38905 if (currentChild && currentChild._owned) {
michael@0 38906 index = this.getChildIndex(currentChild);
michael@0 38907 }
michael@0 38908 }
michael@0 38909 var currentCmd = currentDisplayListItem && currentDisplayListItem.depth === depthInt ? currentDisplayListItem.cmd : null;
michael@0 38910 var nextCmd = nextDisplayList[depth];
michael@0 38911 if (!nextCmd || nextCmd === currentCmd) {
michael@0 38912 continue;
michael@0 38913 }
michael@0 38914 if (currentCmd && currentChild && nextCmd.symbolId === currentCmd.symbolId && nextCmd.ratio === currentCmd.ratio) {
michael@0 38915 if (currentChild._animated) {
michael@0 38916 currentChild._invalidate();
michael@0 38917 if (nextCmd.hasMatrix) {
michael@0 38918 currentChild._setTransformMatrix(nextCmd.matrix, false);
michael@0 38919 }
michael@0 38920 if (nextCmd.hasCxform) {
michael@0 38921 currentChild._cxform = nextCmd.cxform;
michael@0 38922 }
michael@0 38923 if (nextCmd.clip) {
michael@0 38924 currentChild._clipDepth = nextCmd.clipDepth;
michael@0 38925 }
michael@0 38926 if (nextCmd.hasName) {
michael@0 38927 currentChild.name = nextCmd.name;
michael@0 38928 }
michael@0 38929 if (nextCmd.blend) {
michael@0 38930 currentChild._blendMode = this._resolveBlendMode(nextCmd.blendMode);
michael@0 38931 }
michael@0 38932 }
michael@0 38933 currentDisplayListItem.cmd = nextCmd;
michael@0 38934 continue;
michael@0 38935 }
michael@0 38936 var newDisplayListItem = this._addTimelineChild(nextCmd, index);
michael@0 38937 newDisplayListItem.next = currentDisplayListItem;
michael@0 38938 if (prevDisplayListItem) {
michael@0 38939 prevDisplayListItem.next = newDisplayListItem;
michael@0 38940 } else {
michael@0 38941 this._currentDisplayList = newDisplayListItem;
michael@0 38942 }
michael@0 38943 prevDisplayListItem = newDisplayListItem;
michael@0 38944 }
michael@0 38945 },
michael@0 38946 _destructChildren: function destructChildren(nextFrameNum) {
michael@0 38947 var currentFrame = this._currentFrame;
michael@0 38948 if (nextFrameNum === currentFrame) {
michael@0 38949 return;
michael@0 38950 }
michael@0 38951 var timeline = this._timeline;
michael@0 38952 var nextDisplayList = timeline[nextFrameNum - 1];
michael@0 38953 if (nextDisplayList === timeline[currentFrame - 1]) {
michael@0 38954 return;
michael@0 38955 }
michael@0 38956 var prevEntry = null;
michael@0 38957 var currentEntry = this._currentDisplayList;
michael@0 38958 var toRemove = null;
michael@0 38959 while (currentEntry) {
michael@0 38960 var depth = currentEntry.depth;
michael@0 38961 var currentCmd = currentEntry.cmd;
michael@0 38962 var nextCmd = nextDisplayList[depth];
michael@0 38963 if (!nextCmd || nextCmd.symbolId !== currentCmd.symbolId || nextCmd.ratio !== currentCmd.ratio) {
michael@0 38964 var nextDisplayListItem = currentEntry.next;
michael@0 38965 if (prevEntry) {
michael@0 38966 prevEntry.next = nextDisplayListItem;
michael@0 38967 } else {
michael@0 38968 this._currentDisplayList = nextDisplayListItem;
michael@0 38969 }
michael@0 38970 currentEntry.next = toRemove;
michael@0 38971 toRemove = currentEntry;
michael@0 38972 currentEntry = nextDisplayListItem;
michael@0 38973 } else {
michael@0 38974 prevEntry = currentEntry;
michael@0 38975 currentEntry = currentEntry.next;
michael@0 38976 }
michael@0 38977 }
michael@0 38978 while (toRemove) {
michael@0 38979 var child = toRemove.obj;
michael@0 38980 if (child && child._owned) {
michael@0 38981 this._sparse = true;
michael@0 38982 this.removeChild(child);
michael@0 38983 child.destroy();
michael@0 38984 if (child._isPlaying) {
michael@0 38985 child.stop();
michael@0 38986 }
michael@0 38987 }
michael@0 38988 toRemove = toRemove.next;
michael@0 38989 }
michael@0 38990 },
michael@0 38991 _gotoFrame: function gotoFrame(frameNum, execute) {
michael@0 38992 var enterFrame = frameNum !== this._currentFrame;
michael@0 38993 if (this._allowFrameNavigation || !this._loader._isAvm2Enabled) {
michael@0 38994 if (enterFrame) {
michael@0 38995 this._updateDisplayList(frameNum);
michael@0 38996 this._enterFrame(frameNum);
michael@0 38997 }
michael@0 38998 this._constructChildren();
michael@0 38999 if (this._loader._isAvm2Enabled && this.loaderInfo._swfVersion >= 10) {
michael@0 39000 if (enterFrame) {
michael@0 39001 this._addEventListener('executeFrame', this._onExecuteFrame);
michael@0 39002 }
michael@0 39003 var domain = avm2.systemDomain;
michael@0 39004 domain.broadcastMessage('frameConstructed');
michael@0 39005 domain.broadcastMessage('executeFrame');
michael@0 39006 domain.broadcastMessage('exitFrame');
michael@0 39007 return;
michael@0 39008 }
michael@0 39009 if (enterFrame && (execute || !this._loader._isAvm2Enabled)) {
michael@0 39010 this._callFrame(frameNum);
michael@0 39011 }
michael@0 39012 this._postConstructChildren();
michael@0 39013 return;
michael@0 39014 }
michael@0 39015 if (enterFrame) {
michael@0 39016 this._playHead = frameNum;
michael@0 39017 }
michael@0 39018 },
michael@0 39019 _enterFrame: function navigate(frameNum) {
michael@0 39020 if (frameNum === this._currentFrame) {
michael@0 39021 return;
michael@0 39022 }
michael@0 39023 this._currentFrameLabel = null;
michael@0 39024 if (frameNum === 1) {
michael@0 39025 this._currentLabel = null;
michael@0 39026 }
michael@0 39027 var map = this._labelMap;
michael@0 39028 for (var name in map) {
michael@0 39029 if (map[name] === frameNum) {
michael@0 39030 this._currentFrameLabel = this._currentLabel = name;
michael@0 39031 break;
michael@0 39032 }
michael@0 39033 }
michael@0 39034 if (this._scenes) {
michael@0 39035 var scenes = this._scenes;
michael@0 39036 for (var j = 0, n = scenes.length; j < n; j++) {
michael@0 39037 var scene = scenes[j];
michael@0 39038 if (frameNum >= scene._startFrame && frameNum <= scene._endFrame) {
michael@0 39039 this._currentScene = j;
michael@0 39040 break;
michael@0 39041 }
michael@0 39042 }
michael@0 39043 }
michael@0 39044 this._playHead = this._currentFrame = frameNum;
michael@0 39045 },
michael@0 39046 _callFrame: function callFrame(frame) {
michael@0 39047 if (isNaN(frame)) {
michael@0 39048 frame = this._labelMap[frame];
michael@0 39049 if (frame === undefined) {
michael@0 39050 return;
michael@0 39051 }
michael@0 39052 }
michael@0 39053 if (frame in this._frameScripts) {
michael@0 39054 var scripts = this._frameScripts[frame];
michael@0 39055 try {
michael@0 39056 for (var i = 0, n = scripts.length; i < n; i++) {
michael@0 39057 scripts[i].call(this);
michael@0 39058 }
michael@0 39059 } catch (e) {
michael@0 39060 var AVM2_ERROR_TYPE = 2;
michael@0 39061 TelemetryService.reportTelemetry({
michael@0 39062 topic: 'error',
michael@0 39063 error: AVM2_ERROR_TYPE
michael@0 39064 });
michael@0 39065 if (false) {
michael@0 39066 console.error('error ' + e + ', stack: \n' + e.stack);
michael@0 39067 }
michael@0 39068 this.stop();
michael@0 39069 throw e;
michael@0 39070 }
michael@0 39071 }
michael@0 39072 },
michael@0 39073 _gotoButtonState: function gotoButtonState(stateName) {
michael@0 39074 if (this._enabled) {
michael@0 39075 this.gotoLabel('_' + stateName);
michael@0 39076 }
michael@0 39077 },
michael@0 39078 _getAbsFrameNum: function (frameNum, sceneName) {
michael@0 39079 if (frameNum < 1) {
michael@0 39080 frameNum = 1;
michael@0 39081 }
michael@0 39082 if (sceneName && this._scenes && this._scenes.length > 1) {
michael@0 39083 var scenes = this._scenes;
michael@0 39084 for (var i = 0; i < scenes.length; i++) {
michael@0 39085 var scene = scenes[i];
michael@0 39086 if (scene.name === sceneName) {
michael@0 39087 frameNum += scene._startFrame - 1;
michael@0 39088 if (frameNum > scene._endFrame) {
michael@0 39089 frameNum = scene._endFrame;
michael@0 39090 }
michael@0 39091 break;
michael@0 39092 }
michael@0 39093 }
michael@0 39094 }
michael@0 39095 if (frameNum > this._framesLoaded) {
michael@0 39096 return this._framesLoaded;
michael@0 39097 }
michael@0 39098 return frameNum;
michael@0 39099 },
michael@0 39100 _registerStartSounds: function (frameNum, starts) {
michael@0 39101 this._startSoundRegistrations[frameNum] = starts;
michael@0 39102 },
michael@0 39103 _initSoundStream: function (streamInfo) {
michael@0 39104 this._soundStream = new MovieClipSoundStream(streamInfo, this);
michael@0 39105 },
michael@0 39106 _addSoundStreamBlock: function (frameNum, streamBlock) {
michael@0 39107 this._soundStream.appendBlock(frameNum, streamBlock);
michael@0 39108 },
michael@0 39109 _startSounds: function (frameNum) {
michael@0 39110 var starts = this._startSoundRegistrations[frameNum];
michael@0 39111 if (starts) {
michael@0 39112 var sounds = this._sounds || (this._sounds = {});
michael@0 39113 var loader = this.loaderInfo._loader;
michael@0 39114 for (var i = 0; i < starts.length; i++) {
michael@0 39115 var start = starts[i];
michael@0 39116 var symbolId = start.soundId;
michael@0 39117 var info = start.soundInfo;
michael@0 39118 var sound = sounds[symbolId];
michael@0 39119 if (!sound) {
michael@0 39120 var symbolInfo = loader._dictionaryResolved[symbolId];
michael@0 39121 if (!symbolInfo)
michael@0 39122 continue;
michael@0 39123 var symbolClass = avm2.systemDomain.findClass(symbolInfo.className) ? avm2.systemDomain.getClass(symbolInfo.className) : avm2.applicationDomain.getClass(symbolInfo.className);
michael@0 39124 var soundObj = symbolClass.createAsSymbol(symbolInfo.props);
michael@0 39125 symbolClass.instanceConstructor.call(soundObj);
michael@0 39126 sounds[symbolId] = sound = {
michael@0 39127 object: soundObj
michael@0 39128 };
michael@0 39129 }
michael@0 39130 if (sound.channel) {
michael@0 39131 sound.channel.stop();
michael@0 39132 sound.channel = null;
michael@0 39133 }
michael@0 39134 if (!info.stop) {
michael@0 39135 var loops = info.hasLoops ? info.loopCount : 0;
michael@0 39136 sound.channel = sound.object.play(0, loops);
michael@0 39137 }
michael@0 39138 }
michael@0 39139 }
michael@0 39140 if (this._soundStream) {
michael@0 39141 this._soundStream.playFrame(frameNum);
michael@0 39142 }
michael@0 39143 },
michael@0 39144 _getAS2Object: function () {
michael@0 39145 if (!this.$as2Object) {
michael@0 39146 if (this._avm1SymbolClass) {
michael@0 39147 var nativeObject = this, nativeObjectClass = this._avm1SymbolClass;
michael@0 39148 var constructWrapper = function () {
michael@0 39149 this.init(nativeObject);
michael@0 39150 nativeObjectClass.call(this);
michael@0 39151 };
michael@0 39152 constructWrapper.prototype = Object.create(nativeObjectClass.prototype);
michael@0 39153 constructWrapper.instanceConstructor = constructWrapper;
michael@0 39154 constructWrapper.debugName = 'avm1 <symbol constructor wrapper>';
michael@0 39155 construct(constructWrapper);
michael@0 39156 } else {
michael@0 39157 new avm1lib.AS2MovieClip(this);
michael@0 39158 }
michael@0 39159 }
michael@0 39160 return this.$as2Object;
michael@0 39161 },
michael@0 39162 get currentFrame() {
michael@0 39163 var frameNum = this._currentFrame;
michael@0 39164 return this._scenes ? frameNum - this.currentScene._startFrame + 1 : frameNum;
michael@0 39165 },
michael@0 39166 get currentFrameLabel() {
michael@0 39167 return this._currentFrameLabel;
michael@0 39168 },
michael@0 39169 get currentLabel() {
michael@0 39170 return this._currentLabel;
michael@0 39171 },
michael@0 39172 get currentLabels() {
michael@0 39173 if (this._scenes) {
michael@0 39174 return this._scenes[this._currentScene].labels;
michael@0 39175 } else {
michael@0 39176 var labels = [];
michael@0 39177 var map = this._labelMap;
michael@0 39178 for (var name in map) {
michael@0 39179 labels.push(new flash.display.FrameLabel(name, map[name]));
michael@0 39180 }
michael@0 39181 return labels;
michael@0 39182 }
michael@0 39183 },
michael@0 39184 get currentScene() {
michael@0 39185 return this._scenes ? this._scenes[this._currentScene] : new flash.display.Scene('', this.currentLabels, this._framesLoaded);
michael@0 39186 },
michael@0 39187 get enabled() {
michael@0 39188 return this._enabled;
michael@0 39189 },
michael@0 39190 set enabled(val) {
michael@0 39191 this._enabled = val;
michael@0 39192 },
michael@0 39193 get framesLoaded() {
michael@0 39194 return this._framesLoaded;
michael@0 39195 },
michael@0 39196 get totalFrames() {
michael@0 39197 return this._totalFrames;
michael@0 39198 },
michael@0 39199 get scenes() {
michael@0 39200 return this._scenes || [
michael@0 39201 new flash.display.Scene('', this.currentLabels, this._framesLoaded)
michael@0 39202 ];
michael@0 39203 },
michael@0 39204 get trackAsMenu() {
michael@0 39205 return false;
michael@0 39206 },
michael@0 39207 set trackAsMenu(val) {
michael@0 39208 notImplemented();
michael@0 39209 },
michael@0 39210 addFrameScript: function () {
michael@0 39211 var frameScripts = this._frameScripts;
michael@0 39212 for (var i = 0, n = arguments.length; i < n; i += 2) {
michael@0 39213 var frameNum = arguments[i] + 1;
michael@0 39214 var fn = arguments[i + 1];
michael@0 39215 if (!fn) {
michael@0 39216 continue;
michael@0 39217 }
michael@0 39218 var scripts = frameScripts[frameNum];
michael@0 39219 if (scripts) {
michael@0 39220 scripts.push(fn);
michael@0 39221 } else {
michael@0 39222 frameScripts[frameNum] = [
michael@0 39223 fn
michael@0 39224 ];
michael@0 39225 }
michael@0 39226 if (frameNum === this._currentFrame) {
michael@0 39227 this._addEventListener('executeFrame', this._onExecuteFrame);
michael@0 39228 }
michael@0 39229 }
michael@0 39230 },
michael@0 39231 gotoAndPlay: function (frame, scene) {
michael@0 39232 this.play();
michael@0 39233 if (isNaN(frame)) {
michael@0 39234 this.gotoLabel(frame);
michael@0 39235 } else {
michael@0 39236 this._gotoFrame(this._getAbsFrameNum(frame, scene));
michael@0 39237 }
michael@0 39238 },
michael@0 39239 gotoAndStop: function (frame, scene) {
michael@0 39240 this.stop();
michael@0 39241 if (isNaN(frame)) {
michael@0 39242 this.gotoLabel(frame);
michael@0 39243 } else {
michael@0 39244 this._gotoFrame(this._getAbsFrameNum(frame, scene));
michael@0 39245 }
michael@0 39246 },
michael@0 39247 gotoLabel: function (labelName) {
michael@0 39248 var frameNum = this._labelMap[labelName];
michael@0 39249 if (frameNum !== undefined) {
michael@0 39250 this._gotoFrame(frameNum);
michael@0 39251 }
michael@0 39252 },
michael@0 39253 isPlaying: function () {
michael@0 39254 return this._isPlaying;
michael@0 39255 },
michael@0 39256 nextFrame: function () {
michael@0 39257 this.stop();
michael@0 39258 if (this._currentFrame < this._framesLoaded) {
michael@0 39259 this._gotoFrame(this._currentFrame + 1);
michael@0 39260 }
michael@0 39261 },
michael@0 39262 nextScene: function () {
michael@0 39263 if (this._scenes && this._currentScene < this._scenes.length - 1) {
michael@0 39264 this._gotoFrame(this._scenes[this._currentScene + 1]._startFrame);
michael@0 39265 }
michael@0 39266 },
michael@0 39267 play: function () {
michael@0 39268 if (this._isPlaying || this._complete && this._totalFrames <= 1) {
michael@0 39269 return;
michael@0 39270 }
michael@0 39271 this._isPlaying = true;
michael@0 39272 this._addEventListener('advanceFrame', this._onAdvanceFrame);
michael@0 39273 },
michael@0 39274 prevFrame: function () {
michael@0 39275 this.stop();
michael@0 39276 if (this._currentFrame > 1) {
michael@0 39277 this._gotoFrame(this._currentFrame - 1);
michael@0 39278 }
michael@0 39279 },
michael@0 39280 prevScene: function () {
michael@0 39281 if (this._scenes && this._currentScene > 0) {
michael@0 39282 this._gotoFrame(this._scenes[this._currentScene - 1]._startFrame);
michael@0 39283 }
michael@0 39284 },
michael@0 39285 stop: function () {
michael@0 39286 if (!this._isPlaying || this._complete && this._totalFrames <= 1) {
michael@0 39287 return;
michael@0 39288 }
michael@0 39289 this._isPlaying = false;
michael@0 39290 this._removeEventListener('advanceFrame', this._onAdvanceFrame);
michael@0 39291 }
michael@0 39292 };
michael@0 39293 var desc = Object.getOwnPropertyDescriptor;
michael@0 39294 def.__glue__ = {
michael@0 39295 native: {
michael@0 39296 instance: {
michael@0 39297 currentFrame: desc(def, 'currentFrame'),
michael@0 39298 framesLoaded: desc(def, 'framesLoaded'),
michael@0 39299 totalFrames: desc(def, 'totalFrames'),
michael@0 39300 trackAsMenu: desc(def, 'trackAsMenu'),
michael@0 39301 scenes: desc(def, 'scenes'),
michael@0 39302 currentScene: desc(def, 'currentScene'),
michael@0 39303 currentLabel: desc(def, 'currentLabel'),
michael@0 39304 currentFrameLabel: desc(def, 'currentFrameLabel'),
michael@0 39305 enabled: desc(def, 'enabled'),
michael@0 39306 isPlaying: desc(def, 'isPlaying'),
michael@0 39307 play: def.play,
michael@0 39308 stop: def.stop,
michael@0 39309 nextFrame: def.nextFrame,
michael@0 39310 prevFrame: def.prevFrame,
michael@0 39311 gotoAndPlay: def.gotoAndPlay,
michael@0 39312 gotoAndStop: def.gotoAndStop,
michael@0 39313 addFrameScript: def.addFrameScript,
michael@0 39314 prevScene: def.prevScene,
michael@0 39315 nextScene: def.nextScene
michael@0 39316 }
michael@0 39317 }
michael@0 39318 };
michael@0 39319 return def;
michael@0 39320 }.call(this);
michael@0 39321 var MovieClipSoundStream = function () {
michael@0 39322 var MP3_MIME_TYPE = 'audio/mpeg';
michael@0 39323 function openMediaSource(soundStream, mediaSource) {
michael@0 39324 var sourceBuffer;
michael@0 39325 try {
michael@0 39326 sourceBuffer = mediaSource.addSourceBuffer(MP3_MIME_TYPE);
michael@0 39327 soundStream.mediaSource = mediaSource;
michael@0 39328 soundStream.sourceBuffer = sourceBuffer;
michael@0 39329 soundStream.rawFrames.forEach(function (data) {
michael@0 39330 sourceBuffer.appendBuffer(data);
michael@0 39331 });
michael@0 39332 delete soundStream.rawFrames;
michael@0 39333 } catch (e) {
michael@0 39334 console.error('MediaSource mp3 playback is not supported: ' + e);
michael@0 39335 }
michael@0 39336 }
michael@0 39337 function syncTime(element, movieClip) {
michael@0 39338 var initialized = false;
michael@0 39339 var startMediaTime, startRealTime;
michael@0 39340 element.addEventListener('timeupdate', function (e) {
michael@0 39341 if (!initialized) {
michael@0 39342 startMediaTime = element.currentTime;
michael@0 39343 startRealTime = performance.now();
michael@0 39344 initialized = true;
michael@0 39345 movieClip._stage._frameScheduler.startTrackDelta();
michael@0 39346 return;
michael@0 39347 }
michael@0 39348 var mediaDelta = element.currentTime - startMediaTime;
michael@0 39349 var realDelta = performance.now() - startRealTime;
michael@0 39350 movieClip._stage._frameScheduler.setDelta(realDelta - mediaDelta * 1000);
michael@0 39351 });
michael@0 39352 element.addEventListener('pause', function (e) {
michael@0 39353 movieClip._stage._frameScheduler.endTrackDelta();
michael@0 39354 initialized = false;
michael@0 39355 });
michael@0 39356 element.addEventListener('seeking', function (e) {
michael@0 39357 movieClip._stage._frameScheduler.endTrackDelta();
michael@0 39358 initialized = false;
michael@0 39359 });
michael@0 39360 }
michael@0 39361 function MovieClipSoundStream(streamInfo, movieClip) {
michael@0 39362 this.movieClip = movieClip;
michael@0 39363 this.data = {
michael@0 39364 sampleRate: streamInfo.sampleRate,
michael@0 39365 channels: streamInfo.channels
michael@0 39366 };
michael@0 39367 this.seekIndex = [];
michael@0 39368 this.position = 0;
michael@0 39369 var isMP3 = streamInfo.format === 'mp3';
michael@0 39370 if (isMP3 && PLAY_USING_AUDIO_TAG) {
michael@0 39371 var element = document.createElement('audio');
michael@0 39372 element.preload = 'metadata';
michael@0 39373 element.loop = false;
michael@0 39374 syncTime(element, movieClip);
michael@0 39375 if (element.canPlayType(MP3_MIME_TYPE)) {
michael@0 39376 this.element = element;
michael@0 39377 if (typeof MediaSource !== 'undefined') {
michael@0 39378 var mediaSource = new MediaSource();
michael@0 39379 mediaSource.addEventListener('sourceopen', openMediaSource.bind(null, this, mediaSource));
michael@0 39380 element.src = URL.createObjectURL(mediaSource);
michael@0 39381 } else {
michael@0 39382 console.warn('MediaSource is not supported');
michael@0 39383 }
michael@0 39384 this.rawFrames = [];
michael@0 39385 return;
michael@0 39386 }
michael@0 39387 }
michael@0 39388 var totalSamples = streamInfo.samplesCount * streamInfo.channels;
michael@0 39389 this.data.pcm = new Float32Array(totalSamples);
michael@0 39390 if (isMP3) {
michael@0 39391 var soundStream = this;
michael@0 39392 soundStream.decoderPosition = 0;
michael@0 39393 soundStream.decoderSession = new MP3DecoderSession();
michael@0 39394 soundStream.decoderSession.onframedata = function (frameData) {
michael@0 39395 var position = soundStream.decoderPosition;
michael@0 39396 soundStream.data.pcm.set(frameData, position);
michael@0 39397 soundStream.decoderPosition = position + frameData.length;
michael@0 39398 }.bind(this);
michael@0 39399 soundStream.decoderSession.onerror = function (error) {
michael@0 39400 console.error('ERROR: MP3DecoderSession: ' + error);
michael@0 39401 };
michael@0 39402 }
michael@0 39403 }
michael@0 39404 MovieClipSoundStream.prototype = {
michael@0 39405 appendBlock: function (frameNum, streamBlock) {
michael@0 39406 var streamPosition = this.position;
michael@0 39407 this.seekIndex[frameNum] = streamPosition + streamBlock.seek * this.data.channels;
michael@0 39408 this.position = streamPosition + streamBlock.samplesCount * this.data.channels;
michael@0 39409 if (this.sourceBuffer) {
michael@0 39410 this.sourceBuffer.appendBuffer(streamBlock.data);
michael@0 39411 return;
michael@0 39412 }
michael@0 39413 if (this.rawFrames) {
michael@0 39414 this.rawFrames.push(streamBlock.data);
michael@0 39415 return;
michael@0 39416 }
michael@0 39417 var decoderSession = this.decoderSession;
michael@0 39418 if (decoderSession) {
michael@0 39419 decoderSession.pushAsync(streamBlock.data);
michael@0 39420 } else {
michael@0 39421 this.data.pcm.set(streamBlock.pcm, streamPosition);
michael@0 39422 }
michael@0 39423 },
michael@0 39424 playFrame: function (frameNum) {
michael@0 39425 if (isNaN(this.seekIndex[frameNum])) {
michael@0 39426 return;
michael@0 39427 }
michael@0 39428 var PAUSE_WHEN_OF_SYNC_GREATER = 1;
michael@0 39429 var PLAYBACK_ADJUSTMENT = 0.25;
michael@0 39430 var element = this.element;
michael@0 39431 if (element) {
michael@0 39432 var soundStreamData = this.data;
michael@0 39433 var time = this.seekIndex[frameNum] / soundStreamData.sampleRate / soundStreamData.channels;
michael@0 39434 if (!this.channel && (this.movieClip._complete || this.sourceBuffer)) {
michael@0 39435 if (!this.sourceBuffer) {
michael@0 39436 var blob = new Blob(this.rawFrames);
michael@0 39437 element.src = URL.createObjectURL(blob);
michael@0 39438 }
michael@0 39439 var symbolClass = flash.media.SoundChannel.class;
michael@0 39440 var channel = symbolClass.createAsSymbol({
michael@0 39441 element: element
michael@0 39442 });
michael@0 39443 symbolClass.instanceConstructor.call(channel);
michael@0 39444 this.channel = channel;
michael@0 39445 this.expectedFrame = 0;
michael@0 39446 this.waitFor = 0;
michael@0 39447 } else if (this.sourceBuffer || !isNaN(element.duration)) {
michael@0 39448 if (this.mediaSource && this.movieClip._complete) {
michael@0 39449 this.mediaSource.endOfStream();
michael@0 39450 this.mediaSource = null;
michael@0 39451 }
michael@0 39452 var elementTime = element.currentTime;
michael@0 39453 if (this.expectedFrame !== frameNum) {
michael@0 39454 if (element.paused) {
michael@0 39455 element.play();
michael@0 39456 element.addEventListener('playing', function setTime(e) {
michael@0 39457 element.removeEventListener('playing', setTime);
michael@0 39458 element.currentTime = time;
michael@0 39459 });
michael@0 39460 } else {
michael@0 39461 element.currentTime = time;
michael@0 39462 }
michael@0 39463 } else if (this.waitFor > 0) {
michael@0 39464 if (this.waitFor <= time) {
michael@0 39465 if (element.paused) {
michael@0 39466 element.play();
michael@0 39467 }
michael@0 39468 this.waitFor = 0;
michael@0 39469 }
michael@0 39470 } else if (elementTime - time > PAUSE_WHEN_OF_SYNC_GREATER) {
michael@0 39471 console.warn('Sound is faster than frames by ' + (elementTime - time));
michael@0 39472 this.waitFor = elementTime - PLAYBACK_ADJUSTMENT;
michael@0 39473 element.pause();
michael@0 39474 } else if (time - elementTime > PAUSE_WHEN_OF_SYNC_GREATER) {
michael@0 39475 console.warn('Sound is slower than frames by ' + (time - elementTime));
michael@0 39476 element.currentTime = time + PLAYBACK_ADJUSTMENT;
michael@0 39477 }
michael@0 39478 this.expectedFrame = frameNum + 1;
michael@0 39479 }
michael@0 39480 } else if (!this.sound) {
michael@0 39481 var symbolClass = flash.media.Sound.class;
michael@0 39482 var sound = symbolClass.createAsSymbol(this.data);
michael@0 39483 symbolClass.instanceConstructor.call(sound);
michael@0 39484 var channel = sound.play();
michael@0 39485 this.sound = sound;
michael@0 39486 this.channel = channel;
michael@0 39487 }
michael@0 39488 }
michael@0 39489 };
michael@0 39490 return MovieClipSoundStream;
michael@0 39491 }();
michael@0 39492 var NativeMenuDefinition = function () {
michael@0 39493 return {
michael@0 39494 __class__: 'flash.display.NativeMenu',
michael@0 39495 initialize: function () {
michael@0 39496 },
michael@0 39497 __glue__: {
michael@0 39498 native: {
michael@0 39499 static: {},
michael@0 39500 instance: {}
michael@0 39501 }
michael@0 39502 }
michael@0 39503 };
michael@0 39504 }.call(this);
michael@0 39505 var NativeMenuItemDefinition = function () {
michael@0 39506 return {
michael@0 39507 __class__: 'flash.display.NativeMenuItem',
michael@0 39508 initialize: function () {
michael@0 39509 },
michael@0 39510 __glue__: {
michael@0 39511 native: {
michael@0 39512 static: {},
michael@0 39513 instance: {
michael@0 39514 enabled: {
michael@0 39515 get: function enabled() {
michael@0 39516 somewhatImplemented('NativeMenuItem.enabled');
michael@0 39517 return this._enabled;
michael@0 39518 },
michael@0 39519 set: function enabled(isSeparator) {
michael@0 39520 somewhatImplemented('NativeMenuItem.enabled');
michael@0 39521 this._enabled = isSeparator;
michael@0 39522 }
michael@0 39523 }
michael@0 39524 }
michael@0 39525 }
michael@0 39526 }
michael@0 39527 };
michael@0 39528 }.call(this);
michael@0 39529 var SceneDefinition = function () {
michael@0 39530 return {
michael@0 39531 __class__: 'flash.display.Scene',
michael@0 39532 initialize: function () {
michael@0 39533 this._startFrame = 1;
michael@0 39534 this._endFrame = 1;
michael@0 39535 },
michael@0 39536 __glue__: {
michael@0 39537 native: {
michael@0 39538 static: {},
michael@0 39539 instance: {}
michael@0 39540 },
michael@0 39541 script: {
michael@0 39542 static: {},
michael@0 39543 instance: {
michael@0 39544 name: {
michael@0 39545 get: function name() {
michael@0 39546 notImplemented('Scene.name');
michael@0 39547 return this._name;
michael@0 39548 }
michael@0 39549 },
michael@0 39550 labels: {
michael@0 39551 get: function labels() {
michael@0 39552 notImplemented('Scene.labels');
michael@0 39553 return this._labels;
michael@0 39554 }
michael@0 39555 },
michael@0 39556 numFrames: {
michael@0 39557 get: function numFrames() {
michael@0 39558 notImplemented('Scene.numFrames');
michael@0 39559 return this._numFrames;
michael@0 39560 }
michael@0 39561 }
michael@0 39562 }
michael@0 39563 }
michael@0 39564 }
michael@0 39565 };
michael@0 39566 }.call(this);
michael@0 39567 var ShaderDefinition = function () {
michael@0 39568 return {
michael@0 39569 __class__: 'flash.display.Shader',
michael@0 39570 initialize: function () {
michael@0 39571 this._data = null;
michael@0 39572 },
michael@0 39573 __glue__: {
michael@0 39574 native: {
michael@0 39575 static: {},
michael@0 39576 instance: {
michael@0 39577 data: {
michael@0 39578 get: function data() {
michael@0 39579 return this._data;
michael@0 39580 },
michael@0 39581 set: function data(p) {
michael@0 39582 this._data = p;
michael@0 39583 }
michael@0 39584 },
michael@0 39585 precisionHint: {
michael@0 39586 get: function precisionHint() {
michael@0 39587 return this._precisionHint;
michael@0 39588 },
michael@0 39589 set: function precisionHint(p) {
michael@0 39590 this._precisionHint = p;
michael@0 39591 }
michael@0 39592 }
michael@0 39593 }
michael@0 39594 },
michael@0 39595 script: {
michael@0 39596 instance: Glue.ALL
michael@0 39597 }
michael@0 39598 }
michael@0 39599 };
michael@0 39600 }.call(this);
michael@0 39601 var ShaderDataDefinition = function () {
michael@0 39602 return {
michael@0 39603 __class__: 'flash.display.ShaderData',
michael@0 39604 initialize: function () {
michael@0 39605 this._byteCode = null;
michael@0 39606 },
michael@0 39607 __glue__: {
michael@0 39608 native: {
michael@0 39609 static: {},
michael@0 39610 instance: {
michael@0 39611 _setByteCode: function _setByteCode(code) {
michael@0 39612 this._byteCode = code;
michael@0 39613 }
michael@0 39614 }
michael@0 39615 },
michael@0 39616 script: {
michael@0 39617 instance: Glue.ALL
michael@0 39618 }
michael@0 39619 }
michael@0 39620 };
michael@0 39621 }.call(this);
michael@0 39622 var ShapeDefinition = function () {
michael@0 39623 var def = {
michael@0 39624 __class__: 'flash.display.Shape',
michael@0 39625 initialize: function () {
michael@0 39626 var graphics = this._graphics = new flash.display.Graphics();
michael@0 39627 graphics._parent = this;
michael@0 39628 var s = this.symbol;
michael@0 39629 if (s && s.paths) {
michael@0 39630 graphics._paths = s.paths;
michael@0 39631 for (var i = 0; i < s.paths.length; i++) {
michael@0 39632 s.paths[i] = finishShapePath(s.paths[i], s.dictionaryResolved);
michael@0 39633 }
michael@0 39634 graphics.bbox = s.bbox;
michael@0 39635 graphics.strokeBbox = s.strokeBbox;
michael@0 39636 if (this._stage && this._stage._quality === 'low' && !graphics._bitmap)
michael@0 39637 graphics._cacheAsBitmap(this._bbox);
michael@0 39638 this.ratio = s.ratio || 0;
michael@0 39639 }
michael@0 39640 }
michael@0 39641 };
michael@0 39642 def.__glue__ = {
michael@0 39643 native: {
michael@0 39644 instance: {
michael@0 39645 graphics: {
michael@0 39646 get: function () {
michael@0 39647 return this._graphics;
michael@0 39648 }
michael@0 39649 }
michael@0 39650 }
michael@0 39651 }
michael@0 39652 };
michael@0 39653 return def;
michael@0 39654 }.call(this);
michael@0 39655 var SimpleButtonDefinition = function () {
michael@0 39656 var AVM1KeyCodeMap = [
michael@0 39657 0,
michael@0 39658 37,
michael@0 39659 39,
michael@0 39660 36,
michael@0 39661 35,
michael@0 39662 45,
michael@0 39663 46,
michael@0 39664 0,
michael@0 39665 8,
michael@0 39666 0,
michael@0 39667 0,
michael@0 39668 0,
michael@0 39669 0,
michael@0 39670 13,
michael@0 39671 38,
michael@0 39672 40,
michael@0 39673 33,
michael@0 39674 34,
michael@0 39675 9,
michael@0 39676 27
michael@0 39677 ];
michael@0 39678 var AVM1MouseTransitionEvents = [
michael@0 39679 0,
michael@0 39680 0,
michael@0 39681 1,
michael@0 39682 128,
michael@0 39683 64,
michael@0 39684 0,
michael@0 39685 0,
michael@0 39686 32,
michael@0 39687 2,
michael@0 39688 0,
michael@0 39689 0,
michael@0 39690 4,
michael@0 39691 256,
michael@0 39692 16,
michael@0 39693 8,
michael@0 39694 0
michael@0 39695 ];
michael@0 39696 return {
michael@0 39697 __class__: 'flash.display.SimpleButton',
michael@0 39698 initialize: function () {
michael@0 39699 this._useHandCursor = true;
michael@0 39700 this._enabled = true;
michael@0 39701 this._trackAsMenu = false;
michael@0 39702 this._upState = null;
michael@0 39703 this._overState = null;
michael@0 39704 this._downState = null;
michael@0 39705 this._hitTestState = null;
michael@0 39706 this._currentButtonState = 'up';
michael@0 39707 this._mouseChildren = false;
michael@0 39708 this._buttonMode = true;
michael@0 39709 this._prevAvm1StateCode = 0;
michael@0 39710 this._avm1StateCode = 0;
michael@0 39711 this._avm1MouseEvents = null;
michael@0 39712 this._isContainer = true;
michael@0 39713 var s = this.symbol;
michael@0 39714 if (s) {
michael@0 39715 var states = s.states;
michael@0 39716 if (states.down) {
michael@0 39717 this._downState = this._constructState(states.down, this);
michael@0 39718 }
michael@0 39719 if (states.hitTest) {
michael@0 39720 this._hitTestState = this._constructState(states.hitTest, this);
michael@0 39721 }
michael@0 39722 if (states.over) {
michael@0 39723 this._overState = this._constructState(states.over, this);
michael@0 39724 }
michael@0 39725 if (states.up) {
michael@0 39726 this._upState = this._constructState(states.up, this);
michael@0 39727 }
michael@0 39728 }
michael@0 39729 if (this._loader && !this._loader._isAvm2Enabled && s && s.buttonActions) {
michael@0 39730 this._addEventListener('addedToStage', function (e) {
michael@0 39731 this._initAvm1Events(s.buttonActions);
michael@0 39732 }.bind(this), false);
michael@0 39733 }
michael@0 39734 },
michael@0 39735 _constructState: function constructState(symbolInfo) {
michael@0 39736 var symbolClass = avm2.systemDomain.findClass(symbolInfo.className) ? avm2.systemDomain.getClass(symbolInfo.className) : avm2.applicationDomain.getClass(symbolInfo.className);
michael@0 39737 var instance = symbolClass.createAsSymbol(symbolInfo.props);
michael@0 39738 symbolClass.instanceConstructor.call(instance);
michael@0 39739 if (instance._children.length === 1) {
michael@0 39740 instance = instance._children[0];
michael@0 39741 instance._parent = null;
michael@0 39742 instance._index = -1;
michael@0 39743 }
michael@0 39744 return instance;
michael@0 39745 },
michael@0 39746 _updateButton: function updateButton() {
michael@0 39747 var state = null;
michael@0 39748 switch (this._currentButtonState) {
michael@0 39749 case 'up':
michael@0 39750 state = this._upState;
michael@0 39751 break;
michael@0 39752 case 'over':
michael@0 39753 state = this._overState;
michael@0 39754 break;
michael@0 39755 case 'down':
michael@0 39756 state = this._downState;
michael@0 39757 break;
michael@0 39758 }
michael@0 39759 if (!state) {
michael@0 39760 return;
michael@0 39761 }
michael@0 39762 var currentChild = this._children[0];
michael@0 39763 if (currentChild) {
michael@0 39764 if (currentChild === state) {
michael@0 39765 return;
michael@0 39766 }
michael@0 39767 if (this._stage) {
michael@0 39768 this._stage._removeFromStage(currentChild);
michael@0 39769 }
michael@0 39770 currentChild._invalidateTransform();
michael@0 39771 }
michael@0 39772 if (!state) {
michael@0 39773 this._children.shift();
michael@0 39774 return;
michael@0 39775 }
michael@0 39776 this._children[0] = state;
michael@0 39777 state._parent = this;
michael@0 39778 state._invalidateTransform();
michael@0 39779 if (this._stage) {
michael@0 39780 this._stage._addToStage(state);
michael@0 39781 }
michael@0 39782 },
michael@0 39783 _gotoButtonState: function gotoButtonState(buttonState) {
michael@0 39784 this._invalidateBounds();
michael@0 39785 this._currentButtonState = buttonState;
michael@0 39786 this._updateButton();
michael@0 39787 if (this._avm1MouseEvents) {
michael@0 39788 this._processAvm1MouseEvents(this._avm1MouseEvents);
michael@0 39789 }
michael@0 39790 },
michael@0 39791 _getRegion: function getRegion(targetCoordSpace) {
michael@0 39792 if (!this._hitTestState) {
michael@0 39793 return {
michael@0 39794 xMin: 0,
michael@0 39795 yMin: 0,
michael@0 39796 xMax: 0,
michael@0 39797 yMax: 0
michael@0 39798 };
michael@0 39799 }
michael@0 39800 var b = this._hitTestState.getBounds(null);
michael@0 39801 return this._getTransformedRect(b, targetCoordSpace);
michael@0 39802 },
michael@0 39803 _getAS2Object: function () {
michael@0 39804 if (!this.$as2Object) {
michael@0 39805 new avm1lib.AS2Button(this);
michael@0 39806 }
michael@0 39807 return this.$as2Object;
michael@0 39808 },
michael@0 39809 _initAvm1Events: function (buttonActions) {
michael@0 39810 var loader = this._loader;
michael@0 39811 var avm1Context = loader._avm1Context;
michael@0 39812 var keyEvents = null;
michael@0 39813 for (var i = 0; i < buttonActions.length; i++) {
michael@0 39814 var buttonAction = buttonActions[i];
michael@0 39815 var fn = function (actionBlock) {
michael@0 39816 return executeActions(actionBlock, avm1Context, this._getAS2Object());
michael@0 39817 }.bind(this.parent, buttonAction.actionsData);
michael@0 39818 var mouseEventFlags = buttonAction.mouseEventFlags;
michael@0 39819 if (mouseEventFlags) {
michael@0 39820 var mouseEvents = this._avm1MouseEvents || (this._avm1MouseEvents = []);
michael@0 39821 mouseEvents.push({
michael@0 39822 flags: mouseEventFlags,
michael@0 39823 listener: fn
michael@0 39824 });
michael@0 39825 }
michael@0 39826 var keyPress = buttonAction.keyPress;
michael@0 39827 if (keyPress) {
michael@0 39828 keyEvents = keyEvents || (keyEvents = []);
michael@0 39829 keyEvents.push({
michael@0 39830 keyCode: AVM1KeyCodeMap[keyPress] || 0,
michael@0 39831 charCode: keyPress,
michael@0 39832 listener: fn
michael@0 39833 });
michael@0 39834 }
michael@0 39835 }
michael@0 39836 if (keyEvents) {
michael@0 39837 var keyListener = function (e) {
michael@0 39838 for (var i = 0; i < keyEvents.length; i++) {
michael@0 39839 var keyEvent = keyEvents[i];
michael@0 39840 if (keyEvent.keyCode ? keyEvent.keyCode === e.keyCode : keyEvent.charCode === e.charCode) {
michael@0 39841 keyEvent.listener();
michael@0 39842 }
michael@0 39843 }
michael@0 39844 };
michael@0 39845 var KeyboardEventClass = flash.events.KeyboardEvent;
michael@0 39846 this.stage._addEventListener(KeyboardEventClass.class.KEY_DOWN, keyListener, false);
michael@0 39847 this._addEventListener('removedFromStage', function (stage) {
michael@0 39848 stage._removeEventListener(KeyboardEventClass.class.KEY_DOWN, keyListener, false);
michael@0 39849 }.bind(this, this.stage), false);
michael@0 39850 }
michael@0 39851 },
michael@0 39852 _processAvm1MouseEvents: function (mouseEvents) {
michael@0 39853 var prevAvm1StateCode = this._avm1StateCode;
michael@0 39854 var avm1StateCode = (this._currentButtonState === 'down' ? 1 : 0) | (this._currentButtonState !== 'up' ? 2 : 0);
michael@0 39855 if (prevAvm1StateCode !== avm1StateCode) {
michael@0 39856 this._prevAvm1StateCode = prevAvm1StateCode;
michael@0 39857 this._avm1StateCode = avm1StateCode;
michael@0 39858 var flag = AVM1MouseTransitionEvents[prevAvm1StateCode << 2 | avm1StateCode];
michael@0 39859 for (var i = 0; i < mouseEvents.length; i++) {
michael@0 39860 var mouseEvent = mouseEvents[i];
michael@0 39861 if ((mouseEvent.flags & flag) !== 0) {
michael@0 39862 mouseEvent.listener();
michael@0 39863 }
michael@0 39864 }
michael@0 39865 }
michael@0 39866 },
michael@0 39867 __glue__: {
michael@0 39868 native: {
michael@0 39869 instance: {
michael@0 39870 _updateButton: function _updateButton() {
michael@0 39871 this._updateButton();
michael@0 39872 },
michael@0 39873 useHandCursor: {
michael@0 39874 get: function useHandCursor() {
michael@0 39875 return this._useHandCursor;
michael@0 39876 },
michael@0 39877 set: function useHandCursor(value) {
michael@0 39878 this._useHandCursor = value;
michael@0 39879 }
michael@0 39880 },
michael@0 39881 enabled: {
michael@0 39882 get: function enabled() {
michael@0 39883 return this._enabled;
michael@0 39884 },
michael@0 39885 set: function enabled(value) {
michael@0 39886 this._enabled = value;
michael@0 39887 }
michael@0 39888 },
michael@0 39889 trackAsMenu: {
michael@0 39890 get: function trackAsMenu() {
michael@0 39891 notImplemented('SimpleButton.trackAsMenu');
michael@0 39892 return this._trackAsMenu;
michael@0 39893 },
michael@0 39894 set: function trackAsMenu(value) {
michael@0 39895 notImplemented('SimpleButton.trackAsMenu');
michael@0 39896 this._trackAsMenu = value;
michael@0 39897 }
michael@0 39898 },
michael@0 39899 upState: {
michael@0 39900 get: function upState() {
michael@0 39901 return this._upState;
michael@0 39902 },
michael@0 39903 set: function upState(value) {
michael@0 39904 this._upState = value;
michael@0 39905 this._updateButton();
michael@0 39906 }
michael@0 39907 },
michael@0 39908 overState: {
michael@0 39909 get: function overState() {
michael@0 39910 return this._overState;
michael@0 39911 },
michael@0 39912 set: function overState(value) {
michael@0 39913 this._overState = value;
michael@0 39914 this._updateButton();
michael@0 39915 }
michael@0 39916 },
michael@0 39917 downState: {
michael@0 39918 get: function downState() {
michael@0 39919 return this._downState;
michael@0 39920 },
michael@0 39921 set: function downState(value) {
michael@0 39922 this._downState = value;
michael@0 39923 this._updateButton();
michael@0 39924 }
michael@0 39925 },
michael@0 39926 hitTestState: {
michael@0 39927 get: function hitTestState() {
michael@0 39928 return this._hitTestState;
michael@0 39929 },
michael@0 39930 set: function hitTestState(value) {
michael@0 39931 if (value === this._hitTestState) {
michael@0 39932 return;
michael@0 39933 }
michael@0 39934 this._invalidate();
michael@0 39935 this._hitTestState = value;
michael@0 39936 }
michael@0 39937 },
michael@0 39938 soundTransform: {
michael@0 39939 get: function soundTransform() {
michael@0 39940 notImplemented('SimpleButton.soundTransform');
michael@0 39941 return this._soundTransform;
michael@0 39942 },
michael@0 39943 set: function soundTransform(value) {
michael@0 39944 notImplemented('SimpleButton.soundTransform');
michael@0 39945 this._soundTransform = value;
michael@0 39946 }
michael@0 39947 }
michael@0 39948 }
michael@0 39949 }
michael@0 39950 }
michael@0 39951 };
michael@0 39952 }.call(this);
michael@0 39953 var SpriteDefinition = function () {
michael@0 39954 var def = {
michael@0 39955 __class__: 'flash.display.Sprite',
michael@0 39956 initialize: function () {
michael@0 39957 this._buttonMode = false;
michael@0 39958 this._hitArea = null;
michael@0 39959 this._useHandCursor = true;
michael@0 39960 this._hitTarget = null;
michael@0 39961 this._currentDisplayList = null;
michael@0 39962 var s = this.symbol;
michael@0 39963 if (s) {
michael@0 39964 this._graphics = s.graphics || new flash.display.Graphics();
michael@0 39965 if (s.timeline) {
michael@0 39966 var displayList = s.timeline[0];
michael@0 39967 if (displayList) {
michael@0 39968 var depths = displayList.depths;
michael@0 39969 for (var i = 0; i < depths.length; i++) {
michael@0 39970 var cmd = displayList[depths[i]];
michael@0 39971 if (cmd) {
michael@0 39972 var displayListItem = this._addTimelineChild(cmd);
michael@0 39973 displayListItem.next = this._currentDisplayList;
michael@0 39974 this._currentDisplayList = displayListItem;
michael@0 39975 }
michael@0 39976 }
michael@0 39977 }
michael@0 39978 }
michael@0 39979 } else {
michael@0 39980 this._graphics = new flash.display.Graphics();
michael@0 39981 }
michael@0 39982 this._graphics._parent = this;
michael@0 39983 },
michael@0 39984 _addTimelineChild: function addTimelineChild(cmd, index) {
michael@0 39985 var symbolInfo = cmd.symbolInfo;
michael@0 39986 var props = Object.create(symbolInfo.props);
michael@0 39987 props.symbolId = cmd.symbolId;
michael@0 39988 props.depth = cmd.depth;
michael@0 39989 if (cmd.clip) {
michael@0 39990 props.clipDepth = cmd.clipDepth;
michael@0 39991 }
michael@0 39992 if (cmd.hasCxform) {
michael@0 39993 props.cxform = cmd.cxform;
michael@0 39994 }
michael@0 39995 if (cmd.hasMatrix) {
michael@0 39996 props.currentTransform = cmd.matrix;
michael@0 39997 }
michael@0 39998 if (cmd.hasName) {
michael@0 39999 props.name = cmd.name;
michael@0 40000 }
michael@0 40001 if (cmd.hasRatio) {
michael@0 40002 props.ratio = cmd.ratio / 65535;
michael@0 40003 }
michael@0 40004 if (cmd.blend) {
michael@0 40005 props.blendMode = cmd.blendMode;
michael@0 40006 }
michael@0 40007 var displayListItem = {
michael@0 40008 cmd: cmd,
michael@0 40009 depth: cmd.depth,
michael@0 40010 className: symbolInfo.className,
michael@0 40011 props: props,
michael@0 40012 events: cmd.events,
michael@0 40013 obj: null
michael@0 40014 };
michael@0 40015 if (index !== undefined) {
michael@0 40016 this._children.splice(index, 0, displayListItem);
michael@0 40017 } else {
michael@0 40018 this._children.push(displayListItem);
michael@0 40019 }
michael@0 40020 this._sparse = true;
michael@0 40021 return displayListItem;
michael@0 40022 },
michael@0 40023 _constructChildren: function () {
michael@0 40024 if (!this._sparse) {
michael@0 40025 return;
michael@0 40026 }
michael@0 40027 var loader = this._loader;
michael@0 40028 var children = this._children;
michael@0 40029 for (var i = 0; i < children.length; i++) {
michael@0 40030 var displayListItem = children[i];
michael@0 40031 Counter.count('constructChild');
michael@0 40032 if (flash.display.DisplayObject.class.isInstanceOf(displayListItem)) {
michael@0 40033 displayListItem._index = i;
michael@0 40034 } else {
michael@0 40035 var symbolClass = avm2.systemDomain.findClass(displayListItem.className) ? avm2.systemDomain.getClass(displayListItem.className) : avm2.applicationDomain.getClass(displayListItem.className);
michael@0 40036 var props = Object.create(displayListItem.props);
michael@0 40037 var name = props.name;
michael@0 40038 props.animated = true;
michael@0 40039 props.owned = true;
michael@0 40040 props.parent = this;
michael@0 40041 props.stage = this._stage;
michael@0 40042 if (this._level > -1) {
michael@0 40043 props.level = this._level + 1;
michael@0 40044 }
michael@0 40045 props.index = i;
michael@0 40046 var instance = symbolClass.createAsSymbol(props);
michael@0 40047 if (name) {
michael@0 40048 this[Multiname.getPublicQualifiedName(name)] = instance;
michael@0 40049 }
michael@0 40050 symbolClass.instanceConstructor.call(instance);
michael@0 40051 if (flash.display.BitmapData.class.isInstanceOf(instance)) {
michael@0 40052 var bitmapData = instance;
michael@0 40053 instance = flash.display.Bitmap.class.createAsSymbol(props);
michael@0 40054 flash.display.Bitmap.class.instanceConstructor.call(instance, bitmapData);
michael@0 40055 }
michael@0 40056 if (!loader._isAvm2Enabled) {
michael@0 40057 this._initAvm1Bindings(instance, name, displayListItem.events);
michael@0 40058 instance._dispatchEvent('init');
michael@0 40059 instance._dispatchEvent('construct');
michael@0 40060 instance._needLoadEvent = true;
michael@0 40061 } else {
michael@0 40062 instance._dispatchEvent('load');
michael@0 40063 }
michael@0 40064 instance._dispatchEvent('added', undefined, true);
michael@0 40065 if (this._stage) {
michael@0 40066 this._stage._addToStage(instance);
michael@0 40067 }
michael@0 40068 children[i] = instance;
michael@0 40069 displayListItem.obj = instance;
michael@0 40070 }
michael@0 40071 }
michael@0 40072 this._sparse = false;
michael@0 40073 },
michael@0 40074 _postConstructChildren: function () {
michael@0 40075 var loader = this._loader;
michael@0 40076 if (!loader || loader._isAvm2Enabled) {
michael@0 40077 return;
michael@0 40078 }
michael@0 40079 var children = this._children;
michael@0 40080 for (var i = 0; i < children.length; i++) {
michael@0 40081 var instance = children[i];
michael@0 40082 if (instance._needLoadEvent) {
michael@0 40083 instance._needLoadEvent = false;
michael@0 40084 instance._dispatchEvent('load');
michael@0 40085 }
michael@0 40086 }
michael@0 40087 },
michael@0 40088 _duplicate: function (name, depth, initObject) {
michael@0 40089 var loader = this._loader;
michael@0 40090 var parent = this._parent;
michael@0 40091 var children = parent._children;
michael@0 40092 var symbolClass = this.class;
michael@0 40093 var symbolInfo = this.symbol;
michael@0 40094 var props = Object.create(symbolInfo);
michael@0 40095 props.name = name;
michael@0 40096 props.parent = parent;
michael@0 40097 props.depth = depth;
michael@0 40098 var instance = symbolClass.createAsSymbol(props);
michael@0 40099 if (name && loader && !loader._isAvm2Enabled && !parent.asHasProperty(undefined, name, 0, false)) {
michael@0 40100 parent.asSetPublicProperty(name, instance);
michael@0 40101 }
michael@0 40102 symbolClass.instanceConstructor.call(instance);
michael@0 40103 instance._index = children.length;
michael@0 40104 children.push(instance);
michael@0 40105 if (!loader._isAvm2Enabled) {
michael@0 40106 parent._initAvm1Bindings(instance, name, symbolInfo && symbolInfo.events);
michael@0 40107 instance._dispatchEvent('init');
michael@0 40108 instance._dispatchEvent('construct');
michael@0 40109 }
michael@0 40110 instance._dispatchEvent('load');
michael@0 40111 instance._dispatchEvent('added');
michael@0 40112 if (this._stage) {
michael@0 40113 instance._invalidate();
michael@0 40114 }
michael@0 40115 return instance;
michael@0 40116 },
michael@0 40117 _insertChildAtDepth: function (child, depth) {
michael@0 40118 this.addChild(child);
michael@0 40119 var name = child._name;
michael@0 40120 var loader = this._loader;
michael@0 40121 if (name && loader && !loader._isAvm2Enabled && !this._getAS2Object().asHasProperty(undefined, name, 0, true)) {
michael@0 40122 this._getAS2Object().asSetPublicProperty(name, child._getAS2Object());
michael@0 40123 }
michael@0 40124 },
michael@0 40125 _initAvm1Bindings: function (instance, name, events) {
michael@0 40126 var loader = this._loader;
michael@0 40127 var avm1Context = loader._avm1Context;
michael@0 40128 var symbolProps = instance.symbol;
michael@0 40129 if (symbolProps && symbolProps.variableName) {
michael@0 40130 instance._getAS2Object().asSetPublicProperty('variable', symbolProps.variableName);
michael@0 40131 }
michael@0 40132 if (events) {
michael@0 40133 var eventsBound = [];
michael@0 40134 for (var i = 0; i < events.length; i++) {
michael@0 40135 var event = events[i];
michael@0 40136 if (event.eoe) {
michael@0 40137 break;
michael@0 40138 }
michael@0 40139 var fn = function (actionBlock) {
michael@0 40140 return executeActions(actionBlock, avm1Context, this._getAS2Object());
michael@0 40141 }.bind(instance, event.actionsData);
michael@0 40142 for (var eventName in event) {
michael@0 40143 if (eventName.indexOf('on') !== 0 || !event[eventName])
michael@0 40144 continue;
michael@0 40145 var avm2EventName = eventName[2].toLowerCase() + eventName.substring(3);
michael@0 40146 if (avm2EventName === 'enterFrame') {
michael@0 40147 avm2EventName = 'frameConstructed';
michael@0 40148 }
michael@0 40149 var avm2EventTarget = instance;
michael@0 40150 if (avm2EventName === 'mouseDown' || avm2EventName === 'mouseUp' || avm2EventName === 'mouseMove') {
michael@0 40151 avm2EventTarget = this._stage;
michael@0 40152 }
michael@0 40153 avm2EventTarget._addEventListener(avm2EventName, fn, false);
michael@0 40154 eventsBound.push({
michael@0 40155 name: avm2EventName,
michael@0 40156 fn: fn,
michael@0 40157 target: avm2EventTarget
michael@0 40158 });
michael@0 40159 }
michael@0 40160 }
michael@0 40161 if (eventsBound.length > 0) {
michael@0 40162 instance._addEventListener('removed', function (eventsBound) {
michael@0 40163 for (var i = 0; i < eventsBound.length; i++) {
michael@0 40164 eventsBound[i].target._removeEventListener(eventsBound[i].name, eventsBound[i].fn, false);
michael@0 40165 }
michael@0 40166 }.bind(instance, eventsBound), false);
michael@0 40167 }
michael@0 40168 }
michael@0 40169 if (name && this._getAS2Object && instance._getAS2Object) {
michael@0 40170 this._getAS2Object().asSetPublicProperty(name, instance._getAS2Object());
michael@0 40171 }
michael@0 40172 },
michael@0 40173 _gotoButtonState: function gotoButtonState(stateName) {
michael@0 40174 },
michael@0 40175 get buttonMode() {
michael@0 40176 return this._buttonMode;
michael@0 40177 },
michael@0 40178 set buttonMode(val) {
michael@0 40179 this._buttonMode = val;
michael@0 40180 },
michael@0 40181 get graphics() {
michael@0 40182 return this._graphics;
michael@0 40183 },
michael@0 40184 get hitArea() {
michael@0 40185 return this._hitArea;
michael@0 40186 },
michael@0 40187 set hitArea(val) {
michael@0 40188 if (this._hitArea === val) {
michael@0 40189 return;
michael@0 40190 }
michael@0 40191 if (val && val._hitTarget) {
michael@0 40192 val._hitTarget.hitArea = null;
michael@0 40193 }
michael@0 40194 this._hitArea = val;
michael@0 40195 if (val) {
michael@0 40196 val._hitTarget = this;
michael@0 40197 }
michael@0 40198 },
michael@0 40199 get soundTransform() {
michael@0 40200 notImplemented();
michael@0 40201 },
michael@0 40202 set soundTransform(val) {
michael@0 40203 notImplemented();
michael@0 40204 },
michael@0 40205 get useHandCursor() {
michael@0 40206 return this._useHandCursor;
michael@0 40207 },
michael@0 40208 set useHandCursor(val) {
michael@0 40209 this._useHandCursor = val;
michael@0 40210 if (this._stage) {
michael@0 40211 this._stage._mouseMoved = true;
michael@0 40212 }
michael@0 40213 },
michael@0 40214 startDrag: function (lockCenter, bounds) {
michael@0 40215 notImplemented();
michael@0 40216 },
michael@0 40217 startTouchDrag: function (touchPointID, lockCenter, bounds) {
michael@0 40218 notImplemented();
michael@0 40219 },
michael@0 40220 stopDrag: function () {
michael@0 40221 notImplemented();
michael@0 40222 },
michael@0 40223 stopTouchDrag: function (touchPointID) {
michael@0 40224 notImplemented();
michael@0 40225 }
michael@0 40226 };
michael@0 40227 var desc = Object.getOwnPropertyDescriptor;
michael@0 40228 def.__glue__ = {
michael@0 40229 native: {
michael@0 40230 instance: {
michael@0 40231 graphics: desc(def, 'graphics'),
michael@0 40232 buttonMode: desc(def, 'buttonMode'),
michael@0 40233 dropTarget: desc(def, 'dropTarget'),
michael@0 40234 startDrag: def.startDrag,
michael@0 40235 stopDrag: def.stopDrag,
michael@0 40236 startTouchDrag: def.startTouchDrag,
michael@0 40237 stopTouchDrag: def.stopTouchDrag,
michael@0 40238 constructChildren: def._constructChildren,
michael@0 40239 hitArea: desc(def, 'hitArea'),
michael@0 40240 useHandCursor: desc(def, 'useHandCursor'),
michael@0 40241 soundTransform: desc(def, 'soundTransform')
michael@0 40242 }
michael@0 40243 }
michael@0 40244 };
michael@0 40245 return def;
michael@0 40246 }.call(this);
michael@0 40247 var StageDefinition = function () {
michael@0 40248 return {
michael@0 40249 __class__: 'flash.display.Stage',
michael@0 40250 initialize: function () {
michael@0 40251 this._frameRate = 24;
michael@0 40252 this._scaleMode = 'showAll';
michael@0 40253 this._align = '';
michael@0 40254 this._stageWidth = 0;
michael@0 40255 this._stageHeight = 0;
michael@0 40256 this._quality = 'high';
michael@0 40257 this._color = 4294967295;
michael@0 40258 this._stage = this;
michael@0 40259 this._deferRenderEvent = false;
michael@0 40260 this._focus = null;
michael@0 40261 this._showDefaultContextMenu = true;
michael@0 40262 this._displayState = 'normal';
michael@0 40263 this._colorCorrection = 'default';
michael@0 40264 this._stageFocusRect = true;
michael@0 40265 this._fullScreenSourceRect = null;
michael@0 40266 this._wmodeGPU = false;
michael@0 40267 this._root = null;
michael@0 40268 this._qtree = null;
michael@0 40269 this._invalidRegions = new RegionCluster();
michael@0 40270 this._mouseMoved = false;
michael@0 40271 this._mouseTarget = this;
michael@0 40272 this._mouseEvents = [];
michael@0 40273 this._cursor = 'auto';
michael@0 40274 this._stageVideos = [];
michael@0 40275 this._concatenatedTransform.invalid = false;
michael@0 40276 },
michael@0 40277 _setup: function setup(ctx, options) {
michael@0 40278 this._qtree = new QuadTree(0, 0, this._stageWidth, this._stageHeight, null);
michael@0 40279 this._invalid = true;
michael@0 40280 },
michael@0 40281 _addToStage: function addToStage(displayObject) {
michael@0 40282 displayObject._stage = this;
michael@0 40283 var parent = displayObject._parent;
michael@0 40284 displayObject._level = parent._level + 1;
michael@0 40285 displayObject._invalid = true;
michael@0 40286 var children = displayObject._children;
michael@0 40287 for (var i = 0; i < children.length; i++) {
michael@0 40288 var child = children[i];
michael@0 40289 if (child._stage === null) {
michael@0 40290 this._addToStage(child);
michael@0 40291 }
michael@0 40292 }
michael@0 40293 displayObject._dispatchEvent('addedToStage');
michael@0 40294 },
michael@0 40295 _removeFromStage: function removeFromStage(displayObject) {
michael@0 40296 var children = displayObject._children;
michael@0 40297 for (var i = 0; i < children.length; i++) {
michael@0 40298 var child = children[i];
michael@0 40299 if (child._stage) {
michael@0 40300 this._removeFromStage(children[i]);
michael@0 40301 }
michael@0 40302 }
michael@0 40303 displayObject._dispatchEvent('removedFromStage');
michael@0 40304 displayObject._stage = null;
michael@0 40305 displayObject._level = -1;
michael@0 40306 if (displayObject._region) {
michael@0 40307 this._qtree.remove(displayObject._region);
michael@0 40308 this._invalidRegions.insert(displayObject._region);
michael@0 40309 displayObject._region = null;
michael@0 40310 }
michael@0 40311 },
michael@0 40312 _processInvalidations: function processInvalidations(refreshStage) {
michael@0 40313 var qtree = this._qtree;
michael@0 40314 var invalidRegions = this._invalidRegions;
michael@0 40315 var stack = [];
michael@0 40316 var zindex = 0;
michael@0 40317 var children = this._children;
michael@0 40318 var i = children.length;
michael@0 40319 while (i--) {
michael@0 40320 var child = children[i];
michael@0 40321 if (refreshStage) {
michael@0 40322 child._invalid = true;
michael@0 40323 }
michael@0 40324 child._invisible = !child._visible;
michael@0 40325 stack.push(child);
michael@0 40326 }
michael@0 40327 while (stack.length) {
michael@0 40328 var node = stack.pop();
michael@0 40329 var m = node._concatenatedTransform;
michael@0 40330 var children = node._children;
michael@0 40331 var i = children.length;
michael@0 40332 while (i--) {
michael@0 40333 var child = children[i];
michael@0 40334 if (!flash.display.DisplayObject.class.isInstanceOf(child)) {
michael@0 40335 continue;
michael@0 40336 }
michael@0 40337 if (node._invalid) {
michael@0 40338 child._invalid = true;
michael@0 40339 }
michael@0 40340 if (m.invalid) {
michael@0 40341 child._concatenatedTransform.invalid = true;
michael@0 40342 }
michael@0 40343 child._invisible = node._invisible || !child._visible;
michael@0 40344 stack.push(child);
michael@0 40345 }
michael@0 40346 if (node._level && m.invalid) {
michael@0 40347 var m2 = node._currentTransform;
michael@0 40348 var m3 = node._parent._concatenatedTransform;
michael@0 40349 m.a = m2.a * m3.a + m2.b * m3.c;
michael@0 40350 m.b = m2.a * m3.b + m2.b * m3.d;
michael@0 40351 m.c = m2.c * m3.a + m2.d * m3.c;
michael@0 40352 m.d = m2.d * m3.d + m2.c * m3.b;
michael@0 40353 m.tx = m2.tx * m3.a + m3.tx + m2.ty * m3.c;
michael@0 40354 m.ty = m2.ty * m3.d + m3.ty + m2.tx * m3.b;
michael@0 40355 m.invalid = false;
michael@0 40356 }
michael@0 40357 var invalidRegion = node._region;
michael@0 40358 var currentRegion = node._getRegion(m);
michael@0 40359 var hidden = node._invisible || !currentRegion || currentRegion.xMax - currentRegion.xMin === 0 || currentRegion.yMax - currentRegion.yMin === 0 || currentRegion.xMax <= 0 || currentRegion.xMin >= this._stageWidth || currentRegion.yMax <= 0 || currentRegion.yMin >= this._stageHeight;
michael@0 40360 if (node._invalid) {
michael@0 40361 if (invalidRegion) {
michael@0 40362 invalidRegions.insert(invalidRegion);
michael@0 40363 }
michael@0 40364 if (!hidden && (!invalidRegion || currentRegion.xMin !== invalidRegion.xMin || currentRegion.yMin !== invalidRegion.yMin || currentRegion.xMax !== invalidRegion.xMax || currentRegion.yMax !== invalidRegion.yMax)) {
michael@0 40365 invalidRegions.insert(currentRegion);
michael@0 40366 }
michael@0 40367 }
michael@0 40368 if (hidden) {
michael@0 40369 if (invalidRegion) {
michael@0 40370 qtree.remove(invalidRegion);
michael@0 40371 node._region = null;
michael@0 40372 }
michael@0 40373 } else if (invalidRegion) {
michael@0 40374 invalidRegion.xMin = currentRegion.xMin;
michael@0 40375 invalidRegion.xMax = currentRegion.xMax;
michael@0 40376 invalidRegion.yMin = currentRegion.yMin;
michael@0 40377 invalidRegion.yMax = currentRegion.yMax;
michael@0 40378 qtree.update(invalidRegion);
michael@0 40379 } else {
michael@0 40380 currentRegion.obj = node;
michael@0 40381 qtree.insert(currentRegion);
michael@0 40382 node._region = currentRegion;
michael@0 40383 }
michael@0 40384 node._zindex = zindex++;
michael@0 40385 }
michael@0 40386 var invalidPath = new ShapePath();
michael@0 40387 if (refreshStage) {
michael@0 40388 invalidPath.rect(0, 0, this._stageWidth, this._stageHeight);
michael@0 40389 invalidRegions.reset();
michael@0 40390 return invalidPath;
michael@0 40391 }
michael@0 40392 var redrawRegions = invalidRegions.retrieve();
michael@0 40393 for (var i = 0; i < redrawRegions.length; i++) {
michael@0 40394 var region = redrawRegions[i];
michael@0 40395 var xMin = region.xMin - region.xMin % 20 - 40;
michael@0 40396 var yMin = region.yMin - region.yMin % 20 - 40;
michael@0 40397 var xMax = region.xMax - region.xMax % 20 + 80;
michael@0 40398 var yMax = region.yMax - region.yMax % 20 + 80;
michael@0 40399 var intersectees = qtree.retrieve(xMin, xMax, yMin, yMax);
michael@0 40400 for (var j = 0; j < intersectees.length; j++) {
michael@0 40401 var item = intersectees[j];
michael@0 40402 item.obj._invalid = true;
michael@0 40403 }
michael@0 40404 invalidPath.rect(xMin, yMin, xMax - xMin, yMax - yMin);
michael@0 40405 }
michael@0 40406 invalidRegions.reset();
michael@0 40407 return invalidPath;
michael@0 40408 },
michael@0 40409 _handleMouseButtons: function () {
michael@0 40410 if (this._mouseEvents.length === 0) {
michael@0 40411 return;
michael@0 40412 }
michael@0 40413 var eventType = this._mouseEvents.shift();
michael@0 40414 switch (eventType) {
michael@0 40415 case 'mousedown':
michael@0 40416 if (this._mouseTarget._buttonMode) {
michael@0 40417 this._mouseTarget._gotoButtonState('down');
michael@0 40418 }
michael@0 40419 this._mouseTarget._dispatchEvent('mouseDown');
michael@0 40420 break;
michael@0 40421 case 'mouseup':
michael@0 40422 if (this._mouseTarget._buttonMode) {
michael@0 40423 this._mouseTarget._gotoButtonState('over');
michael@0 40424 }
michael@0 40425 this._mouseTarget._dispatchEvent('mouseUp');
michael@0 40426 break;
michael@0 40427 }
michael@0 40428 },
michael@0 40429 _handleMouse: function handleMouse() {
michael@0 40430 var mouseX = this._mouseX;
michael@0 40431 var mouseY = this._mouseY;
michael@0 40432 var candidates = this._qtree.retrieve(mouseX, mouseX, mouseY, mouseY);
michael@0 40433 var objectsUnderMouse = [];
michael@0 40434 for (var i = 0; i < candidates.length; i++) {
michael@0 40435 var item = candidates[i];
michael@0 40436 var displayObject = item.obj;
michael@0 40437 var isUnderMouse = false;
michael@0 40438 if (flash.display.SimpleButton.class.isInstanceOf(displayObject)) {
michael@0 40439 if (!displayObject._enabled) {
michael@0 40440 continue;
michael@0 40441 }
michael@0 40442 var hitArea = displayObject._hitTestState;
michael@0 40443 hitArea._parent = displayObject;
michael@0 40444 isUnderMouse = hitArea._hitTest(true, mouseX, mouseY, true);
michael@0 40445 hitArea._parent = null;
michael@0 40446 } else {
michael@0 40447 isUnderMouse = displayObject._hitTest(true, mouseX, mouseY, true);
michael@0 40448 }
michael@0 40449 if (isUnderMouse) {
michael@0 40450 var currentNode = displayObject;
michael@0 40451 var lastEnabled = null;
michael@0 40452 if (!flash.display.InteractiveObject.class.isInstanceOf(currentNode)) {
michael@0 40453 lastEnabled = currentNode;
michael@0 40454 currentNode = currentNode._parent;
michael@0 40455 }
michael@0 40456 do {
michael@0 40457 if (!currentNode._mouseEnabled) {
michael@0 40458 lastEnabled = null;
michael@0 40459 } else if (lastEnabled === null) {
michael@0 40460 lastEnabled = currentNode;
michael@0 40461 }
michael@0 40462 currentNode = currentNode._parent;
michael@0 40463 } while (currentNode);
michael@0 40464 objectsUnderMouse.push(lastEnabled);
michael@0 40465 }
michael@0 40466 }
michael@0 40467 var target;
michael@0 40468 if (objectsUnderMouse.length) {
michael@0 40469 objectsUnderMouse.sort(sortByZindex);
michael@0 40470 var i = objectsUnderMouse.length;
michael@0 40471 while (i--) {
michael@0 40472 target = null;
michael@0 40473 var currentNode = objectsUnderMouse[i];
michael@0 40474 if (!flash.display.InteractiveObject.class.isInstanceOf(currentNode)) {
michael@0 40475 var j = i;
michael@0 40476 while (j--) {
michael@0 40477 if (objectsUnderMouse[j]._parent === currentNode._parent && flash.display.InteractiveObject.class.isInstanceOf(objectsUnderMouse[j])) {
michael@0 40478 currentNode = objectsUnderMouse[j];
michael@0 40479 i = j;
michael@0 40480 }
michael@0 40481 }
michael@0 40482 }
michael@0 40483 do {
michael@0 40484 if (flash.display.InteractiveObject.class.isInstanceOf(currentNode)) {
michael@0 40485 if ((!target || !currentNode._mouseChildren) && !currentNode._hitArea) {
michael@0 40486 target = currentNode;
michael@0 40487 }
michael@0 40488 }
michael@0 40489 currentNode = currentNode._parent;
michael@0 40490 } while (currentNode);
michael@0 40491 if (target !== objectsUnderMouse[i] && flash.display.SimpleButton.class.isInstanceOf(target)) {
michael@0 40492 continue;
michael@0 40493 }
michael@0 40494 break;
michael@0 40495 }
michael@0 40496 }
michael@0 40497 if (!target) {
michael@0 40498 target = this;
michael@0 40499 } else if (target._hitTarget) {
michael@0 40500 target = target._hitTarget;
michael@0 40501 }
michael@0 40502 if (target === this._mouseTarget) {
michael@0 40503 target._dispatchEvent('mouseMove');
michael@0 40504 } else {
michael@0 40505 if (this._mouseTarget._buttonMode) {
michael@0 40506 this._mouseTarget._gotoButtonState('up');
michael@0 40507 }
michael@0 40508 this._mouseTarget._dispatchEvent('mouseOut');
michael@0 40509 var nodeLeft = this._mouseTarget;
michael@0 40510 var containerLeft = nodeLeft._parent;
michael@0 40511 var nodeEntered = target;
michael@0 40512 var containerEntered = nodeEntered._parent;
michael@0 40513 var cursor = 'auto';
michael@0 40514 while (nodeLeft._level >= 0 && nodeLeft !== containerEntered) {
michael@0 40515 if (nodeLeft._hasEventListener('rollOut')) {
michael@0 40516 nodeLeft._dispatchEvent('rollOut');
michael@0 40517 }
michael@0 40518 nodeLeft = nodeLeft._parent;
michael@0 40519 }
michael@0 40520 while (nodeEntered._level >= 0 && nodeEntered !== containerLeft) {
michael@0 40521 if (nodeEntered._hasEventListener('rollOver')) {
michael@0 40522 nodeEntered._dispatchEvent('rollOver');
michael@0 40523 }
michael@0 40524 if (nodeEntered._buttonMode && nodeEntered._useHandCursor) {
michael@0 40525 cursor = 'pointer';
michael@0 40526 }
michael@0 40527 nodeEntered = nodeEntered._parent;
michael@0 40528 }
michael@0 40529 if (target._buttonMode) {
michael@0 40530 target._gotoButtonState('over');
michael@0 40531 }
michael@0 40532 target._dispatchEvent('mouseOver');
michael@0 40533 this._mouseTarget = target;
michael@0 40534 this._cursor = cursor;
michael@0 40535 }
michael@0 40536 },
michael@0 40537 _as2SetLevel: function (level, loader) {
michael@0 40538 somewhatImplemented('Stage._as2SetLevel');
michael@0 40539 this.addChild(loader);
michael@0 40540 },
michael@0 40541 __glue__: {
michael@0 40542 native: {
michael@0 40543 instance: {
michael@0 40544 invalidate: function invalidate() {
michael@0 40545 this._invalid = true;
michael@0 40546 this._deferRenderEvent = true;
michael@0 40547 },
michael@0 40548 isFocusInaccessible: function isFocusInaccessible() {
michael@0 40549 notImplemented('Stage.isFocusInaccessible');
michael@0 40550 },
michael@0 40551 set_displayState: function set_displayState(value) {
michael@0 40552 somewhatImplemented('Stage.set_displayState');
michael@0 40553 this._displayState = value;
michael@0 40554 },
michael@0 40555 get_simulatedFullScreenWidth: function get_simulatedFullScreenWidth() {
michael@0 40556 notImplemented('Stage.get_simulatedFullScreenWidth');
michael@0 40557 },
michael@0 40558 get_simulatedFullScreenHeight: function get_simulatedFullScreenHeight() {
michael@0 40559 notImplemented('Stage.get_simulatedFullScreenHeight');
michael@0 40560 },
michael@0 40561 removeChildAt: function removeChildAt(index) {
michael@0 40562 notImplemented('Stage.removeChildAt');
michael@0 40563 },
michael@0 40564 swapChildrenAt: function swapChildrenAt(index1, index2) {
michael@0 40565 notImplemented('Stage.swapChildrenAt');
michael@0 40566 },
michael@0 40567 requireOwnerPermissions: function requireOwnerPermissions() {
michael@0 40568 somewhatImplemented('Stage.requireOwnerPermissions');
michael@0 40569 },
michael@0 40570 frameRate: {
michael@0 40571 get: function frameRate() {
michael@0 40572 return this._frameRate;
michael@0 40573 },
michael@0 40574 set: function frameRate(value) {
michael@0 40575 this._frameRate = value;
michael@0 40576 }
michael@0 40577 },
michael@0 40578 scaleMode: {
michael@0 40579 get: function scaleMode() {
michael@0 40580 return this._scaleMode;
michael@0 40581 },
michael@0 40582 set: function scaleMode(value) {
michael@0 40583 this._scaleMode = value;
michael@0 40584 this._invalid = true;
michael@0 40585 }
michael@0 40586 },
michael@0 40587 align: {
michael@0 40588 get: function align() {
michael@0 40589 return this._align;
michael@0 40590 },
michael@0 40591 set: function align(value) {
michael@0 40592 this._align = value;
michael@0 40593 this._invalid = true;
michael@0 40594 }
michael@0 40595 },
michael@0 40596 stageWidth: {
michael@0 40597 get: function stageWidth() {
michael@0 40598 return this._stageWidth / 20;
michael@0 40599 },
michael@0 40600 set: function stageWidth(value) {
michael@0 40601 notImplemented('Stage.stageWidth');
michael@0 40602 this._stageWidth = value * 20 | 0;
michael@0 40603 }
michael@0 40604 },
michael@0 40605 stageHeight: {
michael@0 40606 get: function stageHeight() {
michael@0 40607 return this._stageHeight / 20;
michael@0 40608 },
michael@0 40609 set: function stageHeight(value) {
michael@0 40610 notImplemented('Stage.stageHeight');
michael@0 40611 this._stageHeight = value * 20 | 0;
michael@0 40612 }
michael@0 40613 },
michael@0 40614 showDefaultContextMenu: {
michael@0 40615 get: function showDefaultContextMenu() {
michael@0 40616 return this._showDefaultContextMenu;
michael@0 40617 },
michael@0 40618 set: function showDefaultContextMenu(value) {
michael@0 40619 somewhatImplemented('Stage.showDefaultContextMenu');
michael@0 40620 this._showDefaultContextMenu = value;
michael@0 40621 }
michael@0 40622 },
michael@0 40623 focus: {
michael@0 40624 get: function focus() {
michael@0 40625 return this._focus;
michael@0 40626 },
michael@0 40627 set: function focus(newFocus) {
michael@0 40628 somewhatImplemented('Stage.focus');
michael@0 40629 this._focus = newFocus;
michael@0 40630 }
michael@0 40631 },
michael@0 40632 colorCorrection: {
michael@0 40633 get: function colorCorrection() {
michael@0 40634 return this._colorCorrection;
michael@0 40635 },
michael@0 40636 set: function colorCorrection(value) {
michael@0 40637 notImplemented('Stage.colorCorrection');
michael@0 40638 this._colorCorrection = value;
michael@0 40639 }
michael@0 40640 },
michael@0 40641 colorCorrectionSupport: {
michael@0 40642 get: function colorCorrectionSupport() {
michael@0 40643 return false;
michael@0 40644 }
michael@0 40645 },
michael@0 40646 stageFocusRect: {
michael@0 40647 get: function stageFocusRect() {
michael@0 40648 return this._stageFocusRect;
michael@0 40649 },
michael@0 40650 set: function stageFocusRect(on) {
michael@0 40651 somewhatImplemented('Stage.stageFocusRect');
michael@0 40652 this._stageFocusRect = on;
michael@0 40653 }
michael@0 40654 },
michael@0 40655 quality: {
michael@0 40656 get: function quality() {
michael@0 40657 return this._quality;
michael@0 40658 },
michael@0 40659 set: function quality(value) {
michael@0 40660 somewhatImplemented('Stage.stageFocusRect');
michael@0 40661 this._quality = value;
michael@0 40662 }
michael@0 40663 },
michael@0 40664 displayState: {
michael@0 40665 get: function displayState() {
michael@0 40666 return this._displayState;
michael@0 40667 },
michael@0 40668 set: function displayState(value) {
michael@0 40669 this._displayState = value;
michael@0 40670 }
michael@0 40671 },
michael@0 40672 simulatedDisplayState: {
michael@0 40673 get: function simulatedDisplayState() {
michael@0 40674 notImplemented('Stage.simulatedDisplayState');
michael@0 40675 return this._simulatedDisplayState;
michael@0 40676 },
michael@0 40677 set: function simulatedDisplayState(value) {
michael@0 40678 notImplemented('Stage.simulatedDisplayState');
michael@0 40679 this._simulatedDisplayState = value;
michael@0 40680 }
michael@0 40681 },
michael@0 40682 fullScreenSourceRect: {
michael@0 40683 get: function fullScreenSourceRect() {
michael@0 40684 return this._fullScreenSourceRect;
michael@0 40685 },
michael@0 40686 set: function fullScreenSourceRect(value) {
michael@0 40687 notImplemented('Stage.fullScreenSourceRect');
michael@0 40688 this._fullScreenSourceRect = value;
michael@0 40689 }
michael@0 40690 },
michael@0 40691 simulatedFullScreenSourceRect: {
michael@0 40692 get: function simulatedFullScreenSourceRect() {
michael@0 40693 notImplemented('Stage.simulatedFullScreenSourceRect');
michael@0 40694 return this._simulatedFullScreenSourceRect;
michael@0 40695 },
michael@0 40696 set: function simulatedFullScreenSourceRect(value) {
michael@0 40697 notImplemented('Stage.simulatedFullScreenSourceRect');
michael@0 40698 this._simulatedFullScreenSourceRect = value;
michael@0 40699 }
michael@0 40700 },
michael@0 40701 stageVideos: {
michael@0 40702 get: function stageVideos() {
michael@0 40703 somewhatImplemented('Stage.stageVideos');
michael@0 40704 return this._stageVideos;
michael@0 40705 }
michael@0 40706 },
michael@0 40707 stage3Ds: {
michael@0 40708 get: function stage3Ds() {
michael@0 40709 notImplemented('Stage.stage3Ds');
michael@0 40710 return this._stage3Ds;
michael@0 40711 }
michael@0 40712 },
michael@0 40713 color: {
michael@0 40714 get: function color() {
michael@0 40715 return this._color;
michael@0 40716 },
michael@0 40717 set: function color(color) {
michael@0 40718 this._color = color;
michael@0 40719 this._invalid = true;
michael@0 40720 }
michael@0 40721 },
michael@0 40722 fullScreenWidth: {
michael@0 40723 get: function fullScreenWidth() {
michael@0 40724 notImplemented('Stage.fullScreenWidth');
michael@0 40725 return this._fullScreenWidth;
michael@0 40726 }
michael@0 40727 },
michael@0 40728 fullScreenHeight: {
michael@0 40729 get: function fullScreenHeight() {
michael@0 40730 notImplemented('Stage.fullScreenHeight');
michael@0 40731 return this._fullScreenHeight;
michael@0 40732 }
michael@0 40733 },
michael@0 40734 wmodeGPU: {
michael@0 40735 get: function wmodeGPU() {
michael@0 40736 somewhatImplemented('Stage.wmodeGPU');
michael@0 40737 return this._wmodeGPU;
michael@0 40738 }
michael@0 40739 },
michael@0 40740 softKeyboardRect: {
michael@0 40741 get: function softKeyboardRect() {
michael@0 40742 notImplemented('Stage.softKeyboardRect');
michael@0 40743 return this._softKeyboardRect;
michael@0 40744 }
michael@0 40745 },
michael@0 40746 allowsFullScreen: {
michael@0 40747 get: function allowsFullScreen() {
michael@0 40748 return false;
michael@0 40749 }
michael@0 40750 },
michael@0 40751 displayContextInfo: {
michael@0 40752 get: function displayContextInfo() {
michael@0 40753 notImplemented('Stage.displayContextInfo');
michael@0 40754 return this._displayContextInfo;
michael@0 40755 }
michael@0 40756 }
michael@0 40757 }
michael@0 40758 }
michael@0 40759 }
michael@0 40760 };
michael@0 40761 }.call(this);
michael@0 40762 {
michael@0 40763 var EventDefinition = function () {
michael@0 40764 return {
michael@0 40765 __class__: 'flash.events.Event',
michael@0 40766 initialize: function () {
michael@0 40767 this._stopPropagation = false;
michael@0 40768 this._stopImmediatePropagation = false;
michael@0 40769 this._isDefaultPrevented = false;
michael@0 40770 this._target = null;
michael@0 40771 this._currentTarget = null;
michael@0 40772 this._eventPhase = 2;
michael@0 40773 },
michael@0 40774 __glue__: {
michael@0 40775 native: {
michael@0 40776 instance: {
michael@0 40777 ctor: function ctor(type, bubbles, cancelable) {
michael@0 40778 Counter.count('Event: ' + type);
michael@0 40779 this._type = type;
michael@0 40780 this._bubbles = bubbles;
michael@0 40781 this._cancelable = cancelable;
michael@0 40782 },
michael@0 40783 stopPropagation: function stopPropagation() {
michael@0 40784 this._stopPropagation = true;
michael@0 40785 },
michael@0 40786 stopImmediatePropagation: function stopImmediatePropagation() {
michael@0 40787 this._stopImmediatePropagation = this._stopPropagation = true;
michael@0 40788 },
michael@0 40789 preventDefault: function preventDefault() {
michael@0 40790 if (this._cancelable)
michael@0 40791 this._isDefaultPrevented = true;
michael@0 40792 },
michael@0 40793 isDefaultPrevented: function isDefaultPrevented() {
michael@0 40794 return this._isDefaultPrevented;
michael@0 40795 },
michael@0 40796 type: {
michael@0 40797 get: function type() {
michael@0 40798 return this._type;
michael@0 40799 }
michael@0 40800 },
michael@0 40801 bubbles: {
michael@0 40802 get: function bubbles() {
michael@0 40803 return this._bubbles;
michael@0 40804 }
michael@0 40805 },
michael@0 40806 cancelable: {
michael@0 40807 get: function cancelable() {
michael@0 40808 return this._cancelable;
michael@0 40809 }
michael@0 40810 },
michael@0 40811 target: {
michael@0 40812 get: function target() {
michael@0 40813 return this._target;
michael@0 40814 }
michael@0 40815 },
michael@0 40816 currentTarget: {
michael@0 40817 get: function currentTarget() {
michael@0 40818 return this._currentTarget;
michael@0 40819 }
michael@0 40820 },
michael@0 40821 eventPhase: {
michael@0 40822 get: function eventPhase() {
michael@0 40823 return this._eventPhase;
michael@0 40824 }
michael@0 40825 }
michael@0 40826 }
michael@0 40827 },
michael@0 40828 script: {
michael@0 40829 static: Glue.ALL,
michael@0 40830 instance: {
michael@0 40831 clone: 'open public clone'
michael@0 40832 }
michael@0 40833 }
michael@0 40834 }
michael@0 40835 };
michael@0 40836 }.call(this);
michael@0 40837 }
michael@0 40838 var EventDispatcherDefinition = function () {
michael@0 40839 var mouseEvents = {
michael@0 40840 click: true,
michael@0 40841 contextMenu: true,
michael@0 40842 doubleClick: true,
michael@0 40843 middleClick: true,
michael@0 40844 middleMouseDown: true,
michael@0 40845 middleMouseUp: true,
michael@0 40846 mouseDown: true,
michael@0 40847 mouseMove: true,
michael@0 40848 mouseOut: true,
michael@0 40849 mouseOver: true,
michael@0 40850 mouseUp: true,
michael@0 40851 mouseWheel: true,
michael@0 40852 releaseOutside: true,
michael@0 40853 rightClick: true,
michael@0 40854 rightMouseDown: true,
michael@0 40855 rightMouseUp: true,
michael@0 40856 rollOut: false,
michael@0 40857 rollOver: false
michael@0 40858 };
michael@0 40859 function doDispatchEvent(dispatcher, event, eventClass, bubbles) {
michael@0 40860 var target = dispatcher._target;
michael@0 40861 var type = event._type || event;
michael@0 40862 var listeners = dispatcher._listeners[type];
michael@0 40863 if (bubbles || typeof event === 'string' && mouseEvents[event] || event._bubbles) {
michael@0 40864 var ancestors = [];
michael@0 40865 var currentNode = target._parent;
michael@0 40866 while (currentNode) {
michael@0 40867 if (currentNode._hasEventListener(type)) {
michael@0 40868 ancestors.push(currentNode);
michael@0 40869 }
michael@0 40870 currentNode = currentNode._parent;
michael@0 40871 }
michael@0 40872 if (!listeners && !ancestors.length) {
michael@0 40873 return true;
michael@0 40874 }
michael@0 40875 var keepPropagating = true;
michael@0 40876 var i = ancestors.length;
michael@0 40877 while (i-- && keepPropagating) {
michael@0 40878 var currentTarget = ancestors[i];
michael@0 40879 var queue = currentTarget._captureListeners[type];
michael@0 40880 keepPropagating = processListeners(queue, event, eventClass, bubbles, target, currentTarget, 1);
michael@0 40881 }
michael@0 40882 if (listeners && keepPropagating) {
michael@0 40883 keepPropagating = processListeners(listeners, event, eventClass, bubbles, target);
michael@0 40884 }
michael@0 40885 for (var i = 0; i < ancestors.length && keepPropagating; i++) {
michael@0 40886 var currentTarget = ancestors[i];
michael@0 40887 var queue = currentTarget._listeners[type];
michael@0 40888 keepPropagating = processListeners(queue, event, eventClass, bubbles, target, currentTarget, 3);
michael@0 40889 }
michael@0 40890 } else if (listeners) {
michael@0 40891 processListeners(listeners, event, eventClass, bubbles, target);
michael@0 40892 }
michael@0 40893 return !event._isDefaultPrevented;
michael@0 40894 }
michael@0 40895 function processListeners(queue, event, eventClass, bubbles, target, currentTarget, eventPhase) {
michael@0 40896 if (queue) {
michael@0 40897 queue = queue.slice();
michael@0 40898 var needsInit = true;
michael@0 40899 try {
michael@0 40900 for (var i = 0; i < queue.length; i++) {
michael@0 40901 var item = queue[i];
michael@0 40902 var methodInfo = item.handleEvent.methodInfo;
michael@0 40903 if (methodInfo) {
michael@0 40904 if (methodInfo.parameters.length) {
michael@0 40905 if (!methodInfo.parameters[0].isUsed) {
michael@0 40906 item.handleEvent();
michael@0 40907 continue;
michael@0 40908 }
michael@0 40909 }
michael@0 40910 }
michael@0 40911 if (needsInit) {
michael@0 40912 if (typeof event === 'string') {
michael@0 40913 if (eventClass) {
michael@0 40914 event = new eventClass(event);
michael@0 40915 } else {
michael@0 40916 if (mouseEvents[event]) {
michael@0 40917 event = new flash.events.MouseEvent(event, mouseEvents[event]);
michael@0 40918 if (target._stage) {
michael@0 40919 event._localX = target.mouseX;
michael@0 40920 event._localY = target.mouseY;
michael@0 40921 }
michael@0 40922 } else {
michael@0 40923 event = new flash.events.Event(event);
michael@0 40924 }
michael@0 40925 }
michael@0 40926 } else if (event._target) {
michael@0 40927 event = event.clone();
michael@0 40928 }
michael@0 40929 event._target = target;
michael@0 40930 event._currentTarget = currentTarget || target;
michael@0 40931 event._eventPhase = eventPhase || 2;
michael@0 40932 needsInit = false;
michael@0 40933 }
michael@0 40934 item.handleEvent(event);
michael@0 40935 if (event._stopImmediatePropagation) {
michael@0 40936 break;
michael@0 40937 }
michael@0 40938 }
michael@0 40939 } catch (e) {
michael@0 40940 avm2.exceptions.push({
michael@0 40941 source: 'avm2',
michael@0 40942 message: e.message,
michael@0 40943 stack: e.stack
michael@0 40944 });
michael@0 40945 throw e;
michael@0 40946 }
michael@0 40947 }
michael@0 40948 return !event._stopPropagation;
michael@0 40949 }
michael@0 40950 return {
michael@0 40951 __class__: 'flash.events.EventDispatcher',
michael@0 40952 initialize: function () {
michael@0 40953 this._target = this;
michael@0 40954 this._listeners = {};
michael@0 40955 this._captureListeners = {};
michael@0 40956 },
michael@0 40957 _addEventListenerImpl: function addEventListenerImpl(type, listener, useCapture, priority) {
michael@0 40958 if (typeof listener !== 'function') {
michael@0 40959 throwError('TypeError', Errors.CheckTypeFailedError, listener, 'Function');
michael@0 40960 }
michael@0 40961 var listeners = useCapture ? this._captureListeners : this._listeners;
michael@0 40962 var queue = listeners[type];
michael@0 40963 var listenerObj = {
michael@0 40964 handleEvent: listener,
michael@0 40965 priority: priority || 0
michael@0 40966 };
michael@0 40967 if (queue) {
michael@0 40968 var level = queue.length;
michael@0 40969 var i = level;
michael@0 40970 while (i--) {
michael@0 40971 var item = queue[i];
michael@0 40972 if (item.handleEvent === listener) {
michael@0 40973 return;
michael@0 40974 }
michael@0 40975 if (priority > item.priority) {
michael@0 40976 level = i;
michael@0 40977 }
michael@0 40978 }
michael@0 40979 queue.splice(level, 0, listenerObj);
michael@0 40980 } else {
michael@0 40981 listeners[type] = [
michael@0 40982 listenerObj
michael@0 40983 ];
michael@0 40984 }
michael@0 40985 },
michael@0 40986 _addEventListener: function addEventListener(type, listener, useCapture, priority) {
michael@0 40987 this._addEventListenerImpl(type, listener, useCapture, priority);
michael@0 40988 },
michael@0 40989 _removeEventListenerImpl: function removeEventListenerImpl(type, listener, useCapture) {
michael@0 40990 if (typeof listener !== 'function') {
michael@0 40991 throwError('TypeError', Errors.CheckTypeFailedError, listener, 'Function');
michael@0 40992 }
michael@0 40993 var listeners = useCapture ? this._captureListeners : this._listeners;
michael@0 40994 var queue = listeners[type];
michael@0 40995 if (queue) {
michael@0 40996 for (var i = 0; i < queue.length; i++) {
michael@0 40997 var item = queue[i];
michael@0 40998 if (item.handleEvent === listener) {
michael@0 40999 queue.splice(i, 1);
michael@0 41000 if (!queue.length) {
michael@0 41001 listeners[type] = null;
michael@0 41002 }
michael@0 41003 return;
michael@0 41004 }
michael@0 41005 }
michael@0 41006 }
michael@0 41007 },
michael@0 41008 _removeEventListener: function removeEventListener(type, listener, useCapture) {
michael@0 41009 this._removeEventListenerImpl(type, listener, useCapture);
michael@0 41010 },
michael@0 41011 _hasEventListener: function hasEventListener(type) {
michael@0 41012 return this._listeners[type] || this._captureListeners[type];
michael@0 41013 },
michael@0 41014 _dispatchEvent: function dispatchEvent(event, eventClass, bubbles) {
michael@0 41015 doDispatchEvent(this, event, eventClass, bubbles);
michael@0 41016 },
michael@0 41017 __glue__: {
michael@0 41018 native: {
michael@0 41019 instance: {
michael@0 41020 ctor: function ctor(target) {
michael@0 41021 this._target = target || this;
michael@0 41022 },
michael@0 41023 addEventListener: function addEventListener(type, listener, useCapture, priority, useWeakReference) {
michael@0 41024 this._addEventListener(type, listener, useCapture, priority);
michael@0 41025 },
michael@0 41026 removeEventListener: function removeEventListener(type, listener, useCapture) {
michael@0 41027 this._removeEventListener(type, listener, useCapture);
michael@0 41028 },
michael@0 41029 hasEventListener: function hasEventListener(type) {
michael@0 41030 return this._hasEventListener(type);
michael@0 41031 },
michael@0 41032 willTrigger: function willTrigger(type) {
michael@0 41033 var currentNode = this._target;
michael@0 41034 do {
michael@0 41035 if (currentNode._hasEventListener(type)) {
michael@0 41036 return true;
michael@0 41037 }
michael@0 41038 } while (currentNode = currentNode._parent);
michael@0 41039 return false;
michael@0 41040 },
michael@0 41041 dispatchEventFunction: function dispatchEventFunction(event) {
michael@0 41042 return doDispatchEvent(this, event);
michael@0 41043 }
michael@0 41044 }
michael@0 41045 }
michael@0 41046 }
michael@0 41047 };
michael@0 41048 }.call(this);
michael@0 41049 var KeyboardEventDefinition = function () {
michael@0 41050 return {
michael@0 41051 __class__: 'flash.events.KeyboardEvent',
michael@0 41052 __glue__: {
michael@0 41053 native: {
michael@0 41054 instance: {
michael@0 41055 updateAfterEvent: function updateAfterEvent() {
michael@0 41056 notImplemented('KeyboardEvent.updateAfterEvent');
michael@0 41057 },
michael@0 41058 charCode: {
michael@0 41059 get: function charCode() {
michael@0 41060 return this._charCode;
michael@0 41061 },
michael@0 41062 set: function charCode(value) {
michael@0 41063 this._charCode = value;
michael@0 41064 }
michael@0 41065 },
michael@0 41066 ctrlKey: {
michael@0 41067 get: function ctrlKey() {
michael@0 41068 return this._ctrlKey;
michael@0 41069 },
michael@0 41070 set: function ctrlKey(value) {
michael@0 41071 this._ctrlKey = value;
michael@0 41072 }
michael@0 41073 },
michael@0 41074 altKey: {
michael@0 41075 get: function altKey() {
michael@0 41076 return this._altKey;
michael@0 41077 },
michael@0 41078 set: function altKey(value) {
michael@0 41079 this._altKey = value;
michael@0 41080 }
michael@0 41081 },
michael@0 41082 shiftKey: {
michael@0 41083 get: function shiftKey() {
michael@0 41084 return this._shiftKey;
michael@0 41085 },
michael@0 41086 set: function shiftKey(value) {
michael@0 41087 this._shiftKey = value;
michael@0 41088 }
michael@0 41089 }
michael@0 41090 }
michael@0 41091 },
michael@0 41092 script: {
michael@0 41093 static: Glue.ALL,
michael@0 41094 instance: {
michael@0 41095 keyCode: 'public keyCode'
michael@0 41096 }
michael@0 41097 }
michael@0 41098 }
michael@0 41099 };
michael@0 41100 }.call(this);
michael@0 41101 var MouseEventDefinition = function () {
michael@0 41102 return {
michael@0 41103 __class__: 'flash.events.MouseEvent',
michael@0 41104 initialize: function () {
michael@0 41105 this._localX = NaN;
michael@0 41106 this._localY = NaN;
michael@0 41107 },
michael@0 41108 __glue__: {
michael@0 41109 native: {
michael@0 41110 instance: {
michael@0 41111 updateAfterEvent: function updateAfterEvent() {
michael@0 41112 },
michael@0 41113 getStageX: function getStageX() {
michael@0 41114 if (this._target) {
michael@0 41115 var m = this._target._getConcatenatedTransform(null, false);
michael@0 41116 var x = m.a * this._localX + m.c * this._localY + m.tx;
michael@0 41117 return x / 20;
michael@0 41118 }
michael@0 41119 return this._localX / 20;
michael@0 41120 },
michael@0 41121 getStageY: function getStageY() {
michael@0 41122 if (this._target) {
michael@0 41123 var m = this._target._getConcatenatedTransform(null, false);
michael@0 41124 var y = m.d * this._localY + m.b * this._localX + m.ty;
michael@0 41125 return y / 20;
michael@0 41126 }
michael@0 41127 return this._localY / 20;
michael@0 41128 },
michael@0 41129 localX: {
michael@0 41130 get: function localX() {
michael@0 41131 return this._localX / 20;
michael@0 41132 },
michael@0 41133 set: function localX(value) {
michael@0 41134 this._localX = value * 20 | 0;
michael@0 41135 }
michael@0 41136 },
michael@0 41137 localY: {
michael@0 41138 get: function localY() {
michael@0 41139 return this._localY / 20;
michael@0 41140 },
michael@0 41141 set: function localY(value) {
michael@0 41142 this._localY = value * 20 | 0;
michael@0 41143 }
michael@0 41144 }
michael@0 41145 }
michael@0 41146 },
michael@0 41147 script: {
michael@0 41148 static: Glue.ALL
michael@0 41149 }
michael@0 41150 }
michael@0 41151 };
michael@0 41152 }.call(this);
michael@0 41153 var TextEventDefinition = function () {
michael@0 41154 return {
michael@0 41155 __class__: 'flash.events.TextEvent',
michael@0 41156 __glue__: {
michael@0 41157 native: {
michael@0 41158 instance: {
michael@0 41159 copyNativeData: function copyNativeData(other) {
michael@0 41160 notImplemented('TextEvent.copyNativeData');
michael@0 41161 }
michael@0 41162 }
michael@0 41163 }
michael@0 41164 }
michael@0 41165 };
michael@0 41166 }.call(this);
michael@0 41167 var TimerEventDefinition = function () {
michael@0 41168 return {
michael@0 41169 __class__: 'flash.events.TimerEvent',
michael@0 41170 __glue__: {
michael@0 41171 native: {
michael@0 41172 instance: {
michael@0 41173 updateAfterEvent: function updateAfterEvent() {
michael@0 41174 notImplemented('TimerEvent.updateAfterEvent');
michael@0 41175 }
michael@0 41176 }
michael@0 41177 }
michael@0 41178 }
michael@0 41179 };
michael@0 41180 }.call(this);
michael@0 41181 {
michael@0 41182 var ExternalInterfaceDefinition = function () {
michael@0 41183 function getAvailable() {
michael@0 41184 return true;
michael@0 41185 }
michael@0 41186 var initialized = false;
michael@0 41187 var registeredCallbacks = {};
michael@0 41188 function callIn(functionName, args) {
michael@0 41189 if (!registeredCallbacks.hasOwnProperty(functionName))
michael@0 41190 return;
michael@0 41191 return registeredCallbacks[functionName](functionName, args);
michael@0 41192 }
michael@0 41193 return {
michael@0 41194 __class__: 'flash.external.ExternalInterface',
michael@0 41195 initialize: function () {
michael@0 41196 },
michael@0 41197 __glue__: {
michael@0 41198 native: {
michael@0 41199 static: {
michael@0 41200 _initJS: function _initJS() {
michael@0 41201 if (initialized)
michael@0 41202 return;
michael@0 41203 TelemetryService.reportTelemetry({
michael@0 41204 topic: 'feature',
michael@0 41205 feature: EXTERNAL_INTERFACE_FEATURE
michael@0 41206 });
michael@0 41207 initialized = true;
michael@0 41208 FirefoxCom.initJS(callIn);
michael@0 41209 },
michael@0 41210 _getPropNames: function _getPropNames(obj) {
michael@0 41211 var keys = [];
michael@0 41212 forEachPublicProperty(obj, function (key) {
michael@0 41213 keys.push(key);
michael@0 41214 });
michael@0 41215 return keys;
michael@0 41216 },
michael@0 41217 _addCallback: function _addCallback(functionName, closure, hasNullCallback) {
michael@0 41218 FirefoxCom.request('externalCom', {
michael@0 41219 action: 'register',
michael@0 41220 functionName: functionName,
michael@0 41221 remove: hasNullCallback
michael@0 41222 });
michael@0 41223 if (hasNullCallback) {
michael@0 41224 delete registeredCallbacks[functionName];
michael@0 41225 } else {
michael@0 41226 registeredCallbacks[functionName] = closure;
michael@0 41227 }
michael@0 41228 },
michael@0 41229 _evalJS: function _evalJS(expression) {
michael@0 41230 return FirefoxCom.requestSync('externalCom', {
michael@0 41231 action: 'eval',
michael@0 41232 expression: expression
michael@0 41233 });
michael@0 41234 },
michael@0 41235 _callOut: function _callOut(request) {
michael@0 41236 return FirefoxCom.requestSync('externalCom', {
michael@0 41237 action: 'call',
michael@0 41238 request: request
michael@0 41239 });
michael@0 41240 },
michael@0 41241 available: {
michael@0 41242 get: getAvailable
michael@0 41243 },
michael@0 41244 objectID: {
michael@0 41245 get: function objectID() {
michael@0 41246 return FirefoxCom.requestSync('externalCom', {
michael@0 41247 action: 'getId'
michael@0 41248 });
michael@0 41249 }
michael@0 41250 },
michael@0 41251 activeX: {
michael@0 41252 get: function activeX() {
michael@0 41253 return false;
michael@0 41254 }
michael@0 41255 }
michael@0 41256 },
michael@0 41257 instance: {}
michael@0 41258 }
michael@0 41259 }
michael@0 41260 };
michael@0 41261 }.call(this);
michael@0 41262 }
michael@0 41263 {
michael@0 41264 var BevelFilterDefinition = function () {
michael@0 41265 var def = {
michael@0 41266 __class__: 'flash.filters.BevelFilter',
michael@0 41267 initialize: function () {
michael@0 41268 },
michael@0 41269 _updateFilterBounds: function (bounds) {
michael@0 41270 }
michael@0 41271 };
michael@0 41272 def.__glue__ = {};
michael@0 41273 return def;
michael@0 41274 }.call(this);
michael@0 41275 }
michael@0 41276 var BitmapFilterDefinition = function () {
michael@0 41277 var def = {
michael@0 41278 __class__: 'flash.filters.BitmapFilter',
michael@0 41279 initialize: function () {
michael@0 41280 },
michael@0 41281 _updateFilterBounds: function (bounds) {
michael@0 41282 }
michael@0 41283 };
michael@0 41284 def.__glue__ = {};
michael@0 41285 return def;
michael@0 41286 }.call(this);
michael@0 41287 var BlurFilterDefinition = function () {
michael@0 41288 return {
michael@0 41289 __class__: 'flash.filters.BlurFilter',
michael@0 41290 initialize: function () {
michael@0 41291 },
michael@0 41292 _updateFilterBounds: function (bounds) {
michael@0 41293 var bx = this._blurX * this._quality * 20;
michael@0 41294 var by = this._blurY * this._quality * 20;
michael@0 41295 bounds.xMin -= bx;
michael@0 41296 bounds.xMax += bx;
michael@0 41297 bounds.yMin -= by;
michael@0 41298 bounds.yMax += by;
michael@0 41299 },
michael@0 41300 __glue__: {
michael@0 41301 native: {
michael@0 41302 static: {},
michael@0 41303 instance: {
michael@0 41304 blurX: {
michael@0 41305 get: function blurX() {
michael@0 41306 return this._blurX;
michael@0 41307 },
michael@0 41308 set: function blurX(value) {
michael@0 41309 this._blurX = value;
michael@0 41310 }
michael@0 41311 },
michael@0 41312 blurY: {
michael@0 41313 get: function blurY() {
michael@0 41314 return this._blurY;
michael@0 41315 },
michael@0 41316 set: function blurY(value) {
michael@0 41317 this._blurY = value;
michael@0 41318 }
michael@0 41319 },
michael@0 41320 quality: {
michael@0 41321 get: function quality() {
michael@0 41322 return this._quality;
michael@0 41323 },
michael@0 41324 set: function quality(value) {
michael@0 41325 this._quality = value;
michael@0 41326 }
michael@0 41327 }
michael@0 41328 }
michael@0 41329 }
michael@0 41330 }
michael@0 41331 };
michael@0 41332 }.call(this);
michael@0 41333 var ColorMatrixFilterDefinition = function () {
michael@0 41334 return {
michael@0 41335 __class__: 'flash.filters.ColorMatrixFilter',
michael@0 41336 initialize: function () {
michael@0 41337 },
michael@0 41338 _updateFilterBounds: function (bounds) {
michael@0 41339 },
michael@0 41340 __glue__: {
michael@0 41341 native: {
michael@0 41342 instance: {
michael@0 41343 matrix: {
michael@0 41344 get: function matrix() {
michael@0 41345 return this._matrix;
michael@0 41346 },
michael@0 41347 set: function matrix(value) {
michael@0 41348 this._matrix = value;
michael@0 41349 }
michael@0 41350 }
michael@0 41351 }
michael@0 41352 }
michael@0 41353 }
michael@0 41354 };
michael@0 41355 }.call(this);
michael@0 41356 var ConvolutionFilterDefinition = function () {
michael@0 41357 var def = {
michael@0 41358 __class__: 'flash.filters.ConvolutionFilter',
michael@0 41359 initialize: function () {
michael@0 41360 },
michael@0 41361 _updateFilterBounds: function (bounds) {
michael@0 41362 }
michael@0 41363 };
michael@0 41364 def.__glue__ = {};
michael@0 41365 return def;
michael@0 41366 }.call(this);
michael@0 41367 var DisplacementMapFilterDefinition = function () {
michael@0 41368 var def = {
michael@0 41369 __class__: 'flash.filters.DisplacementMapFilter',
michael@0 41370 initialize: function () {
michael@0 41371 },
michael@0 41372 _updateFilterBounds: function (bounds) {
michael@0 41373 }
michael@0 41374 };
michael@0 41375 def.__glue__ = {};
michael@0 41376 return def;
michael@0 41377 }.call(this);
michael@0 41378 var DropShadowFilterDefinition = function () {
michael@0 41379 return {
michael@0 41380 __class__: 'flash.filters.DropShadowFilter',
michael@0 41381 initialize: function () {
michael@0 41382 },
michael@0 41383 _updateFilterBounds: function (bounds) {
michael@0 41384 var a = this._angle * Math.PI / 180;
michael@0 41385 var dy = Math.sin(a) * this._distance;
michael@0 41386 var dx = Math.cos(a) * this._distance;
michael@0 41387 var bx = this._blurX * this._quality * 20;
michael@0 41388 var by = this._blurY * this._quality * 20;
michael@0 41389 bounds.xMin -= bx - (dx > 0 ? 0 : dx);
michael@0 41390 bounds.xMax += bx + Math.abs(dx);
michael@0 41391 bounds.yMin -= by - (dy > 0 ? 0 : dy);
michael@0 41392 bounds.yMax += by + Math.abs(dy);
michael@0 41393 },
michael@0 41394 __glue__: {
michael@0 41395 native: {
michael@0 41396 instance: {
michael@0 41397 distance: {
michael@0 41398 get: function distance() {
michael@0 41399 return this._distance;
michael@0 41400 },
michael@0 41401 set: function distance(value) {
michael@0 41402 this._distance = value;
michael@0 41403 }
michael@0 41404 },
michael@0 41405 angle: {
michael@0 41406 get: function angle() {
michael@0 41407 return this._angle;
michael@0 41408 },
michael@0 41409 set: function angle(value) {
michael@0 41410 this._angle = value;
michael@0 41411 }
michael@0 41412 },
michael@0 41413 color: {
michael@0 41414 get: function color() {
michael@0 41415 return this._color;
michael@0 41416 },
michael@0 41417 set: function color(value) {
michael@0 41418 this._color = value;
michael@0 41419 }
michael@0 41420 },
michael@0 41421 alpha: {
michael@0 41422 get: function alpha() {
michael@0 41423 return this._alpha;
michael@0 41424 },
michael@0 41425 set: function alpha(value) {
michael@0 41426 this._alpha = value;
michael@0 41427 }
michael@0 41428 },
michael@0 41429 blurX: {
michael@0 41430 get: function blurX() {
michael@0 41431 return this._blurX;
michael@0 41432 },
michael@0 41433 set: function blurX(value) {
michael@0 41434 this._blurX = value;
michael@0 41435 }
michael@0 41436 },
michael@0 41437 blurY: {
michael@0 41438 get: function blurY() {
michael@0 41439 return this._blurY;
michael@0 41440 },
michael@0 41441 set: function blurY(value) {
michael@0 41442 this._blurY = value;
michael@0 41443 }
michael@0 41444 },
michael@0 41445 hideObject: {
michael@0 41446 get: function hideObject() {
michael@0 41447 return this._hideObject;
michael@0 41448 },
michael@0 41449 set: function hideObject(value) {
michael@0 41450 this._hideObject = value;
michael@0 41451 }
michael@0 41452 },
michael@0 41453 inner: {
michael@0 41454 get: function inner() {
michael@0 41455 return this._inner;
michael@0 41456 },
michael@0 41457 set: function inner(value) {
michael@0 41458 this._inner = value;
michael@0 41459 }
michael@0 41460 },
michael@0 41461 knockout: {
michael@0 41462 get: function knockout() {
michael@0 41463 return this._knockout;
michael@0 41464 },
michael@0 41465 set: function knockout(value) {
michael@0 41466 this._knockout = value;
michael@0 41467 }
michael@0 41468 },
michael@0 41469 quality: {
michael@0 41470 get: function quality() {
michael@0 41471 return this._quality;
michael@0 41472 },
michael@0 41473 set: function quality(value) {
michael@0 41474 this._quality = value;
michael@0 41475 }
michael@0 41476 },
michael@0 41477 strength: {
michael@0 41478 get: function strength() {
michael@0 41479 return this._strength;
michael@0 41480 },
michael@0 41481 set: function strength(value) {
michael@0 41482 this._strength = value;
michael@0 41483 }
michael@0 41484 }
michael@0 41485 }
michael@0 41486 }
michael@0 41487 }
michael@0 41488 };
michael@0 41489 }.call(this);
michael@0 41490 var GlowFilterDefinition = function () {
michael@0 41491 return {
michael@0 41492 __class__: 'flash.filters.GlowFilter',
michael@0 41493 initialize: function () {
michael@0 41494 },
michael@0 41495 _updateFilterBounds: function (bounds) {
michael@0 41496 var bx = this._blurX * this._quality * 20;
michael@0 41497 var by = this._blurY * this._quality * 20;
michael@0 41498 bounds.xMin -= bx;
michael@0 41499 bounds.xMax += bx;
michael@0 41500 bounds.yMin -= by;
michael@0 41501 bounds.yMax += by;
michael@0 41502 },
michael@0 41503 __glue__: {
michael@0 41504 native: {
michael@0 41505 static: {},
michael@0 41506 instance: {
michael@0 41507 color: {
michael@0 41508 get: function color() {
michael@0 41509 return this._color;
michael@0 41510 },
michael@0 41511 set: function color(value) {
michael@0 41512 this._color = value;
michael@0 41513 }
michael@0 41514 },
michael@0 41515 alpha: {
michael@0 41516 get: function alpha() {
michael@0 41517 return this._alpha;
michael@0 41518 },
michael@0 41519 set: function alpha(value) {
michael@0 41520 this._alpha = value;
michael@0 41521 }
michael@0 41522 },
michael@0 41523 blurX: {
michael@0 41524 get: function blurX() {
michael@0 41525 return this._blurX;
michael@0 41526 },
michael@0 41527 set: function blurX(value) {
michael@0 41528 this._blurX = value;
michael@0 41529 }
michael@0 41530 },
michael@0 41531 blurY: {
michael@0 41532 get: function blurY() {
michael@0 41533 return this._blurY;
michael@0 41534 },
michael@0 41535 set: function blurY(value) {
michael@0 41536 this._blurY = value;
michael@0 41537 }
michael@0 41538 },
michael@0 41539 inner: {
michael@0 41540 get: function inner() {
michael@0 41541 return this._inner;
michael@0 41542 },
michael@0 41543 set: function inner(value) {
michael@0 41544 this._inner = value;
michael@0 41545 }
michael@0 41546 },
michael@0 41547 knockout: {
michael@0 41548 get: function knockout() {
michael@0 41549 return this._knockout;
michael@0 41550 },
michael@0 41551 set: function knockout(value) {
michael@0 41552 this._knockout = value;
michael@0 41553 }
michael@0 41554 },
michael@0 41555 quality: {
michael@0 41556 get: function quality() {
michael@0 41557 return this._quality;
michael@0 41558 },
michael@0 41559 set: function quality(value) {
michael@0 41560 this._quality = value;
michael@0 41561 }
michael@0 41562 },
michael@0 41563 strength: {
michael@0 41564 get: function strength() {
michael@0 41565 return this._strength;
michael@0 41566 },
michael@0 41567 set: function strength(value) {
michael@0 41568 this._strength = value;
michael@0 41569 }
michael@0 41570 }
michael@0 41571 }
michael@0 41572 }
michael@0 41573 }
michael@0 41574 };
michael@0 41575 }.call(this);
michael@0 41576 var GradientBevelFilterDefinition = function () {
michael@0 41577 var def = {
michael@0 41578 __class__: 'flash.filters.GradientBevelFilter',
michael@0 41579 initialize: function () {
michael@0 41580 },
michael@0 41581 _updateFilterBounds: function (bounds) {
michael@0 41582 }
michael@0 41583 };
michael@0 41584 def.__glue__ = {};
michael@0 41585 return def;
michael@0 41586 }.call(this);
michael@0 41587 var GradientGlowFilterDefinition = function () {
michael@0 41588 var def = {
michael@0 41589 __class__: 'flash.filters.GradientGlowFilter',
michael@0 41590 initialize: function () {
michael@0 41591 },
michael@0 41592 _updateFilterBounds: function (bounds) {
michael@0 41593 }
michael@0 41594 };
michael@0 41595 def.__glue__ = {};
michael@0 41596 return def;
michael@0 41597 }.call(this);
michael@0 41598 var ShaderFilterDefinition = function () {
michael@0 41599 var def = {
michael@0 41600 __class__: 'flash.filters.ShaderFilter',
michael@0 41601 initialize: function () {
michael@0 41602 },
michael@0 41603 _updateFilterBounds: function (bounds) {
michael@0 41604 }
michael@0 41605 };
michael@0 41606 def.__glue__ = {};
michael@0 41607 return def;
michael@0 41608 }.call(this);
michael@0 41609 {
michael@0 41610 var ColorTransformDefinition = function () {
michael@0 41611 return {
michael@0 41612 __class__: 'flash.geom.ColorTransform',
michael@0 41613 __glue__: {
michael@0 41614 script: {
michael@0 41615 instance: Glue.ALL
michael@0 41616 }
michael@0 41617 }
michael@0 41618 };
michael@0 41619 }.call(this);
michael@0 41620 }
michael@0 41621 var MatrixDefinition = function () {
michael@0 41622 return {
michael@0 41623 __class__: 'flash.geom.Matrix',
michael@0 41624 __glue__: {
michael@0 41625 script: {
michael@0 41626 instance: Glue.ALL
michael@0 41627 }
michael@0 41628 }
michael@0 41629 };
michael@0 41630 }.call(this);
michael@0 41631 var Matrix3DDefinition = function () {
michael@0 41632 var precision = 1e-7;
michael@0 41633 var transposeTransform = new Uint32Array([
michael@0 41634 0,
michael@0 41635 4,
michael@0 41636 8,
michael@0 41637 12,
michael@0 41638 1,
michael@0 41639 5,
michael@0 41640 9,
michael@0 41641 13,
michael@0 41642 2,
michael@0 41643 6,
michael@0 41644 10,
michael@0 41645 14,
michael@0 41646 3,
michael@0 41647 7,
michael@0 41648 11,
michael@0 41649 15
michael@0 41650 ]);
michael@0 41651 function getRotationMatrix(theta, u, v, w, a, b, c) {
michael@0 41652 var u2 = u * u, v2 = v * v, w2 = w * w;
michael@0 41653 var L2 = u2 + v2 + w2, L = Math.sqrt(L2);
michael@0 41654 u /= L;
michael@0 41655 v /= L;
michael@0 41656 w /= L;
michael@0 41657 u2 /= L2;
michael@0 41658 v2 /= L2;
michael@0 41659 w2 /= L2;
michael@0 41660 var cos = Math.cos(theta), sin = Math.sin(theta);
michael@0 41661 return new flash.geom.Matrix3D([
michael@0 41662 u2 + (v2 + w2) * cos,
michael@0 41663 u * v * (1 - cos) + w * sin,
michael@0 41664 u * w * (1 - cos) - v * sin,
michael@0 41665 0,
michael@0 41666 u * v * (1 - cos) - w * sin,
michael@0 41667 v2 + (u2 + w2) * cos,
michael@0 41668 v * w * (1 - cos) + u * sin,
michael@0 41669 0,
michael@0 41670 u * w * (1 - cos) + v * sin,
michael@0 41671 v * w * (1 - cos) - u * sin,
michael@0 41672 w2 + (u2 + v2) * cos,
michael@0 41673 0,
michael@0 41674 (a * (v2 + w2) - u * (b * v + c * w)) * (1 - cos) + (b * w - c * v) * sin,
michael@0 41675 (b * (u2 + w2) - v * (a * u + c * w)) * (1 - cos) + (c * u - a * w) * sin,
michael@0 41676 (c * (u2 + v2) - w * (a * u + b * v)) * (1 - cos) + (a * v - b * u) * sin,
michael@0 41677 1
michael@0 41678 ]);
michael@0 41679 }
michael@0 41680 return {
michael@0 41681 __class__: 'flash.geom.Matrix3D',
michael@0 41682 initialize: function () {
michael@0 41683 },
michael@0 41684 __glue__: {
michael@0 41685 native: {
michael@0 41686 static: {
michael@0 41687 interpolate: function interpolate(thisMat, toMat, percent) {
michael@0 41688 notImplemented('Matrix3D.interpolate');
michael@0 41689 }
michael@0 41690 },
michael@0 41691 instance: {
michael@0 41692 ctor: function ctor(v) {
michael@0 41693 this._matrix = new Float32Array(16);
michael@0 41694 if (v && v.length >= 16) {
michael@0 41695 this.copyRawDataFrom(v, 0, false);
michael@0 41696 } else {
michael@0 41697 this.identity();
michael@0 41698 }
michael@0 41699 },
michael@0 41700 clone: function clone() {
michael@0 41701 return new flash.geom.Matrix3D(this._matrix);
michael@0 41702 },
michael@0 41703 copyToMatrix3D: function copyToMatrix3D(dest) {
michael@0 41704 dest._matrix.set(this._matrix);
michael@0 41705 },
michael@0 41706 append: function append(lhs) {
michael@0 41707 var ma = lhs._matrix, mb = this._matrix, m = this._matrix;
michael@0 41708 var ma11 = ma[0], ma12 = ma[4], ma13 = ma[8], ma14 = ma[12], ma21 = ma[1], ma22 = ma[5], ma23 = ma[9], ma24 = ma[13], ma31 = ma[2], ma32 = ma[6], ma33 = ma[10], ma34 = ma[14], ma41 = ma[3], ma42 = ma[7], ma43 = ma[11], ma44 = ma[15];
michael@0 41709 var mb11 = mb[0], mb12 = mb[4], mb13 = mb[8], mb14 = mb[12], mb21 = mb[1], mb22 = mb[5], mb23 = mb[9], mb24 = mb[13], mb31 = mb[2], mb32 = mb[6], mb33 = mb[10], mb34 = mb[14], mb41 = mb[3], mb42 = mb[7], mb43 = mb[11], mb44 = mb[15];
michael@0 41710 m[0] = ma11 * mb11 + ma12 * mb21 + ma13 * mb31 + ma14 * mb41;
michael@0 41711 m[1] = ma21 * mb11 + ma22 * mb21 + ma23 * mb31 + ma24 * mb41;
michael@0 41712 m[2] = ma31 * mb11 + ma32 * mb21 + ma33 * mb31 + ma34 * mb41;
michael@0 41713 m[3] = ma41 * mb11 + ma42 * mb21 + ma43 * mb31 + ma44 * mb41;
michael@0 41714 m[4] = ma11 * mb12 + ma12 * mb22 + ma13 * mb32 + ma14 * mb42;
michael@0 41715 m[5] = ma21 * mb12 + ma22 * mb22 + ma23 * mb32 + ma24 * mb42;
michael@0 41716 m[6] = ma31 * mb12 + ma32 * mb22 + ma33 * mb32 + ma34 * mb42;
michael@0 41717 m[7] = ma41 * mb12 + ma42 * mb22 + ma43 * mb32 + ma44 * mb42;
michael@0 41718 m[8] = ma11 * mb13 + ma12 * mb23 + ma13 * mb33 + ma14 * mb43;
michael@0 41719 m[9] = ma21 * mb13 + ma22 * mb23 + ma23 * mb33 + ma24 * mb43;
michael@0 41720 m[10] = ma31 * mb13 + ma32 * mb23 + ma33 * mb33 + ma34 * mb43;
michael@0 41721 m[11] = ma41 * mb13 + ma42 * mb23 + ma43 * mb33 + ma44 * mb43;
michael@0 41722 m[12] = ma11 * mb14 + ma12 * mb24 + ma13 * mb34 + ma14 * mb44;
michael@0 41723 m[13] = ma21 * mb14 + ma22 * mb24 + ma23 * mb34 + ma24 * mb44;
michael@0 41724 m[14] = ma31 * mb14 + ma32 * mb24 + ma33 * mb34 + ma34 * mb44;
michael@0 41725 m[15] = ma41 * mb14 + ma42 * mb24 + ma43 * mb34 + ma44 * mb44;
michael@0 41726 },
michael@0 41727 prepend: function prepend(rhs) {
michael@0 41728 var ma = this._matrix, mb = rhs._matrix, m = this._matrix;
michael@0 41729 var ma11 = ma[0], ma12 = ma[4], ma13 = ma[8], ma14 = ma[12], ma21 = ma[1], ma22 = ma[5], ma23 = ma[9], ma24 = ma[13], ma31 = ma[2], ma32 = ma[6], ma33 = ma[10], ma34 = ma[14], ma41 = ma[3], ma42 = ma[7], ma43 = ma[11], ma44 = ma[15];
michael@0 41730 var mb11 = mb[0], mb12 = mb[4], mb13 = mb[8], mb14 = mb[12], mb21 = mb[1], mb22 = mb[5], mb23 = mb[9], mb24 = mb[13], mb31 = mb[2], mb32 = mb[6], mb33 = mb[10], mb34 = mb[14], mb41 = mb[3], mb42 = mb[7], mb43 = mb[11], mb44 = mb[15];
michael@0 41731 m[0] = ma11 * mb11 + ma12 * mb21 + ma13 * mb31 + ma14 * mb41;
michael@0 41732 m[1] = ma21 * mb11 + ma22 * mb21 + ma23 * mb31 + ma24 * mb41;
michael@0 41733 m[2] = ma31 * mb11 + ma32 * mb21 + ma33 * mb31 + ma34 * mb41;
michael@0 41734 m[3] = ma41 * mb11 + ma42 * mb21 + ma43 * mb31 + ma44 * mb41;
michael@0 41735 m[4] = ma11 * mb12 + ma12 * mb22 + ma13 * mb32 + ma14 * mb42;
michael@0 41736 m[5] = ma21 * mb12 + ma22 * mb22 + ma23 * mb32 + ma24 * mb42;
michael@0 41737 m[6] = ma31 * mb12 + ma32 * mb22 + ma33 * mb32 + ma34 * mb42;
michael@0 41738 m[7] = ma41 * mb12 + ma42 * mb22 + ma43 * mb32 + ma44 * mb42;
michael@0 41739 m[8] = ma11 * mb13 + ma12 * mb23 + ma13 * mb33 + ma14 * mb43;
michael@0 41740 m[9] = ma21 * mb13 + ma22 * mb23 + ma23 * mb33 + ma24 * mb43;
michael@0 41741 m[10] = ma31 * mb13 + ma32 * mb23 + ma33 * mb33 + ma34 * mb43;
michael@0 41742 m[11] = ma41 * mb13 + ma42 * mb23 + ma43 * mb33 + ma44 * mb43;
michael@0 41743 m[12] = ma11 * mb14 + ma12 * mb24 + ma13 * mb34 + ma14 * mb44;
michael@0 41744 m[13] = ma21 * mb14 + ma22 * mb24 + ma23 * mb34 + ma24 * mb44;
michael@0 41745 m[14] = ma31 * mb14 + ma32 * mb24 + ma33 * mb34 + ma34 * mb44;
michael@0 41746 m[15] = ma41 * mb14 + ma42 * mb24 + ma43 * mb34 + ma44 * mb44;
michael@0 41747 },
michael@0 41748 invert: function invert() {
michael@0 41749 var d = this.determinant;
michael@0 41750 if (Math.abs(d) < precision) {
michael@0 41751 return false;
michael@0 41752 }
michael@0 41753 d = 1 / d;
michael@0 41754 var m = this._matrix;
michael@0 41755 var m11 = m[0], m12 = m[1], m13 = m[2], m14 = m[3], m21 = m[4], m22 = m[5], m23 = m[6], m24 = m[7], m31 = m[8], m32 = m[9], m33 = m[10], m34 = m[11], m41 = m[12], m42 = m[13], m43 = m[14], m44 = m[15];
michael@0 41756 m[0] = d * (m22 * (m33 * m44 - m43 * m34) - m32 * (m23 * m44 - m43 * m24) + m42 * (m23 * m34 - m33 * m24));
michael@0 41757 m[1] = -d * (m12 * (m33 * m44 - m43 * m34) - m32 * (m13 * m44 - m43 * m14) + m42 * (m13 * m34 - m33 * m14));
michael@0 41758 m[2] = d * (m12 * (m23 * m44 - m43 * m24) - m22 * (m13 * m44 - m43 * m14) + m42 * (m13 * m24 - m23 * m14));
michael@0 41759 m[3] = -d * (m12 * (m23 * m34 - m33 * m24) - m22 * (m13 * m34 - m33 * m14) + m32 * (m13 * m24 - m23 * m14));
michael@0 41760 m[4] = -d * (m21 * (m33 * m44 - m43 * m34) - m31 * (m23 * m44 - m43 * m24) + m41 * (m23 * m34 - m33 * m24));
michael@0 41761 m[5] = d * (m11 * (m33 * m44 - m43 * m34) - m31 * (m13 * m44 - m43 * m14) + m41 * (m13 * m34 - m33 * m14));
michael@0 41762 m[6] = -d * (m11 * (m23 * m44 - m43 * m24) - m21 * (m13 * m44 - m43 * m14) + m41 * (m13 * m24 - m23 * m14));
michael@0 41763 m[7] = d * (m11 * (m23 * m34 - m33 * m24) - m21 * (m13 * m34 - m33 * m14) + m31 * (m13 * m24 - m23 * m14));
michael@0 41764 m[8] = d * (m21 * (m32 * m44 - m42 * m34) - m31 * (m22 * m44 - m42 * m24) + m41 * (m22 * m34 - m32 * m24));
michael@0 41765 m[9] = -d * (m11 * (m32 * m44 - m42 * m34) - m31 * (m12 * m44 - m42 * m14) + m41 * (m12 * m34 - m32 * m14));
michael@0 41766 m[10] = d * (m11 * (m22 * m44 - m42 * m24) - m21 * (m12 * m44 - m42 * m14) + m41 * (m12 * m24 - m22 * m14));
michael@0 41767 m[11] = -d * (m11 * (m22 * m34 - m32 * m24) - m21 * (m12 * m34 - m32 * m14) + m31 * (m12 * m24 - m22 * m14));
michael@0 41768 m[12] = -d * (m21 * (m32 * m43 - m42 * m33) - m31 * (m22 * m43 - m42 * m23) + m41 * (m22 * m33 - m32 * m23));
michael@0 41769 m[13] = d * (m11 * (m32 * m43 - m42 * m33) - m31 * (m12 * m43 - m42 * m13) + m41 * (m12 * m33 - m32 * m13));
michael@0 41770 m[14] = -d * (m11 * (m22 * m43 - m42 * m23) - m21 * (m12 * m43 - m42 * m13) + m41 * (m12 * m23 - m22 * m13));
michael@0 41771 m[15] = d * (m11 * (m22 * m33 - m32 * m23) - m21 * (m12 * m33 - m32 * m13) + m31 * (m12 * m23 - m22 * m13));
michael@0 41772 return true;
michael@0 41773 },
michael@0 41774 identity: function identity() {
michael@0 41775 var m = this._matrix;
michael@0 41776 m[0] = m[5] = m[10] = m[15] = 1;
michael@0 41777 m[1] = m[2] = m[3] = m[4] = m[6] = m[7] = m[8] = m[9] = m[11] = m[12] = m[13] = m[14] = 0;
michael@0 41778 },
michael@0 41779 decompose: function decompose(orientationStyle) {
michael@0 41780 notImplemented('Matrix3D.decompose');
michael@0 41781 },
michael@0 41782 recompose: function recompose(components, orientationStyle) {
michael@0 41783 notImplemented('Matrix3D.recompose');
michael@0 41784 },
michael@0 41785 appendTranslation: function appendTranslation(x, y, z) {
michael@0 41786 var m = this._matrix;
michael@0 41787 var m41 = m[3], m42 = m[7], m43 = m[11], m44 = m[15];
michael@0 41788 m[0] += x * m41;
michael@0 41789 m[1] += y * m41;
michael@0 41790 m[2] += z * m41;
michael@0 41791 m[4] += x * m42;
michael@0 41792 m[5] += y * m42;
michael@0 41793 m[6] += z * m42;
michael@0 41794 m[8] += x * m43;
michael@0 41795 m[9] += y * m43;
michael@0 41796 m[10] += z * m43;
michael@0 41797 m[12] += x * m44;
michael@0 41798 m[13] += y * m44;
michael@0 41799 m[14] += z * m44;
michael@0 41800 },
michael@0 41801 appendRotation: function appendRotation(degrees, axis, pivotPoint) {
michael@0 41802 this.append(getRotationMatrix(degrees / 180 * Math.PI, axis.x, axis.y, axis.z, pivotPoint ? pivotPoint.x : 0, pivotPoint ? pivotPoint.y : 0, pivotPoint ? pivotPoint.z : 0));
michael@0 41803 },
michael@0 41804 appendScale: function appendScale(xScale, yScale, zScale) {
michael@0 41805 var m = this._matrix;
michael@0 41806 m[0] *= xScale;
michael@0 41807 m[1] *= yScale;
michael@0 41808 m[2] *= zScale;
michael@0 41809 m[4] *= xScale;
michael@0 41810 m[5] *= yScale;
michael@0 41811 m[6] *= zScale;
michael@0 41812 m[8] *= xScale;
michael@0 41813 m[9] *= yScale;
michael@0 41814 m[10] *= zScale;
michael@0 41815 m[12] *= xScale;
michael@0 41816 m[13] *= yScale;
michael@0 41817 m[14] *= zScale;
michael@0 41818 },
michael@0 41819 prependTranslation: function prependTranslation(x, y, z) {
michael@0 41820 var m = this._matrix;
michael@0 41821 var m11 = m[0], m12 = m[4], m13 = m[8], m14 = m[12], m21 = m[1], m22 = m[5], m23 = m[9], m24 = m[13], m31 = m[2], m32 = m[6], m33 = m[10], m34 = m[14], m41 = m[3], m42 = m[7], m43 = m[11], m44 = m[15];
michael@0 41822 m[12] += m11 * x + m12 * y + m13 * z;
michael@0 41823 m[13] += m21 * x + m22 * y + m23 * z;
michael@0 41824 m[14] += m31 * x + m32 * y + m33 * z;
michael@0 41825 m[15] += m41 * x + m42 * y + m43 * z;
michael@0 41826 },
michael@0 41827 prependRotation: function prependRotation(degrees, axis, pivotPoint) {
michael@0 41828 this.prepend(getRotationMatrix(degrees / 180 * Math.PI, axis.x, axis.y, axis.z, pivotPoint ? pivotPoint.x : 0, pivotPoint ? pivotPoint.y : 0, pivotPoint ? pivotPoint.z : 0));
michael@0 41829 },
michael@0 41830 prependScale: function prependScale(xScale, yScale, zScale) {
michael@0 41831 var m = this._matrix;
michael@0 41832 m[0] *= xScale;
michael@0 41833 m[1] *= xScale;
michael@0 41834 m[2] *= xScale;
michael@0 41835 m[3] *= xScale;
michael@0 41836 m[4] *= yScale;
michael@0 41837 m[5] *= yScale;
michael@0 41838 m[6] *= yScale;
michael@0 41839 m[7] *= yScale;
michael@0 41840 m[8] *= zScale;
michael@0 41841 m[9] *= zScale;
michael@0 41842 m[10] *= zScale;
michael@0 41843 m[11] *= zScale;
michael@0 41844 },
michael@0 41845 transformVector: function transformVector(v) {
michael@0 41846 var m = this._matrix;
michael@0 41847 var x = v.x, y = v.y, z = v.z;
michael@0 41848 return new flash.geom.Vector3D(m[0] * x + m[4] * y + m[8] * z + m[12], m[1] * x + m[5] * y + m[9] * z + m[13], m[2] * x + m[6] * y + m[10] * z + m[14]);
michael@0 41849 },
michael@0 41850 deltaTransformVector: function deltaTransformVector(v) {
michael@0 41851 var m = this._matrix;
michael@0 41852 var x = v.x, y = v.y, z = v.z;
michael@0 41853 return new flash.geom.Vector3D(m[0] * x + m[4] * y + m[8] * z, m[1] * x + m[5] * y + m[9] * z, m[2] * x + m[6] * y + m[10] * z);
michael@0 41854 },
michael@0 41855 transformVectors: function transformVectors(vin, vout) {
michael@0 41856 var m = this._matrix;
michael@0 41857 var m11 = m[0], m12 = m[4], m13 = m[8], m14 = m[12], m21 = m[1], m22 = m[5], m23 = m[9], m24 = m[13], m31 = m[2], m32 = m[6], m33 = m[10], m34 = m[14], m41 = m[3], m42 = m[7], m43 = m[11], m44 = m[15];
michael@0 41858 for (var i = 0; i < vin.length - 2; i += 3) {
michael@0 41859 var x = vin.asGetNumericProperty(i), y = vin.asGetNumericProperty(i + 1), z = vin.asGetNumericProperty(i + 2);
michael@0 41860 vout.push(m11 * x + m12 * y + m13 * z + m14);
michael@0 41861 vout.push(m21 * x + m22 * y + m23 * z + m24);
michael@0 41862 vout.push(m31 * x + m32 * y + m33 * z + m34);
michael@0 41863 }
michael@0 41864 },
michael@0 41865 transpose: function transpose() {
michael@0 41866 var m = this._matrix;
michael@0 41867 var tmp;
michael@0 41868 tmp = m[1];
michael@0 41869 m[1] = m[4];
michael@0 41870 m[4] = tmp;
michael@0 41871 tmp = m[2];
michael@0 41872 m[2] = m[8];
michael@0 41873 m[5] = tmp;
michael@0 41874 tmp = m[3];
michael@0 41875 m[3] = m[12];
michael@0 41876 m[12] = tmp;
michael@0 41877 tmp = m[6];
michael@0 41878 m[6] = m[9];
michael@0 41879 m[9] = tmp;
michael@0 41880 tmp = m[7];
michael@0 41881 m[7] = m[13];
michael@0 41882 m[13] = tmp;
michael@0 41883 tmp = m[11];
michael@0 41884 m[11] = m[14];
michael@0 41885 m[14] = tmp;
michael@0 41886 },
michael@0 41887 pointAt: function pointAt(pos, at, up) {
michael@0 41888 notImplemented('Matrix3D.pointAt');
michael@0 41889 },
michael@0 41890 interpolateTo: function interpolateTo(toMat, percent) {
michael@0 41891 notImplemented('Matrix3D.interpolateTo');
michael@0 41892 },
michael@0 41893 copyFrom: function copyFrom(sourceMatrix3D) {
michael@0 41894 this._matrix.set(sourceMatrix3D._matrix);
michael@0 41895 },
michael@0 41896 copyRawDataTo: function copyRawDataTo(vector, index, transpose) {
michael@0 41897 var m = this._matrix;
michael@0 41898 if (transpose) {
michael@0 41899 for (var i = 0, j = index | 0; i < 16; i++, j++) {
michael@0 41900 vector.asSetNumericProperty(j, m[transposeTransform[i]]);
michael@0 41901 }
michael@0 41902 } else {
michael@0 41903 for (var i = 0, j = index | 0; i < 16; i++, j++) {
michael@0 41904 vector.asSetNumericProperty(j, m[i]);
michael@0 41905 }
michael@0 41906 }
michael@0 41907 },
michael@0 41908 copyRawDataFrom: function copyRawDataFrom(vector, index, transpose) {
michael@0 41909 var m = this._matrix;
michael@0 41910 if (transpose) {
michael@0 41911 for (var i = 0, j = index | 0; i < 16; i++, j++) {
michael@0 41912 m[transposeTransform[i]] = vector.asGetNumericProperty(j) || 0;
michael@0 41913 }
michael@0 41914 } else {
michael@0 41915 for (var i = 0, j = index | 0; i < 16; i++, j++) {
michael@0 41916 m[i] = vector.asGetNumericProperty(j) || 0;
michael@0 41917 }
michael@0 41918 }
michael@0 41919 },
michael@0 41920 copyRowTo: function copyRowTo(row, vector3D) {
michael@0 41921 var offset = row | 0;
michael@0 41922 var m = this._matrix;
michael@0 41923 vector3D.x = m[offset];
michael@0 41924 vector3D.y = m[offset + 4];
michael@0 41925 vector3D.z = m[offset + 8];
michael@0 41926 vector3D.w = m[offset + 12];
michael@0 41927 },
michael@0 41928 copyColumnTo: function copyColumnTo(column, vector3D) {
michael@0 41929 var offset = column << 2;
michael@0 41930 var m = this._matrix;
michael@0 41931 vector3D.x = m[offset];
michael@0 41932 vector3D.y = m[offset + 1];
michael@0 41933 vector3D.z = m[offset + 2];
michael@0 41934 vector3D.w = m[offset + 3];
michael@0 41935 },
michael@0 41936 copyRowFrom: function copyRowFrom(row, vector3D) {
michael@0 41937 var offset = row | 0;
michael@0 41938 var m = this._matrix;
michael@0 41939 m[offset] = vector3D.x;
michael@0 41940 m[offset + 4] = vector3D.y;
michael@0 41941 m[offset + 8] = vector3D.z;
michael@0 41942 m[offset + 12] = vector3D.w;
michael@0 41943 },
michael@0 41944 copyColumnFrom: function copyColumnFrom(column, vector3D) {
michael@0 41945 var offset = column << 2;
michael@0 41946 var m = this._matrix;
michael@0 41947 m[offset] = vector3D.x;
michael@0 41948 m[offset + 1] = vector3D.y;
michael@0 41949 m[offset + 2] = vector3D.z;
michael@0 41950 m[offset + 3] = vector3D.w;
michael@0 41951 },
michael@0 41952 rawData: {
michael@0 41953 get: function rawData() {
michael@0 41954 var result = new Float64Vector();
michael@0 41955 this.copyRawDataTo(result, 0, false);
michael@0 41956 return result;
michael@0 41957 },
michael@0 41958 set: function rawData(v) {
michael@0 41959 this.copyRawDataFrom(v, 0, false);
michael@0 41960 }
michael@0 41961 },
michael@0 41962 position: {
michael@0 41963 get: function position() {
michael@0 41964 var m = this._matrix;
michael@0 41965 return new flash.geom.Vector3D(m[12], m[13], m[14]);
michael@0 41966 },
michael@0 41967 set: function position(pos) {
michael@0 41968 var m = this._matrix;
michael@0 41969 m[12] = pos.x;
michael@0 41970 m[13] = pos.y;
michael@0 41971 m[14] = pos.z;
michael@0 41972 }
michael@0 41973 },
michael@0 41974 determinant: {
michael@0 41975 get: function determinant() {
michael@0 41976 var m = this._matrix;
michael@0 41977 var m11 = m[0], m12 = m[4], m13 = m[8], m14 = m[12], m21 = m[1], m22 = m[5], m23 = m[9], m24 = m[13], m31 = m[2], m32 = m[6], m33 = m[10], m34 = m[14], m41 = m[3], m42 = m[7], m43 = m[11], m44 = m[15];
michael@0 41978 var d;
michael@0 41979 d = m11 * (m22 * (m33 * m44 - m43 * m34) - m32 * (m23 * m44 - m43 * m24) + m42 * (m23 * m34 - m33 * m24)) - m21 * (m12 * (m33 * m44 - m43 * m34) - m32 * (m13 * m44 - m43 * m14) + m42 * (m13 * m34 - m33 * m14)) + m31 * (m12 * (m23 * m44 - m43 * m24) - m22 * (m13 * m44 - m43 * m14) + m42 * (m13 * m24 - m23 * m14)) - m41 * (m12 * (m23 * m34 - m33 * m24) - m22 * (m13 * m34 - m33 * m14) + m32 * (m13 * m24 - m23 * m14));
michael@0 41980 return d;
michael@0 41981 }
michael@0 41982 }
michael@0 41983 }
michael@0 41984 },
michael@0 41985 script: {
michael@0 41986 instance: Glue.ALL
michael@0 41987 }
michael@0 41988 }
michael@0 41989 };
michael@0 41990 }.call(this);
michael@0 41991 var PointDefinition = function () {
michael@0 41992 return {
michael@0 41993 __class__: 'flash.geom.Point',
michael@0 41994 __glue__: {
michael@0 41995 script: {
michael@0 41996 static: Glue.ALL,
michael@0 41997 instance: Glue.ALL
michael@0 41998 }
michael@0 41999 }
michael@0 42000 };
michael@0 42001 }.call(this);
michael@0 42002 var RectangleDefinition = function () {
michael@0 42003 return {
michael@0 42004 __class__: 'flash.geom.Rectangle',
michael@0 42005 __glue__: {
michael@0 42006 script: {
michael@0 42007 instance: Glue.ALL
michael@0 42008 }
michael@0 42009 }
michael@0 42010 };
michael@0 42011 }.call(this);
michael@0 42012 var TransformDefinition = function () {
michael@0 42013 var def = {
michael@0 42014 __class__: 'flash.geom.Transform',
michael@0 42015 get colorTransform() {
michael@0 42016 var cxform = this._target._cxform;
michael@0 42017 if (cxform) {
michael@0 42018 return new flash.geom.ColorTransform(cxform.redMultiplier / 256, cxform.greenMultiplier / 256, cxform.blueMultiplier / 256, cxform.alphaMultiplier / 256, cxform.redOffset, cxform.greenOffset, cxform.blueOffset, cxform.alphaOffset);
michael@0 42019 } else {
michael@0 42020 return new flash.geom.ColorTransform();
michael@0 42021 }
michael@0 42022 },
michael@0 42023 set colorTransform(val) {
michael@0 42024 var CTClass = avm2.systemDomain.getClass('flash.geom.ColorTransform');
michael@0 42025 if (!CTClass.isInstanceOf(val)) {
michael@0 42026 throwError('TypeError', Errors.CheckTypeFailedError, val, 'flash.geom.ColorTransform');
michael@0 42027 }
michael@0 42028 this._target._cxform = {
michael@0 42029 redMultiplier: val.redMultiplier * 256,
michael@0 42030 greenMultiplier: val.greenMultiplier * 256,
michael@0 42031 blueMultiplier: val.blueMultiplier * 256,
michael@0 42032 alphaMultiplier: val.alphaMultiplier * 256,
michael@0 42033 redOffset: val.redOffset,
michael@0 42034 greenOffset: val.greenOffset,
michael@0 42035 blueOffset: val.blueOffset,
michael@0 42036 alphaOffset: val.alphaOffset
michael@0 42037 };
michael@0 42038 this._target._invalidate();
michael@0 42039 },
michael@0 42040 get concatenatedColorTransform() {
michael@0 42041 var cxform = this.colorTransform;
michael@0 42042 cxform.concat(this._target.parent.transform.concatenatedColorTransform);
michael@0 42043 return cxform;
michael@0 42044 },
michael@0 42045 get concatenatedMatrix() {
michael@0 42046 if (this._target._current3DTransform) {
michael@0 42047 return null;
michael@0 42048 }
michael@0 42049 var m = this._target._getConcatenatedTransform(null, false);
michael@0 42050 return new flash.geom.Matrix(m.a, m.b, m.c, m.d, m.tx / 20, m.ty / 20);
michael@0 42051 },
michael@0 42052 get matrix() {
michael@0 42053 if (this._target._current3DTransform) {
michael@0 42054 return null;
michael@0 42055 }
michael@0 42056 var m = this._target._currentTransform;
michael@0 42057 return new flash.geom.Matrix(m.a, m.b, m.c, m.d, m.tx / 20, m.ty / 20);
michael@0 42058 },
michael@0 42059 set matrix(val) {
michael@0 42060 if (!flash.geom.Matrix.class.isInstanceOf(val)) {
michael@0 42061 throwError('TypeError', Errors.CheckTypeFailedError, val, 'flash.geom.Matrix');
michael@0 42062 }
michael@0 42063 var target = this._target;
michael@0 42064 target._invalidate();
michael@0 42065 target._setTransformMatrix(val, true);
michael@0 42066 target._current3DTransform = null;
michael@0 42067 target._animated = false;
michael@0 42068 },
michael@0 42069 get matrix3D() {
michael@0 42070 var m = this._target._current3DTransform;
michael@0 42071 return m && m.clone();
michael@0 42072 },
michael@0 42073 set matrix3D(val) {
michael@0 42074 var Matrix3DClass = avm2.systemDomain.getClass('flash.geom.Matrix3D');
michael@0 42075 if (!Matrix3DClass.isInstanceOf(val)) {
michael@0 42076 throwError('TypeError', Errors.CheckTypeFailedError, val, 'flash.geom.Matrix3D');
michael@0 42077 }
michael@0 42078 var raw = val.rawData;
michael@0 42079 this.matrix = new flash.geom.Matrix(raw.asGetPublicProperty(0), raw.asGetPublicProperty(1), raw.asGetPublicProperty(4), raw.asGetPublicProperty(5), raw.asGetPublicProperty(12), raw.asGetPublicProperty(13));
michael@0 42080 this._target._current3DTransform = val;
michael@0 42081 },
michael@0 42082 ctor: function (target) {
michael@0 42083 this._target = target;
michael@0 42084 }
michael@0 42085 };
michael@0 42086 var desc = Object.getOwnPropertyDescriptor;
michael@0 42087 def.__glue__ = {
michael@0 42088 native: {
michael@0 42089 instance: {
michael@0 42090 colorTransform: desc(def, 'colorTransform'),
michael@0 42091 concatenatedColorTransform: desc(def, 'concatenatedColorTransform'),
michael@0 42092 concatenatedMatrix: desc(def, 'concatenatedMatrix'),
michael@0 42093 matrix: desc(def, 'matrix'),
michael@0 42094 matrix3D: desc(def, 'matrix3D'),
michael@0 42095 ctor: def.ctor
michael@0 42096 }
michael@0 42097 }
michael@0 42098 };
michael@0 42099 return def;
michael@0 42100 }.call(this);
michael@0 42101 var Vector3DDefinition = function () {
michael@0 42102 return {
michael@0 42103 __class__: 'flash.geom.Vector3D',
michael@0 42104 initialize: function () {
michael@0 42105 },
michael@0 42106 __glue__: {
michael@0 42107 script: {
michael@0 42108 instance: Glue.ALL
michael@0 42109 }
michael@0 42110 }
michael@0 42111 };
michael@0 42112 }.call(this);
michael@0 42113 {
michael@0 42114 var ID3InfoDefinition = function () {
michael@0 42115 return {
michael@0 42116 __glue__: {
michael@0 42117 script: {
michael@0 42118 instance: {
michael@0 42119 songName: 'public songName',
michael@0 42120 genre: 'public genre',
michael@0 42121 artist: 'public artist',
michael@0 42122 track: 'public track',
michael@0 42123 album: 'public album',
michael@0 42124 year: 'public year',
michael@0 42125 comment: 'public comment'
michael@0 42126 }
michael@0 42127 }
michael@0 42128 }
michael@0 42129 };
michael@0 42130 }.call(this);
michael@0 42131 }
michael@0 42132 var MicrophoneDefinition = function () {
michael@0 42133 return {
michael@0 42134 __class__: 'flash.media.Microphone',
michael@0 42135 initialize: function () {
michael@0 42136 },
michael@0 42137 __glue__: {
michael@0 42138 native: {
michael@0 42139 static: {
michael@0 42140 getMicrophone: function getMicrophone(index) {
michael@0 42141 notImplemented('Microphone.getMicrophone');
michael@0 42142 },
michael@0 42143 getEnhancedMicrophone: function getEnhancedMicrophone(index) {
michael@0 42144 notImplemented('Microphone.getEnhancedMicrophone');
michael@0 42145 },
michael@0 42146 names: {
michael@0 42147 get: function names() {
michael@0 42148 notImplemented('Microphone.names');
michael@0 42149 }
michael@0 42150 },
michael@0 42151 isSupported: {
michael@0 42152 get: function isSupported() {
michael@0 42153 notImplemented('Microphone.isSupported');
michael@0 42154 }
michael@0 42155 }
michael@0 42156 },
michael@0 42157 instance: {
michael@0 42158 setSilenceLevel: function setSilenceLevel(silenceLevel, timeout) {
michael@0 42159 notImplemented('Microphone.setSilenceLevel');
michael@0 42160 },
michael@0 42161 setUseEchoSuppression: function setUseEchoSuppression(useEchoSuppression) {
michael@0 42162 notImplemented('Microphone.setUseEchoSuppression');
michael@0 42163 },
michael@0 42164 setLoopBack: function setLoopBack(state) {
michael@0 42165 notImplemented('Microphone.setLoopBack');
michael@0 42166 },
michael@0 42167 gain: {
michael@0 42168 set: function gain(gain) {
michael@0 42169 notImplemented('Microphone.gain');
michael@0 42170 this._gain = gain;
michael@0 42171 },
michael@0 42172 get: function gain() {
michael@0 42173 notImplemented('Microphone.gain');
michael@0 42174 return this._gain;
michael@0 42175 }
michael@0 42176 },
michael@0 42177 rate: {
michael@0 42178 set: function rate(rate) {
michael@0 42179 notImplemented('Microphone.rate');
michael@0 42180 this._rate = rate;
michael@0 42181 },
michael@0 42182 get: function rate() {
michael@0 42183 notImplemented('Microphone.rate');
michael@0 42184 return this._rate;
michael@0 42185 }
michael@0 42186 },
michael@0 42187 codec: {
michael@0 42188 set: function codec(codec) {
michael@0 42189 notImplemented('Microphone.codec');
michael@0 42190 this._codec = codec;
michael@0 42191 },
michael@0 42192 get: function codec() {
michael@0 42193 notImplemented('Microphone.codec');
michael@0 42194 return this._codec;
michael@0 42195 }
michael@0 42196 },
michael@0 42197 framesPerPacket: {
michael@0 42198 get: function framesPerPacket() {
michael@0 42199 notImplemented('Microphone.framesPerPacket');
michael@0 42200 return this._framesPerPacket;
michael@0 42201 },
michael@0 42202 set: function framesPerPacket(frames) {
michael@0 42203 notImplemented('Microphone.framesPerPacket');
michael@0 42204 this._framesPerPacket = frames;
michael@0 42205 }
michael@0 42206 },
michael@0 42207 encodeQuality: {
michael@0 42208 get: function encodeQuality() {
michael@0 42209 notImplemented('Microphone.encodeQuality');
michael@0 42210 return this._encodeQuality;
michael@0 42211 },
michael@0 42212 set: function encodeQuality(quality) {
michael@0 42213 notImplemented('Microphone.encodeQuality');
michael@0 42214 this._encodeQuality = quality;
michael@0 42215 }
michael@0 42216 },
michael@0 42217 noiseSuppressionLevel: {
michael@0 42218 get: function noiseSuppressionLevel() {
michael@0 42219 notImplemented('Microphone.noiseSuppressionLevel');
michael@0 42220 return this._noiseSuppressionLevel;
michael@0 42221 },
michael@0 42222 set: function noiseSuppressionLevel(level) {
michael@0 42223 notImplemented('Microphone.noiseSuppressionLevel');
michael@0 42224 this._noiseSuppressionLevel = level;
michael@0 42225 }
michael@0 42226 },
michael@0 42227 enableVAD: {
michael@0 42228 get: function enableVAD() {
michael@0 42229 notImplemented('Microphone.enableVAD');
michael@0 42230 return this._enableVAD;
michael@0 42231 },
michael@0 42232 set: function enableVAD(enable) {
michael@0 42233 notImplemented('Microphone.enableVAD');
michael@0 42234 this._enableVAD = enable;
michael@0 42235 }
michael@0 42236 },
michael@0 42237 activityLevel: {
michael@0 42238 get: function activityLevel() {
michael@0 42239 notImplemented('Microphone.activityLevel');
michael@0 42240 return this._activityLevel;
michael@0 42241 }
michael@0 42242 },
michael@0 42243 index: {
michael@0 42244 get: function index() {
michael@0 42245 notImplemented('Microphone.index');
michael@0 42246 return this._index;
michael@0 42247 }
michael@0 42248 },
michael@0 42249 muted: {
michael@0 42250 get: function muted() {
michael@0 42251 notImplemented('Microphone.muted');
michael@0 42252 return this._muted;
michael@0 42253 }
michael@0 42254 },
michael@0 42255 name: {
michael@0 42256 get: function name() {
michael@0 42257 notImplemented('Microphone.name');
michael@0 42258 return this._name;
michael@0 42259 }
michael@0 42260 },
michael@0 42261 silenceLevel: {
michael@0 42262 get: function silenceLevel() {
michael@0 42263 notImplemented('Microphone.silenceLevel');
michael@0 42264 return this._silenceLevel;
michael@0 42265 }
michael@0 42266 },
michael@0 42267 silenceTimeout: {
michael@0 42268 get: function silenceTimeout() {
michael@0 42269 notImplemented('Microphone.silenceTimeout');
michael@0 42270 return this._silenceTimeout;
michael@0 42271 }
michael@0 42272 },
michael@0 42273 useEchoSuppression: {
michael@0 42274 get: function useEchoSuppression() {
michael@0 42275 notImplemented('Microphone.useEchoSuppression');
michael@0 42276 return this._useEchoSuppression;
michael@0 42277 }
michael@0 42278 },
michael@0 42279 soundTransform: {
michael@0 42280 get: function soundTransform() {
michael@0 42281 notImplemented('Microphone.soundTransform');
michael@0 42282 return this._soundTransform;
michael@0 42283 },
michael@0 42284 set: function soundTransform(sndTransform) {
michael@0 42285 notImplemented('Microphone.soundTransform');
michael@0 42286 this._soundTransform = sndTransform;
michael@0 42287 }
michael@0 42288 },
michael@0 42289 enhancedOptions: {
michael@0 42290 get: function enhancedOptions() {
michael@0 42291 notImplemented('Microphone.enhancedOptions');
michael@0 42292 return this._enhancedOptions;
michael@0 42293 },
michael@0 42294 set: function enhancedOptions(options) {
michael@0 42295 notImplemented('Microphone.enhancedOptions');
michael@0 42296 this._enhancedOptions = options;
michael@0 42297 }
michael@0 42298 }
michael@0 42299 }
michael@0 42300 },
michael@0 42301 script: {
michael@0 42302 instance: Glue.ALL
michael@0 42303 }
michael@0 42304 }
michael@0 42305 };
michael@0 42306 }.call(this);
michael@0 42307 var PLAY_USING_AUDIO_TAG = true;
michael@0 42308 var SoundDefinition = function () {
michael@0 42309 function getAudioDescription(soundData, onComplete) {
michael@0 42310 var audioElement = document.createElement('audio');
michael@0 42311 if (!audioElement.canPlayType(soundData.mimeType)) {
michael@0 42312 onComplete({
michael@0 42313 duration: 0
michael@0 42314 });
michael@0 42315 return;
michael@0 42316 }
michael@0 42317 audioElement.preload = 'metadata';
michael@0 42318 var blob = new Blob([
michael@0 42319 soundData.data
michael@0 42320 ], {
michael@0 42321 type: soundData.mimeType
michael@0 42322 });
michael@0 42323 audioElement.src = URL.createObjectURL(blob);
michael@0 42324 audioElement.load();
michael@0 42325 audioElement.addEventListener('loadedmetadata', function () {
michael@0 42326 onComplete({
michael@0 42327 duration: this.duration * 1000
michael@0 42328 });
michael@0 42329 });
michael@0 42330 }
michael@0 42331 var def = {
michael@0 42332 initialize: function initialize() {
michael@0 42333 this._playQueue = [];
michael@0 42334 this._url = null;
michael@0 42335 this._length = 0;
michael@0 42336 this._bytesTotal = 0;
michael@0 42337 this._bytesLoaded = 0;
michael@0 42338 this._id3 = new flash.media.ID3Info();
michael@0 42339 var s = this.symbol;
michael@0 42340 if (s) {
michael@0 42341 var soundData = {};
michael@0 42342 if (s.pcm) {
michael@0 42343 soundData.sampleRate = s.sampleRate;
michael@0 42344 soundData.channels = s.channels;
michael@0 42345 soundData.pcm = s.pcm;
michael@0 42346 soundData.end = s.pcm.length;
michael@0 42347 }
michael@0 42348 soundData.completed = true;
michael@0 42349 if (s.packaged) {
michael@0 42350 soundData.data = s.packaged.data.buffer;
michael@0 42351 soundData.mimeType = s.packaged.mimeType;
michael@0 42352 }
michael@0 42353 var _this = this;
michael@0 42354 getAudioDescription(soundData, function (description) {
michael@0 42355 _this._length = description.duration;
michael@0 42356 });
michael@0 42357 this._soundData = soundData;
michael@0 42358 }
michael@0 42359 TelemetryService.reportTelemetry({
michael@0 42360 topic: 'feature',
michael@0 42361 feature: SOUND_FEATURE
michael@0 42362 });
michael@0 42363 },
michael@0 42364 close: function close() {
michael@0 42365 somewhatImplemented('Sound.close');
michael@0 42366 },
michael@0 42367 extract: function extract(target, length, startPosition) {
michael@0 42368 notImplemented('Sound.extract');
michael@0 42369 },
michael@0 42370 _load: function _load(request, checkPolicyFile, bufferTime) {
michael@0 42371 if (!request) {
michael@0 42372 return;
michael@0 42373 }
michael@0 42374 var _this = this;
michael@0 42375 var stream = this._stream = new flash.net.URLStream();
michael@0 42376 var ByteArrayClass = avm2.systemDomain.getClass('flash.utils.ByteArray');
michael@0 42377 var data = ByteArrayClass.createInstance();
michael@0 42378 var dataPosition = 0;
michael@0 42379 var mp3DecodingSession = null;
michael@0 42380 var soundData = {
michael@0 42381 completed: false
michael@0 42382 };
michael@0 42383 stream._addEventListener('progress', function (event) {
michael@0 42384 _this._bytesLoaded = event[Multiname.getPublicQualifiedName('bytesLoaded')];
michael@0 42385 _this._bytesTotal = event[Multiname.getPublicQualifiedName('bytesTotal')];
michael@0 42386 if (!PLAY_USING_AUDIO_TAG && !mp3DecodingSession) {
michael@0 42387 mp3DecodingSession = decodeMP3(soundData, function (duration, final) {
michael@0 42388 if (_this._length === 0) {
michael@0 42389 _this._soundData = soundData;
michael@0 42390 _this._playQueue.forEach(function (item) {
michael@0 42391 item.channel._playSoundDataViaChannel(soundData, item.startTime);
michael@0 42392 });
michael@0 42393 }
michael@0 42394 _this._length = final ? duration * 1000 : Math.max(duration, mp3DecodingSession.estimateDuration(_this._bytesTotal)) * 1000;
michael@0 42395 });
michael@0 42396 }
michael@0 42397 var bytesAvailable = stream.bytesAvailable;
michael@0 42398 stream.readBytes(data, dataPosition, bytesAvailable);
michael@0 42399 if (mp3DecodingSession) {
michael@0 42400 mp3DecodingSession.pushData(new Uint8Array(data.a, dataPosition, bytesAvailable));
michael@0 42401 }
michael@0 42402 dataPosition += bytesAvailable;
michael@0 42403 _this._dispatchEvent(event);
michael@0 42404 });
michael@0 42405 stream._addEventListener('complete', function (event) {
michael@0 42406 _this._dispatchEvent(event);
michael@0 42407 soundData.data = data.a;
michael@0 42408 soundData.mimeType = 'audio/mpeg';
michael@0 42409 soundData.completed = true;
michael@0 42410 if (PLAY_USING_AUDIO_TAG) {
michael@0 42411 _this._soundData = soundData;
michael@0 42412 getAudioDescription(soundData, function (description) {
michael@0 42413 _this._length = description.duration;
michael@0 42414 });
michael@0 42415 _this._playQueue.forEach(function (item) {
michael@0 42416 item.channel._playSoundDataViaAudio(soundData, item.startTime);
michael@0 42417 });
michael@0 42418 }
michael@0 42419 if (mp3DecodingSession) {
michael@0 42420 mp3DecodingSession.close();
michael@0 42421 }
michael@0 42422 });
michael@0 42423 stream.load(request);
michael@0 42424 },
michael@0 42425 loadCompressedDataFromByteArray: function loadCompressedDataFromByteArray(bytes, bytesLength) {
michael@0 42426 notImplemented('Sound#loadCompressedDataFromByteArray');
michael@0 42427 },
michael@0 42428 loadPCMFromByteArray: function loadPCMFromByteArray(bytes, samples, format, stereo, sampleRate) {
michael@0 42429 notImplemented('Sound#loadPCMFromByteArray');
michael@0 42430 },
michael@0 42431 play: function play(startTime, loops, soundTransform) {
michael@0 42432 startTime = startTime || 0;
michael@0 42433 loops = loops || 0;
michael@0 42434 var channel = new flash.media.SoundChannel();
michael@0 42435 channel._sound = this;
michael@0 42436 channel._soundTransform = isNullOrUndefined(soundTransform) ? new flash.media.SoundTransform() : soundTransform;
michael@0 42437 this._playQueue.push({
michael@0 42438 channel: channel,
michael@0 42439 startTime: startTime
michael@0 42440 });
michael@0 42441 if (this._soundData) {
michael@0 42442 if (PLAY_USING_AUDIO_TAG)
michael@0 42443 channel._playSoundDataViaAudio(this._soundData, startTime, loops);
michael@0 42444 else
michael@0 42445 channel._playSoundDataViaChannel(this._soundData, startTime, loops);
michael@0 42446 }
michael@0 42447 return channel;
michael@0 42448 },
michael@0 42449 get bytesLoaded() {
michael@0 42450 return this._bytesLoaded;
michael@0 42451 },
michael@0 42452 get bytesTotal() {
michael@0 42453 return this._bytesTotal;
michael@0 42454 },
michael@0 42455 get id3() {
michael@0 42456 return this._id3;
michael@0 42457 },
michael@0 42458 get isBuffering() {
michael@0 42459 notImplemented('Sound#isBuffering');
michael@0 42460 },
michael@0 42461 get isURLInaccessible() {
michael@0 42462 notImplemented('Sound#isURLInaccessible');
michael@0 42463 },
michael@0 42464 get length() {
michael@0 42465 return this._length;
michael@0 42466 },
michael@0 42467 get url() {
michael@0 42468 return this._url;
michael@0 42469 }
michael@0 42470 };
michael@0 42471 function decodeMP3(soundData, ondurationchanged) {
michael@0 42472 var currentSize = 8000;
michael@0 42473 var pcm = new Float32Array(currentSize);
michael@0 42474 var position = 0;
michael@0 42475 var lastTimeRatio = 0;
michael@0 42476 var durationEstimationData = {
michael@0 42477 estimateBitRate: true,
michael@0 42478 bitRateSum: 0,
michael@0 42479 bitRateCount: 0,
michael@0 42480 metadataSize: 0,
michael@0 42481 averageBitRate: 0
michael@0 42482 };
michael@0 42483 var mp3DecoderSession = new MP3DecoderSession();
michael@0 42484 mp3DecoderSession.onframedata = function (frame, channels, sampleRate, bitRate) {
michael@0 42485 if (durationEstimationData.estimateBitRate) {
michael@0 42486 var FramesToEstimate = 200;
michael@0 42487 if (durationEstimationData.bitRateCount < FramesToEstimate) {
michael@0 42488 durationEstimationData.bitRateSum += bitRate;
michael@0 42489 durationEstimationData.bitRateCount++;
michael@0 42490 } else {
michael@0 42491 durationEstimationData.estimateBitRate = false;
michael@0 42492 }
michael@0 42493 this.averageBitRate = durationEstimationData.bitRateSum / durationEstimationData.bitRateCount;
michael@0 42494 }
michael@0 42495 if (frame.length === 0)
michael@0 42496 return;
michael@0 42497 if (!position) {
michael@0 42498 soundData.sampleRate = sampleRate, soundData.channels = channels;
michael@0 42499 soundData.pcm = pcm;
michael@0 42500 }
michael@0 42501 if (position + frame.length >= currentSize) {
michael@0 42502 do {
michael@0 42503 currentSize *= 2;
michael@0 42504 } while (position + frame.length >= currentSize);
michael@0 42505 var newPcm = new Float32Array(currentSize);
michael@0 42506 newPcm.set(pcm);
michael@0 42507 pcm = soundData.pcm = newPcm;
michael@0 42508 }
michael@0 42509 pcm.set(frame, position);
michael@0 42510 soundData.end = position += frame.length;
michael@0 42511 lastTimeRatio = 1 / soundData.sampleRate / soundData.channels;
michael@0 42512 ondurationchanged(position * lastTimeRatio, false);
michael@0 42513 };
michael@0 42514 mp3DecoderSession.onid3tag = function (data) {
michael@0 42515 durationEstimationData.metadataSize += data.length;
michael@0 42516 }, mp3DecoderSession.onclosed = function () {
michael@0 42517 ondurationchanged(position * lastTimeRatio, true);
michael@0 42518 };
michael@0 42519 var completed = false;
michael@0 42520 return {
michael@0 42521 pushData: function (data) {
michael@0 42522 mp3DecoderSession.pushAsync(data);
michael@0 42523 },
michael@0 42524 estimateDuration: function (fileSize) {
michael@0 42525 return Math.max(0, (fileSize - durationEstimationData.metadataSize) * 8 / durationEstimationData.averageBitRate);
michael@0 42526 },
michael@0 42527 close: function () {
michael@0 42528 mp3DecoderSession.close();
michael@0 42529 }
michael@0 42530 };
michael@0 42531 }
michael@0 42532 var desc = Object.getOwnPropertyDescriptor;
michael@0 42533 def.__glue__ = {
michael@0 42534 native: {
michael@0 42535 instance: {
michael@0 42536 close: def.close,
michael@0 42537 extract: def.extract,
michael@0 42538 _load: def._load,
michael@0 42539 loadCompressedDataFromByteArray: def.loadCompressedDataFromByteArray,
michael@0 42540 loadPCMFromByteArray: def.loadPCMFromByteArray,
michael@0 42541 play: def.play,
michael@0 42542 bytesLoaded: desc(def, 'bytesLoaded'),
michael@0 42543 bytesTotal: desc(def, 'bytesTotal'),
michael@0 42544 id3: desc(def, 'id3'),
michael@0 42545 isBuffering: desc(def, 'isBuffering'),
michael@0 42546 isURLInaccessible: desc(def, 'isURLInaccessible'),
michael@0 42547 length: desc(def, 'length'),
michael@0 42548 url: desc(def, 'url')
michael@0 42549 }
michael@0 42550 }
michael@0 42551 };
michael@0 42552 return def;
michael@0 42553 }.call(this);
michael@0 42554 var SoundChannelDefinition = function () {
michael@0 42555 return {
michael@0 42556 initialize: function () {
michael@0 42557 this._element = null;
michael@0 42558 this._position = 0;
michael@0 42559 this._leftPeak = 0;
michael@0 42560 this._rightPeak = 0;
michael@0 42561 this._pcmData = null;
michael@0 42562 this._soundTransform = new flash.media.SoundTransform();
michael@0 42563 this._soundMixerClass = avm2.systemDomain.getClass('flash.media.SoundMixer');
michael@0 42564 var s = this.symbol;
michael@0 42565 if (s) {
michael@0 42566 this._element = s.element || null;
michael@0 42567 }
michael@0 42568 if (this._element) {
michael@0 42569 this._registerWithSoundMixer();
michael@0 42570 }
michael@0 42571 },
michael@0 42572 _registerWithSoundMixer: function () {
michael@0 42573 this._soundMixerClass.native.static._registerChannel(this);
michael@0 42574 },
michael@0 42575 _unregisterWithSoundMixer: function () {
michael@0 42576 this._soundMixerClass.native.static._unregisterChannel(this);
michael@0 42577 },
michael@0 42578 _applySoundTransform: function () {
michael@0 42579 var volume = this._soundTransform._volume;
michael@0 42580 if (this._soundMixerClass._soundTransform) {
michael@0 42581 volume *= this._soundMixerClass._soundTransform._volume;
michael@0 42582 }
michael@0 42583 volume *= this._soundMixerClass.native.static._getMasterVolume();
michael@0 42584 if (this._element) {
michael@0 42585 this._element.volume = clamp(volume, 0, 1);
michael@0 42586 }
michael@0 42587 if (this._audioChannel) {
michael@0 42588 }
michael@0 42589 },
michael@0 42590 _playSoundDataViaChannel: function (soundData, startTime, loops) {
michael@0 42591 this._registerWithSoundMixer();
michael@0 42592 var self = this;
michael@0 42593 var startPosition = Math.round(startTime / 1000 * soundData.sampleRate) * soundData.channels;
michael@0 42594 var position = startPosition;
michael@0 42595 this._position = startTime;
michael@0 42596 this._audioChannel = createAudioChannel(soundData.sampleRate, soundData.channels);
michael@0 42597 this._audioChannel.ondatarequested = function (e) {
michael@0 42598 var end = soundData.end;
michael@0 42599 if (position >= end && soundData.completed) {
michael@0 42600 self._unregisterWithSoundMixer();
michael@0 42601 self._audioChannel.stop();
michael@0 42602 self._dispatchEvent(new flash.events.Event('soundComplete', false, false));
michael@0 42603 return;
michael@0 42604 }
michael@0 42605 var left = e.count;
michael@0 42606 var data = e.data;
michael@0 42607 var source = soundData.pcm;
michael@0 42608 do {
michael@0 42609 var count = Math.min(end - position, left);
michael@0 42610 for (var j = 0; j < count; j++) {
michael@0 42611 data[j] = source[position++];
michael@0 42612 }
michael@0 42613 left -= count;
michael@0 42614 if (position >= end) {
michael@0 42615 if (!loops)
michael@0 42616 break;
michael@0 42617 loops--;
michael@0 42618 position = startPosition;
michael@0 42619 }
michael@0 42620 } while (left > 0);
michael@0 42621 self._position = position / soundData.sampleRate / soundData.channels * 1000;
michael@0 42622 };
michael@0 42623 this._audioChannel.start();
michael@0 42624 this._applySoundTransform();
michael@0 42625 },
michael@0 42626 _playSoundDataViaAudio: function (soundData, startTime, loops) {
michael@0 42627 if (!soundData.mimeType)
michael@0 42628 return;
michael@0 42629 this._registerWithSoundMixer();
michael@0 42630 this._position = startTime;
michael@0 42631 var self = this;
michael@0 42632 var lastCurrentTime = 0;
michael@0 42633 var element = document.createElement('audio');
michael@0 42634 if (!element.canPlayType(soundData.mimeType)) {
michael@0 42635 console.error('ERROR: "' + soundData.mimeType + '" ' + 'type playback is not supported by the browser');
michael@0 42636 return;
michael@0 42637 }
michael@0 42638 element.preload = 'metadata';
michael@0 42639 element.loop = loops > 0;
michael@0 42640 var blob = new Blob([
michael@0 42641 soundData.data
michael@0 42642 ], {
michael@0 42643 type: soundData.mimeType
michael@0 42644 });
michael@0 42645 element.src = URL.createObjectURL(blob);
michael@0 42646 element.addEventListener('loadeddata', function loaded() {
michael@0 42647 element.currentTime = startTime / 1000;
michael@0 42648 element.play();
michael@0 42649 });
michael@0 42650 element.addEventListener('timeupdate', function timeupdate() {
michael@0 42651 var currentTime = element.currentTime;
michael@0 42652 if (loops && lastCurrentTime > currentTime) {
michael@0 42653 --loops;
michael@0 42654 if (!loops)
michael@0 42655 element.loop = false;
michael@0 42656 if (currentTime < startTime / 1000)
michael@0 42657 element.currentTime = startTime / 1000;
michael@0 42658 }
michael@0 42659 self._position = (lastCurrentTime = currentTime) * 1000;
michael@0 42660 });
michael@0 42661 element.addEventListener('ended', function ended() {
michael@0 42662 self._unregisterWithSoundMixer();
michael@0 42663 self._dispatchEvent(new flash.events.Event('soundComplete', false, false));
michael@0 42664 self._element = null;
michael@0 42665 });
michael@0 42666 this._element = element;
michael@0 42667 this._applySoundTransform();
michael@0 42668 },
michael@0 42669 __glue__: {
michael@0 42670 native: {
michael@0 42671 static: {},
michael@0 42672 instance: {
michael@0 42673 stop: function stop() {
michael@0 42674 if (this._element) {
michael@0 42675 this._unregisterWithSoundMixer();
michael@0 42676 this._element.pause();
michael@0 42677 }
michael@0 42678 if (this._audioChannel) {
michael@0 42679 this._unregisterWithSoundMixer();
michael@0 42680 this._audioChannel.stop();
michael@0 42681 }
michael@0 42682 },
michael@0 42683 'position': {
michael@0 42684 get: function position() {
michael@0 42685 return this._position;
michael@0 42686 }
michael@0 42687 },
michael@0 42688 'leftPeak': {
michael@0 42689 get: function leftPeak() {
michael@0 42690 return this._leftPeak;
michael@0 42691 }
michael@0 42692 },
michael@0 42693 'rightPeak': {
michael@0 42694 get: function rightPeak() {
michael@0 42695 return this.rightPeak;
michael@0 42696 }
michael@0 42697 },
michael@0 42698 'soundTransform': {
michael@0 42699 get: function soundTransform() {
michael@0 42700 somewhatImplemented('SoundChannel.soundTransform');
michael@0 42701 return new flash.media.SoundTransform(this._soundTransform._volume, this._soundTransform.pan);
michael@0 42702 },
michael@0 42703 set: function soundTransform(soundTransform) {
michael@0 42704 somewhatImplemented('SoundChannel.soundTransform');
michael@0 42705 this._soundTransform = isNullOrUndefined(soundTransform) ? new flash.media.SoundTransform() : soundTransform;
michael@0 42706 this._applySoundTransform();
michael@0 42707 }
michael@0 42708 }
michael@0 42709 }
michael@0 42710 },
michael@0 42711 script: {
michael@0 42712 instance: scriptProperties('public', [
michael@0 42713 'stop'
michael@0 42714 ])
michael@0 42715 }
michael@0 42716 }
michael@0 42717 };
michael@0 42718 }.call(this);
michael@0 42719 function createAudioChannel(sampleRate, channels) {
michael@0 42720 if (WebAudioChannel.isSupported)
michael@0 42721 return new WebAudioChannel(sampleRate, channels);
michael@0 42722 else
michael@0 42723 error('PCM data playback is not supported by the browser');
michael@0 42724 }
michael@0 42725 function AudioResampler(sourceRate, targetRate) {
michael@0 42726 this.sourceRate = sourceRate;
michael@0 42727 this.targetRate = targetRate;
michael@0 42728 this.tail = [];
michael@0 42729 this.sourceOffset = 0;
michael@0 42730 }
michael@0 42731 AudioResampler.prototype = {
michael@0 42732 ondatarequested: function (e) {
michael@0 42733 },
michael@0 42734 getData: function (channelsData, count) {
michael@0 42735 var k = this.sourceRate / this.targetRate;
michael@0 42736 var offset = this.sourceOffset;
michael@0 42737 var needed = Math.ceil((count - 1) * k + offset) + 1;
michael@0 42738 var sourceData = [];
michael@0 42739 for (var channel = 0; channel < channelsData.length; channel++)
michael@0 42740 sourceData.push(new Float32Array(needed));
michael@0 42741 var e = {
michael@0 42742 data: sourceData,
michael@0 42743 count: needed
michael@0 42744 };
michael@0 42745 this.ondatarequested(e);
michael@0 42746 for (var channel = 0; channel < channelsData.length; channel++) {
michael@0 42747 var data = channelsData[channel];
michael@0 42748 var source = sourceData[channel];
michael@0 42749 for (var j = 0; j < count; j++) {
michael@0 42750 var i = j * k + offset;
michael@0 42751 var i1 = i | 0, i2 = Math.ceil(i) | 0;
michael@0 42752 var source_i1 = i1 < 0 ? this.tail[channel] : source[i1];
michael@0 42753 if (i1 === i2) {
michael@0 42754 data[j] = source_i1;
michael@0 42755 } else {
michael@0 42756 var alpha = i - i1;
michael@0 42757 data[j] = source_i1 * (1 - alpha) + source[i2] * alpha;
michael@0 42758 }
michael@0 42759 }
michael@0 42760 this.tail[channel] = source[needed - 1];
michael@0 42761 }
michael@0 42762 this.sourceOffset = (count - 1) * k + offset - (needed - 1);
michael@0 42763 }
michael@0 42764 };
michael@0 42765 function WebAudioChannel(sampleRate, channels) {
michael@0 42766 var context = WebAudioChannel.context;
michael@0 42767 if (!context) {
michael@0 42768 if (typeof AudioContext !== 'undefined')
michael@0 42769 context = new AudioContext();
michael@0 42770 else
michael@0 42771 context = new webkitAudioContext();
michael@0 42772 WebAudioChannel.context = context;
michael@0 42773 }
michael@0 42774 this.context = context;
michael@0 42775 this.contextSampleRate = context.sampleRate || 44100;
michael@0 42776 this.channels = channels;
michael@0 42777 this.sampleRate = sampleRate;
michael@0 42778 if (this.contextSampleRate != sampleRate) {
michael@0 42779 this.resampler = new AudioResampler(sampleRate, this.contextSampleRate);
michael@0 42780 this.resampler.ondatarequested = function (e) {
michael@0 42781 this.requestData(e.data, e.count);
michael@0 42782 }.bind(this);
michael@0 42783 }
michael@0 42784 }
michael@0 42785 WebAudioChannel.prototype = {
michael@0 42786 start: function () {
michael@0 42787 var source = this.context.createScriptProcessor ? this.context.createScriptProcessor(2048, 0, this.channels) : this.context.createJavaScriptNode(2048, 0, this.channels);
michael@0 42788 var self = this;
michael@0 42789 source.onaudioprocess = function (e) {
michael@0 42790 var channelsData = [];
michael@0 42791 for (var i = 0; i < self.channels; i++)
michael@0 42792 channelsData.push(e.outputBuffer.getChannelData(i));
michael@0 42793 var count = channelsData[0].length;
michael@0 42794 if (self.resampler) {
michael@0 42795 self.resampler.getData(channelsData, count);
michael@0 42796 } else {
michael@0 42797 var e = {
michael@0 42798 data: channelsData,
michael@0 42799 count: count
michael@0 42800 };
michael@0 42801 self.requestData(channelsData, count);
michael@0 42802 }
michael@0 42803 };
michael@0 42804 source.connect(this.context.destination);
michael@0 42805 this.source = source;
michael@0 42806 },
michael@0 42807 stop: function () {
michael@0 42808 this.source.disconnect(this.context.destination);
michael@0 42809 },
michael@0 42810 requestData: function (channelsData, count) {
michael@0 42811 var channels = this.channels;
michael@0 42812 var buffer = new Float32Array(count * channels);
michael@0 42813 var e = {
michael@0 42814 data: buffer,
michael@0 42815 count: buffer.length
michael@0 42816 };
michael@0 42817 this.ondatarequested(e);
michael@0 42818 for (var j = 0, p = 0; j < count; j++) {
michael@0 42819 for (var i = 0; i < channels; i++)
michael@0 42820 channelsData[i][j] = buffer[p++];
michael@0 42821 }
michael@0 42822 }
michael@0 42823 };
michael@0 42824 WebAudioChannel.isSupported = function () {
michael@0 42825 return typeof AudioContext !== 'undefined' || typeof webkitAudioContext != 'undefined';
michael@0 42826 }();
michael@0 42827 var SoundMixerDefinition = function () {
michael@0 42828 var masterVolume = 1;
michael@0 42829 var registeredChannels = [];
michael@0 42830 return {
michael@0 42831 __class__: 'flash.media.SoundMixer',
michael@0 42832 initialize: function () {
michael@0 42833 },
michael@0 42834 __glue__: {
michael@0 42835 native: {
michael@0 42836 static: {
michael@0 42837 _registerChannel: function _registerChannel(channel) {
michael@0 42838 registeredChannels.push(channel);
michael@0 42839 },
michael@0 42840 _unregisterChannel: function _unregisterChannel(channel) {
michael@0 42841 var index = registeredChannels.indexOf(channel);
michael@0 42842 if (index >= 0)
michael@0 42843 registeredChannels.splice(index, 1);
michael@0 42844 },
michael@0 42845 _getMasterVolume: function _getMasterVolume() {
michael@0 42846 return masterVolume;
michael@0 42847 },
michael@0 42848 _setMasterVolume: function _setMasterVolume(volume) {
michael@0 42849 masterVolume = volume;
michael@0 42850 registeredChannels.forEach(function (channel) {
michael@0 42851 channel._applySoundTransform();
michael@0 42852 });
michael@0 42853 },
michael@0 42854 stopAll: function stopAll() {
michael@0 42855 registeredChannels.forEach(function (channel) {
michael@0 42856 channel.stop();
michael@0 42857 });
michael@0 42858 registeredChannels = [];
michael@0 42859 },
michael@0 42860 computeSpectrum: function computeSpectrum(outputArray, FFTMode, stretchFactor) {
michael@0 42861 somewhatImplemented('SoundMixer.computeSpectrum');
michael@0 42862 var data = new Float32Array(1024);
michael@0 42863 for (var i = 0; i < 1024; i++) {
michael@0 42864 data[i] = Math.random();
michael@0 42865 }
michael@0 42866 outputArray.writeRawBytes(data);
michael@0 42867 outputArray.position = 0;
michael@0 42868 },
michael@0 42869 areSoundsInaccessible: function areSoundsInaccessible() {
michael@0 42870 notImplemented('SoundMixer.areSoundsInaccessible');
michael@0 42871 },
michael@0 42872 bufferTime: {
michael@0 42873 get: function bufferTime() {
michael@0 42874 notImplemented('SoundMixer.bufferTime');
michael@0 42875 },
michael@0 42876 set: function bufferTime(pA) {
michael@0 42877 notImplemented('SoundMixer.bufferTime');
michael@0 42878 }
michael@0 42879 },
michael@0 42880 soundTransform: {
michael@0 42881 get: function soundTransform() {
michael@0 42882 somewhatImplemented('SoundMixer.soundTransform');
michael@0 42883 return isNullOrUndefined(this._soundTransform) ? new flash.media.SoundTransform() : new flash.media.SoundTransform(this._soundTransform._volume, this._soundTransform.pan);
michael@0 42884 },
michael@0 42885 set: function soundTransform(soundTransform) {
michael@0 42886 somewhatImplemented('SoundMixer.soundTransform');
michael@0 42887 this._soundTransform = isNullOrUndefined(soundTransform) ? new flash.media.SoundTransform() : soundTransform;
michael@0 42888 registeredChannels.forEach(function (channel) {
michael@0 42889 channel._applySoundTransform();
michael@0 42890 });
michael@0 42891 }
michael@0 42892 },
michael@0 42893 audioPlaybackMode: {
michael@0 42894 get: function audioPlaybackMode() {
michael@0 42895 notImplemented('SoundMixer.audioPlaybackMode');
michael@0 42896 },
michael@0 42897 set: function audioPlaybackMode(pA) {
michael@0 42898 notImplemented('SoundMixer.audioPlaybackMode');
michael@0 42899 }
michael@0 42900 },
michael@0 42901 useSpeakerphoneForVoice: {
michael@0 42902 get: function useSpeakerphoneForVoice() {
michael@0 42903 notImplemented('SoundMixer.useSpeakerphoneForVoice');
michael@0 42904 },
michael@0 42905 set: function useSpeakerphoneForVoice(pA) {
michael@0 42906 notImplemented('SoundMixer.useSpeakerphoneForVoice');
michael@0 42907 }
michael@0 42908 }
michael@0 42909 },
michael@0 42910 instance: {}
michael@0 42911 }
michael@0 42912 }
michael@0 42913 };
michael@0 42914 }.call(this);
michael@0 42915 var SoundTransformDefinition = function () {
michael@0 42916 return {
michael@0 42917 __class__: 'flash.media.SoundTransform',
michael@0 42918 initialize: function () {
michael@0 42919 },
michael@0 42920 _updateTransform: function () {
michael@0 42921 somewhatImplemented('SoundTransform._updateTransform');
michael@0 42922 },
michael@0 42923 __glue__: {
michael@0 42924 native: {
michael@0 42925 static: {},
michael@0 42926 instance: {
michael@0 42927 volume: {
michael@0 42928 get: function volume() {
michael@0 42929 return this._volume;
michael@0 42930 },
michael@0 42931 set: function volume(volume) {
michael@0 42932 this._volume = volume;
michael@0 42933 this._updateTransform();
michael@0 42934 }
michael@0 42935 },
michael@0 42936 leftToLeft: {
michael@0 42937 get: function leftToLeft() {
michael@0 42938 return this._leftToLeft;
michael@0 42939 },
michael@0 42940 set: function leftToLeft(leftToLeft) {
michael@0 42941 this._leftToLeft = leftToLeft;
michael@0 42942 this._updateTransform();
michael@0 42943 }
michael@0 42944 },
michael@0 42945 leftToRight: {
michael@0 42946 get: function leftToRight() {
michael@0 42947 return this._leftToRight;
michael@0 42948 },
michael@0 42949 set: function leftToRight(leftToRight) {
michael@0 42950 this._leftToRight = leftToRight;
michael@0 42951 this._updateTransform();
michael@0 42952 }
michael@0 42953 },
michael@0 42954 rightToRight: {
michael@0 42955 get: function rightToRight() {
michael@0 42956 return this._rightToRight;
michael@0 42957 },
michael@0 42958 set: function rightToRight(rightToRight) {
michael@0 42959 this._rightToRight = rightToRight;
michael@0 42960 this._updateTransform();
michael@0 42961 }
michael@0 42962 },
michael@0 42963 rightToLeft: {
michael@0 42964 get: function rightToLeft() {
michael@0 42965 return this._rightToLeft;
michael@0 42966 },
michael@0 42967 set: function rightToLeft(rightToLeft) {
michael@0 42968 this._rightToLeft = rightToLeft;
michael@0 42969 this._updateTransform();
michael@0 42970 }
michael@0 42971 }
michael@0 42972 }
michael@0 42973 },
michael@0 42974 script: {
michael@0 42975 instance: {
michael@0 42976 pan: 'public pan'
michael@0 42977 }
michael@0 42978 }
michael@0 42979 }
michael@0 42980 };
michael@0 42981 }.call(this);
michael@0 42982 var StageVideoDefinition = function () {
michael@0 42983 return {
michael@0 42984 __class__: 'flash.media.StageVideo',
michael@0 42985 initialize: function () {
michael@0 42986 },
michael@0 42987 __glue__: {
michael@0 42988 native: {
michael@0 42989 static: {},
michael@0 42990 instance: {
michael@0 42991 attachNetStream: function attachNetStream(netStream) {
michael@0 42992 notImplemented('StageVideo.attachNetStream');
michael@0 42993 },
michael@0 42994 attachCamera: function attachCamera(theCamera) {
michael@0 42995 notImplemented('StageVideo.attachCamera');
michael@0 42996 },
michael@0 42997 viewPort: {
michael@0 42998 get: function viewPort() {
michael@0 42999 notImplemented('StageVideo.viewPort');
michael@0 43000 return this._viewPort;
michael@0 43001 },
michael@0 43002 set: function viewPort(rect) {
michael@0 43003 notImplemented('StageVideo.viewPort');
michael@0 43004 this._viewPort = rect;
michael@0 43005 }
michael@0 43006 },
michael@0 43007 pan: {
michael@0 43008 set: function pan(point) {
michael@0 43009 notImplemented('StageVideo.pan');
michael@0 43010 this._pan = point;
michael@0 43011 },
michael@0 43012 get: function pan() {
michael@0 43013 notImplemented('StageVideo.pan');
michael@0 43014 return this._pan;
michael@0 43015 }
michael@0 43016 },
michael@0 43017 zoom: {
michael@0 43018 set: function zoom(point) {
michael@0 43019 notImplemented('StageVideo.zoom');
michael@0 43020 this._zoom = point;
michael@0 43021 },
michael@0 43022 get: function zoom() {
michael@0 43023 notImplemented('StageVideo.zoom');
michael@0 43024 return this._zoom;
michael@0 43025 }
michael@0 43026 },
michael@0 43027 depth: {
michael@0 43028 set: function depth(depth) {
michael@0 43029 notImplemented('StageVideo.depth');
michael@0 43030 this._depth = depth;
michael@0 43031 },
michael@0 43032 get: function depth() {
michael@0 43033 notImplemented('StageVideo.depth');
michael@0 43034 return this._depth;
michael@0 43035 }
michael@0 43036 },
michael@0 43037 videoWidth: {
michael@0 43038 get: function videoWidth() {
michael@0 43039 notImplemented('StageVideo.videoWidth');
michael@0 43040 return this._videoWidth;
michael@0 43041 }
michael@0 43042 },
michael@0 43043 videoHeight: {
michael@0 43044 get: function videoHeight() {
michael@0 43045 notImplemented('StageVideo.videoHeight');
michael@0 43046 return this._videoHeight;
michael@0 43047 }
michael@0 43048 },
michael@0 43049 colorSpaces: {
michael@0 43050 get: function colorSpaces() {
michael@0 43051 notImplemented('StageVideo.colorSpaces');
michael@0 43052 return this._colorSpaces;
michael@0 43053 }
michael@0 43054 }
michael@0 43055 }
michael@0 43056 }
michael@0 43057 }
michael@0 43058 };
michael@0 43059 }.call(this);
michael@0 43060 var VideoDefinition = function () {
michael@0 43061 function burnHole(ctx, x, y, width, height) {
michael@0 43062 ctx.save();
michael@0 43063 ctx.beginPath();
michael@0 43064 ctx.rect(0, 0, width, height);
michael@0 43065 ctx.clip();
michael@0 43066 ctx.clearRect(0, 0, width, height);
michael@0 43067 ctx.restore();
michael@0 43068 }
michael@0 43069 var def = {
michael@0 43070 initialize: function initialize() {
michael@0 43071 TelemetryService.reportTelemetry({
michael@0 43072 topic: 'feature',
michael@0 43073 feature: VIDEO_FEATURE
michael@0 43074 });
michael@0 43075 },
michael@0 43076 attachNetStream: function (netStream) {
michael@0 43077 if (this._netStream === netStream) {
michael@0 43078 return;
michael@0 43079 }
michael@0 43080 if (this._netStream) {
michael@0 43081 this._netStream._videoReady.then(function (element) {
michael@0 43082 this._element = null;
michael@0 43083 if (this._added) {
michael@0 43084 element.remove();
michael@0 43085 this._added = false;
michael@0 43086 }
michael@0 43087 }.bind(this));
michael@0 43088 }
michael@0 43089 this._netStream = netStream;
michael@0 43090 if (!netStream) {
michael@0 43091 return;
michael@0 43092 }
michael@0 43093 netStream._videoReady.then(function (element) {
michael@0 43094 this._element = element;
michael@0 43095 netStream._videoMetadataReady.then(function (url) {
michael@0 43096 this._element.width = this._videoWidth = this._element.videoWidth;
michael@0 43097 this._element.height = this._videoHeight = this._element.videoHeight;
michael@0 43098 if (this.stage) {
michael@0 43099 this.stage._invalid = true;
michael@0 43100 }
michael@0 43101 }.bind(this));
michael@0 43102 }.bind(this));
michael@0 43103 },
michael@0 43104 ctor: function (width, height) {
michael@0 43105 if (!width || width < 0)
michael@0 43106 width = 320;
michael@0 43107 if (!height || height < 0)
michael@0 43108 height = 240;
michael@0 43109 this._bbox = {
michael@0 43110 xMin: 0,
michael@0 43111 yMin: 0,
michael@0 43112 xMax: width * 20,
michael@0 43113 yMax: height * 20
michael@0 43114 };
michael@0 43115 this._initialWidth = this._videoWidth = width;
michael@0 43116 this._initialHeight = this._videoHeight = height;
michael@0 43117 this._netStream = null;
michael@0 43118 this._element = null;
michael@0 43119 this._added = false;
michael@0 43120 },
michael@0 43121 draw: function (ctx, ratio, ct, parentCtxs) {
michael@0 43122 if (!this._element) {
michael@0 43123 return;
michael@0 43124 }
michael@0 43125 if (!this._added && this._stage) {
michael@0 43126 this._stage._domContainer.appendChild(this._element);
michael@0 43127 this._added = true;
michael@0 43128 }
michael@0 43129 var width = this._initialWidth;
michael@0 43130 var height = this._initialHeight;
michael@0 43131 var matrix = this._getConcatenatedTransform(null, true);
michael@0 43132 var scaleFactor = this.stage && this.stage._contentsScaleFactor || 1;
michael@0 43133 var a = matrix.a / scaleFactor;
michael@0 43134 var b = matrix.b / scaleFactor;
michael@0 43135 var c = matrix.c / scaleFactor;
michael@0 43136 var d = matrix.d / scaleFactor;
michael@0 43137 var e = matrix.tx / 20 / scaleFactor;
michael@0 43138 var f = matrix.ty / 20 / scaleFactor;
michael@0 43139 if (width > 0 && height > 0) {
michael@0 43140 burnHole(ctx, 0, 0, width, height);
michael@0 43141 parentCtxs.forEach(function (ctx) {
michael@0 43142 ctx.save();
michael@0 43143 ctx.setTransform(a, b, c, d, e, f);
michael@0 43144 burnHole(ctx, 0, 0, width, height);
michael@0 43145 ctx.restore();
michael@0 43146 });
michael@0 43147 }
michael@0 43148 var sx = width / this._videoWidth;
michael@0 43149 var sy = height / this._videoHeight;
michael@0 43150 var cssTransform = 'transform: matrix(' + sx * a + ',' + sx * b + ',' + sy * c + ',' + sy * d + ',' + e + ',' + f + ');';
michael@0 43151 if (this._currentCssTransform !== cssTransform) {
michael@0 43152 this._currentCssTransform = cssTransform;
michael@0 43153 this._element.setAttribute('style', 'position: absolute; top:0; left:0; z-index: -100;transform-origin: 0px 0px 0;' + cssTransform + '-webkit-transform-origin: 0px 0px 0; -webkit-' + cssTransform);
michael@0 43154 }
michael@0 43155 }
michael@0 43156 };
michael@0 43157 def.__glue__ = {
michael@0 43158 native: {
michael@0 43159 instance: {
michael@0 43160 attachNetStream: def.attachNetStream,
michael@0 43161 ctor: def.ctor,
michael@0 43162 smoothing: {
michael@0 43163 get: function smoothing() {
michael@0 43164 return this._smoothing;
michael@0 43165 },
michael@0 43166 set: function smoothing(value) {
michael@0 43167 somewhatImplemented('Video.smoothing');
michael@0 43168 this._smoothing = value;
michael@0 43169 }
michael@0 43170 },
michael@0 43171 videoHeight: {
michael@0 43172 get: function videoHeight() {
michael@0 43173 return this._videoHeight;
michael@0 43174 }
michael@0 43175 },
michael@0 43176 videoWidth: {
michael@0 43177 get: function videoWidth() {
michael@0 43178 return this._videoWidth;
michael@0 43179 }
michael@0 43180 }
michael@0 43181 }
michael@0 43182 }
michael@0 43183 };
michael@0 43184 return def;
michael@0 43185 }.call(this);
michael@0 43186 {
michael@0 43187 var FileFilterDefinition = function () {
michael@0 43188 return {
michael@0 43189 __class__: 'flash.net.FileFilter',
michael@0 43190 initialize: function () {
michael@0 43191 this._description = null;
michael@0 43192 this._extension = null;
michael@0 43193 this._macType = null;
michael@0 43194 },
michael@0 43195 __glue__: {
michael@0 43196 native: {
michael@0 43197 static: {},
michael@0 43198 instance: {
michael@0 43199 description: {
michael@0 43200 get: function description() {
michael@0 43201 return this._description;
michael@0 43202 },
michael@0 43203 set: function description(value) {
michael@0 43204 this._description = value;
michael@0 43205 }
michael@0 43206 },
michael@0 43207 extension: {
michael@0 43208 get: function extension() {
michael@0 43209 return this._extension;
michael@0 43210 },
michael@0 43211 set: function extension(value) {
michael@0 43212 this._extension = value;
michael@0 43213 }
michael@0 43214 },
michael@0 43215 macType: {
michael@0 43216 get: function macType() {
michael@0 43217 return this._macType;
michael@0 43218 },
michael@0 43219 set: function macType(value) {
michael@0 43220 this._macType = value;
michael@0 43221 }
michael@0 43222 }
michael@0 43223 }
michael@0 43224 }
michael@0 43225 }
michael@0 43226 };
michael@0 43227 }.call(this);
michael@0 43228 }
michael@0 43229 var LocalConnectionDefinition = function () {
michael@0 43230 return {
michael@0 43231 __class__: 'flash.net.LocalConnection',
michael@0 43232 initialize: function () {
michael@0 43233 },
michael@0 43234 __glue__: {
michael@0 43235 native: {
michael@0 43236 static: {},
michael@0 43237 instance: {
michael@0 43238 close: function close() {
michael@0 43239 notImplemented('LocalConnection.close');
michael@0 43240 },
michael@0 43241 connect: function connect(connectionName) {
michael@0 43242 notImplemented('LocalConnection.connect');
michael@0 43243 },
michael@0 43244 send: function send(connectionName, methodName) {
michael@0 43245 notImplemented('LocalConnection.send');
michael@0 43246 },
michael@0 43247 allowDomain: function allowDomain() {
michael@0 43248 notImplemented('LocalConnection.allowDomain');
michael@0 43249 },
michael@0 43250 allowInsecureDomain: function allowInsecureDomain() {
michael@0 43251 notImplemented('LocalConnection.allowInsecureDomain');
michael@0 43252 },
michael@0 43253 domain: {
michael@0 43254 get: function domain() {
michael@0 43255 somewhatImplemented('LocalConnection.domain');
michael@0 43256 var url = FileLoadingService.resolveUrl('/');
michael@0 43257 var m = /:\/\/(.+?)[:?#\/]/.exec(url);
michael@0 43258 return m && m[1];
michael@0 43259 }
michael@0 43260 },
michael@0 43261 client: {
michael@0 43262 get: function client() {
michael@0 43263 notImplemented('LocalConnection.client');
michael@0 43264 return this._client;
michael@0 43265 },
michael@0 43266 set: function client(client) {
michael@0 43267 notImplemented('LocalConnection.client');
michael@0 43268 this._client = client;
michael@0 43269 }
michael@0 43270 },
michael@0 43271 isPerUser: {
michael@0 43272 get: function isPerUser() {
michael@0 43273 notImplemented('LocalConnection.isPerUser');
michael@0 43274 return this._isPerUser;
michael@0 43275 },
michael@0 43276 set: function isPerUser(newValue) {
michael@0 43277 notImplemented('LocalConnection.isPerUser');
michael@0 43278 this._isPerUser = newValue;
michael@0 43279 }
michael@0 43280 }
michael@0 43281 }
michael@0 43282 }
michael@0 43283 }
michael@0 43284 };
michael@0 43285 }.call(this);
michael@0 43286 var NetConnectionDefinition = function () {
michael@0 43287 var defaultObjectEncoding = 3;
michael@0 43288 return {
michael@0 43289 __class__: 'flash.net.NetConnection',
michael@0 43290 initialize: function () {
michael@0 43291 TelemetryService.reportTelemetry({
michael@0 43292 topic: 'feature',
michael@0 43293 feature: NETCONNECTION_FEATURE
michael@0 43294 });
michael@0 43295 },
michael@0 43296 _invoke: function (index, args) {
michael@0 43297 var simulated = false, result;
michael@0 43298 switch (index) {
michael@0 43299 case 2:
michael@0 43300 simulated = true;
michael@0 43301 break;
michael@0 43302 }
michael@0 43303 (simulated ? somewhatImplemented : notImplemented)('NetConnection._invoke (' + index + ')');
michael@0 43304 return result;
michael@0 43305 },
michael@0 43306 __glue__: {
michael@0 43307 native: {
michael@0 43308 static: {
michael@0 43309 defaultObjectEncoding: {
michael@0 43310 get: function defaultObjectEncoding() {
michael@0 43311 return defaultObjectEncoding;
michael@0 43312 },
michael@0 43313 set: function defaultObjectEncoding(version) {
michael@0 43314 somewhatImplemented('NetConnection.defaultObjectEncoding');
michael@0 43315 return defaultObjectEncoding;
michael@0 43316 }
michael@0 43317 }
michael@0 43318 },
michael@0 43319 instance: {
michael@0 43320 ctor: function ctor() {
michael@0 43321 this._uri = null;
michael@0 43322 this._connected = false;
michael@0 43323 this._client = null;
michael@0 43324 this._proxyType = 'none';
michael@0 43325 this._objectEncoding = defaultObjectEncoding;
michael@0 43326 },
michael@0 43327 connect: function connect(command) {
michael@0 43328 var NetStatusEvent = flash.events.NetStatusEvent;
michael@0 43329 somewhatImplemented('NetConnection.connect');
michael@0 43330 this._uri = command;
michael@0 43331 if (!command) {
michael@0 43332 this._connected = true;
michael@0 43333 this._dispatchEvent(new NetStatusEvent(NetStatusEvent.class.NET_STATUS, false, false, wrapJSObject({
michael@0 43334 level: 'status',
michael@0 43335 code: 'NetConnection.Connect.Success'
michael@0 43336 })));
michael@0 43337 } else {
michael@0 43338 this._dispatchEvent(new NetStatusEvent(NetStatusEvent.class.NET_STATUS, false, false, wrapJSObject({
michael@0 43339 level: 'status',
michael@0 43340 code: 'NetConnection.Connect.Failed'
michael@0 43341 })));
michael@0 43342 }
michael@0 43343 },
michael@0 43344 call: function call(command, responder) {
michael@0 43345 notImplemented('NetConnection.call');
michael@0 43346 },
michael@0 43347 connected: {
michael@0 43348 get: function connected() {
michael@0 43349 return this._connected;
michael@0 43350 }
michael@0 43351 },
michael@0 43352 uri: {
michael@0 43353 get: function uri() {
michael@0 43354 return this._uri;
michael@0 43355 }
michael@0 43356 },
michael@0 43357 client: {
michael@0 43358 get: function client() {
michael@0 43359 return this._client;
michael@0 43360 },
michael@0 43361 set: function client(object) {
michael@0 43362 this._client = object;
michael@0 43363 }
michael@0 43364 },
michael@0 43365 objectEncoding: {
michael@0 43366 get: function objectEncoding() {
michael@0 43367 return this._objectEncoding;
michael@0 43368 },
michael@0 43369 set: function objectEncoding(version) {
michael@0 43370 somewhatImplemented('NetConnection.objectEncoding');
michael@0 43371 this._objectEncoding = version;
michael@0 43372 }
michael@0 43373 },
michael@0 43374 proxyType: {
michael@0 43375 get: function proxyType() {
michael@0 43376 return this._proxyType;
michael@0 43377 },
michael@0 43378 set: function proxyType(ptype) {
michael@0 43379 notImplemented('NetConnection.proxyType');
michael@0 43380 this._proxyType = ptype;
michael@0 43381 }
michael@0 43382 },
michael@0 43383 connectedProxyType: {
michael@0 43384 get: function connectedProxyType() {
michael@0 43385 notImplemented('NetConnection.connectedProxyType');
michael@0 43386 return this._connectedProxyType;
michael@0 43387 }
michael@0 43388 },
michael@0 43389 usingTLS: {
michael@0 43390 get: function usingTLS() {
michael@0 43391 somewhatImplemented('NetConnection.usingTLS');
michael@0 43392 return false;
michael@0 43393 }
michael@0 43394 },
michael@0 43395 protocol: {
michael@0 43396 get: function protocol() {
michael@0 43397 notImplemented('NetConnection.protocol');
michael@0 43398 return this._protocol;
michael@0 43399 }
michael@0 43400 },
michael@0 43401 maxPeerConnections: {
michael@0 43402 get: function maxPeerConnections() {
michael@0 43403 notImplemented('NetConnection.maxPeerConnections');
michael@0 43404 return this._maxPeerConnections;
michael@0 43405 },
michael@0 43406 set: function maxPeerConnections(maxPeers) {
michael@0 43407 notImplemented('NetConnection.maxPeerConnections');
michael@0 43408 this._maxPeerConnections = maxPeers;
michael@0 43409 }
michael@0 43410 },
michael@0 43411 nearID: {
michael@0 43412 get: function nearID() {
michael@0 43413 notImplemented('NetConnection.nearID');
michael@0 43414 return this._nearID;
michael@0 43415 }
michael@0 43416 },
michael@0 43417 farID: {
michael@0 43418 get: function farID() {
michael@0 43419 notImplemented('NetConnection.farID');
michael@0 43420 return this._farID;
michael@0 43421 }
michael@0 43422 },
michael@0 43423 nearNonce: {
michael@0 43424 get: function nearNonce() {
michael@0 43425 notImplemented('NetConnection.nearNonce');
michael@0 43426 return this._nearNonce;
michael@0 43427 }
michael@0 43428 },
michael@0 43429 farNonce: {
michael@0 43430 get: function farNonce() {
michael@0 43431 notImplemented('NetConnection.farNonce');
michael@0 43432 return this._farNonce;
michael@0 43433 }
michael@0 43434 },
michael@0 43435 unconnectedPeerStreams: {
michael@0 43436 get: function unconnectedPeerStreams() {
michael@0 43437 notImplemented('NetConnection.unconnectedPeerStreams');
michael@0 43438 return this._unconnectedPeerStreams;
michael@0 43439 }
michael@0 43440 },
michael@0 43441 invoke: function invokeWithArgsArray(index) {
michael@0 43442 return this._invoke(index, Array.prototype.slice.call(arguments, 1));
michael@0 43443 },
michael@0 43444 invokeWithArgsArray: function invokeWithArgsArray(index, p_arguments) {
michael@0 43445 return this._invoke.call(this, index, p_arguments);
michael@0 43446 }
michael@0 43447 }
michael@0 43448 }
michael@0 43449 }
michael@0 43450 };
michael@0 43451 }.call(this);
michael@0 43452 var USE_MEDIASOURCE_API = false;
michael@0 43453 var NetStreamDefinition = function () {
michael@0 43454 return {
michael@0 43455 __class__: 'flash.net.NetStream',
michael@0 43456 initialize: function () {
michael@0 43457 },
michael@0 43458 _invoke: function (index, args) {
michael@0 43459 var simulated = false, result;
michael@0 43460 var videoElement = this._videoElement;
michael@0 43461 switch (index) {
michael@0 43462 case 4:
michael@0 43463 this._videoState.bufferTime = args[0];
michael@0 43464 simulated = true;
michael@0 43465 break;
michael@0 43466 case 202:
michael@0 43467 switch (args[1]) {
michael@0 43468 case 'pause':
michael@0 43469 simulated = true;
michael@0 43470 if (videoElement) {
michael@0 43471 if (args[3] !== false && !videoElement.paused) {
michael@0 43472 videoElement.pause();
michael@0 43473 } else if (args[3] !== true && videoElement.paused) {
michael@0 43474 videoElement.play();
michael@0 43475 }
michael@0 43476 videoElement.currentTime = args[4] / 1000;
michael@0 43477 }
michael@0 43478 break;
michael@0 43479 case 'seek':
michael@0 43480 simulated = true;
michael@0 43481 if (videoElement && !videoElement.paused) {
michael@0 43482 videoElement.currentTime = args[3] / 1000;
michael@0 43483 }
michael@0 43484 break;
michael@0 43485 }
michael@0 43486 break;
michael@0 43487 case 300:
michael@0 43488 result = videoElement ? videoElement.currentTime : 0;
michael@0 43489 simulated = true;
michael@0 43490 break;
michael@0 43491 case 302:
michael@0 43492 result = this._videoState.bufferTime;
michael@0 43493 simulated = true;
michael@0 43494 break;
michael@0 43495 case 303:
michael@0 43496 result = videoElement ? videoElement.duration : 0;
michael@0 43497 simulated = true;
michael@0 43498 break;
michael@0 43499 case 305:
michael@0 43500 result = this._videoState.buffer === 'full' ? 100 : this._videoState.buffer === 'progress' ? 50 : 0;
michael@0 43501 simulated = true;
michael@0 43502 break;
michael@0 43503 case 306:
michael@0 43504 result = 100;
michael@0 43505 simulated = true;
michael@0 43506 break;
michael@0 43507 }
michael@0 43508 (simulated ? somewhatImplemented : notImplemented)('NetStream._invoke (' + index + ')');
michael@0 43509 return result;
michael@0 43510 },
michael@0 43511 _createVideoElement: function (url) {
michael@0 43512 function notifyPlayStart(e) {
michael@0 43513 if (netStream._videoState.started) {
michael@0 43514 return;
michael@0 43515 }
michael@0 43516 netStream._videoState.started = true;
michael@0 43517 netStream._dispatchEvent(new NetStatusEvent(NetStatusEvent.class.NET_STATUS, false, false, wrapJSObject({
michael@0 43518 code: 'NetStream.Play.Start',
michael@0 43519 level: 'status'
michael@0 43520 })));
michael@0 43521 }
michael@0 43522 function notifyPlayStop(e) {
michael@0 43523 netStream._videoState.started = false;
michael@0 43524 netStream._dispatchEvent(new NetStatusEvent(NetStatusEvent.class.NET_STATUS, false, false, wrapJSObject({
michael@0 43525 code: 'NetStream.Play.Stop',
michael@0 43526 level: 'status'
michael@0 43527 })));
michael@0 43528 }
michael@0 43529 function notifyBufferFull(e) {
michael@0 43530 netStream._videoState.buffer = 'full';
michael@0 43531 netStream._dispatchEvent(new NetStatusEvent(NetStatusEvent.class.NET_STATUS, false, false, wrapJSObject({
michael@0 43532 code: 'NetStream.Buffer.Full',
michael@0 43533 level: 'status'
michael@0 43534 })));
michael@0 43535 }
michael@0 43536 function notifyProgress(e) {
michael@0 43537 netStream._videoState.buffer = 'progress';
michael@0 43538 }
michael@0 43539 function notifyBufferEmpty(e) {
michael@0 43540 netStream._videoState.buffer = 'empty';
michael@0 43541 netStream._dispatchEvent(new NetStatusEvent(NetStatusEvent.class.NET_STATUS, false, false, wrapJSObject({
michael@0 43542 code: 'NetStream.Buffer.Empty',
michael@0 43543 level: 'status'
michael@0 43544 })));
michael@0 43545 }
michael@0 43546 function notifyError(e) {
michael@0 43547 var code = e.target.error.code === 4 ? 'NetStream.Play.NoSupportedTrackFound' : e.target.error.code === 3 ? 'NetStream.Play.FileStructureInvalid' : 'NetStream.Play.StreamNotFound';
michael@0 43548 netStream._dispatchEvent(new NetStatusEvent(NetStatusEvent.class.NET_STATUS, false, false, wrapJSObject({
michael@0 43549 code: code,
michael@0 43550 level: 'error'
michael@0 43551 })));
michael@0 43552 }
michael@0 43553 function notifyMetadata(e) {
michael@0 43554 netStream._videoMetadataReady.resolve({
michael@0 43555 videoWidth: element.videoWidth,
michael@0 43556 videoHeight: element.videoHeight
michael@0 43557 });
michael@0 43558 if (netStream._client) {
michael@0 43559 var data = {};
michael@0 43560 data.asSetPublicProperty('width', element.videoWidth);
michael@0 43561 data.asSetPublicProperty('height', element.videoHeight);
michael@0 43562 data.asSetPublicProperty('duration', element.duration);
michael@0 43563 netStream._client.asCallPublicProperty('onMetaData', [
michael@0 43564 data
michael@0 43565 ]);
michael@0 43566 }
michael@0 43567 }
michael@0 43568 var NetStatusEvent = flash.events.NetStatusEvent;
michael@0 43569 var netStream = this;
michael@0 43570 if (/\.mp4$/i.test(url) && /Intel Mac OS X.*?Firefox\/\d+/.test(window.navigator.userAgent)) {
michael@0 43571 url = 'http://videos-cdn.mozilla.net/brand/Mozilla_2011_Story.webm';
michael@0 43572 }
michael@0 43573 var element = document.createElement('video');
michael@0 43574 element.preload = 'metadata';
michael@0 43575 element.src = url;
michael@0 43576 element.addEventListener('play', notifyPlayStart);
michael@0 43577 element.addEventListener('ended', notifyPlayStop);
michael@0 43578 element.addEventListener('loadeddata', notifyBufferFull);
michael@0 43579 element.addEventListener('progress', notifyProgress);
michael@0 43580 element.addEventListener('waiting', notifyBufferEmpty);
michael@0 43581 element.addEventListener('loadedmetadata', notifyMetadata);
michael@0 43582 element.addEventListener('error', notifyError);
michael@0 43583 element.play();
michael@0 43584 this._videoElement = element;
michael@0 43585 this._videoReady.resolve(element);
michael@0 43586 },
michael@0 43587 __glue__: {
michael@0 43588 script: {
michael@0 43589 instance: scriptProperties('public', [
michael@0 43590 'appendBytes',
michael@0 43591 'appendBytesAction'
michael@0 43592 ])
michael@0 43593 },
michael@0 43594 native: {
michael@0 43595 static: {},
michael@0 43596 instance: {
michael@0 43597 ctor: function ctor(connection, peerID) {
michael@0 43598 somewhatImplemented('NetStream.ctor');
michael@0 43599 this._contentTypeHint = null;
michael@0 43600 this._mediaSource = null;
michael@0 43601 this._checkPolicyFile = true;
michael@0 43602 this._videoElement = null;
michael@0 43603 var videoReadyResolve, videoReadyReject;
michael@0 43604 this._videoReady = new Promise(function (resolve, reject) {
michael@0 43605 videoReadyResolve = resolve;
michael@0 43606 videoReadyReject = reject;
michael@0 43607 });
michael@0 43608 this._videoReady.resolve = videoReadyResolve;
michael@0 43609 this._videoReady.reject = videoReadyReject;
michael@0 43610 var videoMetadataReadyResolve, videoMetadataReadyReject;
michael@0 43611 this._videoMetadataReady = new Promise(function (resolve, reject) {
michael@0 43612 videoMetadataReadyResolve = resolve;
michael@0 43613 videoMetadataReadyReject = reject;
michael@0 43614 });
michael@0 43615 this._videoMetadataReady.resolve = videoMetadataReadyResolve;
michael@0 43616 this._videoMetadataReady.reject = videoMetadataReadyReject;
michael@0 43617 this._videoState = {
michael@0 43618 started: false,
michael@0 43619 buffer: 'empty',
michael@0 43620 bufferTime: 0.1
michael@0 43621 };
michael@0 43622 },
michael@0 43623 onResult: function onResult(streamId) {
michael@0 43624 notImplemented('NetStream.onResult');
michael@0 43625 },
michael@0 43626 dispose: function dispose() {
michael@0 43627 notImplemented('NetStream.dispose');
michael@0 43628 },
michael@0 43629 play: function play(url) {
michael@0 43630 var isMediaSourceEnabled = USE_MEDIASOURCE_API;
michael@0 43631 if (isMediaSourceEnabled && typeof MediaSource === 'undefined') {
michael@0 43632 console.warn('MediaSource API is not enabled, falling back to regular playback');
michael@0 43633 isMediaSourceEnabled = false;
michael@0 43634 }
michael@0 43635 if (!isMediaSourceEnabled) {
michael@0 43636 somewhatImplemented('NetStream.play');
michael@0 43637 this._createVideoElement(FileLoadingService.resolveUrl(url));
michael@0 43638 return;
michael@0 43639 }
michael@0 43640 var mediaSource = new MediaSource();
michael@0 43641 mediaSource.addEventListener('sourceopen', function (e) {
michael@0 43642 this._mediaSource = mediaSource;
michael@0 43643 }.bind(this));
michael@0 43644 mediaSource.addEventListener('sourceend', function (e) {
michael@0 43645 this._mediaSource = null;
michael@0 43646 }.bind(this));
michael@0 43647 this._createVideoElement(window.URL.createObjectURL(mediaSource));
michael@0 43648 if (!url) {
michael@0 43649 return;
michael@0 43650 }
michael@0 43651 var request = new flash.net.URLRequest(url);
michael@0 43652 request._checkPolicyFile = this._checkPolicyFile;
michael@0 43653 var stream = new flash.net.URLStream();
michael@0 43654 stream._addEventListener('httpStatus', function (e) {
michael@0 43655 var responseHeaders = e.asGetPublicProperty('responseHeaders');
michael@0 43656 var contentTypeHeader = responseHeaders.filter(function (h) {
michael@0 43657 return h.asGetPublicProperty('name') === 'Content-Type';
michael@0 43658 })[0];
michael@0 43659 if (contentTypeHeader && contentTypeHeader.asGetPublicProperty('value') !== 'application/octet-stream') {
michael@0 43660 this._contentTypeHint = contentTypeHeader.asGetPublicProperty('value');
michael@0 43661 }
michael@0 43662 }.bind(this));
michael@0 43663 stream._addEventListener('progress', function (e) {
michael@0 43664 var available = stream.bytesAvailable;
michael@0 43665 var ByteArrayClass = avm2.systemDomain.getClass('flash.utils.ByteArray');
michael@0 43666 var data = ByteArrayClass.createInstance();
michael@0 43667 stream.readBytes(data, 0, available);
michael@0 43668 this.appendBytes(data);
michael@0 43669 }.bind(this));
michael@0 43670 stream._addEventListener('complete', function (e) {
michael@0 43671 this.appendBytesAction('endSequence');
michael@0 43672 }.bind(this));
michael@0 43673 stream.load(request);
michael@0 43674 },
michael@0 43675 play2: function play2(param) {
michael@0 43676 notImplemented('NetStream.play2');
michael@0 43677 },
michael@0 43678 invoke: function invoke(index) {
michael@0 43679 return this._invoke(index, Array.prototype.slice.call(arguments, 1));
michael@0 43680 },
michael@0 43681 invokeWithArgsArray: function invokeWithArgsArray(index, p_arguments) {
michael@0 43682 return this._invoke.call(this, index, p_arguments);
michael@0 43683 },
michael@0 43684 appendBytes: function appendBytes(bytes) {
michael@0 43685 if (this._mediaSource) {
michael@0 43686 if (!this._mediaSourceBuffer) {
michael@0 43687 this._mediaSourceBuffer = this._mediaSource.addSourceBuffer(this._contentTypeHint);
michael@0 43688 }
michael@0 43689 this._mediaSourceBuffer.appendBuffer(new Uint8Array(bytes.a, 0, bytes.length));
michael@0 43690 }
michael@0 43691 somewhatImplemented('NetStream.appendBytes');
michael@0 43692 },
michael@0 43693 appendBytesAction: function appendBytesAction(netStreamAppendBytesAction) {
michael@0 43694 if (netStreamAppendBytesAction === 'endSequence' && this._mediaSource) {
michael@0 43695 this._mediaSource.endOfStream();
michael@0 43696 }
michael@0 43697 somewhatImplemented('NetStream.appendBytesAction');
michael@0 43698 },
michael@0 43699 info: {
michael@0 43700 get: function info() {
michael@0 43701 notImplemented('NetStream.info');
michael@0 43702 return this._info;
michael@0 43703 }
michael@0 43704 },
michael@0 43705 multicastInfo: {
michael@0 43706 get: function multicastInfo() {
michael@0 43707 notImplemented('NetStream.multicastInfo');
michael@0 43708 return this._multicastInfo;
michael@0 43709 }
michael@0 43710 },
michael@0 43711 soundTransform: {
michael@0 43712 get: function soundTransform() {
michael@0 43713 return this._soundTransform;
michael@0 43714 },
michael@0 43715 set: function soundTransform(sndTransform) {
michael@0 43716 somewhatImplemented('NetStream.soundTransform');
michael@0 43717 this._soundTransform = sndTransform;
michael@0 43718 }
michael@0 43719 },
michael@0 43720 checkPolicyFile: {
michael@0 43721 get: function checkPolicyFile() {
michael@0 43722 return this._checkPolicyFile;
michael@0 43723 },
michael@0 43724 set: function checkPolicyFile(state) {
michael@0 43725 this._checkPolicyFile = state;
michael@0 43726 }
michael@0 43727 },
michael@0 43728 client: {
michael@0 43729 get: function client() {
michael@0 43730 somewhatImplemented('NetStream.client');
michael@0 43731 return this._client;
michael@0 43732 },
michael@0 43733 set: function client(object) {
michael@0 43734 somewhatImplemented('NetStream.client');
michael@0 43735 this._client = object;
michael@0 43736 }
michael@0 43737 },
michael@0 43738 objectEncoding: {
michael@0 43739 get: function objectEncoding() {
michael@0 43740 notImplemented('NetStream.objectEncoding');
michael@0 43741 return this._objectEncoding;
michael@0 43742 }
michael@0 43743 },
michael@0 43744 multicastPushNeighborLimit: {
michael@0 43745 get: function multicastPushNeighborLimit() {
michael@0 43746 notImplemented('NetStream.multicastPushNeighborLimit');
michael@0 43747 return this._multicastPushNeighborLimit;
michael@0 43748 },
michael@0 43749 set: function multicastPushNeighborLimit(neighbors) {
michael@0 43750 notImplemented('NetStream.multicastPushNeighborLimit');
michael@0 43751 this._multicastPushNeighborLimit = neighbors;
michael@0 43752 }
michael@0 43753 },
michael@0 43754 multicastWindowDuration: {
michael@0 43755 get: function multicastWindowDuration() {
michael@0 43756 notImplemented('NetStream.multicastWindowDuration');
michael@0 43757 return this._multicastWindowDuration;
michael@0 43758 },
michael@0 43759 set: function multicastWindowDuration(seconds) {
michael@0 43760 notImplemented('NetStream.multicastWindowDuration');
michael@0 43761 this._multicastWindowDuration = seconds;
michael@0 43762 }
michael@0 43763 },
michael@0 43764 multicastRelayMarginDuration: {
michael@0 43765 get: function multicastRelayMarginDuration() {
michael@0 43766 notImplemented('NetStream.multicastRelayMarginDuration');
michael@0 43767 return this._multicastRelayMarginDuration;
michael@0 43768 },
michael@0 43769 set: function multicastRelayMarginDuration(seconds) {
michael@0 43770 notImplemented('NetStream.multicastRelayMarginDuration');
michael@0 43771 this._multicastRelayMarginDuration = seconds;
michael@0 43772 }
michael@0 43773 },
michael@0 43774 multicastAvailabilityUpdatePeriod: {
michael@0 43775 get: function multicastAvailabilityUpdatePeriod() {
michael@0 43776 notImplemented('NetStream.multicastAvailabilityUpdatePeriod');
michael@0 43777 return this._multicastAvailabilityUpdatePeriod;
michael@0 43778 },
michael@0 43779 set: function multicastAvailabilityUpdatePeriod(seconds) {
michael@0 43780 notImplemented('NetStream.multicastAvailabilityUpdatePeriod');
michael@0 43781 this._multicastAvailabilityUpdatePeriod = seconds;
michael@0 43782 }
michael@0 43783 },
michael@0 43784 multicastFetchPeriod: {
michael@0 43785 get: function multicastFetchPeriod() {
michael@0 43786 notImplemented('NetStream.multicastFetchPeriod');
michael@0 43787 return this._multicastFetchPeriod;
michael@0 43788 },
michael@0 43789 set: function multicastFetchPeriod(seconds) {
michael@0 43790 notImplemented('NetStream.multicastFetchPeriod');
michael@0 43791 this._multicastFetchPeriod = seconds;
michael@0 43792 }
michael@0 43793 },
michael@0 43794 multicastAvailabilitySendToAll: {
michael@0 43795 get: function multicastAvailabilitySendToAll() {
michael@0 43796 notImplemented('NetStream.multicastAvailabilitySendToAll');
michael@0 43797 return this._multicastAvailabilitySendToAll;
michael@0 43798 },
michael@0 43799 set: function multicastAvailabilitySendToAll(value) {
michael@0 43800 notImplemented('NetStream.multicastAvailabilitySendToAll');
michael@0 43801 this._multicastAvailabilitySendToAll = value;
michael@0 43802 }
michael@0 43803 },
michael@0 43804 farID: {
michael@0 43805 get: function farID() {
michael@0 43806 notImplemented('NetStream.farID');
michael@0 43807 return this._farID;
michael@0 43808 }
michael@0 43809 },
michael@0 43810 nearNonce: {
michael@0 43811 get: function nearNonce() {
michael@0 43812 notImplemented('NetStream.nearNonce');
michael@0 43813 return this._nearNonce;
michael@0 43814 }
michael@0 43815 },
michael@0 43816 farNonce: {
michael@0 43817 get: function farNonce() {
michael@0 43818 notImplemented('NetStream.farNonce');
michael@0 43819 return this._farNonce;
michael@0 43820 }
michael@0 43821 },
michael@0 43822 peerStreams: {
michael@0 43823 get: function peerStreams() {
michael@0 43824 notImplemented('NetStream.peerStreams');
michael@0 43825 return this._peerStreams;
michael@0 43826 }
michael@0 43827 },
michael@0 43828 audioReliable: {
michael@0 43829 get: function audioReliable() {
michael@0 43830 notImplemented('NetStream.audioReliable');
michael@0 43831 return this._audioReliable;
michael@0 43832 },
michael@0 43833 set: function audioReliable(reliable) {
michael@0 43834 notImplemented('NetStream.audioReliable');
michael@0 43835 this._audioReliable = reliable;
michael@0 43836 }
michael@0 43837 },
michael@0 43838 videoReliable: {
michael@0 43839 get: function videoReliable() {
michael@0 43840 notImplemented('NetStream.videoReliable');
michael@0 43841 return this._videoReliable;
michael@0 43842 },
michael@0 43843 set: function videoReliable(reliable) {
michael@0 43844 notImplemented('NetStream.videoReliable');
michael@0 43845 this._videoReliable = reliable;
michael@0 43846 }
michael@0 43847 },
michael@0 43848 dataReliable: {
michael@0 43849 get: function dataReliable() {
michael@0 43850 notImplemented('NetStream.dataReliable');
michael@0 43851 return this._dataReliable;
michael@0 43852 },
michael@0 43853 set: function dataReliable(reliable) {
michael@0 43854 notImplemented('NetStream.dataReliable');
michael@0 43855 this._dataReliable = reliable;
michael@0 43856 }
michael@0 43857 },
michael@0 43858 audioSampleAccess: {
michael@0 43859 get: function audioSampleAccess() {
michael@0 43860 notImplemented('NetStream.audioSampleAccess');
michael@0 43861 return this._audioSampleAccess;
michael@0 43862 },
michael@0 43863 set: function audioSampleAccess(reliable) {
michael@0 43864 notImplemented('NetStream.audioSampleAccess');
michael@0 43865 this._audioSampleAccess = reliable;
michael@0 43866 }
michael@0 43867 },
michael@0 43868 videoSampleAccess: {
michael@0 43869 get: function videoSampleAccess() {
michael@0 43870 notImplemented('NetStream.videoSampleAccess');
michael@0 43871 return this._videoSampleAccess;
michael@0 43872 },
michael@0 43873 set: function videoSampleAccess(reliable) {
michael@0 43874 notImplemented('NetStream.videoSampleAccess');
michael@0 43875 this._videoSampleAccess = reliable;
michael@0 43876 }
michael@0 43877 },
michael@0 43878 useHardwareDecoder: {
michael@0 43879 get: function useHardwareDecoder() {
michael@0 43880 notImplemented('NetStream.useHardwareDecoder');
michael@0 43881 return this._useHardwareDecoder;
michael@0 43882 },
michael@0 43883 set: function useHardwareDecoder(v) {
michael@0 43884 notImplemented('NetStream.useHardwareDecoder');
michael@0 43885 this._useHardwareDecoder = v;
michael@0 43886 }
michael@0 43887 },
michael@0 43888 useJitterBuffer: {
michael@0 43889 get: function useJitterBuffer() {
michael@0 43890 notImplemented('NetStream.useJitterBuffer');
michael@0 43891 return this._useJitterBuffer;
michael@0 43892 },
michael@0 43893 set: function useJitterBuffer(value) {
michael@0 43894 notImplemented('NetStream.useJitterBuffer');
michael@0 43895 this._useJitterBuffer = value;
michael@0 43896 }
michael@0 43897 },
michael@0 43898 videoStreamSettings: {
michael@0 43899 get: function videoStreamSettings() {
michael@0 43900 notImplemented('NetStream.videoStreamSettings');
michael@0 43901 return this._videoStreamSettings;
michael@0 43902 },
michael@0 43903 set: function videoStreamSettings(settings) {
michael@0 43904 notImplemented('NetStream.videoStreamSettings');
michael@0 43905 this._videoStreamSettings = settings;
michael@0 43906 }
michael@0 43907 }
michael@0 43908 }
michael@0 43909 }
michael@0 43910 }
michael@0 43911 };
michael@0 43912 }.call(this);
michael@0 43913 var ObjectEncodingDefinition = function () {
michael@0 43914 return {
michael@0 43915 __class__: 'flash.net.ObjectEncoding',
michael@0 43916 initialize: function () {
michael@0 43917 },
michael@0 43918 __glue__: {
michael@0 43919 native: {
michael@0 43920 static: {
michael@0 43921 dynamicPropertyWriter: {
michael@0 43922 get: function dynamicPropertyWriter() {
michael@0 43923 notImplemented('ObjectEncoding.dynamicPropertyWriter');
michael@0 43924 },
michael@0 43925 set: function dynamicPropertyWriter(object) {
michael@0 43926 notImplemented('ObjectEncoding.dynamicPropertyWriter');
michael@0 43927 }
michael@0 43928 }
michael@0 43929 },
michael@0 43930 instance: {}
michael@0 43931 }
michael@0 43932 }
michael@0 43933 };
michael@0 43934 }.call(this);
michael@0 43935 var ResponderDefinition = function () {
michael@0 43936 var def = {
michael@0 43937 ctor: function (result, status) {
michael@0 43938 }
michael@0 43939 };
michael@0 43940 def.__glue__ = {
michael@0 43941 native: {
michael@0 43942 instance: {
michael@0 43943 ctor: def.ctor
michael@0 43944 }
michael@0 43945 }
michael@0 43946 };
michael@0 43947 return def;
michael@0 43948 }.call(this);
michael@0 43949 var SharedObjectDefinition = function () {
michael@0 43950 var _defaultObjectEncoding = 3;
michael@0 43951 var sharedObjects = createEmptyObject();
michael@0 43952 function invokeWithArgsArray(index, args) {
michael@0 43953 var simulated = false, result;
michael@0 43954 switch (index) {
michael@0 43955 case 4:
michael@0 43956 result = JSON.stringify(this._data).length - 2;
michael@0 43957 simulated = true;
michael@0 43958 break;
michael@0 43959 case 6:
michael@0 43960 this._data = {};
michael@0 43961 sessionStorage.removeItem(this._path);
michael@0 43962 simulated = true;
michael@0 43963 break;
michael@0 43964 case 2:
michael@0 43965 sessionStorage.setItem(this._path, JSON.stringify(this._data));
michael@0 43966 simulated = true;
michael@0 43967 result = true;
michael@0 43968 break;
michael@0 43969 case 3:
michael@0 43970 simulated = true;
michael@0 43971 break;
michael@0 43972 }
michael@0 43973 (simulated ? somewhatImplemented : notImplemented)('SharedObject.invoke (' + index + ')');
michael@0 43974 return result;
michael@0 43975 }
michael@0 43976 return {
michael@0 43977 __class__: 'flash.net.SharedObject',
michael@0 43978 initialize: function () {
michael@0 43979 this._path = null;
michael@0 43980 this._data = null;
michael@0 43981 this._objectEncoding = _defaultObjectEncoding;
michael@0 43982 TelemetryService.reportTelemetry({
michael@0 43983 topic: 'feature',
michael@0 43984 feature: SHAREDOBJECT_FEATURE
michael@0 43985 });
michael@0 43986 },
michael@0 43987 __glue__: {
michael@0 43988 native: {
michael@0 43989 static: {
michael@0 43990 deleteAll: function deleteAll(url) {
michael@0 43991 notImplemented('SharedObject.deleteAll');
michael@0 43992 },
michael@0 43993 getDiskUsage: function getDiskUsage(url) {
michael@0 43994 notImplemented('SharedObject.getDiskUsage');
michael@0 43995 },
michael@0 43996 getLocal: function getLocal(name, localPath, secure) {
michael@0 43997 var path = (localPath || '') + '/' + name;
michael@0 43998 if (sharedObjects[path]) {
michael@0 43999 return sharedObjects[path];
michael@0 44000 }
michael@0 44001 var so = new flash.net.SharedObject();
michael@0 44002 so._path = path;
michael@0 44003 var data = sessionStorage.getItem(path);
michael@0 44004 so._data = data ? JSON.parse(data) : {};
michael@0 44005 return so;
michael@0 44006 },
michael@0 44007 getRemote: function getRemote(name, remotePath, persistence, secure) {
michael@0 44008 notImplemented('SharedObject.getRemote');
michael@0 44009 },
michael@0 44010 defaultObjectEncoding: {
michael@0 44011 get: function defaultObjectEncoding() {
michael@0 44012 return _defaultObjectEncoding;
michael@0 44013 },
michael@0 44014 set: function defaultObjectEncoding(version) {
michael@0 44015 _defaultObjectEncoding = version;
michael@0 44016 }
michael@0 44017 }
michael@0 44018 },
michael@0 44019 instance: {
michael@0 44020 setDirty: function setDirty(propertyName) {
michael@0 44021 somewhatImplemented('SharedObject.setDirty');
michael@0 44022 },
michael@0 44023 invoke: function invoke(index) {
michael@0 44024 return invokeWithArgsArray.call(this, index, Array.prototype.slice.call(arguments, 1));
michael@0 44025 },
michael@0 44026 invokeWithArgsArray: function invokeWithArgsArray(index, args) {
michael@0 44027 return invokeWithArgsArray.call(this, index, args);
michael@0 44028 },
michael@0 44029 data: {
michael@0 44030 get: function data() {
michael@0 44031 return this._data;
michael@0 44032 }
michael@0 44033 },
michael@0 44034 objectEncoding: {
michael@0 44035 get: function objectEncoding() {
michael@0 44036 return this._objectEncoding;
michael@0 44037 },
michael@0 44038 set: function objectEncoding(version) {
michael@0 44039 this._objectEncoding = version;
michael@0 44040 }
michael@0 44041 },
michael@0 44042 client: {
michael@0 44043 get: function client() {
michael@0 44044 notImplemented('SharedObject.client');
michael@0 44045 return this._client;
michael@0 44046 },
michael@0 44047 set: function client(object) {
michael@0 44048 notImplemented('SharedObject.client');
michael@0 44049 this._client = object;
michael@0 44050 }
michael@0 44051 }
michael@0 44052 }
michael@0 44053 }
michael@0 44054 }
michael@0 44055 };
michael@0 44056 }.call(this);
michael@0 44057 var SocketDefinition = function () {
michael@0 44058 return {
michael@0 44059 __class__: 'flash.net.Socket',
michael@0 44060 initialize: function () {
michael@0 44061 this._connected = false;
michael@0 44062 },
michael@0 44063 __glue__: {
michael@0 44064 native: {
michael@0 44065 static: {},
michael@0 44066 instance: {
michael@0 44067 internalGetSecurityErrorMessage: function internalGetSecurityErrorMessage(host, port) {
michael@0 44068 somewhatImplemented('Socket.internalGetSecurityErrorMessage');
michael@0 44069 return 'SecurityErrorEvent';
michael@0 44070 },
michael@0 44071 internalConnect: function internalConnect(host, port) {
michael@0 44072 somewhatImplemented('Socket.internalConnect');
michael@0 44073 throwError('SecurityError', Errors.SocketConnectError, host, port);
michael@0 44074 },
michael@0 44075 didFailureOccur: function didFailureOccur() {
michael@0 44076 somewhatImplemented('Socket.didFailureOccur');
michael@0 44077 return true;
michael@0 44078 },
michael@0 44079 readBytes: function readBytes(bytes, offset, length) {
michael@0 44080 notImplemented('Socket.readBytes');
michael@0 44081 },
michael@0 44082 writeBytes: function writeBytes(bytes, offset, length) {
michael@0 44083 notImplemented('Socket.writeBytes');
michael@0 44084 },
michael@0 44085 writeBoolean: function writeBoolean(value) {
michael@0 44086 notImplemented('Socket.writeBoolean');
michael@0 44087 },
michael@0 44088 writeByte: function writeByte(value) {
michael@0 44089 notImplemented('Socket.writeByte');
michael@0 44090 },
michael@0 44091 writeShort: function writeShort(value) {
michael@0 44092 notImplemented('Socket.writeShort');
michael@0 44093 },
michael@0 44094 writeInt: function writeInt(value) {
michael@0 44095 notImplemented('Socket.writeInt');
michael@0 44096 },
michael@0 44097 writeUnsignedInt: function writeUnsignedInt(value) {
michael@0 44098 notImplemented('Socket.writeUnsignedInt');
michael@0 44099 },
michael@0 44100 writeFloat: function writeFloat(value) {
michael@0 44101 notImplemented('Socket.writeFloat');
michael@0 44102 },
michael@0 44103 writeDouble: function writeDouble(value) {
michael@0 44104 notImplemented('Socket.writeDouble');
michael@0 44105 },
michael@0 44106 writeMultiByte: function writeMultiByte(value, charSet) {
michael@0 44107 notImplemented('Socket.writeMultiByte');
michael@0 44108 },
michael@0 44109 writeUTF: function writeUTF(value) {
michael@0 44110 notImplemented('Socket.writeUTF');
michael@0 44111 },
michael@0 44112 writeUTFBytes: function writeUTFBytes(value) {
michael@0 44113 notImplemented('Socket.writeUTFBytes');
michael@0 44114 },
michael@0 44115 readBoolean: function readBoolean() {
michael@0 44116 notImplemented('Socket.readBoolean');
michael@0 44117 },
michael@0 44118 readByte: function readByte() {
michael@0 44119 notImplemented('Socket.readByte');
michael@0 44120 },
michael@0 44121 readUnsignedByte: function readUnsignedByte() {
michael@0 44122 notImplemented('Socket.readUnsignedByte');
michael@0 44123 },
michael@0 44124 readShort: function readShort() {
michael@0 44125 notImplemented('Socket.readShort');
michael@0 44126 },
michael@0 44127 readUnsignedShort: function readUnsignedShort() {
michael@0 44128 notImplemented('Socket.readUnsignedShort');
michael@0 44129 },
michael@0 44130 readInt: function readInt() {
michael@0 44131 notImplemented('Socket.readInt');
michael@0 44132 },
michael@0 44133 readUnsignedInt: function readUnsignedInt() {
michael@0 44134 notImplemented('Socket.readUnsignedInt');
michael@0 44135 },
michael@0 44136 readFloat: function readFloat() {
michael@0 44137 notImplemented('Socket.readFloat');
michael@0 44138 },
michael@0 44139 readDouble: function readDouble() {
michael@0 44140 notImplemented('Socket.readDouble');
michael@0 44141 },
michael@0 44142 readMultiByte: function readMultiByte(length, charSet) {
michael@0 44143 notImplemented('Socket.readMultiByte');
michael@0 44144 },
michael@0 44145 readUTF: function readUTF() {
michael@0 44146 notImplemented('Socket.readUTF');
michael@0 44147 },
michael@0 44148 readUTFBytes: function readUTFBytes(length) {
michael@0 44149 notImplemented('Socket.readUTFBytes');
michael@0 44150 },
michael@0 44151 internalClose: function internalClose() {
michael@0 44152 notImplemented('Socket.internalClose');
michael@0 44153 },
michael@0 44154 flush: function flush() {
michael@0 44155 notImplemented('Socket.flush');
michael@0 44156 },
michael@0 44157 writeObject: function writeObject(object) {
michael@0 44158 notImplemented('Socket.writeObject');
michael@0 44159 },
michael@0 44160 readObject: function readObject() {
michael@0 44161 notImplemented('Socket.readObject');
michael@0 44162 },
michael@0 44163 bytesAvailable: {
michael@0 44164 get: function bytesAvailable() {
michael@0 44165 notImplemented('Socket.bytesAvailable');
michael@0 44166 return this._bytesAvailable;
michael@0 44167 }
michael@0 44168 },
michael@0 44169 connected: {
michael@0 44170 get: function connected() {
michael@0 44171 somewhatImplemented('Socket.connected');
michael@0 44172 return this._connected;
michael@0 44173 }
michael@0 44174 },
michael@0 44175 objectEncoding: {
michael@0 44176 get: function objectEncoding() {
michael@0 44177 notImplemented('Socket.objectEncoding');
michael@0 44178 return this._objectEncoding;
michael@0 44179 },
michael@0 44180 set: function objectEncoding(version) {
michael@0 44181 notImplemented('Socket.objectEncoding');
michael@0 44182 this._objectEncoding = version;
michael@0 44183 }
michael@0 44184 },
michael@0 44185 endian: {
michael@0 44186 get: function endian() {
michael@0 44187 notImplemented('Socket.endian');
michael@0 44188 return this._endian;
michael@0 44189 },
michael@0 44190 set: function endian(type) {
michael@0 44191 notImplemented('Socket.endian');
michael@0 44192 this._endian = type;
michael@0 44193 }
michael@0 44194 },
michael@0 44195 bytesPending: {
michael@0 44196 get: function bytesPending() {
michael@0 44197 notImplemented('Socket.bytesPending');
michael@0 44198 return this._bytesPending;
michael@0 44199 }
michael@0 44200 }
michael@0 44201 }
michael@0 44202 },
michael@0 44203 script: {
michael@0 44204 instance: Glue.ALL
michael@0 44205 }
michael@0 44206 }
michael@0 44207 };
michael@0 44208 }.call(this);
michael@0 44209 var URLLoaderDefinition = function () {
michael@0 44210 return {
michael@0 44211 initialize: function () {
michael@0 44212 },
michael@0 44213 __glue__: {
michael@0 44214 native: {
michael@0 44215 static: {},
michael@0 44216 instance: {}
michael@0 44217 },
michael@0 44218 script: {
michael@0 44219 static: {},
michael@0 44220 instance: {
michael@0 44221 data: 'public data',
michael@0 44222 dataFormat: 'public dataFormat',
michael@0 44223 bytesTotal: 'public bytesTotal',
michael@0 44224 bytesLoaded: 'public bytesLoaded',
michael@0 44225 load: 'public load'
michael@0 44226 }
michael@0 44227 }
michael@0 44228 }
michael@0 44229 };
michael@0 44230 }.call(this);
michael@0 44231 var URLRequestDefinition = function () {
michael@0 44232 function toFileLoadingServiceRequest() {
michael@0 44233 var obj = {};
michael@0 44234 obj.url = this._url;
michael@0 44235 obj.method = this._method;
michael@0 44236 obj.checkPolicyFile = this._checkPolicyFile;
michael@0 44237 if (this._data) {
michael@0 44238 obj.mimeType = this._contentType;
michael@0 44239 var ByteArrayClass = avm2.systemDomain.getClass('flash.utils.ByteArray');
michael@0 44240 if (ByteArrayClass.isInstanceOf(this._data)) {
michael@0 44241 obj.data = new Uint8Array(this._data.a, 0, this._data.length);
michael@0 44242 } else {
michael@0 44243 var data = this._data.asGetPublicProperty('toString').call(this._data);
michael@0 44244 if (this._method === 'GET') {
michael@0 44245 var i = obj.url.lastIndexOf('?');
michael@0 44246 obj.url = (i < 0 ? obj.url : obj.url.substring(0, i)) + '?' + data;
michael@0 44247 } else {
michael@0 44248 obj.data = data;
michael@0 44249 }
michael@0 44250 }
michael@0 44251 }
michael@0 44252 return obj;
michael@0 44253 }
michael@0 44254 var def = {
michael@0 44255 initialize: function () {
michael@0 44256 this._url = null;
michael@0 44257 this._method = 'GET';
michael@0 44258 this._data = null;
michael@0 44259 this._digest = null;
michael@0 44260 this._contentType = 'application/x-www-form-urlencoded';
michael@0 44261 this._requestHeaders = null;
michael@0 44262 this._checkPolicyFile = true;
michael@0 44263 this._toFileRequest = toFileLoadingServiceRequest;
michael@0 44264 },
michael@0 44265 setMethod: function (val) {
michael@0 44266 this._method = val;
michael@0 44267 },
michael@0 44268 setRequestHeaders: function (val) {
michael@0 44269 this._requestHeaders = val;
michael@0 44270 },
michael@0 44271 get contentType() {
michael@0 44272 return this._contentType;
michael@0 44273 },
michael@0 44274 set contentType(val) {
michael@0 44275 this._contentType = val;
michael@0 44276 },
michael@0 44277 get data() {
michael@0 44278 return this._data;
michael@0 44279 },
michael@0 44280 set data(val) {
michael@0 44281 this._data = val;
michael@0 44282 },
michael@0 44283 get digest() {
michael@0 44284 return this._digest;
michael@0 44285 },
michael@0 44286 set digest(val) {
michael@0 44287 this._digest = val;
michael@0 44288 },
michael@0 44289 get method() {
michael@0 44290 return this._method;
michael@0 44291 },
michael@0 44292 set method(method) {
michael@0 44293 this._method = method;
michael@0 44294 },
michael@0 44295 get requestHeaders() {
michael@0 44296 return this._requestHeaders;
michael@0 44297 },
michael@0 44298 set requestHeaders(requestHeaders) {
michael@0 44299 this._requestHeaders = requestHeaders;
michael@0 44300 },
michael@0 44301 get url() {
michael@0 44302 return this._url;
michael@0 44303 },
michael@0 44304 set url(val) {
michael@0 44305 this._url = val;
michael@0 44306 }
michael@0 44307 };
michael@0 44308 var desc = Object.getOwnPropertyDescriptor;
michael@0 44309 def.__glue__ = {
michael@0 44310 native: {
michael@0 44311 instance: {
michael@0 44312 setMethod: def.setMethod,
michael@0 44313 setRequestHeaders: def.setRequestHeaders,
michael@0 44314 contentType: desc(def, 'contentType'),
michael@0 44315 data: desc(def, 'data'),
michael@0 44316 digest: desc(def, 'digest'),
michael@0 44317 method: desc(def, 'method'),
michael@0 44318 requestHeaders: desc(def, 'requestHeaders'),
michael@0 44319 url: desc(def, 'url')
michael@0 44320 }
michael@0 44321 }
michael@0 44322 };
michael@0 44323 return def;
michael@0 44324 }.call(this);
michael@0 44325 var URLStreamDefinition = function () {
michael@0 44326 var def = {
michael@0 44327 initialize: function () {
michael@0 44328 this._stream = null;
michael@0 44329 this._connected = false;
michael@0 44330 this._littleEndian = false;
michael@0 44331 },
michael@0 44332 close: function close() {
michael@0 44333 this._session.close();
michael@0 44334 },
michael@0 44335 load: function load(request) {
michael@0 44336 var session = FileLoadingService.createSession();
michael@0 44337 var self = this;
michael@0 44338 var initStream = true;
michael@0 44339 session.onprogress = function (data, progressState) {
michael@0 44340 if (initStream) {
michael@0 44341 initStream = false;
michael@0 44342 var length = Math.max(progressState.bytesTotal, data.length);
michael@0 44343 var buffer = new ArrayBuffer(length);
michael@0 44344 self._stream = new Stream(buffer, 0, 0, length);
michael@0 44345 } else if (self._stream.end + data.length > self._stream.bytes.length) {
michael@0 44346 var length = self._stream.end + data.length;
michael@0 44347 var buffer = new ArrayBuffer(length);
michael@0 44348 var newStream = new Stream(buffer, 0, 0, length);
michael@0 44349 newStream.push(self._stream.bytes.subarray(0, self._stream.end));
michael@0 44350 self._stream = newStream;
michael@0 44351 }
michael@0 44352 self._stream.push(data);
michael@0 44353 var ProgressEventClass = avm2.systemDomain.getClass('flash.events.ProgressEvent');
michael@0 44354 self._dispatchEvent(ProgressEventClass.createInstance([
michael@0 44355 'progress',
michael@0 44356 false,
michael@0 44357 false,
michael@0 44358 progressState.bytesLoaded,
michael@0 44359 progressState.bytesTotal
michael@0 44360 ]));
michael@0 44361 };
michael@0 44362 session.onerror = function (error) {
michael@0 44363 self._connected = false;
michael@0 44364 if (!self._stream) {
michael@0 44365 self._stream = new Stream(new ArrayBuffer(0), 0, 0, 0);
michael@0 44366 }
michael@0 44367 self._dispatchEvent(new flash.events.IOErrorEvent(flash.events.IOErrorEvent.class.IO_ERROR, false, false, error));
michael@0 44368 };
michael@0 44369 session.onopen = function () {
michael@0 44370 self._connected = true;
michael@0 44371 self._dispatchEvent(new flash.events.Event('open', false, false));
michael@0 44372 };
michael@0 44373 session.onhttpstatus = function (location, httpStatus, httpHeaders) {
michael@0 44374 var HTTPStatusEventClass = avm2.systemDomain.getClass('flash.events.HTTPStatusEvent');
michael@0 44375 var URLRequestHeaderClass = avm2.systemDomain.getClass('flash.net.URLRequestHeader');
michael@0 44376 var httpStatusEvent = HTTPStatusEventClass.createInstance([
michael@0 44377 'httpStatus',
michael@0 44378 false,
michael@0 44379 false,
michael@0 44380 httpStatus
michael@0 44381 ]);
michael@0 44382 var headers = [];
michael@0 44383 httpHeaders.split(/(?:\n|\r?\n)/g).forEach(function (h) {
michael@0 44384 var m = /^([^:]+): (.*)$/.exec(h);
michael@0 44385 if (m) {
michael@0 44386 headers.push(URLRequestHeaderClass.createInstance([
michael@0 44387 m[1],
michael@0 44388 m[2]
michael@0 44389 ]));
michael@0 44390 if (m[1] === 'Location') {
michael@0 44391 location = m[2];
michael@0 44392 }
michael@0 44393 }
michael@0 44394 });
michael@0 44395 httpStatusEvent.asSetPublicProperty('responseHeaders', headers);
michael@0 44396 httpStatusEvent.asSetPublicProperty('responseURL', location);
michael@0 44397 self._dispatchEvent(httpStatusEvent);
michael@0 44398 };
michael@0 44399 session.onclose = function () {
michael@0 44400 self._connected = false;
michael@0 44401 if (!self._stream) {
michael@0 44402 self._stream = new Stream(new ArrayBuffer(0), 0, 0, 0);
michael@0 44403 }
michael@0 44404 self._dispatchEvent(new flash.events.Event('complete', false, false));
michael@0 44405 };
michael@0 44406 session.open(request._toFileRequest());
michael@0 44407 this._session = session;
michael@0 44408 },
michael@0 44409 readBoolean: function readBoolean() {
michael@0 44410 notImplemented('URLStream.readBoolean');
michael@0 44411 },
michael@0 44412 readByte: function readByte() {
michael@0 44413 var stream = this._stream;
michael@0 44414 stream.ensure(1);
michael@0 44415 return stream.bytes[stream.pos++];
michael@0 44416 },
michael@0 44417 readBytes: function readBytes(bytes, offset, length) {
michael@0 44418 if (length < 0)
michael@0 44419 throw 'Invalid length argument';
michael@0 44420 var stream = this._stream;
michael@0 44421 if (!length)
michael@0 44422 length = stream.remaining();
michael@0 44423 else
michael@0 44424 stream.ensure(length);
michael@0 44425 bytes.writeRawBytes(stream.bytes.subarray(stream.pos, stream.pos + length), offset, length);
michael@0 44426 stream.pos += length;
michael@0 44427 },
michael@0 44428 readDouble: function readDouble() {
michael@0 44429 notImplemented('URLStream.readDouble');
michael@0 44430 },
michael@0 44431 readFloat: function readFloat() {
michael@0 44432 notImplemented('URLStream.readFloat');
michael@0 44433 },
michael@0 44434 readInt: function readInt() {
michael@0 44435 notImplemented('URLStream.readInt');
michael@0 44436 },
michael@0 44437 readMultiByte: function readMultiByte(length, charSet) {
michael@0 44438 notImplemented('URLStream.readMultiByte');
michael@0 44439 },
michael@0 44440 readObject: function readObject() {
michael@0 44441 notImplemented('URLStream.readObject');
michael@0 44442 },
michael@0 44443 readShort: function readShort() {
michael@0 44444 notImplemented('URLStream.readShort');
michael@0 44445 },
michael@0 44446 readUTF: function readUTF() {
michael@0 44447 return this.readUTFBytes(this.readUnsignedShort());
michael@0 44448 },
michael@0 44449 readUTFBytes: function readUTFBytes(length) {
michael@0 44450 if (length < 0)
michael@0 44451 throw 'Invalid length argument';
michael@0 44452 var stream = this._stream;
michael@0 44453 stream.ensure(length);
michael@0 44454 var str = utf8encode(stream.bytes.subarray(stream.pos, stream.pos + length));
michael@0 44455 stream.pos += length;
michael@0 44456 return str;
michael@0 44457 },
michael@0 44458 readUnsignedByte: function readUnsignedByte() {
michael@0 44459 notImplemented('URLStream.readUnsignedByte');
michael@0 44460 },
michael@0 44461 readUnsignedInt: function readUnsignedInt() {
michael@0 44462 notImplemented('URLStream.readUnsignedInt');
michael@0 44463 },
michael@0 44464 readUnsignedShort: function readUnsignedShort() {
michael@0 44465 var stream = this._stream;
michael@0 44466 stream.ensure(2);
michael@0 44467 var result = stream.getUint16(stream.pos, this._littleEndian);
michael@0 44468 stream.pos += 2;
michael@0 44469 return result;
michael@0 44470 },
michael@0 44471 get bytesAvailable() {
michael@0 44472 return this._stream.remaining();
michael@0 44473 },
michael@0 44474 get connected() {
michael@0 44475 return this._connected;
michael@0 44476 },
michael@0 44477 get endian() {
michael@0 44478 return this._littleEndian ? 'littleEndian' : 'bigEndian';
michael@0 44479 },
michael@0 44480 set endian(val) {
michael@0 44481 this._littleEndian = val == 'littleEndian';
michael@0 44482 },
michael@0 44483 get objectEncoding() {
michael@0 44484 notImplemented('URLStream.objectEncoding');
michael@0 44485 },
michael@0 44486 set objectEncoding(val) {
michael@0 44487 notImplemented('URLStream.objectEncoding');
michael@0 44488 }
michael@0 44489 };
michael@0 44490 var desc = Object.getOwnPropertyDescriptor;
michael@0 44491 def.__glue__ = {
michael@0 44492 native: {
michael@0 44493 instance: {
michael@0 44494 close: def.close,
michael@0 44495 load: def.load,
michael@0 44496 readBoolean: def.readBoolean,
michael@0 44497 readByte: def.readByte,
michael@0 44498 readBytes: def.readBytes,
michael@0 44499 readDouble: def.readDouble,
michael@0 44500 readFloat: def.readFloat,
michael@0 44501 readInt: def.readInt,
michael@0 44502 readMultiByte: def.readMultiByte,
michael@0 44503 readObject: def.readObject,
michael@0 44504 readShort: def.readShort,
michael@0 44505 readUTF: def.readUTF,
michael@0 44506 readUTFBytes: def.readUTFBytes,
michael@0 44507 readUnsignedByte: def.readUnsignedByte,
michael@0 44508 readUnsignedInt: def.readUnsignedInt,
michael@0 44509 readUnsignedShort: def.readUnsignedShort,
michael@0 44510 bytesAvailable: desc(def, 'bytesAvailable'),
michael@0 44511 connected: desc(def, 'connected'),
michael@0 44512 endian: desc(def, 'endian'),
michael@0 44513 objectEncoding: desc(def, 'objectEncoding')
michael@0 44514 }
michael@0 44515 }
michael@0 44516 };
michael@0 44517 return def;
michael@0 44518 }.call(this);
michael@0 44519 {
michael@0 44520 var ApplicationDomainDefinition = function () {
michael@0 44521 return {
michael@0 44522 __class__: 'flash.system.ApplicationDomain',
michael@0 44523 initialize: function () {
michael@0 44524 },
michael@0 44525 __glue__: {
michael@0 44526 native: {
michael@0 44527 static: {
michael@0 44528 currentDomain: {
michael@0 44529 get: function currentDomain() {
michael@0 44530 return new flash.system.ApplicationDomain(AVM2.currentDomain());
michael@0 44531 }
michael@0 44532 },
michael@0 44533 MIN_DOMAIN_MEMORY_LENGTH: {
michael@0 44534 get: function MIN_DOMAIN_MEMORY_LENGTH() {
michael@0 44535 notImplemented('ApplicationDomain.MIN_DOMAIN_MEMORY_LENGTH');
michael@0 44536 }
michael@0 44537 }
michael@0 44538 },
michael@0 44539 instance: {
michael@0 44540 ctor: function ctor(parentDomainOrNativeObject) {
michael@0 44541 if (parentDomainOrNativeObject instanceof ApplicationDomain) {
michael@0 44542 this.nativeObject = parentDomainOrNativeObject;
michael@0 44543 return;
michael@0 44544 }
michael@0 44545 var parentNativeObject = parentDomainOrNativeObject ? parentDomainOrNativeObject.nativeObject : AVM2.currentDomain().system;
michael@0 44546 this.nativeObject = new ApplicationDomain(parentNativeObject.vm, parentNativeObject);
michael@0 44547 },
michael@0 44548 getDefinition: function getDefinition(name) {
michael@0 44549 var simpleName = name.replace('::', '.');
michael@0 44550 return this.nativeObject.getProperty(Multiname.fromSimpleName(simpleName), true, true);
michael@0 44551 },
michael@0 44552 hasDefinition: function hasDefinition(name) {
michael@0 44553 if (name === undefined) {
michael@0 44554 return false;
michael@0 44555 }
michael@0 44556 var simpleName = name.replace('::', '.');
michael@0 44557 return !(!this.nativeObject.findDomainProperty(Multiname.fromSimpleName(simpleName), false, false));
michael@0 44558 },
michael@0 44559 getQualifiedDefinitionNames: function getQualifiedDefinitionNames() {
michael@0 44560 notImplemented('ApplicationDomain.getQualifiedDefinitionNames');
michael@0 44561 },
michael@0 44562 parentDomain: {
michael@0 44563 get: function parentDomain() {
michael@0 44564 var base = this.nativeObject.base;
michael@0 44565 if (!base) {
michael@0 44566 return undefined;
michael@0 44567 }
michael@0 44568 return new flash.system.ApplicationDomain(base);
michael@0 44569 }
michael@0 44570 },
michael@0 44571 domainMemory: {
michael@0 44572 get: function domainMemory() {
michael@0 44573 notImplemented('ApplicationDomain.domainMemory');
michael@0 44574 return this._domainMemory;
michael@0 44575 },
michael@0 44576 set: function domainMemory(mem) {
michael@0 44577 notImplemented('ApplicationDomain.domainMemory');
michael@0 44578 this._domainMemory = mem;
michael@0 44579 }
michael@0 44580 }
michael@0 44581 }
michael@0 44582 },
michael@0 44583 script: {
michael@0 44584 static: Glue.ALL,
michael@0 44585 instance: Glue.ALL
michael@0 44586 }
michael@0 44587 }
michael@0 44588 };
michael@0 44589 }.call(this);
michael@0 44590 }
michael@0 44591 var CapabilitiesDefinition = function () {
michael@0 44592 var def = {};
michael@0 44593 var os;
michael@0 44594 var userAgent = window.navigator.userAgent;
michael@0 44595 if (userAgent.indexOf('Macintosh') > 0) {
michael@0 44596 os = 'Mac OS 10.5.2';
michael@0 44597 } else if (userAgent.indexOf('Windows') > 0) {
michael@0 44598 os = 'Windows XP';
michael@0 44599 } else if (userAgent.indexOf('Linux') > 0) {
michael@0 44600 os = 'Linux';
michael@0 44601 } else if (/(iPad|iPhone|iPod|Android)/.test(userAgent)) {
michael@0 44602 os = 'iPhone3,1';
michael@0 44603 } else {
michael@0 44604 notImplemented();
michael@0 44605 }
michael@0 44606 def.__glue__ = {
michael@0 44607 native: {
michael@0 44608 static: {
michael@0 44609 version: {
michael@0 44610 get: function version() {
michael@0 44611 return 'SHUMWAY 10,0,0,0';
michael@0 44612 },
michael@0 44613 enumerable: true
michael@0 44614 },
michael@0 44615 os: {
michael@0 44616 get: function () {
michael@0 44617 return os;
michael@0 44618 },
michael@0 44619 enumerable: true
michael@0 44620 },
michael@0 44621 serverString: {
michael@0 44622 get: function () {
michael@0 44623 var str = toKeyValueArray({
michael@0 44624 OS: os
michael@0 44625 }).map(function (pair) {
michael@0 44626 return pair[0] + '=' + encodeURIComponent(pair[1]);
michael@0 44627 }).join('&');
michael@0 44628 somewhatImplemented('Capabilities.serverString: ' + str);
michael@0 44629 return str;
michael@0 44630 }
michael@0 44631 },
michael@0 44632 hasAccessibility: {
michael@0 44633 get: function hasAccessibility() {
michael@0 44634 somewhatImplemented('Capabilities.hasAccessibility');
michael@0 44635 return false;
michael@0 44636 }
michael@0 44637 },
michael@0 44638 isDebugger: {
michael@0 44639 get: function isDebugger() {
michael@0 44640 return false;
michael@0 44641 }
michael@0 44642 },
michael@0 44643 screenResolutionX: {
michael@0 44644 get: function screenResolutionX() {
michael@0 44645 return window.screen.width;
michael@0 44646 }
michael@0 44647 },
michael@0 44648 screenResolutionY: {
michael@0 44649 get: function screenResolutionY() {
michael@0 44650 return window.screen.height;
michael@0 44651 }
michael@0 44652 },
michael@0 44653 manufacturer: {
michael@0 44654 get: function manufacturer() {
michael@0 44655 somewhatImplemented('Capabilities.manufacturer');
michael@0 44656 return 'Mozilla Research';
michael@0 44657 }
michael@0 44658 },
michael@0 44659 language: {
michael@0 44660 get: function language() {
michael@0 44661 somewhatImplemented('Capabilities.language');
michael@0 44662 return 'en';
michael@0 44663 }
michael@0 44664 },
michael@0 44665 playerType: {
michael@0 44666 get: function playerType() {
michael@0 44667 somewhatImplemented('Capabilities.playerType');
michael@0 44668 return 'PlugIn';
michael@0 44669 }
michael@0 44670 }
michael@0 44671 }
michael@0 44672 },
michael@0 44673 script: {
michael@0 44674 static: scriptProperties('public', [
michael@0 44675 'version',
michael@0 44676 'os'
michael@0 44677 ])
michael@0 44678 }
michael@0 44679 };
michael@0 44680 return def;
michael@0 44681 }.call(this);
michael@0 44682 var FSCommandDefinition = function () {
michael@0 44683 var def = {};
michael@0 44684 function fscommand(command, parameters) {
michael@0 44685 console.log('FSCommand: ' + command + '; ' + parameters);
michael@0 44686 switch (command.toLowerCase()) {
michael@0 44687 case 'quit':
michael@0 44688 renderingTerminated = true;
michael@0 44689 return;
michael@0 44690 case 'debugger':
michael@0 44691 debugger;
michael@0 44692 return;
michael@0 44693 default:
michael@0 44694 break;
michael@0 44695 }
michael@0 44696 }
michael@0 44697 def.__glue__ = {
michael@0 44698 native: {
michael@0 44699 static: {
michael@0 44700 _fscommand: fscommand
michael@0 44701 }
michael@0 44702 }
michael@0 44703 };
michael@0 44704 return def;
michael@0 44705 }.call(this);
michael@0 44706 var SecurityDefinition = function () {
michael@0 44707 var _exactSettings;
michael@0 44708 return {
michael@0 44709 __class__: 'flash.system.Security',
michael@0 44710 initialize: function () {
michael@0 44711 },
michael@0 44712 __glue__: {
michael@0 44713 native: {
michael@0 44714 static: {
michael@0 44715 allowDomain: function allowDomain() {
michael@0 44716 somewhatImplemented('Security.allowDomain ["' + Array.prototype.join.call(arguments, '", "') + '"]');
michael@0 44717 },
michael@0 44718 allowInsecureDomain: function allowInsecureDomain() {
michael@0 44719 somewhatImplemented('Security.allowInsecureDomain');
michael@0 44720 },
michael@0 44721 loadPolicyFile: function loadPolicyFile(url) {
michael@0 44722 somewhatImplemented('Security.loadPolicyFile');
michael@0 44723 },
michael@0 44724 duplicateSandboxBridgeInputArguments: function duplicateSandboxBridgeInputArguments(toplevel, args) {
michael@0 44725 notImplemented('Security.duplicateSandboxBridgeInputArguments');
michael@0 44726 },
michael@0 44727 duplicateSandboxBridgeOutputArgument: function duplicateSandboxBridgeOutputArgument(toplevel, arg) {
michael@0 44728 notImplemented('Security.duplicateSandboxBridgeOutputArgument');
michael@0 44729 },
michael@0 44730 showSettings: function showSettings(panel) {
michael@0 44731 notImplemented('Security.showSettings');
michael@0 44732 },
michael@0 44733 exactSettings: {
michael@0 44734 get: function () {
michael@0 44735 return _exactSettings;
michael@0 44736 },
michael@0 44737 set: function (value) {
michael@0 44738 _exactSettings = value;
michael@0 44739 }
michael@0 44740 },
michael@0 44741 disableAVM1Loading: {
michael@0 44742 get: function disableAVM1Loading() {
michael@0 44743 notImplemented('Security.disableAVM1Loading');
michael@0 44744 },
michael@0 44745 set: function disableAVM1Loading(value) {
michael@0 44746 notImplemented('Security.disableAVM1Loading');
michael@0 44747 }
michael@0 44748 },
michael@0 44749 sandboxType: {
michael@0 44750 get: function () {
michael@0 44751 somewhatImplemented('Security.sandboxType');
michael@0 44752 return 'remote';
michael@0 44753 }
michael@0 44754 },
michael@0 44755 pageDomain: {
michael@0 44756 get: function pageDomain() {
michael@0 44757 somewhatImplemented('Security.pageDomain');
michael@0 44758 var pageHost = FileLoadingService.resolveUrl('/');
michael@0 44759 var parts = pageHost.split('/');
michael@0 44760 parts.pop();
michael@0 44761 return parts.pop();
michael@0 44762 }
michael@0 44763 }
michael@0 44764 }
michael@0 44765 }
michael@0 44766 }
michael@0 44767 };
michael@0 44768 }.call(this);
michael@0 44769 var SecurityDomainDefinition = function () {
michael@0 44770 return {
michael@0 44771 __class__: 'flash.system.SecurityDomain',
michael@0 44772 initialize: function () {
michael@0 44773 },
michael@0 44774 _currentDomain: null,
michael@0 44775 __glue__: {
michael@0 44776 native: {
michael@0 44777 static: {
michael@0 44778 currentDomain: {
michael@0 44779 get: function () {
michael@0 44780 return this._currentDomain;
michael@0 44781 }
michael@0 44782 }
michael@0 44783 },
michael@0 44784 instance: {
michael@0 44785 ctor_impl: function ctor_impl() {
michael@0 44786 notImplemented('SecurityDomain.ctor_impl');
michael@0 44787 },
michael@0 44788 domainID: {
michael@0 44789 get: function domainID() {
michael@0 44790 notImplemented('SecurityDomain.domainID');
michael@0 44791 return this._domainID;
michael@0 44792 }
michael@0 44793 }
michael@0 44794 }
michael@0 44795 }
michael@0 44796 }
michael@0 44797 };
michael@0 44798 }.call(this);
michael@0 44799 var SystemDefinition = function () {
michael@0 44800 return {
michael@0 44801 __class__: 'flash.system.System',
michael@0 44802 initialize: function () {
michael@0 44803 },
michael@0 44804 __glue__: {
michael@0 44805 native: {
michael@0 44806 static: {
michael@0 44807 setClipboard: function setClipboard(string) {
michael@0 44808 FirefoxCom.request('setClipboard', string);
michael@0 44809 TelemetryService.reportTelemetry({
michael@0 44810 topic: 'feature',
michael@0 44811 feature: CLIPBOARD_FEATURE
michael@0 44812 });
michael@0 44813 },
michael@0 44814 pause: function pause() {
michael@0 44815 somewhatImplemented('System.pause');
michael@0 44816 },
michael@0 44817 resume: function resume() {
michael@0 44818 somewhatImplemented('System.resume');
michael@0 44819 },
michael@0 44820 exit: function exit(code) {
michael@0 44821 somewhatImplemented('System.exit');
michael@0 44822 renderingTerminated = true;
michael@0 44823 },
michael@0 44824 gc: function gc() {
michael@0 44825 somewhatImplemented('System.gc');
michael@0 44826 },
michael@0 44827 pauseForGCIfCollectionImminent: function pauseForGCIfCollectionImminent(imminence) {
michael@0 44828 notImplemented('System.pauseForGCIfCollectionImminent');
michael@0 44829 },
michael@0 44830 disposeXML: function disposeXML(node) {
michael@0 44831 notImplemented('System.disposeXML');
michael@0 44832 },
michael@0 44833 ime: {
michael@0 44834 get: function ime() {
michael@0 44835 notImplemented('System.ime');
michael@0 44836 }
michael@0 44837 },
michael@0 44838 totalMemoryNumber: {
michael@0 44839 get: function totalMemoryNumber() {
michael@0 44840 if (performance.memory) {
michael@0 44841 return performance.memory.usedJSHeapSize;
michael@0 44842 }
michael@0 44843 return 0;
michael@0 44844 }
michael@0 44845 },
michael@0 44846 freeMemory: {
michael@0 44847 get: function freeMemory() {
michael@0 44848 notImplemented('System.freeMemory');
michael@0 44849 }
michael@0 44850 },
michael@0 44851 privateMemory: {
michael@0 44852 get: function privateMemory() {
michael@0 44853 return 0;
michael@0 44854 }
michael@0 44855 },
michael@0 44856 processCPUUsage: {
michael@0 44857 get: function processCPUUsage() {
michael@0 44858 notImplemented('System.processCPUUsage');
michael@0 44859 }
michael@0 44860 },
michael@0 44861 useCodePage: {
michael@0 44862 get: function useCodePage() {
michael@0 44863 somewhatImplemented('System.useCodePage');
michael@0 44864 return false;
michael@0 44865 },
michael@0 44866 set: function useCodePage(value) {
michael@0 44867 notImplemented('System.useCodePage');
michael@0 44868 }
michael@0 44869 },
michael@0 44870 vmVersion: {
michael@0 44871 get: function vmVersion() {
michael@0 44872 somewhatImplemented('System.vmVersion');
michael@0 44873 return '1.0 shumway';
michael@0 44874 }
michael@0 44875 },
michael@0 44876 swfVersion: {
michael@0 44877 get: function () {
michael@0 44878 return 19;
michael@0 44879 }
michael@0 44880 },
michael@0 44881 apiVersion: {
michael@0 44882 get: function () {
michael@0 44883 return 26;
michael@0 44884 }
michael@0 44885 },
michael@0 44886 getArgv: function () {
michael@0 44887 return [];
michael@0 44888 },
michael@0 44889 getRunmode: function () {
michael@0 44890 return 'mixed';
michael@0 44891 }
michael@0 44892 },
michael@0 44893 instance: {}
michael@0 44894 }
michael@0 44895 }
michael@0 44896 };
michael@0 44897 }.call(this);
michael@0 44898 {
michael@0 44899 var FontDefinition = function () {
michael@0 44900 var fonts = [];
michael@0 44901 var fontsByUniqueName = Object.create(null);
michael@0 44902 var fontsByNameStyleType = Object.create(null);
michael@0 44903 var _deviceFontMetrics;
michael@0 44904 var def = {
michael@0 44905 __class__: 'flash.text.Font',
michael@0 44906 initialize: function () {
michael@0 44907 var s = this.symbol;
michael@0 44908 if (s) {
michael@0 44909 this._fontName = s.name || null;
michael@0 44910 this._uniqueName = s.uniqueName;
michael@0 44911 if (s.bold) {
michael@0 44912 if (s.italic) {
michael@0 44913 this._fontStyle = 'boldItalic';
michael@0 44914 } else {
michael@0 44915 this._fontStyle = 'bold';
michael@0 44916 }
michael@0 44917 } else if (s.italic) {
michael@0 44918 this._fontStyle = 'italic';
michael@0 44919 } else {
michael@0 44920 this._fontStyle = 'regular';
michael@0 44921 }
michael@0 44922 var metrics = s.metrics;
michael@0 44923 metrics.height = metrics.ascent + metrics.descent + metrics.leading;
michael@0 44924 this._metrics = metrics;
michael@0 44925 this._fontType = 'embedded';
michael@0 44926 fonts.push(this);
michael@0 44927 fontsByUniqueName[this._uniqueName] = this;
michael@0 44928 var ident = this._fontName.toLowerCase() + '_' + this._fontStyle + '_embedded';
michael@0 44929 fontsByNameStyleType[ident] = this;
michael@0 44930 }
michael@0 44931 },
michael@0 44932 get fontName() {
michael@0 44933 return this._fontName;
michael@0 44934 },
michael@0 44935 get fontStyle() {
michael@0 44936 return this._fontStyle;
michael@0 44937 },
michael@0 44938 get fontType() {
michael@0 44939 return this._fontType;
michael@0 44940 },
michael@0 44941 hasGlyphs: function hasGlyphs(str) {
michael@0 44942 return true;
michael@0 44943 },
michael@0 44944 getFont: function (name, style, embedded) {
michael@0 44945 var ident = name.toLowerCase() + '_' + style + (embedded ? '_embedded' : '_device');
michael@0 44946 var font = fontsByNameStyleType[ident];
michael@0 44947 if (font) {
michael@0 44948 return font;
michael@0 44949 }
michael@0 44950 font = new flash.text.Font();
michael@0 44951 font._fontName = font._uniqueName = name;
michael@0 44952 font._fontStyle = style;
michael@0 44953 font._fontType = 'device';
michael@0 44954 var metrics = deviceFontMetrics()[name];
michael@0 44955 if (!metrics) {
michael@0 44956 metrics = deviceFontMetrics().serif;
michael@0 44957 font._fontName = font._uniqueName = 'serif';
michael@0 44958 }
michael@0 44959 font._metrics = {
michael@0 44960 ascent: metrics[0],
michael@0 44961 descent: metrics[1],
michael@0 44962 leading: metrics[2]
michael@0 44963 };
michael@0 44964 font._metrics.height = metrics[0] + metrics[1] + metrics[2];
michael@0 44965 fontsByNameStyleType[ident] = font;
michael@0 44966 return font;
michael@0 44967 },
michael@0 44968 getFontByUniqueName: function (name) {
michael@0 44969 return fontsByUniqueName[name];
michael@0 44970 }
michael@0 44971 };
michael@0 44972 function enumerateFonts(device) {
michael@0 44973 return fonts.slice();
michael@0 44974 }
michael@0 44975 function registerFont(font) {
michael@0 44976 somewhatImplemented('Font.registerFont');
michael@0 44977 }
michael@0 44978 function deviceFontMetrics() {
michael@0 44979 if (_deviceFontMetrics) {
michael@0 44980 return _deviceFontMetrics;
michael@0 44981 }
michael@0 44982 var userAgent = window.navigator.userAgent;
michael@0 44983 if (userAgent.indexOf('Windows') > -1) {
michael@0 44984 _deviceFontMetrics = DEVICE_FONT_METRICS_WIN;
michael@0 44985 } else if (/(Macintosh|iPad|iPhone|iPod|Android)/.test(userAgent)) {
michael@0 44986 _deviceFontMetrics = DEVICE_FONT_METRICS_MAC;
michael@0 44987 } else {
michael@0 44988 _deviceFontMetrics = DEVICE_FONT_METRICS_LINUX;
michael@0 44989 }
michael@0 44990 return _deviceFontMetrics;
michael@0 44991 }
michael@0 44992 var desc = Object.getOwnPropertyDescriptor;
michael@0 44993 def.__glue__ = {
michael@0 44994 native: {
michael@0 44995 instance: {
michael@0 44996 fontName: desc(def, 'fontName'),
michael@0 44997 fontStyle: desc(def, 'fontStyle'),
michael@0 44998 fontType: desc(def, 'fontType'),
michael@0 44999 hasGlyphs: def.hasGlyphs
michael@0 45000 },
michael@0 45001 static: {
michael@0 45002 enumerateFonts: enumerateFonts,
michael@0 45003 registerFont: registerFont
michael@0 45004 }
michael@0 45005 }
michael@0 45006 };
michael@0 45007 return def;
michael@0 45008 }.call(this);
michael@0 45009 var DEVICE_FONT_METRICS_WIN = {
michael@0 45010 'serif': [
michael@0 45011 1,
michael@0 45012 0.25,
michael@0 45013 0
michael@0 45014 ],
michael@0 45015 'sans-serif': [
michael@0 45016 1,
michael@0 45017 0.25,
michael@0 45018 0
michael@0 45019 ],
michael@0 45020 'monospace': [
michael@0 45021 1,
michael@0 45022 0.25,
michael@0 45023 0
michael@0 45024 ],
michael@0 45025 'birch std': [
michael@0 45026 0.9167,
michael@0 45027 0.25,
michael@0 45028 0
michael@0 45029 ],
michael@0 45030 'blackoak std': [
michael@0 45031 1,
michael@0 45032 0.3333,
michael@0 45033 0
michael@0 45034 ],
michael@0 45035 'chaparral pro': [
michael@0 45036 0.8333,
michael@0 45037 0.3333,
michael@0 45038 0
michael@0 45039 ],
michael@0 45040 'chaparral pro light': [
michael@0 45041 0.8333,
michael@0 45042 0.3333,
michael@0 45043 0
michael@0 45044 ],
michael@0 45045 'charlemagne std': [
michael@0 45046 0.9167,
michael@0 45047 0.25,
michael@0 45048 0
michael@0 45049 ],
michael@0 45050 'cooper std black': [
michael@0 45051 0.9167,
michael@0 45052 0.25,
michael@0 45053 0
michael@0 45054 ],
michael@0 45055 'giddyup std': [
michael@0 45056 0.8333,
michael@0 45057 0.3333,
michael@0 45058 0
michael@0 45059 ],
michael@0 45060 'hobo std': [
michael@0 45061 1.0833,
michael@0 45062 0.3333,
michael@0 45063 0
michael@0 45064 ],
michael@0 45065 'kozuka gothic pro b': [
michael@0 45066 1,
michael@0 45067 0.4167,
michael@0 45068 0
michael@0 45069 ],
michael@0 45070 'kozuka gothic pro el': [
michael@0 45071 1.0833,
michael@0 45072 0.25,
michael@0 45073 0
michael@0 45074 ],
michael@0 45075 'kozuka gothic pro h': [
michael@0 45076 1,
michael@0 45077 0.4167,
michael@0 45078 0
michael@0 45079 ],
michael@0 45080 'kozuka gothic pro l': [
michael@0 45081 1,
michael@0 45082 0.3333,
michael@0 45083 0
michael@0 45084 ],
michael@0 45085 'kozuka gothic pro m': [
michael@0 45086 1.0833,
michael@0 45087 0.3333,
michael@0 45088 0
michael@0 45089 ],
michael@0 45090 'kozuka gothic pro r': [
michael@0 45091 1,
michael@0 45092 0.3333,
michael@0 45093 0
michael@0 45094 ],
michael@0 45095 'kozuka mincho pro b': [
michael@0 45096 1.0833,
michael@0 45097 0.25,
michael@0 45098 0
michael@0 45099 ],
michael@0 45100 'kozuka mincho pro el': [
michael@0 45101 1.0833,
michael@0 45102 0.25,
michael@0 45103 0
michael@0 45104 ],
michael@0 45105 'kozuka mincho pro h': [
michael@0 45106 1.1667,
michael@0 45107 0.25,
michael@0 45108 0
michael@0 45109 ],
michael@0 45110 'kozuka mincho pro l': [
michael@0 45111 1.0833,
michael@0 45112 0.25,
michael@0 45113 0
michael@0 45114 ],
michael@0 45115 'kozuka mincho pro m': [
michael@0 45116 1.0833,
michael@0 45117 0.25,
michael@0 45118 0
michael@0 45119 ],
michael@0 45120 'kozuka mincho pro r': [
michael@0 45121 1.0833,
michael@0 45122 0.25,
michael@0 45123 0
michael@0 45124 ],
michael@0 45125 'mesquite std': [
michael@0 45126 0.9167,
michael@0 45127 0.25,
michael@0 45128 0
michael@0 45129 ],
michael@0 45130 'minion pro cond': [
michael@0 45131 1,
michael@0 45132 0.3333,
michael@0 45133 0
michael@0 45134 ],
michael@0 45135 'minion pro med': [
michael@0 45136 1,
michael@0 45137 0.3333,
michael@0 45138 0
michael@0 45139 ],
michael@0 45140 'minion pro smbd': [
michael@0 45141 1,
michael@0 45142 0.3333,
michael@0 45143 0
michael@0 45144 ],
michael@0 45145 'myriad arabic': [
michael@0 45146 1,
michael@0 45147 0.4167,
michael@0 45148 0
michael@0 45149 ],
michael@0 45150 'nueva std': [
michael@0 45151 0.75,
michael@0 45152 0.25,
michael@0 45153 0
michael@0 45154 ],
michael@0 45155 'nueva std cond': [
michael@0 45156 0.75,
michael@0 45157 0.25,
michael@0 45158 0
michael@0 45159 ],
michael@0 45160 'ocr a std': [
michael@0 45161 0.8333,
michael@0 45162 0.25,
michael@0 45163 0
michael@0 45164 ],
michael@0 45165 'orator std': [
michael@0 45166 1.0833,
michael@0 45167 0.25,
michael@0 45168 0
michael@0 45169 ],
michael@0 45170 'poplar std': [
michael@0 45171 0.9167,
michael@0 45172 0.25,
michael@0 45173 0
michael@0 45174 ],
michael@0 45175 'prestige elite std': [
michael@0 45176 0.9167,
michael@0 45177 0.25,
michael@0 45178 0
michael@0 45179 ],
michael@0 45180 'rosewood std regular': [
michael@0 45181 0.8333,
michael@0 45182 0.3333,
michael@0 45183 0
michael@0 45184 ],
michael@0 45185 'stencil std': [
michael@0 45186 1,
michael@0 45187 0.3333,
michael@0 45188 0
michael@0 45189 ],
michael@0 45190 'trajan pro': [
michael@0 45191 1,
michael@0 45192 0.25,
michael@0 45193 0
michael@0 45194 ],
michael@0 45195 'kozuka gothic pr6n b': [
michael@0 45196 1.4167,
michael@0 45197 0.4167,
michael@0 45198 0
michael@0 45199 ],
michael@0 45200 'kozuka gothic pr6n el': [
michael@0 45201 1.4167,
michael@0 45202 0.3333,
michael@0 45203 0
michael@0 45204 ],
michael@0 45205 'kozuka gothic pr6n h': [
michael@0 45206 1.4167,
michael@0 45207 0.4167,
michael@0 45208 0
michael@0 45209 ],
michael@0 45210 'kozuka gothic pr6n l': [
michael@0 45211 1.4167,
michael@0 45212 0.3333,
michael@0 45213 0
michael@0 45214 ],
michael@0 45215 'kozuka gothic pr6n m': [
michael@0 45216 1.5,
michael@0 45217 0.3333,
michael@0 45218 0
michael@0 45219 ],
michael@0 45220 'kozuka gothic pr6n r': [
michael@0 45221 1.4167,
michael@0 45222 0.3333,
michael@0 45223 0
michael@0 45224 ],
michael@0 45225 'kozuka mincho pr6n b': [
michael@0 45226 1.3333,
michael@0 45227 0.3333,
michael@0 45228 0
michael@0 45229 ],
michael@0 45230 'kozuka mincho pr6n el': [
michael@0 45231 1.3333,
michael@0 45232 0.3333,
michael@0 45233 0
michael@0 45234 ],
michael@0 45235 'kozuka mincho pr6n h': [
michael@0 45236 1.4167,
michael@0 45237 0.3333,
michael@0 45238 0
michael@0 45239 ],
michael@0 45240 'kozuka mincho pr6n l': [
michael@0 45241 1.3333,
michael@0 45242 0.3333,
michael@0 45243 0
michael@0 45244 ],
michael@0 45245 'kozuka mincho pr6n m': [
michael@0 45246 1.3333,
michael@0 45247 0.3333,
michael@0 45248 0
michael@0 45249 ],
michael@0 45250 'kozuka mincho pr6n r': [
michael@0 45251 1.3333,
michael@0 45252 0.3333,
michael@0 45253 0
michael@0 45254 ],
michael@0 45255 'letter gothic std': [
michael@0 45256 1,
michael@0 45257 0.25,
michael@0 45258 0
michael@0 45259 ],
michael@0 45260 'minion pro': [
michael@0 45261 1,
michael@0 45262 0.3333,
michael@0 45263 0
michael@0 45264 ],
michael@0 45265 'myriad hebrew': [
michael@0 45266 0.8333,
michael@0 45267 0.3333,
michael@0 45268 0
michael@0 45269 ],
michael@0 45270 'myriad pro': [
michael@0 45271 0.9167,
michael@0 45272 0.25,
michael@0 45273 0
michael@0 45274 ],
michael@0 45275 'myriad pro cond': [
michael@0 45276 0.9167,
michael@0 45277 0.25,
michael@0 45278 0
michael@0 45279 ],
michael@0 45280 'myriad pro light': [
michael@0 45281 1,
michael@0 45282 0.25,
michael@0 45283 0
michael@0 45284 ],
michael@0 45285 'marlett': [
michael@0 45286 1,
michael@0 45287 0,
michael@0 45288 0
michael@0 45289 ],
michael@0 45290 'arial': [
michael@0 45291 1,
michael@0 45292 0.25,
michael@0 45293 0
michael@0 45294 ],
michael@0 45295 'arabic transparent': [
michael@0 45296 1,
michael@0 45297 0.25,
michael@0 45298 0
michael@0 45299 ],
michael@0 45300 'arial baltic': [
michael@0 45301 1,
michael@0 45302 0.25,
michael@0 45303 0
michael@0 45304 ],
michael@0 45305 'arial ce': [
michael@0 45306 1,
michael@0 45307 0.25,
michael@0 45308 0
michael@0 45309 ],
michael@0 45310 'arial cyr': [
michael@0 45311 1,
michael@0 45312 0.25,
michael@0 45313 0
michael@0 45314 ],
michael@0 45315 'arial greek': [
michael@0 45316 1,
michael@0 45317 0.25,
michael@0 45318 0
michael@0 45319 ],
michael@0 45320 'arial tur': [
michael@0 45321 1,
michael@0 45322 0.25,
michael@0 45323 0
michael@0 45324 ],
michael@0 45325 'batang': [
michael@0 45326 0.8333,
michael@0 45327 0.1667,
michael@0 45328 0
michael@0 45329 ],
michael@0 45330 'batangche': [
michael@0 45331 0.8333,
michael@0 45332 0.1667,
michael@0 45333 0
michael@0 45334 ],
michael@0 45335 'gungsuh': [
michael@0 45336 0.8333,
michael@0 45337 0.1667,
michael@0 45338 0
michael@0 45339 ],
michael@0 45340 'gungsuhche': [
michael@0 45341 0.8333,
michael@0 45342 0.1667,
michael@0 45343 0
michael@0 45344 ],
michael@0 45345 'courier new': [
michael@0 45346 1,
michael@0 45347 0.25,
michael@0 45348 0
michael@0 45349 ],
michael@0 45350 'courier new baltic': [
michael@0 45351 1,
michael@0 45352 0.25,
michael@0 45353 0
michael@0 45354 ],
michael@0 45355 'courier new ce': [
michael@0 45356 1,
michael@0 45357 0.25,
michael@0 45358 0
michael@0 45359 ],
michael@0 45360 'courier new cyr': [
michael@0 45361 1,
michael@0 45362 0.25,
michael@0 45363 0
michael@0 45364 ],
michael@0 45365 'courier new greek': [
michael@0 45366 1,
michael@0 45367 0.25,
michael@0 45368 0
michael@0 45369 ],
michael@0 45370 'courier new tur': [
michael@0 45371 1,
michael@0 45372 0.25,
michael@0 45373 0
michael@0 45374 ],
michael@0 45375 'daunpenh': [
michael@0 45376 0.6667,
michael@0 45377 0.6667,
michael@0 45378 0
michael@0 45379 ],
michael@0 45380 'dokchampa': [
michael@0 45381 1.4167,
michael@0 45382 0.5833,
michael@0 45383 0
michael@0 45384 ],
michael@0 45385 'estrangelo edessa': [
michael@0 45386 0.75,
michael@0 45387 0.3333,
michael@0 45388 0
michael@0 45389 ],
michael@0 45390 'euphemia': [
michael@0 45391 1.0833,
michael@0 45392 0.3333,
michael@0 45393 0
michael@0 45394 ],
michael@0 45395 'gautami': [
michael@0 45396 1.1667,
michael@0 45397 0.8333,
michael@0 45398 0
michael@0 45399 ],
michael@0 45400 'vani': [
michael@0 45401 1.0833,
michael@0 45402 0.75,
michael@0 45403 0
michael@0 45404 ],
michael@0 45405 'gulim': [
michael@0 45406 0.8333,
michael@0 45407 0.1667,
michael@0 45408 0
michael@0 45409 ],
michael@0 45410 'gulimche': [
michael@0 45411 0.8333,
michael@0 45412 0.1667,
michael@0 45413 0
michael@0 45414 ],
michael@0 45415 'dotum': [
michael@0 45416 0.8333,
michael@0 45417 0.1667,
michael@0 45418 0
michael@0 45419 ],
michael@0 45420 'dotumche': [
michael@0 45421 0.8333,
michael@0 45422 0.1667,
michael@0 45423 0
michael@0 45424 ],
michael@0 45425 'impact': [
michael@0 45426 1.0833,
michael@0 45427 0.25,
michael@0 45428 0
michael@0 45429 ],
michael@0 45430 'iskoola pota': [
michael@0 45431 1,
michael@0 45432 0.3333,
michael@0 45433 0
michael@0 45434 ],
michael@0 45435 'kalinga': [
michael@0 45436 1.0833,
michael@0 45437 0.5,
michael@0 45438 0
michael@0 45439 ],
michael@0 45440 'kartika': [
michael@0 45441 1,
michael@0 45442 0.4167,
michael@0 45443 0
michael@0 45444 ],
michael@0 45445 'khmer ui': [
michael@0 45446 1.0833,
michael@0 45447 0.3333,
michael@0 45448 0
michael@0 45449 ],
michael@0 45450 'lao ui': [
michael@0 45451 1,
michael@0 45452 0.25,
michael@0 45453 0
michael@0 45454 ],
michael@0 45455 'latha': [
michael@0 45456 1.0833,
michael@0 45457 0.4167,
michael@0 45458 0
michael@0 45459 ],
michael@0 45460 'lucida console': [
michael@0 45461 0.75,
michael@0 45462 0.25,
michael@0 45463 0
michael@0 45464 ],
michael@0 45465 'malgun gothic': [
michael@0 45466 1,
michael@0 45467 0.25,
michael@0 45468 0
michael@0 45469 ],
michael@0 45470 'mangal': [
michael@0 45471 1.0833,
michael@0 45472 0.3333,
michael@0 45473 0
michael@0 45474 ],
michael@0 45475 'meiryo': [
michael@0 45476 1.0833,
michael@0 45477 0.4167,
michael@0 45478 0
michael@0 45479 ],
michael@0 45480 'meiryo ui': [
michael@0 45481 1,
michael@0 45482 0.25,
michael@0 45483 0
michael@0 45484 ],
michael@0 45485 'microsoft himalaya': [
michael@0 45486 0.5833,
michael@0 45487 0.4167,
michael@0 45488 0
michael@0 45489 ],
michael@0 45490 'microsoft jhenghei': [
michael@0 45491 1,
michael@0 45492 0.3333,
michael@0 45493 0
michael@0 45494 ],
michael@0 45495 'microsoft yahei': [
michael@0 45496 1.0833,
michael@0 45497 0.3333,
michael@0 45498 0
michael@0 45499 ],
michael@0 45500 'mingliu': [
michael@0 45501 0.8333,
michael@0 45502 0.1667,
michael@0 45503 0
michael@0 45504 ],
michael@0 45505 'pmingliu': [
michael@0 45506 0.8333,
michael@0 45507 0.1667,
michael@0 45508 0
michael@0 45509 ],
michael@0 45510 'mingliu_hkscs': [
michael@0 45511 0.8333,
michael@0 45512 0.1667,
michael@0 45513 0
michael@0 45514 ],
michael@0 45515 'mingliu-extb': [
michael@0 45516 0.8333,
michael@0 45517 0.1667,
michael@0 45518 0
michael@0 45519 ],
michael@0 45520 'pmingliu-extb': [
michael@0 45521 0.8333,
michael@0 45522 0.1667,
michael@0 45523 0
michael@0 45524 ],
michael@0 45525 'mingliu_hkscs-extb': [
michael@0 45526 0.8333,
michael@0 45527 0.1667,
michael@0 45528 0
michael@0 45529 ],
michael@0 45530 'mongolian baiti': [
michael@0 45531 0.8333,
michael@0 45532 0.25,
michael@0 45533 0
michael@0 45534 ],
michael@0 45535 'ms gothic': [
michael@0 45536 0.8333,
michael@0 45537 0.1667,
michael@0 45538 0
michael@0 45539 ],
michael@0 45540 'ms pgothic': [
michael@0 45541 0.8333,
michael@0 45542 0.1667,
michael@0 45543 0
michael@0 45544 ],
michael@0 45545 'ms ui gothic': [
michael@0 45546 0.8333,
michael@0 45547 0.1667,
michael@0 45548 0
michael@0 45549 ],
michael@0 45550 'ms mincho': [
michael@0 45551 0.8333,
michael@0 45552 0.1667,
michael@0 45553 0
michael@0 45554 ],
michael@0 45555 'ms pmincho': [
michael@0 45556 0.8333,
michael@0 45557 0.1667,
michael@0 45558 0
michael@0 45559 ],
michael@0 45560 'mv boli': [
michael@0 45561 1.1667,
michael@0 45562 0.25,
michael@0 45563 0
michael@0 45564 ],
michael@0 45565 'microsoft new tai lue': [
michael@0 45566 1,
michael@0 45567 0.4167,
michael@0 45568 0
michael@0 45569 ],
michael@0 45570 'nyala': [
michael@0 45571 0.9167,
michael@0 45572 0.3333,
michael@0 45573 0
michael@0 45574 ],
michael@0 45575 'microsoft phagspa': [
michael@0 45576 1.0833,
michael@0 45577 0.25,
michael@0 45578 0
michael@0 45579 ],
michael@0 45580 'plantagenet cherokee': [
michael@0 45581 1,
michael@0 45582 0.4167,
michael@0 45583 0
michael@0 45584 ],
michael@0 45585 'raavi': [
michael@0 45586 1.0833,
michael@0 45587 0.6667,
michael@0 45588 0
michael@0 45589 ],
michael@0 45590 'segoe script': [
michael@0 45591 1.0833,
michael@0 45592 0.5,
michael@0 45593 0
michael@0 45594 ],
michael@0 45595 'segoe ui': [
michael@0 45596 1,
michael@0 45597 0.25,
michael@0 45598 0
michael@0 45599 ],
michael@0 45600 'segoe ui semibold': [
michael@0 45601 1,
michael@0 45602 0.25,
michael@0 45603 0
michael@0 45604 ],
michael@0 45605 'segoe ui light': [
michael@0 45606 1,
michael@0 45607 0.25,
michael@0 45608 0
michael@0 45609 ],
michael@0 45610 'segoe ui symbol': [
michael@0 45611 1,
michael@0 45612 0.25,
michael@0 45613 0
michael@0 45614 ],
michael@0 45615 'shruti': [
michael@0 45616 1.0833,
michael@0 45617 0.5,
michael@0 45618 0
michael@0 45619 ],
michael@0 45620 'simsun': [
michael@0 45621 0.8333,
michael@0 45622 0.1667,
michael@0 45623 0
michael@0 45624 ],
michael@0 45625 'nsimsun': [
michael@0 45626 0.8333,
michael@0 45627 0.1667,
michael@0 45628 0
michael@0 45629 ],
michael@0 45630 'simsun-extb': [
michael@0 45631 0.8333,
michael@0 45632 0.1667,
michael@0 45633 0
michael@0 45634 ],
michael@0 45635 'sylfaen': [
michael@0 45636 1,
michael@0 45637 0.3333,
michael@0 45638 0
michael@0 45639 ],
michael@0 45640 'microsoft tai le': [
michael@0 45641 1,
michael@0 45642 0.3333,
michael@0 45643 0
michael@0 45644 ],
michael@0 45645 'times new roman': [
michael@0 45646 1,
michael@0 45647 0.25,
michael@0 45648 0
michael@0 45649 ],
michael@0 45650 'times new roman baltic': [
michael@0 45651 1,
michael@0 45652 0.25,
michael@0 45653 0
michael@0 45654 ],
michael@0 45655 'times new roman ce': [
michael@0 45656 1,
michael@0 45657 0.25,
michael@0 45658 0
michael@0 45659 ],
michael@0 45660 'times new roman cyr': [
michael@0 45661 1,
michael@0 45662 0.25,
michael@0 45663 0
michael@0 45664 ],
michael@0 45665 'times new roman greek': [
michael@0 45666 1,
michael@0 45667 0.25,
michael@0 45668 0
michael@0 45669 ],
michael@0 45670 'times new roman tur': [
michael@0 45671 1,
michael@0 45672 0.25,
michael@0 45673 0
michael@0 45674 ],
michael@0 45675 'tunga': [
michael@0 45676 1.0833,
michael@0 45677 0.75,
michael@0 45678 0
michael@0 45679 ],
michael@0 45680 'vrinda': [
michael@0 45681 1,
michael@0 45682 0.4167,
michael@0 45683 0
michael@0 45684 ],
michael@0 45685 'shonar bangla': [
michael@0 45686 0.8333,
michael@0 45687 0.5,
michael@0 45688 0
michael@0 45689 ],
michael@0 45690 'microsoft yi baiti': [
michael@0 45691 0.8333,
michael@0 45692 0.1667,
michael@0 45693 0
michael@0 45694 ],
michael@0 45695 'tahoma': [
michael@0 45696 1,
michael@0 45697 0.1667,
michael@0 45698 0
michael@0 45699 ],
michael@0 45700 'microsoft sans serif': [
michael@0 45701 1.0833,
michael@0 45702 0.1667,
michael@0 45703 0
michael@0 45704 ],
michael@0 45705 'angsana new': [
michael@0 45706 0.9167,
michael@0 45707 0.4167,
michael@0 45708 0
michael@0 45709 ],
michael@0 45710 'aparajita': [
michael@0 45711 0.75,
michael@0 45712 0.4167,
michael@0 45713 0
michael@0 45714 ],
michael@0 45715 'cordia new': [
michael@0 45716 0.9167,
michael@0 45717 0.5,
michael@0 45718 0
michael@0 45719 ],
michael@0 45720 'ebrima': [
michael@0 45721 1.0833,
michael@0 45722 0.5,
michael@0 45723 0
michael@0 45724 ],
michael@0 45725 'gisha': [
michael@0 45726 0.9167,
michael@0 45727 0.25,
michael@0 45728 0
michael@0 45729 ],
michael@0 45730 'kokila': [
michael@0 45731 0.8333,
michael@0 45732 0.3333,
michael@0 45733 0
michael@0 45734 ],
michael@0 45735 'leelawadee': [
michael@0 45736 0.9167,
michael@0 45737 0.25,
michael@0 45738 0
michael@0 45739 ],
michael@0 45740 'microsoft uighur': [
michael@0 45741 1.0833,
michael@0 45742 0.5,
michael@0 45743 0
michael@0 45744 ],
michael@0 45745 'moolboran': [
michael@0 45746 0.6667,
michael@0 45747 0.6667,
michael@0 45748 0
michael@0 45749 ],
michael@0 45750 'symbol': [
michael@0 45751 1,
michael@0 45752 0.25,
michael@0 45753 0
michael@0 45754 ],
michael@0 45755 'utsaah': [
michael@0 45756 0.8333,
michael@0 45757 0.4167,
michael@0 45758 0
michael@0 45759 ],
michael@0 45760 'vijaya': [
michael@0 45761 1.0833,
michael@0 45762 0.25,
michael@0 45763 0
michael@0 45764 ],
michael@0 45765 'wingdings': [
michael@0 45766 0.9167,
michael@0 45767 0.25,
michael@0 45768 0
michael@0 45769 ],
michael@0 45770 'andalus': [
michael@0 45771 1.3333,
michael@0 45772 0.4167,
michael@0 45773 0
michael@0 45774 ],
michael@0 45775 'arabic typesetting': [
michael@0 45776 0.8333,
michael@0 45777 0.5,
michael@0 45778 0
michael@0 45779 ],
michael@0 45780 'simplified arabic': [
michael@0 45781 1.3333,
michael@0 45782 0.5,
michael@0 45783 0
michael@0 45784 ],
michael@0 45785 'simplified arabic fixed': [
michael@0 45786 1,
michael@0 45787 0.4167,
michael@0 45788 0
michael@0 45789 ],
michael@0 45790 'sakkal majalla': [
michael@0 45791 0.9167,
michael@0 45792 0.5,
michael@0 45793 0
michael@0 45794 ],
michael@0 45795 'traditional arabic': [
michael@0 45796 1.3333,
michael@0 45797 0.5,
michael@0 45798 0
michael@0 45799 ],
michael@0 45800 'aharoni': [
michael@0 45801 0.75,
michael@0 45802 0.25,
michael@0 45803 0
michael@0 45804 ],
michael@0 45805 'david': [
michael@0 45806 0.75,
michael@0 45807 0.25,
michael@0 45808 0
michael@0 45809 ],
michael@0 45810 'frankruehl': [
michael@0 45811 0.75,
michael@0 45812 0.25,
michael@0 45813 0
michael@0 45814 ],
michael@0 45815 'fangsong': [
michael@0 45816 0.8333,
michael@0 45817 0.1667,
michael@0 45818 0
michael@0 45819 ],
michael@0 45820 'simhei': [
michael@0 45821 0.8333,
michael@0 45822 0.1667,
michael@0 45823 0
michael@0 45824 ],
michael@0 45825 'kaiti': [
michael@0 45826 0.8333,
michael@0 45827 0.1667,
michael@0 45828 0
michael@0 45829 ],
michael@0 45830 'browallia new': [
michael@0 45831 0.8333,
michael@0 45832 0.4167,
michael@0 45833 0
michael@0 45834 ],
michael@0 45835 'lucida sans unicode': [
michael@0 45836 1.0833,
michael@0 45837 0.25,
michael@0 45838 0
michael@0 45839 ],
michael@0 45840 'arial black': [
michael@0 45841 1.0833,
michael@0 45842 0.3333,
michael@0 45843 0
michael@0 45844 ],
michael@0 45845 'calibri': [
michael@0 45846 0.9167,
michael@0 45847 0.25,
michael@0 45848 0
michael@0 45849 ],
michael@0 45850 'cambria': [
michael@0 45851 0.9167,
michael@0 45852 0.25,
michael@0 45853 0
michael@0 45854 ],
michael@0 45855 'cambria math': [
michael@0 45856 3.0833,
michael@0 45857 2.5,
michael@0 45858 0
michael@0 45859 ],
michael@0 45860 'candara': [
michael@0 45861 0.9167,
michael@0 45862 0.25,
michael@0 45863 0
michael@0 45864 ],
michael@0 45865 'comic sans ms': [
michael@0 45866 1.0833,
michael@0 45867 0.3333,
michael@0 45868 0
michael@0 45869 ],
michael@0 45870 'consolas': [
michael@0 45871 0.9167,
michael@0 45872 0.25,
michael@0 45873 0
michael@0 45874 ],
michael@0 45875 'constantia': [
michael@0 45876 0.9167,
michael@0 45877 0.25,
michael@0 45878 0
michael@0 45879 ],
michael@0 45880 'corbel': [
michael@0 45881 0.9167,
michael@0 45882 0.25,
michael@0 45883 0
michael@0 45884 ],
michael@0 45885 'franklin gothic medium': [
michael@0 45886 1,
michael@0 45887 0.3333,
michael@0 45888 0
michael@0 45889 ],
michael@0 45890 'gabriola': [
michael@0 45891 1.1667,
michael@0 45892 0.6667,
michael@0 45893 0
michael@0 45894 ],
michael@0 45895 'georgia': [
michael@0 45896 1,
michael@0 45897 0.25,
michael@0 45898 0
michael@0 45899 ],
michael@0 45900 'palatino linotype': [
michael@0 45901 1.0833,
michael@0 45902 0.3333,
michael@0 45903 0
michael@0 45904 ],
michael@0 45905 'segoe print': [
michael@0 45906 1.25,
michael@0 45907 0.5,
michael@0 45908 0
michael@0 45909 ],
michael@0 45910 'trebuchet ms': [
michael@0 45911 1.0833,
michael@0 45912 0.4167,
michael@0 45913 0
michael@0 45914 ],
michael@0 45915 'verdana': [
michael@0 45916 1,
michael@0 45917 0.1667,
michael@0 45918 0
michael@0 45919 ],
michael@0 45920 'webdings': [
michael@0 45921 1.0833,
michael@0 45922 0.5,
michael@0 45923 0
michael@0 45924 ],
michael@0 45925 'lucida bright': [
michael@0 45926 0.9167,
michael@0 45927 0.25,
michael@0 45928 0
michael@0 45929 ],
michael@0 45930 'lucida sans': [
michael@0 45931 0.9167,
michael@0 45932 0.25,
michael@0 45933 0
michael@0 45934 ],
michael@0 45935 'lucida sans typewriter': [
michael@0 45936 0.9167,
michael@0 45937 0.25,
michael@0 45938 0
michael@0 45939 ],
michael@0 45940 'gentium basic': [
michael@0 45941 0.8333,
michael@0 45942 0.25,
michael@0 45943 0
michael@0 45944 ],
michael@0 45945 'dejavu serif condensed': [
michael@0 45946 0.9167,
michael@0 45947 0.25,
michael@0 45948 0
michael@0 45949 ],
michael@0 45950 'arimo': [
michael@0 45951 1,
michael@0 45952 0.25,
michael@0 45953 0
michael@0 45954 ],
michael@0 45955 'dejavu sans condensed': [
michael@0 45956 0.9167,
michael@0 45957 0.25,
michael@0 45958 0
michael@0 45959 ],
michael@0 45960 'dejavu sans': [
michael@0 45961 0.9167,
michael@0 45962 0.25,
michael@0 45963 0
michael@0 45964 ],
michael@0 45965 'dejavu sans light': [
michael@0 45966 0.9167,
michael@0 45967 0.25,
michael@0 45968 0
michael@0 45969 ],
michael@0 45970 'opensymbol': [
michael@0 45971 0.8333,
michael@0 45972 0.1667,
michael@0 45973 0
michael@0 45974 ],
michael@0 45975 'gentium book basic': [
michael@0 45976 0.8333,
michael@0 45977 0.25,
michael@0 45978 0
michael@0 45979 ],
michael@0 45980 'dejavu sans mono': [
michael@0 45981 0.9167,
michael@0 45982 0.25,
michael@0 45983 0
michael@0 45984 ],
michael@0 45985 'dejavu serif': [
michael@0 45986 0.9167,
michael@0 45987 0.25,
michael@0 45988 0
michael@0 45989 ],
michael@0 45990 'calibri light': [
michael@0 45991 0.9167,
michael@0 45992 0.25,
michael@0 45993 0
michael@0 45994 ]
michael@0 45995 };
michael@0 45996 var DEVICE_FONT_METRICS_MAC = {
michael@0 45997 'al bayan plain': [
michael@0 45998 1,
michael@0 45999 0.5,
michael@0 46000 0
michael@0 46001 ],
michael@0 46002 'al bayan bold': [
michael@0 46003 1,
michael@0 46004 0.5833,
michael@0 46005 0
michael@0 46006 ],
michael@0 46007 'american typewriter': [
michael@0 46008 0.9167,
michael@0 46009 0.25,
michael@0 46010 0
michael@0 46011 ],
michael@0 46012 'american typewriter bold': [
michael@0 46013 0.9167,
michael@0 46014 0.25,
michael@0 46015 0
michael@0 46016 ],
michael@0 46017 'american typewriter condensed': [
michael@0 46018 0.9167,
michael@0 46019 0.25,
michael@0 46020 0
michael@0 46021 ],
michael@0 46022 'american typewriter condensed bold': [
michael@0 46023 0.9167,
michael@0 46024 0.25,
michael@0 46025 0
michael@0 46026 ],
michael@0 46027 'american typewriter condensed light': [
michael@0 46028 0.8333,
michael@0 46029 0.25,
michael@0 46030 0
michael@0 46031 ],
michael@0 46032 'american typewriter light': [
michael@0 46033 0.9167,
michael@0 46034 0.25,
michael@0 46035 0
michael@0 46036 ],
michael@0 46037 'andale mono': [
michael@0 46038 0.9167,
michael@0 46039 0.25,
michael@0 46040 0
michael@0 46041 ],
michael@0 46042 'apple symbols': [
michael@0 46043 0.6667,
michael@0 46044 0.25,
michael@0 46045 0
michael@0 46046 ],
michael@0 46047 'arial bold italic': [
michael@0 46048 0.9167,
michael@0 46049 0.25,
michael@0 46050 0
michael@0 46051 ],
michael@0 46052 'arial bold': [
michael@0 46053 0.9167,
michael@0 46054 0.25,
michael@0 46055 0
michael@0 46056 ],
michael@0 46057 'arial italic': [
michael@0 46058 0.9167,
michael@0 46059 0.25,
michael@0 46060 0
michael@0 46061 ],
michael@0 46062 'arial hebrew': [
michael@0 46063 0.75,
michael@0 46064 0.3333,
michael@0 46065 0
michael@0 46066 ],
michael@0 46067 'arial hebrew bold': [
michael@0 46068 0.75,
michael@0 46069 0.3333,
michael@0 46070 0
michael@0 46071 ],
michael@0 46072 'arial': [
michael@0 46073 0.9167,
michael@0 46074 0.25,
michael@0 46075 0
michael@0 46076 ],
michael@0 46077 'arial narrow': [
michael@0 46078 0.9167,
michael@0 46079 0.25,
michael@0 46080 0
michael@0 46081 ],
michael@0 46082 'arial narrow bold': [
michael@0 46083 0.9167,
michael@0 46084 0.25,
michael@0 46085 0
michael@0 46086 ],
michael@0 46087 'arial narrow bold italic': [
michael@0 46088 0.9167,
michael@0 46089 0.25,
michael@0 46090 0
michael@0 46091 ],
michael@0 46092 'arial narrow italic': [
michael@0 46093 0.9167,
michael@0 46094 0.25,
michael@0 46095 0
michael@0 46096 ],
michael@0 46097 'arial rounded mt bold': [
michael@0 46098 0.9167,
michael@0 46099 0.25,
michael@0 46100 0
michael@0 46101 ],
michael@0 46102 'arial unicode ms': [
michael@0 46103 1.0833,
michael@0 46104 0.25,
michael@0 46105 0
michael@0 46106 ],
michael@0 46107 'avenir black': [
michael@0 46108 1,
michael@0 46109 0.3333,
michael@0 46110 0
michael@0 46111 ],
michael@0 46112 'avenir black oblique': [
michael@0 46113 1,
michael@0 46114 0.3333,
michael@0 46115 0
michael@0 46116 ],
michael@0 46117 'avenir book': [
michael@0 46118 1,
michael@0 46119 0.3333,
michael@0 46120 0
michael@0 46121 ],
michael@0 46122 'avenir book oblique': [
michael@0 46123 1,
michael@0 46124 0.3333,
michael@0 46125 0
michael@0 46126 ],
michael@0 46127 'avenir heavy': [
michael@0 46128 1,
michael@0 46129 0.3333,
michael@0 46130 0
michael@0 46131 ],
michael@0 46132 'avenir heavy oblique': [
michael@0 46133 1,
michael@0 46134 0.3333,
michael@0 46135 0
michael@0 46136 ],
michael@0 46137 'avenir light': [
michael@0 46138 1,
michael@0 46139 0.3333,
michael@0 46140 0
michael@0 46141 ],
michael@0 46142 'avenir light oblique': [
michael@0 46143 1,
michael@0 46144 0.3333,
michael@0 46145 0
michael@0 46146 ],
michael@0 46147 'avenir medium': [
michael@0 46148 1,
michael@0 46149 0.3333,
michael@0 46150 0
michael@0 46151 ],
michael@0 46152 'avenir medium oblique': [
michael@0 46153 1,
michael@0 46154 0.3333,
michael@0 46155 0
michael@0 46156 ],
michael@0 46157 'avenir oblique': [
michael@0 46158 1,
michael@0 46159 0.3333,
michael@0 46160 0
michael@0 46161 ],
michael@0 46162 'avenir roman': [
michael@0 46163 1,
michael@0 46164 0.3333,
michael@0 46165 0
michael@0 46166 ],
michael@0 46167 'avenir next bold': [
michael@0 46168 1,
michael@0 46169 0.3333,
michael@0 46170 0
michael@0 46171 ],
michael@0 46172 'avenir next bold italic': [
michael@0 46173 1,
michael@0 46174 0.3333,
michael@0 46175 0
michael@0 46176 ],
michael@0 46177 'avenir next demi bold': [
michael@0 46178 1,
michael@0 46179 0.3333,
michael@0 46180 0
michael@0 46181 ],
michael@0 46182 'avenir next demi bold italic': [
michael@0 46183 1,
michael@0 46184 0.3333,
michael@0 46185 0
michael@0 46186 ],
michael@0 46187 'avenir next heavy': [
michael@0 46188 1,
michael@0 46189 0.3333,
michael@0 46190 0
michael@0 46191 ],
michael@0 46192 'avenir next heavy italic': [
michael@0 46193 1,
michael@0 46194 0.3333,
michael@0 46195 0
michael@0 46196 ],
michael@0 46197 'avenir next italic': [
michael@0 46198 1,
michael@0 46199 0.3333,
michael@0 46200 0
michael@0 46201 ],
michael@0 46202 'avenir next medium': [
michael@0 46203 1,
michael@0 46204 0.3333,
michael@0 46205 0
michael@0 46206 ],
michael@0 46207 'avenir next medium italic': [
michael@0 46208 1,
michael@0 46209 0.3333,
michael@0 46210 0
michael@0 46211 ],
michael@0 46212 'avenir next regular': [
michael@0 46213 1,
michael@0 46214 0.3333,
michael@0 46215 0
michael@0 46216 ],
michael@0 46217 'avenir next ultra light': [
michael@0 46218 1,
michael@0 46219 0.3333,
michael@0 46220 0
michael@0 46221 ],
michael@0 46222 'avenir next ultra light italic': [
michael@0 46223 1,
michael@0 46224 0.3333,
michael@0 46225 0
michael@0 46226 ],
michael@0 46227 'avenir next condensed bold': [
michael@0 46228 1,
michael@0 46229 0.3333,
michael@0 46230 0
michael@0 46231 ],
michael@0 46232 'avenir next condensed bold italic': [
michael@0 46233 1,
michael@0 46234 0.3333,
michael@0 46235 0
michael@0 46236 ],
michael@0 46237 'avenir next condensed demi bold': [
michael@0 46238 1,
michael@0 46239 0.3333,
michael@0 46240 0
michael@0 46241 ],
michael@0 46242 'avenir next condensed demi bold italic': [
michael@0 46243 1,
michael@0 46244 0.3333,
michael@0 46245 0
michael@0 46246 ],
michael@0 46247 'avenir next condensed heavy': [
michael@0 46248 1,
michael@0 46249 0.3333,
michael@0 46250 0
michael@0 46251 ],
michael@0 46252 'avenir next condensed heavy italic': [
michael@0 46253 1,
michael@0 46254 0.3333,
michael@0 46255 0
michael@0 46256 ],
michael@0 46257 'avenir next condensed italic': [
michael@0 46258 1,
michael@0 46259 0.3333,
michael@0 46260 0
michael@0 46261 ],
michael@0 46262 'avenir next condensed medium': [
michael@0 46263 1,
michael@0 46264 0.3333,
michael@0 46265 0
michael@0 46266 ],
michael@0 46267 'avenir next condensed medium italic': [
michael@0 46268 1,
michael@0 46269 0.3333,
michael@0 46270 0
michael@0 46271 ],
michael@0 46272 'avenir next condensed regular': [
michael@0 46273 1,
michael@0 46274 0.3333,
michael@0 46275 0
michael@0 46276 ],
michael@0 46277 'avenir next condensed ultra light': [
michael@0 46278 1,
michael@0 46279 0.3333,
michael@0 46280 0
michael@0 46281 ],
michael@0 46282 'avenir next condensed ultra light italic': [
michael@0 46283 1,
michael@0 46284 0.3333,
michael@0 46285 0
michael@0 46286 ],
michael@0 46287 'ayuthaya': [
michael@0 46288 1.0833,
michael@0 46289 0.3333,
michael@0 46290 0
michael@0 46291 ],
michael@0 46292 'baghdad': [
michael@0 46293 0.9167,
michael@0 46294 0.4167,
michael@0 46295 0
michael@0 46296 ],
michael@0 46297 'bangla mn': [
michael@0 46298 0.9167,
michael@0 46299 0.6667,
michael@0 46300 0
michael@0 46301 ],
michael@0 46302 'bangla mn bold': [
michael@0 46303 0.9167,
michael@0 46304 0.6667,
michael@0 46305 0
michael@0 46306 ],
michael@0 46307 'bangla sangam mn': [
michael@0 46308 0.9167,
michael@0 46309 0.4167,
michael@0 46310 0
michael@0 46311 ],
michael@0 46312 'bangla sangam mn bold': [
michael@0 46313 0.9167,
michael@0 46314 0.4167,
michael@0 46315 0
michael@0 46316 ],
michael@0 46317 'baskerville': [
michael@0 46318 0.9167,
michael@0 46319 0.25,
michael@0 46320 0
michael@0 46321 ],
michael@0 46322 'baskerville bold': [
michael@0 46323 0.9167,
michael@0 46324 0.25,
michael@0 46325 0
michael@0 46326 ],
michael@0 46327 'baskerville bold italic': [
michael@0 46328 0.9167,
michael@0 46329 0.25,
michael@0 46330 0
michael@0 46331 ],
michael@0 46332 'baskerville italic': [
michael@0 46333 0.9167,
michael@0 46334 0.25,
michael@0 46335 0
michael@0 46336 ],
michael@0 46337 'baskerville semibold': [
michael@0 46338 0.9167,
michael@0 46339 0.25,
michael@0 46340 0
michael@0 46341 ],
michael@0 46342 'baskerville semibold italic': [
michael@0 46343 0.9167,
michael@0 46344 0.25,
michael@0 46345 0
michael@0 46346 ],
michael@0 46347 'big caslon medium': [
michael@0 46348 0.9167,
michael@0 46349 0.25,
michael@0 46350 0
michael@0 46351 ],
michael@0 46352 'brush script mt italic': [
michael@0 46353 0.9167,
michael@0 46354 0.3333,
michael@0 46355 0
michael@0 46356 ],
michael@0 46357 'chalkboard': [
michael@0 46358 1,
michael@0 46359 0.25,
michael@0 46360 0
michael@0 46361 ],
michael@0 46362 'chalkboard bold': [
michael@0 46363 1,
michael@0 46364 0.25,
michael@0 46365 0
michael@0 46366 ],
michael@0 46367 'chalkboard se bold': [
michael@0 46368 1.1667,
michael@0 46369 0.25,
michael@0 46370 0
michael@0 46371 ],
michael@0 46372 'chalkboard se light': [
michael@0 46373 1.1667,
michael@0 46374 0.25,
michael@0 46375 0
michael@0 46376 ],
michael@0 46377 'chalkboard se regular': [
michael@0 46378 1.1667,
michael@0 46379 0.25,
michael@0 46380 0
michael@0 46381 ],
michael@0 46382 'chalkduster': [
michael@0 46383 1,
michael@0 46384 0.25,
michael@0 46385 0
michael@0 46386 ],
michael@0 46387 'charcoal cy': [
michael@0 46388 1,
michael@0 46389 0.25,
michael@0 46390 0
michael@0 46391 ],
michael@0 46392 'cochin': [
michael@0 46393 0.9167,
michael@0 46394 0.25,
michael@0 46395 0
michael@0 46396 ],
michael@0 46397 'cochin bold': [
michael@0 46398 0.9167,
michael@0 46399 0.25,
michael@0 46400 0
michael@0 46401 ],
michael@0 46402 'cochin bold italic': [
michael@0 46403 0.9167,
michael@0 46404 0.25,
michael@0 46405 0
michael@0 46406 ],
michael@0 46407 'cochin italic': [
michael@0 46408 0.9167,
michael@0 46409 0.25,
michael@0 46410 0
michael@0 46411 ],
michael@0 46412 'comic sans ms': [
michael@0 46413 1.0833,
michael@0 46414 0.25,
michael@0 46415 0
michael@0 46416 ],
michael@0 46417 'comic sans ms bold': [
michael@0 46418 1.0833,
michael@0 46419 0.25,
michael@0 46420 0
michael@0 46421 ],
michael@0 46422 'copperplate': [
michael@0 46423 0.75,
michael@0 46424 0.25,
michael@0 46425 0
michael@0 46426 ],
michael@0 46427 'copperplate bold': [
michael@0 46428 0.75,
michael@0 46429 0.25,
michael@0 46430 0
michael@0 46431 ],
michael@0 46432 'copperplate light': [
michael@0 46433 0.75,
michael@0 46434 0.25,
michael@0 46435 0
michael@0 46436 ],
michael@0 46437 'corsiva hebrew': [
michael@0 46438 0.6667,
michael@0 46439 0.3333,
michael@0 46440 0
michael@0 46441 ],
michael@0 46442 'corsiva hebrew bold': [
michael@0 46443 0.6667,
michael@0 46444 0.3333,
michael@0 46445 0
michael@0 46446 ],
michael@0 46447 'courier': [
michael@0 46448 0.75,
michael@0 46449 0.25,
michael@0 46450 0
michael@0 46451 ],
michael@0 46452 'courier bold': [
michael@0 46453 0.75,
michael@0 46454 0.25,
michael@0 46455 0
michael@0 46456 ],
michael@0 46457 'courier bold oblique': [
michael@0 46458 0.75,
michael@0 46459 0.25,
michael@0 46460 0
michael@0 46461 ],
michael@0 46462 'courier oblique': [
michael@0 46463 0.75,
michael@0 46464 0.25,
michael@0 46465 0
michael@0 46466 ],
michael@0 46467 'courier new bold italic': [
michael@0 46468 0.8333,
michael@0 46469 0.3333,
michael@0 46470 0
michael@0 46471 ],
michael@0 46472 'courier new bold': [
michael@0 46473 0.8333,
michael@0 46474 0.3333,
michael@0 46475 0
michael@0 46476 ],
michael@0 46477 'courier new italic': [
michael@0 46478 0.8333,
michael@0 46479 0.3333,
michael@0 46480 0
michael@0 46481 ],
michael@0 46482 'courier new': [
michael@0 46483 0.8333,
michael@0 46484 0.3333,
michael@0 46485 0
michael@0 46486 ],
michael@0 46487 'biaukai': [
michael@0 46488 0.8333,
michael@0 46489 0.1667,
michael@0 46490 0
michael@0 46491 ],
michael@0 46492 'damascus': [
michael@0 46493 0.5833,
michael@0 46494 0.4167,
michael@0 46495 0
michael@0 46496 ],
michael@0 46497 'damascus bold': [
michael@0 46498 0.5833,
michael@0 46499 0.4167,
michael@0 46500 0
michael@0 46501 ],
michael@0 46502 'decotype naskh': [
michael@0 46503 1.1667,
michael@0 46504 0.6667,
michael@0 46505 0
michael@0 46506 ],
michael@0 46507 'devanagari mt': [
michael@0 46508 0.9167,
michael@0 46509 0.6667,
michael@0 46510 0
michael@0 46511 ],
michael@0 46512 'devanagari mt bold': [
michael@0 46513 0.9167,
michael@0 46514 0.6667,
michael@0 46515 0
michael@0 46516 ],
michael@0 46517 'devanagari sangam mn': [
michael@0 46518 0.9167,
michael@0 46519 0.4167,
michael@0 46520 0
michael@0 46521 ],
michael@0 46522 'devanagari sangam mn bold': [
michael@0 46523 0.9167,
michael@0 46524 0.4167,
michael@0 46525 0
michael@0 46526 ],
michael@0 46527 'didot': [
michael@0 46528 0.9167,
michael@0 46529 0.3333,
michael@0 46530 0
michael@0 46531 ],
michael@0 46532 'didot bold': [
michael@0 46533 1,
michael@0 46534 0.3333,
michael@0 46535 0
michael@0 46536 ],
michael@0 46537 'didot italic': [
michael@0 46538 0.9167,
michael@0 46539 0.25,
michael@0 46540 0
michael@0 46541 ],
michael@0 46542 'euphemia ucas': [
michael@0 46543 1.0833,
michael@0 46544 0.25,
michael@0 46545 0
michael@0 46546 ],
michael@0 46547 'euphemia ucas bold': [
michael@0 46548 1.0833,
michael@0 46549 0.25,
michael@0 46550 0
michael@0 46551 ],
michael@0 46552 'euphemia ucas italic': [
michael@0 46553 1.0833,
michael@0 46554 0.25,
michael@0 46555 0
michael@0 46556 ],
michael@0 46557 'futura condensed extrabold': [
michael@0 46558 1,
michael@0 46559 0.25,
michael@0 46560 0
michael@0 46561 ],
michael@0 46562 'futura condensed medium': [
michael@0 46563 1,
michael@0 46564 0.25,
michael@0 46565 0
michael@0 46566 ],
michael@0 46567 'futura medium': [
michael@0 46568 1,
michael@0 46569 0.25,
michael@0 46570 0
michael@0 46571 ],
michael@0 46572 'futura medium italic': [
michael@0 46573 1,
michael@0 46574 0.25,
michael@0 46575 0
michael@0 46576 ],
michael@0 46577 'gb18030 bitmap': [
michael@0 46578 1,
michael@0 46579 0.6667,
michael@0 46580 0
michael@0 46581 ],
michael@0 46582 'geeza pro': [
michael@0 46583 0.9167,
michael@0 46584 0.3333,
michael@0 46585 0
michael@0 46586 ],
michael@0 46587 'geeza pro bold': [
michael@0 46588 0.9167,
michael@0 46589 0.3333,
michael@0 46590 0
michael@0 46591 ],
michael@0 46592 'geneva': [
michael@0 46593 1,
michael@0 46594 0.25,
michael@0 46595 0
michael@0 46596 ],
michael@0 46597 'geneva cy': [
michael@0 46598 1,
michael@0 46599 0.25,
michael@0 46600 0
michael@0 46601 ],
michael@0 46602 'georgia': [
michael@0 46603 0.9167,
michael@0 46604 0.25,
michael@0 46605 0
michael@0 46606 ],
michael@0 46607 'georgia bold': [
michael@0 46608 0.9167,
michael@0 46609 0.25,
michael@0 46610 0
michael@0 46611 ],
michael@0 46612 'georgia bold italic': [
michael@0 46613 0.9167,
michael@0 46614 0.25,
michael@0 46615 0
michael@0 46616 ],
michael@0 46617 'georgia italic': [
michael@0 46618 0.9167,
michael@0 46619 0.25,
michael@0 46620 0
michael@0 46621 ],
michael@0 46622 'gill sans': [
michael@0 46623 0.9167,
michael@0 46624 0.25,
michael@0 46625 0
michael@0 46626 ],
michael@0 46627 'gill sans bold': [
michael@0 46628 0.9167,
michael@0 46629 0.25,
michael@0 46630 0
michael@0 46631 ],
michael@0 46632 'gill sans bold italic': [
michael@0 46633 0.9167,
michael@0 46634 0.25,
michael@0 46635 0
michael@0 46636 ],
michael@0 46637 'gill sans italic': [
michael@0 46638 0.9167,
michael@0 46639 0.25,
michael@0 46640 0
michael@0 46641 ],
michael@0 46642 'gill sans light': [
michael@0 46643 0.9167,
michael@0 46644 0.25,
michael@0 46645 0
michael@0 46646 ],
michael@0 46647 'gill sans light italic': [
michael@0 46648 0.9167,
michael@0 46649 0.25,
michael@0 46650 0
michael@0 46651 ],
michael@0 46652 'gujarati mt': [
michael@0 46653 0.9167,
michael@0 46654 0.6667,
michael@0 46655 0
michael@0 46656 ],
michael@0 46657 'gujarati mt bold': [
michael@0 46658 0.9167,
michael@0 46659 0.6667,
michael@0 46660 0
michael@0 46661 ],
michael@0 46662 'gujarati sangam mn': [
michael@0 46663 0.8333,
michael@0 46664 0.4167,
michael@0 46665 0
michael@0 46666 ],
michael@0 46667 'gujarati sangam mn bold': [
michael@0 46668 0.8333,
michael@0 46669 0.4167,
michael@0 46670 0
michael@0 46671 ],
michael@0 46672 'gurmukhi mn': [
michael@0 46673 0.9167,
michael@0 46674 0.25,
michael@0 46675 0
michael@0 46676 ],
michael@0 46677 'gurmukhi mn bold': [
michael@0 46678 0.9167,
michael@0 46679 0.25,
michael@0 46680 0
michael@0 46681 ],
michael@0 46682 'gurmukhi sangam mn': [
michael@0 46683 0.9167,
michael@0 46684 0.3333,
michael@0 46685 0
michael@0 46686 ],
michael@0 46687 'gurmukhi sangam mn bold': [
michael@0 46688 0.9167,
michael@0 46689 0.3333,
michael@0 46690 0
michael@0 46691 ],
michael@0 46692 'helvetica': [
michael@0 46693 0.75,
michael@0 46694 0.25,
michael@0 46695 0
michael@0 46696 ],
michael@0 46697 'helvetica bold': [
michael@0 46698 0.75,
michael@0 46699 0.25,
michael@0 46700 0
michael@0 46701 ],
michael@0 46702 'helvetica bold oblique': [
michael@0 46703 0.75,
michael@0 46704 0.25,
michael@0 46705 0
michael@0 46706 ],
michael@0 46707 'helvetica light': [
michael@0 46708 0.75,
michael@0 46709 0.25,
michael@0 46710 0
michael@0 46711 ],
michael@0 46712 'helvetica light oblique': [
michael@0 46713 0.75,
michael@0 46714 0.25,
michael@0 46715 0
michael@0 46716 ],
michael@0 46717 'helvetica oblique': [
michael@0 46718 0.75,
michael@0 46719 0.25,
michael@0 46720 0
michael@0 46721 ],
michael@0 46722 'helvetica neue': [
michael@0 46723 0.9167,
michael@0 46724 0.25,
michael@0 46725 0
michael@0 46726 ],
michael@0 46727 'helvetica neue bold': [
michael@0 46728 1,
michael@0 46729 0.25,
michael@0 46730 0
michael@0 46731 ],
michael@0 46732 'helvetica neue bold italic': [
michael@0 46733 1,
michael@0 46734 0.25,
michael@0 46735 0
michael@0 46736 ],
michael@0 46737 'helvetica neue condensed black': [
michael@0 46738 1,
michael@0 46739 0.25,
michael@0 46740 0
michael@0 46741 ],
michael@0 46742 'helvetica neue condensed bold': [
michael@0 46743 1,
michael@0 46744 0.25,
michael@0 46745 0
michael@0 46746 ],
michael@0 46747 'helvetica neue italic': [
michael@0 46748 0.9167,
michael@0 46749 0.25,
michael@0 46750 0
michael@0 46751 ],
michael@0 46752 'helvetica neue light': [
michael@0 46753 1,
michael@0 46754 0.25,
michael@0 46755 0
michael@0 46756 ],
michael@0 46757 'helvetica neue light italic': [
michael@0 46758 0.9167,
michael@0 46759 0.25,
michael@0 46760 0
michael@0 46761 ],
michael@0 46762 'helvetica neue medium': [
michael@0 46763 1,
michael@0 46764 0.25,
michael@0 46765 0
michael@0 46766 ],
michael@0 46767 'helvetica neue ultralight': [
michael@0 46768 0.9167,
michael@0 46769 0.25,
michael@0 46770 0
michael@0 46771 ],
michael@0 46772 'helvetica neue ultralight italic': [
michael@0 46773 0.9167,
michael@0 46774 0.25,
michael@0 46775 0
michael@0 46776 ],
michael@0 46777 'herculanum': [
michael@0 46778 0.8333,
michael@0 46779 0.1667,
michael@0 46780 0
michael@0 46781 ],
michael@0 46782 'hiragino kaku gothic pro w3': [
michael@0 46783 0.9167,
michael@0 46784 0.0833,
michael@0 46785 0
michael@0 46786 ],
michael@0 46787 'hiragino kaku gothic pro w6': [
michael@0 46788 0.9167,
michael@0 46789 0.0833,
michael@0 46790 0
michael@0 46791 ],
michael@0 46792 'hiragino kaku gothic pron w3': [
michael@0 46793 0.9167,
michael@0 46794 0.0833,
michael@0 46795 0
michael@0 46796 ],
michael@0 46797 'hiragino kaku gothic pron w6': [
michael@0 46798 0.9167,
michael@0 46799 0.0833,
michael@0 46800 0
michael@0 46801 ],
michael@0 46802 'hiragino kaku gothic std w8': [
michael@0 46803 0.9167,
michael@0 46804 0.0833,
michael@0 46805 0
michael@0 46806 ],
michael@0 46807 'hiragino kaku gothic stdn w8': [
michael@0 46808 0.9167,
michael@0 46809 0.0833,
michael@0 46810 0
michael@0 46811 ],
michael@0 46812 'hiragino maru gothic pro w4': [
michael@0 46813 0.9167,
michael@0 46814 0.0833,
michael@0 46815 0
michael@0 46816 ],
michael@0 46817 'hiragino maru gothic pron w4': [
michael@0 46818 0.9167,
michael@0 46819 0.0833,
michael@0 46820 0
michael@0 46821 ],
michael@0 46822 'hiragino mincho pro w3': [
michael@0 46823 0.9167,
michael@0 46824 0.0833,
michael@0 46825 0
michael@0 46826 ],
michael@0 46827 'hiragino mincho pro w6': [
michael@0 46828 0.9167,
michael@0 46829 0.0833,
michael@0 46830 0
michael@0 46831 ],
michael@0 46832 'hiragino mincho pron w3': [
michael@0 46833 0.9167,
michael@0 46834 0.0833,
michael@0 46835 0
michael@0 46836 ],
michael@0 46837 'hiragino mincho pron w6': [
michael@0 46838 0.9167,
michael@0 46839 0.0833,
michael@0 46840 0
michael@0 46841 ],
michael@0 46842 'hiragino sans gb w3': [
michael@0 46843 0.9167,
michael@0 46844 0.0833,
michael@0 46845 0
michael@0 46846 ],
michael@0 46847 'hiragino sans gb w6': [
michael@0 46848 0.9167,
michael@0 46849 0.0833,
michael@0 46850 0
michael@0 46851 ],
michael@0 46852 'hoefler text black': [
michael@0 46853 0.75,
michael@0 46854 0.25,
michael@0 46855 0
michael@0 46856 ],
michael@0 46857 'hoefler text black italic': [
michael@0 46858 0.75,
michael@0 46859 0.25,
michael@0 46860 0
michael@0 46861 ],
michael@0 46862 'hoefler text italic': [
michael@0 46863 0.75,
michael@0 46864 0.25,
michael@0 46865 0
michael@0 46866 ],
michael@0 46867 'hoefler text ornaments': [
michael@0 46868 0.8333,
michael@0 46869 0.1667,
michael@0 46870 0
michael@0 46871 ],
michael@0 46872 'hoefler text': [
michael@0 46873 0.75,
michael@0 46874 0.25,
michael@0 46875 0
michael@0 46876 ],
michael@0 46877 'impact': [
michael@0 46878 1,
michael@0 46879 0.25,
michael@0 46880 0
michael@0 46881 ],
michael@0 46882 'inaimathi': [
michael@0 46883 0.8333,
michael@0 46884 0.4167,
michael@0 46885 0
michael@0 46886 ],
michael@0 46887 'headlinea regular': [
michael@0 46888 0.8333,
michael@0 46889 0.1667,
michael@0 46890 0
michael@0 46891 ],
michael@0 46892 'pilgi regular': [
michael@0 46893 0.8333,
michael@0 46894 0.25,
michael@0 46895 0
michael@0 46896 ],
michael@0 46897 'gungseo regular': [
michael@0 46898 0.8333,
michael@0 46899 0.25,
michael@0 46900 0
michael@0 46901 ],
michael@0 46902 'pcmyungjo regular': [
michael@0 46903 0.8333,
michael@0 46904 0.25,
michael@0 46905 0
michael@0 46906 ],
michael@0 46907 'kailasa regular': [
michael@0 46908 1.0833,
michael@0 46909 0.5833,
michael@0 46910 0
michael@0 46911 ],
michael@0 46912 'kannada mn': [
michael@0 46913 0.9167,
michael@0 46914 0.25,
michael@0 46915 0
michael@0 46916 ],
michael@0 46917 'kannada mn bold': [
michael@0 46918 0.9167,
michael@0 46919 0.25,
michael@0 46920 0
michael@0 46921 ],
michael@0 46922 'kannada sangam mn': [
michael@0 46923 1,
michael@0 46924 0.5833,
michael@0 46925 0
michael@0 46926 ],
michael@0 46927 'kannada sangam mn bold': [
michael@0 46928 1,
michael@0 46929 0.5833,
michael@0 46930 0
michael@0 46931 ],
michael@0 46932 'kefa bold': [
michael@0 46933 0.9167,
michael@0 46934 0.25,
michael@0 46935 0
michael@0 46936 ],
michael@0 46937 'kefa regular': [
michael@0 46938 0.9167,
michael@0 46939 0.25,
michael@0 46940 0
michael@0 46941 ],
michael@0 46942 'khmer mn': [
michael@0 46943 1,
michael@0 46944 0.6667,
michael@0 46945 0
michael@0 46946 ],
michael@0 46947 'khmer mn bold': [
michael@0 46948 1,
michael@0 46949 0.6667,
michael@0 46950 0
michael@0 46951 ],
michael@0 46952 'khmer sangam mn': [
michael@0 46953 1.0833,
michael@0 46954 0.6667,
michael@0 46955 0
michael@0 46956 ],
michael@0 46957 'kokonor regular': [
michael@0 46958 1.0833,
michael@0 46959 0.5833,
michael@0 46960 0
michael@0 46961 ],
michael@0 46962 'krungthep': [
michael@0 46963 1,
michael@0 46964 0.25,
michael@0 46965 0
michael@0 46966 ],
michael@0 46967 'kufistandardgk': [
michael@0 46968 0.9167,
michael@0 46969 0.5,
michael@0 46970 0
michael@0 46971 ],
michael@0 46972 'lao mn': [
michael@0 46973 0.9167,
michael@0 46974 0.4167,
michael@0 46975 0
michael@0 46976 ],
michael@0 46977 'lao mn bold': [
michael@0 46978 0.9167,
michael@0 46979 0.4167,
michael@0 46980 0
michael@0 46981 ],
michael@0 46982 'lao sangam mn': [
michael@0 46983 1,
michael@0 46984 0.3333,
michael@0 46985 0
michael@0 46986 ],
michael@0 46987 'apple ligothic medium': [
michael@0 46988 0.8333,
michael@0 46989 0.1667,
michael@0 46990 0
michael@0 46991 ],
michael@0 46992 'lihei pro': [
michael@0 46993 0.8333,
michael@0 46994 0.1667,
michael@0 46995 0
michael@0 46996 ],
michael@0 46997 'lisong pro': [
michael@0 46998 0.8333,
michael@0 46999 0.1667,
michael@0 47000 0
michael@0 47001 ],
michael@0 47002 'lucida grande': [
michael@0 47003 1,
michael@0 47004 0.25,
michael@0 47005 0
michael@0 47006 ],
michael@0 47007 'lucida grande bold': [
michael@0 47008 1,
michael@0 47009 0.25,
michael@0 47010 0
michael@0 47011 ],
michael@0 47012 'malayalam mn': [
michael@0 47013 1,
michael@0 47014 0.4167,
michael@0 47015 0
michael@0 47016 ],
michael@0 47017 'malayalam mn bold': [
michael@0 47018 1,
michael@0 47019 0.4167,
michael@0 47020 0
michael@0 47021 ],
michael@0 47022 'malayalam sangam mn': [
michael@0 47023 0.8333,
michael@0 47024 0.4167,
michael@0 47025 0
michael@0 47026 ],
michael@0 47027 'malayalam sangam mn bold': [
michael@0 47028 0.8333,
michael@0 47029 0.4167,
michael@0 47030 0
michael@0 47031 ],
michael@0 47032 'marion bold': [
michael@0 47033 0.6667,
michael@0 47034 0.3333,
michael@0 47035 0
michael@0 47036 ],
michael@0 47037 'marion italic': [
michael@0 47038 0.6667,
michael@0 47039 0.3333,
michael@0 47040 0
michael@0 47041 ],
michael@0 47042 'marion regular': [
michael@0 47043 0.6667,
michael@0 47044 0.3333,
michael@0 47045 0
michael@0 47046 ],
michael@0 47047 'marker felt thin': [
michael@0 47048 0.8333,
michael@0 47049 0.25,
michael@0 47050 0
michael@0 47051 ],
michael@0 47052 'marker felt wide': [
michael@0 47053 0.9167,
michael@0 47054 0.25,
michael@0 47055 0
michael@0 47056 ],
michael@0 47057 'menlo bold': [
michael@0 47058 0.9167,
michael@0 47059 0.25,
michael@0 47060 0
michael@0 47061 ],
michael@0 47062 'menlo bold italic': [
michael@0 47063 0.9167,
michael@0 47064 0.25,
michael@0 47065 0
michael@0 47066 ],
michael@0 47067 'menlo italic': [
michael@0 47068 0.9167,
michael@0 47069 0.25,
michael@0 47070 0
michael@0 47071 ],
michael@0 47072 'menlo regular': [
michael@0 47073 0.9167,
michael@0 47074 0.25,
michael@0 47075 0
michael@0 47076 ],
michael@0 47077 'microsoft sans serif': [
michael@0 47078 0.9167,
michael@0 47079 0.25,
michael@0 47080 0
michael@0 47081 ],
michael@0 47082 'monaco': [
michael@0 47083 1,
michael@0 47084 0.25,
michael@0 47085 0
michael@0 47086 ],
michael@0 47087 'gurmukhi mt': [
michael@0 47088 0.8333,
michael@0 47089 0.4167,
michael@0 47090 0
michael@0 47091 ],
michael@0 47092 'mshtakan': [
michael@0 47093 0.9167,
michael@0 47094 0.25,
michael@0 47095 0
michael@0 47096 ],
michael@0 47097 'mshtakan bold': [
michael@0 47098 0.9167,
michael@0 47099 0.25,
michael@0 47100 0
michael@0 47101 ],
michael@0 47102 'mshtakan boldoblique': [
michael@0 47103 0.9167,
michael@0 47104 0.25,
michael@0 47105 0
michael@0 47106 ],
michael@0 47107 'mshtakan oblique': [
michael@0 47108 0.9167,
michael@0 47109 0.25,
michael@0 47110 0
michael@0 47111 ],
michael@0 47112 'myanmar mn': [
michael@0 47113 1,
michael@0 47114 0.4167,
michael@0 47115 0
michael@0 47116 ],
michael@0 47117 'myanmar mn bold': [
michael@0 47118 1,
michael@0 47119 0.4167,
michael@0 47120 0
michael@0 47121 ],
michael@0 47122 'myanmar sangam mn': [
michael@0 47123 0.9167,
michael@0 47124 0.4167,
michael@0 47125 0
michael@0 47126 ],
michael@0 47127 'nadeem': [
michael@0 47128 0.9167,
michael@0 47129 0.4167,
michael@0 47130 0
michael@0 47131 ],
michael@0 47132 'nanum brush script': [
michael@0 47133 0.9167,
michael@0 47134 0.25,
michael@0 47135 0
michael@0 47136 ],
michael@0 47137 'nanumgothic': [
michael@0 47138 0.9167,
michael@0 47139 0.25,
michael@0 47140 0
michael@0 47141 ],
michael@0 47142 'nanumgothic bold': [
michael@0 47143 0.9167,
michael@0 47144 0.25,
michael@0 47145 0
michael@0 47146 ],
michael@0 47147 'nanumgothic extrabold': [
michael@0 47148 0.9167,
michael@0 47149 0.25,
michael@0 47150 0
michael@0 47151 ],
michael@0 47152 'nanummyeongjo': [
michael@0 47153 0.9167,
michael@0 47154 0.25,
michael@0 47155 0
michael@0 47156 ],
michael@0 47157 'nanummyeongjo bold': [
michael@0 47158 0.9167,
michael@0 47159 0.25,
michael@0 47160 0
michael@0 47161 ],
michael@0 47162 'nanummyeongjo extrabold': [
michael@0 47163 0.9167,
michael@0 47164 0.25,
michael@0 47165 0
michael@0 47166 ],
michael@0 47167 'nanum pen script': [
michael@0 47168 0.9167,
michael@0 47169 0.25,
michael@0 47170 0
michael@0 47171 ],
michael@0 47172 'optima bold': [
michael@0 47173 0.9167,
michael@0 47174 0.25,
michael@0 47175 0
michael@0 47176 ],
michael@0 47177 'optima bold italic': [
michael@0 47178 0.9167,
michael@0 47179 0.25,
michael@0 47180 0
michael@0 47181 ],
michael@0 47182 'optima extrablack': [
michael@0 47183 1,
michael@0 47184 0.25,
michael@0 47185 0
michael@0 47186 ],
michael@0 47187 'optima italic': [
michael@0 47188 0.9167,
michael@0 47189 0.25,
michael@0 47190 0
michael@0 47191 ],
michael@0 47192 'optima regular': [
michael@0 47193 0.9167,
michael@0 47194 0.25,
michael@0 47195 0
michael@0 47196 ],
michael@0 47197 'oriya mn': [
michael@0 47198 0.9167,
michael@0 47199 0.25,
michael@0 47200 0
michael@0 47201 ],
michael@0 47202 'oriya mn bold': [
michael@0 47203 0.9167,
michael@0 47204 0.25,
michael@0 47205 0
michael@0 47206 ],
michael@0 47207 'oriya sangam mn': [
michael@0 47208 0.8333,
michael@0 47209 0.4167,
michael@0 47210 0
michael@0 47211 ],
michael@0 47212 'oriya sangam mn bold': [
michael@0 47213 0.8333,
michael@0 47214 0.4167,
michael@0 47215 0
michael@0 47216 ],
michael@0 47217 'osaka': [
michael@0 47218 1,
michael@0 47219 0.25,
michael@0 47220 0
michael@0 47221 ],
michael@0 47222 'osaka-mono': [
michael@0 47223 0.8333,
michael@0 47224 0.1667,
michael@0 47225 0
michael@0 47226 ],
michael@0 47227 'palatino bold': [
michael@0 47228 0.8333,
michael@0 47229 0.25,
michael@0 47230 0
michael@0 47231 ],
michael@0 47232 'palatino bold italic': [
michael@0 47233 0.8333,
michael@0 47234 0.25,
michael@0 47235 0
michael@0 47236 ],
michael@0 47237 'palatino italic': [
michael@0 47238 0.8333,
michael@0 47239 0.25,
michael@0 47240 0
michael@0 47241 ],
michael@0 47242 'palatino': [
michael@0 47243 0.8333,
michael@0 47244 0.25,
michael@0 47245 0
michael@0 47246 ],
michael@0 47247 'papyrus': [
michael@0 47248 0.9167,
michael@0 47249 0.5833,
michael@0 47250 0
michael@0 47251 ],
michael@0 47252 'papyrus condensed': [
michael@0 47253 0.9167,
michael@0 47254 0.5833,
michael@0 47255 0
michael@0 47256 ],
michael@0 47257 'plantagenet cherokee': [
michael@0 47258 0.6667,
michael@0 47259 0.25,
michael@0 47260 0
michael@0 47261 ],
michael@0 47262 'raanana': [
michael@0 47263 0.75,
michael@0 47264 0.25,
michael@0 47265 0
michael@0 47266 ],
michael@0 47267 'raanana bold': [
michael@0 47268 0.75,
michael@0 47269 0.25,
michael@0 47270 0
michael@0 47271 ],
michael@0 47272 'hei regular': [
michael@0 47273 0.8333,
michael@0 47274 0.1667,
michael@0 47275 0
michael@0 47276 ],
michael@0 47277 'kai regular': [
michael@0 47278 0.8333,
michael@0 47279 0.1667,
michael@0 47280 0
michael@0 47281 ],
michael@0 47282 'stfangsong': [
michael@0 47283 0.8333,
michael@0 47284 0.1667,
michael@0 47285 0
michael@0 47286 ],
michael@0 47287 'stheiti': [
michael@0 47288 0.8333,
michael@0 47289 0.1667,
michael@0 47290 0
michael@0 47291 ],
michael@0 47292 'heiti sc light': [
michael@0 47293 0.8333,
michael@0 47294 0.1667,
michael@0 47295 0
michael@0 47296 ],
michael@0 47297 'heiti sc medium': [
michael@0 47298 0.8333,
michael@0 47299 0.1667,
michael@0 47300 0
michael@0 47301 ],
michael@0 47302 'heiti tc light': [
michael@0 47303 0.8333,
michael@0 47304 0.1667,
michael@0 47305 0
michael@0 47306 ],
michael@0 47307 'heiti tc medium': [
michael@0 47308 0.8333,
michael@0 47309 0.1667,
michael@0 47310 0
michael@0 47311 ],
michael@0 47312 'stkaiti': [
michael@0 47313 0.8333,
michael@0 47314 0.1667,
michael@0 47315 0
michael@0 47316 ],
michael@0 47317 'kaiti sc black': [
michael@0 47318 1.0833,
michael@0 47319 0.3333,
michael@0 47320 0
michael@0 47321 ],
michael@0 47322 'kaiti sc bold': [
michael@0 47323 1.0833,
michael@0 47324 0.3333,
michael@0 47325 0
michael@0 47326 ],
michael@0 47327 'kaiti sc regular': [
michael@0 47328 1.0833,
michael@0 47329 0.3333,
michael@0 47330 0
michael@0 47331 ],
michael@0 47332 'stsong': [
michael@0 47333 0.8333,
michael@0 47334 0.1667,
michael@0 47335 0
michael@0 47336 ],
michael@0 47337 'songti sc black': [
michael@0 47338 1.0833,
michael@0 47339 0.3333,
michael@0 47340 0
michael@0 47341 ],
michael@0 47342 'songti sc bold': [
michael@0 47343 1.0833,
michael@0 47344 0.3333,
michael@0 47345 0
michael@0 47346 ],
michael@0 47347 'songti sc light': [
michael@0 47348 1.0833,
michael@0 47349 0.3333,
michael@0 47350 0
michael@0 47351 ],
michael@0 47352 'songti sc regular': [
michael@0 47353 1.0833,
michael@0 47354 0.3333,
michael@0 47355 0
michael@0 47356 ],
michael@0 47357 'stxihei': [
michael@0 47358 0.8333,
michael@0 47359 0.1667,
michael@0 47360 0
michael@0 47361 ],
michael@0 47362 'sathu': [
michael@0 47363 0.9167,
michael@0 47364 0.3333,
michael@0 47365 0
michael@0 47366 ],
michael@0 47367 'silom': [
michael@0 47368 1,
michael@0 47369 0.3333,
michael@0 47370 0
michael@0 47371 ],
michael@0 47372 'sinhala mn': [
michael@0 47373 0.9167,
michael@0 47374 0.25,
michael@0 47375 0
michael@0 47376 ],
michael@0 47377 'sinhala mn bold': [
michael@0 47378 0.9167,
michael@0 47379 0.25,
michael@0 47380 0
michael@0 47381 ],
michael@0 47382 'sinhala sangam mn': [
michael@0 47383 1.1667,
michael@0 47384 0.3333,
michael@0 47385 0
michael@0 47386 ],
michael@0 47387 'sinhala sangam mn bold': [
michael@0 47388 1.1667,
michael@0 47389 0.3333,
michael@0 47390 0
michael@0 47391 ],
michael@0 47392 'skia regular': [
michael@0 47393 0.75,
michael@0 47394 0.25,
michael@0 47395 0
michael@0 47396 ],
michael@0 47397 'symbol': [
michael@0 47398 0.6667,
michael@0 47399 0.3333,
michael@0 47400 0
michael@0 47401 ],
michael@0 47402 'tahoma negreta': [
michael@0 47403 1,
michael@0 47404 0.1667,
michael@0 47405 0
michael@0 47406 ],
michael@0 47407 'tamil mn': [
michael@0 47408 0.9167,
michael@0 47409 0.25,
michael@0 47410 0
michael@0 47411 ],
michael@0 47412 'tamil mn bold': [
michael@0 47413 0.9167,
michael@0 47414 0.25,
michael@0 47415 0
michael@0 47416 ],
michael@0 47417 'tamil sangam mn': [
michael@0 47418 0.75,
michael@0 47419 0.25,
michael@0 47420 0
michael@0 47421 ],
michael@0 47422 'tamil sangam mn bold': [
michael@0 47423 0.75,
michael@0 47424 0.25,
michael@0 47425 0
michael@0 47426 ],
michael@0 47427 'telugu mn': [
michael@0 47428 0.9167,
michael@0 47429 0.25,
michael@0 47430 0
michael@0 47431 ],
michael@0 47432 'telugu mn bold': [
michael@0 47433 0.9167,
michael@0 47434 0.25,
michael@0 47435 0
michael@0 47436 ],
michael@0 47437 'telugu sangam mn': [
michael@0 47438 1,
michael@0 47439 0.5833,
michael@0 47440 0
michael@0 47441 ],
michael@0 47442 'telugu sangam mn bold': [
michael@0 47443 1,
michael@0 47444 0.5833,
michael@0 47445 0
michael@0 47446 ],
michael@0 47447 'thonburi': [
michael@0 47448 1.0833,
michael@0 47449 0.25,
michael@0 47450 0
michael@0 47451 ],
michael@0 47452 'thonburi bold': [
michael@0 47453 1.0833,
michael@0 47454 0.25,
michael@0 47455 0
michael@0 47456 ],
michael@0 47457 'times bold': [
michael@0 47458 0.75,
michael@0 47459 0.25,
michael@0 47460 0
michael@0 47461 ],
michael@0 47462 'times bold italic': [
michael@0 47463 0.75,
michael@0 47464 0.25,
michael@0 47465 0
michael@0 47466 ],
michael@0 47467 'times italic': [
michael@0 47468 0.75,
michael@0 47469 0.25,
michael@0 47470 0
michael@0 47471 ],
michael@0 47472 'times roman': [
michael@0 47473 0.75,
michael@0 47474 0.25,
michael@0 47475 0
michael@0 47476 ],
michael@0 47477 'times new roman bold italic': [
michael@0 47478 0.9167,
michael@0 47479 0.25,
michael@0 47480 0
michael@0 47481 ],
michael@0 47482 'times new roman bold': [
michael@0 47483 0.9167,
michael@0 47484 0.25,
michael@0 47485 0
michael@0 47486 ],
michael@0 47487 'times new roman italic': [
michael@0 47488 0.9167,
michael@0 47489 0.25,
michael@0 47490 0
michael@0 47491 ],
michael@0 47492 'times new roman': [
michael@0 47493 0.9167,
michael@0 47494 0.25,
michael@0 47495 0
michael@0 47496 ],
michael@0 47497 'trebuchet ms bold italic': [
michael@0 47498 0.9167,
michael@0 47499 0.25,
michael@0 47500 0
michael@0 47501 ],
michael@0 47502 'trebuchet ms': [
michael@0 47503 0.9167,
michael@0 47504 0.25,
michael@0 47505 0
michael@0 47506 ],
michael@0 47507 'trebuchet ms bold': [
michael@0 47508 0.9167,
michael@0 47509 0.25,
michael@0 47510 0
michael@0 47511 ],
michael@0 47512 'trebuchet ms italic': [
michael@0 47513 0.9167,
michael@0 47514 0.25,
michael@0 47515 0
michael@0 47516 ],
michael@0 47517 'verdana': [
michael@0 47518 1,
michael@0 47519 0.25,
michael@0 47520 0
michael@0 47521 ],
michael@0 47522 'verdana bold': [
michael@0 47523 1,
michael@0 47524 0.25,
michael@0 47525 0
michael@0 47526 ],
michael@0 47527 'verdana bold italic': [
michael@0 47528 1,
michael@0 47529 0.25,
michael@0 47530 0
michael@0 47531 ],
michael@0 47532 'verdana italic': [
michael@0 47533 1,
michael@0 47534 0.25,
michael@0 47535 0
michael@0 47536 ],
michael@0 47537 'webdings': [
michael@0 47538 0.8333,
michael@0 47539 0.1667,
michael@0 47540 0
michael@0 47541 ],
michael@0 47542 'wingdings 2': [
michael@0 47543 0.8333,
michael@0 47544 0.25,
michael@0 47545 0
michael@0 47546 ],
michael@0 47547 'wingdings 3': [
michael@0 47548 0.9167,
michael@0 47549 0.25,
michael@0 47550 0
michael@0 47551 ],
michael@0 47552 'yuppy sc regular': [
michael@0 47553 1.0833,
michael@0 47554 0.3333,
michael@0 47555 0
michael@0 47556 ],
michael@0 47557 'yuppy tc regular': [
michael@0 47558 1.0833,
michael@0 47559 0.3333,
michael@0 47560 0
michael@0 47561 ],
michael@0 47562 'zapf dingbats': [
michael@0 47563 0.8333,
michael@0 47564 0.1667,
michael@0 47565 0
michael@0 47566 ],
michael@0 47567 'zapfino': [
michael@0 47568 1.9167,
michael@0 47569 1.5,
michael@0 47570 0
michael@0 47571 ]
michael@0 47572 };
michael@0 47573 var DEVICE_FONT_METRICS_LINUX = {
michael@0 47574 'kacstfarsi': [
michael@0 47575 1.0831,
michael@0 47576 0.5215,
michael@0 47577 0
michael@0 47578 ],
michael@0 47579 'meera': [
michael@0 47580 0.682,
michael@0 47581 0.4413,
michael@0 47582 0
michael@0 47583 ],
michael@0 47584 'freemono': [
michael@0 47585 0.8023,
michael@0 47586 0.2006,
michael@0 47587 0
michael@0 47588 ],
michael@0 47589 'undotum': [
michael@0 47590 1.0029,
michael@0 47591 0.2808,
michael@0 47592 0
michael@0 47593 ],
michael@0 47594 'loma': [
michael@0 47595 1.1634,
michael@0 47596 0.4814,
michael@0 47597 0
michael@0 47598 ],
michael@0 47599 'century schoolbook l': [
michael@0 47600 1.0029,
michael@0 47601 0.3209,
michael@0 47602 0
michael@0 47603 ],
michael@0 47604 'kacsttitlel': [
michael@0 47605 1.0831,
michael@0 47606 0.5215,
michael@0 47607 0
michael@0 47608 ],
michael@0 47609 'undinaru': [
michael@0 47610 1.0029,
michael@0 47611 0.2407,
michael@0 47612 0
michael@0 47613 ],
michael@0 47614 'ungungseo': [
michael@0 47615 1.0029,
michael@0 47616 0.2808,
michael@0 47617 0
michael@0 47618 ],
michael@0 47619 'garuda': [
michael@0 47620 1.3238,
michael@0 47621 0.6017,
michael@0 47622 0
michael@0 47623 ],
michael@0 47624 'rekha': [
michael@0 47625 1.1232,
michael@0 47626 0.2808,
michael@0 47627 0
michael@0 47628 ],
michael@0 47629 'purisa': [
michael@0 47630 1.1232,
michael@0 47631 0.5215,
michael@0 47632 0
michael@0 47633 ],
michael@0 47634 'dejavu sans mono': [
michael@0 47635 0.9628,
michael@0 47636 0.2407,
michael@0 47637 0
michael@0 47638 ],
michael@0 47639 'vemana2000': [
michael@0 47640 0.8825,
michael@0 47641 0.8424,
michael@0 47642 0
michael@0 47643 ],
michael@0 47644 'kacstoffice': [
michael@0 47645 1.0831,
michael@0 47646 0.5215,
michael@0 47647 0
michael@0 47648 ],
michael@0 47649 'umpush': [
michael@0 47650 1.2837,
michael@0 47651 0.682,
michael@0 47652 0
michael@0 47653 ],
michael@0 47654 'opensymbol': [
michael@0 47655 0.8023,
michael@0 47656 0.2006,
michael@0 47657 0
michael@0 47658 ],
michael@0 47659 'sawasdee': [
michael@0 47660 1.1232,
michael@0 47661 0.4413,
michael@0 47662 0
michael@0 47663 ],
michael@0 47664 'urw palladio l': [
michael@0 47665 1.0029,
michael@0 47666 0.3209,
michael@0 47667 0
michael@0 47668 ],
michael@0 47669 'freeserif': [
michael@0 47670 0.9227,
michael@0 47671 0.3209,
michael@0 47672 0
michael@0 47673 ],
michael@0 47674 'kacstdigital': [
michael@0 47675 1.0831,
michael@0 47676 0.5215,
michael@0 47677 0
michael@0 47678 ],
michael@0 47679 'ubuntu condensed': [
michael@0 47680 0.9628,
michael@0 47681 0.2006,
michael@0 47682 0
michael@0 47683 ],
michael@0 47684 'unpilgi': [
michael@0 47685 1.0029,
michael@0 47686 0.4413,
michael@0 47687 0
michael@0 47688 ],
michael@0 47689 'mry_kacstqurn': [
michael@0 47690 1.4442,
michael@0 47691 0.7221,
michael@0 47692 0
michael@0 47693 ],
michael@0 47694 'urw gothic l': [
michael@0 47695 1.0029,
michael@0 47696 0.2407,
michael@0 47697 0
michael@0 47698 ],
michael@0 47699 'dingbats': [
michael@0 47700 0.8424,
michael@0 47701 0.1605,
michael@0 47702 0
michael@0 47703 ],
michael@0 47704 'urw chancery l': [
michael@0 47705 1.0029,
michael@0 47706 0.3209,
michael@0 47707 0
michael@0 47708 ],
michael@0 47709 'phetsarath ot': [
michael@0 47710 1.0831,
michael@0 47711 0.5215,
michael@0 47712 0
michael@0 47713 ],
michael@0 47714 'tlwg typist': [
michael@0 47715 0.8825,
michael@0 47716 0.4012,
michael@0 47717 0
michael@0 47718 ],
michael@0 47719 'kacstletter': [
michael@0 47720 1.0831,
michael@0 47721 0.5215,
michael@0 47722 0
michael@0 47723 ],
michael@0 47724 'utkal': [
michael@0 47725 1.2035,
michael@0 47726 0.6418,
michael@0 47727 0
michael@0 47728 ],
michael@0 47729 'dejavu sans light': [
michael@0 47730 0.9628,
michael@0 47731 0.2407,
michael@0 47732 0
michael@0 47733 ],
michael@0 47734 'norasi': [
michael@0 47735 1.2436,
michael@0 47736 0.5215,
michael@0 47737 0
michael@0 47738 ],
michael@0 47739 'dejavu serif condensed': [
michael@0 47740 0.9628,
michael@0 47741 0.2407,
michael@0 47742 0
michael@0 47743 ],
michael@0 47744 'kacstone': [
michael@0 47745 1.2436,
michael@0 47746 0.6418,
michael@0 47747 0
michael@0 47748 ],
michael@0 47749 'liberation sans narrow': [
michael@0 47750 0.9628,
michael@0 47751 0.2407,
michael@0 47752 0
michael@0 47753 ],
michael@0 47754 'symbol': [
michael@0 47755 1.043,
michael@0 47756 0.3209,
michael@0 47757 0
michael@0 47758 ],
michael@0 47759 'nanummyeongjo': [
michael@0 47760 0.9227,
michael@0 47761 0.2407,
michael@0 47762 0
michael@0 47763 ],
michael@0 47764 'untitled1': [
michael@0 47765 0.682,
michael@0 47766 0.5616,
michael@0 47767 0
michael@0 47768 ],
michael@0 47769 'lohit gujarati': [
michael@0 47770 0.9628,
michael@0 47771 0.4012,
michael@0 47772 0
michael@0 47773 ],
michael@0 47774 'liberation mono': [
michael@0 47775 0.8424,
michael@0 47776 0.3209,
michael@0 47777 0
michael@0 47778 ],
michael@0 47779 'kacstart': [
michael@0 47780 1.0831,
michael@0 47781 0.5215,
michael@0 47782 0
michael@0 47783 ],
michael@0 47784 'mallige': [
michael@0 47785 1.0029,
michael@0 47786 0.682,
michael@0 47787 0
michael@0 47788 ],
michael@0 47789 'bitstream charter': [
michael@0 47790 1.0029,
michael@0 47791 0.2407,
michael@0 47792 0
michael@0 47793 ],
michael@0 47794 'nanumgothic': [
michael@0 47795 0.9227,
michael@0 47796 0.2407,
michael@0 47797 0
michael@0 47798 ],
michael@0 47799 'liberation serif': [
michael@0 47800 0.9227,
michael@0 47801 0.2407,
michael@0 47802 0
michael@0 47803 ],
michael@0 47804 'dejavu sans condensed': [
michael@0 47805 0.9628,
michael@0 47806 0.2407,
michael@0 47807 0
michael@0 47808 ],
michael@0 47809 'ubuntu': [
michael@0 47810 0.9628,
michael@0 47811 0.2006,
michael@0 47812 0
michael@0 47813 ],
michael@0 47814 'courier 10 pitch': [
michael@0 47815 0.8825,
michael@0 47816 0.3209,
michael@0 47817 0
michael@0 47818 ],
michael@0 47819 'nimbus sans l': [
michael@0 47820 0.9628,
michael@0 47821 0.3209,
michael@0 47822 0
michael@0 47823 ],
michael@0 47824 'takaopgothic': [
michael@0 47825 0.8825,
michael@0 47826 0.2006,
michael@0 47827 0
michael@0 47828 ],
michael@0 47829 'wenquanyi micro hei mono': [
michael@0 47830 0.9628,
michael@0 47831 0.2407,
michael@0 47832 0
michael@0 47833 ],
michael@0 47834 'dejavu sans': [
michael@0 47835 0.9628,
michael@0 47836 0.2407,
michael@0 47837 0
michael@0 47838 ],
michael@0 47839 'kedage': [
michael@0 47840 1.0029,
michael@0 47841 0.682,
michael@0 47842 0
michael@0 47843 ],
michael@0 47844 'kinnari': [
michael@0 47845 1.3238,
michael@0 47846 0.5215,
michael@0 47847 0
michael@0 47848 ],
michael@0 47849 'tlwgmono': [
michael@0 47850 0.8825,
michael@0 47851 0.4012,
michael@0 47852 0
michael@0 47853 ],
michael@0 47854 'standard symbols l': [
michael@0 47855 1.043,
michael@0 47856 0.3209,
michael@0 47857 0
michael@0 47858 ],
michael@0 47859 'lohit punjabi': [
michael@0 47860 1.2035,
michael@0 47861 0.682,
michael@0 47862 0
michael@0 47863 ],
michael@0 47864 'nimbus mono l': [
michael@0 47865 0.8424,
michael@0 47866 0.2808,
michael@0 47867 0
michael@0 47868 ],
michael@0 47869 'rachana': [
michael@0 47870 0.682,
michael@0 47871 0.5616,
michael@0 47872 0
michael@0 47873 ],
michael@0 47874 'waree': [
michael@0 47875 1.2436,
michael@0 47876 0.4413,
michael@0 47877 0
michael@0 47878 ],
michael@0 47879 'kacstposter': [
michael@0 47880 1.0831,
michael@0 47881 0.5215,
michael@0 47882 0
michael@0 47883 ],
michael@0 47884 'khmer os': [
michael@0 47885 1.2837,
michael@0 47886 0.7622,
michael@0 47887 0
michael@0 47888 ],
michael@0 47889 'freesans': [
michael@0 47890 1.0029,
michael@0 47891 0.3209,
michael@0 47892 0
michael@0 47893 ],
michael@0 47894 'gargi': [
michael@0 47895 0.9628,
michael@0 47896 0.2808,
michael@0 47897 0
michael@0 47898 ],
michael@0 47899 'nimbus roman no9 l': [
michael@0 47900 0.9628,
michael@0 47901 0.3209,
michael@0 47902 0
michael@0 47903 ],
michael@0 47904 'dejavu serif': [
michael@0 47905 0.9628,
michael@0 47906 0.2407,
michael@0 47907 0
michael@0 47908 ],
michael@0 47909 'wenquanyi micro hei': [
michael@0 47910 0.9628,
michael@0 47911 0.2407,
michael@0 47912 0
michael@0 47913 ],
michael@0 47914 'ubuntu light': [
michael@0 47915 0.9628,
michael@0 47916 0.2006,
michael@0 47917 0
michael@0 47918 ],
michael@0 47919 'tlwgtypewriter': [
michael@0 47920 0.9227,
michael@0 47921 0.4012,
michael@0 47922 0
michael@0 47923 ],
michael@0 47924 'kacstpen': [
michael@0 47925 1.0831,
michael@0 47926 0.5215,
michael@0 47927 0
michael@0 47928 ],
michael@0 47929 'tlwg typo': [
michael@0 47930 0.8825,
michael@0 47931 0.4012,
michael@0 47932 0
michael@0 47933 ],
michael@0 47934 'mukti narrow': [
michael@0 47935 1.2837,
michael@0 47936 0.4413,
michael@0 47937 0
michael@0 47938 ],
michael@0 47939 'ubuntu mono': [
michael@0 47940 0.8424,
michael@0 47941 0.2006,
michael@0 47942 0
michael@0 47943 ],
michael@0 47944 'lohit bengali': [
michael@0 47945 1.0029,
michael@0 47946 0.4413,
michael@0 47947 0
michael@0 47948 ],
michael@0 47949 'liberation sans': [
michael@0 47950 0.9227,
michael@0 47951 0.2407,
michael@0 47952 0
michael@0 47953 ],
michael@0 47954 'unbatang': [
michael@0 47955 1.0029,
michael@0 47956 0.2808,
michael@0 47957 0
michael@0 47958 ],
michael@0 47959 'kacstdecorative': [
michael@0 47960 1.1232,
michael@0 47961 0.5215,
michael@0 47962 0
michael@0 47963 ],
michael@0 47964 'khmer os system': [
michael@0 47965 1.2436,
michael@0 47966 0.6017,
michael@0 47967 0
michael@0 47968 ],
michael@0 47969 'saab': [
michael@0 47970 1.0029,
michael@0 47971 0.682,
michael@0 47972 0
michael@0 47973 ],
michael@0 47974 'kacsttitle': [
michael@0 47975 1.0831,
michael@0 47976 0.5215,
michael@0 47977 0
michael@0 47978 ],
michael@0 47979 'mukti narrow bold': [
michael@0 47980 1.2837,
michael@0 47981 0.4413,
michael@0 47982 0
michael@0 47983 ],
michael@0 47984 'lohit hindi': [
michael@0 47985 1.0029,
michael@0 47986 0.5215,
michael@0 47987 0
michael@0 47988 ],
michael@0 47989 'kacstqurn': [
michael@0 47990 1.0831,
michael@0 47991 0.5215,
michael@0 47992 0
michael@0 47993 ],
michael@0 47994 'urw bookman l': [
michael@0 47995 0.9628,
michael@0 47996 0.2808,
michael@0 47997 0
michael@0 47998 ],
michael@0 47999 'kacstnaskh': [
michael@0 48000 1.0831,
michael@0 48001 0.5215,
michael@0 48002 0
michael@0 48003 ],
michael@0 48004 'kacstscreen': [
michael@0 48005 1.0831,
michael@0 48006 0.5215,
michael@0 48007 0
michael@0 48008 ],
michael@0 48009 'pothana2000': [
michael@0 48010 0.8825,
michael@0 48011 0.8424,
michael@0 48012 0
michael@0 48013 ],
michael@0 48014 'ungraphic': [
michael@0 48015 1.0029,
michael@0 48016 0.2808,
michael@0 48017 0
michael@0 48018 ],
michael@0 48019 'lohit tamil': [
michael@0 48020 0.8825,
michael@0 48021 0.361,
michael@0 48022 0
michael@0 48023 ],
michael@0 48024 'kacstbook': [
michael@0 48025 1.0831,
michael@0 48026 0.5215,
michael@0 48027 0
michael@0 48028 ]
michael@0 48029 };
michael@0 48030 DEVICE_FONT_METRICS_MAC.__proto__ = DEVICE_FONT_METRICS_WIN;
michael@0 48031 DEVICE_FONT_METRICS_LINUX.__proto__ = DEVICE_FONT_METRICS_MAC;
michael@0 48032 }
michael@0 48033 var StaticTextDefinition = function () {
michael@0 48034 var def = {
michael@0 48035 __class__: 'flash.text.StaticText',
michael@0 48036 initialize: function () {
michael@0 48037 var s = this.symbol;
michael@0 48038 if (s) {
michael@0 48039 this.draw = s.draw;
michael@0 48040 }
michael@0 48041 },
michael@0 48042 get text() {
michael@0 48043 return this._text;
michael@0 48044 },
michael@0 48045 set text(val) {
michael@0 48046 this._text = val;
michael@0 48047 }
michael@0 48048 };
michael@0 48049 var desc = Object.getOwnPropertyDescriptor;
michael@0 48050 def.__glue__ = {
michael@0 48051 native: {
michael@0 48052 instance: {
michael@0 48053 text: desc(def, 'text')
michael@0 48054 }
michael@0 48055 }
michael@0 48056 };
michael@0 48057 return def;
michael@0 48058 }.call(this);
michael@0 48059 var StyleSheetDefinition = function () {
michael@0 48060 return {
michael@0 48061 __class__: 'flash.text.StyleSheet',
michael@0 48062 initialize: function () {
michael@0 48063 },
michael@0 48064 __glue__: {
michael@0 48065 native: {
michael@0 48066 static: {},
michael@0 48067 instance: {
michael@0 48068 _update: function _update() {
michael@0 48069 somewhatImplemented('StyleSheet._update');
michael@0 48070 },
michael@0 48071 _parseCSSInternal: function _parseCSSInternal(cssText) {
michael@0 48072 somewhatImplemented('StyleSheet._parseCSSInternal');
michael@0 48073 return null;
michael@0 48074 },
michael@0 48075 _parseCSSFontFamily: function _parseCSSFontFamily(fontFamily) {
michael@0 48076 notImplemented('StyleSheet._parseCSSFontFamily');
michael@0 48077 },
michael@0 48078 _parseColor: function _parseColor(color) {
michael@0 48079 notImplemented('StyleSheet._parseColor');
michael@0 48080 },
michael@0 48081 _styles: {
michael@0 48082 get: function _styles() {
michael@0 48083 return this.__styles;
michael@0 48084 },
michael@0 48085 set: function _styles(styles) {
michael@0 48086 somewhatImplemented('StyleSheet._styles');
michael@0 48087 this.__styles = styles;
michael@0 48088 }
michael@0 48089 }
michael@0 48090 }
michael@0 48091 }
michael@0 48092 }
michael@0 48093 };
michael@0 48094 }.call(this);
michael@0 48095 var TextFieldDefinition = function () {
michael@0 48096 var def = {
michael@0 48097 __class__: 'flash.text.TextField',
michael@0 48098 initialize: function () {
michael@0 48099 this._bbox = {
michael@0 48100 xMin: 0,
michael@0 48101 yMin: 0,
michael@0 48102 xMax: 2000,
michael@0 48103 yMax: 2000
michael@0 48104 };
michael@0 48105 var initialFormat = {
michael@0 48106 align: 'LEFT',
michael@0 48107 face: 'serif',
michael@0 48108 size: 12,
michael@0 48109 letterspacing: 0,
michael@0 48110 kerning: 0,
michael@0 48111 color: 0,
michael@0 48112 leading: 0
michael@0 48113 };
michael@0 48114 this._content = new TextFieldContent(initialFormat);
michael@0 48115 this._type = 'dynamic';
michael@0 48116 this._embedFonts = false;
michael@0 48117 this._selectable = true;
michael@0 48118 this._autoSize = 'none';
michael@0 48119 this._scrollV = 1;
michael@0 48120 this._maxScrollV = 1;
michael@0 48121 this._bottomScrollV = 1;
michael@0 48122 this._drawingOffsetH = 0;
michael@0 48123 this._background = false;
michael@0 48124 this._border = false;
michael@0 48125 this._backgroundColor = 16777215;
michael@0 48126 this._backgroundColorStr = '#ffffff';
michael@0 48127 this._borderColor = 0;
michael@0 48128 this._borderColorStr = '#000000';
michael@0 48129 var s = this.symbol;
michael@0 48130 if (!s) {
michael@0 48131 this._currentTransform.tx -= 40;
michael@0 48132 this._currentTransform.ty -= 40;
michael@0 48133 this._content.resolveFont(initialFormat, false);
michael@0 48134 this.text = '';
michael@0 48135 return;
michael@0 48136 }
michael@0 48137 var tag = s.tag;
michael@0 48138 var bbox = tag.bbox;
michael@0 48139 this._currentTransform.tx += bbox.xMin;
michael@0 48140 this._currentTransform.ty += bbox.yMin;
michael@0 48141 this._bbox.xMax = bbox.xMax - bbox.xMin;
michael@0 48142 this._bbox.yMax = bbox.yMax - bbox.yMin;
michael@0 48143 if (tag.hasLayout) {
michael@0 48144 initialFormat.size = tag.fontHeight / 20;
michael@0 48145 initialFormat.leading = (tag.leading | 0) / 20;
michael@0 48146 }
michael@0 48147 if (tag.hasColor) {
michael@0 48148 initialFormat.color = rgbaObjToStr(tag.color);
michael@0 48149 }
michael@0 48150 if (tag.hasFont) {
michael@0 48151 var font = FontDefinition.getFontByUniqueName(tag.font);
michael@0 48152 initialFormat.font = font;
michael@0 48153 initialFormat.face = font._fontName;
michael@0 48154 initialFormat.bold = font.symbol.bold;
michael@0 48155 initialFormat.italic = font.symbol.italic;
michael@0 48156 initialFormat.str = this._content.makeFormatString(initialFormat);
michael@0 48157 }
michael@0 48158 this._content.multiline = !(!tag.multiline);
michael@0 48159 this._content.wordWrap = !(!tag.wordWrap);
michael@0 48160 this._embedFonts = !(!tag.useOutlines);
michael@0 48161 this._selectable = !tag.noSelect;
michael@0 48162 this._border = !(!tag.border);
michael@0 48163 switch (tag.align) {
michael@0 48164 case 1:
michael@0 48165 initialFormat.align = 'right';
michael@0 48166 break;
michael@0 48167 case 2:
michael@0 48168 initialFormat.align = 'center';
michael@0 48169 break;
michael@0 48170 case 3:
michael@0 48171 initialFormat.align = 'justified';
michael@0 48172 break;
michael@0 48173 default:
michael@0 48174 }
michael@0 48175 if (tag.initialText) {
michael@0 48176 if (tag.html) {
michael@0 48177 this.htmlText = tag.initialText;
michael@0 48178 } else {
michael@0 48179 this.text = tag.initialText;
michael@0 48180 }
michael@0 48181 } else {
michael@0 48182 this.text = '';
michael@0 48183 }
michael@0 48184 },
michael@0 48185 _getAS2Object: function () {
michael@0 48186 if (!this.$as2Object) {
michael@0 48187 new avm1lib.AS2TextField(this);
michael@0 48188 }
michael@0 48189 return this.$as2Object;
michael@0 48190 },
michael@0 48191 replaceText: function (begin, end, str) {
michael@0 48192 var text = this._content.text;
michael@0 48193 this.text = text.substring(0, begin) + str + text.substring(end);
michael@0 48194 },
michael@0 48195 draw: function (ctx, ratio, colorTransform) {
michael@0 48196 this.ensureDimensions();
michael@0 48197 var bounds = this._bbox;
michael@0 48198 var width = bounds.xMax / 20;
michael@0 48199 var height = bounds.yMax / 20;
michael@0 48200 if (width <= 0 || height <= 0) {
michael@0 48201 return;
michael@0 48202 }
michael@0 48203 ctx.save();
michael@0 48204 ctx.beginPath();
michael@0 48205 ctx.rect(0, 0, width + 1, height + 1);
michael@0 48206 ctx.clip();
michael@0 48207 if (this._background) {
michael@0 48208 colorTransform.setFillStyle(ctx, this._backgroundColorStr);
michael@0 48209 ctx.fill();
michael@0 48210 }
michael@0 48211 if (this._border) {
michael@0 48212 colorTransform.setStrokeStyle(ctx, this._borderColorStr);
michael@0 48213 ctx.lineCap = 'square';
michael@0 48214 ctx.lineWidth = 1;
michael@0 48215 ctx.strokeRect(0.5, 0.5, width | 0, height | 0);
michael@0 48216 }
michael@0 48217 ctx.closePath();
michael@0 48218 if (this._content.lines.length === 0) {
michael@0 48219 ctx.restore();
michael@0 48220 return;
michael@0 48221 }
michael@0 48222 ctx.translate(2, 2);
michael@0 48223 ctx.save();
michael@0 48224 colorTransform.setAlpha(ctx);
michael@0 48225 var runs = this._content._textRuns;
michael@0 48226 var offsetY = this._content.lines[this._scrollV - 1].y;
michael@0 48227 for (var i = 0; i < runs.length; i++) {
michael@0 48228 var run = runs[i];
michael@0 48229 if (run.type === 'f') {
michael@0 48230 ctx.restore();
michael@0 48231 ctx.font = run.format.str;
michael@0 48232 colorTransform.setFillStyle(ctx, run.format.color);
michael@0 48233 ctx.save();
michael@0 48234 colorTransform.setAlpha(ctx);
michael@0 48235 } else {
michael@0 48236 if (run.y < offsetY) {
michael@0 48237 continue;
michael@0 48238 }
michael@0 48239 ctx.fillText(run.text, run.x - this._drawingOffsetH, run.y - offsetY);
michael@0 48240 }
michael@0 48241 }
michael@0 48242 ctx.restore();
michael@0 48243 ctx.restore();
michael@0 48244 },
michael@0 48245 invalidateDimensions: function () {
michael@0 48246 this._invalidate();
michael@0 48247 this._invalidateBounds();
michael@0 48248 this._dimensionsValid = false;
michael@0 48249 },
michael@0 48250 ensureDimensions: function () {
michael@0 48251 if (this._dimensionsValid) {
michael@0 48252 return;
michael@0 48253 }
michael@0 48254 var bounds = this._bbox;
michael@0 48255 var combinedAlign = this._content.calculateMetrics(bounds, this._embedFonts);
michael@0 48256 this._scrollV = 1;
michael@0 48257 this._maxScrollV = 1;
michael@0 48258 this._bottomScrollV = 1;
michael@0 48259 var autoSize = this._autoSize;
michael@0 48260 if (autoSize === 'none') {
michael@0 48261 var maxVisibleY = (bounds.yMax - 80) / 20;
michael@0 48262 if (this._content.textHeight > maxVisibleY) {
michael@0 48263 var lines = this._content.lines;
michael@0 48264 for (var i = 0; i < lines.length; i++) {
michael@0 48265 var line = lines[i];
michael@0 48266 if (line.y + line.height > maxVisibleY) {
michael@0 48267 this._maxScrollV = i + 1;
michael@0 48268 this._bottomScrollV = i === 0 ? 1 : i;
michael@0 48269 break;
michael@0 48270 }
michael@0 48271 }
michael@0 48272 }
michael@0 48273 } else {
michael@0 48274 var width = Math.max(bounds.xMax / 20 - 4, 1);
michael@0 48275 var targetWidth = this._content.textWidth;
michael@0 48276 var align = combinedAlign;
michael@0 48277 var diffX = 0;
michael@0 48278 if (align !== 'mixed') {
michael@0 48279 switch (autoSize) {
michael@0 48280 case 'left':
michael@0 48281 break;
michael@0 48282 case 'center':
michael@0 48283 diffX = width - targetWidth >> 1;
michael@0 48284 break;
michael@0 48285 case 'right':
michael@0 48286 diffX = width - targetWidth;
michael@0 48287 }
michael@0 48288 if (align === 'left') {
michael@0 48289 this._drawingOffsetH = 0;
michael@0 48290 } else {
michael@0 48291 var offset;
michael@0 48292 switch (autoSize) {
michael@0 48293 case 'left':
michael@0 48294 offset = width - targetWidth;
michael@0 48295 break;
michael@0 48296 case 'center':
michael@0 48297 offset = diffX << 1;
michael@0 48298 break;
michael@0 48299 case 'right':
michael@0 48300 offset = diffX;
michael@0 48301 break;
michael@0 48302 }
michael@0 48303 if (align === 'center') {
michael@0 48304 offset >>= 1;
michael@0 48305 }
michael@0 48306 this._drawingOffsetH = offset;
michael@0 48307 }
michael@0 48308 this._invalidateTransform();
michael@0 48309 this._currentTransform.tx += diffX * 20 | 0;
michael@0 48310 bounds.xMax = (targetWidth * 20 | 0) + 80;
michael@0 48311 }
michael@0 48312 bounds.yMax = (this._content.textHeight * 20 | 0) + 80;
michael@0 48313 console.log(bounds.yMax);
michael@0 48314 this._invalidateBounds();
michael@0 48315 }
michael@0 48316 this._dimensionsValid = true;
michael@0 48317 },
michael@0 48318 get text() {
michael@0 48319 return this._content.text;
michael@0 48320 },
michael@0 48321 set text(val) {
michael@0 48322 this._content.text = val;
michael@0 48323 this.invalidateDimensions();
michael@0 48324 },
michael@0 48325 get htmlText() {
michael@0 48326 return this._content.htmlText;
michael@0 48327 },
michael@0 48328 set htmlText(val) {
michael@0 48329 this._content.htmlText = val;
michael@0 48330 this.invalidateDimensions();
michael@0 48331 },
michael@0 48332 get defaultTextFormat() {
michael@0 48333 var format = this._content.defaultTextFormat;
michael@0 48334 return new flash.text.TextFormat().fromObject(format);
michael@0 48335 },
michael@0 48336 set defaultTextFormat(val) {
michael@0 48337 this._content.defaultTextFormat = val.toObject();
michael@0 48338 this.invalidateDimensions();
michael@0 48339 },
michael@0 48340 getTextFormat: function (beginIndex, endIndex) {
michael@0 48341 return this.defaultTextFormat;
michael@0 48342 },
michael@0 48343 setTextFormat: function (format, beginIndex, endIndex) {
michael@0 48344 this.defaultTextFormat = format;
michael@0 48345 if (this.text === this.htmlText) {
michael@0 48346 this.text = this.text;
michael@0 48347 }
michael@0 48348 this.invalidateDimensions();
michael@0 48349 },
michael@0 48350 get x() {
michael@0 48351 this.ensureDimensions();
michael@0 48352 return this._currentTransform.tx;
michael@0 48353 },
michael@0 48354 set x(val) {
michael@0 48355 if (val === this._currentTransform.tx) {
michael@0 48356 return;
michael@0 48357 }
michael@0 48358 this._invalidate();
michael@0 48359 this._invalidateBounds();
michael@0 48360 this._invalidateTransform();
michael@0 48361 this._currentTransform.tx = val;
michael@0 48362 },
michael@0 48363 get width() {
michael@0 48364 this.ensureDimensions();
michael@0 48365 return this._bbox.xMax;
michael@0 48366 },
michael@0 48367 set width(value) {
michael@0 48368 if (value < 0) {
michael@0 48369 return;
michael@0 48370 }
michael@0 48371 this._bbox.xMax = value;
michael@0 48372 this.invalidateDimensions();
michael@0 48373 },
michael@0 48374 get height() {
michael@0 48375 this.ensureDimensions();
michael@0 48376 return this._bbox.yMax;
michael@0 48377 },
michael@0 48378 set height(value) {
michael@0 48379 if (value < 0) {
michael@0 48380 return;
michael@0 48381 }
michael@0 48382 this._bbox.yMax = value;
michael@0 48383 this._invalidate();
michael@0 48384 },
michael@0 48385 _getContentBounds: function () {
michael@0 48386 this.ensureDimensions();
michael@0 48387 return this._bbox;
michael@0 48388 },
michael@0 48389 _getRegion: function getRegion(targetCoordSpace) {
michael@0 48390 return this._getTransformedRect(this._getContentBounds(), targetCoordSpace);
michael@0 48391 },
michael@0 48392 getLineMetrics: function (lineIndex) {
michael@0 48393 this.ensureDimensions();
michael@0 48394 if (lineIndex < 0 || lineIndex >= this._content.lines.length) {
michael@0 48395 throwError('RangeError', Errors.ParamRangeError);
michael@0 48396 }
michael@0 48397 var line = this._content.lines[lineIndex];
michael@0 48398 var format = line.largestFormat;
michael@0 48399 var metrics = format.font._metrics;
michael@0 48400 var size = format.size;
michael@0 48401 var ascent = metrics.ascent * size + 0.49999 | 0;
michael@0 48402 var descent = metrics.descent * size + 0.49999 | 0;
michael@0 48403 var leading = metrics.leading * size + 0.49999 + line.leading | 0;
michael@0 48404 return new flash.text.TextLineMetrics(line.x + 2, line.width, line.height, ascent, descent, leading);
michael@0 48405 },
michael@0 48406 getCharBoundaries: function getCharBoundaries(index) {
michael@0 48407 somewhatImplemented('TextField.getCharBoundaries');
michael@0 48408 return new flash.geom.Rectangle(0, 0, 0, 0);
michael@0 48409 }
michael@0 48410 };
michael@0 48411 var desc = Object.getOwnPropertyDescriptor;
michael@0 48412 def.__glue__ = {
michael@0 48413 native: {
michael@0 48414 instance: {
michael@0 48415 text: desc(def, 'text'),
michael@0 48416 defaultTextFormat: desc(def, 'defaultTextFormat'),
michael@0 48417 draw: def.draw,
michael@0 48418 htmlText: desc(def, 'htmlText'),
michael@0 48419 replaceText: def.replaceText,
michael@0 48420 getTextFormat: def.getTextFormat,
michael@0 48421 setTextFormat: def.setTextFormat,
michael@0 48422 getCharBoundaries: def.getCharBoundaries,
michael@0 48423 autoSize: {
michael@0 48424 get: function autoSize() {
michael@0 48425 return this._autoSize;
michael@0 48426 },
michael@0 48427 set: function autoSize(value) {
michael@0 48428 if (this._autoSize === value) {
michael@0 48429 return;
michael@0 48430 }
michael@0 48431 this._autoSize = value;
michael@0 48432 this.invalidateDimensions();
michael@0 48433 }
michael@0 48434 },
michael@0 48435 multiline: {
michael@0 48436 get: function multiline() {
michael@0 48437 return this._content.multiline;
michael@0 48438 },
michael@0 48439 set: function multiline(value) {
michael@0 48440 if (this._content.multiline === value) {
michael@0 48441 return;
michael@0 48442 }
michael@0 48443 this._content.multiline = value;
michael@0 48444 this.invalidateDimensions();
michael@0 48445 }
michael@0 48446 },
michael@0 48447 textColor: {
michael@0 48448 get: function textColor() {
michael@0 48449 return this._content.textColor;
michael@0 48450 },
michael@0 48451 set: function textColor(value) {
michael@0 48452 if (this._content.textColor === value) {
michael@0 48453 return;
michael@0 48454 }
michael@0 48455 this._content.textColor = value;
michael@0 48456 this._invalidate();
michael@0 48457 }
michael@0 48458 },
michael@0 48459 selectable: {
michael@0 48460 get: function selectable() {
michael@0 48461 return this._selectable;
michael@0 48462 },
michael@0 48463 set: function selectable(value) {
michael@0 48464 somewhatImplemented('TextField.selectable');
michael@0 48465 this._selectable = value;
michael@0 48466 }
michael@0 48467 },
michael@0 48468 wordWrap: {
michael@0 48469 get: function wordWrap() {
michael@0 48470 return this._content.wordWrap;
michael@0 48471 },
michael@0 48472 set: function wordWrap(value) {
michael@0 48473 if (this._content.wordWrap === value) {
michael@0 48474 return;
michael@0 48475 }
michael@0 48476 this._content.wordWrap = value;
michael@0 48477 this.invalidateDimensions();
michael@0 48478 }
michael@0 48479 },
michael@0 48480 textHeight: {
michael@0 48481 get: function textHeight() {
michael@0 48482 this.ensureDimensions();
michael@0 48483 return this._content.textHeight;
michael@0 48484 }
michael@0 48485 },
michael@0 48486 textWidth: {
michael@0 48487 get: function textWidth() {
michael@0 48488 this.ensureDimensions();
michael@0 48489 return this._content.textWidth;
michael@0 48490 }
michael@0 48491 },
michael@0 48492 length: {
michael@0 48493 get: function length() {
michael@0 48494 return this.text.length;
michael@0 48495 }
michael@0 48496 },
michael@0 48497 numLines: {
michael@0 48498 get: function numLines() {
michael@0 48499 this.ensureDimensions();
michael@0 48500 return this._content.lines.length;
michael@0 48501 }
michael@0 48502 },
michael@0 48503 getLineMetrics: function (lineIndex) {
michael@0 48504 return this.getLineMetrics(lineIndex);
michael@0 48505 },
michael@0 48506 setSelection: function (beginIndex, endIndex) {
michael@0 48507 somewhatImplemented('TextField.setSelection');
michael@0 48508 },
michael@0 48509 scrollV: {
michael@0 48510 get: function scrollV() {
michael@0 48511 return this._scrollV;
michael@0 48512 },
michael@0 48513 set: function scrollV(value) {
michael@0 48514 this.ensureDimensions();
michael@0 48515 value = Math.max(1, Math.min(this._maxScrollV, value));
michael@0 48516 this._scrollV = value;
michael@0 48517 }
michael@0 48518 },
michael@0 48519 bottomScrollV: {
michael@0 48520 get: function bottomScrollV() {
michael@0 48521 this.ensureDimensions();
michael@0 48522 if (this._scrollV === 1) {
michael@0 48523 return this._bottomScrollV;
michael@0 48524 }
michael@0 48525 var maxVisibleY = (this._bbox.yMax - 80) / 20;
michael@0 48526 var lines = this._content.lines;
michael@0 48527 var offsetY = lines[this._scrollV - 1].y;
michael@0 48528 for (var i = this._bottomScrollV; i < lines.length; i++) {
michael@0 48529 var line = lines[i];
michael@0 48530 if (line.y + line.height + offsetY > maxVisibleY) {
michael@0 48531 return i + 1;
michael@0 48532 }
michael@0 48533 }
michael@0 48534 }
michael@0 48535 },
michael@0 48536 maxScrollV: {
michael@0 48537 get: function maxScrollV() {
michael@0 48538 this.ensureDimensions();
michael@0 48539 return this._maxScrollV;
michael@0 48540 }
michael@0 48541 },
michael@0 48542 maxScrollH: {
michael@0 48543 get: function maxScrollH() {
michael@0 48544 this.ensureDimensions();
michael@0 48545 return Math.max(this._content.textWidth - this._bbox.xMax / 20 + 4, 0);
michael@0 48546 }
michael@0 48547 },
michael@0 48548 background: {
michael@0 48549 get: function background() {
michael@0 48550 return this._background;
michael@0 48551 },
michael@0 48552 set: function background(value) {
michael@0 48553 if (this._background === value) {
michael@0 48554 return;
michael@0 48555 }
michael@0 48556 this._background = value;
michael@0 48557 this._invalidate();
michael@0 48558 }
michael@0 48559 },
michael@0 48560 backgroundColor: {
michael@0 48561 get: function backgroundColor() {
michael@0 48562 return this._backgroundColor;
michael@0 48563 },
michael@0 48564 set: function backgroundColor(value) {
michael@0 48565 if (this._backgroundColor === value) {
michael@0 48566 return;
michael@0 48567 }
michael@0 48568 this._backgroundColor = value;
michael@0 48569 this._backgroundColorStr = rgbIntAlphaToStr(value, 1);
michael@0 48570 if (this._background) {
michael@0 48571 this._invalidate();
michael@0 48572 }
michael@0 48573 }
michael@0 48574 },
michael@0 48575 border: {
michael@0 48576 get: function border() {
michael@0 48577 return this._border;
michael@0 48578 },
michael@0 48579 set: function border(value) {
michael@0 48580 if (this._border === value) {
michael@0 48581 return;
michael@0 48582 }
michael@0 48583 this._border = value;
michael@0 48584 this._invalidate();
michael@0 48585 }
michael@0 48586 },
michael@0 48587 borderColor: {
michael@0 48588 get: function borderColor() {
michael@0 48589 return this._borderColor;
michael@0 48590 },
michael@0 48591 set: function borderColor(value) {
michael@0 48592 if (this._borderColor === value) {
michael@0 48593 return;
michael@0 48594 }
michael@0 48595 this._borderColor = value;
michael@0 48596 this._borderColorStr = rgbIntAlphaToStr(value, 1);
michael@0 48597 if (this._border) {
michael@0 48598 this._invalidate();
michael@0 48599 }
michael@0 48600 }
michael@0 48601 },
michael@0 48602 type: {
michael@0 48603 get: function borderColor() {
michael@0 48604 return this._type;
michael@0 48605 },
michael@0 48606 set: function borderColor(value) {
michael@0 48607 somewhatImplemented('TextField.type');
michael@0 48608 this._type = value;
michael@0 48609 }
michael@0 48610 },
michael@0 48611 embedFonts: {
michael@0 48612 get: function embedFonts() {
michael@0 48613 return this._embedFonts;
michael@0 48614 },
michael@0 48615 set: function embedFonts(value) {
michael@0 48616 this.invalidateDimensions();
michael@0 48617 this._embedFonts = value;
michael@0 48618 }
michael@0 48619 },
michael@0 48620 condenseWhite: {
michael@0 48621 get: function condenseWhite() {
michael@0 48622 return this._content.condenseWhite;
michael@0 48623 },
michael@0 48624 set: function condenseWhite(value) {
michael@0 48625 somewhatImplemented('TextField.condenseWhite');
michael@0 48626 this._content.condenseWhite = value;
michael@0 48627 }
michael@0 48628 },
michael@0 48629 sharpness: {
michael@0 48630 get: function sharpness() {
michael@0 48631 return this._sharpness;
michael@0 48632 },
michael@0 48633 set: function sharpness(value) {
michael@0 48634 somewhatImplemented('TextField.sharpness');
michael@0 48635 this._sharpness = value;
michael@0 48636 }
michael@0 48637 }
michael@0 48638 }
michael@0 48639 }
michael@0 48640 };
michael@0 48641 return def;
michael@0 48642 }.call(this);
michael@0 48643 function TextFieldContent(initialFormat) {
michael@0 48644 this.defaultTextFormat = initialFormat;
michael@0 48645 this.textWidth = 0;
michael@0 48646 this.textHeight = 0;
michael@0 48647 this.condenseWhite = false;
michael@0 48648 this.wordWrap = false;
michael@0 48649 this.multiline = false;
michael@0 48650 this.textColor = null;
michael@0 48651 this._text = '';
michael@0 48652 this._htmlText = '';
michael@0 48653 this._createTrunk();
michael@0 48654 this._textRuns = null;
michael@0 48655 this._htmlParser = document.createElement('p');
michael@0 48656 this._measureCtx = document.createElement('canvas').getContext('2d');
michael@0 48657 }
michael@0 48658 TextFieldContent.knownNodeTypes = {
michael@0 48659 'BR': true,
michael@0 48660 'LI': true,
michael@0 48661 'P': true,
michael@0 48662 'B': true,
michael@0 48663 'I': true,
michael@0 48664 'FONT': true,
michael@0 48665 'TEXTFORMAT': true,
michael@0 48666 'U': true,
michael@0 48667 'A': true,
michael@0 48668 'IMG': true,
michael@0 48669 'SPAN': true
michael@0 48670 };
michael@0 48671 TextFieldContent.WRAP_OPPORTUNITIES = {
michael@0 48672 ' ': true,
michael@0 48673 '.': true,
michael@0 48674 '-': true,
michael@0 48675 '\t': true
michael@0 48676 };
michael@0 48677 TextFieldContent.TextLine = function (y) {
michael@0 48678 this.x = 0;
michael@0 48679 this.width = 0;
michael@0 48680 this.y = y;
michael@0 48681 this.height = 0;
michael@0 48682 this.leading = 0;
michael@0 48683 this.runs = [];
michael@0 48684 this.largestFormat = null;
michael@0 48685 };
michael@0 48686 TextFieldContent.prototype = {
michael@0 48687 get text() {
michael@0 48688 return this._text;
michael@0 48689 },
michael@0 48690 set text(val) {
michael@0 48691 val = val + '';
michael@0 48692 if (this._text === val) {
michael@0 48693 return;
michael@0 48694 }
michael@0 48695 var lines = [];
michael@0 48696 var lineOffset = 0;
michael@0 48697 for (var index = 0; index < val.length;) {
michael@0 48698 var char = val[index];
michael@0 48699 if (char === '\r' || char === '\n') {
michael@0 48700 lines.push(val.substring(lineOffset, index));
michael@0 48701 lineOffset = index;
michael@0 48702 if (char === '\r' && val[index + 1] === '\n') {
michael@0 48703 index++;
michael@0 48704 }
michael@0 48705 }
michael@0 48706 index++;
michael@0 48707 }
michael@0 48708 lines.push(val.substring(lineOffset, index));
michael@0 48709 this._createTrunk();
michael@0 48710 this._text = val;
michael@0 48711 this._htmlText = val;
michael@0 48712 this._tree.children[0].children[0] = {
michael@0 48713 type: 'plain-text',
michael@0 48714 lines: lines
michael@0 48715 };
michael@0 48716 },
michael@0 48717 get htmlText() {
michael@0 48718 return this._htmlText;
michael@0 48719 },
michael@0 48720 set htmlText(val) {
michael@0 48721 if (this._htmlText === val) {
michael@0 48722 return;
michael@0 48723 }
michael@0 48724 this.defaultTextFormat.bold = false;
michael@0 48725 this.defaultTextFormat.italic = false;
michael@0 48726 this._parseHtml(val);
michael@0 48727 },
michael@0 48728 calculateMetrics: function (bounds, embedFonts) {
michael@0 48729 var initialFormat = this.defaultTextFormat;
michael@0 48730 this.resolveFont(initialFormat, embedFonts);
michael@0 48731 this.lines = [];
michael@0 48732 this._textRuns = [
michael@0 48733 {
michael@0 48734 type: 'f',
michael@0 48735 format: initialFormat
michael@0 48736 }
michael@0 48737 ];
michael@0 48738 var width = Math.max(bounds.xMax / 20 - 4, 1);
michael@0 48739 var height = Math.max(bounds.yMax / 20 - 4, 1);
michael@0 48740 var state = {
michael@0 48741 ctx: this._measureCtx,
michael@0 48742 w: width,
michael@0 48743 h: height,
michael@0 48744 maxLineWidth: 0,
michael@0 48745 formats: [
michael@0 48746 initialFormat
michael@0 48747 ],
michael@0 48748 currentFormat: initialFormat,
michael@0 48749 line: new TextFieldContent.TextLine(0),
michael@0 48750 wordWrap: this.wordWrap,
michael@0 48751 combinedAlign: null,
michael@0 48752 textColor: this.textColor,
michael@0 48753 embedFonts: embedFonts
michael@0 48754 };
michael@0 48755 this._collectRuns(state, this._tree);
michael@0 48756 this._finishLine(state, false);
michael@0 48757 this.textWidth = state.maxLineWidth | 0;
michael@0 48758 this.textHeight = state.line.y | 0;
michael@0 48759 return state.combinedAlign;
michael@0 48760 },
michael@0 48761 makeFormatString: function (format) {
michael@0 48762 var boldItalic = '';
michael@0 48763 if (format.italic) {
michael@0 48764 boldItalic += 'italic';
michael@0 48765 }
michael@0 48766 if (format.bold) {
michael@0 48767 boldItalic += ' bold';
michael@0 48768 }
michael@0 48769 return boldItalic + ' ' + format.size + 'px ' + (format.font._uniqueName || format.font._fontName);
michael@0 48770 },
michael@0 48771 resolveFont: function (format, embedded) {
michael@0 48772 var face = format.face.toLowerCase();
michael@0 48773 if (face === '_sans') {
michael@0 48774 face = 'sans-serif';
michael@0 48775 } else if (face === '_serif') {
michael@0 48776 face = 'serif';
michael@0 48777 } else if (face === '_typewriter') {
michael@0 48778 face = 'monospace';
michael@0 48779 }
michael@0 48780 var style;
michael@0 48781 if (format.bold) {
michael@0 48782 if (format.italic) {
michael@0 48783 style = 'boldItalic';
michael@0 48784 } else {
michael@0 48785 style = 'bold';
michael@0 48786 }
michael@0 48787 } else if (format.italic) {
michael@0 48788 style = 'italic';
michael@0 48789 } else {
michael@0 48790 style = 'regular';
michael@0 48791 }
michael@0 48792 var font = FontDefinition.getFont(face, style, embedded);
michael@0 48793 format.font = font;
michael@0 48794 },
michael@0 48795 _parseHtml: function (val) {
michael@0 48796 this._htmlParser.innerHTML = val;
michael@0 48797 var rootElement = this._htmlParser.childNodes.length !== 1 ? this._htmlParser : this._htmlParser.childNodes[0];
michael@0 48798 this._text = '';
michael@0 48799 this._htmlText = val;
michael@0 48800 this._createTrunk();
michael@0 48801 if (rootElement.nodeType === 3) {
michael@0 48802 this._convertNode(rootElement, this._tree.children[0].children);
michael@0 48803 }
michael@0 48804 var initialNodeList = [
michael@0 48805 rootElement
michael@0 48806 ];
michael@0 48807 var attributes;
michael@0 48808 var format;
michael@0 48809 var key;
michael@0 48810 if (initialNodeList.length == 1 && rootElement.localName.toUpperCase() == 'P') {
michael@0 48811 attributes = this._extractAttributes(rootElement);
michael@0 48812 format = this._tree.format;
michael@0 48813 for (key in attributes) {
michael@0 48814 format[key] = attributes[key];
michael@0 48815 }
michael@0 48816 initialNodeList = rootElement.childNodes;
michael@0 48817 rootElement = rootElement.childNodes[0];
michael@0 48818 }
michael@0 48819 if (initialNodeList.length == 1 && rootElement.localName.toUpperCase() == 'FONT') {
michael@0 48820 attributes = this._extractAttributes(rootElement);
michael@0 48821 format = this._tree.children[0].format;
michael@0 48822 for (key in attributes) {
michael@0 48823 format[key] = attributes[key];
michael@0 48824 }
michael@0 48825 initialNodeList = rootElement.childNodes;
michael@0 48826 }
michael@0 48827 this._convertNodeList(initialNodeList, this._tree.children[0].children);
michael@0 48828 },
michael@0 48829 _createTrunk: function () {
michael@0 48830 var initialFormat = this.defaultTextFormat;
michael@0 48831 this._tree = {
michael@0 48832 type: 'SPAN',
michael@0 48833 format: {
michael@0 48834 ALIGN: initialFormat.align
michael@0 48835 },
michael@0 48836 children: []
michael@0 48837 };
michael@0 48838 var fontAttributes = {
michael@0 48839 FACE: initialFormat.face,
michael@0 48840 LETTERSPACING: initialFormat.letterSpacing,
michael@0 48841 KERNING: initialFormat.kerning,
michael@0 48842 LEADING: initialFormat.leading,
michael@0 48843 COLOR: initialFormat.color
michael@0 48844 };
michael@0 48845 this._tree.children[0] = {
michael@0 48846 type: 'FONT',
michael@0 48847 format: fontAttributes,
michael@0 48848 children: []
michael@0 48849 };
michael@0 48850 },
michael@0 48851 _convertNode: function (input, destinationList) {
michael@0 48852 if (!(input.nodeType === 1 || input.nodeType === 3) || input.prefix) {
michael@0 48853 return;
michael@0 48854 }
michael@0 48855 var node;
michael@0 48856 if (input.nodeType === 3) {
michael@0 48857 var text = input.textContent;
michael@0 48858 node = {
michael@0 48859 type: 'text',
michael@0 48860 text: text,
michael@0 48861 format: null,
michael@0 48862 children: null
michael@0 48863 };
michael@0 48864 this._text += text;
michael@0 48865 destinationList.push(node);
michael@0 48866 return;
michael@0 48867 }
michael@0 48868 var nodeType = input.localName.toUpperCase();
michael@0 48869 if (!TextFieldContent.knownNodeTypes[nodeType] || this.multiline === false && (nodeType === 'P' || nodeType === 'BR')) {
michael@0 48870 if (nodeType === 'SBR') {
michael@0 48871 destinationList.push({
michael@0 48872 type: 'BR',
michael@0 48873 text: null,
michael@0 48874 format: null,
michael@0 48875 children: null
michael@0 48876 });
michael@0 48877 }
michael@0 48878 this._convertNodeList(input.childNodes, destinationList);
michael@0 48879 return;
michael@0 48880 }
michael@0 48881 node = {
michael@0 48882 type: nodeType,
michael@0 48883 text: null,
michael@0 48884 format: this._extractAttributes(input),
michael@0 48885 children: []
michael@0 48886 };
michael@0 48887 this._convertNodeList(input.childNodes, node.children);
michael@0 48888 destinationList.push(node);
michael@0 48889 },
michael@0 48890 _convertNodeList: function (from, to) {
michael@0 48891 var childCount = from.length;
michael@0 48892 for (var i = 0; i < childCount; i++) {
michael@0 48893 this._convertNode(from[i], to);
michael@0 48894 }
michael@0 48895 },
michael@0 48896 _extractAttributes: function (node) {
michael@0 48897 var attributesList = node.attributes;
michael@0 48898 var attributesMap = {};
michael@0 48899 for (var i = 0; i < attributesList.length; i++) {
michael@0 48900 var attr = attributesList[i];
michael@0 48901 if (attr.prefix) {
michael@0 48902 continue;
michael@0 48903 }
michael@0 48904 attributesMap[attr.localName.toUpperCase()] = attr.value;
michael@0 48905 }
michael@0 48906 return attributesMap;
michael@0 48907 },
michael@0 48908 _collectRuns: function (state, node) {
michael@0 48909 var formatNode = false;
michael@0 48910 var blockNode = false;
michael@0 48911 switch (node.type) {
michael@0 48912 case 'plain-text':
michael@0 48913 var lines = node.lines;
michael@0 48914 for (var i = 0; i < lines.length; i++) {
michael@0 48915 this._addRunsForText(state, lines[i]);
michael@0 48916 if (i < lines.length - 1) {
michael@0 48917 this._finishLine(state, true);
michael@0 48918 }
michael@0 48919 }
michael@0 48920 return;
michael@0 48921 case 'text':
michael@0 48922 this._addRunsForText(state, node.text);
michael@0 48923 return;
michael@0 48924 case 'BR':
michael@0 48925 this._finishLine(state, true);
michael@0 48926 return;
michael@0 48927 case 'LI':
michael@0 48928 case 'P':
michael@0 48929 this._finishLine(state, false);
michael@0 48930 this._pushFormat(state, node);
michael@0 48931 blockNode = true;
michael@0 48932 break;
michael@0 48933 case 'B':
michael@0 48934 case 'I':
michael@0 48935 case 'FONT':
michael@0 48936 case 'TEXTFORMAT':
michael@0 48937 this._pushFormat(state, node);
michael@0 48938 formatNode = true;
michael@0 48939 break;
michael@0 48940 case 'U':
michael@0 48941 case 'A':
michael@0 48942 case 'IMG':
michael@0 48943 case 'SPAN':
michael@0 48944 default:
michael@0 48945 }
michael@0 48946 for (var i = 0; i < node.children.length; i++) {
michael@0 48947 var child = node.children[i];
michael@0 48948 this._collectRuns(state, child);
michael@0 48949 }
michael@0 48950 if (formatNode) {
michael@0 48951 this._popFormat(state);
michael@0 48952 }
michael@0 48953 if (blockNode) {
michael@0 48954 this._finishLine(state, true);
michael@0 48955 }
michael@0 48956 },
michael@0 48957 _addRunsForText: function (state, text) {
michael@0 48958 if (!text) {
michael@0 48959 return;
michael@0 48960 }
michael@0 48961 if (!state.wordWrap) {
michael@0 48962 this._addTextRun(state, text, state.ctx.measureText(text).width);
michael@0 48963 return;
michael@0 48964 }
michael@0 48965 while (text.length) {
michael@0 48966 var width = state.ctx.measureText(text).width;
michael@0 48967 var availableWidth = state.w - state.line.width;
michael@0 48968 if (availableWidth <= 0) {
michael@0 48969 this._finishLine(state, false);
michael@0 48970 availableWidth = state.w - state.line.width;
michael@0 48971 }
michael@0 48972 if (width <= availableWidth) {
michael@0 48973 this._addTextRun(state, text, width);
michael@0 48974 break;
michael@0 48975 } else {
michael@0 48976 var offset = text.length / width * availableWidth | 0;
michael@0 48977 while (state.ctx.measureText(text.substr(0, offset)).width < availableWidth && offset < text.length) {
michael@0 48978 offset++;
michael@0 48979 }
michael@0 48980 var wrapOffset = offset;
michael@0 48981 while (wrapOffset > -1) {
michael@0 48982 if (TextFieldContent.WRAP_OPPORTUNITIES[text[wrapOffset]]) {
michael@0 48983 wrapOffset++;
michael@0 48984 break;
michael@0 48985 }
michael@0 48986 wrapOffset--;
michael@0 48987 }
michael@0 48988 if (wrapOffset === -1) {
michael@0 48989 if (state.line.width > 0) {
michael@0 48990 this._finishLine(state, false);
michael@0 48991 continue;
michael@0 48992 }
michael@0 48993 while (state.ctx.measureText(text.substr(0, offset)).width > availableWidth) {
michael@0 48994 offset--;
michael@0 48995 }
michael@0 48996 if (offset === 0) {
michael@0 48997 offset = 1;
michael@0 48998 }
michael@0 48999 wrapOffset = offset;
michael@0 49000 }
michael@0 49001 var runText = text.substr(0, wrapOffset);
michael@0 49002 width = state.ctx.measureText(runText).width;
michael@0 49003 this._addTextRun(state, runText, width);
michael@0 49004 if (state.wordWrap) {
michael@0 49005 this._finishLine(state, false);
michael@0 49006 }
michael@0 49007 text = text.substr(wrapOffset);
michael@0 49008 }
michael@0 49009 }
michael@0 49010 },
michael@0 49011 _addTextRun: function (state, text, width) {
michael@0 49012 if (text.length === 0) {
michael@0 49013 return;
michael@0 49014 }
michael@0 49015 var line = state.line;
michael@0 49016 var format = state.currentFormat;
michael@0 49017 var size = format.size;
michael@0 49018 var run = {
michael@0 49019 type: 't',
michael@0 49020 text: text,
michael@0 49021 x: line.width
michael@0 49022 };
michael@0 49023 this._textRuns.push(run);
michael@0 49024 state.line.runs.push(run);
michael@0 49025 line.width += width | 0;
michael@0 49026 if (line.leading === 0 && format.leading > line.leading) {
michael@0 49027 line.leading = format.leading;
michael@0 49028 }
michael@0 49029 if (!line.largestFormat || size > line.largestFormat.size) {
michael@0 49030 line.largestFormat = format;
michael@0 49031 }
michael@0 49032 },
michael@0 49033 _finishLine: function (state, forceNewline) {
michael@0 49034 var line = state.line;
michael@0 49035 if (line.runs.length === 0) {
michael@0 49036 if (forceNewline) {
michael@0 49037 var format = state.currentFormat;
michael@0 49038 state.line.y += format.font._metrics.height * format.size + format.leading | 0;
michael@0 49039 }
michael@0 49040 return;
michael@0 49041 }
michael@0 49042 var runs = line.runs;
michael@0 49043 var format = line.largestFormat;
michael@0 49044 var baselinePos = line.y + format.font._metrics.ascent * format.size;
michael@0 49045 for (var i = runs.length; i--;) {
michael@0 49046 runs[i].y = baselinePos;
michael@0 49047 }
michael@0 49048 var align = (state.currentFormat.align || '').toLowerCase();
michael@0 49049 if (state.combinedAlign === null) {
michael@0 49050 state.combinedAlign = align;
michael@0 49051 } else if (state.combinedAlign !== align) {
michael@0 49052 state.combinedAlign = 'mixed';
michael@0 49053 }
michael@0 49054 if (align === 'center' || align === 'right') {
michael@0 49055 var offset = Math.max(state.w - line.width, 0);
michael@0 49056 if (align === 'center') {
michael@0 49057 offset >>= 1;
michael@0 49058 }
michael@0 49059 for (i = runs.length; i--;) {
michael@0 49060 runs[i].x += offset;
michael@0 49061 }
michael@0 49062 }
michael@0 49063 line.height = format.font._metrics.height * format.size + line.leading | 0;
michael@0 49064 state.maxLineWidth = Math.max(state.maxLineWidth, line.width);
michael@0 49065 this.lines.push(line);
michael@0 49066 state.line = new TextFieldContent.TextLine(line.y + line.height);
michael@0 49067 },
michael@0 49068 _pushFormat: function (state, node) {
michael@0 49069 var attributes = node.format;
michael@0 49070 var format = Object.create(state.formats[state.formats.length - 1]);
michael@0 49071 var fontChanged = false;
michael@0 49072 switch (node.type) {
michael@0 49073 case 'P':
michael@0 49074 if (attributes.ALIGN === format.align) {
michael@0 49075 return;
michael@0 49076 }
michael@0 49077 format.align = attributes.ALIGN;
michael@0 49078 break;
michael@0 49079 case 'B':
michael@0 49080 format.bold = true;
michael@0 49081 fontChanged = true;
michael@0 49082 break;
michael@0 49083 case 'I':
michael@0 49084 format.italic = true;
michael@0 49085 fontChanged = true;
michael@0 49086 break;
michael@0 49087 case 'FONT':
michael@0 49088 if (attributes.COLOR !== undefined) {
michael@0 49089 format.color = attributes.COLOR;
michael@0 49090 }
michael@0 49091 if (attributes.FACE !== undefined) {
michael@0 49092 format.face = attributes.FACE;
michael@0 49093 fontChanged = true;
michael@0 49094 }
michael@0 49095 if (attributes.SIZE !== undefined) {
michael@0 49096 format.size = parseFloat(attributes.SIZE);
michael@0 49097 }
michael@0 49098 if (attributes.LETTERSPACING !== undefined) {
michael@0 49099 format.letterspacing = parseFloat(attributes.LETTERSPACING);
michael@0 49100 }
michael@0 49101 if (attributes.KERNING !== undefined) {
michael@0 49102 format.kerning = attributes.KERNING && true;
michael@0 49103 }
michael@0 49104 case 'TEXTFORMAT':
michael@0 49105 if (attributes.LEADING !== undefined) {
michael@0 49106 format.leading = parseFloat(attributes.LEADING);
michael@0 49107 }
michael@0 49108 if (attributes.INDENT !== undefined) {
michael@0 49109 state.line.x = attributes.INDENT;
michael@0 49110 state.line.width += attributes.INDENT | 0;
michael@0 49111 }
michael@0 49112 break;
michael@0 49113 default:
michael@0 49114 warning('Unknown format node encountered: ' + node.type);
michael@0 49115 return;
michael@0 49116 }
michael@0 49117 if (state.textColor !== null) {
michael@0 49118 format.color = rgbIntAlphaToStr(state.textColor, 1);
michael@0 49119 }
michael@0 49120 if (fontChanged) {
michael@0 49121 this.resolveFont(format, state.embedFonts);
michael@0 49122 }
michael@0 49123 format.str = this.makeFormatString(format);
michael@0 49124 state.formats.push(format);
michael@0 49125 this._textRuns.push({
michael@0 49126 type: 'f',
michael@0 49127 format: format
michael@0 49128 });
michael@0 49129 state.currentFormat = format;
michael@0 49130 state.ctx.font = format.str;
michael@0 49131 },
michael@0 49132 _popFormat: function (state) {
michael@0 49133 state.formats.pop();
michael@0 49134 var format = state.currentFormat = state.formats[state.formats.length - 1];
michael@0 49135 this._textRuns.push({
michael@0 49136 type: 'f',
michael@0 49137 format: format
michael@0 49138 });
michael@0 49139 state.ctx.font = state.str;
michael@0 49140 }
michael@0 49141 };
michael@0 49142 var TextFormatDefinition = function () {
michael@0 49143 var measureTextField;
michael@0 49144 return {
michael@0 49145 __class__: 'flash.text.TextFormat',
michael@0 49146 initialize: function () {
michael@0 49147 },
michael@0 49148 fromObject: function (obj) {
michael@0 49149 this._font = obj.face || null;
michael@0 49150 this._size = typeof obj.size === 'number' ? obj.size : null;
michael@0 49151 this._color = typeof obj.color === 'number' ? obj.color : null;
michael@0 49152 this._bold = typeof obj.bold === 'boolean' ? obj.bold : null;
michael@0 49153 this._italic = typeof obj.italic === 'boolean' ? obj.italic : null;
michael@0 49154 this._underline = typeof obj.underline === 'boolean' ? obj.underline : null;
michael@0 49155 this._url = obj.url || null;
michael@0 49156 this._target = obj.target || null;
michael@0 49157 this._align = obj.align || null;
michael@0 49158 this._leftMargin = typeof obj.leftMargin === 'number' ? obj.leftMargin : null;
michael@0 49159 this._rightMargin = typeof obj.rightMargin === 'number' ? obj.rightMargin : null;
michael@0 49160 this._indent = typeof obj.indent === 'number' ? obj.indent : null;
michael@0 49161 this._leading = typeof obj.leading === 'number' ? obj.leading : null;
michael@0 49162 return this;
michael@0 49163 },
michael@0 49164 toObject: function () {
michael@0 49165 return {
michael@0 49166 face: this._font || 'serif',
michael@0 49167 size: this._size || 12,
michael@0 49168 color: this._color || 0,
michael@0 49169 bold: this._bold || false,
michael@0 49170 italic: this._italic || false,
michael@0 49171 underline: this._underline || false,
michael@0 49172 url: this._url,
michael@0 49173 target: this._target,
michael@0 49174 align: this._align || 'left',
michael@0 49175 leftMargin: this._leftMargin || 0,
michael@0 49176 rightMargin: this._rightMargin || 0,
michael@0 49177 indent: this._indent || 0,
michael@0 49178 leading: this._leading || 0
michael@0 49179 };
michael@0 49180 },
michael@0 49181 as2GetTextExtent: function (text, width) {
michael@0 49182 if (!measureTextField) {
michael@0 49183 measureTextField = new flash.text.TextField();
michael@0 49184 measureTextField._multiline = true;
michael@0 49185 }
michael@0 49186 if (!isNaN(width) && width > 0) {
michael@0 49187 measureTextField.width = width + 4;
michael@0 49188 measureTextField._wordWrap = true;
michael@0 49189 } else {
michael@0 49190 measureTextField._wordWrap = false;
michael@0 49191 }
michael@0 49192 measureTextField.defaultTextFormat = this;
michael@0 49193 measureTextField.text = text;
michael@0 49194 measureTextField.ensureDimensions();
michael@0 49195 var result = {};
michael@0 49196 var textWidth = measureTextField._textWidth;
michael@0 49197 var textHeight = measureTextField._textHeight;
michael@0 49198 result.asSetPublicProperty('width', textWidth);
michael@0 49199 result.asSetPublicProperty('height', textHeight);
michael@0 49200 result.asSetPublicProperty('textFieldWidth', textWidth + 4);
michael@0 49201 result.asSetPublicProperty('textFieldHeight', textHeight + 4);
michael@0 49202 var metrics = measureTextField.getLineMetrics(0);
michael@0 49203 result.asSetPublicProperty('ascent', metrics.asGetPublicProperty('ascent'));
michael@0 49204 result.asSetPublicProperty('descent', metrics.asGetPublicProperty('descent'));
michael@0 49205 return result;
michael@0 49206 },
michael@0 49207 __glue__: {
michael@0 49208 native: {
michael@0 49209 static: {},
michael@0 49210 instance: {
michael@0 49211 align: {
michael@0 49212 get: function align() {
michael@0 49213 return this._align;
michael@0 49214 },
michael@0 49215 set: function align(value) {
michael@0 49216 this._align = value;
michael@0 49217 }
michael@0 49218 },
michael@0 49219 blockIndent: {
michael@0 49220 get: function blockIndent() {
michael@0 49221 return this._blockIndent;
michael@0 49222 },
michael@0 49223 set: function blockIndent(value) {
michael@0 49224 this._blockIndent = value;
michael@0 49225 }
michael@0 49226 },
michael@0 49227 bold: {
michael@0 49228 get: function bold() {
michael@0 49229 return this._bold;
michael@0 49230 },
michael@0 49231 set: function bold(value) {
michael@0 49232 this._bold = value;
michael@0 49233 }
michael@0 49234 },
michael@0 49235 bullet: {
michael@0 49236 get: function bullet() {
michael@0 49237 return this._bullet;
michael@0 49238 },
michael@0 49239 set: function bullet(value) {
michael@0 49240 this._bullet = value;
michael@0 49241 }
michael@0 49242 },
michael@0 49243 color: {
michael@0 49244 get: function color() {
michael@0 49245 return this._color;
michael@0 49246 },
michael@0 49247 set: function color(value) {
michael@0 49248 this._color = value;
michael@0 49249 }
michael@0 49250 },
michael@0 49251 display: {
michael@0 49252 get: function display() {
michael@0 49253 return this._display;
michael@0 49254 },
michael@0 49255 set: function display(value) {
michael@0 49256 this._display = value;
michael@0 49257 }
michael@0 49258 },
michael@0 49259 font: {
michael@0 49260 get: function font() {
michael@0 49261 return this._font;
michael@0 49262 },
michael@0 49263 set: function font(value) {
michael@0 49264 this._font = value;
michael@0 49265 }
michael@0 49266 },
michael@0 49267 indent: {
michael@0 49268 get: function indent() {
michael@0 49269 return this._indent;
michael@0 49270 },
michael@0 49271 set: function indent(value) {
michael@0 49272 this._indent = value;
michael@0 49273 }
michael@0 49274 },
michael@0 49275 italic: {
michael@0 49276 get: function italic() {
michael@0 49277 return this._italic;
michael@0 49278 },
michael@0 49279 set: function italic(value) {
michael@0 49280 this._italic = value;
michael@0 49281 }
michael@0 49282 },
michael@0 49283 kerning: {
michael@0 49284 get: function kerning() {
michael@0 49285 return this._kerning;
michael@0 49286 },
michael@0 49287 set: function kerning(value) {
michael@0 49288 this._kerning = value;
michael@0 49289 }
michael@0 49290 },
michael@0 49291 leading: {
michael@0 49292 get: function leading() {
michael@0 49293 return this._leading;
michael@0 49294 },
michael@0 49295 set: function leading(value) {
michael@0 49296 this._leading = value;
michael@0 49297 }
michael@0 49298 },
michael@0 49299 leftMargin: {
michael@0 49300 get: function leftMargin() {
michael@0 49301 return this._leftMargin;
michael@0 49302 },
michael@0 49303 set: function leftMargin(value) {
michael@0 49304 this._leftMargin = value;
michael@0 49305 }
michael@0 49306 },
michael@0 49307 letterSpacing: {
michael@0 49308 get: function letterSpacing() {
michael@0 49309 return this._letterSpacing;
michael@0 49310 },
michael@0 49311 set: function letterSpacing(value) {
michael@0 49312 this._letterSpacing = value;
michael@0 49313 }
michael@0 49314 },
michael@0 49315 rightMargin: {
michael@0 49316 get: function rightMargin() {
michael@0 49317 return this._rightMargin;
michael@0 49318 },
michael@0 49319 set: function rightMargin(value) {
michael@0 49320 this._rightMargin = value;
michael@0 49321 }
michael@0 49322 },
michael@0 49323 size: {
michael@0 49324 get: function size() {
michael@0 49325 return this._size;
michael@0 49326 },
michael@0 49327 set: function size(value) {
michael@0 49328 this._size = value;
michael@0 49329 }
michael@0 49330 },
michael@0 49331 tabStops: {
michael@0 49332 get: function tabStops() {
michael@0 49333 return this._tabStops;
michael@0 49334 },
michael@0 49335 set: function tabStops(value) {
michael@0 49336 this._tabStops = value;
michael@0 49337 }
michael@0 49338 },
michael@0 49339 target: {
michael@0 49340 get: function target() {
michael@0 49341 return this._target;
michael@0 49342 },
michael@0 49343 set: function target(value) {
michael@0 49344 this._target = value;
michael@0 49345 }
michael@0 49346 },
michael@0 49347 underline: {
michael@0 49348 get: function underline() {
michael@0 49349 return this._underline;
michael@0 49350 },
michael@0 49351 set: function underline(value) {
michael@0 49352 this._underline = value;
michael@0 49353 }
michael@0 49354 },
michael@0 49355 url: {
michael@0 49356 get: function url() {
michael@0 49357 return this._url;
michael@0 49358 },
michael@0 49359 set: function url(value) {
michael@0 49360 this._url = value;
michael@0 49361 }
michael@0 49362 }
michael@0 49363 }
michael@0 49364 }
michael@0 49365 }
michael@0 49366 };
michael@0 49367 }.call(this);
michael@0 49368 var ContentElementDefinition = function () {
michael@0 49369 return {
michael@0 49370 __class__: 'flash.text.engine.ContentElement',
michael@0 49371 initialize: function () {
michael@0 49372 },
michael@0 49373 __glue__: {
michael@0 49374 native: {
michael@0 49375 static: {},
michael@0 49376 instance: {
michael@0 49377 textBlock: {
michael@0 49378 get: function textBlock() {
michael@0 49379 notImplemented('ContentElement.textBlock');
michael@0 49380 return this._textBlock;
michael@0 49381 }
michael@0 49382 },
michael@0 49383 textBlockBeginIndex: {
michael@0 49384 get: function textBlockBeginIndex() {
michael@0 49385 notImplemented('ContentElement.textBlockBeginIndex');
michael@0 49386 return this._textBlockBeginIndex;
michael@0 49387 }
michael@0 49388 },
michael@0 49389 elementFormat: {
michael@0 49390 get: function elementFormat() {
michael@0 49391 return this._elementFormat;
michael@0 49392 },
michael@0 49393 set: function elementFormat(value) {
michael@0 49394 somewhatImplemented('ContentElement.elementFormat');
michael@0 49395 this._elementFormat = value;
michael@0 49396 }
michael@0 49397 },
michael@0 49398 eventMirror: {
michael@0 49399 get: function eventMirror() {
michael@0 49400 return this._eventMirror;
michael@0 49401 },
michael@0 49402 set: function eventMirror(value) {
michael@0 49403 somewhatImplemented('ContentElement.eventMirror');
michael@0 49404 this._eventMirror = value;
michael@0 49405 }
michael@0 49406 },
michael@0 49407 groupElement: {
michael@0 49408 get: function groupElement() {
michael@0 49409 notImplemented('ContentElement.groupElement');
michael@0 49410 return this._groupElement;
michael@0 49411 }
michael@0 49412 },
michael@0 49413 rawText: {
michael@0 49414 get: function rawText() {
michael@0 49415 notImplemented('ContentElement.rawText');
michael@0 49416 return this._rawText;
michael@0 49417 }
michael@0 49418 },
michael@0 49419 text: {
michael@0 49420 get: function text() {
michael@0 49421 notImplemented('ContentElement.text');
michael@0 49422 return this._text;
michael@0 49423 }
michael@0 49424 },
michael@0 49425 textRotation: {
michael@0 49426 get: function textRotation() {
michael@0 49427 return this._textRotation;
michael@0 49428 },
michael@0 49429 set: function textRotation(value) {
michael@0 49430 somewhatImplemented('ContentElement.textRotation');
michael@0 49431 this._textRotation = value;
michael@0 49432 }
michael@0 49433 }
michael@0 49434 }
michael@0 49435 }
michael@0 49436 }
michael@0 49437 };
michael@0 49438 }.call(this);
michael@0 49439 var ElementFormatDefinition = function () {
michael@0 49440 return {
michael@0 49441 __class__: 'flash.text.engine.ElementFormat',
michael@0 49442 initialize: function () {
michael@0 49443 },
michael@0 49444 __glue__: {
michael@0 49445 native: {
michael@0 49446 static: {},
michael@0 49447 instance: {
michael@0 49448 getFontMetrics: function getFontMetrics() {
michael@0 49449 notImplemented('ElementFormat.getFontMetrics');
michael@0 49450 },
michael@0 49451 alignmentBaseline: {
michael@0 49452 get: function alignmentBaseline() {
michael@0 49453 return this._alignmentBaseline;
michael@0 49454 },
michael@0 49455 set: function alignmentBaseline(alignmentBaseline) {
michael@0 49456 somewhatImplemented('ElementFormat.alignmentBaseline');
michael@0 49457 this._alignmentBaseline = alignmentBaseline;
michael@0 49458 }
michael@0 49459 },
michael@0 49460 alpha: {
michael@0 49461 get: function alpha() {
michael@0 49462 return this._alpha;
michael@0 49463 },
michael@0 49464 set: function alpha(value) {
michael@0 49465 somewhatImplemented('ElementFormat.alpha');
michael@0 49466 this._alpha = value;
michael@0 49467 }
michael@0 49468 },
michael@0 49469 baselineShift: {
michael@0 49470 get: function baselineShift() {
michael@0 49471 return this._baselineShift;
michael@0 49472 },
michael@0 49473 set: function baselineShift(value) {
michael@0 49474 somewhatImplemented('ElementFormat.baselineShift');
michael@0 49475 this._baselineShift = value;
michael@0 49476 }
michael@0 49477 },
michael@0 49478 breakOpportunity: {
michael@0 49479 get: function breakOpportunity() {
michael@0 49480 return this._breakOpportunity;
michael@0 49481 },
michael@0 49482 set: function breakOpportunity(opportunityType) {
michael@0 49483 somewhatImplemented('ElementFormat.breakOpportunity');
michael@0 49484 this._breakOpportunity = opportunityType;
michael@0 49485 }
michael@0 49486 },
michael@0 49487 color: {
michael@0 49488 get: function color() {
michael@0 49489 return this._color;
michael@0 49490 },
michael@0 49491 set: function color(value) {
michael@0 49492 somewhatImplemented('ElementFormat.color');
michael@0 49493 this._color = value;
michael@0 49494 }
michael@0 49495 },
michael@0 49496 dominantBaseline: {
michael@0 49497 get: function dominantBaseline() {
michael@0 49498 return this._dominantBaseline;
michael@0 49499 },
michael@0 49500 set: function dominantBaseline(dominantBaseline) {
michael@0 49501 somewhatImplemented('ElementFormat.dominantBaseline');
michael@0 49502 this._dominantBaseline = dominantBaseline;
michael@0 49503 }
michael@0 49504 },
michael@0 49505 fontDescription: {
michael@0 49506 get: function fontDescription() {
michael@0 49507 return this._fontDescription;
michael@0 49508 },
michael@0 49509 set: function fontDescription(value) {
michael@0 49510 somewhatImplemented('ElementFormat.fontDescription');
michael@0 49511 this._fontDescription = value;
michael@0 49512 }
michael@0 49513 },
michael@0 49514 digitCase: {
michael@0 49515 get: function digitCase() {
michael@0 49516 return this._digitCase;
michael@0 49517 },
michael@0 49518 set: function digitCase(digitCaseType) {
michael@0 49519 somewhatImplemented('ElementFormat.digitCase');
michael@0 49520 this._digitCase = digitCaseType;
michael@0 49521 }
michael@0 49522 },
michael@0 49523 digitWidth: {
michael@0 49524 get: function digitWidth() {
michael@0 49525 return this._digitWidth;
michael@0 49526 },
michael@0 49527 set: function digitWidth(digitWidthType) {
michael@0 49528 somewhatImplemented('ElementFormat.digitWidth');
michael@0 49529 this._digitWidth = digitWidthType;
michael@0 49530 }
michael@0 49531 },
michael@0 49532 ligatureLevel: {
michael@0 49533 get: function ligatureLevel() {
michael@0 49534 return this._ligatureLevel;
michael@0 49535 },
michael@0 49536 set: function ligatureLevel(ligatureLevelType) {
michael@0 49537 somewhatImplemented('ElementFormat.ligatureLevel');
michael@0 49538 this._ligatureLevel = ligatureLevelType;
michael@0 49539 }
michael@0 49540 },
michael@0 49541 fontSize: {
michael@0 49542 get: function fontSize() {
michael@0 49543 return this._fontSize;
michael@0 49544 },
michael@0 49545 set: function fontSize(value) {
michael@0 49546 somewhatImplemented('ElementFormat.fontSize');
michael@0 49547 this._fontSize = value;
michael@0 49548 }
michael@0 49549 },
michael@0 49550 kerning: {
michael@0 49551 get: function kerning() {
michael@0 49552 return this._kerning;
michael@0 49553 },
michael@0 49554 set: function kerning(value) {
michael@0 49555 somewhatImplemented('ElementFormat.kerning');
michael@0 49556 this._kerning = value;
michael@0 49557 }
michael@0 49558 },
michael@0 49559 locale: {
michael@0 49560 get: function locale() {
michael@0 49561 return this._locale;
michael@0 49562 },
michael@0 49563 set: function locale(value) {
michael@0 49564 somewhatImplemented('ElementFormat.locale');
michael@0 49565 this._locale = value;
michael@0 49566 }
michael@0 49567 },
michael@0 49568 textRotation: {
michael@0 49569 get: function textRotation() {
michael@0 49570 return this._textRotation;
michael@0 49571 },
michael@0 49572 set: function textRotation(value) {
michael@0 49573 somewhatImplemented('ElementFormat.textRotation');
michael@0 49574 this._textRotation = value;
michael@0 49575 }
michael@0 49576 },
michael@0 49577 trackingRight: {
michael@0 49578 get: function trackingRight() {
michael@0 49579 return this._trackingRight;
michael@0 49580 },
michael@0 49581 set: function trackingRight(value) {
michael@0 49582 somewhatImplemented('ElementFormat.trackingRight');
michael@0 49583 this._trackingRight = value;
michael@0 49584 }
michael@0 49585 },
michael@0 49586 trackingLeft: {
michael@0 49587 get: function trackingLeft() {
michael@0 49588 return this._trackingLeft;
michael@0 49589 },
michael@0 49590 set: function trackingLeft(value) {
michael@0 49591 somewhatImplemented('ElementFormat.trackingLeft');
michael@0 49592 this._trackingLeft = value;
michael@0 49593 }
michael@0 49594 },
michael@0 49595 typographicCase: {
michael@0 49596 get: function typographicCase() {
michael@0 49597 return this._typographicCase;
michael@0 49598 },
michael@0 49599 set: function typographicCase(typographicCaseType) {
michael@0 49600 somewhatImplemented('ElementFormat.typographicCase');
michael@0 49601 this._typographicCase = typographicCaseType;
michael@0 49602 }
michael@0 49603 },
michael@0 49604 locked: {
michael@0 49605 get: function locked() {
michael@0 49606 notImplemented('ElementFormat.locked');
michael@0 49607 return this._locked;
michael@0 49608 },
michael@0 49609 set: function locked(value) {
michael@0 49610 notImplemented('ElementFormat.locked');
michael@0 49611 this._locked = value;
michael@0 49612 }
michael@0 49613 }
michael@0 49614 }
michael@0 49615 }
michael@0 49616 }
michael@0 49617 };
michael@0 49618 }.call(this);
michael@0 49619 var FontDescriptionDefinition = function () {
michael@0 49620 return {
michael@0 49621 __class__: 'flash.text.engine.FontDescription',
michael@0 49622 initialize: function () {
michael@0 49623 },
michael@0 49624 __glue__: {
michael@0 49625 native: {
michael@0 49626 static: {
michael@0 49627 isFontCompatible: function isFontCompatible(fontName, fontWeight, fontPosture) {
michael@0 49628 notImplemented('FontDescription.isFontCompatible');
michael@0 49629 },
michael@0 49630 isDeviceFontCompatible: function isDeviceFontCompatible(fontName, fontWeight, fontPosture) {
michael@0 49631 notImplemented('FontDescription.isDeviceFontCompatible');
michael@0 49632 }
michael@0 49633 },
michael@0 49634 instance: {
michael@0 49635 renderingMode: {
michael@0 49636 get: function renderingMode() {
michael@0 49637 return this._renderingMode;
michael@0 49638 },
michael@0 49639 set: function renderingMode(value) {
michael@0 49640 somewhatImplemented('FontDescription.renderingMode');
michael@0 49641 this._renderingMode = value;
michael@0 49642 }
michael@0 49643 },
michael@0 49644 fontLookup: {
michael@0 49645 get: function fontLookup() {
michael@0 49646 return this._fontLookup;
michael@0 49647 },
michael@0 49648 set: function fontLookup(value) {
michael@0 49649 somewhatImplemented('FontDescription.fontLookup');
michael@0 49650 this._fontLookup = value;
michael@0 49651 }
michael@0 49652 },
michael@0 49653 fontName: {
michael@0 49654 get: function fontName() {
michael@0 49655 return this._fontName;
michael@0 49656 },
michael@0 49657 set: function fontName(value) {
michael@0 49658 somewhatImplemented('FontDescription.fontName');
michael@0 49659 this._fontName = value;
michael@0 49660 }
michael@0 49661 },
michael@0 49662 fontPosture: {
michael@0 49663 get: function fontPosture() {
michael@0 49664 return this._fontPosture;
michael@0 49665 },
michael@0 49666 set: function fontPosture(value) {
michael@0 49667 somewhatImplemented('FontDescription.fontPosture');
michael@0 49668 this._fontPosture = value;
michael@0 49669 }
michael@0 49670 },
michael@0 49671 fontWeight: {
michael@0 49672 get: function fontWeight() {
michael@0 49673 return this._fontWeight;
michael@0 49674 },
michael@0 49675 set: function fontWeight(value) {
michael@0 49676 somewhatImplemented('FontDescription.fontWeight');
michael@0 49677 this._fontWeight = value;
michael@0 49678 }
michael@0 49679 },
michael@0 49680 cffHinting: {
michael@0 49681 get: function cffHinting() {
michael@0 49682 return this._cffHinting;
michael@0 49683 },
michael@0 49684 set: function cffHinting(value) {
michael@0 49685 somewhatImplemented('FontDescription.cffHinting');
michael@0 49686 this._cffHinting = value;
michael@0 49687 }
michael@0 49688 },
michael@0 49689 locked: {
michael@0 49690 get: function locked() {
michael@0 49691 notImplemented('FontDescription.locked');
michael@0 49692 return this._locked;
michael@0 49693 },
michael@0 49694 set: function locked(value) {
michael@0 49695 notImplemented('FontDescription.locked');
michael@0 49696 this._locked = value;
michael@0 49697 }
michael@0 49698 }
michael@0 49699 }
michael@0 49700 },
michael@0 49701 script: {
michael@0 49702 static: {},
michael@0 49703 instance: {}
michael@0 49704 }
michael@0 49705 }
michael@0 49706 };
michael@0 49707 }.call(this);
michael@0 49708 var GroupElementDefinition = function () {
michael@0 49709 return {
michael@0 49710 __class__: 'flash.text.engine.GroupElement',
michael@0 49711 initialize: function () {
michael@0 49712 },
michael@0 49713 __glue__: {
michael@0 49714 native: {
michael@0 49715 static: {},
michael@0 49716 instance: {
michael@0 49717 getElementAt: function getElementAt(index) {
michael@0 49718 notImplemented('GroupElement.getElementAt');
michael@0 49719 },
michael@0 49720 setElements: function setElements(value) {
michael@0 49721 somewhatImplemented('GroupElement.setElements');
michael@0 49722 this._elements = value;
michael@0 49723 },
michael@0 49724 groupElements: function groupElements(beginIndex, endIndex) {
michael@0 49725 notImplemented('GroupElement.groupElements');
michael@0 49726 },
michael@0 49727 ungroupElements: function ungroupElements(groupIndex) {
michael@0 49728 notImplemented('GroupElement.ungroupElements');
michael@0 49729 },
michael@0 49730 mergeTextElements: function mergeTextElements(beginIndex, endIndex) {
michael@0 49731 notImplemented('GroupElement.mergeTextElements');
michael@0 49732 },
michael@0 49733 splitTextElement: function splitTextElement(elementIndex, splitIndex) {
michael@0 49734 notImplemented('GroupElement.splitTextElement');
michael@0 49735 },
michael@0 49736 replaceElements: function replaceElements(beginIndex, endIndex, newElements) {
michael@0 49737 notImplemented('GroupElement.replaceElements');
michael@0 49738 },
michael@0 49739 getElementAtCharIndex: function getElementAtCharIndex(charIndex) {
michael@0 49740 notImplemented('GroupElement.getElementAtCharIndex');
michael@0 49741 },
michael@0 49742 elementCount: {
michael@0 49743 get: function elementCount() {
michael@0 49744 notImplemented('GroupElement.elementCount');
michael@0 49745 return this._elementCount;
michael@0 49746 }
michael@0 49747 }
michael@0 49748 }
michael@0 49749 }
michael@0 49750 }
michael@0 49751 };
michael@0 49752 }.call(this);
michael@0 49753 var SpaceJustifierDefinition = function () {
michael@0 49754 return {
michael@0 49755 __class__: 'flash.text.engine.SpaceJustifier',
michael@0 49756 initialize: function () {
michael@0 49757 this._letterSpacing = false;
michael@0 49758 this._optimumSpacing = 1;
michael@0 49759 this._minimumSpacing = 0.5;
michael@0 49760 this._maximumSpacing = 1.5;
michael@0 49761 },
michael@0 49762 __glue__: {
michael@0 49763 native: {
michael@0 49764 static: {},
michael@0 49765 instance: {
michael@0 49766 cloneSpacing: function cloneSpacing(justifier) {
michael@0 49767 somewhatImplemented('SpaceJustifier.cloneSpacing');
michael@0 49768 justifier._optimumSpacing = this._optimumSpacing;
michael@0 49769 justifier._minimumSpacing = this._minimumSpacing;
michael@0 49770 justifier._maximumSpacing = this._maximumSpacing;
michael@0 49771 },
michael@0 49772 letterSpacing: {
michael@0 49773 get: function letterSpacing() {
michael@0 49774 return this._letterSpacing;
michael@0 49775 },
michael@0 49776 set: function letterSpacing(value) {
michael@0 49777 somewhatImplemented('SpaceJustifier.letterSpacing');
michael@0 49778 this._letterSpacing = value;
michael@0 49779 }
michael@0 49780 },
michael@0 49781 minimumSpacing: {
michael@0 49782 get: function minimumSpacing() {
michael@0 49783 return this._minimumSpacing;
michael@0 49784 },
michael@0 49785 set: function minimumSpacing(value) {
michael@0 49786 somewhatImplemented('SpaceJustifier.minimumSpacing');
michael@0 49787 this._minimumSpacing = value;
michael@0 49788 }
michael@0 49789 },
michael@0 49790 optimumSpacing: {
michael@0 49791 get: function optimumSpacing() {
michael@0 49792 return this._optimumSpacing;
michael@0 49793 },
michael@0 49794 set: function optimumSpacing(value) {
michael@0 49795 somewhatImplemented('SpaceJustifier.optimumSpacing');
michael@0 49796 this._optimumSpacing = value;
michael@0 49797 }
michael@0 49798 },
michael@0 49799 maximumSpacing: {
michael@0 49800 get: function maximumSpacing() {
michael@0 49801 return this._maximumSpacing;
michael@0 49802 },
michael@0 49803 set: function maximumSpacing(value) {
michael@0 49804 somewhatImplemented('SpaceJustifier.maximumSpacing');
michael@0 49805 this._maximumSpacing = value;
michael@0 49806 }
michael@0 49807 }
michael@0 49808 }
michael@0 49809 }
michael@0 49810 }
michael@0 49811 };
michael@0 49812 }.call(this);
michael@0 49813 var TextBlockDefinition = function () {
michael@0 49814 return {
michael@0 49815 __class__: 'flash.text.engine.TextBlock',
michael@0 49816 initialize: function () {
michael@0 49817 this._firstLine = null;
michael@0 49818 this._lastLine = null;
michael@0 49819 },
michael@0 49820 __glue__: {
michael@0 49821 native: {
michael@0 49822 static: {},
michael@0 49823 instance: {
michael@0 49824 getTextJustifier: function getTextJustifier() {
michael@0 49825 return this._textJustifier;
michael@0 49826 },
michael@0 49827 setTextJustifier: function setTextJustifier(value) {
michael@0 49828 somewhatImplemented('TextBlock.setTextJustifier');
michael@0 49829 this._textJustifier = value;
michael@0 49830 },
michael@0 49831 getTabStops: function getTabStops() {
michael@0 49832 return this._tabStops;
michael@0 49833 },
michael@0 49834 setTabStops: function setTabStops(value) {
michael@0 49835 somewhatImplemented('TextBlock.setTabStops');
michael@0 49836 this._tabStops = value;
michael@0 49837 },
michael@0 49838 findNextAtomBoundary: function findNextAtomBoundary(afterCharIndex) {
michael@0 49839 notImplemented('TextBlock.findNextAtomBoundary');
michael@0 49840 },
michael@0 49841 findPreviousAtomBoundary: function findPreviousAtomBoundary(beforeCharIndex) {
michael@0 49842 notImplemented('TextBlock.findPreviousAtomBoundary');
michael@0 49843 },
michael@0 49844 findNextWordBoundary: function findNextWordBoundary(afterCharIndex) {
michael@0 49845 notImplemented('TextBlock.findNextWordBoundary');
michael@0 49846 },
michael@0 49847 findPreviousWordBoundary: function findPreviousWordBoundary(beforeCharIndex) {
michael@0 49848 notImplemented('TextBlock.findPreviousWordBoundary');
michael@0 49849 },
michael@0 49850 getTextLineAtCharIndex: function getTextLineAtCharIndex(charIndex) {
michael@0 49851 notImplemented('TextBlock.getTextLineAtCharIndex');
michael@0 49852 },
michael@0 49853 DoCreateTextLine: function DoCreateTextLine(previousLine, width, lineOffset, fitSomething, reuseLine) {
michael@0 49854 somewhatImplemented('TextBlock.DoCreateTextLine');
michael@0 49855 if (previousLine) {
michael@0 49856 return null;
michael@0 49857 }
michael@0 49858 var textLine = new flash.text.engine.TextLine();
michael@0 49859 textLine._textBlock = this;
michael@0 49860 textLine._specifiedWidth = width;
michael@0 49861 textLine._rawTextLength = 0;
michael@0 49862 textLine._textWidth = 0;
michael@0 49863 textLine._textHeight = 0;
michael@0 49864 textLine._ascent = 0;
michael@0 49865 textLine._descent = 0;
michael@0 49866 textLine._unjustifiedTextWidth = 0;
michael@0 49867 textLine._validity = 'valid';
michael@0 49868 textLine._previousLine = null;
michael@0 49869 textLine._nextLine = null;
michael@0 49870 this._firstLine = textLine;
michael@0 49871 this._lastLine = textLine;
michael@0 49872 return textLine;
michael@0 49873 },
michael@0 49874 releaseLineCreationData: function releaseLineCreationData() {
michael@0 49875 notImplemented('TextBlock.releaseLineCreationData');
michael@0 49876 },
michael@0 49877 releaseLines: function releaseLines(firstLine, lastLine) {
michael@0 49878 notImplemented('TextBlock.releaseLines');
michael@0 49879 },
michael@0 49880 dump: function dump() {
michael@0 49881 notImplemented('TextBlock.dump');
michael@0 49882 },
michael@0 49883 applyNonLinearFontScaling: {
michael@0 49884 get: function applyNonLinearFontScaling() {
michael@0 49885 return this._applyNonLinearFontScaling;
michael@0 49886 },
michael@0 49887 set: function applyNonLinearFontScaling(value) {
michael@0 49888 somewhatImplemented('TextBlock.applyNonLinearFontScaling');
michael@0 49889 this._applyNonLinearFontScaling = value;
michael@0 49890 }
michael@0 49891 },
michael@0 49892 baselineFontDescription: {
michael@0 49893 get: function baselineFontDescription() {
michael@0 49894 return this._baselineFontDescription;
michael@0 49895 },
michael@0 49896 set: function baselineFontDescription(value) {
michael@0 49897 somewhatImplemented('TextBlock.baselineFontDescription');
michael@0 49898 this._baselineFontDescription = value;
michael@0 49899 }
michael@0 49900 },
michael@0 49901 baselineFontSize: {
michael@0 49902 get: function baselineFontSize() {
michael@0 49903 return this._baselineFontSize;
michael@0 49904 },
michael@0 49905 set: function baselineFontSize(value) {
michael@0 49906 somewhatImplemented('TextBlock.baselineFontSize');
michael@0 49907 this._baselineFontSize = value;
michael@0 49908 }
michael@0 49909 },
michael@0 49910 baselineZero: {
michael@0 49911 get: function baselineZero() {
michael@0 49912 return this._baselineZero;
michael@0 49913 },
michael@0 49914 set: function baselineZero(value) {
michael@0 49915 somewhatImplemented('TextBlock.baselineZero');
michael@0 49916 this._baselineZero = value;
michael@0 49917 }
michael@0 49918 },
michael@0 49919 content: {
michael@0 49920 get: function content() {
michael@0 49921 return this._content;
michael@0 49922 },
michael@0 49923 set: function content(value) {
michael@0 49924 somewhatImplemented('TextBlock.content');
michael@0 49925 this._content = value;
michael@0 49926 }
michael@0 49927 },
michael@0 49928 bidiLevel: {
michael@0 49929 get: function bidiLevel() {
michael@0 49930 return this._bidiLevel;
michael@0 49931 },
michael@0 49932 set: function bidiLevel(value) {
michael@0 49933 somewhatImplemented('TextBlock.bidiLevel');
michael@0 49934 this._bidiLevel = value;
michael@0 49935 }
michael@0 49936 },
michael@0 49937 firstInvalidLine: {
michael@0 49938 get: function firstInvalidLine() {
michael@0 49939 notImplemented('TextBlock.firstInvalidLine');
michael@0 49940 return this._firstInvalidLine;
michael@0 49941 }
michael@0 49942 },
michael@0 49943 firstLine: {
michael@0 49944 get: function firstLine() {
michael@0 49945 somewhatImplemented('TextBlock.firstLine');
michael@0 49946 return this._firstLine;
michael@0 49947 }
michael@0 49948 },
michael@0 49949 lastLine: {
michael@0 49950 get: function lastLine() {
michael@0 49951 somewhatImplemented('TextBlock.lastLine');
michael@0 49952 return this._lastLine;
michael@0 49953 }
michael@0 49954 },
michael@0 49955 textLineCreationResult: {
michael@0 49956 get: function textLineCreationResult() {
michael@0 49957 notImplemented('TextBlock.textLineCreationResult');
michael@0 49958 return this._textLineCreationResult;
michael@0 49959 }
michael@0 49960 },
michael@0 49961 lineRotation: {
michael@0 49962 get: function lineRotation() {
michael@0 49963 return this._lineRotation;
michael@0 49964 },
michael@0 49965 set: function lineRotation(value) {
michael@0 49966 somewhatImplemented('TextBlock.lineRotation');
michael@0 49967 this._lineRotation = value;
michael@0 49968 }
michael@0 49969 }
michael@0 49970 }
michael@0 49971 }
michael@0 49972 }
michael@0 49973 };
michael@0 49974 }.call(this);
michael@0 49975 var TextElementDefinition = function () {
michael@0 49976 return {
michael@0 49977 __class__: 'flash.text.engine.TextElement',
michael@0 49978 initialize: function () {
michael@0 49979 },
michael@0 49980 __glue__: {
michael@0 49981 native: {
michael@0 49982 static: {},
michael@0 49983 instance: {
michael@0 49984 replaceText: function replaceText(beginIndex, endIndex, newText) {
michael@0 49985 somewhatImplemented('TextElement.replaceText');
michael@0 49986 var text = this._text || '';
michael@0 49987 this._text = text.slice(0, beginIndex) + newText + text.slice(endIndex);
michael@0 49988 },
michael@0 49989 text: {
michael@0 49990 set: function text(value) {
michael@0 49991 somewhatImplemented('TextElement.text');
michael@0 49992 this._text = value;
michael@0 49993 }
michael@0 49994 }
michael@0 49995 }
michael@0 49996 }
michael@0 49997 }
michael@0 49998 };
michael@0 49999 }.call(this);
michael@0 50000 var TextJustifierDefinition = function () {
michael@0 50001 return {
michael@0 50002 __class__: 'flash.text.engine.TextJustifier',
michael@0 50003 initialize: function () {
michael@0 50004 this._locale = null;
michael@0 50005 this._lineJustification = null;
michael@0 50006 },
michael@0 50007 __glue__: {
michael@0 50008 native: {
michael@0 50009 static: {},
michael@0 50010 instance: {
michael@0 50011 setLocale: function setLocale(value) {
michael@0 50012 somewhatImplemented('TextJustifier.setLocale');
michael@0 50013 this._locale = value;
michael@0 50014 },
michael@0 50015 locale: {
michael@0 50016 get: function locale() {
michael@0 50017 return this._locale;
michael@0 50018 }
michael@0 50019 },
michael@0 50020 lineJustification: {
michael@0 50021 get: function lineJustification() {
michael@0 50022 return this._lineJustification;
michael@0 50023 },
michael@0 50024 set: function lineJustification(value) {
michael@0 50025 somewhatImplemented('TextJustifier.lineJustification');
michael@0 50026 this._lineJustification = value;
michael@0 50027 }
michael@0 50028 }
michael@0 50029 }
michael@0 50030 }
michael@0 50031 }
michael@0 50032 };
michael@0 50033 }.call(this);
michael@0 50034 var TextLineDefinition = function () {
michael@0 50035 return {
michael@0 50036 __class__: 'flash.text.engine.TextLine',
michael@0 50037 initialize: function () {
michael@0 50038 },
michael@0 50039 __glue__: {
michael@0 50040 native: {
michael@0 50041 static: {},
michael@0 50042 instance: {
michael@0 50043 getAtomIndexAtPoint: function getAtomIndexAtPoint(stageX, stageY) {
michael@0 50044 notImplemented('TextLine.getAtomIndexAtPoint');
michael@0 50045 },
michael@0 50046 getAtomIndexAtCharIndex: function getAtomIndexAtCharIndex(charIndex) {
michael@0 50047 notImplemented('TextLine.getAtomIndexAtCharIndex');
michael@0 50048 },
michael@0 50049 getAtomBounds: function getAtomBounds(atomIndex) {
michael@0 50050 notImplemented('TextLine.getAtomBounds');
michael@0 50051 },
michael@0 50052 getAtomBidiLevel: function getAtomBidiLevel(atomIndex) {
michael@0 50053 notImplemented('TextLine.getAtomBidiLevel');
michael@0 50054 },
michael@0 50055 getAtomTextRotation: function getAtomTextRotation(atomIndex) {
michael@0 50056 notImplemented('TextLine.getAtomTextRotation');
michael@0 50057 },
michael@0 50058 getAtomTextBlockBeginIndex: function getAtomTextBlockBeginIndex(atomIndex) {
michael@0 50059 notImplemented('TextLine.getAtomTextBlockBeginIndex');
michael@0 50060 },
michael@0 50061 getAtomTextBlockEndIndex: function getAtomTextBlockEndIndex(atomIndex) {
michael@0 50062 notImplemented('TextLine.getAtomTextBlockEndIndex');
michael@0 50063 },
michael@0 50064 getAtomCenter: function getAtomCenter(atomIndex) {
michael@0 50065 notImplemented('TextLine.getAtomCenter');
michael@0 50066 },
michael@0 50067 getAtomWordBoundaryOnLeft: function getAtomWordBoundaryOnLeft(atomIndex) {
michael@0 50068 notImplemented('TextLine.getAtomWordBoundaryOnLeft');
michael@0 50069 },
michael@0 50070 getAtomGraphic: function getAtomGraphic(atomIndex) {
michael@0 50071 notImplemented('TextLine.getAtomGraphic');
michael@0 50072 },
michael@0 50073 getBaselinePosition: function getBaselinePosition(baseline) {
michael@0 50074 notImplemented('TextLine.getBaselinePosition');
michael@0 50075 },
michael@0 50076 dump: function dump() {
michael@0 50077 notImplemented('TextLine.dump');
michael@0 50078 },
michael@0 50079 textBlock: {
michael@0 50080 get: function textBlock() {
michael@0 50081 notImplemented('TextLine.textBlock');
michael@0 50082 return this._textBlock;
michael@0 50083 }
michael@0 50084 },
michael@0 50085 hasGraphicElement: {
michael@0 50086 get: function hasGraphicElement() {
michael@0 50087 notImplemented('TextLine.hasGraphicElement');
michael@0 50088 return this._hasGraphicElement;
michael@0 50089 }
michael@0 50090 },
michael@0 50091 hasTabs: {
michael@0 50092 get: function hasTabs() {
michael@0 50093 notImplemented('TextLine.hasTabs');
michael@0 50094 return this._hasTabs;
michael@0 50095 }
michael@0 50096 },
michael@0 50097 nextLine: {
michael@0 50098 get: function nextLine() {
michael@0 50099 somewhatImplemented('TextLine.nextLine');
michael@0 50100 return this._nextLine;
michael@0 50101 }
michael@0 50102 },
michael@0 50103 previousLine: {
michael@0 50104 get: function previousLine() {
michael@0 50105 somewhatImplemented('TextLine.previousLine');
michael@0 50106 return this._previousLine;
michael@0 50107 }
michael@0 50108 },
michael@0 50109 ascent: {
michael@0 50110 get: function ascent() {
michael@0 50111 somewhatImplemented('TextLine.ascent');
michael@0 50112 return this._ascent;
michael@0 50113 }
michael@0 50114 },
michael@0 50115 descent: {
michael@0 50116 get: function descent() {
michael@0 50117 somewhatImplemented('TextLine.descent');
michael@0 50118 return this._descent;
michael@0 50119 }
michael@0 50120 },
michael@0 50121 textHeight: {
michael@0 50122 get: function textHeight() {
michael@0 50123 somewhatImplemented('TextLine.textHeight');
michael@0 50124 return this._textHeight;
michael@0 50125 }
michael@0 50126 },
michael@0 50127 textWidth: {
michael@0 50128 get: function textWidth() {
michael@0 50129 somewhatImplemented('TextLine.textWidth');
michael@0 50130 return this._textWidth;
michael@0 50131 }
michael@0 50132 },
michael@0 50133 totalAscent: {
michael@0 50134 get: function totalAscent() {
michael@0 50135 notImplemented('TextLine.totalAscent');
michael@0 50136 return this._totalAscent;
michael@0 50137 }
michael@0 50138 },
michael@0 50139 totalDescent: {
michael@0 50140 get: function totalDescent() {
michael@0 50141 notImplemented('TextLine.totalDescent');
michael@0 50142 return this._totalDescent;
michael@0 50143 }
michael@0 50144 },
michael@0 50145 totalHeight: {
michael@0 50146 get: function totalHeight() {
michael@0 50147 notImplemented('TextLine.totalHeight');
michael@0 50148 return this._totalHeight;
michael@0 50149 }
michael@0 50150 },
michael@0 50151 textBlockBeginIndex: {
michael@0 50152 get: function textBlockBeginIndex() {
michael@0 50153 notImplemented('TextLine.textBlockBeginIndex');
michael@0 50154 return this._textBlockBeginIndex;
michael@0 50155 }
michael@0 50156 },
michael@0 50157 rawTextLength: {
michael@0 50158 get: function rawTextLength() {
michael@0 50159 somewhatImplemented('TextLine.rawTextLength');
michael@0 50160 return this._rawTextLength;
michael@0 50161 }
michael@0 50162 },
michael@0 50163 specifiedWidth: {
michael@0 50164 get: function specifiedWidth() {
michael@0 50165 somewhatImplemented('TextLine.specifiedWidth');
michael@0 50166 return this._specifiedWidth;
michael@0 50167 }
michael@0 50168 },
michael@0 50169 unjustifiedTextWidth: {
michael@0 50170 get: function unjustifiedTextWidth() {
michael@0 50171 somewhatImplemented('TextLine.unjustifiedTextWidth');
michael@0 50172 return this._unjustifiedTextWidth;
michael@0 50173 }
michael@0 50174 },
michael@0 50175 validity: {
michael@0 50176 get: function validity() {
michael@0 50177 return this._validity;
michael@0 50178 },
michael@0 50179 set: function validity(value) {
michael@0 50180 somewhatImplemented('TextLine.validity');
michael@0 50181 this._validity = value;
michael@0 50182 }
michael@0 50183 },
michael@0 50184 atomCount: {
michael@0 50185 get: function atomCount() {
michael@0 50186 notImplemented('TextLine.atomCount');
michael@0 50187 return this._atomCount;
michael@0 50188 }
michael@0 50189 },
michael@0 50190 mirrorRegions: {
michael@0 50191 get: function mirrorRegions() {
michael@0 50192 notImplemented('TextLine.mirrorRegions');
michael@0 50193 return this._mirrorRegions;
michael@0 50194 }
michael@0 50195 }
michael@0 50196 }
michael@0 50197 }
michael@0 50198 }
michael@0 50199 };
michael@0 50200 }.call(this);
michael@0 50201 {
michael@0 50202 var ContextMenuDefinition = function () {
michael@0 50203 return {
michael@0 50204 __class__: 'flash.ui.ContextMenu',
michael@0 50205 initialize: function () {
michael@0 50206 },
michael@0 50207 __glue__: {
michael@0 50208 native: {
michael@0 50209 static: {
michael@0 50210 _checkSupported: function _checkSupported() {
michael@0 50211 notImplemented('ContextMenu._checkSupported');
michael@0 50212 }
michael@0 50213 },
michael@0 50214 instance: {
michael@0 50215 cloneLinkAndClipboardProperties: function cloneLinkAndClipboardProperties(c) {
michael@0 50216 notImplemented('ContextMenu.cloneLinkAndClipboardProperties');
michael@0 50217 },
michael@0 50218 builtInItems: {
michael@0 50219 get: function builtInItems() {
michael@0 50220 somewhatImplemented('ContextMenu.builtInItems');
michael@0 50221 return this._builtInItems;
michael@0 50222 },
michael@0 50223 set: function builtInItems(value) {
michael@0 50224 somewhatImplemented('ContextMenu.builtInItems');
michael@0 50225 this._builtInItems = value;
michael@0 50226 }
michael@0 50227 },
michael@0 50228 customItems: {
michael@0 50229 get: function customItems() {
michael@0 50230 somewhatImplemented('ContextMenu.customItems');
michael@0 50231 return this._customItems;
michael@0 50232 },
michael@0 50233 set: function customItems(value) {
michael@0 50234 somewhatImplemented('ContextMenu.customItems');
michael@0 50235 this._customItems = value;
michael@0 50236 }
michael@0 50237 },
michael@0 50238 link: {
michael@0 50239 get: function link() {
michael@0 50240 notImplemented('ContextMenu.link');
michael@0 50241 return this._link;
michael@0 50242 },
michael@0 50243 set: function link(value) {
michael@0 50244 notImplemented('ContextMenu.link');
michael@0 50245 this._link = value;
michael@0 50246 }
michael@0 50247 },
michael@0 50248 clipboardMenu: {
michael@0 50249 get: function clipboardMenu() {
michael@0 50250 notImplemented('ContextMenu.clipboardMenu');
michael@0 50251 return this._clipboardMenu;
michael@0 50252 },
michael@0 50253 set: function clipboardMenu(value) {
michael@0 50254 notImplemented('ContextMenu.clipboardMenu');
michael@0 50255 this._clipboardMenu = value;
michael@0 50256 }
michael@0 50257 },
michael@0 50258 clipboardItems: {
michael@0 50259 get: function clipboardItems() {
michael@0 50260 notImplemented('ContextMenu.clipboardItems');
michael@0 50261 return this._clipboardItems;
michael@0 50262 },
michael@0 50263 set: function clipboardItems(value) {
michael@0 50264 notImplemented('ContextMenu.clipboardItems');
michael@0 50265 this._clipboardItems = value;
michael@0 50266 }
michael@0 50267 }
michael@0 50268 }
michael@0 50269 }
michael@0 50270 }
michael@0 50271 };
michael@0 50272 }.call(this);
michael@0 50273 }
michael@0 50274 var ContextMenuItemDefinition = function () {
michael@0 50275 return {
michael@0 50276 __class__: 'flash.ui.ContextMenuItem',
michael@0 50277 initialize: function () {
michael@0 50278 },
michael@0 50279 __glue__: {
michael@0 50280 native: {
michael@0 50281 static: {},
michael@0 50282 instance: {
michael@0 50283 caption: {
michael@0 50284 get: function caption() {
michael@0 50285 somewhatImplemented('ContextMenuItem.caption');
michael@0 50286 return this._caption;
michael@0 50287 },
michael@0 50288 set: function caption(value) {
michael@0 50289 somewhatImplemented('ContextMenuItem.caption');
michael@0 50290 this._caption = value;
michael@0 50291 }
michael@0 50292 },
michael@0 50293 separatorBefore: {
michael@0 50294 get: function separatorBefore() {
michael@0 50295 somewhatImplemented('ContextMenuItem.separatorBefore');
michael@0 50296 return this._separatorBefore;
michael@0 50297 },
michael@0 50298 set: function separatorBefore(value) {
michael@0 50299 somewhatImplemented('ContextMenuItem.separatorBefore');
michael@0 50300 this._separatorBefore = value;
michael@0 50301 }
michael@0 50302 },
michael@0 50303 visible: {
michael@0 50304 get: function visible() {
michael@0 50305 somewhatImplemented('ContextMenuItem.visible');
michael@0 50306 return this._visible;
michael@0 50307 },
michael@0 50308 set: function visible(value) {
michael@0 50309 somewhatImplemented('ContextMenuItem.visible');
michael@0 50310 this._visible = value;
michael@0 50311 }
michael@0 50312 }
michael@0 50313 }
michael@0 50314 }
michael@0 50315 }
michael@0 50316 };
michael@0 50317 }.call(this);
michael@0 50318 var ShumwayKeyboardListener = {
michael@0 50319 _lastKeyCode: 0,
michael@0 50320 _captureKeyPress: false,
michael@0 50321 _charCodeMap: [],
michael@0 50322 focus: null,
michael@0 50323 handleEvent: function (domEvt) {
michael@0 50324 var keyCode = domEvt.keyCode;
michael@0 50325 if (domEvt.type === 'keydown') {
michael@0 50326 this._lastKeyCode = keyCode;
michael@0 50327 this._captureKeyPress = keyCode === 8 || keyCode === 9 || keyCode === 13 || keyCode === 32 || keyCode >= 48 && keyCode <= 90 || keyCode > 145;
michael@0 50328 if (this._captureKeyPress) {
michael@0 50329 return;
michael@0 50330 }
michael@0 50331 this._charCodeMap[keyCode] = 0;
michael@0 50332 } else if (domEvt.type === 'keypress') {
michael@0 50333 if (this._captureKeyPress) {
michael@0 50334 keyCode = this._lastKeyCode;
michael@0 50335 this._charCodeMap[keyCode] = domEvt.charCode;
michael@0 50336 } else {
michael@0 50337 return;
michael@0 50338 }
michael@0 50339 }
michael@0 50340 if (this.focus) {
michael@0 50341 this.focus._dispatchEvent(new flash.events.KeyboardEvent(domEvt.type === 'keyup' ? 'keyUp' : 'keyDown', true, false, domEvt.type === 'keyup' ? this._charCodeMap[keyCode] : domEvt.charCode, domEvt.type === 'keyup' ? domEvt.keyCode : this._lastKeyCode, domEvt.keyLocation, domEvt.ctrlKey, domEvt.altKey, domEvt.shiftKey));
michael@0 50342 }
michael@0 50343 }
michael@0 50344 };
michael@0 50345 window.addEventListener('keydown', ShumwayKeyboardListener);
michael@0 50346 window.addEventListener('keypress', ShumwayKeyboardListener);
michael@0 50347 window.addEventListener('keyup', ShumwayKeyboardListener);
michael@0 50348 var KeyboardDefinition = function () {
michael@0 50349 var def = {
michael@0 50350 get capsLock() {
michael@0 50351 return false;
michael@0 50352 },
michael@0 50353 get hasVirtualKeyboard() {
michael@0 50354 return false;
michael@0 50355 },
michael@0 50356 get numLock() {
michael@0 50357 return false;
michael@0 50358 },
michael@0 50359 get physicalKeyboardType() {
michael@0 50360 return 'alphanumeric';
michael@0 50361 },
michael@0 50362 get isAccessible() {
michael@0 50363 return true;
michael@0 50364 }
michael@0 50365 };
michael@0 50366 var desc = Object.getOwnPropertyDescriptor;
michael@0 50367 def.__glue__ = {
michael@0 50368 script: {
michael@0 50369 static: scriptProperties('public', [
michael@0 50370 'A',
michael@0 50371 'ALTERNATE',
michael@0 50372 'AUDIO',
michael@0 50373 'B',
michael@0 50374 'BACK',
michael@0 50375 'BACKQUOTE',
michael@0 50376 'BACKSLASH',
michael@0 50377 'BACKSPACE',
michael@0 50378 'BLUE',
michael@0 50379 'C',
michael@0 50380 'CAPS_LOCK',
michael@0 50381 'CHANNEL_DOWN',
michael@0 50382 'CHANNEL_UP',
michael@0 50383 'COMMA',
michael@0 50384 'COMMAND',
michael@0 50385 'CONTROL',
michael@0 50386 'D',
michael@0 50387 'DELETE',
michael@0 50388 'DOWN',
michael@0 50389 'DVR',
michael@0 50390 'E',
michael@0 50391 'END',
michael@0 50392 'ENTER',
michael@0 50393 'EQUAL',
michael@0 50394 'ESCAPE',
michael@0 50395 'EXIT',
michael@0 50396 'F',
michael@0 50397 'F1',
michael@0 50398 'F10',
michael@0 50399 'F11',
michael@0 50400 'F12',
michael@0 50401 'F13',
michael@0 50402 'F14',
michael@0 50403 'F15',
michael@0 50404 'F2',
michael@0 50405 'F3',
michael@0 50406 'F4',
michael@0 50407 'F5',
michael@0 50408 'F6',
michael@0 50409 'F7',
michael@0 50410 'F8',
michael@0 50411 'F9',
michael@0 50412 'FAST_FORWARD',
michael@0 50413 'G',
michael@0 50414 'GREEN',
michael@0 50415 'GUIDE',
michael@0 50416 'H',
michael@0 50417 'HELP',
michael@0 50418 'HOME',
michael@0 50419 'I',
michael@0 50420 'INFO',
michael@0 50421 'INPUT',
michael@0 50422 'INSERT',
michael@0 50423 'J',
michael@0 50424 'K',
michael@0 50425 'KEYNAME_BEGIN',
michael@0 50426 'KEYNAME_BREAK',
michael@0 50427 'KEYNAME_CLEARDISPLAY',
michael@0 50428 'KEYNAME_CLEARLINE',
michael@0 50429 'KEYNAME_DELETE',
michael@0 50430 'KEYNAME_DELETECHAR',
michael@0 50431 'KEYNAME_DELETELINE',
michael@0 50432 'KEYNAME_DOWNARROW',
michael@0 50433 'KEYNAME_END',
michael@0 50434 'KEYNAME_EXECUTE',
michael@0 50435 'KEYNAME_F1',
michael@0 50436 'KEYNAME_F10',
michael@0 50437 'KEYNAME_F11',
michael@0 50438 'KEYNAME_F12',
michael@0 50439 'KEYNAME_F13',
michael@0 50440 'KEYNAME_F14',
michael@0 50441 'KEYNAME_F15',
michael@0 50442 'KEYNAME_F16',
michael@0 50443 'KEYNAME_F17',
michael@0 50444 'KEYNAME_F18',
michael@0 50445 'KEYNAME_F19',
michael@0 50446 'KEYNAME_F2',
michael@0 50447 'KEYNAME_F20',
michael@0 50448 'KEYNAME_F21',
michael@0 50449 'KEYNAME_F22',
michael@0 50450 'KEYNAME_F23',
michael@0 50451 'KEYNAME_F24',
michael@0 50452 'KEYNAME_F25',
michael@0 50453 'KEYNAME_F26',
michael@0 50454 'KEYNAME_F27',
michael@0 50455 'KEYNAME_F28',
michael@0 50456 'KEYNAME_F29',
michael@0 50457 'KEYNAME_F3',
michael@0 50458 'KEYNAME_F30',
michael@0 50459 'KEYNAME_F31',
michael@0 50460 'KEYNAME_F32',
michael@0 50461 'KEYNAME_F33',
michael@0 50462 'KEYNAME_F34',
michael@0 50463 'KEYNAME_F35',
michael@0 50464 'KEYNAME_F4',
michael@0 50465 'KEYNAME_F5',
michael@0 50466 'KEYNAME_F6',
michael@0 50467 'KEYNAME_F7',
michael@0 50468 'KEYNAME_F8',
michael@0 50469 'KEYNAME_F9',
michael@0 50470 'KEYNAME_FIND',
michael@0 50471 'KEYNAME_HELP',
michael@0 50472 'KEYNAME_HOME',
michael@0 50473 'KEYNAME_INSERT',
michael@0 50474 'KEYNAME_INSERTCHAR',
michael@0 50475 'KEYNAME_INSERTLINE',
michael@0 50476 'KEYNAME_LEFTARROW',
michael@0 50477 'KEYNAME_MENU',
michael@0 50478 'KEYNAME_MODESWITCH',
michael@0 50479 'KEYNAME_NEXT',
michael@0 50480 'KEYNAME_PAGEDOWN',
michael@0 50481 'KEYNAME_PAGEUP',
michael@0 50482 'KEYNAME_PAUSE',
michael@0 50483 'KEYNAME_PREV',
michael@0 50484 'KEYNAME_PRINT',
michael@0 50485 'KEYNAME_PRINTSCREEN',
michael@0 50486 'KEYNAME_REDO',
michael@0 50487 'KEYNAME_RESET',
michael@0 50488 'KEYNAME_RIGHTARROW',
michael@0 50489 'KEYNAME_SCROLLLOCK',
michael@0 50490 'KEYNAME_SELECT',
michael@0 50491 'KEYNAME_STOP',
michael@0 50492 'KEYNAME_SYSREQ',
michael@0 50493 'KEYNAME_SYSTEM',
michael@0 50494 'KEYNAME_UNDO',
michael@0 50495 'KEYNAME_UPARROW',
michael@0 50496 'KEYNAME_USER',
michael@0 50497 'L',
michael@0 50498 'LAST',
michael@0 50499 'LEFT',
michael@0 50500 'LEFTBRACKET',
michael@0 50501 'LIVE',
michael@0 50502 'M',
michael@0 50503 'MASTER_SHELL',
michael@0 50504 'MENU',
michael@0 50505 'MINUS',
michael@0 50506 'N',
michael@0 50507 'NEXT',
michael@0 50508 'NUMBER_0',
michael@0 50509 'NUMBER_1',
michael@0 50510 'NUMBER_2',
michael@0 50511 'NUMBER_3',
michael@0 50512 'NUMBER_4',
michael@0 50513 'NUMBER_5',
michael@0 50514 'NUMBER_6',
michael@0 50515 'NUMBER_7',
michael@0 50516 'NUMBER_8',
michael@0 50517 'NUMBER_9',
michael@0 50518 'NUMPAD',
michael@0 50519 'NUMPAD_0',
michael@0 50520 'NUMPAD_1',
michael@0 50521 'NUMPAD_2',
michael@0 50522 'NUMPAD_3',
michael@0 50523 'NUMPAD_4',
michael@0 50524 'NUMPAD_5',
michael@0 50525 'NUMPAD_6',
michael@0 50526 'NUMPAD_7',
michael@0 50527 'NUMPAD_8',
michael@0 50528 'NUMPAD_9',
michael@0 50529 'NUMPAD_ADD',
michael@0 50530 'NUMPAD_DECIMAL',
michael@0 50531 'NUMPAD_DIVIDE',
michael@0 50532 'NUMPAD_ENTER',
michael@0 50533 'NUMPAD_MULTIPLY',
michael@0 50534 'NUMPAD_SUBTRACT',
michael@0 50535 'O',
michael@0 50536 'P',
michael@0 50537 'PAGE_DOWN',
michael@0 50538 'PAGE_UP',
michael@0 50539 'PAUSE',
michael@0 50540 'PERIOD',
michael@0 50541 'PLAY',
michael@0 50542 'PREVIOUS',
michael@0 50543 'Q',
michael@0 50544 'QUOTE',
michael@0 50545 'R',
michael@0 50546 'RECORD',
michael@0 50547 'RED',
michael@0 50548 'REWIND',
michael@0 50549 'RIGHT',
michael@0 50550 'RIGHTBRACKET',
michael@0 50551 'S',
michael@0 50552 'SEARCH',
michael@0 50553 'SEMICOLON',
michael@0 50554 'SETUP',
michael@0 50555 'SHIFT',
michael@0 50556 'SKIP_BACKWARD',
michael@0 50557 'SKIP_FORWARD',
michael@0 50558 'SLASH',
michael@0 50559 'SPACE',
michael@0 50560 'STOP',
michael@0 50561 'STRING_BEGIN',
michael@0 50562 'STRING_BREAK',
michael@0 50563 'STRING_CLEARDISPLAY',
michael@0 50564 'STRING_CLEARLINE',
michael@0 50565 'STRING_DELETE',
michael@0 50566 'STRING_DELETECHAR',
michael@0 50567 'STRING_DELETELINE',
michael@0 50568 'STRING_DOWNARROW',
michael@0 50569 'STRING_END',
michael@0 50570 'STRING_EXECUTE',
michael@0 50571 'STRING_F1',
michael@0 50572 'STRING_F10',
michael@0 50573 'STRING_F11',
michael@0 50574 'STRING_F12',
michael@0 50575 'STRING_F13',
michael@0 50576 'STRING_F14',
michael@0 50577 'STRING_F15',
michael@0 50578 'STRING_F16',
michael@0 50579 'STRING_F17',
michael@0 50580 'STRING_F18',
michael@0 50581 'STRING_F19',
michael@0 50582 'STRING_F2',
michael@0 50583 'STRING_F20',
michael@0 50584 'STRING_F21',
michael@0 50585 'STRING_F22',
michael@0 50586 'STRING_F23',
michael@0 50587 'STRING_F24',
michael@0 50588 'STRING_F25',
michael@0 50589 'STRING_F26',
michael@0 50590 'STRING_F27',
michael@0 50591 'STRING_F28',
michael@0 50592 'STRING_F29',
michael@0 50593 'STRING_F3',
michael@0 50594 'STRING_F30',
michael@0 50595 'STRING_F31',
michael@0 50596 'STRING_F32',
michael@0 50597 'STRING_F33',
michael@0 50598 'STRING_F34',
michael@0 50599 'STRING_F35',
michael@0 50600 'STRING_F4',
michael@0 50601 'STRING_F5',
michael@0 50602 'STRING_F6',
michael@0 50603 'STRING_F7',
michael@0 50604 'STRING_F8',
michael@0 50605 'STRING_F9',
michael@0 50606 'STRING_FIND',
michael@0 50607 'STRING_HELP',
michael@0 50608 'STRING_HOME',
michael@0 50609 'STRING_INSERT',
michael@0 50610 'STRING_INSERTCHAR',
michael@0 50611 'STRING_INSERTLINE',
michael@0 50612 'STRING_LEFTARROW',
michael@0 50613 'STRING_MENU',
michael@0 50614 'STRING_MODESWITCH',
michael@0 50615 'STRING_NEXT',
michael@0 50616 'STRING_PAGEDOWN',
michael@0 50617 'STRING_PAGEUP',
michael@0 50618 'STRING_PAUSE',
michael@0 50619 'STRING_PREV',
michael@0 50620 'STRING_PRINT',
michael@0 50621 'STRING_PRINTSCREEN',
michael@0 50622 'STRING_REDO',
michael@0 50623 'STRING_RESET',
michael@0 50624 'STRING_RIGHTARROW',
michael@0 50625 'STRING_SCROLLLOCK',
michael@0 50626 'STRING_SELECT',
michael@0 50627 'STRING_STOP',
michael@0 50628 'STRING_SYSREQ',
michael@0 50629 'STRING_SYSTEM',
michael@0 50630 'STRING_UNDO',
michael@0 50631 'STRING_UPARROW',
michael@0 50632 'STRING_USER',
michael@0 50633 'SUBTITLE',
michael@0 50634 'T',
michael@0 50635 'TAB',
michael@0 50636 'U',
michael@0 50637 'UP',
michael@0 50638 'V',
michael@0 50639 'VOD',
michael@0 50640 'W',
michael@0 50641 'X',
michael@0 50642 'Y',
michael@0 50643 'YELLOW',
michael@0 50644 'Z',
michael@0 50645 'CharCodeStrings'
michael@0 50646 ])
michael@0 50647 },
michael@0 50648 native: {
michael@0 50649 instance: {
michael@0 50650 capsLock: desc(def, 'capsLock'),
michael@0 50651 hasVirtualKeyboard: desc(def, 'hasVirtualKeyboard'),
michael@0 50652 numLock: desc(def, 'numLock'),
michael@0 50653 physicalKeyboardType: desc(def, 'physicalKeyboardType'),
michael@0 50654 isAccessible: desc(def, 'isAccessible')
michael@0 50655 }
michael@0 50656 }
michael@0 50657 };
michael@0 50658 return def;
michael@0 50659 }.call(this);
michael@0 50660 var MouseDefinition = function () {
michael@0 50661 var def = {
michael@0 50662 __class__: 'flash.ui.Mouse'
michael@0 50663 };
michael@0 50664 function hide() {
michael@0 50665 }
michael@0 50666 function show() {
michael@0 50667 }
michael@0 50668 function registerCursor() {
michael@0 50669 notImplemented();
michael@0 50670 }
michael@0 50671 function unregisterCursor() {
michael@0 50672 notImplemented();
michael@0 50673 }
michael@0 50674 def.__glue__ = {
michael@0 50675 native: {
michael@0 50676 static: {
michael@0 50677 cursor: {
michael@0 50678 get: function () {
michael@0 50679 return 'auto';
michael@0 50680 },
michael@0 50681 set: function () {
michael@0 50682 notImplemented();
michael@0 50683 }
michael@0 50684 },
michael@0 50685 supportsCursor: {
michael@0 50686 get: function () {
michael@0 50687 return true;
michael@0 50688 }
michael@0 50689 },
michael@0 50690 supportsNativeCursor: {
michael@0 50691 get: function () {
michael@0 50692 return true;
michael@0 50693 }
michael@0 50694 },
michael@0 50695 hide: hide,
michael@0 50696 show: show,
michael@0 50697 registerCursor: registerCursor,
michael@0 50698 unregisterCursor: unregisterCursor
michael@0 50699 }
michael@0 50700 }
michael@0 50701 };
michael@0 50702 return def;
michael@0 50703 }.call(this);
michael@0 50704 var MouseCursorDataDefinition = function () {
michael@0 50705 return {
michael@0 50706 __class__: 'flash.ui.MouseCursorData',
michael@0 50707 initialize: function () {
michael@0 50708 },
michael@0 50709 __glue__: {
michael@0 50710 native: {
michael@0 50711 static: {},
michael@0 50712 instance: {
michael@0 50713 data: {
michael@0 50714 get: function data() {
michael@0 50715 notImplemented('MouseCursorData.data');
michael@0 50716 return this._data;
michael@0 50717 },
michael@0 50718 set: function data(data) {
michael@0 50719 notImplemented('MouseCursorData.data');
michael@0 50720 this._data = data;
michael@0 50721 }
michael@0 50722 },
michael@0 50723 hotSpot: {
michael@0 50724 get: function hotSpot() {
michael@0 50725 notImplemented('MouseCursorData.hotSpot');
michael@0 50726 return this._hotSpot;
michael@0 50727 },
michael@0 50728 set: function hotSpot(data) {
michael@0 50729 notImplemented('MouseCursorData.hotSpot');
michael@0 50730 this._hotSpot = data;
michael@0 50731 }
michael@0 50732 },
michael@0 50733 frameRate: {
michael@0 50734 get: function frameRate() {
michael@0 50735 notImplemented('MouseCursorData.frameRate');
michael@0 50736 return this._frameRate;
michael@0 50737 },
michael@0 50738 set: function frameRate(data) {
michael@0 50739 notImplemented('MouseCursorData.frameRate');
michael@0 50740 this._frameRate = data;
michael@0 50741 }
michael@0 50742 }
michael@0 50743 }
michael@0 50744 }
michael@0 50745 }
michael@0 50746 };
michael@0 50747 }.call(this);
michael@0 50748 {
michael@0 50749 var DictionaryDefinition = function () {
michael@0 50750 return {
michael@0 50751 __class__: 'flash.utils.Dictionary',
michael@0 50752 initialize: function () {
michael@0 50753 },
michael@0 50754 __glue__: {
michael@0 50755 native: {
michael@0 50756 static: {},
michael@0 50757 instance: {
michael@0 50758 init: function init(weakKeys) {
michael@0 50759 notImplemented('Dictionary.init');
michael@0 50760 }
michael@0 50761 }
michael@0 50762 }
michael@0 50763 }
michael@0 50764 };
michael@0 50765 }.call(this);
michael@0 50766 }
michael@0 50767 var TimerDefinition = function () {
michael@0 50768 var def = {
michael@0 50769 __class__: 'flash.utils.Timer',
michael@0 50770 initialize: function () {
michael@0 50771 this._running = false;
michael@0 50772 }
michael@0 50773 };
michael@0 50774 def.__glue__ = {
michael@0 50775 native: {
michael@0 50776 instance: {
michael@0 50777 running: {
michael@0 50778 get: function () {
michael@0 50779 return this._running;
michael@0 50780 }
michael@0 50781 },
michael@0 50782 _start: function (delay, closure) {
michael@0 50783 this._running = true;
michael@0 50784 this.interval = setInterval(closure, delay);
michael@0 50785 },
michael@0 50786 stop: function () {
michael@0 50787 this._running = false;
michael@0 50788 clearInterval(this.interval);
michael@0 50789 },
michael@0 50790 _tick: function () {
michael@0 50791 if (!this._running) {
michael@0 50792 return;
michael@0 50793 }
michael@0 50794 this._dispatchEvent(new flash.events.TimerEvent('timer', true, false));
michael@0 50795 }
michael@0 50796 }
michael@0 50797 }
michael@0 50798 };
michael@0 50799 return def;
michael@0 50800 }.call(this);
michael@0 50801 {
michael@0 50802 var AccessibilityDefinition = function () {
michael@0 50803 return {
michael@0 50804 __class__: 'flash.accessibility.Accessibility',
michael@0 50805 initialize: function () {
michael@0 50806 },
michael@0 50807 __glue__: {
michael@0 50808 native: {
michael@0 50809 static: {
michael@0 50810 sendEvent: function sendEvent(source, childID, eventType, nonHTML) {
michael@0 50811 notImplemented('Accessibility.sendEvent');
michael@0 50812 },
michael@0 50813 updateProperties: function updateProperties() {
michael@0 50814 notImplemented('Accessibility.updateProperties');
michael@0 50815 },
michael@0 50816 active: {
michael@0 50817 get: function active() {
michael@0 50818 somewhatImplemented('Accessibility.active');
michael@0 50819 return false;
michael@0 50820 }
michael@0 50821 }
michael@0 50822 },
michael@0 50823 instance: {}
michael@0 50824 }
michael@0 50825 }
michael@0 50826 };
michael@0 50827 }.call(this);
michael@0 50828 }
michael@0 50829 {
michael@0 50830 var AS2ButtonDefinition = function () {
michael@0 50831 var def = {
michael@0 50832 __class__: 'avm1lib.AS2Button',
michael@0 50833 initialize: function () {
michael@0 50834 }
michael@0 50835 };
michael@0 50836 var desc = Object.getOwnPropertyDescriptor;
michael@0 50837 def.__glue__ = {
michael@0 50838 native: {
michael@0 50839 instance: {
michael@0 50840 _as3Object: {
michael@0 50841 get: function () {
michael@0 50842 return this.$nativeObject;
michael@0 50843 }
michael@0 50844 },
michael@0 50845 _init: function init(nativeButton) {
michael@0 50846 Object.defineProperty(this, '$nativeObject', {
michael@0 50847 value: nativeButton
michael@0 50848 });
michael@0 50849 nativeButton.$as2Object = this;
michael@0 50850 initDefaultListeners(this);
michael@0 50851 }
michael@0 50852 }
michael@0 50853 },
michael@0 50854 script: {
michael@0 50855 instance: Glue.ALL
michael@0 50856 }
michael@0 50857 };
michael@0 50858 return def;
michael@0 50859 }.call(this);
michael@0 50860 }
michael@0 50861 var AS2GlobalsDefinition = function () {
michael@0 50862 var def = {
michael@0 50863 __class__: 'avm1lib.AS2Globals',
michael@0 50864 initialize: function () {
michael@0 50865 flash.text.TextFormat.prototype.asDefinePublicProperty('getTextExtent', {
michael@0 50866 value: TextFormatDefinition.as2GetTextExtent,
michael@0 50867 writable: false,
michael@0 50868 enumerable: false,
michael@0 50869 configurable: false
michael@0 50870 });
michael@0 50871 }
michael@0 50872 };
michael@0 50873 def.__glue__ = {
michael@0 50874 native: {
michael@0 50875 instance: {
michael@0 50876 ASSetPropFlags: function ASSetPropFlags(obj, children, flags, allowFalse) {
michael@0 50877 },
michael@0 50878 _addToPendingScripts: function _addToPendingScripts(subject, fn, args) {
michael@0 50879 AS2Context.instance.addToPendingScripts(function () {
michael@0 50880 fn.apply(subject, args);
michael@0 50881 });
michael@0 50882 },
michael@0 50883 _setLevel: function _setLevel(level, loader) {
michael@0 50884 AS2Context.instance.stage._as2SetLevel(level, loader);
michael@0 50885 },
michael@0 50886 trace: function (expression) {
michael@0 50887 var trace = avm2.applicationDomain.getProperty(Multiname.fromSimpleName('trace'), true, true);
michael@0 50888 trace(expression);
michael@0 50889 }
michael@0 50890 },
michael@0 50891 static: {
michael@0 50892 _addInternalClasses: function _addInternalClasses(proto) {
michael@0 50893 proto.asSetPublicProperty('Object', Stubs.Object);
michael@0 50894 proto.asSetPublicProperty('Function', Stubs.Function);
michael@0 50895 proto.asSetPublicProperty('Array', Stubs.Array);
michael@0 50896 proto.asSetPublicProperty('Number', Stubs.Number);
michael@0 50897 proto.asSetPublicProperty('Math', avm2.systemDomain.getClass('Math'));
michael@0 50898 proto.asSetPublicProperty('Boolean', Stubs.Boolean);
michael@0 50899 proto.asSetPublicProperty('Date', Stubs.Date);
michael@0 50900 proto.asSetPublicProperty('RegExp', Stubs.RegExp);
michael@0 50901 proto.asSetPublicProperty('String', Stubs.String);
michael@0 50902 }
michael@0 50903 }
michael@0 50904 },
michael@0 50905 script: {
michael@0 50906 instance: Glue.ALL
michael@0 50907 }
michael@0 50908 };
michael@0 50909 return def;
michael@0 50910 }.call(this);
michael@0 50911 var AS2MovieClipDefinition = function () {
michael@0 50912 var def = {
michael@0 50913 __class__: 'avm1lib.AS2MovieClip',
michael@0 50914 initialize: function () {
michael@0 50915 },
michael@0 50916 _insertChildAtDepth: function _insertChildAtDepth(mc, depth) {
michael@0 50917 return this.$nativeObject._insertChildAtDepth(mc, depth);
michael@0 50918 },
michael@0 50919 _duplicate: function _duplicate(name, depth, initObject) {
michael@0 50920 return this.$nativeObject._duplicate(name, depth, initObject);
michael@0 50921 },
michael@0 50922 _constructSymbol: function constructSymbol(symbolId, name) {
michael@0 50923 var theClass = AS2Context.instance.classes && AS2Context.instance.classes[symbolId];
michael@0 50924 var symbolProps = AS2Context.instance.assets[symbolId];
michael@0 50925 var symbolClass = flash.display.MovieClip.class;
michael@0 50926 var mc = symbolClass.createAsSymbol(symbolProps);
michael@0 50927 mc._avm1SymbolClass = theClass;
michael@0 50928 symbolClass.instanceConstructor.call(mc);
michael@0 50929 this.$nativeObject.addChild(mc);
michael@0 50930 return mc;
michael@0 50931 },
michael@0 50932 _gotoLabel: function (label) {
michael@0 50933 this.$nativeObject.gotoLabel(label);
michael@0 50934 },
michael@0 50935 _callFrame: function callFrame(frame) {
michael@0 50936 this.$nativeObject._callFrame(frame);
michael@0 50937 },
michael@0 50938 init: function init(nativeMovieClip) {
michael@0 50939 if (!nativeMovieClip) {
michael@0 50940 return;
michael@0 50941 }
michael@0 50942 Object.defineProperty(this, '$nativeObject', {
michael@0 50943 value: nativeMovieClip
michael@0 50944 });
michael@0 50945 nativeMovieClip.$as2Object = this;
michael@0 50946 initDefaultListeners(this);
michael@0 50947 }
michael@0 50948 };
michael@0 50949 var desc = Object.getOwnPropertyDescriptor;
michael@0 50950 def.__glue__ = {
michael@0 50951 native: {
michael@0 50952 instance: {
michael@0 50953 _as3Object: {
michael@0 50954 get: function () {
michael@0 50955 return this.$nativeObject;
michael@0 50956 }
michael@0 50957 },
michael@0 50958 _init: def.init,
michael@0 50959 _insertChildAtDepth: def._insertChildAtDepth,
michael@0 50960 _duplicate: def._duplicate,
michael@0 50961 _constructSymbol: def._constructSymbol,
michael@0 50962 _callFrame: def._callFrame,
michael@0 50963 _gotoLabel: def._gotoLabel
michael@0 50964 }
michael@0 50965 },
michael@0 50966 script: {
michael@0 50967 instance: Glue.ALL
michael@0 50968 }
michael@0 50969 };
michael@0 50970 return def;
michael@0 50971 }.call(this);
michael@0 50972 var AS2MovieClipLoaderDefinition = function () {
michael@0 50973 var def = {
michael@0 50974 __class__: 'avm1lib.AS2MovieClipLoader',
michael@0 50975 initialize: function () {
michael@0 50976 },
michael@0 50977 get _bytesLoaded() {
michael@0 50978 return this.$nativeObject._contentLoaderInfo._bytesLoaded;
michael@0 50979 }
michael@0 50980 };
michael@0 50981 var desc = Object.getOwnPropertyDescriptor;
michael@0 50982 def.__glue__ = {
michael@0 50983 native: {
michael@0 50984 instance: {
michael@0 50985 $nativeObject: {
michael@0 50986 get: function () {
michael@0 50987 return this.$nativeObject;
michael@0 50988 }
michael@0 50989 },
michael@0 50990 _bytesLoaded: desc(def, '_bytesLoaded')
michael@0 50991 }
michael@0 50992 },
michael@0 50993 script: {
michael@0 50994 instance: Glue.ALL
michael@0 50995 }
michael@0 50996 };
michael@0 50997 return def;
michael@0 50998 }.call(this);
michael@0 50999 var AS2TextFieldDefinition = function () {
michael@0 51000 var def = {
michael@0 51001 __class__: 'avm1lib.AS2TextField',
michael@0 51002 initialize: function () {
michael@0 51003 this._variable = '';
michael@0 51004 }
michael@0 51005 };
michael@0 51006 def.__glue__ = {
michael@0 51007 native: {
michael@0 51008 instance: {
michael@0 51009 variable: {
michael@0 51010 get: function () {
michael@0 51011 return this._variable;
michael@0 51012 },
michael@0 51013 set: function (name) {
michael@0 51014 if (name === this._variable) {
michael@0 51015 return;
michael@0 51016 }
michael@0 51017 this._variable = name;
michael@0 51018 var instance = this.$nativeObject;
michael@0 51019 var hasPath = name.indexOf('.') >= 0 || name.indexOf(':') >= 0;
michael@0 51020 var clip;
michael@0 51021 if (hasPath) {
michael@0 51022 var targetPath = name.split(/[.:\/]/g);
michael@0 51023 name = targetPath.pop();
michael@0 51024 if (targetPath[0] == '_root' || targetPath[0] === '') {
michael@0 51025 clip = instance.root._getAS2Object();
michael@0 51026 targetPath.shift();
michael@0 51027 if (targetPath[0] === '') {
michael@0 51028 targetPath.shift();
michael@0 51029 }
michael@0 51030 } else {
michael@0 51031 clip = instance._parent._getAS2Object();
michael@0 51032 }
michael@0 51033 while (targetPath.length > 0) {
michael@0 51034 var childName = targetPath.shift();
michael@0 51035 clip = clip.asGetPublicProperty(childName) || clip[childName];
michael@0 51036 if (!clip) {
michael@0 51037 throw new Error('Cannot find ' + childName + ' variable');
michael@0 51038 }
michael@0 51039 }
michael@0 51040 } else {
michael@0 51041 clip = instance._parent._getAS2Object();
michael@0 51042 }
michael@0 51043 if (!clip.asHasProperty(undefined, name, 0)) {
michael@0 51044 clip.asSetPublicProperty(name, instance.text);
michael@0 51045 }
michael@0 51046 instance._addEventListener('advanceFrame', function () {
michael@0 51047 instance.text = '' + clip.asGetPublicProperty(name);
michael@0 51048 });
michael@0 51049 }
michael@0 51050 },
michael@0 51051 _as3Object: {
michael@0 51052 get: function () {
michael@0 51053 return this.$nativeObject;
michael@0 51054 }
michael@0 51055 },
michael@0 51056 _init: function init(nativeTextField) {
michael@0 51057 Object.defineProperty(this, '$nativeObject', {
michael@0 51058 value: nativeTextField
michael@0 51059 });
michael@0 51060 nativeTextField.$as2Object = this;
michael@0 51061 initDefaultListeners(this);
michael@0 51062 }
michael@0 51063 }
michael@0 51064 },
michael@0 51065 script: {
michael@0 51066 instance: Glue.ALL
michael@0 51067 }
michael@0 51068 };
michael@0 51069 return def;
michael@0 51070 }.call(this);
michael@0 51071 var AS2UtilsDefinition = function () {
michael@0 51072 var def = {
michael@0 51073 __class__: 'avm1lib.AS2Utils',
michael@0 51074 initialize: function () {
michael@0 51075 }
michael@0 51076 };
michael@0 51077 function installObjectMethods() {
michael@0 51078 var c = Stubs.Object, p = c.asGetPublicProperty('prototype');
michael@0 51079 c.asSetPublicProperty('registerClass', function registerClass(name, theClass) {
michael@0 51080 var classes = AS2Context.instance.classes || (AS2Context.instance.classes = {});
michael@0 51081 classes[name] = theClass;
michael@0 51082 });
michael@0 51083 p.asDefinePublicProperty('addProperty', {
michael@0 51084 value: function addProperty(name, getter, setter) {
michael@0 51085 if (typeof name !== 'string' || name === '') {
michael@0 51086 return false;
michael@0 51087 }
michael@0 51088 if (typeof getter !== 'function') {
michael@0 51089 return false;
michael@0 51090 }
michael@0 51091 if (typeof setter !== 'function' && setter !== null) {
michael@0 51092 return false;
michael@0 51093 }
michael@0 51094 this.asDefinePublicProperty(name, {
michael@0 51095 get: getter,
michael@0 51096 set: setter || undefined,
michael@0 51097 configurable: true,
michael@0 51098 enumerable: true
michael@0 51099 });
michael@0 51100 return true;
michael@0 51101 },
michael@0 51102 writable: false,
michael@0 51103 enumerable: false,
michael@0 51104 configurable: false
michael@0 51105 });
michael@0 51106 }
michael@0 51107 def.__glue__ = {
michael@0 51108 native: {
michael@0 51109 static: {
michael@0 51110 getAS2Object: function (nativeObject) {
michael@0 51111 return nativeObject && nativeObject._getAS2Object ? nativeObject._getAS2Object() : null;
michael@0 51112 },
michael@0 51113 addProperty: function (obj, propertyName, getter, setter, enumerable) {
michael@0 51114 obj.asDefinePublicProperty(propertyName, {
michael@0 51115 get: getter,
michael@0 51116 set: setter || undefined,
michael@0 51117 enumerable: enumerable,
michael@0 51118 configurable: true
michael@0 51119 });
michael@0 51120 },
michael@0 51121 resolveTarget: function (target_mc) {
michael@0 51122 return AS2Context.instance.resolveTarget(target_mc);
michael@0 51123 },
michael@0 51124 resolveLevel: function (level) {
michael@0 51125 return AS2Context.instance.resolveLevel(level);
michael@0 51126 },
michael@0 51127 currentStage: {
michael@0 51128 get: function () {
michael@0 51129 return AS2Context.instance.stage;
michael@0 51130 }
michael@0 51131 },
michael@0 51132 _installObjectMethods: installObjectMethods
michael@0 51133 }
michael@0 51134 }
michael@0 51135 };
michael@0 51136 return def;
michael@0 51137 }.call(this);
michael@0 51138 function initDefaultListeners(thisArg) {
michael@0 51139 var defaultListeners = thisArg.asGetPublicProperty('$defaultListeners');
michael@0 51140 if (!defaultListeners) {
michael@0 51141 return;
michael@0 51142 }
michael@0 51143 for (var i = 0; i < defaultListeners.length; i++) {
michael@0 51144 var p = defaultListeners[i];
michael@0 51145 p.asGetPublicProperty('setter').call(thisArg, p.value);
michael@0 51146 }
michael@0 51147 }
michael@0 51148 function bindNativeClassDefinition(nativeName, definition) {
michael@0 51149 natives[nativeName] = function (domain, scope, instanceConstructor, baseClass) {
michael@0 51150 var c = new Class(undefined, instanceConstructor, ApplicationDomain.coerceCallable);
michael@0 51151 c.extend(baseClass);
michael@0 51152 c.linkNatives(definition);
michael@0 51153 return c;
michael@0 51154 };
michael@0 51155 }
michael@0 51156 var Stubs = new function () {
michael@0 51157 var that = this;
michael@0 51158 var definitions = createEmptyObject();
michael@0 51159 var DEFAULT_DEFINITION = {
michael@0 51160 __glue__: {
michael@0 51161 script: {
michael@0 51162 instance: Glue.ALL,
michael@0 51163 static: Glue.ALL
michael@0 51164 }
michael@0 51165 }
michael@0 51166 };
michael@0 51167 this.getClassNames = function () {
michael@0 51168 return Object.keys(definitions);
michael@0 51169 };
michael@0 51170 this.onClassCreated = function (eventType, cls) {
michael@0 51171 var classOriginalName = cls.classInfo.instanceInfo.name.getOriginalName();
michael@0 51172 if (classOriginalName in definitions) {
michael@0 51173 cls.link(definitions[classOriginalName] || DEFAULT_DEFINITION);
michael@0 51174 }
michael@0 51175 };
michael@0 51176 function makeStub(container, classSimpleName, shortName) {
michael@0 51177 Object.defineProperty(container, shortName, {
michael@0 51178 get: function () {
michael@0 51179 var cls = avm2.systemDomain.getClass(classSimpleName);
michael@0 51180 true;
michael@0 51181 Object.defineProperty(container, shortName, {
michael@0 51182 value: cls.instanceConstructor,
michael@0 51183 writable: false
michael@0 51184 });
michael@0 51185 return container[shortName];
michael@0 51186 },
michael@0 51187 configurable: true
michael@0 51188 });
michael@0 51189 }
michael@0 51190 [
michael@0 51191 'Boolean',
michael@0 51192 'Date',
michael@0 51193 'String',
michael@0 51194 'Function',
michael@0 51195 'Object',
michael@0 51196 'Number',
michael@0 51197 'Math',
michael@0 51198 'Array',
michael@0 51199 'RegExp'
michael@0 51200 ].forEach(function (classSimpleName) {
michael@0 51201 makeStub(that, classSimpleName, classSimpleName);
michael@0 51202 });
michael@0 51203 [
michael@0 51204 'Error',
michael@0 51205 'DefinitionError',
michael@0 51206 'EvalError',
michael@0 51207 'RangeError',
michael@0 51208 'ReferenceError',
michael@0 51209 'SecurityError',
michael@0 51210 'SyntaxError',
michael@0 51211 'TypeError',
michael@0 51212 'URIError',
michael@0 51213 'VerifyError',
michael@0 51214 'UninitializedError',
michael@0 51215 'ArgumentError'
michael@0 51216 ].forEach(function (classSimpleName) {
michael@0 51217 makeStub(that, classSimpleName, classSimpleName);
michael@0 51218 });
michael@0 51219 function M(classSimpleName, nativeName, definition) {
michael@0 51220 return {
michael@0 51221 classSimpleName: classSimpleName,
michael@0 51222 nativeName: nativeName,
michael@0 51223 definition: definition
michael@0 51224 };
michael@0 51225 }
michael@0 51226 [
michael@0 51227 M('flash.display.DisplayObject', 'DisplayObjectClass', DisplayObjectDefinition),
michael@0 51228 M('flash.display.InteractiveObject', 'InteractiveObjectClass', InteractiveObjectDefinition),
michael@0 51229 M('flash.display.DisplayObjectContainer', 'ContainerClass', DisplayObjectContainerDefinition),
michael@0 51230 M('flash.display.Sprite', 'SpriteClass', SpriteDefinition),
michael@0 51231 M('flash.display.MovieClip', 'MovieClipClass', MovieClipDefinition),
michael@0 51232 M('flash.display.Shape', 'ShapeClass', ShapeDefinition),
michael@0 51233 M('flash.display.Bitmap', 'BitmapClass', BitmapDefinition),
michael@0 51234 M('flash.display.BitmapData', 'BitmapDataClass', BitmapDataDefinition),
michael@0 51235 M('flash.display.Stage', 'StageClass', StageDefinition),
michael@0 51236 M('flash.display.Loader', 'LoaderClass', LoaderDefinition),
michael@0 51237 M('flash.display.LoaderInfo', 'LoaderInfoClass', LoaderInfoDefinition),
michael@0 51238 M('flash.display.Graphics', 'GraphicsClass', GraphicsDefinition),
michael@0 51239 M('flash.display.SimpleButton', 'SimpleButtonClass', SimpleButtonDefinition),
michael@0 51240 M('flash.display.MorphShape', 'MorphShapeClass', MorphShapeDefinition),
michael@0 51241 M('flash.display.NativeMenu', 'MenuClass', NativeMenuDefinition),
michael@0 51242 M('flash.display.NativeMenuItem', 'MenuItemClass', NativeMenuItemDefinition),
michael@0 51243 M('flash.display.FrameLabel', 'FrameLabelClass', FrameLabelDefinition),
michael@0 51244 M('flash.display.Scene'),
michael@0 51245 M('flash.display.BlendMode'),
michael@0 51246 M('flash.display.Shader', 'ShaderClass', ShaderDefinition),
michael@0 51247 M('flash.display.ShaderData', 'ShaderDataClass', ShaderDataDefinition),
michael@0 51248 M('flash.filters.BevelFilter', 'BevelFilterClass', BevelFilterDefinition),
michael@0 51249 M('flash.filters.BitmapFilter', 'BitmapFilterClass', BitmapFilterDefinition),
michael@0 51250 M('flash.filters.BlurFilter', 'BlurFilterClass', BlurFilterDefinition),
michael@0 51251 M('flash.filters.ColorMatrixFilter', 'ColorMatrixFilterClass', ColorMatrixFilterDefinition),
michael@0 51252 M('flash.filters.ConvolutionFilter', 'ConvolutionFilterClass', ConvolutionFilterDefinition),
michael@0 51253 M('flash.filters.DisplacementMapFilter', 'DisplacementMapFilterClass', DisplacementMapFilterDefinition),
michael@0 51254 M('flash.filters.DropShadowFilter', 'DropShadowFilterClass', DropShadowFilterDefinition),
michael@0 51255 M('flash.filters.GlowFilter', 'GlowFilterClass', GlowFilterDefinition),
michael@0 51256 M('flash.filters.GradientBevelFilter', 'GradientBevelFilterClass', GradientBevelFilterDefinition),
michael@0 51257 M('flash.filters.GradientGlowFilter', 'GradientGlowFilterClass', GradientGlowFilterDefinition),
michael@0 51258 M('flash.filters.ShaderFilter', 'ShaderFilterClass', ShaderFilterDefinition),
michael@0 51259 M('flash.geom.Point', 'PointClass', PointDefinition),
michael@0 51260 M('flash.geom.Rectangle', 'RectangleClass', RectangleDefinition),
michael@0 51261 M('flash.geom.Matrix', 'MatrixClass', MatrixDefinition),
michael@0 51262 M('flash.geom.Matrix3D', 'Matrix3DClass', Matrix3DDefinition),
michael@0 51263 M('flash.geom.Vector3D', 'Vector3DClass', Vector3DDefinition),
michael@0 51264 M('flash.geom.Transform', 'TransformClass', TransformDefinition),
michael@0 51265 M('flash.geom.ColorTransform', 'ColorTransformClass', ColorTransformDefinition),
michael@0 51266 M('flash.events.EventDispatcher', 'EventDispatcherClass', EventDispatcherDefinition),
michael@0 51267 M('flash.events.Event', 'EventClass', EventDefinition),
michael@0 51268 M('flash.events.IOErrorEvent'),
michael@0 51269 M('flash.events.NetStatusEvent'),
michael@0 51270 M('flash.events.KeyboardEvent', 'KeyboardEventClass', KeyboardEventDefinition),
michael@0 51271 M('flash.events.MouseEvent', 'MouseEventClass', MouseEventDefinition),
michael@0 51272 M('flash.events.TextEvent', 'TextEventClass', TextEventDefinition),
michael@0 51273 M('flash.events.TimerEvent', 'TimerEventClass', TimerEventDefinition),
michael@0 51274 M('flash.events.ProgressEvent'),
michael@0 51275 M('flash.events.NetStatusEvent'),
michael@0 51276 M('flash.external.ExternalInterface', 'ExternalInterfaceClass', ExternalInterfaceDefinition),
michael@0 51277 M('flash.ui.ContextMenu', 'ContextMenuClass', ContextMenuDefinition),
michael@0 51278 M('flash.ui.ContextMenuItem', 'ContextMenuItemClass', ContextMenuItemDefinition),
michael@0 51279 M('flash.ui.Keyboard', 'KeyboardClass', KeyboardDefinition),
michael@0 51280 M('flash.ui.Mouse', 'MouseClass', MouseDefinition),
michael@0 51281 M('flash.ui.MouseCursorData', 'MouseCursorDataClass', MouseCursorDataDefinition),
michael@0 51282 M('flash.text.Font', 'FontClass', FontDefinition),
michael@0 51283 M('flash.text.TextField', 'TextFieldClass', TextFieldDefinition),
michael@0 51284 M('flash.text.StaticText', 'StaticTextClass', StaticTextDefinition),
michael@0 51285 M('flash.text.StyleSheet', 'StyleSheetClass', StyleSheetDefinition),
michael@0 51286 M('flash.text.TextFormat', 'TextFormatClass', TextFormatDefinition),
michael@0 51287 M('flash.text.TextLineMetrics'),
michael@0 51288 M('flash.text.engine.ContentElement', 'ContentElementClass', ContentElementDefinition),
michael@0 51289 M('flash.text.engine.ElementFormat', 'ElementFormatClass', ElementFormatDefinition),
michael@0 51290 M('flash.text.engine.FontDescription', 'FontDescriptionClass', FontDescriptionDefinition),
michael@0 51291 M('flash.text.engine.GroupElement', 'GroupElementClass', GroupElementDefinition),
michael@0 51292 M('flash.text.engine.SpaceJustifier', 'SpaceJustifierClass', SpaceJustifierDefinition),
michael@0 51293 M('flash.text.engine.TextBlock', 'TextBlockClass', TextBlockDefinition),
michael@0 51294 M('flash.text.engine.TextElement', 'TextElementClass', TextElementDefinition),
michael@0 51295 M('flash.text.engine.TextJustifier', 'TextJustifierClass', TextJustifierDefinition),
michael@0 51296 M('flash.text.engine.TextLine', 'TextLineClass', TextLineDefinition),
michael@0 51297 M('flash.media.Sound', 'SoundClass', SoundDefinition),
michael@0 51298 M('flash.media.SoundChannel', 'SoundChannelClass', SoundChannelDefinition),
michael@0 51299 M('flash.media.SoundMixer', 'SoundMixerClass', SoundMixerDefinition),
michael@0 51300 M('flash.media.SoundTransform', 'SoundTransformClass', SoundTransformDefinition),
michael@0 51301 M('flash.media.Video', 'VideoClass', VideoDefinition),
michael@0 51302 M('flash.media.ID3Info', 'ID3InfoClass', ID3InfoDefinition),
michael@0 51303 M('flash.media.Microphone', 'MicrophoneClass', MicrophoneDefinition),
michael@0 51304 M('flash.net.FileFilter', 'FileFilterClass', FileFilterDefinition),
michael@0 51305 M('flash.net.NetConnection', 'NetConnectionClass', NetConnectionDefinition),
michael@0 51306 M('flash.net.NetStream', 'NetStreamClass', NetStreamDefinition),
michael@0 51307 M('flash.net.Responder', 'ResponderClass', ResponderDefinition),
michael@0 51308 M('flash.net.URLRequest', 'URLRequestClass', URLRequestDefinition),
michael@0 51309 M('flash.net.URLStream', 'URLStreamClass', URLStreamDefinition),
michael@0 51310 M('flash.net.URLLoader', 'URLLoaderClass', URLLoaderDefinition),
michael@0 51311 M('flash.net.SharedObject', 'SharedObjectClass', SharedObjectDefinition),
michael@0 51312 M('flash.net.ObjectEncoding', 'ObjectEncodingClass', ObjectEncodingDefinition),
michael@0 51313 M('flash.net.LocalConnection', 'LocalConnectionClass', LocalConnectionDefinition),
michael@0 51314 M('flash.net.Socket', 'SocketClass', SocketDefinition),
michael@0 51315 M('flash.net.URLVariables'),
michael@0 51316 M('packageInternal flash.system.FSCommand', 'FSCommandClass', FSCommandDefinition),
michael@0 51317 M('flash.system.Capabilities', 'CapabilitiesClass', CapabilitiesDefinition),
michael@0 51318 M('flash.system.System', 'SystemClass', SystemDefinition),
michael@0 51319 M('flash.system.Security', 'SecurityClass', SecurityDefinition),
michael@0 51320 M('flash.system.SecurityDomain', 'SecurityDomainClass', SecurityDomainDefinition),
michael@0 51321 M('flash.system.ApplicationDomain', 'ApplicationDomainClass', ApplicationDomainDefinition),
michael@0 51322 M('flash.accessibility.Accessibility', 'AccessibilityClass', AccessibilityDefinition),
michael@0 51323 M('flash.utils.Timer', 'TimerClass', TimerDefinition),
michael@0 51324 M('avm1lib.AS2Utils', 'AS2Utils', AS2UtilsDefinition),
michael@0 51325 M('avm1lib.AS2Broadcaster'),
michael@0 51326 M('avm1lib.AS2Key'),
michael@0 51327 M('avm1lib.AS2Mouse'),
michael@0 51328 M('avm1lib.AS2MovieClip', 'AS2MovieClip', AS2MovieClipDefinition),
michael@0 51329 M('avm1lib.AS2Button', 'AS2Button', AS2ButtonDefinition),
michael@0 51330 M('avm1lib.AS2TextField', 'AS2TextField', AS2TextFieldDefinition),
michael@0 51331 M('avm1lib.AS2Stage'),
michael@0 51332 M('avm1lib.AS2System'),
michael@0 51333 M('avm1lib.AS2Color'),
michael@0 51334 M('avm1lib.AS2Globals', 'AS2Globals', AS2GlobalsDefinition),
michael@0 51335 M('avm1lib.AS2MovieClipLoader', 'AS2MovieClipLoader', AS2MovieClipLoaderDefinition)
michael@0 51336 ].forEach(function (m) {
michael@0 51337 var className = Multiname.fromSimpleName(m.classSimpleName);
michael@0 51338 var path = className.getOriginalName().split('.');
michael@0 51339 var container = this;
michael@0 51340 for (var i = 0, j = path.length - 1; i < j; i++) {
michael@0 51341 if (!container[path[i]]) {
michael@0 51342 container[path[i]] = {};
michael@0 51343 }
michael@0 51344 container = container[path[i]];
michael@0 51345 }
michael@0 51346 makeStub(container, m.classSimpleName, path[path.length - 1]);
michael@0 51347 if (m.nativeName) {
michael@0 51348 bindNativeClassDefinition(m.nativeName, m.definition);
michael@0 51349 }
michael@0 51350 definitions[className.getOriginalName()] = m.definition;
michael@0 51351 });
michael@0 51352 }();
michael@0 51353 natives['FlashUtilScript::getAliasName'] = function (domain, scope, instanceConstructor, baseClass) {
michael@0 51354 return function getAliasName(value) {
michael@0 51355 return value.debugName;
michael@0 51356 };
michael@0 51357 };
michael@0 51358 natives['FlashUtilScript::getDefinitionByName'] = natives.getDefinitionByName;
michael@0 51359 natives['FlashUtilScript::getTimer'] = function GetTimerMethod(domain, scope, instanceConstructor, baseClass) {
michael@0 51360 var start = Date.now();
michael@0 51361 return function getTimer() {
michael@0 51362 return Date.now() - start;
michael@0 51363 };
michael@0 51364 };
michael@0 51365 natives['FlashUtilScript::escapeMultiByte'] = function EscapeMultiByteMethod(domain, scope, instanceConstructor, baseClass) {
michael@0 51366 return escape;
michael@0 51367 };
michael@0 51368 natives['FlashUtilScript::unescapeMultiByte'] = function UnescapeMultiByteMethod(domain, scope, instanceConstructor, baseClass) {
michael@0 51369 return unescape;
michael@0 51370 };
michael@0 51371 natives['FlashNetScript::navigateToURL'] = function GetNavigateToURLMethod(domain, scope, instanceConstructor, baseClass) {
michael@0 51372 return function navigateToURL(request, window_) {
michael@0 51373 if (request === null || request === undefined) {
michael@0 51374 throwError('TypeError', Errors.NullPointerError, 'request');
michael@0 51375 }
michael@0 51376 var RequestClass = avm2.systemDomain.getClass('flash.net.URLRequest');
michael@0 51377 if (!RequestClass.isInstanceOf(request)) {
michael@0 51378 throwError('TypeError', Errors.CheckTypeFailedError, request, 'flash.net.URLRequest');
michael@0 51379 }
michael@0 51380 var url = request.url;
michael@0 51381 if (/^fscommand:/i.test(url)) {
michael@0 51382 var fscommand = avm2.applicationDomain.getProperty(Multiname.fromSimpleName('flash.system.fscommand'), true, true);
michael@0 51383 fscommand.call(null, url.substring('fscommand:'.length), window_);
michael@0 51384 return;
michael@0 51385 }
michael@0 51386 var targetWindow = window_ || '_parent';
michael@0 51387 window.open(FileLoadingService.resolveUrl(url), targetWindow);
michael@0 51388 };
michael@0 51389 };
michael@0 51390 natives['FlashNetScript::sendToURL'] = function GetSendToURLMethod(domain, scope, instanceConstructor, baseClass) {
michael@0 51391 return function sendToURL(request) {
michael@0 51392 if (request === null || request === undefined) {
michael@0 51393 throwError('TypeError', Errors.NullPointerError, 'request');
michael@0 51394 }
michael@0 51395 var RequestClass = avm2.systemDomain.getClass('flash.net.URLRequest');
michael@0 51396 if (!RequestClass.isInstanceOf(request)) {
michael@0 51397 throwError('TypeError', Errors.CheckTypeFailedError, request, 'flash.net.URLRequest');
michael@0 51398 }
michael@0 51399 var session = FileLoadingService.createSession();
michael@0 51400 session.onprogress = function () {
michael@0 51401 };
michael@0 51402 session.open(request);
michael@0 51403 };
michael@0 51404 };
michael@0 51405 natives['Toplevel::registerClassAlias'] = function GetRegisterClassAliasMethod(domain, scope, instance, baseClass) {
michael@0 51406 return function registerClassAlias(aliasName, classObject) {
michael@0 51407 if (!aliasName) {
michael@0 51408 throwError('TypeError', Errors.NullPointerError, 'aliasName');
michael@0 51409 }
michael@0 51410 if (!classObject) {
michael@0 51411 throwError('TypeError', Errors.NullPointerError, 'classObject');
michael@0 51412 }
michael@0 51413 AMFUtils.aliasesCache.classes.set(classObject, aliasName);
michael@0 51414 AMFUtils.aliasesCache.names[aliasName] = classObject;
michael@0 51415 };
michael@0 51416 };
michael@0 51417 natives['Toplevel::getClassByAlias'] = function GetGetClassByAliasMethod(domain, scope, instance, baseClass) {
michael@0 51418 return function getClassByAlias(aliasName) {
michael@0 51419 if (!aliasName) {
michael@0 51420 throwError('TypeError', Errors.NullPointerError, 'aliasName');
michael@0 51421 }
michael@0 51422 var classObject = AMFUtils.aliasesCache.names[aliasName];
michael@0 51423 if (!classObject) {
michael@0 51424 throwError('ReferenceError', Errors.ClassNotFoundError, aliasName);
michael@0 51425 }
michael@0 51426 return classObject;
michael@0 51427 };
michael@0 51428 };

mercurial