[ Index ] |
|
Code source de PRADO 3.0.6 |
1 /* ***** BEGIN LICENSE BLOCK ***** 2 * vim: set ts=4 sw=4 et tw=80: 3 * 4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 * 6 * The contents of this file are subject to the Mozilla Public License Version 7 * 1.1 (the "License"); you may not use this file except in compliance with 8 * the License. You may obtain a copy of the License at 9 * http://www.mozilla.org/MPL/ 10 * 11 * Software distributed under the License is distributed on an "AS IS" basis, 12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 * for the specific language governing rights and limitations under the 14 * License. 15 * 16 * The Original Code is the Narcissus JavaScript engine. 17 * 18 * The Initial Developer of the Original Code is 19 * Brendan Eich <brendan@mozilla.org>. 20 * Portions created by the Initial Developer are Copyright (C) 2004 21 * the Initial Developer. All Rights Reserved. 22 * 23 * Contributor(s): 24 * 25 * Alternatively, the contents of this file may be used under the terms of 26 * either the GNU General Public License Version 2 or later (the "GPL"), or 27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 28 * in which case the provisions of the GPL or the LGPL are applicable instead 29 * of those above. If you wish to allow use of your version of this file only 30 * under the terms of either the GPL or the LGPL, and not to allow others to 31 * use your version of this file under the terms of the MPL, indicate your 32 * decision by deleting the provisions above and replace them with the notice 33 * and other provisions required by the GPL or the LGPL. If you do not delete 34 * the provisions above, a recipient may use your version of this file under 35 * the terms of any one of the MPL, the GPL or the LGPL. 36 * 37 * ***** END LICENSE BLOCK ***** */ 38 39 /* 40 * Narcissus - JS implemented in JS. 41 * 42 * Execution of parse trees. 43 * 44 * Standard classes except for eval, Function, Array, and String are borrowed 45 * from the host JS environment. Function is metacircular. Array and String 46 * are reflected via wrapping the corresponding native constructor and adding 47 * an extra level of prototype-based delegation. 48 */ 49 50 // jrh 51 //module('JS.Exec'); 52 // end jrh 53 54 GLOBAL_CODE = 0; EVAL_CODE = 1; FUNCTION_CODE = 2; 55 56 function ExecutionContext(type) { 57 this.type = type; 58 } 59 60 // jrh 61 var agenda = new Array(); 62 var skip_setup = 0; 63 // end jrh 64 65 var global = { 66 // Value properties. 67 NaN: NaN, Infinity: Infinity, undefined: undefined, 68 alert : function(msg) { alert(msg) }, 69 confirm : function(msg) { return confirm(msg) }, 70 document : document, 71 window : window, 72 // jrh 73 //debug: window.open('','debugwindow','width=600,height=400,scrollbars=yes,resizable=yes'), 74 // end jrh 75 navigator : navigator, 76 XMLHttpRequest : function() { return new XMLHttpRequest() }, 77 // Function properties. 78 eval: function(s) { 79 if (typeof s != "string") { 80 return s; 81 } 82 83 var x = ExecutionContext.current; 84 var x2 = new ExecutionContext(EVAL_CODE); 85 x2.thisObject = x.thisObject; 86 x2.caller = x.caller; 87 x2.callee = x.callee; 88 x2.scope = x.scope; 89 ExecutionContext.current = x2; 90 try { 91 execute(parse(s), x2); 92 } catch (e) { 93 x.result = x2.result; 94 throw e; 95 } finally { 96 ExecutionContext.current = x; 97 } 98 return x2.result; 99 }, 100 parseInt: parseInt, parseFloat: parseFloat, 101 isNaN: isNaN, isFinite: isFinite, 102 decodeURI: decodeURI, encodeURI: encodeURI, 103 decodeURIComponent: decodeURIComponent, 104 encodeURIComponent: encodeURIComponent, 105 106 // Class constructors. Where ECMA-262 requires C.length == 1, we declare 107 // a dummy formal parameter. 108 Object: Object, 109 Function: function(dummy) { 110 var p = "", b = "", n = arguments.length; 111 if (n) { 112 var m = n - 1; 113 if (m) { 114 p += arguments[0]; 115 for (var k = 1; k < m; k++) 116 p += "," + arguments[k]; 117 } 118 b += arguments[m]; 119 } 120 121 // XXX We want to pass a good file and line to the tokenizer. 122 // Note the anonymous name to maintain parity with Spidermonkey. 123 var t = new Tokenizer("anonymous(" + p + ") {" + b + "}"); 124 125 // NB: Use the STATEMENT_FORM constant since we don't want to push this 126 // function onto the null compilation context. 127 var f = FunctionDefinition(t, null, false, STATEMENT_FORM); 128 var s = {object: global, parent: null}; 129 return new FunctionObject(f, s); 130 }, 131 Array: function(dummy) { 132 // Array when called as a function acts as a constructor. 133 return GLOBAL.Array.apply(this, arguments); 134 }, 135 String: function(s) { 136 // Called as function or constructor: convert argument to string type. 137 s = arguments.length ? "" + s : ""; 138 if (this instanceof String) { 139 // Called as constructor: save the argument as the string value 140 // of this String object and return this object. 141 this.value = s; 142 return this; 143 } 144 return s; 145 }, 146 Boolean: Boolean, Number: Number, Date: Date, RegExp: RegExp, 147 Error: Error, EvalError: EvalError, RangeError: RangeError, 148 ReferenceError: ReferenceError, SyntaxError: SyntaxError, 149 TypeError: TypeError, URIError: URIError, 150 151 // Other properties. 152 Math: Math, 153 154 // Extensions to ECMA. 155 //snarf: snarf, 156 evaluate: evaluate, 157 load: function(s) { 158 if (typeof s != "string") 159 return s; 160 var req = new XMLHttpRequest(); 161 req.open('GET', s, false); 162 req.send(null); 163 164 evaluate(req.responseText, s, 1) 165 }, 166 print: print, version: null 167 }; 168 169 // jrh 170 //global.debug.document.body.innerHTML = '' 171 // end jrh 172 173 // Helper to avoid Object.prototype.hasOwnProperty polluting scope objects. 174 function hasDirectProperty(o, p) { 175 return Object.prototype.hasOwnProperty.call(o, p); 176 } 177 178 // Reflect a host class into the target global environment by delegation. 179 function reflectClass(name, proto) { 180 var gctor = global[name]; 181 gctor.prototype = proto; 182 proto.constructor = gctor; 183 return proto; 184 } 185 186 // Reflect Array -- note that all Array methods are generic. 187 reflectClass('Array', new Array); 188 189 // Reflect String, overriding non-generic methods. 190 var gSp = reflectClass('String', new String); 191 gSp.toSource = function () { return this.value.toSource(); }; 192 gSp.toString = function () { return this.value; }; 193 gSp.valueOf = function () { return this.value; }; 194 global.String.fromCharCode = String.fromCharCode; 195 196 var XCp = ExecutionContext.prototype; 197 ExecutionContext.current = XCp.caller = XCp.callee = null; 198 XCp.scope = {object: global, parent: null}; 199 XCp.thisObject = global; 200 XCp.result = undefined; 201 XCp.target = null; 202 XCp.ecmaStrictMode = false; 203 204 function Reference(base, propertyName, node) { 205 this.base = base; 206 this.propertyName = propertyName; 207 this.node = node; 208 } 209 210 Reference.prototype.toString = function () { return this.node.getSource(); } 211 212 function getValue(v) { 213 if (v instanceof Reference) { 214 if (!v.base) { 215 throw new ReferenceError(v.propertyName + " is not defined", 216 v.node.filename(), v.node.lineno); 217 } 218 return v.base[v.propertyName]; 219 } 220 return v; 221 } 222 223 function putValue(v, w, vn) { 224 if (v instanceof Reference) 225 return (v.base || global)[v.propertyName] = w; 226 throw new ReferenceError("Invalid assignment left-hand side", 227 vn.filename(), vn.lineno); 228 } 229 230 function isPrimitive(v) { 231 var t = typeof v; 232 return (t == "object") ? v === null : t != "function"; 233 } 234 235 function isObject(v) { 236 var t = typeof v; 237 return (t == "object") ? v !== null : t == "function"; 238 } 239 240 // If r instanceof Reference, v == getValue(r); else v === r. If passed, rn 241 // is the node whose execute result was r. 242 function toObject(v, r, rn) { 243 switch (typeof v) { 244 case "boolean": 245 return new global.Boolean(v); 246 case "number": 247 return new global.Number(v); 248 case "string": 249 return new global.String(v); 250 case "function": 251 return v; 252 case "object": 253 if (v !== null) 254 return v; 255 } 256 var message = r + " (type " + (typeof v) + ") has no properties"; 257 throw rn ? new TypeError(message, rn.filename(), rn.lineno) 258 : new TypeError(message); 259 } 260 261 function execute(n, x) { 262 if (!this.new_block) 263 new_block = new Array(); 264 //alert (n) 265 var a, f, i, j, r, s, t, u, v; 266 switch (n.type) { 267 case FUNCTION: 268 if (n.functionForm != DECLARED_FORM) { 269 if (!n.name || n.functionForm == STATEMENT_FORM) { 270 v = new FunctionObject(n, x.scope); 271 if (n.functionForm == STATEMENT_FORM) 272 x.scope.object[n.name] = v; 273 } else { 274 t = new Object; 275 x.scope = {object: t, parent: x.scope}; 276 try { 277 v = new FunctionObject(n, x.scope); 278 t[n.name] = v; 279 } finally { 280 x.scope = x.scope.parent; 281 } 282 } 283 } 284 break; 285 286 case SCRIPT: 287 t = x.scope.object; 288 a = n.funDecls; 289 for (i = 0, j = a.length; i < j; i++) { 290 s = a[i].name; 291 f = new FunctionObject(a[i], x.scope); 292 t[s] = f; 293 } 294 a = n.varDecls; 295 for (i = 0, j = a.length; i < j; i++) { 296 u = a[i]; 297 s = u.name; 298 if (u.readOnly && hasDirectProperty(t, s)) { 299 throw new TypeError("Redeclaration of const " + s, 300 u.filename(), u.lineno); 301 } 302 if (u.readOnly || !hasDirectProperty(t, s)) { 303 t[s] = null; 304 } 305 } 306 // FALL THROUGH 307 308 case BLOCK: 309 for (i = 0, j = n.$length; i < j; i++) { 310 //jrh 311 //execute(n[i], x); 312 //new_block.unshift([n[i], x]); 313 new_block.push([n[i], x]); 314 } 315 new_block.reverse(); 316 agenda = agenda.concat(new_block); 317 //agenda = new_block.concat(agenda) 318 // end jrh 319 break; 320 321 case IF: 322 if (getValue(execute(n.condition, x))) 323 execute(n.thenPart, x); 324 else if (n.elsePart) 325 execute(n.elsePart, x); 326 break; 327 328 case SWITCH: 329 s = getValue(execute(n.discriminant, x)); 330 a = n.cases; 331 var matchDefault = false; 332 switch_loop: 333 for (i = 0, j = a.length; ; i++) { 334 if (i == j) { 335 if (n.defaultIndex >= 0) { 336 i = n.defaultIndex - 1; // no case matched, do default 337 matchDefault = true; 338 continue; 339 } 340 break; // no default, exit switch_loop 341 } 342 t = a[i]; // next case (might be default!) 343 if (t.type == CASE) { 344 u = getValue(execute(t.caseLabel, x)); 345 } else { 346 if (!matchDefault) // not defaulting, skip for now 347 continue; 348 u = s; // force match to do default 349 } 350 if (u === s) { 351 for (;;) { // this loop exits switch_loop 352 if (t.statements.length) { 353 try { 354 execute(t.statements, x); 355 } catch (e) { 356 if (!(e == BREAK && x.target == n)) { throw e } 357 break switch_loop; 358 } 359 } 360 if (++i == j) 361 break switch_loop; 362 t = a[i]; 363 } 364 // NOT REACHED 365 } 366 } 367 break; 368 369 case FOR: 370 // jrh 371 // added "skip_setup" so initialization doesn't get called 372 // on every call.. 373 if (!skip_setup) 374 n.setup && getValue(execute(n.setup, x)); 375 // FALL THROUGH 376 case WHILE: 377 // jrh 378 //while (!n.condition || getValue(execute(n.condition, x))) { 379 if (!n.condition || getValue(execute(n.condition, x))) { 380 try { 381 // jrh 382 //execute(n.body, x); 383 new_block.push([n.body, x]); 384 agenda.push([n.body, x]) 385 //agenda.unshift([n.body, x]) 386 // end jrh 387 } catch (e) { 388 if (e == BREAK && x.target == n) { 389 break; 390 } else if (e == CONTINUE && x.target == n) { 391 // jrh 392 // 'continue' is invalid inside an 'if' clause 393 // I don't know what commenting this out will break! 394 //continue; 395 // end jrh 396 397 } else { 398 throw e; 399 } 400 } 401 n.update && getValue(execute(n.update, x)); 402 // jrh 403 new_block.unshift([n, x]) 404 agenda.splice(agenda.length-1,0,[n, x]) 405 //agenda.splice(1,0,[n, x]) 406 skip_setup = 1 407 // end jrh 408 } else { 409 skip_setup = 0 410 } 411 412 break; 413 414 case FOR_IN: 415 u = n.varDecl; 416 if (u) 417 execute(u, x); 418 r = n.iterator; 419 s = execute(n.object, x); 420 v = getValue(s); 421 422 // ECMA deviation to track extant browser JS implementation behavior. 423 t = (v == null && !x.ecmaStrictMode) ? v : toObject(v, s, n.object); 424 a = []; 425 for (i in t) 426 a.push(i); 427 for (i = 0, j = a.length; i < j; i++) { 428 putValue(execute(r, x), a[i], r); 429 try { 430 execute(n.body, x); 431 } catch (e) { 432 if (e == BREAK && x.target == n) { 433 break; 434 } else if (e == CONTINUE && x.target == n) { 435 continue; 436 } else { 437 throw e; 438 } 439 } 440 } 441 break; 442 443 case DO: 444 do { 445 try { 446 execute(n.body, x); 447 } catch (e) { 448 if (e == BREAK && x.target == n) { 449 break; 450 } else if (e == CONTINUE && x.target == n) { 451 continue; 452 } else { 453 throw e; 454 } 455 } 456 } while (getValue(execute(n.condition, x))); 457 break; 458 459 case BREAK: 460 case CONTINUE: 461 x.target = n.target; 462 throw n.type; 463 464 case TRY: 465 try { 466 execute(n.tryBlock, x); 467 } catch (e) { 468 if (!(e == THROW && (j = n.catchClauses.length))) { 469 throw e; 470 } 471 e = x.result; 472 x.result = undefined; 473 for (i = 0; ; i++) { 474 if (i == j) { 475 x.result = e; 476 throw THROW; 477 } 478 t = n.catchClauses[i]; 479 x.scope = {object: {}, parent: x.scope}; 480 x.scope.object[t.varName] = e; 481 try { 482 if (t.guard && !getValue(execute(t.guard, x))) 483 continue; 484 execute(t.block, x); 485 break; 486 } finally { 487 x.scope = x.scope.parent; 488 } 489 } 490 } finally { 491 if (n.finallyBlock) 492 execute(n.finallyBlock, x); 493 } 494 break; 495 496 case THROW: 497 x.result = getValue(execute(n.exception, x)); 498 throw THROW; 499 500 case RETURN: 501 x.result = getValue(execute(n.value, x)); 502 throw RETURN; 503 504 case WITH: 505 r = execute(n.object, x); 506 t = toObject(getValue(r), r, n.object); 507 x.scope = {object: t, parent: x.scope}; 508 try { 509 execute(n.body, x); 510 } finally { 511 x.scope = x.scope.parent; 512 } 513 break; 514 515 case VAR: 516 case CONST: 517 for (i = 0, j = n.$length; i < j; i++) { 518 u = n[i].initializer; 519 if (!u) 520 continue; 521 t = n[i].name; 522 for (s = x.scope; s; s = s.parent) { 523 if (hasDirectProperty(s.object, t)) 524 break; 525 } 526 u = getValue(execute(u, x)); 527 if (n.type == CONST) 528 s.object[t] = u; 529 else 530 s.object[t] = u; 531 } 532 break; 533 534 case DEBUGGER: 535 throw "NYI: " + tokens[n.type]; 536 537 case REQUIRE: 538 var req = new XMLHttpRequest(); 539 req.open('GET', n.filename, 'false'); 540 541 case SEMICOLON: 542 if (n.expression) 543 // print debugging statements 544 545 var the_start = n.start 546 var the_end = n.end 547 var the_statement = parse_result.tokenizer.source.slice(the_start,the_end) 548 //global.debug.document.body.innerHTML += ('<pre>>>> <b>' + the_statement + '</b></pre>') 549 LOG.info('>>>' + the_statement) 550 x.result = getValue(execute(n.expression, x)); 551 //if (x.result) 552 //global.debug.document.body.innerHTML += ( '<pre>>>> ' + x.result + '</pre>') 553 554 break; 555 556 case LABEL: 557 try { 558 execute(n.statement, x); 559 } catch (e) { 560 if (!(e == BREAK && x.target == n)) { throw e } 561 } 562 break; 563 564 case COMMA: 565 for (i = 0, j = n.$length; i < j; i++) 566 v = getValue(execute(n[i], x)); 567 break; 568 569 case ASSIGN: 570 r = execute(n[0], x); 571 t = n[0].assignOp; 572 if (t) 573 u = getValue(r); 574 v = getValue(execute(n[1], x)); 575 if (t) { 576 switch (t) { 577 case BITWISE_OR: v = u | v; break; 578 case BITWISE_XOR: v = u ^ v; break; 579 case BITWISE_AND: v = u & v; break; 580 case LSH: v = u << v; break; 581 case RSH: v = u >> v; break; 582 case URSH: v = u >>> v; break; 583 case PLUS: v = u + v; break; 584 case MINUS: v = u - v; break; 585 case MUL: v = u * v; break; 586 case DIV: v = u / v; break; 587 case MOD: v = u % v; break; 588 } 589 } 590 putValue(r, v, n[0]); 591 break; 592 593 case CONDITIONAL: 594 v = getValue(execute(n[0], x)) ? getValue(execute(n[1], x)) 595 : getValue(execute(n[2], x)); 596 break; 597 598 case OR: 599 v = getValue(execute(n[0], x)) || getValue(execute(n[1], x)); 600 break; 601 602 case AND: 603 v = getValue(execute(n[0], x)) && getValue(execute(n[1], x)); 604 break; 605 606 case BITWISE_OR: 607 v = getValue(execute(n[0], x)) | getValue(execute(n[1], x)); 608 break; 609 610 case BITWISE_XOR: 611 v = getValue(execute(n[0], x)) ^ getValue(execute(n[1], x)); 612 break; 613 614 case BITWISE_AND: 615 v = getValue(execute(n[0], x)) & getValue(execute(n[1], x)); 616 break; 617 618 case EQ: 619 v = getValue(execute(n[0], x)) == getValue(execute(n[1], x)); 620 break; 621 622 case NE: 623 v = getValue(execute(n[0], x)) != getValue(execute(n[1], x)); 624 break; 625 626 case STRICT_EQ: 627 v = getValue(execute(n[0], x)) === getValue(execute(n[1], x)); 628 break; 629 630 case STRICT_NE: 631 v = getValue(execute(n[0], x)) !== getValue(execute(n[1], x)); 632 break; 633 634 case LT: 635 v = getValue(execute(n[0], x)) < getValue(execute(n[1], x)); 636 break; 637 638 case LE: 639 v = getValue(execute(n[0], x)) <= getValue(execute(n[1], x)); 640 break; 641 642 case GE: 643 v = getValue(execute(n[0], x)) >= getValue(execute(n[1], x)); 644 break; 645 646 case GT: 647 v = getValue(execute(n[0], x)) > getValue(execute(n[1], x)); 648 break; 649 650 case IN: 651 v = getValue(execute(n[0], x)) in getValue(execute(n[1], x)); 652 break; 653 654 case INSTANCEOF: 655 t = getValue(execute(n[0], x)); 656 u = getValue(execute(n[1], x)); 657 if (isObject(u) && typeof u.__hasInstance__ == "function") 658 v = u.__hasInstance__(t); 659 else 660 v = t instanceof u; 661 break; 662 663 case LSH: 664 v = getValue(execute(n[0], x)) << getValue(execute(n[1], x)); 665 break; 666 667 case RSH: 668 v = getValue(execute(n[0], x)) >> getValue(execute(n[1], x)); 669 break; 670 671 case URSH: 672 v = getValue(execute(n[0], x)) >>> getValue(execute(n[1], x)); 673 break; 674 675 case PLUS: 676 v = getValue(execute(n[0], x)) + getValue(execute(n[1], x)); 677 break; 678 679 case MINUS: 680 v = getValue(execute(n[0], x)) - getValue(execute(n[1], x)); 681 break; 682 683 case MUL: 684 v = getValue(execute(n[0], x)) * getValue(execute(n[1], x)); 685 break; 686 687 case DIV: 688 v = getValue(execute(n[0], x)) / getValue(execute(n[1], x)); 689 break; 690 691 case MOD: 692 v = getValue(execute(n[0], x)) % getValue(execute(n[1], x)); 693 break; 694 695 case DELETE: 696 t = execute(n[0], x); 697 v = !(t instanceof Reference) || delete t.base[t.propertyName]; 698 break; 699 700 case VOID: 701 getValue(execute(n[0], x)); 702 break; 703 704 case TYPEOF: 705 t = execute(n[0], x); 706 if (t instanceof Reference) 707 t = t.base ? t.base[t.propertyName] : undefined; 708 v = typeof t; 709 break; 710 711 case NOT: 712 v = !getValue(execute(n[0], x)); 713 break; 714 715 case BITWISE_NOT: 716 v = ~getValue(execute(n[0], x)); 717 break; 718 719 case UNARY_PLUS: 720 v = +getValue(execute(n[0], x)); 721 break; 722 723 case UNARY_MINUS: 724 v = -getValue(execute(n[0], x)); 725 break; 726 727 case INCREMENT: 728 case DECREMENT: 729 t = execute(n[0], x); 730 u = Number(getValue(t)); 731 if (n.postfix) 732 v = u; 733 putValue(t, (n.type == INCREMENT) ? ++u : --u, n[0]); 734 if (!n.postfix) 735 v = u; 736 break; 737 738 case DOT: 739 r = execute(n[0], x); 740 t = getValue(r); 741 u = n[1].value; 742 v = new Reference(toObject(t, r, n[0]), u, n); 743 break; 744 745 case INDEX: 746 r = execute(n[0], x); 747 t = getValue(r); 748 u = getValue(execute(n[1], x)); 749 v = new Reference(toObject(t, r, n[0]), String(u), n); 750 break; 751 752 case LIST: 753 // Curse ECMA for specifying that arguments is not an Array object! 754 v = {}; 755 for (i = 0, j = n.$length; i < j; i++) { 756 u = getValue(execute(n[i], x)); 757 v[i] = u; 758 } 759 v.length = i; 760 break; 761 762 case CALL: 763 r = execute(n[0], x); 764 a = execute(n[1], x); 765 f = getValue(r); 766 if (isPrimitive(f) || typeof f.__call__ != "function") { 767 throw new TypeError(r + " is not callable", 768 n[0].filename(), n[0].lineno); 769 } 770 t = (r instanceof Reference) ? r.base : null; 771 if (t instanceof Activation) 772 t = null; 773 v = f.__call__(t, a, x); 774 break; 775 776 case NEW: 777 case NEW_WITH_ARGS: 778 r = execute(n[0], x); 779 f = getValue(r); 780 if (n.type == NEW) { 781 a = {}; 782 a.length = 0; 783 } else { 784 a = execute(n[1], x); 785 } 786 if (isPrimitive(f) || typeof f.__construct__ != "function") { 787 throw new TypeError(r + " is not a constructor", 788 n[0].filename(), n[0].lineno); 789 } 790 v = f.__construct__(a, x); 791 break; 792 793 case ARRAY_INIT: 794 v = []; 795 for (i = 0, j = n.$length; i < j; i++) { 796 if (n[i]) 797 v[i] = getValue(execute(n[i], x)); 798 } 799 v.length = j; 800 break; 801 802 case OBJECT_INIT: 803 v = {}; 804 for (i = 0, j = n.$length; i < j; i++) { 805 t = n[i]; 806 if (t.type == PROPERTY_INIT) { 807 v[t[0].value] = getValue(execute(t[1], x)); 808 } else { 809 f = new FunctionObject(t, x.scope); 810 /* 811 u = (t.type == GETTER) ? '__defineGetter__' 812 : '__defineSetter__'; 813 v[u](t.name, thunk(f, x)); 814 */ 815 } 816 } 817 break; 818 819 case NULL: 820 v = null; 821 break; 822 823 case THIS: 824 v = x.thisObject; 825 break; 826 827 case TRUE: 828 v = true; 829 break; 830 831 case FALSE: 832 v = false; 833 break; 834 835 case IDENTIFIER: 836 for (s = x.scope; s; s = s.parent) { 837 if (n.value in s.object) 838 break; 839 } 840 v = new Reference(s && s.object, n.value, n); 841 break; 842 843 case NUMBER: 844 case STRING: 845 case REGEXP: 846 v = n.value; 847 break; 848 849 case GROUP: 850 v = execute(n[0], x); 851 break; 852 853 default: 854 throw "PANIC: unknown operation " + n.type + ": " + uneval(n); 855 } 856 return v; 857 } 858 859 function Activation(f, a) { 860 for (var i = 0, j = f.params.length; i < j; i++) 861 this[f.params[i]] = a[i]; 862 this.arguments = a; 863 } 864 865 // Null Activation.prototype's proto slot so that Object.prototype.* does not 866 // pollute the scope of heavyweight functions. Also delete its 'constructor' 867 // property so that it doesn't pollute function scopes. 868 869 Activation.prototype.__proto__ = null; 870 delete Activation.prototype.constructor; 871 872 function FunctionObject(node, scope) { 873 this.node = node; 874 this.scope = scope; 875 this.length = node.params.length; 876 var proto = {}; 877 this.prototype = proto; 878 proto.constructor = this; 879 } 880 881 var FOp = FunctionObject.prototype = { 882 // Internal methods. 883 __call__: function (t, a, x) { 884 var x2 = new ExecutionContext(FUNCTION_CODE); 885 x2.thisObject = t || global; 886 x2.caller = x; 887 x2.callee = this; 888 a.callee = this; 889 var f = this.node; 890 x2.scope = {object: new Activation(f, a), parent: this.scope}; 891 892 ExecutionContext.current = x2; 893 try { 894 execute(f.body, x2); 895 } catch (e) { 896 if (!(e == RETURN)) { throw e } else if (e == RETURN) { 897 return x2.result; 898 } 899 if (e != THROW) { throw e } 900 x.result = x2.result; 901 throw THROW; 902 } finally { 903 ExecutionContext.current = x; 904 } 905 return undefined; 906 }, 907 908 __construct__: function (a, x) { 909 var o = new Object; 910 var p = this.prototype; 911 if (isObject(p)) 912 o.__proto__ = p; 913 // else o.__proto__ defaulted to Object.prototype 914 915 var v = this.__call__(o, a, x); 916 if (isObject(v)) 917 return v; 918 return o; 919 }, 920 921 __hasInstance__: function (v) { 922 if (isPrimitive(v)) 923 return false; 924 var p = this.prototype; 925 if (isPrimitive(p)) { 926 throw new TypeError("'prototype' property is not an object", 927 this.node.filename(), this.node.lineno); 928 } 929 var o; 930 while ((o = v.__proto__)) { 931 if (o == p) 932 return true; 933 v = o; 934 } 935 return false; 936 }, 937 938 // Standard methods. 939 toString: function () { 940 return this.node.getSource(); 941 }, 942 943 apply: function (t, a) { 944 // Curse ECMA again! 945 if (typeof this.__call__ != "function") { 946 throw new TypeError("Function.prototype.apply called on" + 947 " uncallable object"); 948 } 949 950 if (t === undefined || t === null) 951 t = global; 952 else if (typeof t != "object") 953 t = toObject(t, t); 954 955 if (a === undefined || a === null) { 956 a = {}; 957 a.length = 0; 958 } else if (a instanceof Array) { 959 var v = {}; 960 for (var i = 0, j = a.length; i < j; i++) 961 v[i] = a[i]; 962 v.length = i; 963 a = v; 964 } else if (!(a instanceof Object)) { 965 // XXX check for a non-arguments object 966 throw new TypeError("Second argument to Function.prototype.apply" + 967 " must be an array or arguments object", 968 this.node.filename(), this.node.lineno); 969 } 970 971 return this.__call__(t, a, ExecutionContext.current); 972 }, 973 974 call: function (t) { 975 // Curse ECMA a third time! 976 var a = Array.prototype.splice.call(arguments, 1); 977 return this.apply(t, a); 978 } 979 }; 980 981 // Connect Function.prototype and Function.prototype.constructor in global. 982 reflectClass('Function', FOp); 983 984 // Help native and host-scripted functions be like FunctionObjects. 985 var Fp = Function.prototype; 986 var REp = RegExp.prototype; 987 988 if (!('__call__' in Fp)) { 989 Fp.__call__ = function (t, a, x) { 990 // Curse ECMA yet again! 991 a = Array.prototype.splice.call(a, 0, a.length); 992 return this.apply(t, a); 993 }; 994 995 REp.__call__ = function (t, a, x) { 996 a = Array.prototype.splice.call(a, 0, a.length); 997 return this.exec.apply(this, a); 998 }; 999 1000 Fp.__construct__ = function (a, x) { 1001 switch (a.length) { 1002 case 0: 1003 return new this(); 1004 case 1: 1005 return new this(a[0]); 1006 case 2: 1007 return new this(a[0], a[1]); 1008 case 3: 1009 return new this(a[0], a[1], a[2]); 1010 case 4: 1011 return new this(a[0], a[1], a[2], a[3]); 1012 case 5: 1013 return new this(a[0], a[1], a[2], a[3], a[4]); 1014 case 6: 1015 return new this(a[0], a[1], a[2], a[3], a[4], a[5]); 1016 case 7: 1017 return new this(a[0], a[1], a[2], a[3], a[4], a[5], a[6]); 1018 } 1019 throw "PANIC: too many arguments to constructor"; 1020 } 1021 1022 // Since we use native functions such as Date along with host ones such 1023 // as global.eval, we want both to be considered instances of the native 1024 // Function constructor. 1025 Fp.__hasInstance__ = function (v) { 1026 return v instanceof Function || v instanceof global.Function; 1027 }; 1028 } 1029 1030 function thunk(f, x) { 1031 return function () { return f.__call__(this, arguments, x); }; 1032 } 1033 1034 function evaluate(s, f, l) { 1035 if (typeof s != "string") 1036 return s; 1037 1038 var x = ExecutionContext.current; 1039 var x2 = new ExecutionContext(GLOBAL_CODE); 1040 ExecutionContext.current = x2; 1041 try { 1042 execute(parse(s, f, l), x2); 1043 } catch (e) { 1044 if (e != THROW) { throw e } 1045 if (x) { 1046 x.result = x2.result; 1047 throw(THROW); 1048 } 1049 throw x2.result; 1050 } finally { 1051 ExecutionContext.current = x; 1052 } 1053 return x2.result; 1054 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 21:07:04 2007 | par Balluche grâce à PHPXref 0.7 |