PageRenderTime 78ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/Frameworks/Objective-J/Objective-J.js

http://github.com/polymar/polish
JavaScript | 2436 lines | 2414 code | 1 blank | 21 comment | 393 complexity | 1bd1583396e5b51a52e552f95501ff94 MD5 | raw file
Possible License(s): LGPL-2.1, CC-BY-3.0
  1. /*
  2. * Objective-J.js
  3. * Objective-J
  4. *
  5. * Created by Francisco Tolmasky.
  6. * Copyright 2008, 280 North, Inc.
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. */
  22. var NO = false,
  23. YES = true,
  24. nil = null,
  25. Nil = null,
  26. NULL = null,
  27. ABS = Math.abs,
  28. ASIN = Math.asin,
  29. ACOS = Math.acos,
  30. ATAN = Math.atan,
  31. ATAN2 = Math.atan2,
  32. SIN = Math.sin,
  33. COS = Math.cos,
  34. TAN = Math.tan,
  35. EXP = Math.exp,
  36. POW = Math.pow,
  37. CEIL = Math.ceil,
  38. FLOOR = Math.floor,
  39. ROUND = Math.round,
  40. MIN = Math.min,
  41. MAX = Math.max,
  42. RAND = Math.random,
  43. SQRT = Math.sqrt,
  44. E = Math.E,
  45. LN2 = Math.LN2,
  46. LN10 = Math.LN10,
  47. LOG2E = Math.LOG2E,
  48. LOG10E = Math.LOG10E,
  49. PI = Math.PI,
  50. PI2 = Math.PI * 2.0,
  51. PI_2 = Math.PI / 2.0,
  52. SQRT1_2 = Math.SQRT1_2,
  53. SQRT2 = Math.SQRT2;
  54. window.setNativeTimeout = window.setTimeout;
  55. window.clearNativeTimeout = window.clearTimeout;
  56. window.setNativeInterval = window.setInterval;
  57. window.clearNativeInterval = window.clearInterval;
  58. var objj_continue_alerting = NO;
  59. function objj_alert(aString)
  60. {
  61. if (!objj_continue_alerting)
  62. return;
  63. objj_continue_alerting = confirm(aString + "\n\nClick cancel to prevent further alerts.");
  64. }
  65. function objj_fprintf(stream, string)
  66. {
  67. stream(string);
  68. }
  69. function objj_printf(string)
  70. {
  71. objj_fprintf(alert, string);
  72. }
  73. if (window.console && window.console.warn)
  74. var warning_stream = function(aString) { window.console.warn(aString); }
  75. else
  76. var warning_stream = function(){};
  77. var _sprintfFormatRegex = new RegExp("([^%]+|%[\\+\\-\\ \\#0]*[0-9\\*]*(.[0-9\\*]+)?[hlL]?[cbBdieEfgGosuxXpn%@])", "g");
  78. var _sprintfTagRegex = new RegExp("(%)([\\+\\-\\ \\#0]*)([0-9\\*]*)((.[0-9\\*]+)?)([hlL]?)([cbBdieEfgGosuxXpn%@])");
  79. function sprintf(format)
  80. {
  81. var format = arguments[0],
  82. tokens = format.match(_sprintfFormatRegex),
  83. index = 0,
  84. result = "",
  85. arg = 1;
  86. for (var i = 0; i < tokens.length; i++)
  87. {
  88. var t = tokens[i];
  89. if (format.substring(index, index + t.length) != t)
  90. {
  91. return result;
  92. }
  93. index += t.length;
  94. if (t.charAt(0) != "%")
  95. {
  96. result += t;
  97. }
  98. else
  99. {
  100. var subtokens = t.match(_sprintfTagRegex);
  101. if (subtokens.length != 8 || subtokens[0] != t)
  102. {
  103. return result;
  104. }
  105. var percentSign = subtokens[1],
  106. flags = subtokens[2],
  107. widthString = subtokens[3],
  108. precisionString = subtokens[4],
  109. length = subtokens[6],
  110. specifier = subtokens[7];
  111. var width = null;
  112. if (widthString == "*")
  113. width = arguments[arg++];
  114. else if (widthString != "")
  115. width = Number(widthString);
  116. var precision = null;
  117. if (precisionString == ".*")
  118. precision = arguments[arg++];
  119. else if (precisionString != "")
  120. precision = Number(precisionString.substring(1));
  121. var leftJustify = (flags.indexOf("-") >= 0);
  122. var padZeros = (flags.indexOf("0") >= 0);
  123. var subresult = "";
  124. if (RegExp("[bBdiufeExXo]").test(specifier))
  125. {
  126. var num = Number(arguments[arg++]);
  127. var sign = "";
  128. if (num < 0)
  129. {
  130. sign = "-";
  131. }
  132. else
  133. {
  134. if (flags.indexOf("+") >= 0)
  135. sign = "+";
  136. else if (flags.indexOf(" ") >= 0)
  137. sign = " ";
  138. }
  139. if (specifier == "d" || specifier == "i" || specifier == "u")
  140. {
  141. var number = String(Math.abs(Math.floor(num)));
  142. subresult = _sprintf_justify(sign, "", number, "", width, leftJustify, padZeros)
  143. }
  144. if (specifier == "f")
  145. {
  146. var number = String((precision != null) ? Math.abs(num).toFixed(precision) : Math.abs(num));
  147. var suffix = (flags.indexOf("#") >= 0 && number.indexOf(".") < 0) ? "." : "";
  148. subresult = _sprintf_justify(sign, "", number, suffix, width, leftJustify, padZeros);
  149. }
  150. if (specifier == "e" || specifier == "E")
  151. {
  152. var number = String(Math.abs(num).toExponential(precision != null ? precision : 21));
  153. var suffix = (flags.indexOf("#") >= 0 && number.indexOf(".") < 0) ? "." : "";
  154. subresult = _sprintf_justify(sign, "", number, suffix, width, leftJustify, padZeros);
  155. }
  156. if (specifier == "x" || specifier == "X")
  157. {
  158. var number = String(Math.abs(num).toString(16));
  159. var prefix = (flags.indexOf("#") >= 0 && num != 0) ? "0x" : "";
  160. subresult = _sprintf_justify(sign, prefix, number, "", width, leftJustify, padZeros);
  161. }
  162. if (specifier == "b" || specifier == "B")
  163. {
  164. var number = String(Math.abs(num).toString(2));
  165. var prefix = (flags.indexOf("#") >= 0 && num != 0) ? "0b" : "";
  166. subresult = _sprintf_justify(sign, prefix, number, "", width, leftJustify, padZeros);
  167. }
  168. if (specifier == "o")
  169. {
  170. var number = String(Math.abs(num).toString(8));
  171. var prefix = (flags.indexOf("#") >= 0 && num != 0) ? "0" : "";
  172. subresult = _sprintf_justify(sign, prefix, number, "", width, leftJustify, padZeros);
  173. }
  174. if (RegExp("[A-Z]").test(specifier))
  175. subresult = subresult.toUpperCase();
  176. else
  177. subresult = subresult.toLowerCase();
  178. }
  179. else
  180. {
  181. var subresult = "";
  182. if (specifier == "%")
  183. subresult = "%";
  184. else if (specifier == "c")
  185. subresult = String(arguments[arg++]).charAt(0);
  186. else if (specifier == "s" || specifier == "@")
  187. subresult = String(arguments[arg++]);
  188. else if (specifier == "p" || specifier == "n")
  189. {
  190. arg++;
  191. subresult = "";
  192. }
  193. subresult = _sprintf_justify("", "", subresult, "", width, leftJustify, false);
  194. }
  195. result += subresult;
  196. }
  197. }
  198. return result;
  199. }
  200. var _sprintf_justify = function(sign, prefix, string, suffix, width, leftJustify, padZeros)
  201. {
  202. var length = (sign.length + prefix.length + string.length + suffix.length);
  203. if (leftJustify)
  204. {
  205. return sign + prefix + string + suffix + _sprintf_pad(width - length, " ");
  206. }
  207. else
  208. {
  209. if (padZeros)
  210. return sign + prefix + _sprintf_pad(width - length, "0") + string + suffix;
  211. else
  212. return _sprintf_pad(width - length, " ") + sign + prefix + string + suffix;
  213. }
  214. }
  215. var _sprintf_pad = function(n, ch)
  216. {
  217. var result = "";
  218. for (var i = 0; i < n; i++)
  219. result += ch;
  220. return result;
  221. }
  222. var base64_map_to = [
  223. "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z",
  224. "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z",
  225. "0","1","2","3","4","5","6","7","8","9","+","/","="],
  226. base64_map_from = [];
  227. for (var i = 0; i < base64_map_to.length; i++)
  228. base64_map_from[base64_map_to[i].charCodeAt(0)] = i;
  229. function base64_decode_to_array(input, strip)
  230. {
  231. if (strip)
  232. input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
  233. var pad = (input[input.length-1] == "=" ? 1 : 0) + (input[input.length-2] == "=" ? 1 : 0),
  234. length = input.length,
  235. output = [];
  236. var i = 0;
  237. while (i < length)
  238. {
  239. var bits = (base64_map_from[input.charCodeAt(i++)] << 18) |
  240. (base64_map_from[input.charCodeAt(i++)] << 12) |
  241. (base64_map_from[input.charCodeAt(i++)] << 6) |
  242. (base64_map_from[input.charCodeAt(i++)]);
  243. output.push((bits & 0xFF0000) >> 16);
  244. output.push((bits & 0xFF00) >> 8);
  245. output.push(bits & 0xFF);
  246. }
  247. if (pad > 0)
  248. return output.slice(0, -1 * pad);
  249. return output;
  250. }
  251. function base64_encode_array(input)
  252. {
  253. var pad = (3 - (input.length % 3)) % 3,
  254. length = input.length + pad,
  255. output = [];
  256. if (pad > 0) input.push(0);
  257. if (pad > 1) input.push(0);
  258. var i = 0;
  259. while (i < length)
  260. {
  261. var bits = (input[i++] << 16) |
  262. (input[i++] << 8) |
  263. (input[i++]);
  264. output.push(base64_map_to[(bits & 0xFC0000) >> 18]);
  265. output.push(base64_map_to[(bits & 0x3F000) >> 12]);
  266. output.push(base64_map_to[(bits & 0xFC0) >> 6]);
  267. output.push(base64_map_to[bits & 0x3F]);
  268. }
  269. if (pad > 0)
  270. {
  271. output[output.length-1] = "=";
  272. input.pop();
  273. }
  274. if (pad > 1)
  275. {
  276. output[output.length-2] = "=";
  277. input.pop();
  278. }
  279. return output.join("");
  280. }
  281. function base64_decode_to_string(input, strip)
  282. {
  283. return bytes_to_string(base64_decode_to_array(input, strip));
  284. }
  285. function bytes_to_string(bytes)
  286. {
  287. return String.fromCharCode.apply(null, bytes);
  288. }
  289. function base64_encode_string(input)
  290. {
  291. var temp = [];
  292. for (var i = 0; i < input.length; i++)
  293. temp.push(input.charCodeAt(i));
  294. return base64_encode_array(temp);
  295. }
  296. var CLS_CLASS = 0x1,
  297. CLS_META = 0x2,
  298. CLS_INITIALIZED = 0x4,
  299. CLS_INITIALIZING = 0x8;
  300. function objj_ivar( aName, aType)
  301. {
  302. this.name = aName;
  303. this.type = aType;
  304. }
  305. function objj_method( aName, anImplementation, types)
  306. {
  307. this.name = aName;
  308. this.method_imp = anImplementation;
  309. this.types = types;
  310. }
  311. function objj_class()
  312. {
  313. this.isa = NULL;
  314. this.super_class = NULL;
  315. this.sub_classes = [];
  316. this.name = NULL;
  317. this.info = 0;
  318. this.ivars = [];
  319. this.method_list = [];
  320. this.method_hash = {};
  321. this.method_store = function() { };
  322. this.method_dtable = this.method_store.prototype;
  323. this.allocator = function() { };
  324. this.__address = -1;
  325. }
  326. function objj_object()
  327. {
  328. this.isa = NULL;
  329. this.__address = -1;
  330. }
  331. var OBJECT_COUNT = 0;
  332. function _objj_generateObjectHash()
  333. {
  334. return OBJECT_COUNT++;
  335. }
  336. function class_getName( aClass)
  337. {
  338. if (aClass == Nil)
  339. return "";
  340. return aClass.name;
  341. }
  342. function class_isMetaClass( aClass)
  343. {
  344. if (!aClass)
  345. return NO;
  346. return ((aClass.info & (CLS_META)));
  347. }
  348. function class_getSuperclass( aClass)
  349. {
  350. if (aClass == Nil)
  351. return Nil;
  352. return aClass.super_class;
  353. }
  354. function class_setSuperclass( aClass, aSuperClass)
  355. {
  356. }
  357. function class_isMetaClass( aClass)
  358. {
  359. return ((aClass.info & (CLS_META)));
  360. }
  361. function class_addIvar( aClass, aName, aType)
  362. {
  363. var thePrototype = aClass.allocator.prototype;
  364. if (typeof thePrototype[aName] != "undefined")
  365. return NO;
  366. aClass.ivars.push(new objj_ivar(aName, aType));
  367. thePrototype[aName] = NULL;
  368. return YES;
  369. }
  370. function class_addIvars( aClass, ivars)
  371. {
  372. var index = 0,
  373. count = ivars.length,
  374. thePrototype = aClass.allocator.prototype;
  375. for (; index < count; ++index)
  376. {
  377. var ivar = ivars[index],
  378. name = ivar.name;
  379. if (typeof thePrototype[name] === "undefined")
  380. {
  381. aClass.ivars.push(ivar);
  382. thePrototype[name] = NULL;
  383. }
  384. }
  385. }
  386. function class_copyIvarList( aClass)
  387. {
  388. return aClass.ivars.slice(0);
  389. }
  390. function class_addMethod( aClass, aName, anImplementation, aType)
  391. {
  392. if (aClass.method_hash[aName])
  393. return NO;
  394. var method = new objj_method(aName, anImplementation, aType);
  395. aClass.method_list.push(method);
  396. aClass.method_dtable[aName] = method;
  397. method.method_imp.displayName = (((aClass.info & (CLS_META))) ? '+' : '-') + " [" + class_getName(aClass) + ' ' + method_getName(method) + ']';
  398. if (!((aClass.info & (CLS_META))) && (((aClass.info & (CLS_META))) ? aClass : aClass.isa).isa === (((aClass.info & (CLS_META))) ? aClass : aClass.isa))
  399. class_addMethods((((aClass.info & (CLS_META))) ? aClass : aClass.isa), methods);
  400. return YES;
  401. }
  402. function class_addMethods( aClass, methods)
  403. {
  404. var index = 0,
  405. count = methods.length,
  406. method_list = aClass.method_list,
  407. method_dtable = aClass.method_dtable;
  408. for (; index < count; ++index)
  409. {
  410. var method = methods[index];
  411. if (aClass.method_hash[method.name])
  412. continue;
  413. method_list.push(method);
  414. method_dtable[method.name] = method;
  415. method.method_imp.displayName = (((aClass.info & (CLS_META))) ? '+' : '-') + " [" + class_getName(aClass) + ' ' + method_getName(method) + ']';
  416. }
  417. if (!((aClass.info & (CLS_META))) && (((aClass.info & (CLS_META))) ? aClass : aClass.isa).isa === (((aClass.info & (CLS_META))) ? aClass : aClass.isa))
  418. class_addMethods((((aClass.info & (CLS_META))) ? aClass : aClass.isa), methods);
  419. }
  420. function class_getInstanceMethod( aClass, aSelector)
  421. {
  422. if (!aClass || !aSelector)
  423. return NULL;
  424. var method = aClass.method_dtable[aSelector];
  425. return method ? method : NULL;
  426. }
  427. function class_getClassMethod( aClass, aSelector)
  428. {
  429. if (!aClass || !aSelector)
  430. return NULL;
  431. var method = (((aClass.info & (CLS_META))) ? aClass : aClass.isa).method_dtable[aSelector];
  432. return method ? method : NULL;
  433. }
  434. function class_copyMethodList( aClass)
  435. {
  436. return aClass.method_list.slice(0);
  437. }
  438. function class_replaceMethod( aClass, aSelector, aMethodImplementation)
  439. {
  440. if (!aClass || !aSelector)
  441. return NULL;
  442. var method = aClass.method_dtable[aSelector],
  443. method_imp = NULL;
  444. if (method)
  445. method_imp = method.method_imp;
  446. method.method_imp = aMethodImplementation;
  447. return method_imp;
  448. }
  449. var _class_initialize = function( aClass)
  450. {
  451. var meta = (((aClass.info & (CLS_META))) ? aClass : aClass.isa);
  452. if ((aClass.info & (CLS_META)))
  453. aClass = objj_getClass(aClass.name);
  454. if (aClass.super_class && !((((aClass.super_class.info & (CLS_META))) ? aClass.super_class : aClass.super_class.isa).info & (CLS_INITIALIZED)))
  455. _class_initialize(aClass.super_class);
  456. if (!(meta.info & (CLS_INITIALIZED)) && !(meta.info & (CLS_INITIALIZING)))
  457. {
  458. meta.info = (meta.info | (CLS_INITIALIZING)) & ~(0);
  459. objj_msgSend(aClass, "initialize");
  460. meta.info = (meta.info | (CLS_INITIALIZED)) & ~(CLS_INITIALIZING);
  461. }
  462. }
  463. var _objj_forward = new objj_method("forward", function(self, _cmd)
  464. {
  465. return objj_msgSend(self, "forward::", _cmd, arguments);
  466. });
  467. function class_getMethodImplementation( aClass, aSelector)
  468. {
  469. if (!((((aClass.info & (CLS_META))) ? aClass : aClass.isa).info & (CLS_INITIALIZED))) _class_initialize(aClass); var method = aClass.method_dtable[aSelector]; if (!method) method = _objj_forward; var implementation = method.method_imp;;
  470. return implementation;
  471. }
  472. var GLOBAL_NAMESPACE = window,
  473. REGISTERED_CLASSES = {};
  474. function objj_allocateClassPair( superclass, aName)
  475. {
  476. var classObject = new objj_class(),
  477. metaClassObject = new objj_class(),
  478. rootClassObject = classObject;
  479. if (superclass)
  480. {
  481. rootClassObject = superclass;
  482. while (rootClassObject.superclass)
  483. rootClassObject = rootClassObject.superclass;
  484. classObject.allocator.prototype = new superclass.allocator;
  485. classObject.method_store.prototype = new superclass.method_store;
  486. classObject.method_dtable = classObject.method_store.prototype;
  487. metaClassObject.method_store.prototype = new superclass.isa.method_store;
  488. metaClassObject.method_dtable = metaClassObject.method_store.prototype;
  489. classObject.super_class = superclass;
  490. metaClassObject.super_class = superclass.isa;
  491. }
  492. else
  493. classObject.allocator.prototype = new objj_object();
  494. classObject.isa = metaClassObject;
  495. classObject.name = aName;
  496. classObject.info = CLS_CLASS;
  497. classObject.__address = (OBJECT_COUNT++);
  498. metaClassObject.isa = rootClassObject.isa;
  499. metaClassObject.name = aName;
  500. metaClassObject.info = CLS_META;
  501. metaClassObject.__address = (OBJECT_COUNT++);
  502. return classObject;
  503. }
  504. function objj_registerClassPair( aClass)
  505. {
  506. GLOBAL_NAMESPACE[aClass.name] = aClass;
  507. REGISTERED_CLASSES[aClass.name] = aClass;
  508. }
  509. function class_createInstance( aClass)
  510. {
  511. if (!aClass)
  512. objj_exception_throw(new objj_exception(OBJJNilClassException, "*** Attempting to create object with Nil class."));
  513. var object = new aClass.allocator;
  514. object.__address = (OBJECT_COUNT++);
  515. object.isa = aClass;
  516. return object;
  517. }
  518. var prototype_bug = function() { }
  519. prototype_bug.prototype.member = false;
  520. with (new prototype_bug())
  521. member = true;
  522. if (new prototype_bug().member)
  523. {
  524. var fast_class_createInstance = class_createInstance;
  525. class_createInstance = function( aClass)
  526. {
  527. var object = fast_class_createInstance(aClass);
  528. if (object)
  529. {
  530. var theClass = object.isa,
  531. actualClass = theClass;
  532. while (theClass)
  533. {
  534. var ivars = theClass.ivars;
  535. count = ivars.length;
  536. while (count--)
  537. object[ivars[count].name] = NULL;
  538. theClass = theClass.super_class;
  539. }
  540. object.isa = actualClass;
  541. }
  542. return object;
  543. }
  544. }
  545. function object_getClassName( anObject)
  546. {
  547. if (!anObject)
  548. return "";
  549. var theClass = anObject.isa;
  550. return theClass ? class_getName(theClass) : "";
  551. }
  552. function objj_lookUpClass( aName)
  553. {
  554. var theClass = REGISTERED_CLASSES[aName];
  555. return theClass ? theClass : Nil;
  556. }
  557. function objj_getClass( aName)
  558. {
  559. var theClass = REGISTERED_CLASSES[aName];
  560. if (!theClass)
  561. {
  562. }
  563. return theClass ? theClass : Nil;
  564. }
  565. function objj_getMetaClass( aName)
  566. {
  567. var theClass = objj_getClass(aName);
  568. return (((theClass.info & (CLS_META))) ? theClass : theClass.isa);
  569. }
  570. function ivar_getName(anIvar)
  571. {
  572. return anIvar.name;
  573. }
  574. function ivar_getTypeEncoding(anIvar)
  575. {
  576. return anIvar.type;
  577. }
  578. function objj_msgSend( aReceiver, aSelector)
  579. {
  580. if (aReceiver == nil)
  581. return nil;
  582. if (!((((aReceiver.isa.info & (CLS_META))) ? aReceiver.isa : aReceiver.isa.isa).info & (CLS_INITIALIZED))) _class_initialize(aReceiver.isa); var method = aReceiver.isa.method_dtable[aSelector]; if (!method) method = _objj_forward; var implementation = method.method_imp;;
  583. switch(arguments.length)
  584. {
  585. case 2:
  586. return implementation(aReceiver, aSelector);
  587. case 3:
  588. return implementation(aReceiver, aSelector, arguments[2]);
  589. case 4:
  590. return implementation(aReceiver, aSelector, arguments[2], arguments[3]);
  591. }
  592. return implementation.apply(aReceiver, arguments);
  593. }
  594. function objj_msgSendSuper( aSuper, aSelector)
  595. {
  596. var super_class = aSuper.super_class;
  597. arguments[0] = aSuper.receiver;
  598. if (!((((super_class.info & (CLS_META))) ? super_class : super_class.isa).info & (CLS_INITIALIZED))) _class_initialize(super_class); var method = super_class.method_dtable[aSelector]; if (!method) method = _objj_forward; var implementation = method.method_imp;;
  599. return implementation.apply(aSuper.receiver, arguments);
  600. }
  601. function method_getName( aMethod)
  602. {
  603. return aMethod.name;
  604. }
  605. function method_getImplementation( aMethod)
  606. {
  607. return aMethod.method_imp;
  608. }
  609. function method_setImplementation( aMethod, anImplementation)
  610. {
  611. var oldImplementation = aMethod.method_imp;
  612. aMethod.method_imp = anImplementation;
  613. return oldImplementation;
  614. }
  615. function method_exchangeImplementations( lhs, rhs)
  616. {
  617. var lhs_imp = method_getImplementation(lhs),
  618. rhs_imp = method_getImplementation(rhs);
  619. method_setImplementation(lhs, rhs_imp);
  620. method_setImplementation(rhs, lhs_imp);
  621. }
  622. function sel_getName(aSelector)
  623. {
  624. return aSelector ? aSelector : "<null selector>";
  625. }
  626. function sel_getUid( aName)
  627. {
  628. return aName;
  629. }
  630. function sel_isEqual( lhs, rhs)
  631. {
  632. return lhs === rhs;
  633. }
  634. function sel_registerName(aName)
  635. {
  636. return aName;
  637. }
  638. function objj_dictionary()
  639. {
  640. this._keys = [];
  641. this.count = 0;
  642. this._buckets = {};
  643. this.__address = (OBJECT_COUNT++);
  644. }
  645. function dictionary_containsKey(aDictionary, aKey)
  646. {
  647. return aDictionary._buckets[aKey] != NULL;
  648. }
  649. function dictionary_getCount(aDictionary)
  650. {
  651. return aDictionary.count;
  652. }
  653. function dictionary_getValue(aDictionary, aKey)
  654. {
  655. return aDictionary._buckets[aKey];
  656. }
  657. function dictionary_setValue(aDictionary, aKey, aValue)
  658. {
  659. if (aDictionary._buckets[aKey] == NULL)
  660. {
  661. aDictionary._keys.push(aKey);
  662. ++aDictionary.count;
  663. }
  664. if ((aDictionary._buckets[aKey] = aValue) == NULL)
  665. --aDictionary.count;
  666. }
  667. function dictionary_removeValue(aDictionary, aKey)
  668. {
  669. if (aDictionary._buckets[aKey] == NULL)
  670. return;
  671. --aDictionary.count;
  672. if (aDictionary._keys.indexOf)
  673. aDictionary._keys.splice(aDictionary._keys.indexOf(aKey), 1);
  674. else
  675. {
  676. var keys = aDictionary._keys,
  677. index = 0,
  678. count = keys.length;
  679. for (; index < count; ++index)
  680. if (keys[index] == aKey)
  681. {
  682. keys.splice(index, 1);
  683. break;
  684. }
  685. }
  686. delete aDictionary._buckets[aKey];
  687. }
  688. function dictionary_replaceValue(aDictionary, aKey, aValue)
  689. {
  690. if (aDictionary[aKey] == NULL)
  691. return;
  692. }
  693. function dictionary_description(aDictionary)
  694. {
  695. var str = "{ ";
  696. for ( x in aDictionary._buckets)
  697. str += x + ":" + aDictionary._buckets[x] + ",";
  698. str += " }";
  699. return str;
  700. }
  701. var kCFPropertyListOpenStepFormat = 1,
  702. kCFPropertyListXMLFormat_v1_0 = 100,
  703. kCFPropertyListBinaryFormat_v1_0 = 200,
  704. kCFPropertyList280NorthFormat_v1_0 = -1000;
  705. var OBJJPlistParseException = "OBJJPlistParseException",
  706. OBJJPlistSerializeException = "OBJJPlistSerializeException";
  707. var kCFPropertyList280NorthMagicNumber = "280NPLIST";
  708. function objj_data()
  709. {
  710. this.string = "";
  711. this._plistObject = NULL;
  712. this.bytes = NULL;
  713. this.base64 = NULL;
  714. }
  715. var objj_markedStream = function(aString)
  716. {
  717. var index = aString.indexOf(';');
  718. this._magicNumber = aString.substr(0, index);
  719. this._location = aString.indexOf(';', ++index);
  720. this._version = aString.substring(index, this._location++);
  721. this._string = aString;
  722. }
  723. objj_markedStream.prototype.magicNumber = function()
  724. {
  725. return this._magicNumber;
  726. }
  727. objj_markedStream.prototype.version = function()
  728. {
  729. return this._version;
  730. }
  731. objj_markedStream.prototype.getMarker = function()
  732. {
  733. var string = this._string,
  734. location = this._location;
  735. if (location >= string.length)
  736. return NULL;
  737. var next = string.indexOf(';', location);
  738. if (next < 0)
  739. return NULL;
  740. var marker = string.substring(location, next);
  741. this._location = next + 1;
  742. return marker;
  743. }
  744. objj_markedStream.prototype.getString = function()
  745. {
  746. var string = this._string,
  747. location = this._location;
  748. if (location >= string.length)
  749. return NULL;
  750. var next = string.indexOf(';', location);
  751. if (next < 0)
  752. return NULL;
  753. var size = parseInt(string.substring(location, next)),
  754. text = string.substr(next + 1, size);
  755. this._location = next + 1 + size;
  756. return text;
  757. }
  758. function CPPropertyListCreateData(aPlistObject, aFormat)
  759. {
  760. if (aFormat == kCFPropertyListXMLFormat_v1_0)
  761. return CPPropertyListCreateXMLData(aPlistObject);
  762. if (aFormat == kCFPropertyList280NorthFormat_v1_0)
  763. return CPPropertyListCreate280NorthData(aPlistObject);
  764. return NULL;
  765. }
  766. function CPPropertyListCreateFromData(aData, aFormat)
  767. {
  768. if (!aFormat)
  769. {
  770. if (aData instanceof objj_data)
  771. {
  772. var string = aData.string ? aData.string : objj_msgSend(aData, "string");
  773. if (string.substr(0, kCFPropertyList280NorthMagicNumber.length) == kCFPropertyList280NorthMagicNumber)
  774. aFormat = kCFPropertyList280NorthFormat_v1_0;
  775. else
  776. aFormat = kCFPropertyListXMLFormat_v1_0;
  777. }
  778. else
  779. aFormat = kCFPropertyListXMLFormat_v1_0;
  780. }
  781. if (aFormat == kCFPropertyListXMLFormat_v1_0)
  782. return CPPropertyListCreateFromXMLData(aData);
  783. if (aFormat == kCFPropertyList280NorthFormat_v1_0)
  784. return CPPropertyListCreateFrom280NorthData(aData);
  785. return NULL;
  786. }
  787. var _CPPropertyListSerializeObject = function(aPlist, serializers)
  788. {
  789. var type = typeof aPlist,
  790. valueOf = aPlist.valueOf(),
  791. typeValueOf = typeof valueOf;
  792. if (type != typeValueOf)
  793. {
  794. type = typeValueOf;
  795. aPlist = valueOf;
  796. }
  797. if (type == "string")
  798. return serializers["string"](aPlist, serializers);
  799. else if (aPlist === true || aPlist === false)
  800. return serializers["boolean"](aPlist, serializers);
  801. else if (type == "number")
  802. {
  803. var integer = FLOOR(aPlist);
  804. if (integer == aPlist)
  805. return serializers["integer"](aPlist, serializers);
  806. else
  807. return serializers["real"](aPlist, serializers);
  808. }
  809. else if (aPlist.slice)
  810. return serializers["array"](aPlist, serializers);
  811. else
  812. return serializers["dictionary"](aPlist, serializers);
  813. }
  814. var XML_XML = "xml",
  815. XML_DOCUMENT = "#document",
  816. PLIST_PLIST = "plist",
  817. PLIST_KEY = "key",
  818. PLIST_DICTIONARY = "dict",
  819. PLIST_ARRAY = "array",
  820. PLIST_STRING = "string",
  821. PLIST_BOOLEAN_TRUE = "true",
  822. PLIST_BOOLEAN_FALSE = "false",
  823. PLIST_NUMBER_REAL = "real",
  824. PLIST_NUMBER_INTEGER = "integer",
  825. PLIST_DATA = "data";
  826. var _plist_traverseNextNode = function(anXMLNode, stayWithin, stack)
  827. {
  828. var node = anXMLNode;
  829. node = (node.firstChild); if (node != NULL && ((node.nodeType) == 8 || (node.nodeType) == 3)) while ((node = (node.nextSibling)) && ((node.nodeType) == 8 || (node.nodeType) == 3)) ;;
  830. if (node)
  831. return node;
  832. if ((String(anXMLNode.nodeName)) == PLIST_ARRAY || (String(anXMLNode.nodeName)) == PLIST_DICTIONARY)
  833. stack.pop();
  834. else
  835. {
  836. if (node == stayWithin)
  837. return NULL;
  838. node = anXMLNode;
  839. while ((node = (node.nextSibling)) && ((node.nodeType) == 8 || (node.nodeType) == 3)) ;;
  840. if (node)
  841. return node;
  842. }
  843. node = anXMLNode;
  844. while (node)
  845. {
  846. var next = node;
  847. while ((next = (next.nextSibling)) && ((next.nodeType) == 8 || (next.nodeType) == 3)) ;;
  848. if (next)
  849. return next;
  850. var node = (node.parentNode);
  851. if (stayWithin && node == stayWithin)
  852. return NULL;
  853. stack.pop();
  854. }
  855. return NULL;
  856. }
  857. function CPPropertyListCreateFromXMLData(XMLNodeOrData)
  858. {
  859. var XMLNode = XMLNodeOrData;
  860. if (XMLNode.string)
  861. {
  862. if (window.ActiveXObject)
  863. {
  864. XMLNode = new ActiveXObject("Microsoft.XMLDOM");
  865. XMLNode.loadXML(XMLNodeOrData.string.substr(XMLNodeOrData.string.indexOf(".dtd\">") + 6));
  866. }
  867. else
  868. XMLNode = (new DOMParser().parseFromString(XMLNodeOrData.string, "text/xml").documentElement);
  869. }
  870. while (((String(XMLNode.nodeName)) == XML_DOCUMENT) || ((String(XMLNode.nodeName)) == XML_XML))
  871. XMLNode = (XMLNode.firstChild); if (XMLNode != NULL && ((XMLNode.nodeType) == 8 || (XMLNode.nodeType) == 3)) while ((XMLNode = (XMLNode.nextSibling)) && ((XMLNode.nodeType) == 8 || (XMLNode.nodeType) == 3)) ;;
  872. if (((XMLNode.nodeType) == 10))
  873. while ((XMLNode = (XMLNode.nextSibling)) && ((XMLNode.nodeType) == 8 || (XMLNode.nodeType) == 3)) ;;
  874. if (!((String(XMLNode.nodeName)) == PLIST_PLIST))
  875. return NULL;
  876. var key = "",
  877. object = NULL,
  878. plistObject = NULL,
  879. plistNode = XMLNode,
  880. containers = [],
  881. currentContainer = NULL;
  882. while (XMLNode = _plist_traverseNextNode(XMLNode, plistNode, containers))
  883. {
  884. var count = containers.length;
  885. if (count)
  886. currentContainer = containers[count - 1];
  887. if ((String(XMLNode.nodeName)) == PLIST_KEY)
  888. {
  889. key = ((String((XMLNode.firstChild).nodeValue)));
  890. while ((XMLNode = (XMLNode.nextSibling)) && ((XMLNode.nodeType) == 8 || (XMLNode.nodeType) == 3)) ;;
  891. }
  892. switch (String((String(XMLNode.nodeName))))
  893. {
  894. case PLIST_ARRAY: object = []
  895. containers.push(object);
  896. break;
  897. case PLIST_DICTIONARY: object = new objj_dictionary();
  898. containers.push(object);
  899. break;
  900. case PLIST_NUMBER_REAL: object = parseFloat(((String((XMLNode.firstChild).nodeValue))));
  901. break;
  902. case PLIST_NUMBER_INTEGER: object = parseInt(((String((XMLNode.firstChild).nodeValue))));
  903. break;
  904. case PLIST_STRING: object = _decodeHTMLComponent((XMLNode.firstChild) ? ((String((XMLNode.firstChild).nodeValue))) : "");
  905. break;
  906. case PLIST_BOOLEAN_TRUE: object = true;
  907. break;
  908. case PLIST_BOOLEAN_FALSE: object = false;
  909. break;
  910. case PLIST_DATA: object = new objj_data();
  911. object.bytes = (XMLNode.firstChild) ? base64_decode_to_array(((String((XMLNode.firstChild).nodeValue))), true) : [];
  912. break;
  913. default: objj_exception_throw(new objj_exception(OBJJPlistParseException, "*** " + (String(XMLNode.nodeName)) + " tag not recognized in Plist."));
  914. }
  915. if (!plistObject)
  916. plistObject = object;
  917. else if (currentContainer)
  918. if (currentContainer.slice)
  919. currentContainer.push(object);
  920. else
  921. { if ((currentContainer)._buckets[key] == NULL) { (currentContainer)._keys.push(key); ++(currentContainer).count; } if (((currentContainer)._buckets[key] = object) == NULL) --(currentContainer).count;};
  922. }
  923. return plistObject;
  924. }
  925. function CPPropertyListCreateXMLData(aPlist)
  926. {
  927. var data = new objj_data();
  928. data.string = "";
  929. data.string += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
  930. data.string += "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">";
  931. data.string += "<plist version = \"1.0\">";
  932. _CPPropertyListAppendXMLData(data, aPlist, "");
  933. data.string += "</plist>";
  934. return data;
  935. }
  936. var _CPArrayAppendXMLData = function(XMLData, anArray)
  937. {
  938. var i = 0,
  939. count = anArray.length;
  940. XMLData.string += "<array>";
  941. for (; i < count; ++i)
  942. _CPPropertyListAppendXMLData(XMLData, anArray[i]);
  943. XMLData.string += "</array>";
  944. }
  945. var _CPDictionaryAppendXMLData = function(XMLData, aDictionary)
  946. {
  947. var keys = aDictionary._keys,
  948. i = 0,
  949. count = keys.length;
  950. XMLData.string += "<dict>";
  951. for (; i < count; ++i)
  952. {
  953. XMLData.string += "<key>" + keys[i] + "</key>";
  954. _CPPropertyListAppendXMLData(XMLData, ((aDictionary)._buckets[keys[i]]));
  955. }
  956. XMLData.string += "</dict>";
  957. }
  958. var _encodeHTMLComponent = function(aString)
  959. {
  960. return aString.replace('<', "&lt;").replace('>', "&gt;").replace('\"', "&quot;").replace('\'', "&apos;").replace('&', "&amp;");
  961. }
  962. var _decodeHTMLComponent = function(aString)
  963. {
  964. return aString.replace("&lt;", '<').replace("&gt;", '>').replace("&quot;", '\"').replace("&apos;", '\'').replace("&amp;", '&');
  965. }
  966. var _CPPropertyListAppendXMLData = function(XMLData, aPlist)
  967. {
  968. var type = typeof aPlist,
  969. valueOf = aPlist.valueOf(),
  970. typeValueOf = typeof valueOf;
  971. if (type != typeValueOf)
  972. {
  973. type = typeValueOf;
  974. aPlist = valueOf;
  975. }
  976. if (type == "string")
  977. XMLData.string += "<string>" + _encodeHTMLComponent(aPlist) + "</string>";
  978. else if (aPlist === true)
  979. XMLData.string += "<true/>";
  980. else if (aPlist === false)
  981. XMLData.string += "<false/>";
  982. else if (type == "number")
  983. {
  984. var integer = FLOOR(aPlist);
  985. if (integer == aPlist)
  986. XMLData.string += "<integer>" + aPlist + "</integer>";
  987. else
  988. XMLData.string += "<real>" + aPlist + "</real>";
  989. }
  990. else if (aPlist.slice)
  991. _CPArrayAppendXMLData(XMLData, aPlist);
  992. else if (aPlist._keys)
  993. _CPDictionaryAppendXMLData(XMLData, aPlist);
  994. else
  995. objj_exception_throw(new objj_exception(OBJJPlistSerializeException, "*** unknown plist ("+aPlist+") type: " + type));
  996. }
  997. var ARRAY_MARKER = "A",
  998. DICTIONARY_MARKER = "D",
  999. FLOAT_MARKER = "f",
  1000. INTEGER_MARKER = "d",
  1001. STRING_MARKER = "S",
  1002. TRUE_MARKER = "T",
  1003. FALSE_MARKER = "F",
  1004. KEY_MARKER = "K",
  1005. END_MARKER = "E";
  1006. function CPPropertyListCreateFrom280NorthData(aData)
  1007. {
  1008. var stream = new objj_markedStream(aData.string),
  1009. marker = NULL,
  1010. key = "",
  1011. object = NULL,
  1012. plistObject = NULL,
  1013. containers = [],
  1014. currentContainer = NULL;
  1015. while (marker = stream.getMarker())
  1016. {
  1017. if (marker === END_MARKER)
  1018. {
  1019. containers.pop();
  1020. continue;
  1021. }
  1022. var count = containers.length;
  1023. if (count)
  1024. currentContainer = containers[count - 1];
  1025. if (marker === KEY_MARKER)
  1026. {
  1027. key = stream.getString();
  1028. marker = stream.getMarker();
  1029. }
  1030. switch (marker)
  1031. {
  1032. case ARRAY_MARKER: object = []
  1033. containers.push(object);
  1034. break;
  1035. case DICTIONARY_MARKER: object = new objj_dictionary();
  1036. containers.push(object);
  1037. break;
  1038. case FLOAT_MARKER: object = parseFloat(stream.getString());
  1039. break;
  1040. case INTEGER_MARKER: object = parseInt(stream.getString());
  1041. break;
  1042. case STRING_MARKER: object = stream.getString();
  1043. break;
  1044. case TRUE_MARKER: object = true;
  1045. break;
  1046. case FALSE_MARKER: object = false;
  1047. break;
  1048. default: objj_exception_throw(new objj_exception(OBJJPlistParseException, "*** " + marker + " marker not recognized in Plist."));
  1049. }
  1050. if (!plistObject)
  1051. plistObject = object;
  1052. else if (currentContainer)
  1053. if (currentContainer.slice)
  1054. currentContainer.push(object);
  1055. else
  1056. { if ((currentContainer)._buckets[key] == NULL) { (currentContainer)._keys.push(key); ++(currentContainer).count; } if (((currentContainer)._buckets[key] = object) == NULL) --(currentContainer).count;};
  1057. }
  1058. return plistObject;
  1059. }
  1060. function CPPropertyListCreate280NorthData(aPlist)
  1061. {
  1062. var data = new objj_data();
  1063. data.string = kCFPropertyList280NorthMagicNumber + ";1.0;" + _CPPropertyListSerializeObject(aPlist, _CPPropertyList280NorthSerializers);
  1064. return data;
  1065. }
  1066. var _CPPropertyList280NorthSerializers = {};
  1067. _CPPropertyList280NorthSerializers["string"] = function(aString)
  1068. {
  1069. return STRING_MARKER + ';' + aString.length + ';' + aString;
  1070. }
  1071. _CPPropertyList280NorthSerializers["boolean"] = function(aBoolean)
  1072. {
  1073. return (aBoolean ? TRUE_MARKER : FALSE_MARKER) + ';';
  1074. }
  1075. _CPPropertyList280NorthSerializers["integer"] = function(anInteger)
  1076. {
  1077. var string = "" + anInteger;
  1078. return INTEGER_MARKER + ';' + string.length + ';' + string;
  1079. }
  1080. _CPPropertyList280NorthSerializers["real"] = function(aFloat)
  1081. {
  1082. var string = "" + aFloat;
  1083. return FLOAT_MARKER + ';' + string.length + ';' + string;
  1084. }
  1085. _CPPropertyList280NorthSerializers["array"] = function(anArray, serializers)
  1086. {
  1087. var index = 0,
  1088. count = anArray.length,
  1089. string = ARRAY_MARKER + ';';
  1090. for (; index < count; ++index)
  1091. string += _CPPropertyListSerializeObject(anArray[index], serializers);
  1092. return string + END_MARKER + ';';
  1093. }
  1094. _CPPropertyList280NorthSerializers["dictionary"] = function(aDictionary, serializers)
  1095. {
  1096. var keys = aDictionary._keys,
  1097. index = 0,
  1098. count = keys.length,
  1099. string = DICTIONARY_MARKER +';';
  1100. for (; index < count; ++index)
  1101. {
  1102. var key = keys[index];
  1103. string += KEY_MARKER + ';' + key.length + ';' + key;
  1104. string += _CPPropertyListSerializeObject(((aDictionary)._buckets[key]), serializers);
  1105. }
  1106. return string + END_MARKER + ';';
  1107. }
  1108. var OBJJ_PLATFORMS = ["browser", "objj"];
  1109. var OBJJFileNotFoundException = "OBJJFileNotFoundException",
  1110. OBJJExecutableNotFoundException = "OBJJExecutableNotFoundException";
  1111. var objj_files = { },
  1112. objj_bundles = { },
  1113. objj_bundlesForClass = { },
  1114. objj_searches = { };
  1115. var OBJJ_NO_FILE = {};
  1116. if (typeof OBJJ_INCLUDE_PATHS === "undefined")
  1117. OBJJ_INCLUDE_PATHS = ["Frameworks", "SomethingElse"];
  1118. var OBJJ_BASE_URI = "";
  1119. if (window.opera) {
  1120. var DOMBaseElement = document.getElementsByTagName("base")[0];
  1121. if (DOMBaseElement)
  1122. OBJJ_BASE_URI = (DOMBaseElement.getAttribute('href')).substr(0, (DOMBaseElement.getAttribute('href')).lastIndexOf('/') + 1);
  1123. }
  1124. function objj_file()
  1125. {
  1126. this.path = NULL;
  1127. this.bundle = NULL;
  1128. this.included = NO;
  1129. this.contents = NULL;
  1130. this.fragments = NULL;
  1131. }
  1132. function objj_bundle()
  1133. {
  1134. this.path = NULL;
  1135. this.info = NULL;
  1136. this.__address = (OBJECT_COUNT++);
  1137. }
  1138. function objj_getBundleWithPath(aPath)
  1139. {
  1140. return objj_bundles[aPath];
  1141. }
  1142. function objj_setBundleForPath(aPath, aBundle)
  1143. {
  1144. objj_bundles[aPath] = aBundle;
  1145. }
  1146. function objj_bundleForClass(aClass)
  1147. {
  1148. return objj_bundlesForClass[aClass.name];
  1149. }
  1150. function objj_addClassForBundle(aClass, aBundle)
  1151. {
  1152. objj_bundlesForClass[aClass.name] = aBundle;
  1153. }
  1154. function objj_request_file(aFilePath, shouldSearchLocally, aCallback)
  1155. {
  1156. new objj_search(aFilePath, shouldSearchLocally, aCallback).attemptNextSearchPath();
  1157. }
  1158. var objj_search = function(aFilePath, shouldSearchLocally, aCallback)
  1159. {
  1160. this.filePath = aFilePath;
  1161. this.bundle = NULL;
  1162. this.bundleObservers = [];
  1163. this.searchPath = NULL;
  1164. this.searchedPaths = [];
  1165. this.includePathsIndex = shouldSearchLocally ? -1 : 0;
  1166. this.searchRequest = NULL;
  1167. this.didCompleteCallback = aCallback;
  1168. }
  1169. objj_search.prototype.nextSearchPath = function()
  1170. {
  1171. var path = objj_standardize_path((this.includePathsIndex == -1 ? "" : OBJJ_INCLUDE_PATHS[this.includePathsIndex] + '/') + this.filePath);
  1172. ++this.includePathsIndex;
  1173. return path;
  1174. }
  1175. objj_search.prototype.attemptNextSearchPath = function()
  1176. {
  1177. var searchPath = this.nextSearchPath();
  1178. file = objj_files[searchPath];
  1179. objj_alert("Will attempt to find " + this.filePath + " at " + searchPath);
  1180. if (file)
  1181. {
  1182. objj_alert("The file request at " + this.filePath + " has already been downloaded at " + searchPath);
  1183. if (this.didCompleteCallback)
  1184. this.didCompleteCallback(file);
  1185. return;
  1186. }
  1187. var existingSearch = objj_searches[searchPath];
  1188. if (existingSearch)
  1189. {
  1190. if (this.didCompleteCallback)
  1191. existingSearch.didCompleteCallback = this.didCompleteCallback;
  1192. return;
  1193. }
  1194. this.searchedPaths.push(this.searchPath = searchPath);
  1195. var infoPath = objj_standardize_path((searchPath).substr(0, (searchPath).lastIndexOf('/') + 1) + "Info.plist"),
  1196. bundle = objj_bundles[infoPath];
  1197. if (bundle)
  1198. {
  1199. this.bundle = bundle;
  1200. this.request(searchPath, this.didReceiveSearchResponse);
  1201. }
  1202. else
  1203. {
  1204. var existingBundleSearch = objj_searches[infoPath];
  1205. if (existingBundleSearch)
  1206. {
  1207. --this.includePathsIndex;
  1208. this.searchedPaths.pop();
  1209. if (this.searchedPaths.length)
  1210. this.searchPath = this.searchedPaths[this.searchedPaths.length - 1];
  1211. else
  1212. this.searchPath = NULL;
  1213. existingBundleSearch.bundleObservers.push(this);
  1214. return;
  1215. }
  1216. else
  1217. {
  1218. this.bundleObservers.push(this);
  1219. this.request(infoPath, this.didReceiveBundleResponse);
  1220. if (!this.searchReplaced)
  1221. this.searchRequest = this.request(searchPath, this.didReceiveSearchResponse);
  1222. }
  1223. }
  1224. }
  1225. if (window.ActiveXObject) {
  1226. objj_search.responseCallbackLock = NO;
  1227. objj_search.responseCallbackQueue = [];
  1228. objj_search.removeResponseCallbackForFilePath = function(aFilePath)
  1229. {
  1230. var queue = objj_search.responseCallbackQueue,
  1231. index = queue.length;
  1232. while (index--)
  1233. if (queue[index][3] == aFilePath)
  1234. {
  1235. queue.splice(index, 1);
  1236. return;
  1237. }
  1238. }
  1239. objj_search.serializeResponseCallback = function(aMethod, aSearch, aResponse, aFilePath)
  1240. {
  1241. var queue = objj_search.responseCallbackQueue;
  1242. queue.push([aMethod, aSearch, aResponse, aFilePath]);
  1243. if (objj_search.responseCallbackLock)
  1244. return;
  1245. objj_search.responseCallbackLock = YES;
  1246. while (queue.length)
  1247. {
  1248. var callback = queue[0];
  1249. queue.splice(0, 1);
  1250. callback[0].apply(callback[1], [callback[2]]);
  1251. }
  1252. objj_search.responseCallbackLock = NO;
  1253. }
  1254. }
  1255. objj_search.prototype.request = function(aFilePath, aMethod)
  1256. {
  1257. var search = this,
  1258. isPlist = aFilePath.substr(aFilePath.length - 6, 6) == ".plist",
  1259. request = objj_request_xmlhttp(),
  1260. response = objj_response_xmlhttp();
  1261. response.filePath = aFilePath;
  1262. request.onreadystatechange = function()
  1263. {
  1264. if (request.readyState == 4)
  1265. {
  1266. if (response.success = (request.status != 404 && request.responseText && request.responseText.length) ? YES : NO)
  1267. {
  1268. if (window.files_total)
  1269. {
  1270. if (!window.files_loaded)
  1271. window.files_loaded = 0;
  1272. window.files_loaded += request.responseText.length;
  1273. if (window.update_progress)
  1274. window.update_progress(window.files_loaded / window.files_total);
  1275. }
  1276. if (isPlist)
  1277. response.xml = objj_standardize_xml(request);
  1278. else
  1279. response.text = request.responseText;
  1280. }
  1281. if (window.ActiveXObject)
  1282. objj_search.serializeResponseCallback(aMethod, search, response, aFilePath);
  1283. else
  1284. aMethod.apply(search, [response]);
  1285. }
  1286. }
  1287. objj_searches[aFilePath] = this;
  1288. if (request.overrideMimeType && isPlist)
  1289. request.overrideMimeType('text/xml');
  1290. if (window.opera && aFilePath.charAt(0) != '/')
  1291. aFilePath = OBJJ_BASE_URI + aFilePath;
  1292. try
  1293. {
  1294. request.open("GET", aFilePath, YES);
  1295. request.send("");
  1296. }
  1297. catch (anException)
  1298. {
  1299. response.success = NO;
  1300. if (window.ActiveXObject)
  1301. objj_search.serializeResponseCallback(aMethod, search, response, aFilePath);
  1302. else
  1303. aMethod.apply(search, [response]);
  1304. }
  1305. return request;
  1306. }
  1307. objj_search.prototype.didReceiveSearchResponse = function(aResponse)
  1308. {
  1309. if (!this.bundle)
  1310. {
  1311. this.cachedSearchResponse = aResponse;
  1312. return;
  1313. }
  1314. if (aResponse.success)
  1315. {
  1316. file = new objj_file();
  1317. file.path = aResponse.filePath;
  1318. file.bundle = this.bundle
  1319. file.contents = aResponse.text;
  1320. this.complete(file);
  1321. }
  1322. else if (this.includePathsIndex < OBJJ_INCLUDE_PATHS.length)
  1323. {
  1324. this.bundle = NULL;
  1325. this.attemptNextSearchPath();
  1326. }
  1327. else
  1328. objj_exception_throw(new objj_exception(OBJJFileNotFoundException, "*** Could not locate file named \"" + this.filePath + "\" in search paths."));
  1329. }
  1330. objj_search.prototype.didReceiveBundleResponse = function(aResponse)
  1331. {
  1332. var bundle = new objj_bundle();
  1333. bundle.path = aResponse.filePath;
  1334. if (aResponse.success)
  1335. bundle.info = CPPropertyListCreateFromXMLData(aResponse.xml);
  1336. else
  1337. bundle.info = new objj_dictionary();
  1338. objj_bundles[aResponse.filePath] = bundle;
  1339. var executablePath = ((bundle.info)._buckets["CPBundleExecutable"]);
  1340. if (executablePath)
  1341. {
  1342. var platform = NULL,
  1343. platforms = ((bundle.info)._buckets["CPBundlePlatforms"]),
  1344. index = 0,
  1345. count = OBJJ_PLATFORMS.length,
  1346. innerCount = platforms.length;
  1347. for(; index < count; ++index)
  1348. {
  1349. var innerIndex = 0,
  1350. currentPlatform = OBJJ_PLATFORMS[index];
  1351. for (; innerIndex < innerCount; ++innerIndex)
  1352. if(currentPlatform === platforms[innerIndex])
  1353. {
  1354. platform = currentPlatform;
  1355. break;
  1356. }
  1357. }
  1358. executablePath = platform + ".platform/" + executablePath;
  1359. this.request((aResponse.filePath).substr(0, (aResponse.filePath).lastIndexOf('/') + 1) + executablePath, this.didReceiveExecutableResponse);
  1360. var directory = (aResponse.filePath).substr(0, (aResponse.filePath).lastIndexOf('/') + 1),
  1361. replacedFiles = ((bundle.info)._buckets["CPBundleReplacedFiles"]),
  1362. index = 0,
  1363. count = replacedFiles.length;
  1364. for (; index < count; ++index)
  1365. {
  1366. objj_searches[directory + replacedFiles[index]] = this;
  1367. if (directory + replacedFiles[index] == this.searchPath)
  1368. {
  1369. this.searchReplaced = YES;
  1370. if (!this.cachedSearchResponse && this.searchRequest)
  1371. this.searchRequest.abort();
  1372. if (window.ActiveXObject)
  1373. objj_search.removeResponseCallbackForFilePath(this.searchPath);
  1374. }
  1375. }
  1376. }
  1377. this.bundle = bundle;
  1378. var observers = this.bundleObservers,
  1379. index = 0,
  1380. count = observers.length;
  1381. for(; index < count; ++index)
  1382. {
  1383. var observer = observers[index];
  1384. if (observer != this)
  1385. observer.attemptNextSearchPath();
  1386. else if (this.cachedSearchResponse && !this.searchReplaced)
  1387. this.didReceiveSearchResponse(this.cachedSearchResponse);
  1388. }
  1389. this.bundleObservers = [];
  1390. }
  1391. objj_search.prototype.didReceiveExecutableResponse = function(aResponse)
  1392. {
  1393. if (!aResponse.success)
  1394. objj_exception_throw(new objj_exception(OBJJExecutableNotFoundException, "*** The specified executable could not be located at \"" + this.filePath + "\"."));
  1395. var files = objj_decompile(aResponse.text, this.bundle),
  1396. index = 0,
  1397. count = files.length,
  1398. length = this.filePath.length;
  1399. for (; index < count; ++index)
  1400. {
  1401. var file = files[index],
  1402. path = file.path;
  1403. if (this.filePath == path.substr(path.length - length))
  1404. this.complete(file);
  1405. else
  1406. objj_files[path] = file;
  1407. }
  1408. }
  1409. objj_search.prototype.complete = function(aFile)
  1410. {
  1411. var index = 0,
  1412. count = this.searchedPaths.length;
  1413. for (; index < count; ++index)
  1414. {
  1415. objj_files[this.searchedPaths[index]] = aFile;
  1416. }
  1417. if (this.didCompleteCallback)
  1418. this.didCompleteCallback(aFile);
  1419. }
  1420. function objj_standardize_path(aPath)
  1421. {
  1422. if (aPath.indexOf("/./") != -1 && aPath.indexOf("//") != -1 && aPath.indexOf("/../") != -1)
  1423. return aPath;
  1424. var index = 0,
  1425. components = aPath.split('/');
  1426. for(;index < components.length; ++index)
  1427. if(components[index] == "..")
  1428. {
  1429. components.splice(index - 1, 2);
  1430. index -= 2;
  1431. }
  1432. else if(index != 0 && !components[index].length || components[index] == '.' || components[index] == "..")
  1433. components.splice(index--, 1);
  1434. return components.join('/');
  1435. }
  1436. if (window.ActiveXObject) {
  1437. var objj_standardize_xml = function(aRequest)
  1438. {
  1439. var XMLData = new ActiveXObject("Microsoft.XMLDOM");
  1440. XMLData.loadXML(aRequest.responseText.substr(aRequest.responseText.indexOf(".dtd\">") + 6));
  1441. return XMLData;
  1442. }
  1443. } else {
  1444. var objj_standardize_xml = function(aRequest)
  1445. {
  1446. return aRequest.responseXML;
  1447. }
  1448. }
  1449. function objj_response_xmlhttp()
  1450. {
  1451. return new Object;
  1452. }
  1453. if (window.XMLHttpRequest) {
  1454. var objj_request_xmlhttp = function()
  1455. {
  1456. return new XMLHttpRequest();
  1457. }
  1458. } else if (window.ActiveXObject) {
  1459. var MSXML_XMLHTTP_OBJECTS = [ "Microsoft.XMLHTTP", "Msxml2.XMLHTTP", "Msxml2.XMLHTTP.3.0", "Msxml2.XMLHTTP.6.0" ],
  1460. index = MSXML_XMLHTTP_OBJECTS.length;
  1461. while (index--)
  1462. {
  1463. try
  1464. {
  1465. new ActiveXObject(MSXML_XMLHTTP_OBJECTS[index]);
  1466. break;
  1467. }
  1468. catch (anException)
  1469. {
  1470. }
  1471. }
  1472. var MSXML_XMLHTTP = MSXML_XMLHTTP_OBJECTS[index];
  1473. delete index;
  1474. delete MSXML_XMLHTTP_OBJECTS;
  1475. var objj_request_xmlhttp = function()
  1476. {
  1477. return new ActiveXObject(MSXML_XMLHTTP);
  1478. }
  1479. }
  1480. var OBJJUnrecognizedFormatException = "OBJJUnrecognizedFormatException";
  1481. var STATIC_MAGIC_NUMBER = "@STATIC",
  1482. MARKER_PATH = "p",
  1483. MARKER_CODE = "c",
  1484. MARKER_BUNDLE = "b",
  1485. MARKER_TEXT = "t",
  1486. MARKER_IMPORT_STD = 'I',
  1487. MARKER_IMPORT_LOCAL = 'i';
  1488. var STATIC_EXTENSION = "sj";
  1489. function objj_decompile(aString, bundle)
  1490. {
  1491. var stream = new objj_markedStream(aString);
  1492. if (stream.magicNumber() != STATIC_MAGIC_NUMBER)
  1493. objj_exception_throw(new objj_exception(OBJJUnrecognizedFormatException, "*** Could not recognize executable code format."));
  1494. if (stream.version() != 1.0)
  1495. objj_exception_throw(new objj_exception(OBJJUnrecognizedFormatException, "*** Could not recognize executable code format."));
  1496. var file = NULL,
  1497. files = [],
  1498. marker;
  1499. while (marker = stream.getMarker())
  1500. {
  1501. var text = stream.getString();
  1502. switch (marker)
  1503. {
  1504. case MARKER_PATH: if (file && file.contents && file.path === file.bundle.path)
  1505. file.bundle.info = CPPropertyListCreateWithData({string:file.contents});
  1506. file = new objj_file();
  1507. file.path = (bundle.path).substr(0, (bundle.path).lastIndexOf('/') + 1) + text;
  1508. file.bundle = bundle;
  1509. file.fragments = [];
  1510. files.push(file);
  1511. objj_files[file.path] = file;
  1512. break;
  1513. case MARKER_BUNDLE: var bundlePath = (bundle.path).substr(0, (bundle.path).lastIndexOf('/') + 1) + '/' + text;
  1514. file.bundle = objj_getBundleWithPath(bundlePath);
  1515. if (!file.bundle)
  1516. {
  1517. file.bundle = new objj_bundle();
  1518. file.bundle.path = bundlePath;
  1519. objj_setBundleForPath(file.bundle, bundlePath);
  1520. }
  1521. break;
  1522. case MARKER_TEXT: file.contents = text;
  1523. break;
  1524. case MARKER_CODE: file.fragments.push(fragment_create_code(text, bundle, file));
  1525. break;
  1526. case MARKER_IMPORT_STD: file.fragments.push(fragment_create_file(text, bundle, NO, file));
  1527. break;
  1528. case MARKER_IMPORT_LOCAL: file.fragments.push(fragment_create_file(text, bundle, YES, file));
  1529. break;
  1530. }
  1531. }
  1532. if (file && file.contents && file.path === file.bundle.path)
  1533. file.bundle.info = CPPropertyListCreateWithData({string:file.contents});
  1534. return files;
  1535. }
  1536. var OBJJ_EXCEPTION_OUTPUT_STREAM = NULL;
  1537. function objj_exception(aName, aReason, aUserInfo)
  1538. {
  1539. this.name = aName;
  1540. this.reason = aReason;
  1541. this.userInfo = aUserInfo;
  1542. this.__address = (OBJECT_COUNT++);
  1543. }
  1544. objj_exception.prototype.toString = function()
  1545. {
  1546. return this.reason;
  1547. }
  1548. function objj_exception_throw(anException)
  1549. {
  1550. throw anException;
  1551. }
  1552. function objj_exception_report(anException, aSourceFile)
  1553. {
  1554. objj_fprintf(OBJJ_EXCEPTION_OUTPUT_STREAM, aSourceFile.path + "\n" + anException);
  1555. throw anException;
  1556. }
  1557. function objj_exception_setOutputStream(aStream)
  1558. {
  1559. OBJJ_EXCEPTION_OUTPUT_STREAM = aStream;
  1560. }
  1561. objj_exception_setOutputStream(function(aString) { });
  1562. var OBJJ_PREPROCESSOR_DEBUG_SYMBOLS = 1 << 0;
  1563. function objj_preprocess( aString, aBundle, aSourceFile, flags)
  1564. {
  1565. try
  1566. {
  1567. return new objj_preprocessor(aString.replace(/^#[^\n]+\n/, "\n"), aSourceFile, aBundle, flags).fragments();
  1568. }
  1569. catch (anException)
  1570. {
  1571. objj_exception_report(anException, aSourceFile);
  1572. }
  1573. return [];
  1574. }
  1575. var OBJJParseException = "OBJJParseException",
  1576. OBJJClassNotFoundException = "OBJJClassNotFoundException";
  1577. var TOKEN_ACCESSORS = "accessors",
  1578. TOKEN_CLASS = "class",
  1579. TOKEN_END = "end",
  1580. TOKEN_FUNCTION = "function",
  1581. TOKEN_IMPLEMENTATION = "implementation",
  1582. TOKEN_IMPORT = "import",
  1583. TOKEN_NEW = "new",
  1584. TOKEN_SELECTOR = "selector",
  1585. TOKEN_SUPER = "super",
  1586. TOKEN_EQUAL = '=',
  1587. TOKEN_PLUS = '+',
  1588. TOKEN_MINUS = '-',
  1589. TOKEN_COLON = ':',
  1590. TOKEN_COMMA = ',',
  1591. TOKEN_PERIOD = '.',
  1592. TOKEN_ASTERISK = '*',
  1593. TOKEN_SEMICOLON = ';',
  1594. TOKEN_LESS_THAN = '<',
  1595. TOKEN_OPEN_BRACE = '{',
  1596. TOKEN_CLOSE_BRACE = '}',
  1597. TOKEN_GREATER_THAN = '>',
  1598. TOKEN_OPEN_BRACKET = '[',
  1599. TOKEN_DOUBLE_QUOTE = '"',
  1600. TOKEN_PREPROCESSOR = '@',
  1601. TOKEN_CLOSE_BRACKET = ']',
  1602. TOKEN_QUESTION_MARK = '?',
  1603. TOKEN_OPEN_PARENTHESIS = '(',
  1604. TOKEN_CLOSE_PARENTHESIS = ')',
  1605. TOKEN_WHITESPACE = /^(?:(?:\s+$)|(?:\/(?:\/|\*)))/,
  1606. TOKEN_NUMBER = /^[+-]?\d+(([.]\d+)*([eE][+-]?\d+))?$/,
  1607. TOKEN_IDENTIFIER = /^[a-zA-Z_$](\w|$)*$/;
  1608. var SUPER_CLASSES = new objj_dictionary();
  1609. var OBJJ_CURRENT_BUNDLE = NULL;
  1610. var objj_lexer = function(aString)
  1611. {
  1612. this._index = -1;
  1613. this._tokens = (aString + '\n').match(/\/\/.*(\r|\n)?|\/\*(?:.|\n|\r)*?\*\/|\w+\b|[+-]?\d+(([.]\d+)*([eE][+-]?\d+))?|"[^"\\]*(\\[\s\S][^"\\]*)*"|'[^'\\]*(\\[\s\S][^'\\]*)*'|\s+|./g);
  1614. this._context = [];
  1615. return this;
  1616. }
  1617. objj_lexer.prototype.push = function()
  1618. {
  1619. this._context.push(this._index);
  1620. }
  1621. objj_lexer.prototype.pop = function()
  1622. {
  1623. this._index = this._context.pop();
  1624. }
  1625. objj_lexer.prototype.peak = function(shouldSkipWhitespace)
  1626. {
  1627. if (shouldSkipWhitespace)
  1628. {
  1629. this.push();
  1630. var token = this.skip_whitespace();
  1631. this.pop();
  1632. return token;
  1633. }
  1634. return this._tokens[this._index + 1];
  1635. }
  1636. objj_lexer.prototype.next = function()
  1637. {
  1638. return this._tokens[++this._index];
  1639. }
  1640. objj_lexer.prototype.previous = function()
  1641. {
  1642. return this._tokens[--this._index];
  1643. }
  1644. objj_lexer.prototype.last = function()
  1645. {
  1646. if (this._index < 0)
  1647. return NULL;
  1648. return this._tokens[this._index - 1];
  1649. }
  1650. objj_lexer.prototype.skip_whitespace= function(shouldMoveBackwards)
  1651. {
  1652. var token;
  1653. if (shouldMoveBackwards)
  1654. while((token = this.previous()) && TOKEN_WHITESPACE.test(token)) ;
  1655. else
  1656. while((token = this.next()) && TOKEN_WHITESPACE.test(token)) ;
  1657. return token;
  1658. }
  1659. var objj_stringBuffer = function()
  1660. {
  1661. this.atoms = [];
  1662. }
  1663. objj_stringBuffer.prototype.toString = function()
  1664. {
  1665. return this.atoms.join("");
  1666. }
  1667. objj_stringBuffer.prototype.clear = function()
  1668. {
  1669. this.atoms = [];
  1670. }
  1671. objj_stringBuffer.prototype.isEmpty = function()
  1672. {
  1673. return (this.atoms.length === 0);
  1674. }
  1675. var objj_preprocessor = function(aString, aSourceFile, aBundle, flags)
  1676. {
  1677. this._currentClass = "";
  1678. this._currentSuperClass = "";
  1679. this._file = aSourceFile;
  1680. this._fragments = [];
  1681. this._preprocessed = new objj_stringBuffer();
  1682. this._tokens = new objj_lexer(aString);
  1683. this._flags = flags;
  1684. this._bundle = aBundle;
  1685. this.preprocess(this._tokens, this._preprocessed);
  1686. this.fragment();
  1687. }
  1688. objj_preprocessor.prototype.fragments = function()
  1689. {
  1690. return this._fragments;
  1691. }
  1692. objj_preprocessor.prototype.accessors = function(tokens)
  1693. {
  1694. var token = tokens.skip_whitespace(),
  1695. attributes = {};
  1696. if (token != TOKEN_OPEN_PARENTHESIS)
  1697. {
  1698. tokens.previous();
  1699. return attributes;
  1700. }
  1701. while ((token = tokens.skip_whitespace()) != TOKEN_CLOSE_PARENTHESIS)
  1702. {
  1703. var name = token,
  1704. value = true;
  1705. if (!/^\w+$/.test(name))
  1706. objj_exception_throw(new objj_exception(OBJJParseException, "*** @property attribute name not valid."));
  1707. if ((token = tokens.skip_whitespace()) == TOKEN_EQUAL)
  1708. {
  1709. value = tokens.skip_whitespace();
  1710. if (!/^\w+$/.test(value))
  1711. objj_exception_throw(new objj_exception(OBJJParseException, "*** @property attribute value not valid."));
  1712. if (name == "setter")
  1713. {
  1714. if ((token = tokens.next()) != TOKEN_COLON)
  1715. objj_exception_throw(new objj_exception(OBJJParseException, "*** @property setter attribute requires argument with \":\" at end of selector name."));
  1716. value += ":";
  1717. }
  1718. token = tokens.skip_whitespace();
  1719. }
  1720. attributes[name] = value;
  1721. if (token == TOKEN_CLOSE_PARENTHESIS)
  1722. break;
  1723. if (token != TOKEN_COMMA)
  1724. objj_exception_throw(new objj_exception(OBJJParseException, "*** Expected ',' or ')' in @property attribute list."));
  1725. }
  1726. return attributes;
  1727. }
  1728. objj_preprocessor.prototype.brackets = function( tokens, aStringBuffer)
  1729. {
  1730. var tuples = [];
  1731. while (this.preprocess(tokens, NULL, NULL, NULL, tuples[tuples.length] = [])) ;
  1732. if (tuples[0].length === 1)
  1733. {
  1734. aStringBuffer.atoms[aStringBuffer.atoms.length] = '[';
  1735. aStringBuffer.atoms[aStringBuffer.atoms.length] = tuples[0][0];
  1736. aStringBuffer.atoms[aStringBuffer.atoms.length] = ']';
  1737. }
  1738. else
  1739. {
  1740. var selector = new objj_stringBuffer();
  1741. if (tuples[0][0].atoms[0] == TOKEN_SUPER)
  1742. {
  1743. aStringBuffer.atoms[aStringBuffer.atoms.length] = "objj_msgSendSuper(";
  1744. aStringBuffer.atoms[aStringBuffer.atoms.length] = "{ receiver:self, super_class:" + this._currentSuperClass + " }";
  1745. }
  1746. else
  1747. {
  1748. aStringBuffer.atoms[aStringBuffer.atoms.length] = "objj_msgSend(";
  1749. aStringBuffer.atoms[aStringBuffer.atoms.length] = tuples[0][0];
  1750. }
  1751. selector.atoms[selector.atoms.length] = tuples[0][1];
  1752. var index = 1,
  1753. count = tuples.length,
  1754. marg_list = new objj_stringBuffer();
  1755. for(; index < count; ++index)
  1756. {
  1757. var pair = tuples[index];
  1758. selector.atoms[selector.atoms.length] = pair[1]
  1759. marg_list.atoms[marg_list.atoms.length] = ", " + pair[0];
  1760. }
  1761. aStringBuffer.atoms[aStringBuffer.atoms.length] = ", \"";
  1762. aStringBuffer.atoms[aStringBuffer.atoms.length] = selector;
  1763. aStringBuffer.atoms[aStringBuffer.atoms.length] = '\"';
  1764. aStringBuffer.atoms[aStringBuffer.atoms.length] = marg_list;
  1765. aStringBuffer.atoms[aStringBuffer.atoms.length] = ')';
  1766. }
  1767. }
  1768. objj_preprocessor.prototype.directive = function(tokens, aStringBuffer, allowedDirectivesFlags)
  1769. {
  1770. var buffer = aStringBuffer ? aStringBuffer : new objj_stringBuffer(),
  1771. token = tokens.next();
  1772. if (token.charAt(0) == TOKEN_DOUBLE_QUOTE)
  1773. buffer.atoms[buffer.atoms.length] = token;
  1774. else if (token == TOKEN_CLASS)
  1775. {
  1776. tokens.skip_whitespace();
  1777. return;
  1778. }
  1779. else if (token == TOKEN_IMPLEMENTATION)
  1780. this.implementation(tokens, buffer);
  1781. else if (token == TOKEN_IMPORT)
  1782. this._import(tokens);
  1783. else if (token == TOKEN_SELECTOR)
  1784. this.selector(tokens, buffer);
  1785. else if (token == TOKEN_ACCESSORS)
  1786. return this.accessors(tokens);
  1787. if (!aStringBuffer)
  1788. return buffer;
  1789. }
  1790. objj_preprocessor.prototype.fragment = function()
  1791. {
  1792. var preprocessed = this._preprocessed.toString();
  1793. if ((/[^\s]/).test(preprocessed)) {
  1794. this._fragments.push(fragment_create_code(preprocessed, this._bundle, this._file));
  1795. }
  1796. this._preprocessed.clear();
  1797. }
  1798. objj_preprocessor.prototype.implementation = function(tokens, aStringBuffer)
  1799. {
  1800. var buffer = aStringBuffer,
  1801. token = "",
  1802. category = NO,
  1803. class_name = tokens.skip_whitespace(),
  1804. superclass_name = "Nil",
  1805. instance_methods = new objj_stringBuffer(),
  1806. class_methods = new objj_stringBuffer();
  1807. if (!(/^\w/).test(class_name))
  1808. objj_exception_throw(new objj_exception(OBJJParseException, "*** Expected class name, found \"" + class_name + "\"."));
  1809. this._currentSuperClass = NULL;
  1810. this._currentClass = class_name;
  1811. if((token = tokens.skip_whitespace()) == TOKEN_OPEN_PARENTHESIS)
  1812. {
  1813. token = tokens.skip_whitespace();
  1814. if (token == TOKEN_CLOSE_PARENTHESIS)
  1815. objj_exception_throw(new objj_exception(OBJJParseException, "*** Can't Have Empty Category Name for class \"" + class_name + "\"."));
  1816. if (tokens.skip_whitespace() != TOKEN_CLOSE_PARENTHESIS)
  1817. objj_exception_throw(new objj_exception(OBJJParseException, "*** Improper Category Definition for class \"" + class_name + "\"."));
  1818. buffer.atoms[buffer.atoms.length] = "{\nvar the_class = objj_getClass(\"" + class_name + "\")\n";
  1819. buffer.atoms[buffer.atoms.length] = "if(!the_class) objj_exception_throw(new objj_exception(OBJJClassNotFoundException, \"*** Could not find definition for class \\\"" + class_name + "\\\"\"));\n";
  1820. buffer.atoms[buffer.atoms.length] = "var meta_class = the_class.isa;";
  1821. var superclass_name = ((SUPER_CLASSES)._buckets[class_name]);
  1822. if (!superclass_name)
  1823. this._currentSuperClass = "objj_getClass(\"" + class_name + "\").super_class";
  1824. else
  1825. this._currentSuperClass = "objj_getClass(\"" + superclass_name + "\")";
  1826. }
  1827. else
  1828. {
  1829. if(token == TOKEN_COLON)
  1830. {
  1831. token = tokens.skip_whitespace();
  1832. if (!TOKEN_IDENTIFIER.test(token))
  1833. objj_exception_throw(new objj_exception(OBJJParseException, "*** Expected class name, found \"" + token + "\"."));
  1834. superclass_name = token;
  1835. this._currentSuperClass = "objj_getClass(\"" + superclass_name + "\")";
  1836. { if ((SUPER_CLASSES)._buckets[class_name] == NULL) { (SUPER_CLASSES)._keys.push(class_name); ++(SUPER_CLASSES).count; } if (((SUPER_CLASSES)._buckets[class_name] = superclass_name) == NULL) --(SUPER_CLASSES).count;};
  1837. token = tokens.skip_whitespace();
  1838. }
  1839. buffer.atoms[buffer.atoms.length] = "{var the_class = objj_allocateClassPair(" + superclass_name + ", \"" + class_name + "\"),\nmeta_class = the_class.isa;";
  1840. if (token == TOKEN_OPEN_BRACE)
  1841. {
  1842. var ivar_count = 0,
  1843. declaration = [],
  1844. attributes,
  1845. accessors = {};
  1846. while((token = tokens.skip_whitespace()) && token != TOKEN_CLOSE_BRACE)
  1847. {
  1848. if (token == TOKEN_PREPROCESSOR)
  1849. attributes = this.directive(tokens);
  1850. else if (token == TOKEN_SEMICOLON)
  1851. {
  1852. if (ivar_count++ == 0)
  1853. buffer.atoms[buffer.atoms.length] = "class_addIvars(the_class, [";
  1854. else
  1855. buffer.atoms[buffer.atoms.length] = ", ";
  1856. var name = declaration[declaration.length - 1];
  1857. buffer.atoms[buffer.atoms.length] = "new objj_ivar(\"" + name + "\")";
  1858. declaration = [];
  1859. if (attributes)
  1860. {
  1861. accessors[name] = attributes;
  1862. attributes = NULL;
  1863. }
  1864. }
  1865. else
  1866. declaration.push(token);
  1867. }
  1868. if (declaration.length)
  1869. objj_exception_throw(new objj_exception(OBJJParseException, "*** Expected ';' in ivar declaration, found '}'."));
  1870. if (ivar_count)
  1871. buffer.atoms[buffer.atoms.length] = "]);\n";
  1872. if (!token)
  1873. objj_exception_throw(new objj_exception(OBJJParseException, "*** Expected '}'"));
  1874. for (ivar_name in accessors)
  1875. {
  1876. var accessor = accessors[ivar_name],
  1877. property = accessor["property"] || ivar_name;
  1878. var getterName = accessor["getter"] || property,
  1879. getterCode = "(id)" + getterName + "\n{\nreturn " + ivar_name + ";\n}";
  1880. if (instance_methods.atoms.length !== 0)
  1881. instance_methods.atoms[instance_methods.atoms.length] = ",\n";
  1882. instance_methods.atoms[instance_methods.atoms.length] = this.method(new objj_lexer(getterCode));
  1883. if (accessor["readonly"])
  1884. continue;
  1885. var setterName = accessor["setter"];
  1886. if (!setterName)
  1887. {
  1888. var start = property.charAt(0) == '_' ? 1 : 0;
  1889. setterName = (start ? "_" : "") + "set" + property.substr(start, 1).toUpperCase() + property.substring(start + 1) + ":";
  1890. }
  1891. var setterCode = "(void)" + setterName + "(id)newValue\n{\n";
  1892. if (accessor["copy"])
  1893. setterCode += "if (" + ivar_name + " !== newValue)\n" + ivar_name + " = [newValue copy];\n}";
  1894. else
  1895. setterCode += ivar_name + " = newValue;\n}";
  1896. if (instance_methods.atoms.length !== 0)
  1897. instance_methods.atoms[instance_methods.atoms.length] = ",\n";
  1898. instance_methods.atoms[instance_methods.atoms.length] = this.method(new objj_lexer(setterCode));
  1899. }
  1900. }
  1901. else
  1902. tokens.previous();
  1903. buffer.atoms[buffer.atoms.length] = "objj_registerClassPair(the_class);\n";
  1904. buffer.atoms[buffer.atoms.length] = "objj_addClassForBundle(the_class, objj_getBundleWithPath(OBJJ_CURRENT_BUNDLE.path));\n";
  1905. }
  1906. while ((token = tokens.skip_whitespace()))
  1907. {
  1908. if (token == TOKEN_PLUS)
  1909. {
  1910. if (class_methods.atoms.length !== 0)
  1911. class_methods.atoms[class_methods.atoms.length] = ", ";
  1912. class_methods.atoms[class_methods.atoms.length] = this.method(tokens);
  1913. }
  1914. else if (token == TOKEN_MINUS)
  1915. {
  1916. if (instance_methods.atoms.length !== 0)
  1917. instance_methods.atoms[instance_methods.atoms.length] = ", ";
  1918. instance_methods.atoms[instance_methods.atoms.length] = this.method(tokens);
  1919. }
  1920. else if (token == TOKEN_PREPROCESSOR)
  1921. {
  1922. if ((token = tokens.next()) == TOKEN_END)
  1923. break;
  1924. else
  1925. objj_exception_throw(new objj_exception(OBJJParseException, "*** Expected \"@end\", found \"@" + token + "\"."));
  1926. }
  1927. }
  1928. if (instance_methods.atoms.length !== 0)
  1929. {
  1930. buffer.atoms[buffer.atoms.length] = "class_addMethods(the_class, [";
  1931. buffer.atoms[buffer.atoms.length] = instance_methods;
  1932. buffer.atoms[buffer.atoms.length] = "]);\n";
  1933. }
  1934. if (class_methods.atoms.length !== 0)
  1935. {
  1936. buffer.atoms[buffer.atoms.length] = "class_addMethods(meta_class, [";
  1937. buffer.atoms[buffer.atoms.length] = class_methods;
  1938. buffer.atoms[buffer.atoms.length] = "]);\n";
  1939. }
  1940. buffer.atoms[buffer.atoms.length] = '}';
  1941. }
  1942. objj_preprocessor.prototype._import = function(tokens)
  1943. {
  1944. this.fragment();
  1945. var path = "",
  1946. token = tokens.skip_whitespace(),
  1947. isLocal = (token != TOKEN_LESS_THAN);
  1948. if (token == TOKEN_LESS_THAN)
  1949. {
  1950. while((token = tokens.next()) && token != TOKEN_GREATER_THAN)
  1951. path += token;
  1952. if(!token)
  1953. objj_exception_throw(new objj_exception(OBJJParseException, "*** Unterminated import statement."));
  1954. }
  1955. else if (token.charAt(0) == TOKEN_DOUBLE_QUOTE)
  1956. path = token.substr(1, token.length - 2);
  1957. else
  1958. objj_exception_throw(new objj_exception(OBJJParseException, "*** Expecting '<' or '\"', found \"" + token + "\"."));
  1959. this._fragments.push(fragment_create_file(path, NULL, isLocal, this._file));
  1960. }
  1961. objj_preprocessor.prototype.method = function(tokens)
  1962. {
  1963. var buffer = new objj_stringBuffer(),
  1964. token,
  1965. selector = "",
  1966. parameters = [];
  1967. while((token = tokens.skip_whitespace()) && token != TOKEN_OPEN_BRACE)
  1968. {
  1969. if (token == TOKEN_COLON)
  1970. {
  1971. selector += token;
  1972. token = tokens.skip_whitespace();
  1973. if (token == TOKEN_OPEN_PARENTHESIS)
  1974. {
  1975. while((token = tokens.skip_whitespace()) && token != TOKEN_CLOSE_PARENTHESIS) ;
  1976. token = tokens.skip_whitespace();
  1977. }
  1978. parameters[parameters.length] = token;
  1979. }
  1980. else if (token == TOKEN_OPEN_PARENTHESIS)
  1981. while((token = tokens.skip_whitespace()) && token != TOKEN_CLOSE_PARENTHESIS) ;
  1982. else if (token == TOKEN_COMMA)
  1983. {
  1984. if ((token = tokens.skip_whitespace()) != TOKEN_PERIOD || tokens.next() != TOKEN_PERIOD || tokens.next() != TOKEN_PERIOD)
  1985. objj_exception_throw(new objj_exception(OBJJParseException, "*** Argument list expected after ','."));
  1986. }
  1987. else
  1988. selector += token;
  1989. }
  1990. var index = 0,
  1991. count = parameters.length;
  1992. buffer.atoms[buffer.atoms.length] = "new objj_method(sel_getUid(\"";
  1993. buffer.atoms[buffer.atoms.length] = selector;
  1994. buffer.atoms[buffer.atoms.length] = "\"), function";
  1995. if (this._flags & OBJJ_PREPROCESSOR_DEBUG_SYMBOLS)
  1996. buffer.atoms[buffer.atoms.length] = " $" + this._currentClass + "__" + selector.replace(/:/g, "_");
  1997. buffer.atoms[buffer.atoms.length] = "(self, _cmd";
  1998. for(; index < count; ++index)
  1999. {
  2000. buffer.atoms[buffer.atoms.length] = ", ";
  2001. buffer.atoms[buffer.atoms.length] = parameters[index];
  2002. }
  2003. buffer.atoms[buffer.atoms.length] = ")\n{ with(self)\n{";
  2004. buffer.atoms[buffer.atoms.length] = this.preprocess(tokens, NULL, TOKEN_CLOSE_BRACE, TOKEN_OPEN_BRACE);
  2005. buffer.atoms[buffer.atoms.length] = "}\n})";
  2006. return buffer;
  2007. }
  2008. objj_preprocessor.prototype.preprocess = function(tokens, aStringBuffer, terminator, instigator, tuple)
  2009. {
  2010. var buffer = aStringBuffer ? aStringBuffer : new objj_stringBuffer(),
  2011. count = 0,
  2012. token = "";
  2013. if (tuple)
  2014. {
  2015. tuple[0] = buffer;
  2016. var bracket = false,
  2017. closures = [0, 0, 0];
  2018. }
  2019. while ((token = tokens.next()) && ((token != terminator) || count))
  2020. {
  2021. if (tuple)
  2022. {
  2023. if (token === TOKEN_QUESTION_MARK)
  2024. ++closures[2];
  2025. else if (token === TOKEN_OPEN_BRACE)
  2026. ++closures[0];
  2027. else if (token === TOKEN_CLOSE_BRACE)
  2028. --closures[0];
  2029. else if (token === TOKEN_OPEN_PARENTHESIS)
  2030. ++closures[1];
  2031. else if (token === TOKEN_CLOSE_PARENTHESIS)
  2032. --closures[1];
  2033. else if ((token === TOKEN_COLON && closures[2]-- === 0 ||
  2034. (bracket = (token === TOKEN_CLOSE_BRACKET))) &&
  2035. closures[0] === 0 && closures[1] === 0)
  2036. {
  2037. tokens.push();
  2038. var label = bracket ? tokens.skip_whitespace(true) : tokens.previous(),
  2039. isEmptyLabel = TOKEN_WHITESPACE.test(label);
  2040. if (isEmptyLabel || TOKEN_IDENTIFIER.test(label) && TOKEN_WHITESPACE.test(tokens.previous()))
  2041. {
  2042. tokens.push();
  2043. var last = tokens.skip_whitespace(true),
  2044. operatorCheck = true,
  2045. isDoubleOperator = false;
  2046. if (last === '+' || last === '-'){
  2047. if (tokens.previous() !== last)
  2048. operatorCheck = false;
  2049. else
  2050. {
  2051. last = tokens.skip_whitespace(true);
  2052. isDoubleOperator = true;
  2053. }}
  2054. tokens.pop();
  2055. tokens.pop();
  2056. if (operatorCheck && (
  2057. (!isDoubleOperator && (last === TOKEN_CLOSE_BRACE)) ||
  2058. last === TOKEN_CLOSE_PARENTHESIS || last === TOKEN_CLOSE_BRACKET ||
  2059. last === TOKEN_PERIOD || TOKEN_NUMBER.test(last) ||
  2060. last.charAt(last.length - 1) === '\"' || last.charAt(last.length - 1) === '\'' ||
  2061. TOKEN_IDENTIFIER.test(last) && !/^(new|return|case|var)$/.test(last)))
  2062. {
  2063. if (isEmptyLabel)
  2064. tuple[1] = ':';
  2065. else
  2066. {
  2067. tuple[1] = label;
  2068. if (!bracket)
  2069. tuple[1] += ':';
  2070. var count = buffer.atoms.length;
  2071. while (buffer.atoms[count--] !== label) ;
  2072. buffer.atoms.length = count;
  2073. }
  2074. return !bracket;
  2075. }
  2076. if (bracket)
  2077. return NO;
  2078. }
  2079. tokens.pop();
  2080. if (bracket)
  2081. return NO;
  2082. }
  2083. closures[2] = MAX(closures[2], 0);
  2084. }
  2085. if (instigator)
  2086. {
  2087. if (token == instigator)
  2088. ++count;
  2089. else if (token == terminator)
  2090. --count;
  2091. }
  2092. if(token == TOKEN_IMPORT)
  2093. {
  2094. objj_fprintf(warning_stream, this._file.path + ": import keyword is deprecated, use @import instead.");
  2095. this._import(tokens);
  2096. }
  2097. else if (token === TOKEN_FUNCTION)
  2098. {
  2099. var accumulator = "";
  2100. while((token = tokens.next()) && token != TOKEN_OPEN_PARENTHESIS && !(/^\w/).test(token))
  2101. accumulator += token;
  2102. if (token === TOKEN_OPEN_PARENTHESIS)
  2103. {
  2104. buffer.atoms[buffer.atoms.length] = "function" + accumulator + '(';
  2105. if (tuple)
  2106. ++closures[1];
  2107. }
  2108. else
  2109. {
  2110. buffer.atoms[buffer.atoms.length] = token + "= function";
  2111. }
  2112. }
  2113. else if (token == TOKEN_PREPROCESSOR)
  2114. this.directive(tokens, buffer);
  2115. else if (token == TOKEN_OPEN_BRACKET)
  2116. this.brackets(tokens, buffer);
  2117. else
  2118. buffer.atoms[buffer.atoms.length] = token;
  2119. }
  2120. if (tuple)
  2121. objj_exception_throw(new objj_exception(OBJJParseException, "*** Expected ']' - Unterminated message send or array."));
  2122. if (!aStringBuffer)
  2123. return buffer;
  2124. }
  2125. objj_preprocessor.prototype.selector = function(tokens, aStringBuffer)
  2126. {
  2127. var buffer = aStringBuffer ? aStringBuffer : new objj_stringBuffer();
  2128. buffer.atoms[buffer.atoms.length] = "sel_getUid(\"";
  2129. if (tokens.skip_whitespace() != TOKEN_OPEN_PARENTHESIS)
  2130. objj_exception_throw(new objj_exception(OBJJParseException, "*** Expected '('"));
  2131. var selector = tokens.skip_whitespace();
  2132. if (selector == TOKEN_CLOSE_PARENTHESIS)
  2133. objj_exception_throw(new objj_exception(OBJJParseException, "*** Unexpected ')', can't have empty @selector()"));
  2134. aStringBuffer.atoms[aStringBuffer.atoms.length] = selector;
  2135. var token,
  2136. starting = true;
  2137. while ((token = tokens.next()) && token != TOKEN_CLOSE_PARENTHESIS)
  2138. {
  2139. if (starting && /^\d+$/.test(token) || !(/^(\w|$|\:)/.test(token)))
  2140. {
  2141. if (!(/\S/).test(token))
  2142. if (tokens.skip_whitespace() == TOKEN_CLOSE_PARENTHESIS)
  2143. break;
  2144. else
  2145. objj_exception_throw(new objj_exception(OBJJParseException, "*** Unexpected whitespace in @selector()."));
  2146. else
  2147. objj_exception_throw(new objj_exception(OBJJParseException, "*** Illegal character '" + token + "' in @selector()."));
  2148. }
  2149. buffer.atoms[buffer.atoms.length] = token;
  2150. starting = (token == TOKEN_COLON);
  2151. }
  2152. buffer.atoms[buffer.atoms.length] = "\")";
  2153. if (!aStringBuffer)
  2154. return buffer;
  2155. }
  2156. var objj_included_files = { };
  2157. var FRAGMENT_CODE = 1,
  2158. FRAGMENT_FILE = 1 << 2,
  2159. FRAGMENT_LOCAL = 1 << 3;
  2160. function objj_fragment()
  2161. {
  2162. this.info = NULL;
  2163. this.type = 0;
  2164. this.context = NULL;
  2165. this.bundle = NULL;
  2166. this.file = NULL;
  2167. }
  2168. function objj_context()
  2169. {
  2170. this.fragments = [];
  2171. this.scheduled = NO;
  2172. this.blocked = NO;
  2173. }
  2174. objj_fragment.prototype.toMarkedString = function()
  2175. {
  2176. return (this.type & FRAGMENT_FILE) ? ((this.type & FRAGMENT_LOCAL) ? MARKER_IMPORT_LOCAL : MARKER_IMPORT_STD) + ';' + this.info.length + ';' + this.info :
  2177. MARKER_CODE + ';' + this.info.length + ';' + this.info;
  2178. }
  2179. function fragment_create_code(aCode, aBundle, aFile)
  2180. {
  2181. var fragment = new objj_fragment();
  2182. fragment.type = (FRAGMENT_CODE);
  2183. fragment.info = (aCode);
  2184. fragment.bundle = aBundle;
  2185. fragment.file = aFile;
  2186. return fragment;
  2187. }
  2188. function fragment_create_file(aPath, aBundle, isLocal, aFile)
  2189. {
  2190. var fragment = new objj_fragment();
  2191. fragment.type = (FRAGMENT_FILE | (FRAGMENT_LOCAL * isLocal));
  2192. fragment.info = aPath;
  2193. fragment.bundle = aBundle;
  2194. fragment.file = aFile;
  2195. return fragment;
  2196. }
  2197. objj_context.prototype.evaluate = function()
  2198. {
  2199. this.scheduled = NO;
  2200. if (this.blocked)
  2201. return this.schedule();
  2202. var sleep = NO,
  2203. start = new Date(),
  2204. fragments = this.fragments;
  2205. while (!sleep && fragments.length)
  2206. {
  2207. var fragment = fragments.pop();
  2208. if ((fragment.type & FRAGMENT_FILE))
  2209. sleep = fragment_evaluate_file(fragment);
  2210. else
  2211. sleep = fragment_evaluate_code(fragment);
  2212. sleep = sleep || ((new Date() - start) > 3000);
  2213. }
  2214. if (sleep)
  2215. this.schedule();
  2216. else if (this.didCompleteCallback)
  2217. this.didCompleteCallback(this);
  2218. }
  2219. objj_context.prototype.schedule = function()
  2220. {
  2221. if (this.scheduled)
  2222. return;
  2223. this.scheduled = YES;
  2224. var context = this;
  2225. window.setNativeTimeout(function () { context.evaluate(); }, 0);
  2226. }
  2227. objj_context.prototype.pushFragment = function(aFragment)
  2228. {
  2229. aFragment.context = this;
  2230. this.fragments.push(aFragment);
  2231. }
  2232. function fragment_evaluate_code(aFragment)
  2233. {
  2234. var compiled;
  2235. OBJJ_CURRENT_BUNDLE = aFragment.bundle;
  2236. try
  2237. {
  2238. compiled = new Function(aFragment.info);
  2239. compiled.displayName = aFragment.file.path;
  2240. }
  2241. catch(anException)
  2242. {
  2243. objj_exception_report(anException, aFragment.file);
  2244. }
  2245. try
  2246. {
  2247. compiled();
  2248. }
  2249. catch(anException)
  2250. {
  2251. objj_exception_report(anException, aFragment.file);
  2252. }
  2253. return NO;
  2254. }
  2255. function fragment_evaluate_file(aFragment)
  2256. {
  2257. var context = aFragment.context,
  2258. requiresSleep = YES;
  2259. context.blocked = YES;
  2260. objj_request_file(aFragment.info, (aFragment.type & FRAGMENT_LOCAL), function(aFile)
  2261. {
  2262. requiresSleep = NO;
  2263. context.blocked = NO;
  2264. if (aFile == OBJJ_NO_FILE)
  2265. objj_alert("uh oh!");
  2266. if (objj_included_files[aFile.path])
  2267. return;
  2268. objj_included_files[aFile.path] = YES;
  2269. if (!aFile.fragments)
  2270. aFile.fragments = objj_preprocess(aFile.contents, aFile.bundle, aFile, OBJJ_PREPROCESSOR_DEBUG_SYMBOLS);
  2271. var fragments = aFile.fragments,
  2272. count = fragments.length,
  2273. directory = aFile.path.substr(0, aFile.path.lastIndexOf('/') + 1);
  2274. while (count--)
  2275. {
  2276. var fragment = fragments[count];
  2277. if ((fragment.type & FRAGMENT_FILE))
  2278. {
  2279. if ((fragment.type & FRAGMENT_LOCAL))
  2280. fragment.info = directory + fragment.info;
  2281. objj_request_file(fragment.info, (fragment.type & FRAGMENT_LOCAL), NULL);
  2282. }
  2283. context.pushFragment(fragment);
  2284. }
  2285. });
  2286. return requiresSleep;
  2287. }
  2288. function objj_import( pathOrPaths, isLocal, didCompleteCallback)
  2289. {
  2290. var context = new objj_context(),
  2291. paths = pathOrPaths;
  2292. if (typeof paths === "string")
  2293. paths = [paths];
  2294. var index = 0,
  2295. count = paths.length;
  2296. for (; index < count; ++index)
  2297. context.pushFragment(fragment_create_file(paths[index], new objj_bundle(""), isLocal, NULL));
  2298. context.didCompleteCallback = didCompleteCallback;
  2299. context.evaluate();
  2300. }
  2301. function objj_backtrace_format(aReceiver, aSelector)
  2302. {
  2303. return "[<" + (((aReceiver.info & (CLS_META))) ? aReceiver : aReceiver.isa).name + " " + (typeof sprintf == "function" ? sprintf("%#08x", aReceiver.__address) : aReceiver.__address.toString(16)) + "> " + aSelector + "]";
  2304. }
  2305. function objj_msgSend_Backtrace( aReceiver, aSelector)
  2306. {
  2307. if (aReceiver == nil)
  2308. return nil;
  2309. objj_debug_backtrace.push(objj_backtrace_format(aReceiver, aSelector));
  2310. try
  2311. {
  2312. var result = class_getMethodImplementation(aReceiver.isa, aSelector).apply(aReceiver, arguments);
  2313. }
  2314. catch (anException)
  2315. {
  2316. CPLog.error("Exception " + anException + " in " + objj_backtrace_format(aReceiver, aSelector));
  2317. objj_debug_print_backtrace();
  2318. }
  2319. objj_debug_backtrace.pop();
  2320. return result;
  2321. }
  2322. function objj_msgSendSuper_Backtrace( aSuper, aSelector)
  2323. {
  2324. objj_debug_backtrace.push(objj_backtrace_format(aSuper.receiver, aSelector));
  2325. var super_class = aSuper.super_class;
  2326. arguments[0] = aSuper.receiver;
  2327. try
  2328. {
  2329. var result = class_getMethodImplementation(super_class, aSelector).apply(aSuper.receiver, arguments);
  2330. }
  2331. catch (anException)
  2332. {
  2333. CPLog.error("Exception " + anException + " in " + objj_backtrace_format(aSuper.receiver, aSelector));
  2334. objj_debug_print_backtrace();
  2335. }
  2336. objj_debug_backtrace.pop();
  2337. return result;
  2338. }
  2339. function objj_msgSend_Profile( aReceiver, aSelector)
  2340. {
  2341. if (aReceiver == nil)
  2342. return nil;
  2343. var profileRecord = {
  2344. parent : objj_debug_profile,
  2345. receiver : (((aReceiver.info & (CLS_META))) ? aReceiver : aReceiver.isa).name,
  2346. selector : aSelector,
  2347. calls : []
  2348. }
  2349. objj_debug_profile.calls.push(profileRecord);
  2350. objj_debug_profile = profileRecord;
  2351. profileRecord.start = new Date();
  2352. var result = class_getMethodImplementation(aReceiver.isa, aSelector).apply(aReceiver, arguments);
  2353. profileRecord.end = new Date();
  2354. objj_debug_profile = profileRecord.parent;
  2355. return result;
  2356. }
  2357. function objj_msgSendSuper_Profile( aSuper, aSelector)
  2358. {
  2359. var profileRecord = {
  2360. parent : objj_debug_profile,
  2361. receiver : (((aReceiver.info & (CLS_META))) ? aReceiver : aReceiver.isa).name,
  2362. selector : aSelector,
  2363. calls : []
  2364. }
  2365. objj_debug_profile.calls.push(profileRecord);
  2366. objj_debug_profile = profileRecord;
  2367. profileRecord.start = new Date();
  2368. var super_class = aSuper.super_class;
  2369. arguments[0] = aSuper.receiver;
  2370. var result = class_getMethodImplementation(super_class, aSelector).apply(aSuper.receiver, arguments);
  2371. profileRecord.end = new Date();
  2372. objj_debug_profile = profileRecord.parent;
  2373. return result;
  2374. }
  2375. var objj_msgSend_Standard = objj_msgSend,
  2376. objj_msgSendSuper_Standard = objj_msgSendSuper;
  2377. var objj_debug_backtrace;
  2378. function objj_backtrace_set_enabled(enabled)
  2379. {
  2380. if (enabled)
  2381. {
  2382. objj_debug_backtrace = [];
  2383. objj_msgSend = objj_msgSend_Backtrace;
  2384. objj_msgSendSuper = objj_msgSendSuper_Backtrace;
  2385. }
  2386. else
  2387. {
  2388. objj_msgSend = objj_msgSend_Standard;
  2389. objj_msgSendSuper = objj_msgSendSuper_Standard;
  2390. }
  2391. }
  2392. function objj_debug_print_backtrace()
  2393. {
  2394. print(objj_debug_backtrace_string());
  2395. }
  2396. function objj_debug_backtrace_string()
  2397. {
  2398. return objj_debug_backtrace ? objj_debug_backtrace.join("\n") : "";
  2399. }
  2400. var objj_debug_profile = null,
  2401. objj_currently_profiling = false,
  2402. objj_profile_cleanup;
  2403. function objj_profile(title)
  2404. {
  2405. if (objj_currently_profiling)
  2406. return;
  2407. var objj_msgSend_profile_saved = objj_msgSend,
  2408. objj_msgSendSuper_profile_saved = objj_msgSendSuper;
  2409. objj_msgSend = objj_msgSend_Profile;
  2410. objj_msgSendSuper = objj_msgSendSuper_Profile;
  2411. var root = { calls: [] };
  2412. objj_debug_profile = root;
  2413. var context = {
  2414. start : new Date(),
  2415. title : title,
  2416. profile : root
  2417. };
  2418. objj_profile_cleanup = function() {
  2419. objj_msgSend = objj_msgSend_profile_saved;
  2420. objj_msgSendSuper = objj_msgSendSuper_profile_saved;
  2421. context.end = new Date();
  2422. return context;
  2423. }
  2424. objj_currently_profiling = true;
  2425. }
  2426. function objj_profileEnd()
  2427. {
  2428. if (!objj_currently_profiling)
  2429. return;
  2430. objj_debug_profile = null;
  2431. objj_currently_profiling = false;
  2432. return objj_profile_cleanup();
  2433. }
  2434. if (window.OBJJ_MAIN_FILE)
  2435. objj_import(OBJJ_MAIN_FILE, YES, function() { main(); });