首页 > 代码库 > 用Windjs画圆

用Windjs画圆

  无意中接触了jscex,也就是Wind.js的前身,深深被它和它的作者老赵吸引。该轻量级js库是为了实现异步编程所设计的,可能因为eval的种种不安全因素或者应用不是很广的原因至今也没很大程度上的推广,从github上来看代码也已经两年多没更新了,但是还是有必要写几个小的demo的,毕竟下份需要阅读的代码中有用到该类库。

  先写个canvas上画圆的demo。

  等等,画圆?开玩笑,arc简单搞定!那么,要是不用h5的api自己来写这个函数呢?动手画了下感觉还是蛮easy的:

技术分享
 1 <!DOCTYPE html> 2 <html> 3   <head> 4     <link rel="stylesheet" href="reset.css"> 5     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 6     <title> </title> 7     <script src="jquery.js"></script> 8     <script src="wind-all-0.7.3.js"></script> 9     <script>10       window.onload = function() {11         var canvas = document.getElementById("canvas");12         var ctx = canvas.getContext("2d");13         var x = 250;14         var y = 250;15         var r = 100;16         var frontX = x - r;17         var frontY = y;18 19         for(var i = x - r; i <= x + r; i++) {20           var tempY = Math.sqrt(r * r - (x - i) * (x - i));21           ctx.beginPath();22           ctx.moveTo(frontX, frontY);23           ctx.lineTo(i, y+  tempY);24           ctx.stroke();25           frontX = i;26           frontY = y + tempY;27         }28         29         for(var i = x + r; i >= x - r; i--) {30           var tempY = Math.sqrt(r * r - (x - i) * (x - i));31           ctx.beginPath();32           ctx.moveTo(frontX, frontY);33           ctx.lineTo(i, y - tempY);34           ctx.stroke();35           frontX = i;36           frontY = y - tempY;37         }38       };39     </script>40   </head>41   <body>42     <canvas id=‘canvas‘ width=500 height=500 style=‘border:1px solid red‘>43     </canvas>44   </body>45 </html>
View Code

  这里为了写的规范点,用了beginPath。不用beginPath有时会出现些莫名其妙的错误,值得注意。

  那么,进步一想,能不能在画布上显示绘制过程呢?

  what?开玩笑吧,我们都知道js这样的解释型语言,解释完了也就画完了,咋可能显示绘制过程?

  等等,let me have a try,看看能不能用setTimeout?将stroke函数设置个定时器,约定1s后执行,那么能不能出现1s绘制一帧的效果呢?

  很遗憾,事实上是没有的,实际的效果是1s后全部绘图一瞬间完成,因为for循环就在一瞬间,然后所有的setTimeout同时累计起来了,what a pity!

  技术分享

  这时我们祭出大杀器Windjs!改写后的代码如下:

技术分享
 1 <!DOCTYPE html> 2 <html> 3   <head> 4     <link rel="stylesheet" href="reset.css"> 5     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 6     <title> </title> 7     <script src="jquery.js"></script> 8     <script src="wind-all-0.7.3.js"></script> 9     <script>10       window.onload = function() {11         var canvas = document.getElementById("canvas");12         var ctx = canvas.getContext("2d");13         var x = 250;14         var y = 250;15         var r = 100;16         var frontX = x - r;17         var frontY = y;18 19         var drawAsync = eval(Wind.compile(async, function() {20           for(var i = x - r; i <= x + r; i++) {21             var tempY = Math.sqrt(r * r - (x - i) * (x - i));22             ctx.beginPath();23             ctx.moveTo(frontX, frontY);24             ctx.lineTo(i, y+  tempY);25             $await(Wind.Async.sleep(10));26             ctx.stroke();27             frontX = i;28             frontY = y + tempY;29           }30         31           for(var i = x + r; i >= x - r; i--) {32             var tempY = Math.sqrt(r * r - (x - i) * (x - i));33             ctx.beginPath();34             ctx.moveTo(frontX, frontY);35             ctx.lineTo(i, y - tempY);36             $await(Wind.Async.sleep(10));37             ctx.stroke();38             frontX = i;39             frontY = y - tempY;40           }41         }));42 43         drawAsync().start();44       };45     </script>46   </head>47   <body>48     <canvas id=‘canvas‘ width=500 height=500 style=‘border:1px solid red‘>49     </canvas>50   </body>51 </html>
View Code

  what a pass!来自Windjs的助攻成功地完成了不可能完成的任务!

  ps:Wind.js备份

技术分享
   1 /***********************************************************************   2   wind-core-0.7.0.js   3  ***********************************************************************/   4    5 (function () {   6     "use strict";   7        8     var Wind;   9       10     var _ = (function () {  11       12         var isArray = function (obj) {  13             return Object.prototype.toString.call(obj) === ‘[object Array]‘;  14         }  15       16         var each = function (obj, action) {  17             if (isArray(obj)) {  18                 for (var i = 0, len = obj.length; i < len; i++) {  19                     var value = http://www.mamicode.com/action.length === 1 ? action(obj[i]) : action(i, obj[i]);  20                     if (value !== undefined)  21                         return value;  22                 }  23             } else {  24                 for (var key in obj) {  25                     if (obj.hasOwnProperty(key)) {  26                         var value = http://www.mamicode.com/action.length === 1 ? action(obj[key]) : action(key, obj[key]);  27                         if (value !== undefined)  28                             return value;  29                     }  30                 }  31             }  32         }  33           34         var isEmpty = function (obj) {  35             if (isArray(obj)) {  36                 return obj.length === 0;  37             }  38               39             return !(_.each(obj, function (v) { return true; }));  40         }  41           42         var map = function (obj, mapper, valueMapper) {  43             if (isArray(obj)) {  44                 var array = new Array(obj.length);  45                 for (var i = 0, len = obj.length; i < len; i++) {  46                     array[i] = mapper(obj[i]);  47                 }  48                 return array;  49             } else {  50                 var keyMapper = valueMapper ? mapper : null;  51                 valueMapper = valueMapper || mapper;  52                   53                 var newObj = {};  54                 for (var key in obj) {  55                     if (obj.hasOwnProperty(key)) {  56                         var value =http://www.mamicode.com/ obj[key];  57                         var newKey = keyMapper ? keyMapper(key) : key;  58                         var newValue = http://www.mamicode.com/valueMapper ? valueMapper(value) : value;  59                         newObj[newKey] = newValue;  60                     }  61                 }  62   63                 return newObj;  64             }  65         }  66   67         var clone = function (obj) {  68             return map(obj);  69         }  70           71         var v2n = function (version) {  72             var value = http://www.mamicode.com/0;  73               74             var parts = version.split(".");  75             for (var i = 0; i < 3; i++) {  76                 value *= 100;  77                 if (i < parts.length) {  78                     value += parseInt(parts[i], 10);  79                 }  80             }  81               82             return value;  83         }  84           85         var testVersion = function (expected, version) {  86             var expectedMinVersion = expected.substring(1); // remove leading "~"  87               88             var expectedMaxParts = expectedMinVersion.split(".");  89             expectedMaxParts[expectedMaxParts.length - 1] = "0";  90             expectedMaxParts[expectedMaxParts.length - 2] = (parseInt(expectedMaxParts[expectedMaxParts.length - 2], 10) + 1).toString();  91             var expectedMaxVersion = expectedMaxParts.join(".");  92               93             var versionNumber = v2n(version);  94             return v2n(expectedMinVersion) <= versionNumber && versionNumber < v2n(expectedMaxVersion);  95         }  96           97         var format = function (f, args) {  98             // support _.format(f, a0, a1, ...);  99             if (!isArray(args)) { 100                 var newArgs = new Array(arguments.length - 1); 101                 for (var i = 1; i < arguments.length; i++) { 102                     newArgs[i - 1] = arguments[i]; 103                 } 104                  105                 return format(f, newArgs); 106             } 107              108             return f.replace(/\{{1,2}\d+\}{1,2}/g, function (ph) { 109                 if (ph.indexOf("{{") == 0 && ph.indexOf("}}") == ph.length - 2) { 110                     return ph.substring(1, ph.length - 1); 111                 } 112                  113                 var left = 0; 114                 while (ph[left] == "{") left++; 115                  116                 var right = ph.length - 1; 117                 while (ph[right] == "}") right--; 118                  119                 var index = parseInt(ph.substring(left, right + 1), 10); 120                 return ph.replace("{" + index + "}", args[index]); 121             }); 122         } 123          124         var once = function (fn) { 125             var called = false; 126             return function () { 127                 if (called) return; 128                 fn.apply(this, arguments); 129                 called = true; 130             } 131         }; 132          133         return { 134             isArray: isArray, 135             each: each, 136             isEmpty: isEmpty, 137             map: map, 138             clone: clone, 139             v2n: v2n, 140             testVersion: testVersion, 141             format: format, 142             once: once 143         }; 144     })(); 145  146     var Level = { 147         ALL: 0, 148         TRACE: 1, 149         DEBUG: 2, 150         INFO: 3, 151         WARN: 4, 152         ERROR: 5, 153         OFF: 100 154     }; 155  156     var Logger = function () { 157         this.level = Level.DEBUG; 158     }; 159     Logger.prototype = { 160         log: function (level, msg) { 161             if (this.level <= level) { 162                 try { console.log(msg); } catch (ex) { } 163             } 164         }, 165  166         trace: function (msg) { 167             this.log(Level.TRACE, msg); 168         }, 169  170         debug: function (msg) { 171             this.log(Level.DEBUG, msg); 172         }, 173  174         info: function (msg) { 175             this.log(Level.INFO, msg); 176         }, 177  178         warn: function (msg) { 179             this.log(Level.WARN, msg); 180         }, 181  182         error: function (msg) { 183             this.log(Level.ERROR, msg); 184         } 185     }; 186  187     var exportBasicOptions = function (exports, options) { 188         exports.name = options.name; 189         exports.version = options.version; 190          191         if (options.autoloads) { 192             exports.autoloads = options.autoloads; 193         } 194          195         if (options.dependencies) { 196             exports.dependencies = options.dependencies; 197         } 198     } 199      200     var initModule = function (options) { 201         var existingModule = Wind.modules[options.name]; 202         if (existingModule && existingModule.version != options.version) { 203             Wind.logger.warn(_.format( 204                 ‘The module "{0}" with version "{1}" has already been initialized, skip version "{2}".‘, 205                 options.name, 206                 existingModule.version, 207                 options.version)); 208         } 209  210         checkDependencies(options); 211         options.init(); 212          213         var module = {}; 214         exportBasicOptions(module, options); 215         Wind.modules[options.name] = module; 216     } 217      218     var checkDependencies = function (options) { 219         _.each(options.dependencies || [], function (name, expectedVersion) { 220             var module = Wind.modules[name]; 221             if (!module) { 222                 throw new Error(_.format( 223                     ‘Missing required module: "{0}" (expected version: "{1}").‘, 224                     name, 225                     expectedVersion)); 226             } 227  228             if (!_.testVersion(expectedVersion, module.version)) { 229                 throw new Error(_.format( 230                     ‘Version of module "{0}" mismatched, expected: "{1}", actual: "{2}".‘, 231                     name, 232                     expectedVersion, 233                     module.version)); 234             } 235         }); 236     } 237  238     // CommonJS 239     var isCommonJS = !!(typeof require === "function" && typeof module !== "undefined" && module.exports); 240     // CommonJS AMD 241     var isAmd = !!(typeof require === "function" && typeof define === "function" && define.amd); 242      243     var defineModule = function (options) { 244         var autoloads = options.autoloads || []; 245  246         if (isCommonJS) { 247             var require = options.require; 248             _.each(autoloads, function (name) { 249                 try { 250                     require("./wind-" + name); 251                 } catch (ex) { 252                     require("wind-" + name); 253                 } 254             }); 255              256             initModule(options); 257         } else if (isAmd) { 258             var dependencies = _.map(autoloads, function (name) { return "wind-" + name; }); 259             define("wind-" + options.name, dependencies, function () { 260                 if (options.onerror) { 261                     try { 262                         initModule(options); 263                     } catch (ex) { 264                         options.onerror(ex); 265                     } 266                 } else { 267                     initModule(options); 268                 } 269             }); 270         } else { 271             initModule(options); 272         } 273     } 274  275     var init = function () { 276         Wind.logger = new Logger(); 277         Wind.Logging = { 278             Logger: Logger, 279             Level: Level 280         }; 281  282         Wind._ = _; 283         Wind.modules = { core: { name: "core", version: "0.7.0" } }; 284         Wind.binders = { }; 285         Wind.builders = { }; 286         Wind.define = defineModule; 287     }; 288      289     if (isCommonJS) { 290         Wind = module.exports; 291         init(); 292     } else if (isAmd) { 293         define("wind-core", function () { 294             Wind = { }; 295             init(); 296             return Wind; 297         }); 298     } else { 299         // Get the global object. 300         var Fn = Function, global = Fn(‘return this‘)(); 301      302         if (global.Wind) { 303             throw new Error("There‘s already a Wind root here, please load the component only once."); 304         } 305          306         Wind = global.Wind = { }; 307         init(); 308     } 309 })(); 310  311 /*********************************************************************** 312   wind-compiler-0.7.2.js 313  ***********************************************************************/ 314  315 (function () { 316     "use strict"; 317  318     var parse = (function () { 319  320         /*********************************************************************** 321  322           A JavaScript tokenizer / parser / beautifier / compressor. 323  324           This version is suitable for Node.js.  With minimal changes (the 325           exports stuff) it should work on any JS platform. 326  327           This file contains the tokenizer/parser.  It is a port to JavaScript 328           of parse-js [1], a JavaScript parser library written in Common Lisp 329           by Marijn Haverbeke.  Thank you Marijn! 330  331           [1] http://marijn.haverbeke.nl/parse-js/ 332  333           Exported functions: 334  335             - tokenizer(code) -- returns a function.  Call the returned 336               function to fetch the next token. 337  338             - parse(code) -- returns an AST of the given JavaScript code. 339  340           -------------------------------- (C) --------------------------------- 341  342                                    Author: Mihai Bazon 343                                  <mihai.bazon@gmail.com> 344                                http://mihai.bazon.net/blog 345  346           Distributed under the BSD license: 347  348             Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com> 349             Based on parse-js (http://marijn.haverbeke.nl/parse-js/). 350  351             Redistribution and use in source and binary forms, with or without 352             modification, are permitted provided that the following conditions 353             are met: 354  355                 * Redistributions of source code must retain the above 356                   copyright notice, this list of conditions and the following 357                   disclaimer. 358  359                 * Redistributions in binary form must reproduce the above 360                   copyright notice, this list of conditions and the following 361                   disclaimer in the documentation and/or other materials 362                   provided with the distribution. 363  364             THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY 365             EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 366             IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 367             PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE 368             LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 369             OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 370             PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 371             PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 372             THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 373             TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 374             THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 375             SUCH DAMAGE. 376  377          ***********************************************************************/ 378  379         /* -----[ Tokenizer (constants) ]----- */ 380  381         var KEYWORDS = array_to_hash([ 382                 "break", 383                 "case", 384                 "catch", 385                 "const", 386                 "continue", 387                 "default", 388                 "delete", 389                 "do", 390                 "else", 391                 "finally", 392                 "for", 393                 "function", 394                 "if", 395                 "in", 396                 "instanceof", 397                 "new", 398                 "return", 399                 "switch", 400                 "throw", 401                 "try", 402                 "typeof", 403                 "var", 404                 "void", 405                 "while", 406                 "with" 407         ]); 408  409         var RESERVED_WORDS = array_to_hash([ 410                 "abstract", 411                 "boolean", 412                 "byte", 413                 "char", 414                 "class", 415                 "debugger", 416                 "double", 417                 "enum", 418                 "export", 419                 "extends", 420                 "final", 421                 "float", 422                 "goto", 423                 "implements", 424                 "import", 425                 "int", 426                 "interface", 427                 "long", 428                 "native", 429                 "package", 430                 "private", 431                 "protected", 432                 "public", 433                 "short", 434                 "static", 435                 "super", 436                 "synchronized", 437                 "throws", 438                 "transient", 439                 "volatile" 440         ]); 441  442         var KEYWORDS_BEFORE_EXPRESSION = array_to_hash([ 443                 "return", 444                 "new", 445                 "delete", 446                 "throw", 447                 "else", 448                 "case" 449         ]); 450  451         var KEYWORDS_ATOM = array_to_hash([ 452                 "false", 453                 "null", 454                 "true", 455                 "undefined" 456         ]); 457  458         var OPERATOR_CHARS = array_to_hash(characters("+-*&%=<>!?|~^")); 459  460         var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i; 461         var RE_OCT_NUMBER = /^0[0-7]+$/; 462         var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i; 463  464         var OPERATORS = array_to_hash([ 465                 "in", 466                 "instanceof", 467                 "typeof", 468                 "new", 469                 "void", 470                 "delete", 471                 "++", 472                 "--", 473                 "+", 474                 "-", 475                 "!", 476                 "~", 477                 "&", 478                 "|", 479                 "^", 480                 "*", 481                 "/", 482                 "%", 483                 ">>", 484                 "<<", 485                 ">>>", 486                 "<", 487                 ">", 488                 "<=", 489                 ">=", 490                 "==", 491                 "===", 492                 "!=", 493                 "!==", 494                 "?", 495                 "=", 496                 "+=", 497                 "-=", 498                 "/=", 499                 "*=", 500                 "%=", 501                 ">>=", 502                 "<<=", 503                 ">>>=", 504                 "|=", 505                 "^=", 506                 "&=", 507                 "&&", 508                 "||" 509         ]); 510  511         var WHITESPACE_CHARS = array_to_hash(characters(" \n\r\t\u200b")); 512  513         var PUNC_BEFORE_EXPRESSION = array_to_hash(characters("[{}(,.;:")); 514  515         var PUNC_CHARS = array_to_hash(characters("[]{}(),;:")); 516  517         var REGEXP_MODIFIERS = array_to_hash(characters("gmsiy")); 518  519         /* -----[ Tokenizer ]----- */ 520  521         // regexps adapted from http://xregexp.com/plugins/#unicode 522         var UNICODE = { 523                 letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0523\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0621-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971\\u0972\\u097B-\\u097F\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D28\\u0D2A-\\u0D39\\u0D3D\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC\\u0EDD\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8B\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10D0-\\u10FA\\u10FC\\u1100-\\u1159\\u115F-\\u11A2\\u11A8-\\u11F9\\u1200-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u1676\\u1681-\\u169A\\u16A0-\\u16EA\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19A9\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u2094\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2C6F\\u2C71-\\u2C7D\\u2C80-\\u2CE4\\u2D00-\\u2D25\\u2D30-\\u2D65\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31B7\\u31F0-\\u31FF\\u3400\\u4DB5\\u4E00\\u9FC3\\uA000-\\uA48C\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA65F\\uA662-\\uA66E\\uA67F-\\uA697\\uA717-\\uA71F\\uA722-\\uA788\\uA78B\\uA78C\\uA7FB-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA90A-\\uA925\\uA930-\\uA946\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAC00\\uD7A3\\uF900-\\uFA2D\\uFA30-\\uFA6A\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"), 524                 non_spacing_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065E\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0900-\\u0902\\u093C\\u0941-\\u0948\\u094D\\u0951-\\u0955\\u0962\\u0963\\u0981\\u09BC\\u09C1-\\u09C4\\u09CD\\u09E2\\u09E3\\u0A01\\u0A02\\u0A3C\\u0A41\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81\\u0A82\\u0ABC\\u0AC1-\\u0AC5\\u0AC7\\u0AC8\\u0ACD\\u0AE2\\u0AE3\\u0B01\\u0B3C\\u0B3F\\u0B41-\\u0B44\\u0B4D\\u0B56\\u0B62\\u0B63\\u0B82\\u0BC0\\u0BCD\\u0C3E-\\u0C40\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0CBC\\u0CBF\\u0CC6\\u0CCC\\u0CCD\\u0CE2\\u0CE3\\u0D41-\\u0D44\\u0D4D\\u0D62\\u0D63\\u0DCA\\u0DD2-\\u0DD4\\u0DD6\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F71-\\u0F7E\\u0F80-\\u0F84\\u0F86\\u0F87\\u0F90-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102D-\\u1030\\u1032-\\u1037\\u1039\\u103A\\u103D\\u103E\\u1058\\u1059\\u105E-\\u1060\\u1071-\\u1074\\u1082\\u1085\\u1086\\u108D\\u109D\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B7-\\u17BD\\u17C6\\u17C9-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u1922\\u1927\\u1928\\u1932\\u1939-\\u193B\\u1A17\\u1A18\\u1A56\\u1A58-\\u1A5E\\u1A60\\u1A62\\u1A65-\\u1A6C\\u1A73-\\u1A7C\\u1A7F\\u1B00-\\u1B03\\u1B34\\u1B36-\\u1B3A\\u1B3C\\u1B42\\u1B6B-\\u1B73\\u1B80\\u1B81\\u1BA2-\\u1BA5\\u1BA8\\u1BA9\\u1C2C-\\u1C33\\u1C36\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE0\\u1CE2-\\u1CE8\\u1CED\\u1DC0-\\u1DE6\\u1DFD-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA67C\\uA67D\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA825\\uA826\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA951\\uA980-\\uA982\\uA9B3\\uA9B6-\\uA9B9\\uA9BC\\uAA29-\\uAA2E\\uAA31\\uAA32\\uAA35\\uAA36\\uAA43\\uAA4C\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uABE5\\uABE8\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"), 525                 space_combining_mark: new RegExp("[\\u0903\\u093E-\\u0940\\u0949-\\u094C\\u094E\\u0982\\u0983\\u09BE-\\u09C0\\u09C7\\u09C8\\u09CB\\u09CC\\u09D7\\u0A03\\u0A3E-\\u0A40\\u0A83\\u0ABE-\\u0AC0\\u0AC9\\u0ACB\\u0ACC\\u0B02\\u0B03\\u0B3E\\u0B40\\u0B47\\u0B48\\u0B4B\\u0B4C\\u0B57\\u0BBE\\u0BBF\\u0BC1\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCC\\u0BD7\\u0C01-\\u0C03\\u0C41-\\u0C44\\u0C82\\u0C83\\u0CBE\\u0CC0-\\u0CC4\\u0CC7\\u0CC8\\u0CCA\\u0CCB\\u0CD5\\u0CD6\\u0D02\\u0D03\\u0D3E-\\u0D40\\u0D46-\\u0D48\\u0D4A-\\u0D4C\\u0D57\\u0D82\\u0D83\\u0DCF-\\u0DD1\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0F3E\\u0F3F\\u0F7F\\u102B\\u102C\\u1031\\u1038\\u103B\\u103C\\u1056\\u1057\\u1062-\\u1064\\u1067-\\u106D\\u1083\\u1084\\u1087-\\u108C\\u108F\\u109A-\\u109C\\u17B6\\u17BE-\\u17C5\\u17C7\\u17C8\\u1923-\\u1926\\u1929-\\u192B\\u1930\\u1931\\u1933-\\u1938\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A19-\\u1A1B\\u1A55\\u1A57\\u1A61\\u1A63\\u1A64\\u1A6D-\\u1A72\\u1B04\\u1B35\\u1B3B\\u1B3D-\\u1B41\\u1B43\\u1B44\\u1B82\\u1BA1\\u1BA6\\u1BA7\\u1BAA\\u1C24-\\u1C2B\\u1C34\\u1C35\\u1CE1\\u1CF2\\uA823\\uA824\\uA827\\uA880\\uA881\\uA8B4-\\uA8C3\\uA952\\uA953\\uA983\\uA9B4\\uA9B5\\uA9BA\\uA9BB\\uA9BD-\\uA9C0\\uAA2F\\uAA30\\uAA33\\uAA34\\uAA4D\\uAA7B\\uABE3\\uABE4\\uABE6\\uABE7\\uABE9\\uABEA\\uABEC]"), 526                 connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]") 527         }; 528  529         function is_letter(ch) { 530                 return UNICODE.letter.test(ch); 531         }; 532  533         function is_digit(ch) { 534                 ch = ch.charCodeAt(0); 535                 return ch >= 48 && ch <= 57; //XXX: find out if "UnicodeDigit" means something else than 0..9 536         }; 537  538         function is_alphanumeric_char(ch) { 539                 return is_digit(ch) || is_letter(ch); 540         }; 541  542         function is_unicode_combining_mark(ch) { 543                 return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch); 544         }; 545  546         function is_unicode_connector_punctuation(ch) { 547                 return UNICODE.connector_punctuation.test(ch); 548         }; 549  550         function is_identifier_start(ch) { 551                 return ch == "$" || ch == "_" || is_letter(ch); 552         }; 553  554         function is_identifier_char(ch) { 555                 return is_identifier_start(ch) 556                         || is_unicode_combining_mark(ch) 557                         || is_digit(ch) 558                         || is_unicode_connector_punctuation(ch) 559                         || ch == "\u200c" // zero-width non-joiner <ZWNJ> 560                         || ch == "\u200d" // zero-width joiner <ZWJ> (in my ECMA-262 PDF, this is also 200c) 561                 ; 562         }; 563  564         function parse_js_number(num) { 565                 if (RE_HEX_NUMBER.test(num)) { 566                         return parseInt(num.substr(2), 16); 567                 } else if (RE_OCT_NUMBER.test(num)) { 568                         return parseInt(num.substr(1), 8); 569                 } else if (RE_DEC_NUMBER.test(num)) { 570                         return parseFloat(num); 571                 } 572         }; 573  574         function JS_Parse_Error(message, line, col, pos) { 575                 this.message = message; 576                 this.line = line; 577                 this.col = col; 578                 this.pos = pos; 579                 try { 580                         ({})(); 581                 } catch(ex) { 582                         this.stack = ex.stack; 583                 }; 584         }; 585  586         JS_Parse_Error.prototype.toString = function() { 587                 return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack; 588         }; 589  590         function js_error(message, line, col, pos) { 591                 throw new JS_Parse_Error(message, line, col, pos); 592         }; 593  594         function is_token(token, type, val) { 595                 return token.type == type && (val == null || token.value =http://www.mamicode.com/= val); 596         }; 597  598         var EX_EOF = {}; 599  600         function tokenizer($TEXT) { 601  602                 var S = { 603                         text            : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, ‘‘), 604                         pos             : 0, 605                         tokpos          : 0, 606                         line            : 0, 607                         tokline         : 0, 608                         col             : 0, 609                         tokcol          : 0, 610                         newline_before  : false, 611                         regex_allowed   : false, 612                         comments_before : [] 613                 }; 614  615                 function peek() { return S.text.charAt(S.pos); }; 616  617                 function next(signal_eof) { 618                         var ch = S.text.charAt(S.pos++); 619                         if (signal_eof && !ch) 620                                 throw EX_EOF; 621                         if (ch == "\n") { 622                                 S.newline_before = true; 623                                 ++S.line; 624                                 S.col = 0; 625                         } else { 626                                 ++S.col; 627                         } 628                         return ch; 629                 }; 630  631                 function eof() { 632                         return !S.peek(); 633                 }; 634  635                 function find(what, signal_eof) { 636                         var pos = S.text.indexOf(what, S.pos); 637                         if (signal_eof && pos == -1) throw EX_EOF; 638                         return pos; 639                 }; 640  641                 function start_token() { 642                         S.tokline = S.line; 643                         S.tokcol = S.col; 644                         S.tokpos = S.pos; 645                 }; 646  647                 function token(type, value, is_comment) { 648                         S.regex_allowed = ((type == "operator" && !HOP(UNARY_POSTFIX, value)) || 649                                            (type == "keyword" && HOP(KEYWORDS_BEFORE_EXPRESSION, value)) || 650                                            (type == "punc" && HOP(PUNC_BEFORE_EXPRESSION, value))); 651                         var ret = { 652                                 type  : type, 653                                 value : value, 654                                 line  : S.tokline, 655                                 col   : S.tokcol, 656                                 pos   : S.tokpos, 657                                 nlb   : S.newline_before 658                         }; 659                         if (!is_comment) { 660                                 ret.comments_before = S.comments_before; 661                                 S.comments_before = []; 662                         } 663                         S.newline_before = false; 664                         return ret; 665                 }; 666  667                 function skip_whitespace() { 668                         while (HOP(WHITESPACE_CHARS, peek())) 669                                 next(); 670                 }; 671  672                 function read_while(pred) { 673                         var ret = "", ch = peek(), i = 0; 674                         while (ch && pred(ch, i++)) { 675                                 ret += next(); 676                                 ch = peek(); 677                         } 678                         return ret; 679                 }; 680  681                 function parse_error(err) { 682                         js_error(err, S.tokline, S.tokcol, S.tokpos); 683                 }; 684  685                 function read_num(prefix) { 686                         var has_e = false, after_e = false, has_x = false, has_dot = prefix == "."; 687                         var num = read_while(function(ch, i){ 688                                 if (ch == "x" || ch == "X") { 689                                         if (has_x) return false; 690                                         return has_x = true; 691                                 } 692                                 if (!has_x && (ch == "E" || ch == "e")) { 693                                         if (has_e) return false; 694                                         return has_e = after_e = true; 695                                 } 696                                 if (ch == "-") { 697                                         if (after_e || (i == 0 && !prefix)) return true; 698                                         return false; 699                                 } 700                                 if (ch == "+") return after_e; 701                                 after_e = false; 702                                 if (ch == ".") { 703                                         if (!has_dot && !has_x) 704                                                 return has_dot = true; 705                                         return false; 706                                 } 707                                 return is_alphanumeric_char(ch); 708                         }); 709                         if (prefix) 710                                 num = prefix + num; 711                         var valid = parse_js_number(num); 712                         if (!isNaN(valid)) { 713                                 return token("num", valid); 714                         } else { 715                                 parse_error("Invalid syntax: " + num); 716                         } 717                 }; 718  719                 function read_escaped_char() { 720                         var ch = next(true); 721                         switch (ch) { 722                             case "n" : return "\n"; 723                             case "r" : return "\r"; 724                             case "t" : return "\t"; 725                             case "b" : return "\b"; 726                             case "v" : return "\v"; 727                             case "f" : return "\f"; 728                             case "0" : return "\0"; 729                             case "x" : return String.fromCharCode(hex_bytes(2)); 730                             case "u" : return String.fromCharCode(hex_bytes(4)); 731                             default  : return ch; 732                         } 733                 }; 734  735                 function hex_bytes(n) { 736                         var num = 0; 737                         for (; n > 0; --n) { 738                                 var digit = parseInt(next(true), 16); 739                                 if (isNaN(digit)) 740                                         parse_error("Invalid hex-character pattern in string"); 741                                 num = (num << 4) | digit; 742                         } 743                         return num; 744                 }; 745  746                 function read_string() { 747                         return with_eof_error("Unterminated string constant", function(){ 748                                 var quote = next(), ret = ""; 749                                 for (;;) { 750                                         var ch = next(true); 751                                         if (ch == "\\") ch = read_escaped_char(); 752                                         else if (ch == quote) break; 753                                         ret += ch; 754                                 } 755                                 return token("string", ret); 756                         }); 757                 }; 758  759                 function read_line_comment() { 760                         next(); 761                         var i = find("\n"), ret; 762                         if (i == -1) { 763                                 ret = S.text.substr(S.pos); 764                                 S.pos = S.text.length; 765                         } else { 766                                 ret = S.text.substring(S.pos, i); 767                                 S.pos = i; 768                         } 769                         return token("comment1", ret, true); 770                 }; 771  772                 function read_multiline_comment() { 773                         next(); 774                         return with_eof_error("Unterminated multiline comment", function(){ 775                                 var i = find("*/", true), 776                                     text = S.text.substring(S.pos, i), 777                                     tok = token("comment2", text, true); 778                                 S.pos = i + 2; 779                                 S.line += text.split("\n").length - 1; 780                                 S.newline_before = text.indexOf("\n") >= 0; 781  782                                 // https://github.com/mishoo/UglifyJS/issues/#issue/100 783                                 if (/^@cc_on/i.test(text)) { 784                                         warn("WARNING: at line " + S.line); 785                                         warn("*** Found \"conditional comment\": " + text); 786                                         warn("*** UglifyJS DISCARDS ALL COMMENTS.  This means your code might no longer work properly in Internet Explorer."); 787                                 } 788  789                                 return tok; 790                         }); 791                 }; 792  793                 function read_name() { 794                         var backslash = false, name = "", ch; 795                         while ((ch = peek()) != null) { 796                                 if (!backslash) { 797                                         if (ch == "\\") backslash = true, next(); 798                                         else if (is_identifier_char(ch)) name += next(); 799                                         else break; 800                                 } 801                                 else { 802                                         if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX"); 803                                         ch = read_escaped_char(); 804                                         if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier"); 805                                         name += ch; 806                                         backslash = false; 807                                 } 808                         } 809                         return name; 810                 }; 811  812                 function read_regexp() { 813                         return with_eof_error("Unterminated regular expression", function(){ 814                                 var prev_backslash = false, regexp = "", ch, in_class = false; 815                                 while ((ch = next(true))) if (prev_backslash) { 816                                         regexp += "\\" + ch; 817                                         prev_backslash = false; 818                                 } else if (ch == "[") { 819                                         in_class = true; 820                                         regexp += ch; 821                                 } else if (ch == "]" && in_class) { 822                                         in_class = false; 823                                         regexp += ch; 824                                 } else if (ch == "/" && !in_class) { 825                                         break; 826                                 } else if (ch == "\\") { 827                                         prev_backslash = true; 828                                 } else { 829                                         regexp += ch; 830                                 } 831                                 var mods = read_name(); 832                                 return token("regexp", [ regexp, mods ]); 833                         }); 834                 }; 835  836                 function read_operator(prefix) { 837                         function grow(op) { 838                                 if (!peek()) return op; 839                                 var bigger = op + peek(); 840                                 if (HOP(OPERATORS, bigger)) { 841                                         next(); 842                                         return grow(bigger); 843                                 } else { 844                                         return op; 845                                 } 846                         }; 847                         return token("operator", grow(prefix || next())); 848                 }; 849  850                 function handle_slash() { 851                         next(); 852                         var regex_allowed = S.regex_allowed; 853                         switch (peek()) { 854                             case "/": 855                                 S.comments_before.push(read_line_comment()); 856                                 S.regex_allowed = regex_allowed; 857                                 return next_token(); 858                             case "*": 859                                 S.comments_before.push(read_multiline_comment()); 860                                 S.regex_allowed = regex_allowed; 861                                 return next_token(); 862                         } 863                         return S.regex_allowed ? read_regexp() : read_operator("/"); 864                 }; 865  866                 function handle_dot() { 867                         next(); 868                         return is_digit(peek()) 869                                 ? read_num(".") 870                                 : token("punc", "."); 871                 }; 872  873                 function read_word() { 874                         var word = read_name(); 875                         return !HOP(KEYWORDS, word) 876                                 ? token("name", word) 877                                 : HOP(OPERATORS, word) 878                                 ? token("operator", word) 879                                 : HOP(KEYWORDS_ATOM, word) 880                                 ? token("atom", word) 881                                 : token("keyword", word); 882                 }; 883  884                 function with_eof_error(eof_error, cont) { 885                         try { 886                                 return cont(); 887                         } catch(ex) { 888                                 if (ex === EX_EOF) parse_error(eof_error); 889                                 else throw ex; 890                         } 891                 }; 892  893                 function next_token(force_regexp) { 894                         if (force_regexp) 895                                 return read_regexp(); 896                         skip_whitespace(); 897                         start_token(); 898                         var ch = peek(); 899                         if (!ch) return token("eof"); 900                         if (is_digit(ch)) return read_num(); 901                         if (ch == ‘"‘ || ch == "‘") return read_string(); 902                         if (HOP(PUNC_CHARS, ch)) return token("punc", next()); 903                         if (ch == ".") return handle_dot(); 904                         if (ch == "/") return handle_slash(); 905                         if (HOP(OPERATOR_CHARS, ch)) return read_operator(); 906                         if (ch == "\\" || is_identifier_start(ch)) return read_word(); 907                         parse_error("Unexpected character ‘" + ch + "‘"); 908                 }; 909  910                 next_token.context = function(nc) { 911                         if (nc) S = nc; 912                         return S; 913                 }; 914  915                 return next_token; 916  917         }; 918  919         /* -----[ Parser (constants) ]----- */ 920  921         var UNARY_PREFIX = array_to_hash([ 922                 "typeof", 923                 "void", 924                 "delete", 925                 "--", 926                 "++", 927                 "!", 928                 "~", 929                 "-", 930                 "+" 931         ]); 932  933         var UNARY_POSTFIX = array_to_hash([ "--", "++" ]); 934  935         var ASSIGNMENT = (function(a, ret, i){ 936                 while (i < a.length) { 937                         ret[a[i]] = a[i].substr(0, a[i].length - 1); 938                         i++; 939                 } 940                 return ret; 941         })( 942                 ["+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&="], 943                 { "=": true }, 944                 0 945         ); 946  947         var PRECEDENCE = (function(a, ret){ 948                 for (var i = 0, n = 1; i < a.length; ++i, ++n) { 949                         var b = a[i]; 950                         for (var j = 0; j < b.length; ++j) { 951                                 ret[b[j]] = n; 952                         } 953                 } 954                 return ret; 955         })( 956                 [ 957                         ["||"], 958                         ["&&"], 959                         ["|"], 960                         ["^"], 961                         ["&"], 962                         ["==", "===", "!=", "!=="], 963                         ["<", ">", "<=", ">=", "in", "instanceof"], 964                         [">>", "<<", ">>>"], 965                         ["+", "-"], 966                         ["*", "/", "%"] 967                 ], 968                 {} 969         ); 970  971         var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]); 972  973         var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]); 974  975         /* -----[ Parser ]----- */ 976  977         function NodeWithToken(str, start, end) { 978                 this.name = str; 979                 this.start = start; 980                 this.end = end; 981         }; 982  983         NodeWithToken.prototype.toString = function() { return this.name; }; 984  985         function parse($TEXT, exigent_mode, embed_tokens) { 986  987                 var S = { 988                         input       : typeof $TEXT == "string" ? tokenizer($TEXT, true) : $TEXT, 989                         token       : null, 990                         prev        : null, 991                         peeked      : null, 992                         in_function : 0, 993                         in_loop     : 0, 994                         labels      : [] 995                 }; 996  997                 S.token = next(); 998  999                 function is(type, value) {1000                         return is_token(S.token, type, value);1001                 };1002 1003                 function peek() { return S.peeked || (S.peeked = S.input()); };1004 1005                 function next() {1006                         S.prev = S.token;1007                         if (S.peeked) {1008                                 S.token = S.peeked;1009                                 S.peeked = null;1010                         } else {1011                                 S.token = S.input();1012                         }1013                         return S.token;1014                 };1015 1016                 function prev() {1017                         return S.prev;1018                 };1019 1020                 function croak(msg, line, col, pos) {1021                         var ctx = S.input.context();1022                         js_error(msg,1023                                  line != null ? line : ctx.tokline,1024                                  col != null ? col : ctx.tokcol,1025                                  pos != null ? pos : ctx.tokpos);1026                 };1027 1028                 function token_error(token, msg) {1029                         croak(msg, token.line, token.col);1030                 };1031 1032                 function unexpected(token) {1033                         if (token == null)1034                                 token = S.token;1035                         token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")");1036                 };1037 1038                 function expect_token(type, val) {1039                         if (is(type, val)) {1040                                 return next();1041                         }1042                         token_error(S.token, "Unexpected token " + S.token.type + ", expected " + type);1043                 };1044 1045                 function expect(punc) { return expect_token("punc", punc); };1046 1047                 function can_insert_semicolon() {1048                         return !exigent_mode && (1049                                 S.token.nlb || is("eof") || is("punc", "}")1050                         );1051                 };1052 1053                 function semicolon() {1054                         if (is("punc", ";")) next();1055                         else if (!can_insert_semicolon()) unexpected();1056                 };1057 1058                 function as() {1059                         return slice(arguments);1060                 };1061 1062                 function parenthesised() {1063                         expect("(");1064                         var ex = expression();1065                         expect(")");1066                         return ex;1067                 };1068 1069                 function add_tokens(str, start, end) {1070                         return str instanceof NodeWithToken ? str : new NodeWithToken(str, start, end);1071                 };1072 1073                 var statement = embed_tokens ? function() {1074                         var start = S.token;1075                         var ast = $statement.apply(this, arguments);1076                         ast[0] = add_tokens(ast[0], start, prev());1077                         return ast;1078                 } : $statement;1079 1080                 function $statement() {1081                         if (is("operator", "/")) {1082                                 S.peeked = null;1083                                 S.token = S.input(true); // force regexp1084                         }1085                         switch (S.token.type) {1086                             case "num":1087                             case "string":1088                             case "regexp":1089                             case "operator":1090                             case "atom":1091                                 return simple_statement();1092 1093                             case "name":1094                                 return is_token(peek(), "punc", ":")1095                                         ? labeled_statement(prog1(S.token.value, next, next))1096                                         : simple_statement();1097 1098                             case "punc":1099                                 switch (S.token.value) {1100                                     case "{":1101                                         return as("block", block_());1102                                     case "[":1103                                     case "(":1104                                         return simple_statement();1105                                     case ";":1106                                         next();1107                                         return as("block");1108                                     default:1109                                         unexpected();1110                                 }1111 1112                             case "keyword":1113                                 switch (prog1(S.token.value, next)) {1114                                     case "break":1115                                         return break_cont("break");1116 1117                                     case "continue":1118                                         return break_cont("continue");1119 1120                                     case "debugger":1121                                         semicolon();1122                                         return as("debugger");1123 1124                                     case "do":1125                                         return (function(body){1126                                                 expect_token("keyword", "while");1127                                                 return as("do", prog1(parenthesised, semicolon), body);1128                                         })(in_loop(statement));1129 1130                                     case "for":1131                                         return for_();1132 1133                                     case "function":1134                                         return function_(true);1135 1136                                     case "if":1137                                         return if_();1138 1139                                     case "return":1140                                         if (S.in_function == 0)1141                                                 croak("‘return‘ outside of function");1142                                         return as("return",1143                                                   is("punc", ";")1144                                                   ? (next(), null)1145                                                   : can_insert_semicolon()1146                                                   ? null1147                                                   : prog1(expression, semicolon));1148 1149                                     case "switch":1150                                         return as("switch", parenthesised(), switch_block_());1151 1152                                     case "throw":1153                                         return as("throw", prog1(expression, semicolon));1154 1155                                     case "try":1156                                         return try_();1157 1158                                     case "var":1159                                         return prog1(var_, semicolon);1160 1161                                     case "const":1162                                         return prog1(const_, semicolon);1163 1164                                     case "while":1165                                         return as("while", parenthesised(), in_loop(statement));1166 1167                                     case "with":1168                                         return as("with", parenthesised(), statement());1169 1170                                     default:1171                                         unexpected();1172                                 }1173                         }1174                 };1175 1176                 function labeled_statement(label) {1177                         S.labels.push(label);1178                         var start = S.token, stat = statement();1179                         if (exigent_mode && !HOP(STATEMENTS_WITH_LABELS, stat[0]))1180                                 unexpected(start);1181                         S.labels.pop();1182                         return as("label", label, stat);1183                 };1184 1185                 function simple_statement() {1186                         return as("stat", prog1(expression, semicolon));1187                 };1188 1189                 function break_cont(type) {1190                         var name = is("name") ? S.token.value : null;1191                         if (name != null) {1192                                 next();1193                                 if (!member(name, S.labels))1194                                         croak("Label " + name + " without matching loop or statement");1195                         }1196                         else if (S.in_loop == 0)1197                                 croak(type + " not inside a loop or switch");1198                         semicolon();1199                         return as(type, name);1200                 };1201 1202                 function for_() {1203                         expect("(");1204                         var init = null;1205                         if (!is("punc", ";")) {1206                                 init = is("keyword", "var")1207                                         ? (next(), var_(true))1208                                         : expression(true, true);1209                                 if (is("operator", "in"))1210                                         return for_in(init);1211                         }1212                         return regular_for(init);1213                 };1214 1215                 function regular_for(init) {1216                         expect(";");1217                         var test = is("punc", ";") ? null : expression();1218                         expect(";");1219                         var step = is("punc", ")") ? null : expression();1220                         expect(")");1221                         return as("for", init, test, step, in_loop(statement));1222                 };1223 1224                 function for_in(init) {1225                         var lhs = init[0] == "var" ? as("name", init[1][0]) : init;1226                         next();1227                         var obj = expression();1228                         expect(")");1229                         return as("for-in", init, lhs, obj, in_loop(statement));1230                 };1231 1232                 var function_ = embed_tokens ? function() {1233                         var start = prev();1234                         var ast = $function_.apply(this, arguments);1235                         ast[0] = add_tokens(ast[0], start, prev());1236                         return ast;1237                 } : $function_;1238 1239                 function $function_(in_statement) {1240                         var name = is("name") ? prog1(S.token.value, next) : null;1241                         if (in_statement && !name)1242                                 unexpected();1243                         expect("(");1244                         return as(in_statement ? "defun" : "function",1245                                   name,1246                                   // arguments1247                                   (function(first, a){1248                                           while (!is("punc", ")")) {1249                                                   if (first) first = false; else expect(",");1250                                                   if (!is("name")) unexpected();1251                                                   a.push(S.token.value);1252                                                   next();1253                                           }1254                                           next();1255                                           return a;1256                                   })(true, []),1257                                   // body1258                                   (function(){1259                                           ++S.in_function;1260                                           var loop = S.in_loop;1261                                           S.in_loop = 0;1262                                           var a = block_();1263                                           --S.in_function;1264                                           S.in_loop = loop;1265                                           return a;1266                                   })());1267                 };1268 1269                 function if_() {1270                         var cond = parenthesised(), body = statement(), belse;1271                         if (is("keyword", "else")) {1272                                 next();1273                                 belse = statement();1274                         }1275                         return as("if", cond, body, belse);1276                 };1277 1278                 function block_() {1279                         expect("{");1280                         var a = [];1281                         while (!is("punc", "}")) {1282                                 if (is("eof")) unexpected();1283                                 a.push(statement());1284                         }1285                         next();1286                         return a;1287                 };1288 1289                 var switch_block_ = curry(in_loop, function(){1290                         expect("{");1291                         var a = [], cur = null;1292                         while (!is("punc", "}")) {1293                                 if (is("eof")) unexpected();1294                                 if (is("keyword", "case")) {1295                                         next();1296                                         cur = [];1297                                         a.push([ expression(), cur ]);1298                                         expect(":");1299                                 }1300                                 else if (is("keyword", "default")) {1301                                         next();1302                                         expect(":");1303                                         cur = [];1304                                         a.push([ null, cur ]);1305                                 }1306                                 else {1307                                         if (!cur) unexpected();1308                                         cur.push(statement());1309                                 }1310                         }1311                         next();1312                         return a;1313                 });1314 1315                 function try_() {1316                         var body = block_(), bcatch, bfinally;1317                         if (is("keyword", "catch")) {1318                                 next();1319                                 expect("(");1320                                 if (!is("name"))1321                                         croak("Name expected");1322                                 var name = S.token.value;1323                                 next();1324                                 expect(")");1325                                 bcatch = [ name, block_() ];1326                         }1327                         if (is("keyword", "finally")) {1328                                 next();1329                                 bfinally = block_();1330                         }1331                         if (!bcatch && !bfinally)1332                                 croak("Missing catch/finally blocks");1333                         return as("try", body, bcatch, bfinally);1334                 };1335 1336                 function vardefs(no_in) {1337                         var a = [];1338                         for (;;) {1339                                 if (!is("name"))1340                                         unexpected();1341                                 var name = S.token.value;1342                                 next();1343                                 if (is("operator", "=")) {1344                                         next();1345                                         a.push([ name, expression(false, no_in) ]);1346                                 } else {1347                                         a.push([ name ]);1348                                 }1349                                 if (!is("punc", ","))1350                                         break;1351                                 next();1352                         }1353                         return a;1354                 };1355 1356                 function var_(no_in) {1357                         return as("var", vardefs(no_in));1358                 };1359 1360                 function const_() {1361                         return as("const", vardefs());1362                 };1363 1364                 function new_() {1365                         var newexp = expr_atom(false), args;1366                         if (is("punc", "(")) {1367                                 next();1368                                 args = expr_list(")");1369                         } else {1370                                 args = [];1371                         }1372                         return subscripts(as("new", newexp, args), true);1373                 };1374 1375                 function expr_atom(allow_calls) {1376                         if (is("operator", "new")) {1377                                 next();1378                                 return new_();1379                         }1380                         if (is("operator") && HOP(UNARY_PREFIX, S.token.value)) {1381                                 return make_unary("unary-prefix",1382                                                   prog1(S.token.value, next),1383                                                   expr_atom(allow_calls));1384                         }1385                         if (is("punc")) {1386                                 switch (S.token.value) {1387                                     case "(":1388                                         next();1389                                         return subscripts(prog1(expression, curry(expect, ")")), allow_calls);1390                                     case "[":1391                                         next();1392                                         return subscripts(array_(), allow_calls);1393                                     case "{":1394                                         next();1395                                         return subscripts(object_(), allow_calls);1396                                 }1397                                 unexpected();1398                         }1399                         if (is("keyword", "function")) {1400                                 next();1401                                 return subscripts(function_(false), allow_calls);1402                         }1403                         if (HOP(ATOMIC_START_TOKEN, S.token.type)) {1404                                 var atom = S.token.type == "regexp"1405                                         ? as("regexp", S.token.value[0], S.token.value[1])1406                                         : as(S.token.type, S.token.value);1407                                 return subscripts(prog1(atom, next), allow_calls);1408                         }1409                         unexpected();1410                 };1411 1412                 function expr_list(closing, allow_trailing_comma, allow_empty) {1413                         var first = true, a = [];1414                         while (!is("punc", closing)) {1415                                 if (first) first = false; else expect(",");1416                                 if (allow_trailing_comma && is("punc", closing)) break;1417                                 if (is("punc", ",") && allow_empty) {1418                                         a.push([ "atom", "undefined" ]);1419                                 } else {1420                                         a.push(expression(false));1421                                 }1422                         }1423                         next();1424                         return a;1425                 };1426 1427                 function array_() {1428                         return as("array", expr_list("]", !exigent_mode, true));1429                 };1430 1431                 function object_() {1432                         var first = true, a = [];1433                         while (!is("punc", "}")) {1434                                 if (first) first = false; else expect(",");1435                                 if (!exigent_mode && is("punc", "}"))1436                                         // allow trailing comma1437                                         break;1438                                 var type = S.token.type;1439                                 var name = as_property_name();1440                                 if (type == "name" && (name == "get" || name == "set") && !is("punc", ":")) {1441                                         a.push([ as_name(), function_(false), name ]);1442                                 } else {1443                                         expect(":");1444                                         a.push([ name, expression(false) ]);1445                                 }1446                         }1447                         next();1448                         return as("object", a);1449                 };1450 1451                 function as_property_name() {1452                         switch (S.token.type) {1453                             case "num":1454                             case "string":1455                                 return prog1(S.token.value, next);1456                         }1457                         return as_name();1458                 };1459 1460                 function as_name() {1461                         switch (S.token.type) {1462                             case "name":1463                             case "operator":1464                             case "keyword":1465                             case "atom":1466                                 return prog1(S.token.value, next);1467                             default:1468                                 unexpected();1469                         }1470                 };1471 1472                 function subscripts(expr, allow_calls) {1473                         if (is("punc", ".")) {1474                                 next();1475                                 return subscripts(as("dot", expr, as_name()), allow_calls);1476                         }1477                         if (is("punc", "[")) {1478                                 next();1479                                 return subscripts(as("sub", expr, prog1(expression, curry(expect, "]"))), allow_calls);1480                         }1481                         if (allow_calls && is("punc", "(")) {1482                                 next();1483                                 return subscripts(as("call", expr, expr_list(")")), true);1484                         }1485                         if (allow_calls && is("operator") && HOP(UNARY_POSTFIX, S.token.value)) {1486                                 return prog1(curry(make_unary, "unary-postfix", S.token.value, expr),1487                                              next);1488                         }1489                         return expr;1490                 };1491 1492                 function make_unary(tag, op, expr) {1493                         if ((op == "++" || op == "--") && !is_assignable(expr))1494                                 croak("Invalid use of " + op + " operator");1495                         return as(tag, op, expr);1496                 };1497 1498                 function expr_op(left, min_prec, no_in) {1499                         var op = is("operator") ? S.token.value : null;1500                         if (op && op == "in" && no_in) op = null;1501                         var prec = op != null ? PRECEDENCE[op] : null;1502                         if (prec != null && prec > min_prec) {1503                                 next();1504                                 var right = expr_op(expr_atom(true), prec, no_in);1505                                 return expr_op(as("binary", op, left, right), min_prec, no_in);1506                         }1507                         return left;1508                 };1509 1510                 function expr_ops(no_in) {1511                         return expr_op(expr_atom(true), 0, no_in);1512                 };1513 1514                 function maybe_conditional(no_in) {1515                         var expr = expr_ops(no_in);1516                         if (is("operator", "?")) {1517                                 next();1518                                 var yes = expression(false);1519                                 expect(":");1520                                 return as("conditional", expr, yes, expression(false, no_in));1521                         }1522                         return expr;1523                 };1524 1525                 function is_assignable(expr) {1526                         if (!exigent_mode) return true;1527                         switch (expr[0]) {1528                             case "dot":1529                             case "sub":1530                             case "new":1531                             case "call":1532                                 return true;1533                             case "name":1534                                 return expr[1] != "this";1535                         }1536                 };1537 1538                 function maybe_assign(no_in) {1539                         var left = maybe_conditional(no_in), val = S.token.value;1540                         if (is("operator") && HOP(ASSIGNMENT, val)) {1541                                 if (is_assignable(left)) {1542                                         next();1543                                         return as("assign", ASSIGNMENT[val], left, maybe_assign(no_in));1544                                 }1545                                 croak("Invalid assignment");1546                         }1547                         return left;1548                 };1549 1550                 function expression(commas, no_in) {1551                         if (arguments.length == 0)1552                                 commas = true;1553                         var expr = maybe_assign(no_in);1554                         if (commas && is("punc", ",")) {1555                                 next();1556                                 return as("seq", expr, expression(true, no_in));1557                         }1558                         return expr;1559                 };1560 1561                 function in_loop(cont) {1562                         try {1563                                 ++S.in_loop;1564                                 return cont();1565                         } finally {1566                                 --S.in_loop;1567                         }1568                 };1569 1570                 return as("toplevel", (function(a){1571                         while (!is("eof"))1572                                 a.push(statement());1573                         return a;1574                 })([]));1575 1576         };1577 1578         /* -----[ Utilities ]----- */1579 1580         function curry(f) {1581                 var args = slice(arguments, 1);1582                 return function() { return f.apply(this, args.concat(slice(arguments))); };1583         };1584 1585         function prog1(ret) {1586                 if (ret instanceof Function)1587                         ret = ret();1588                 for (var i = 1, n = arguments.length; --n > 0; ++i)1589                         arguments[i]();1590                 return ret;1591         };1592 1593         function array_to_hash(a) {1594                 var ret = {};1595                 for (var i = 0; i < a.length; ++i)1596                         ret[a[i]] = true;1597                 return ret;1598         };1599 1600         function slice(a, start) {1601                 return Array.prototype.slice.call(a, start == null ? 0 : start);1602         };1603 1604         function characters(str) {1605                 return str.split("");1606         };1607 1608         function member(name, array) {1609                 for (var i = array.length; --i >= 0;)1610                         if (array[i] === name)1611                                 return true;1612                 return false;1613         };1614 1615         function HOP(obj, prop) {1616                 return Object.prototype.hasOwnProperty.call(obj, prop);1617         };1618 1619         var warn = function() {};1620 1621         return parse;1622 1623     })();1624     1625     var Wind;1626     1627     var codeGenerator = (typeof eval("(function () {})") == "function") ?1628         function (code) { return code; } :1629         function (code) { return "false || " + code; };1630         1631     // support string type only.1632     var stringify = (typeof JSON !== "undefined" && JSON.stringify) ?1633         function (s) { return JSON.stringify(s); } :1634         (function () {1635             // Implementation comes from JSON2 (http://www.json.org/js.html)1636         1637             var escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;1638             1639             var meta = {    // table of character substitutions1640                 ‘\b‘: ‘\\b‘,1641                 ‘\t‘: ‘\\t‘,1642                 ‘\n‘: ‘\\n‘,1643                 ‘\f‘: ‘\\f‘,1644                 ‘\r‘: ‘\\r‘,1645                 ‘"‘ : ‘\\"‘,1646                 ‘\\‘: ‘\\\\‘1647             }1648             1649             return function (s) {1650                 // If the string contains no control characters, no quote characters, and no1651                 // backslash characters, then we can safely slap some quotes around it.1652                 // Otherwise we must also replace the offending characters with safe escape1653                 // sequences.1654 1655                 escapable.lastIndex = 0;1656                 return escapable.test(s) ? ‘"‘ + s.replace(escapable, function (a) {1657                     var c = meta[a];1658                     return typeof c === ‘s‘ ? c :1659                         ‘\\u‘ + (‘0000‘ + a.charCodeAt(0).toString(16)).slice(-4);1660                 }) + ‘"‘ : ‘"‘ + s + ‘"‘;1661             };1662         })();1663     1664     function sprintf(format) {1665         var args = arguments;1666         return format.toString().replace(new RegExp("{\\d+}", "g"), function (p) {1667             var n = parseInt(p.substring(1, p.length - 1), 10);1668             return args[n + 1];1669         });1670     }1671     1672     function trim(s) {1673         return s.replace(/ +/g, "");1674     }1675 1676     function getPrecedence(ast) {1677         var type = ast[0];1678         switch (type) {1679             case "dot": // .1680             case "sub": // []1681             case "call": // ()1682                 return 1;1683             case "unary-postfix": // ++ -- - ~ ! delete new typeof void1684             case "unary-prefix":1685                 return 2;1686             case "var":1687             case "binary":1688                 switch (ast[1]) {1689                     case "*":1690                     case "/":1691                     case "%":1692                         return 3;1693                     case "+":1694                     case "-":1695                         return 4;1696                     case "<<":1697                     case ">>":1698                     case ">>>":1699                         return 5;1700                     case "<":1701                     case "<=":1702                     case ">":1703                     case ">=":1704                     case "instanceof":1705                         return 6;1706                     case "==":1707                     case "!=":1708                     case "===":1709                     case "!==":1710                         return 7;1711                     case "&":1712                         return 8;1713                     case "^":1714                         return 9;1715                     case "|":1716                         return 10;1717                     case "&&":1718                         return 11;1719                     case "||":1720                         return 12;1721                 }1722             case "conditional":1723                 return 13;1724             case "assign":1725                 return 14;1726             case "new":1727                 return 15;1728             case "seq":1729             case "stat":1730             case "name":1731             case "object":1732             case "array":1733             case "num":1734             case "regexp":1735             case "string":1736             case "function":1737             case "defun":1738             case "for":1739             case "for-in":1740             case "block":1741             case "while":1742             case "do":1743             case "if":1744             case "break":1745             case "continue":1746             case "return":1747             case "throw":1748             case "try":1749             case "switch": 1750                 return 0;1751             default:1752                 return 100; // the lowest1753         }1754     }1755 1756     var CodeWriter = function (indent) {1757         this._indent = indent || "    ";1758         this._indentLevel = 0;1759         1760         this.lines = [];1761     }1762     CodeWriter.prototype = {1763         write: function (str) {1764             if (str === undefined) return;1765             1766             if (this.lines.length == 0) {1767                 this.lines.push("");1768             }1769 1770             this.lines[this.lines.length - 1] += str;1771             return this;1772         },1773         1774         writeLine: function () {1775             this.write.apply(this, arguments);1776             this.lines.push("");1777             return this;1778         },1779         1780         writeIndents: function () {1781             var indents = new Array(this._indentLevel);1782             for (var i = 0; i < this._indentLevel; i++) {1783                 indents[i] = this._indent;1784             }1785             1786             this.write(indents.join(""));1787             return this;1788         }, 1789         1790         addIndentLevel: function (diff) {1791             this._indentLevel += diff;1792             return this;1793         }1794     };1795     1796     var SeedProvider = function () {1797         this._seeds = {};1798     }1799     SeedProvider.prototype.next = function (key) {1800         var value = http://www.mamicode.com/this._seeds[key];1801         if (value =http://www.mamicode.com/= undefined) {1802             this._seeds[key] = 0;1803             return 0;1804         } else {1805             this._seeds[key] = ++value;1806             return value;1807         }1808     }1809     1810     function isWindPattern(ast) {1811         if (ast[0] != "call") return false;1812         1813         var evalName = ast[1];1814         if (evalName[0] != "name" || evalName[1] != "eval") return false;1815 1816         var compileCall = ast[2][0];1817         if (!compileCall || compileCall[0] != "call") return false;1818 1819         var compileMethod = compileCall[1];1820         if (!compileMethod || compileMethod[0] != "dot" || compileMethod[2] != "compile") return false;1821 1822         var windName = compileMethod[1];1823         if (!windName || windName[0] != "name" || windName[1] != compile.rootName) return false;1824 1825         var builder = compileCall[2][0];1826         if (!builder || builder[0] != "string") return false;1827 1828         var func = compileCall[2][1];1829         if (!func || func[0] != "function") return false;1830 1831         return true;1832     }1833     1834     function compileWindPattern(ast, seedProvider, codeWriter, commentWriter) {1835 1836         var builderName = ast[2][0][2][0][1];1837         var funcAst = ast[2][0][2][1];1838 1839         var windTreeGenerator = new WindTreeGenerator(builderName, seedProvider);1840         var windAst = windTreeGenerator.generate(funcAst);1841 1842         commentWriter.write(builderName + " << ");1843         var codeGenerator = new CodeGenerator(builderName, seedProvider, codeWriter, commentWriter);1844         1845         var funcName = funcAst[1] || "";1846         codeGenerator.generate(funcName, funcAst[2], windAst);1847         1848         return funcName;1849     }1850         1851     var WindTreeGenerator = function (builderName, seedProvider) {1852         this._binder = Wind.binders[builderName];1853         this._seedProvider = seedProvider;1854     }1855     WindTreeGenerator.prototype = {1856 1857         generate: function (ast) {1858 1859             var params = ast[2], statements = ast[3];1860 1861             var rootAst = { type: "delay", stmts: [] };1862 1863             this._visitStatements(statements, rootAst.stmts);1864 1865             return rootAst;1866         },1867 1868         _getBindInfo: function (stmt) {1869 1870             var type = stmt[0];1871             if (type == "stat") {1872                 var expr = stmt[1];1873                 if (expr[0] == "call") {1874                     var callee = expr[1];1875                     if (callee[0] == "name" && callee[1] == this._binder && expr[2].length == 1) {1876                         return {1877                             expression: expr[2][0],1878                             argName: "",1879                             assignee: null1880                         };1881                     }1882                 } else if (expr[0] == "assign") {1883                     var assignee = expr[2];1884                     expr = expr[3];1885                     if (expr[0] == "call") {1886                         var callee = expr[1];1887                         if (callee[0] == "name" && callee[1] == this._binder && expr[2].length == 1) {1888                             return {1889                                 expression: expr[2][0],1890                                 argName: "_result_$",1891                                 assignee: assignee1892                             };1893                         }1894                     }1895                 }1896             } else if (type == "var") {1897                 var defs = stmt[1];1898                 if (defs.length == 1) {1899                     var item = defs[0];1900                     var name = item[0];1901                     var expr = item[1];1902                     if (expr && expr[0] == "call") {1903                         var callee = expr[1];1904                         if (callee[0] == "name" && callee[1] == this._binder && expr[2].length == 1) {1905                             return {1906                                 expression: expr[2][0],1907                                 argName: name,1908                                 assignee: null1909                             };                            1910                         }1911                     }1912                 }1913             } else if (type == "return") {1914                 var expr = stmt[1];1915                 if (expr && expr[0] == "call") {1916                     var callee = expr[1];1917                     if (callee[0] == "name" && callee[1] == this._binder && expr[2].length == 1) {1918                         return {1919                             expression: expr[2][0],1920                             argName: "_result_$",1921                             assignee: "return"1922                         };1923                     }1924                 }1925             }1926 1927             return null;1928         },1929 1930         _visitStatements: function (statements, stmts, index) {1931             if (arguments.length <= 2) index = 0;1932 1933             if (index >= statements.length) {1934                 stmts.push({ type: "normal" });1935                 return this;1936             }1937 1938             var currStmt = statements[index];1939             var bindInfo = this._getBindInfo(currStmt);1940 1941             if (bindInfo) {1942                 var bindStmt = { type: "bind", info: bindInfo };1943                 stmts.push(bindStmt);1944 1945                 if (bindInfo.assignee != "return") {1946                     bindStmt.stmts = [];1947                     this._visitStatements(statements, bindStmt.stmts, index + 1);1948                 }1949 1950             } else {1951                 var type = currStmt[0];1952                 if (type == "return" || type == "break" || type == "continue" || type == "throw") {1953 1954                     stmts.push({ type: type, stmt: currStmt });1955 1956                 } else if (type == "if" || type == "try" || type == "for" || type == "do"1957                            || type == "while" || type == "switch" || type == "for-in") {1958 1959                     var newStmt = this._visit(currStmt);1960 1961                     if (newStmt.type == "raw") {1962                         stmts.push(newStmt);1963                         this._visitStatements(statements, stmts, index + 1);1964                     } else {1965                         var isLast = (index == statements.length - 1);1966                         if (isLast) {1967                             stmts.push(newStmt);1968                         } else {1969 1970                             var combineStmt = {1971                                 type: "combine",1972                                 first: { type: "delay", stmts: [newStmt] },1973                                 second: { type: "delay", stmts: [] }1974                             };1975                             stmts.push(combineStmt);1976 1977                             this._visitStatements(statements, combineStmt.second.stmts, index + 1);1978                         }1979                     }1980 1981                 } else {1982 1983                     stmts.push({ type: "raw", stmt: currStmt });1984 1985                     this._visitStatements(statements, stmts, index + 1);1986                 }1987             }1988 1989             return this;1990         },1991 1992         _visit: function (ast) {1993 1994             var type = ast[0];1995 1996             function throwUnsupportedError() {1997                 throw new Error(‘"‘ + type + ‘" is not currently supported.‘);1998             }1999 2000             var visitor = this._visitors[type];2001 2002             if (visitor) {2003                 return visitor.call(this, ast);2004             } else {2005                 throwUnsupportedError();2006             }2007         },2008 2009         _visitBody: function (ast, stmts) {2010             if (ast[0] == "block") {2011                 this._visitStatements(ast[1], stmts);2012             } else {2013                 this._visitStatements([ast], stmts);2014             }2015         },2016 2017         _noBinding: function (stmts) {2018             switch (stmts[stmts.length - 1].type) {2019                 case "normal":2020                 case "return":2021                 case "break":2022                 case "throw":2023                 case "continue":2024                     return true;2025             }2026 2027             return false;2028         },2029 2030         _collectCaseStatements: function (cases, index) {2031             var res = [];2032 2033             for (var i = index; i < cases.length; i++) {2034                 var rawStmts = cases[i][1];2035                 for (var j = 0; j < rawStmts.length; j++) {2036                     if (rawStmts[j][0] == "break") {2037                         return res2038                     }2039 2040                     res.push(rawStmts[j]);2041                 }2042             }2043 2044             return res;2045         },2046 2047         _visitors: {2048 2049             "for": function (ast) {2050                 var bodyStmts = [];2051                 var body = ast[4];2052                 this._visitBody(body, bodyStmts);2053 2054                 if (this._noBinding(bodyStmts)) {2055                     return { type: "raw", stmt: ast };2056                 }2057                 2058                 var delayStmt = { type: "delay", stmts: [] };2059                 2060                 var setup = ast[1];2061                 if (setup) {2062                     delayStmt.stmts.push({ type: "raw", stmt: setup });2063                 }2064                 2065                 var forStmt = { type: "for", bodyStmt: { type: "delay", stmts: bodyStmts } };2066                 delayStmt.stmts.push(forStmt);2067                 2068                 var condition = ast[2];2069                 if (condition) {2070                     forStmt.condition = condition;2071                 }2072                 2073                 var update = ast[3];2074                 if (update) {2075                     forStmt.update = update;2076                 }2077 2078                 return delayStmt;2079             },2080             2081             "for-in": function (ast) {2082 2083                 var body = ast[4];2084                 2085                 var bodyStmts = [];2086                 this._visitBody(body, bodyStmts);2087 2088                 if (this._noBinding(bodyStmts)) {2089                     return { type: "raw", stmt: ast };2090                 }2091                 2092                 var forInStmt = { type: "for-in", bodyStmts: bodyStmts, obj: ast[3] };2093             2094                 var argName = ast[2][1]; // ast[2] == ["name", m]2095                 if (ast[1][0] == "var") {2096                     forInStmt.argName = argName;2097                 } else {2098                     var keyVar = "_forInKey_$" + this._seedProvider.next("forInKey");2099                     forInStmt.argName = keyVar;2100                     forInStmt.bodyStmts.unshift({2101                         type: "raw",2102                         stmt: parse(argName + " = " + keyVar + ";")[1][0]2103                     });2104                 }2105             2106                 return forInStmt;2107             },2108         2109             "while": function (ast) {2110 2111                 var bodyStmts = [];2112                 var body = ast[2];2113                 this._visitBody(body, bodyStmts);2114 2115                 if (this._noBinding(bodyStmts)) {2116                     return { type: "raw", stmt: ast }2117                 }2118 2119                 var loopStmt = { type: "while", bodyStmt: { type: "delay", stmts: bodyStmts } };2120 2121                 var condition = ast[1];2122                 loopStmt.condition = condition;2123 2124                 return loopStmt;2125             },2126             2127             "do": function (ast) {2128 2129                 var bodyStmts = [];2130                 var body = ast[2];2131                 this._visitBody(body, bodyStmts);2132 2133                 if (this._noBinding(bodyStmts)) {2134                     return { type: "raw", stmt: ast };2135                 }2136 2137                 var doStmt = {2138                     type: "do",2139                     bodyStmt: { type: "delay", stmts: bodyStmts },2140                     condition: ast[1]2141                 };2142 2143                 return doStmt;2144             },2145 2146             "switch": function (ast) {2147                 var noBinding = true;2148 2149                 var switchStmt = { type: "switch", item: ast[1], caseStmts: [] };2150 2151                 var cases = ast[2];2152                 for (var i = 0; i < cases.length; i++) {                    2153                     var caseStmt = { item: cases[i][0], stmts: [] };2154                     switchStmt.caseStmts.push(caseStmt);2155 2156                     var statements = this._collectCaseStatements(cases, i);2157                     this._visitStatements(statements, caseStmt.stmts);2158                     noBinding = noBinding && this._noBinding(caseStmt.stmts);2159                 }2160 2161                 if (noBinding) {2162                     return { type: "raw", stmt: ast };2163                 } else {2164                     return switchStmt;2165                 }2166             },2167 2168             "if": function (ast) {2169 2170                 var noBinding = true;2171 2172                 var ifStmt = { type: "if", conditionStmts: [] };2173 2174                 var currAst = ast;2175                 while (true) {2176                     var condition = currAst[1];2177                     var condStmt = { cond: condition, stmts: [] };2178                     ifStmt.conditionStmts.push(condStmt);2179 2180                     var thenPart = currAst[2];2181                     this._visitBody(thenPart, condStmt.stmts);2182 2183                     noBinding = noBinding && this._noBinding(condStmt.stmts);2184 2185                     var elsePart = currAst[3];2186                     if (elsePart && elsePart[0] == "if") {2187                         currAst = elsePart;2188                     } else {2189                         break;2190                     }2191                 }2192     2193                 var elsePart = currAst[3];2194                 if (elsePart) {2195                     ifStmt.elseStmts = [];2196 2197                     this._visitBody(elsePart, ifStmt.elseStmts);2198                     2199                     noBinding = noBinding && this._noBinding(ifStmt.elseStmts);2200                 }2201 2202                 if (noBinding) {2203                     return { type: "raw", stmt: ast };2204                 } else {2205                     return ifStmt;2206                 }2207             },2208 2209             "try": function (ast, stmts) {2210 2211                 var bodyStmts = [];2212                 var bodyStatements = ast[1];2213                 this._visitStatements(bodyStatements, bodyStmts);2214 2215                 var noBinding = this._noBinding(bodyStmts)2216 2217                 var tryStmt = { type: "try", bodyStmt: { type: "delay", stmts: bodyStmts } };2218                 2219                 var catchClause = ast[2];2220                 if (catchClause) {2221                     var exVar = catchClause[0];2222                     tryStmt.exVar = exVar;2223                     tryStmt.catchStmts = [];2224 2225                     this._visitStatements(catchClause[1], tryStmt.catchStmts);2226 2227                     noBinding = noBinding && this._noBinding(tryStmt.catchStmts);2228                 }2229 2230                 var finallyStatements = ast[3];2231                 if (finallyStatements) {2232                     tryStmt.finallyStmt = { type: "delay", stmts: [] };2233 2234                     this._visitStatements(finallyStatements, tryStmt.finallyStmt.stmts);2235 2236                     noBinding = noBinding && this._noBinding(tryStmt.finallyStmt.stmts);2237                 }2238 2239                 if (noBinding) {2240                     return { type: "raw", stmt: ast };2241                 } else {2242                     return tryStmt;2243                 }2244             }2245         }2246     }2247     2248     var CodeGenerator = function (builderName, seedProvider, codeWriter, commentWriter) {2249         this._builderName = builderName;2250         this._binder = Wind.binders[builderName];2251         this._seedProvider = seedProvider;2252         2253         this._codeWriter = codeWriter;2254         this._commentWriter = commentWriter;2255     }2256     CodeGenerator.prototype = {2257     2258         _code: function () {2259             this._codeWriter.write.apply(this._codeWriter, arguments);2260             return this;2261         },2262         2263         _codeLine: function () {2264             this._codeWriter.writeLine.apply(this._codeWriter, arguments);2265             return this;2266         },2267         2268         _codeIndents: function () {2269             this._codeWriter.writeIndents();2270             return this;2271         },2272         2273         _codeIndentLevel: function (diff) {2274             this._codeWriter.addIndentLevel(diff);2275             return this;2276         },2277         2278         _comment: function () {2279             this._commentWriter.write.apply(this._commentWriter, arguments);2280             return this;2281         },2282         2283         _commentLine: function () {2284             this._commentWriter.writeLine.apply(this._commentWriter, arguments);2285             return this;2286         },2287         2288         _commentIndents: function () {2289             this._commentWriter.writeIndents();2290             return this;2291         },2292         2293         _commentIndentLevel: function (diff) {2294             this._commentWriter.addIndentLevel(diff);2295             return this;2296         },2297         2298         _both: function () {2299             this._codeWriter.write.apply(this._codeWriter, arguments);2300             this._commentWriter.write.apply(this._commentWriter, arguments);2301 2302             return this;2303         },2304         2305         _bothLine: function () {2306             this._codeWriter.writeLine.apply(this._codeWriter, arguments);2307             this._commentWriter.writeLine.apply(this._commentWriter, arguments);2308             2309             return this;2310         },2311         2312         _bothIndents: function () {2313             this._codeWriter.writeIndents();2314             this._commentWriter.writeIndents();2315             2316             return this;2317         },2318         2319         _bothIndentLevel: function (diff) {2320             this._codeWriter.addIndentLevel(diff);2321             this._commentWriter.addIndentLevel(diff);2322             2323             return this;2324         },2325         2326         _newLine: function () {2327             this._codeWriter.writeLine.apply(this._codeWriter, arguments);2328             this._commentWriter.writeLine(); // To Remove2329             return this;2330         },2331     2332         generate: function (name, params, windAst) {2333             this._normalMode = false;2334             this._builderVar = "_builder_$" + this._seedProvider.next("builderId");2335             2336             this._codeLine("(function " + name + "(" + params.join(", ") + ") {")._commentLine("function (" + params.join(", ") + ") {");2337             this._bothIndentLevel(1);2338 2339             this._codeIndents()._newLine("var " + this._builderVar + " = " + compile.rootName + ".builders[" + stringify(this._builderName) + "];");2340 2341             this._codeIndents()._newLine("return " + this._builderVar + ".Start(this,");2342             this._codeIndentLevel(1);2343 2344             this._pos = { };2345 2346             this._bothIndents()._visitWind(windAst)._newLine();2347             this._codeIndentLevel(-1);2348 2349             this._codeIndents()._newLine(");");2350             this._bothIndentLevel(-1);2351 2352             this._bothIndents()._code("})")._comment("}");2353         },2354 2355         _visitWind: function (ast) {2356             this._windVisitors[ast.type].call(this, ast);2357             return this;2358         },2359 2360         _visitRaw: function (ast) {2361             var type = ast[0];2362 2363             var visitor = this._rawVisitors[type];2364             if (visitor) {2365                 visitor.call(this, ast);2366             } else {2367                 throw new Error(‘"‘ + type + ‘" is not currently supported.‘);2368             }2369 2370             return this;2371         },2372 2373         _visitWindStatements: function (statements) {2374             for (var i = 0; i < statements.length; i++) {2375                 var stmt = statements[i];2376 2377                 if (stmt.type == "raw" || stmt.type == "if" || stmt.type == "switch") {2378                     this._bothIndents()._visitWind(stmt)._newLine();2379                 } else if (stmt.type == "delay") {2380                     this._visitWindStatements(stmt.stmts);2381                 } else {2382                     this._bothIndents()._code("return ")._visitWind(stmt)._newLine(";");2383                 }2384             }2385         },2386 2387         _visitRawStatements: function (statements) {2388             for (var i = 0; i < statements.length; i++) {2389                 var s = statements[i];2390 2391                 this._bothIndents()._visitRaw(s)._bothLine();2392 2393                 switch (s[0]) {2394                     case "break":2395                     case "return":2396                     case "continue":2397                     case "throw":2398                         return;2399                 }2400             }2401         },2402 2403         _visitRawBody: function (body) {2404             if (body[0] == "block") {2405                 this._visitRaw(body);2406             } else {2407                 this._bothLine();2408                 this._bothIndentLevel(1);2409 2410                 this._bothIndents()._visitRaw(body);2411                 this._bothIndentLevel(-1);2412             }2413 2414             return this;2415         },2416 2417         _visitRawFunction: function (ast) {2418             var funcName = ast[1] || "";2419             var args = ast[2];2420             var statements = ast[3];2421             2422             this._bothLine("function " + funcName + "(" + args.join(", ") + ") {")2423             this._bothIndentLevel(1);2424 2425             var currInFunction = this._pos.inFunction;2426             this._pos.inFunction = true;2427 2428             this._visitRawStatements(statements);2429             this._bothIndentLevel(-1);2430 2431             this._pos.inFunction = currInFunction;2432 2433             this._bothIndents()._both("}");2434         },2435         2436         _windVisitors: {2437             "delay": function (ast) {2438                 if (ast.stmts.length == 1) {2439                     var subStmt = ast.stmts[0];2440                     switch (subStmt.type) {2441                         case "delay":2442                         case "combine":2443                         case "normal":2444                         case "break":2445                         case "continue":2446                         case "for":2447                         case "for-in":2448                         case "while":2449                         case "do":2450                         case "try":2451                             this._visitWind(subStmt);2452                             return;2453                         case "return":2454                             if (!subStmt.stmt[1]) {2455                                 this._visitWind(subStmt);2456                                 return;2457                             }2458                     }2459                 }2460 2461                 this._newLine(this._builderVar + ".Delay(function () {");2462                 this._codeIndentLevel(1);2463 2464                 this._visitWindStatements(ast.stmts);2465                 this._codeIndentLevel(-1);2466 2467                 this._codeIndents()._code("})");2468             },2469 2470             "combine": function (ast) {2471                 this._newLine(this._builderVar + ".Combine(");2472                 this._codeIndentLevel(1);2473 2474                 this._bothIndents()._visitWind(ast.first)._newLine(",");2475                 this._bothIndents()._visitWind(ast.second)._newLine();2476                 this._codeIndentLevel(-1);2477 2478                 this._codeIndents()._code(")");2479             },2480             2481             "for": function (ast) {                2482                 if (ast.condition) {2483                     this._codeLine(this._builderVar + ".For(function () {")2484                         ._commentLine("for (");2485                     this._codeIndentLevel(1);2486                     2487                     this._bothIndents()2488                         ._code("return ")2489                         ._comment("; ")2490                             ._visitRaw(ast.condition)2491                                 ._newLine(";");2492                     this._codeIndentLevel(-1);2493                     2494                     this._bothIndents()._code("}, ");2495                 } else {2496                     this._code(this._builderVar + ".For(null, ")2497                         ._comment("for (; ");2498                 }2499                 2500                 if (ast.update) {2501                     this._newLine("function () {");2502                     this._codeIndentLevel(1);2503                     2504                     this._bothIndents()2505                         ._comment("; ")2506                             ._visitRaw(ast.update)2507                                 ._codeLine(";")2508                                 ._commentLine(") {");2509                     this._codeIndentLevel(-1);2510                     2511                     this._codeIndents()._newLine("},");2512                 } else {2513                     this._codeLine("null,")._commentLine("; ) {");2514                 }2515                 this._bothIndentLevel(1);2516                 2517                 this._bothIndents()._visitWind(ast.bodyStmt)._newLine();2518                 this._bothIndentLevel(-1);2519                 2520                 this._bothIndents()._code(")")._comment("}");2521             },2522             2523             "for-in": function (ast) {2524                 this._code(this._builderVar + ".ForIn(")2525                     ._comment("for (var " + ast.argName + " in ")2526                         ._visitRaw(ast.obj)2527                             ._codeLine(", function (" + ast.argName + ") {")2528                             ._commentLine(") {");2529                 this._bothIndentLevel(1);2530                 2531                 this._visitWindStatements(ast.bodyStmts);2532                 this._bothIndentLevel(-1);2533                 2534                 this._bothIndents()._code("})")._comment("}");2535             },2536             2537             "while": function (ast) {2538                 this._newLine(this._builderVar + ".While(function () {");2539                 this._codeIndentLevel(1);2540                 2541                 this._bothIndents()2542                     ._code("return ")2543                     ._comment("while (")2544                         ._visitRaw(ast.condition)2545                             ._codeLine(";")2546                             ._commentLine(") {");2547                 this._codeIndentLevel(-1);2548                 2549                 this._codeIndents()._newLine("},");2550                 this._bothIndentLevel(1);2551                 2552                 this._bothIndents()._visitWind(ast.bodyStmt)._newLine();2553                 this._bothIndentLevel(-1);2554                 2555                 this._bothIndents()._code(")")._comment("}");2556             },2557             2558             "do": function (ast) {2559                 this._codeLine(this._builderVar + ".Do(")._commentLine("do {");2560                 this._bothIndentLevel(1);2561                 2562                 this._bothIndents()._visitWind(ast.bodyStmt)._newLine(",");2563                 this._commentIndentLevel(-1);2564                 2565                 this._codeIndents()._newLine("function () {");2566                 this._codeIndentLevel(1);2567                 2568                 this._bothIndents()2569                     ._code("return ")2570                     ._comment("} while (")2571                         ._visitRaw(ast.condition)2572                             ._codeLine(";")2573                             ._commentLine(");");2574                 this._codeIndentLevel(-1);2575                 2576                 this._codeIndents()._newLine("}");2577                 this._codeIndentLevel(-1);2578                 2579                 this._codeIndents()._code(")");2580             },2581 2582             "raw": function (ast) {2583                 this._visitRaw(ast.stmt, true);2584             },2585 2586             "bind": function (ast) {2587                 var info = ast.info;2588                 2589                 var commentPrefix = "";2590                 if (info.assignee == "return") {2591                     commentPrefix = "return ";2592                 } else if (info.argName != "") {2593                     commentPrefix = "var " + info.argName + " = ";2594                 }2595                 2596                 this._code(this._builderVar + ".Bind(")._comment(commentPrefix + this._binder + "(")._visitRaw(info.expression)._comment(");")._newLine(", function (" + info.argName + ") {");2597                 this._codeIndentLevel(1);2598 2599                 if (info.assignee == "return") {2600                     this._codeIndents()2601                         ._newLine("return " + this._builderVar + ".Return(" + info.argName + ");");2602                 } else {2603                     if (info.assignee) {2604                         this._bothIndents()2605                             ._visitRaw(info.assignee)._bothLine(" = " + info.argName + ";");2606                     }2607 2608                     this._visitWindStatements(ast.stmts);2609                 }2610                 this._codeIndentLevel(-1);2611 2612                 this._codeIndents()2613                     ._code("})");2614             },2615 2616             "if": function (ast) {2617 2618                 for (var i = 0; i < ast.conditionStmts.length; i++) {2619                     var stmt = ast.conditionStmts[i];2620                     2621                     this._both("if (")._visitRaw(stmt.cond)._bothLine(") {");2622                     this._bothIndentLevel(1);2623 2624                     this._visitWindStatements(stmt.stmts);2625                     this._bothIndentLevel(-1);2626 2627                     if (i < ast.conditionStmts.length - 1 || ast.elseStmts) {2628                         this._bothIndents()._both("} else ");2629                     } else {2630                         this._bothIndents()._code("} else ")._comment("}");2631                     }2632                 }2633 2634                 if (ast.elseStmts) {2635                     this._bothLine("{");2636                     this._bothIndentLevel(1);2637                 } else {2638                     this._newLine("{");2639                     this._codeIndentLevel(1);2640                 }2641 2642                 if (ast.elseStmts) {2643                     this._visitWindStatements(ast.elseStmts);2644                 } else {2645                     this._codeIndents()2646                         ._newLine("return " + this._builderVar + ".Normal();");2647                 }2648 2649                 if (ast.elseStmts) {2650                     this._bothIndentLevel(-1);2651                 } else {2652                     this._codeIndentLevel(-1);2653                 }2654 2655                 if (ast.elseStmts) {2656                     this._bothIndents()2657                         ._both("}");2658                 } else {2659                     this._codeIndents()2660                         ._code("}");2661                 }2662             },2663 2664             "switch": function (ast) {2665                 this._both("switch (")._visitRaw(ast.item)._bothLine(") {");2666                 this._bothIndentLevel(1);2667 2668                 for (var i = 0; i < ast.caseStmts.length; i++) {2669                     var caseStmt = ast.caseStmts[i];2670                     2671                     if (caseStmt.item) {2672                         this._bothIndents()2673                             ._both("case ")._visitRaw(caseStmt.item)._bothLine(":");2674                     } else {2675                         this._bothIndents()._bothLine("default:");2676                     }2677                     this._bothIndentLevel(1);2678 2679                     this._visitWindStatements(caseStmt.stmts);                    2680                     this._bothIndentLevel(-1);2681                 }2682 2683                 this._bothIndents()._code("}");2684             },2685 2686             "try": function (ast) {2687                 this._codeLine(this._builderVar + ".Try(")._commentLine("try {");2688                 this._bothIndentLevel(1);2689 2690                 this._bothIndents()._visitWind(ast.bodyStmt)._newLine(",");2691                 this._commentIndentLevel(-1);2692                 2693                 if (ast.catchStmts) {2694                     this._bothIndents()2695                         ._codeLine("function (" + ast.exVar + ") {")2696                         ._commentLine("} catch (" + ast.exVar + ") {");2697                     this._bothIndentLevel(1);2698 2699                     this._visitWindStatements(ast.catchStmts);2700                     this._bothIndentLevel(-1);2701 2702                     this._bothIndents()._codeLine("},");2703                     if (ast.finallyStmt) {2704                         this._commentLine("} finally {");2705                     } else {2706                         this._commentLine("}");2707                     }2708                 } else {2709                     this._bothIndents()._codeLine("null,")._commentLine("} finally {");2710                 }2711                 2712                 if (ast.finallyStmt) {2713                     this._commentIndentLevel(1);2714                     this._bothIndents()._visitWind(ast.finallyStmt)._newLine();2715                     this._commentIndentLevel(-1);2716                 } else {2717                     this._codeIndents()._newLine("null");2718                 }2719                 this._codeIndentLevel(-1);2720                 2721                 this._codeIndents()._code(")");2722                 if (ast.finallyStmt) {2723                     this._commentIndents()._comment("}");2724                 }2725             },2726 2727             "normal": function (ast) {2728                 this._code(this._builderVar + ".Normal()");2729             },2730 2731             "throw": function (ast) {2732                 this2733                     ._code(this._builderVar + ".Throw(")2734                     ._comment("throw ")2735                         ._visitRaw(ast.stmt[1])2736                             ._code(")")._comment(";");2737             },2738 2739             "break": function (ast) {2740                 this._code(this._builderVar + ".Break()")._comment("break;");2741             },2742 2743             "continue": function (ast) {2744                 this._code(this._builderVar + ".Continue()")._comment("continue;");2745             },2746 2747             "return": function (ast) {2748                 this._code(this._builderVar + ".Return(")._comment("return");2749                 if (ast.stmt[1]) {2750                     this._comment(" ")._visitRaw(ast.stmt[1]);2751                 }2752                 2753                 this._code(")")._comment(";");2754             }2755         },2756 2757         _rawVisitors: {2758             "var": function (ast) {2759                 this._both("var ");2760 2761                 var items = ast[1];2762                 for (var i = 0; i < items.length; i++) {2763                     this._both(items[i][0]);2764                     if (items[i].length > 1) {2765                         this._both(" = ")._visitRaw(items[i][1]);2766                     }2767                     if (i < items.length - 1) this._both(", ");2768                 }2769 2770                 this._both(";");2771             },2772 2773             "seq": function (ast, noBracket) {2774                 var left = ast[1];2775                 var right = ast[2];2776                 2777                 if (!noBracket) this._both("(");2778                 2779                 this._visitRaw(left);2780                 this._both(", ");2781                 2782                 if (right[0] == "seq") {2783                     arguments.callee.call(this, right, true);2784                 } else {2785                     this._visitRaw(right);2786                 }2787                 2788                 if (!noBracket) this._both(")");2789             },2790 2791             "binary": function (ast) {2792                 var op = ast[1], left = ast[2], right = ast[3];2793 2794                 if (getPrecedence(ast) < getPrecedence(left)) {2795                     this._both("(")._visitRaw(left)._both(") ");2796                 } else {2797                     this._visitRaw(left)._both(" ");2798                 }2799 2800                 this._both(op);2801 2802                 if (getPrecedence(ast) <= getPrecedence(right)) {2803                     this._both(" (")._visitRaw(right)._both(")");2804                 } else {2805                     this._both(" ")._visitRaw(right);2806                 }2807             },2808 2809             "sub": function (ast) {2810                 var prop = ast[1], index = ast[2];2811 2812                 if (getPrecedence(ast) < getPrecedence(prop)) {2813                     this._both("(")._visitRaw(prop)._both(")[")._visitRaw(index)._both("]");2814                 } else {2815                     this._visitRaw(prop)._both("[")._visitRaw(index)._both("]");2816                 }2817             },2818 2819             "unary-postfix": function (ast) {2820                 var op = ast[1];2821                 var item = ast[2];2822                 2823                 if (getPrecedence(ast) <= getPrecedence(item)) {2824                     this._both("(")._visitRaw(item)._both(")");2825                 } else {2826                     this._visitRaw(item);2827                 }2828                 2829                 this._both(" " + op);2830             },2831 2832             "unary-prefix": function (ast) {2833                 var op = ast[1];2834                 var item = ast[2];2835                 2836                 this._both(op + " ");2837                 2838                 if (getPrecedence(ast) < getPrecedence(item)) {2839                     this._both("(")._visitRaw(item)._both(")");2840                 } else {2841                     this._visitRaw(item);2842                 }2843             },2844 2845             "assign": function (ast) {2846                 var op = ast[1];2847                 var name = ast[2];2848                 var value = http://www.mamicode.com/ast[3];2849                 2850                 if (name[0] == "assign") {2851                     this._both("(")._visitRaw(name)._both(")");2852                 } else {2853                     this._visitRaw(name);2854                 }2855                 2856                 if ((typeof op) == "string") {2857                     this._both(" " + op + "= ");2858                 } else {2859                     this._both(" = ");2860                 }2861                 2862                 this._visitRaw(value);2863             },2864 2865             "stat": function (ast) {2866                 this._visitRaw(ast[1])._both(";");2867             },2868 2869             "dot": function (ast) {2870                 var left = ast[1];2871                 var right = ast[2];2872                 2873                 if (getPrecedence(ast) < getPrecedence(left)) {2874                     this._both("(")._visitRaw(left)._both(").")._both(right);2875                 } else {2876                     this._visitRaw(left)._both(".")._both(right);2877                 }2878             },2879 2880             "new": function (ast) {2881                 var ctor = ast[1];2882 2883                 this._both("new ")._visitRaw(ctor)._both("(");2884 2885                 var args = ast[2];2886                 for (var i = 0, len = args.length; i < len; i++) {2887                     this._visitRaw(args[i]);2888                     if (i < len - 1) this._both(", ");2889                 }2890 2891                 this._both(")");2892             },2893 2894             "call": function (ast) {2895             2896                 if (isWindPattern(ast)) {2897                     compileWindPattern(ast, this._seedProvider, this._codeWriter, this._commentWriter);2898                 } else {2899                     var caller = ast[1];2900                 2901                     var invalidBind = (caller[0] == "name") && (caller[1] == this._binder);2902                     // throw?2903 2904                     if (getPrecedence(ast) < getPrecedence(caller)) {2905                         this._both("(")._visitRaw(caller)._both(")");2906                     } else {2907                         this._visitRaw(caller);2908                     }2909                     2910                     this._both("(");2911 2912                     var args = ast[2];2913                     for (var i = 0; i < args.length; i++) {2914                         this._visitRaw(args[i]);2915                         if (i < args.length - 1) this._both(", ");2916                     }2917 2918                     this._both(")");2919                 }2920             },2921 2922             "name": function (ast) {2923                 this._both(ast[1]);2924             },2925 2926             "object": function (ast) {2927                 var items = ast[1];2928                 if (items.length <= 0) {2929                     this._both("{ }");2930                 } else {2931                     this._bothLine("{");2932                     this._bothIndentLevel(1);2933                     2934                     for (var i = 0; i < items.length; i++) {2935                         this._bothIndents()2936                             ._both(stringify(items[i][0]) + ": ")2937                             ._visitRaw(items[i][1]);2938                         2939                         if (i < items.length - 1) {2940                             this._bothLine(",");2941                         } else {2942                             this._bothLine("");2943                         }2944                     }2945                     2946                     this._bothIndentLevel(-1);2947                     this._bothIndents()._both("}");2948                 }2949             },2950 2951             "array": function (ast) {2952                 this._both("[");2953 2954                 var items = ast[1];2955                 for (var i = 0; i < items.length; i++) {2956                     this._visitRaw(items[i]);2957                     if (i < items.length - 1) this._both(", ");2958                 }2959 2960                 this._both("]");2961             },2962 2963             "num": function (ast) {2964                 this._both(ast[1]);2965             },2966 2967             "regexp": function (ast) {2968                 this._both("/" + ast[1] + "/" + ast[2]);2969             },2970 2971             "string": function (ast) {2972                 this._both(stringify(ast[1]));2973             },2974 2975             "function": function (ast) {2976                 this._visitRawFunction(ast);2977             },2978 2979             "defun": function (ast) {2980                 this._visitRawFunction(ast);2981             },2982             2983             "for": function (ast) {2984                 this._both("for (");2985 2986                 var setup = ast[1];2987                 if (setup) {2988                     this._visitRaw(setup);2989                     if (setup[0] != "var") {2990                         this._both("; ");2991                     } else {2992                         this._both(" ");2993                     }2994                 } else {2995                     this._both("; ");2996                 }2997 2998                 var condition = ast[2];2999                 if (condition) this._visitRaw(condition);3000                 this._both("; ");3001 3002                 var update = ast[3];3003                 if (update) this._visitRaw(update);3004                 this._both(") ");3005 3006                 var currInLoop = this._pos.inLoop;3007                 this._pos.inLoop = true;3008 3009                 var body = ast[4];3010                 this._visitRawBody(body);3011 3012                 this._pos.inLoop = currInLoop;3013             },3014 3015             "for-in": function (ast) {3016                 this._both("for (");3017 3018                 var declare = ast[1];3019                 if (declare[0] == "var") { // declare == ["var", [["m"]]]3020                     this._both("var " + declare[1][0][0]);3021                 } else {3022                     this._visitRaw(declare);3023                 }3024                 3025                 this._both(" in ")._visitRaw(ast[3])._both(") ");3026 3027                 var currInLoop = this._pos.inLoop;3028                 this._pos.inLoop = true;3029                 3030                 var body = ast[4];3031                 this._visitRawBody(body);3032 3033                 this._pos.inLoop = currInLoop;3034             },3035 3036             "block": function (ast) {3037                 if (ast.length > 1) {            3038                     this._bothLine("{")3039                     this._bothIndentLevel(1);3040 3041                     this._visitRawStatements(ast[1]);3042                     this._bothIndentLevel(-1);3043 3044                     this._bothIndents()3045                         ._both("}");3046                 } else {3047                     this._both(";");3048                 }3049             },3050 3051             "while": function (ast) {3052                 var condition = ast[1];3053                 var body = ast[2];3054 3055                 var currInLoop = this._pos.inLoop;3056                 this._pos.inLoop = true;3057 3058                 this._both("while (")._visitRaw(condition)._both(") ")._visitRawBody(body);3059 3060                 this._pos.inLoop = currInLoop;3061             },3062 3063             "do": function (ast) {3064                 var condition = ast[1];3065                 var body = ast[2];3066 3067                 var currInLoop = this._pos.inLoop;3068                 this._pos.inLoop = true;3069 3070                 this._both("do ")._visitRawBody(body);3071 3072                 this._pos.inLoop = currInLoop;3073 3074                 if (body[0] == "block") {3075                     this._both(" ");3076                 } else {3077                     this._bothLine()3078                         ._bothIndents();3079                 }3080 3081                 this._both("while (")._visitRaw(condition)._both(");");3082             },3083 3084             "if": function (ast) {3085                 var condition = ast[1];3086                 var thenPart = ast[2];3087 3088                 this._both("if (")._visitRaw(condition)._both(") ")._visitRawBody(thenPart);3089 3090                 var elsePart = ast[3];3091                 if (elsePart) {3092                     if (thenPart[0] == "block") {3093                         this._both(" ");3094                     } else {3095                         this._bothLine("")3096                             ._bothIndents();3097                     }3098 3099                     if (elsePart[0] == "if") {3100                         this._both("else ")._visitRaw(elsePart);3101                     } else {3102                         this._both("else ")._visitRawBody(elsePart);3103                     }3104                 }3105             },3106 3107             "break": function (ast) {3108                 if (this._pos.inLoop || this._pos.inSwitch) {3109                     this._both("break;");3110                 } else {3111                     this._code("return ")._visitWind({ type: "break", stmt: ast })._code(";");3112                 }3113             },3114 3115             "continue": function (ast) {3116                 if (this._pos.inLoop) {3117                     this._both("continue;");3118                 } else {3119                     this._code("return ")._visitWind({ type: "continue", stmt: ast })._code(";");3120                 }3121             },3122 3123             "return": function (ast) {3124                 if (this._pos.inFunction) {3125                     this._both("return");3126                     var value = http://www.mamicode.com/ast[1];3127                     if (value) this._both(" ")._visitRaw(value);3128                     this._both(";");3129                 } else {3130                     this._code("return ")._visitWind({ type: "return", stmt: ast })._code(";");3131                 }3132             },3133 3134             "throw": function (ast) {3135                 var pos = this._pos;3136                 if (pos.inTry || pos.inFunction) {3137                     this._both("throw ")._visitRaw(ast[1])._both(";");3138                 } else {3139                     this._code("return ")._visitWind({ type: "throw", stmt: ast })._code(";");3140                 }3141             },3142 3143             "conditional": function (ast) {3144                 this._both("(")._visitRaw(ast[1])._both(") ? (")._visitRaw(ast[2])._both(") : (")._visitRaw(ast[3])._both(")");3145             },3146 3147             "try": function (ast) {3148 3149                 this._bothLine("try {");3150                 this._bothIndentLevel(1);3151 3152                 var currInTry = this._pos.inTry;3153                 this._pos.inTry = true;3154 3155                 this._visitRawStatements(ast[1]);3156                 this._bothIndentLevel(-1);3157 3158                 this._pos.inTry = currInTry;3159 3160                 var catchClause = ast[2];3161                 var finallyStatements = ast[3];3162 3163                 if (catchClause) {3164                     this._bothIndents()3165                         ._bothLine("} catch (" + catchClause[0] + ") {")3166                     this._bothIndentLevel(1);3167 3168                     this._visitRawStatements(catchClause[1]);3169                     this._bothIndentLevel(-1);3170                 }3171 3172                 if (finallyStatements) {3173                     this._bothIndents()3174                         ._bothLine("} finally {");3175                     this._bothIndentLevel(1);3176 3177                     this._visitRawStatements(finallyStatements);3178                     this._bothIndentLevel(-1);3179                 }                3180 3181                 this._bothIndents()3182                     ._both("}");3183             },3184 3185             "switch": function (ast) {3186                 this._both("switch (")._visitRaw(ast[1])._bothLine(") {");3187                 this._bothIndentLevel(1);3188 3189                 var currInSwitch = this._pos.inSwitch;3190                 this._pos.inSwitch = true;3191 3192                 var cases = ast[2];3193                 for (var i = 0; i < cases.length; i++) {3194                     var c = cases[i];3195                     this._bothIndents();3196 3197                     if (c[0]) {3198                         this._both("case ")._visitRaw(c[0])._bothLine(":");3199                     } else {3200                         this._bothLine("default:");3201                     }3202                     this._bothIndentLevel(1);3203 3204                     this._visitRawStatements(c[1]);3205                     this._bothIndentLevel(-1);3206                 }3207                 this._bothIndentLevel(-1);3208 3209                 this._pos.inSwitch = currInSwitch;3210 3211                 this._bothIndents()3212                     ._both("}");3213             }3214         }3215     };3216     3217     var merge = function (commentLines, codeLines) {3218         var length = commentLines.length;3219         3220         var maxShift = 0;3221         3222         for (var i = 0; i < length; i++) {3223             var matches = codeLines[i].match(" +");3224             var spaceLength = matches ? matches[0].length : 0;3225             3226             var shift = commentLines[i].length - spaceLength + 10;3227             if (shift > maxShift) {3228                 maxShift = shift;3229             }3230         }3231         3232         var shiftBuffer = new Array(maxShift);3233         for (var i = 0; i < maxShift; i++) {3234             shiftBuffer[i] = " ";3235         }3236         3237         var shiftSpaces = shiftBuffer.join("");3238 3239         var buffer = [];3240         for (var i = 0; i < length; i++) {3241             var comment = commentLines[i]; 3242             if (comment.replace(/ +/g, "").length > 0) {3243                 comment = "/* " + comment + " */   ";3244             }3245             3246             var code = shiftSpaces + codeLines[i];3247             3248             buffer.push(comment);3249             buffer.push(code.substring(comment.length));3250             3251             if (i != length - 1) {3252                 buffer.push("\n");3253             }3254         }3255         3256         return buffer.join("");3257     }3258     3259     var sourceUrlSeed = 0;3260     3261     var getOptions = function (options) {3262         options = options || { };3263         options.root = options.root || "Wind";3264         options.noSourceUrl = options.noSourceUrl || false;3265         3266         return options;3267     }3268     3269     var compile = function (builderName, func, options) {3270         options = getOptions(options);3271         3272         var funcCode = func.toString();3273         var evalCode = "eval(" + compile.rootName + ".compile(" + stringify(builderName) + ", " + funcCode + "))"3274         var evalCodeAst = parse(evalCode);3275 3276         var codeWriter = new CodeWriter();3277         var commentWriter = new CodeWriter();3278         3279         // [ "toplevel", [ [ "stat", [ "call", ... ] ] ] ]3280         var evalAst = evalCodeAst[1][0][1];3281         var funcName = compileWindPattern(evalAst, new SeedProvider(), codeWriter, commentWriter);3282         3283         var newCode = merge(commentWriter.lines, codeWriter.lines);3284         if (!options.noSourceUrl) {3285             newCode += ("\n//@ sourceURL=wind/" + (sourceUrlSeed++) + "_" + (funcName || "anonymous") + ".js");3286         }3287         3288         Wind.logger.debug("// Original: \r\n" + funcCode + "\r\n\r\n// Compiled: \r\n" + newCode + "\r\n");3289         3290         return codeGenerator(newCode);3291     }3292 3293     compile.rootName = "Wind";3294 3295     // CommonJS3296     var isCommonJS = !!(typeof require === "function" && typeof module !== "undefined" && module.exports);3297     // CommonJS AMD3298     var isAmd = !!(typeof require === "function" && typeof define === "function" && define.amd);3299 3300     var defineModule = function () {3301         Wind.define({3302             name: "compiler",3303             version: "0.7.2",3304             require: isCommonJS && require,3305             dependencies: { core: "~0.7.0" },3306             init: function () {3307                 Wind.parse = parse;3308                 Wind.compile = compile;3309             }3310         });3311     }3312 3313     if (isCommonJS) {3314         try {3315             Wind = require("./wind-core");3316         } catch (ex) {3317             Wind = require("wind-core");3318         }3319         3320         defineModule();3321     } else if (isAmd) {3322         require(["wind-core"], function (wind) {3323             Wind = wind;3324             defineModule();3325         });3326     } else {3327         var Fn = Function, global = Fn(‘return this‘)();3328         if (!global.Wind) {3329             throw new Error(‘Missing the root object, please load "wind" component first.‘);3330         }3331         3332         Wind = global.Wind;3333         defineModule();3334     }3335 })();3336 3337 /***********************************************************************3338   wind-builderbase-0.7.0.js3339  ***********************************************************************/3340 3341 (function () {3342     "use strict";3343     3344     var BuilderBase = function () { }3345     BuilderBase.prototype = {3346         For: function (condition, update, body) {3347             return {3348                 next: function (_this, callback) {3349                     3350                     var loop = function (skipUpdate) {3351                         try {3352                             if (update && !skipUpdate) {3353                                 update.call(_this);3354                             }3355 3356                             if (!condition || condition.call(_this)) {3357                                 body.next(_this, function (type, value, target) {3358                                     if (type == "normal" || type == "continue") {3359                                         loop(false);3360                                     } else if (type == "throw" || type == "return") {3361                                         callback(type, value);3362                                     } else if (type == "break") {3363                                         callback("normal");3364                                     } else {3365                                         throw new Error(‘Invalid type for "Loop": ‘ + type);3366                                     }3367                                 });3368                             } else {3369                                 callback("normal");3370                             }3371                         } catch (ex) {3372                             callback("throw", ex);3373                         }3374                     }3375                     3376                     loop(true);3377                 }3378             };3379         },3380         3381         ForIn: function (obj, bodyGenerator) {3382             return {3383                 next: function (_this, callback) {3384                 3385                     var keys = [];3386                     for (var k in obj) {3387                         keys.push(k);3388                     }3389                     3390                     var loop = function (i) {3391                         try {3392                             if (i < keys.length) {3393                                 var body = bodyGenerator(keys[i]);3394                                 body.next(_this, function (type, value, target) {3395                                     if (type == "normal" || type == "continue") {3396                                         loop(i + 1);3397                                     } else if (type == "throw" || type == "return") {3398                                         callback(type, value);3399                                     } else if (type == "break") {3400                                         callback("normal");3401                                     } else {3402                                         throw new Error(‘Invalid type for "Loop": ‘ + type);3403                                     }3404                                 });3405                             } else {3406                                 callback("normal");3407                             }3408                         } catch (ex) {3409                             callback("throw", ex);3410                         }3411                     }3412                     3413                     loop(0);3414                 }3415             };3416         },3417         3418         While: function (condition, body) {3419             return {3420                 next: function (_this, callback) {3421                     var loop = function () {3422                         try {3423                             if (condition.call(_this)) {3424                                 body.next(_this, function (type, value, target) {3425                                     if (type == "normal" || type == "continue") {3426                                         loop();3427                                     } else if (type == "throw" || type == "return") {3428                                         callback(type, value);3429                                     } else if (type == "break") {3430                                         callback("normal");3431                                     } else {3432                                         throw new Error(‘Invalid type for "Loop": ‘ + type);3433                                     }3434                                 });3435                             } else {3436                                 callback("normal");3437                             }3438                         } catch (ex) {3439                             callback("throw", ex);3440                         }3441                     }3442                     3443                     loop();3444                 }3445             };3446         },3447         3448         Do: function (body, condition) {3449             return {3450                 next: function (_this, callback) {3451                 3452                     var loop = function () {3453                         body.next(_this, function (type, value, target) {3454                             if (type == "normal" || type == "continue") {3455                                 try {3456                                     if (condition.call(_this)) {3457                                         loop();3458                                     } else {3459                                         callback("normal");3460                                     }3461                                 } catch (ex) {3462                                     callback("throw", ex);3463                                 }3464                             } else if (type == "throw" || type == "return") {3465                                 callback(type, value);3466                             } else if (type == "break") {3467                                 callback("normal");3468                             } else {3469                                 throw new Error(‘Invalid type for "Loop": ‘ + type);3470                             }3471                         });3472                     };3473                 3474                     loop();3475                 }3476             };3477         },3478         3479         Delay: function (generator) {3480             return {3481                 next: function (_this, callback) {3482                     try {3483                         var step = generator.call(_this);3484                         step.next(_this, callback);3485                     } catch (ex) {3486                         callback("throw", ex);3487                     }3488                 }3489             };3490         },3491 3492         Combine: function (s1, s2) {3493             return {3494                 next: function (_this, callback) {3495                     s1.next(_this, function (type, value, target) {3496                         if (type == "normal") {3497                             try {3498                                 s2.next(_this, callback);3499                             } catch (ex) {3500                                 callback("throw", ex);3501                             }3502                         } else {3503                             callback(type, value, target);3504                         }3505                     });3506                 }3507             };3508         },3509 3510         Return: function (result) {3511             return {3512                 next: function (_this, callback) {3513                     callback("return", result);3514                 }3515             };3516         },3517 3518         Normal: function () {3519             return {3520                 next: function (_this, callback) {3521                     callback("normal");3522                 }3523             };3524         },3525 3526         Break: function () {3527             return {3528                 next: function (_this, callback) {3529                     callback("break");3530                 }3531             };3532         },3533 3534         Continue: function () {3535             return {3536                 next: function (_this, callback) {3537                     callback("continue");3538                 }3539             };3540         },3541 3542         Throw: function (ex) {3543             return {3544                 next: function (_this, callback) {3545                     callback("throw", ex);3546                 }3547             };3548         },3549 3550         Try: function (tryTask, catchGenerator, finallyStep) {3551             return {3552                 next: function (_this, callback) {3553                     tryTask.next(_this, function (type, value, target) {3554                         if (type != "throw" || !catchGenerator) {3555                             if (!finallyStep) {3556                                 callback(type, value, target);3557                             } else {3558                                 finallyStep.next(_this, function (finallyType, finallyValue, finallyTarget) {3559                                     if (finallyType == "normal") {3560                                         callback(type, value, target);3561                                     } else {3562                                         callback(finallyType, finallyValue, finallyTarget);3563                                     }3564                                 });3565                             }3566                         } else {3567 3568                             if (catchGenerator) {3569 3570                                 var catchTask;3571                                 try {3572                                     catchTask = catchGenerator.call(_this, value);3573                                 } catch (ex) {3574                                     if (finallyStep) {3575                                         finallyStep.next(_this, function (finallyType, finallyValue, finallyTarget) {3576                                             if (finallyType == "normal") {3577                                                 callback("throw", ex);3578                                             } else {3579                                                 callback(finallyType, finallyValue, finallyTarget);3580                                             }3581                                         });3582                                     } else {3583                                         callback("throw", ex);3584                                     }3585                                 }3586                                 3587                                 if (catchTask) {3588                                     catchTask.next(_this, function (catchType, catchValue, catchTarget) {3589                                         if (catchType == "throw") {3590                                             if (finallyStep) {3591                                                 finallyStep.next(_this, function (finallyType, finallyValue, finallyTarget) {3592                                                     if (finallyType == "normal") {3593                                                         callback(catchType, catchValue, catchTarget);3594                                                     } else {3595                                                         callback(finallyType, finallyValue, finallyTarget);3596                                                     }3597                                                 });3598                                             } else {3599                                                 callback(catchType, catchValue, catchTarget);3600                                             }3601                                         } else {3602                                             if (finallyStep) {3603                                                 finallyStep.next(_this, function (finallyType, finallyValue, finallyTarget) {3604                                                     if (finallyType == "normal") {3605                                                         callback(catchType, catchValue, catchTarget);3606                                                     } else {3607                                                         callback(finallyType, finallyValue, finallyTarget);3608                                                     }3609                                                 });3610                                             } else {3611                                                 callback(catchType, catchValue, catchTarget);3612                                             }3613                                         }  3614                                     });3615                                 }3616                             } else {3617                                 finallyStep.next(_this, function (finallyType, finallyValue, finallyTarget) {3618                                     if (finallyType == "normal") {3619                                         callback(type, value, target);3620                                     } else {3621                                         callback(finallyType, finallyValue, finallyTarget);3622                                     }3623                                 });3624                             }3625                         }3626                     });3627                 }3628             };3629         }3630     }3631 3632     // CommonJS3633     var isCommonJS = !!(typeof require === "function" && typeof module !== "undefined" && module.exports);3634     // CommonJS AMD3635     var isAmd = !!(typeof require === "function" && typeof define === "function" && define.amd);3636 3637     var Wind;3638 3639     var defineModule = function () {3640         Wind.define({3641             name: "builderbase",3642             version: "0.7.0",3643             require: isCommonJS && require,3644             dependencies: { core: "~0.7.0" },3645             init: function () {3646                 Wind.BuilderBase = BuilderBase;3647             }3648         });3649     }3650 3651     if (isCommonJS) {3652         try {3653             Wind = require("./wind-core");3654         } catch (ex) {3655             Wind = require("wind-core");3656         }3657         3658         defineModule();3659     } else if (isAmd) {3660         require(["wind-core"], function (wind) {3661             Wind = wind;3662             defineModule();3663         });3664     } else {3665         var Fn = Function, global = Fn(‘return this‘)();3666         if (!global.Wind) {3667             throw new Error(‘Missing the root object, please load "wind" component first.‘);3668         }3669         3670         Wind = global.Wind;3671         defineModule();3672     }3673 })();3674 3675 /***********************************************************************3676   wind-async-0.7.1.js3677  ***********************************************************************/3678 3679 (function () {3680     "use strict";3681 3682     var supportDefineProperty = (function () {3683         var i = 0;3684         var getter = function () {3685             if (i === 0) {3686                 throw new Error("Execute too soon.");3687             }3688             3689             return i;3690         };3691 3692         var obj = {};3693         3694         try {3695             Object.defineProperty(obj, "value", { get: getter });3696             3697             i = 1;3698             return obj.value =http://www.mamicode.com/== 1;3699         } catch (ex) {3700             return false;3701         }3702     })();3703     3704     var Wind, _;3705     3706     var Async = { };3707     3708     /***********************************************************************3709       Errors3710      ***********************************************************************/3711 3712     var CanceledErrorTypeID = "670a1076-712b-4edd-9b70-64b152fe1cd9";3713     var isCanceledError = function (ex) { return ex._typeId == CanceledErrorTypeID; }3714     var CanceledError = Async.CanceledError = function () { }3715     CanceledError.prototype = {3716         isTypeOf: isCanceledError,3717         _typeId: CanceledErrorTypeID,3718         message: "The task has been cancelled."3719     }3720     3721     var AggregateErrorTypeID = "4a73efb8-c2e2-4305-a05c-72385288650a";3722     var AggregateError = Async.AggregateError = function (errors) {3723         this.children = [];3724         3725         if (errors) {3726             for (var i = 0; i < errors.length; i++) {3727                 this.children.push(errors[i]);3728             }3729         }3730     }3731     AggregateError.prototype = {3732         _typeId: AggregateErrorTypeID,3733         message: "This is an error contains sub-errors, please check the ‘children‘ collection for more details.",3734         isTypeOf: function (ex) {3735             return ex._typeId == AggregateErrorTypeID;3736         }3737     }3738 3739     /***********************************************************************3740       CancellationToken3741      ***********************************************************************/3742     3743     var CancellationToken = Async.CancellationToken = function () { }3744     CancellationToken.prototype = {3745         register: function (handler) {3746             if (this.isCancellationRequested) {3747                 handler();3748             }3749 3750             if (!this._handlers) {3751                 this._handlers = [];3752             }3753 3754             this._handlers.push(handler);3755         },3756         3757         unregister: function (handler) {3758             if (!this._handlers) {3759                 return;3760             }3761             3762             var index = this._handlers.indexOf(handler);3763             if (index >= 0) {3764                 this._handlers.splice(index, 1);3765             }3766         },3767         3768         cancel: function () {3769             if (this.isCancellationRequested) {3770                 return;3771             }3772 3773             this.isCancellationRequested = true;3774 3775             var handlers = this._handlers;3776             delete this._handlers;3777 3778             for (var i = 0; i < handlers.length; i++) {3779                 try {3780                     handlers[i]();3781                 } catch (ex) {3782                     Wind.logger.warn("Cancellation handler threw an error: " + ex);3783                 }3784             }3785         },3786 3787         throwIfCancellationRequested: function () {3788             if (this.isCancellationRequested) {3789                 throw new CanceledError();3790             }3791         }3792     };3793 3794     /***********************************************************************3795       Task3796      ***********************************************************************/3797     3798     var EventManager = function () {3799         this._listeners = {};3800         this._firing = null;3801     }3802     EventManager.prototype = {3803         add: function (name, listener) {3804             if (this._firing === name) {3805                 var self = this;3806                 setTimeout(function () {3807                     self.add(name, listener);3808                 }, 0);3809                 3810                 return;3811             }3812         3813             var eventListeners = this._listeners[name];3814             if (!eventListeners) {3815                 eventListeners = this._listeners[name] = [];3816             }3817 3818             eventListeners.push(listener);3819         },3820         3821         remove: function (name, listener) {3822             if (this._firing === name) {3823                 var self = this;3824                 setTimeout(function () {3825                     self.remove(name, listener);3826                 }, 0);3827                 3828                 return;3829             }3830         3831             var eventListeners = this._listeners[name];3832             if (!eventListeners) return;3833             3834             var index = eventListeners.indexOf(listener);3835             if (index >= 0) {3836                 eventListeners.splice(index, 1);3837             }3838         },3839         3840         fire: function (name, self, args) {3841             var listeners = this._listeners[name];3842             if (!listeners) return;3843             3844             this._firing = name;3845 3846             for (var i = 0; i < listeners.length; i++) {3847                 try {3848                     listeners[i].call(self, args);3849                 } catch (ex) {3850                     Wind.logger.warn(‘An error occurred in "‘ + name + ‘ listener": ‘ + ex);3851                 }3852             }3853             3854             this._firing = null;3855         }3856     };3857     3858     var taskEventManager = new EventManager();3859     3860     var Task = Async.Task = function (delegate) {3861         this._delegate = delegate;3862         this._eventManager = new EventManager();3863         this.status = "ready";3864     }3865     Task.prototype = {3866         start: function () {3867             if (this.status != "ready") {3868                 throw new Error(‘Task can only be started in "ready" status.‘);3869             }3870 3871             this.status = "running";3872             3873             try {3874                 this._delegate(this);3875             } catch (ex) {3876                 if (this.status == "running") {3877                     this.complete("failure", ex);3878                 } else {3879                     Wind.logger.warn("An unexpected error occurred after the task is completed: " + ex);3880                 }3881             }3882             3883             return this;3884         },3885         3886         complete: function (type, value) {3887             if (type !== "success" && type !== "failure") {3888                 throw new Error("Unsupported type: " + type);3889             }3890             3891             if (this.status != "running") {3892                 throw new Error(‘The "complete" method can only be called in "running" status.‘);3893             }3894 3895             var eventManager = this._eventManager;3896             this._eventManager = null;3897             3898             if (type === "success") {3899                 this.status = "succeeded";3900                 3901                 if (supportDefineProperty) {3902                     this._result = value;3903                 } else {3904                     this.result = value;3905                 }3906 3907                 eventManager.fire("success", this);3908             } else {3909                 if (isCanceledError(value)) {3910                     this.status = "canceled";3911                 } else {3912                     this.status = "faulted";3913                 }3914                 3915                 if (supportDefineProperty) {3916                     this._error = value;3917                 } else {3918                     this.error = value;3919                 }3920                 3921                 eventManager.fire("failure", this);3922             }3923             3924             eventManager.fire("complete", this);3925             3926             if (type !== "failure") return;3927             if (!supportDefineProperty) return;3928             if (this._errorObserved) return;3929             3930             var self = this;3931             this._unobservedTimeoutToken = setTimeout(function () {3932                 self._handleUnobservedError(value);3933             }, Task.unobservedTimeout);3934         },3935         3936         observeError: function () {3937             if (this.status === "ready" || this.status === "running") {3938                 throw new Error("The method could only be called when it‘s completed.");3939             }3940         3941             if (!supportDefineProperty) return this.error;3942         3943             var token = this._unobservedTimeoutToken;3944             if (token) {3945                 clearTimeout(token);3946                 this._unobservedTimeoutToken = null;3947             }3948             3949             this._errorObserved = true;3950             return this._error;3951         },3952         3953         _handleUnobservedError: function (error) {3954             this._unobservedTimeoutToken = null;3955 3956             var args = {3957                 task: this,3958                 error: error,3959                 observed: false3960             };3961             3962             taskEventManager.fire("unobservedError", Task, args);3963             3964             if (!args.observed) {3965                 throw error;3966             }3967         },3968         3969         then: function (nextGenerator) {3970             var firstTask = this;3971             3972             return Task.create(function (t) {3973                 3974                 var nextOnComplete = function () {3975                     if (this.error) {3976                         t.complete("failure", this.error);3977                     } else {3978                         t.complete("success", this.result);3979                     }3980                 };3981                 3982                 var processNext = function (nextTask) {3983                     if (nextTask.status == "ready") {3984                         nextTask.start();3985                     }3986                 3987                     if (nextTask.status == "running") {3988                         nextTask.on("complete", nextOnComplete);3989                     } else {3990                         nextOnComplete.call(nextTask);3991                     }3992                 };3993                 3994                 var firstOnComplete = function () {3995                     if (this.error) {3996                         return t.complete("failure", this.error);3997                     }3998                     3999                     var nextTask;4000                     try {4001                         nextTask = nextGenerator(this.result);4002                     } catch (ex) {4003                         return t.complete("failure", ex);4004                     }4005                     4006                     processNext(nextTask);4007                 };4008                 4009                 if (firstTask.status == "ready") {4010                     firstTask.start();4011                 }4012                 4013                 if (firstTask.status == "running") {4014                     firstTask.on("complete", firstOnComplete);4015                 } else {4016                     firstOnComplete.call(firstTask);4017                 }4018             });4019         }4020     };4021     4022     Task.prototype.on = Task.prototype.addEventListener = function () {4023         var eventManager = this._eventManager;4024         if (!eventManager) {4025             throw new Error("Cannot add event listeners when the task is complete.");4026         }4027         4028         eventManager.add.apply(eventManager, arguments);4029         return this;4030     };4031     4032     Task.prototype.off = Task.prototype.removeEventListener = function () {4033         var eventManager = this._eventManager;4034         if (!eventManager) {4035             throw new Error("All the event listeners have been removed when the task was complete.");4036         }4037         4038         eventManager.remove.apply(eventManager, arguments);4039         return this;4040     };4041     4042     if (supportDefineProperty) {4043         Object.defineProperty(Task.prototype, "error", {4044             get: function () {4045                 return this.observeError();4046             }4047         });4048         4049         Object.defineProperty(Task.prototype, "result", {4050             get: function () {4051                 var error = this.observeError();4052                 if (error) throw error;4053                 4054                 return this._result;4055             }4056         });4057     }4058     4059     var observeErrorListener = function () { this.observeError(); };4060     4061     Task.on = Task.addEventListener = function () {4062         taskEventManager.add.apply(taskEventManager, arguments);4063     }4064     4065     Task.off = Task.removeEventListener = function (name, listener) {4066         taskEventManager.remove.apply(taskEventManager, arguments);4067     }4068     4069     Task.unobservedTimeout = 10 * 1000;4070     4071     var isTask = Task.isTask = function (t) {4072         return t && (typeof t.start === "function") && (typeof t.addEventListener) === "function" && (typeof t.removeEventListener) === "function" && (typeof t.complete) === "function";4073     };4074     4075     var create = Task.create = function (delegate) {4076         return new Task(delegate);4077     }4078     4079     /***********************************************************************4080       Task helpers4081      ***********************************************************************/4082     4083     var whenAll = Task.whenAll = function () {4084         var inputTasks;4085 4086         if (arguments.length == 1) {4087             var arg = arguments[0];4088             if (isTask(arg)) { // a single task4089                 inputTasks = [arg];4090             } else {4091                 inputTasks = arg;4092             }4093         } else {4094             inputTasks = new Array(arguments.length);4095             for (var i = 0; i < arguments.length; i++) {4096                 inputTasks[i] = arguments[i];4097             }4098         }4099     4100         return create(function (taskWhenAll) {4101 4102             var errors;4103             4104             var done = function () {4105                 if (errors) {4106                     taskWhenAll.complete("failure", new AggregateError(errors));4107                 } else {4108                     var results = _.map(inputTasks, function (t) {4109                         return t.result;4110                     });4111                     4112                     taskWhenAll.complete("success", results);4113                 }4114             }4115 4116             var runningNumber = 0;4117 4118             _.each(inputTasks, function (key, task) {4119                 if (!task) return;4120                 4121                 if (!isTask(task)) {4122                     inputTasks[key] = task = whenAll(task);4123                 }4124                 4125                 if (task.status === "ready") {4126                     task.start();4127                 }4128                 4129                 if (task.status === "running") {4130                     runningNumber++;4131                     task.addEventListener("complete", function () {4132                         if (this.status !== "succeeded") {4133                             if (!errors) errors = [];4134                             errors.push(this.error);4135                         }4136 4137                         if (--runningNumber == 0) {4138                             done();4139                         }4140                     });4141                 } else if (task.status === "faulted" || task.status === "canceled") {4142                     if (!errors) errors = [];4143                     errors.push(task.error);4144                 }4145             });4146 4147             if (runningNumber == 0) {4148                 done();4149             }4150         });4151     };4152     4153     var whenAny = Task.whenAny = function () {4154 4155         var inputTasks = { };4156         var isArray = true;4157 4158         if (arguments.length == 1) {4159             var arg = arguments[0];4160             if (isTask(arg)) {4161                 inputTasks[0] = arg;4162             } else {4163                 isArray = _.isArray(arg);4164                 _.each(arg, function (key, task) {4165                     if (isTask(task)) {4166                         inputTasks[key] = task;4167                     }4168                 });4169             }4170         } else {4171             for (var i = 0; i < arguments.length; i++) {4172                 var task = arguments[i];4173                 if (isTask(task)) {4174                     inputTasks[i] = task;4175                 }4176             }4177         }4178         4179         var processKey = isArray4180             ? function (key) { return parseInt(key, 10); }4181             : function (key) { return key; }4182         4183         return create(function (taskWhenAny) {4184             if (_.isEmpty(inputTasks)) {4185                 return taskWhenAny.complete("failure", "There‘s no valid input tasks.");4186             }4187             4188             var result;4189             4190             _.each(inputTasks, function (key, task) {4191                 if (task.status === "ready") {4192                     task.start();4193                 }4194                 4195                 if (task.status !== "running") {4196                     task.observeError();4197                     4198                     if (!result) {4199                         result = { key: processKey(key), task: task };4200                     }4201                 }4202             });4203             4204             if (result) {4205                 _.each(inputTasks, function (key, task) {4206                     if (task.status === "running") {4207                         task.on("failure", observeErrorListener);4208                     }4209                 });4210 4211                 return taskWhenAny.complete("success", result);4212             }4213             4214             var onComplete = function () {4215                 this.observeError();4216                 4217                 var taskCompleted = this;4218                 var keyCompleted;4219                 4220                 _.each(inputTasks, function (key, task) {4221                     if (taskCompleted === task) {4222                         keyCompleted = key;4223                         return;4224                     }4225 4226                     task.off("complete", onComplete);4227                     task.on("failure", observeErrorListener);4228                 });4229 4230                 taskWhenAny.complete("success", { key: processKey(keyCompleted), task: this });4231             }4232             4233             _.each(inputTasks, function (task) {4234                 task.addEventListener("complete", onComplete);4235             });4236         });4237     }4238 4239     /***********************************************************************4240       Async helpers4241      ***********************************************************************/4242     4243     var sleep = Async.sleep = function (delay, /* CancellationToken */ ct) {4244         return Task.create(function (t) {4245             if (ct && ct.isCancellationRequested) {4246                 t.complete("failure", new CanceledError());4247             }4248 4249             var seed;4250             var cancelHandler;4251             4252             if (ct) {4253                 cancelHandler = function () {4254                     clearTimeout(seed);4255                     t.complete("failure", new CanceledError());4256                 }4257             }4258             4259             var seed = setTimeout(function () {4260                 if (ct) {4261                     ct.unregister(cancelHandler);4262                 }4263                 4264                 t.complete("success");4265             }, delay);4266             4267             if (ct) {4268                 ct.register(cancelHandler);4269             }4270         });4271     }4272     4273     var onEvent = Async.onEvent = function (target, eventName, /* CancellationToken*/ ct) {4274         return Task.create(function (t) {4275             if (ct && ct.isCancellationRequested) {4276                 t.complete("failure", new CanceledError());4277             }4278 4279             var cleanUp = function () {4280                 if (target.removeEventListener) {4281                     target.removeEventListener(eventName, eventHandler);4282                 } else if (target.removeListener) {4283                     target.removeListener(eventName, eventHandler);4284                 } else {4285                     target.detachEvent(eventName, eventHandler);4286                 }4287             }4288             4289             var eventHandler;4290             var cancelHandler;4291 4292             if (ct) {4293                 cancelHandler = function () {4294                     cleanUp();4295                     t.complete("failure", new CanceledError());4296                 }4297             }4298             4299             var eventHandler = function (ev) {4300                 if (ct) {4301                     ct.unregister(cancelHandler);4302                 }4303                 4304                 cleanUp();4305                 t.complete("success", ev);4306             }4307             4308             if (target.addEventListener) {4309                 target.addEventListener(eventName, eventHandler);4310             } else if (target.addListener) {4311                 target.addListener(eventName, eventHandler);4312             } else {4313                 target.attachEvent(eventName, eventHandler);4314             }4315             4316             if (ct) {4317                 ct.register(cancelHandler);4318             }4319         });4320     }4321     4322     /***********************************************************************4323       AsyncBuilder4324      ***********************************************************************/4325     4326     var AsyncBuilder = Async.AsyncBuilder = function () { }4327     AsyncBuilder.prototype = {4328         Start: function (_this, task) {4329             return Task.create(function (t) {4330                 task.next(_this, function (type, value, target) {4331                     if (type == "normal" || type == "return") {4332                         t.complete("success", value);4333                     } else if (type == "throw") {4334                         t.complete("failure", value);4335                     } else {4336                         throw new Error("Unsupported type: " + type);4337                     }4338                 });4339             });4340         },4341 4342         Bind: function (task, generator) {4343             return {4344                 next: function (_this, callback) {4345                     4346                     var onComplete = function () {4347                         if (this.error) {4348                             callback("throw", this.error);4349                         } else {4350                             var nextTask;4351                             try {4352                                 nextTask = generator.call(_this, this.result);4353                             } catch (ex) {4354                                 callback("throw", ex);4355                                 return;4356                             }4357 4358                             nextTask.next(_this, callback);4359                         }4360                     }4361 4362                     if (task.status == "ready") {4363                         task.addEventListener("complete", onComplete);4364                         task.start();4365                     } else if (task.status == "running") {4366                         task.addEventListener("complete", onComplete);4367                     } else {4368                         onComplete.call(task);4369                     }4370                 }4371             };4372         }4373     }4374     4375     var Binding = Async.Binding = { };4376     4377     var collectArgs = function (args, requiredArgs) {4378         var result = [];4379         for (var i = 0; i < args.length; i++) {4380             result.push(args[i]);4381         }4382 4383         while (result.length < requiredArgs) {4384             result.push(undefined);4385         }4386 4387         return result;4388     }4389     4390     var collectCallbackArgNames = function (args) {4391         if (args.length <= 1) return null;4392         4393         var result = [];4394         for (var i = 1; i < args.length; i++) {4395             result.push(args[i]);4396         }4397         4398         return result;4399     }4400     4401     var fromStandard = Binding.fromStandard = function (fn) {4402         var callbackArgNames = collectCallbackArgNames(arguments);4403     4404         return function () {4405             var _this = this;4406             var args = collectArgs(arguments, fn.length - 1);4407 4408             return Task.create(function (t) {4409                 args.push(function (error, result) {4410                     if (error) {4411                         t.complete("failure", error);4412                     } else if (!callbackArgNames) {4413                         t.complete("success", result);4414                     } else {4415                         var data =http://www.mamicode.com/ {};4416                         for (var i = 0; i < callbackArgNames.length; i++) {4417                             data[callbackArgNames[i]] = arguments[i + 1];4418                         }4419                         4420                         return t.complete("success", data);4421                     }4422                 });4423                 4424                 fn.apply(_this, args);4425             });4426         };4427     };4428     4429     var fromCallback = Binding.fromCallback = function (fn) {4430         var callbackArgNames = collectCallbackArgNames(arguments);4431     4432         return function () {4433             var _this = this;4434             var args = collectArgs(arguments, fn.length - 1);4435 4436             return Task.create(function (t) {4437                 args.push(function (result) {4438                     if (callbackArgNames) {4439                         var data =http://www.mamicode.com/ {};4440                         for (var i = 0; i < callbackArgNames.length; i++) {4441                             data[callbackArgNames[i]] = arguments[i];4442                         }4443                         4444                         t.complete("success", data);4445                     } else {4446                         t.complete("success", result);4447                     }4448                 });4449                 4450                 fn.apply(_this, args);4451             });4452         };4453     };4454     4455     // CommonJS4456     var isCommonJS = !!(typeof require === "function" && typeof module !== "undefined" && module.exports);4457     // CommonJS AMD4458     var isAmd = !!(typeof require === "function" && typeof define === "function" && define.amd);4459 4460     var defineModule = function () {4461         Wind.define({4462             name: "async",4463             version: "0.7.1",4464             require: isCommonJS && require,4465             autoloads: [ "builderbase" ],4466             dependencies: { builderbase: "~0.7.0" },4467             init: function () {4468                 4469                 _ = Wind._;4470                 4471                 _.each(Wind.BuilderBase.prototype, function (m, fn) {4472                     AsyncBuilder.prototype[m] = fn;4473                 });4474                 4475                 Wind.Async = Async;4476             4477                 Wind.binders["async"] = "$await";4478                 Wind.builders["async"] = new AsyncBuilder();4479             }4480         });4481     }4482 4483     if (isCommonJS) {4484         try {4485             Wind = require("./wind-core");4486         } catch (ex) {4487             Wind = require("wind-core");4488         }4489         4490         defineModule();4491     } else if (isAmd) {4492         require(["wind-core"], function (wind) {4493             Wind = wind;4494             defineModule();4495         });4496     } else {4497         var Fn = Function, global = Fn(‘return this‘)();4498     4499         if (!global.Wind) {4500             throw new Error(‘Missing the root object, please load "wind" component first.‘);4501         }4502         4503         Wind = global.Wind;4504         defineModule();4505     }4506 })();4507 4508 4509 /***********************************************************************4510   wind-promise-0.7.0.js4511  ***********************************************************************/4512 4513 (function () {4514     "use strict";4515 4516     var Wind;4517     4518     var defaultCreate = function () {4519         throw new Error(‘Please set "Wind.Promise.create" to provide a factory method for creating a promise object.‘);4520     }4521     4522     var PromiseBuilder = function () { }4523     PromiseBuilder.prototype = {4524         Start: function (_this, task) {4525             return Wind.Promise.create(function (complete, error) {4526                 task.next(_this, function (type, value, target) {4527                     if (type == "normal" || type == "return") {4528                         complete(value);4529                     } else if (type == "throw") {4530                         error(value);4531                     } else {4532                         throw new Error("Unsupported type: " + type);4533                     }4534                 });4535             });4536         },4537 4538         Bind: function (promise, generator) {4539             return {4540                 next: function (_this, callback) {4541                     promise.then(function (result) {4542                         var nextTask;4543                         try {4544                             nextTask = generator.call(_this, result);4545                         } catch (ex) {4546                             return callback("throw", ex);4547                         }4548 4549                         nextTask.next(_this, callback);4550                     }, function (error) {4551                         callback("throw", error);4552                     });4553                 }4554             };4555         }4556     }4557     4558     // CommonJS4559     var isCommonJS = !!(typeof require === "function" && typeof module !== "undefined" && module.exports);4560     // CommonJS AMD4561     var isAmd = !!(typeof require === "function" && typeof define === "function" && define.amd);4562 4563     var defineModule = function () {4564         Wind.define({4565             name: "promise",4566             version: "0.7.0",4567             require: isCommonJS && require,4568             autoloads: [ "builderbase" ],4569             dependencies: { builderbase: "~0.7.0" },4570             init: function () {4571                 Wind._.each(Wind.BuilderBase.prototype, function (m, fn) {4572                     PromiseBuilder.prototype[m] = fn;4573                 });4574             4575                 if (!Wind.Promise) {4576                     Wind.Promise = {};4577                 }4578                 4579                 Wind.Promise.create = defaultCreate;4580             4581                 Wind.binders["promise"] = "$await";4582                 Wind.builders["promise"] = new PromiseBuilder();4583             }4584         });4585     }4586 4587     if (isCommonJS) {4588         try {4589             Wind = require("./wind-core");4590         } catch (ex) {4591             Wind = require("wind-core");4592         }4593         4594         defineModule();4595     } else if (isAmd) {4596         require(["wind-core"], function (wind) {4597             Wind = wind;4598             defineModule();4599         });4600     } else {4601         var Fn = Function, global = Fn(‘return this‘)();4602 4603         if (!global.Wind) {4604             throw new Error(‘Missing the root object, please load "wind" component first.‘);4605         }4606         4607         Wind = global.Wind;4608         defineModule();4609     }4610 })();
wind-all-0.7.3.js

 

  

用Windjs画圆