2011-08-09 4 views
0

javascriptインタプリタはコードを圧縮した後にSytaxErrorをトリガしますが、コードでこの問題を引き起こした正確な位置がわかりません。見つけにくいです。私もjsLintを試しましたが、問題を指摘できません。 、私はパッカーに作品によってコードピースを貼り付け 私は最終的に自分でこの問題を解決:Javascript SytaxError例外が発生した場合の正確な位置の取得方法

(function(){var session,start,end,pool={length:0},result=[],id=0;function poolAdd(procedure,expected,description){pool[id+++""]={"description":description||"No description","procedure":procedure,"expected":expected};pool["length"]++;return id-1;}function poolRun(id){var actual,expect,pass,test=pool[id];if(test){try{actual=typeof test.procedure==="function"?test.procedure():test.procedure;expect=typeof test.expected==="function"?test.expected():test.expected;pass=actual===expect;if(pass){test["pass"]=true}else{test["fail"]={"actual":actual,"expect":expect}}}catch(e){test["fail"]={"message":e.toString()}}finally{delete pool[id];pool.length--;return result.push(test)-1;}}return-1;}function percentage(fraction){return!(fraction>=0&&fraction<=1)?"Not available":(fraction*100+"").substr(0,5)+"%"}function Statics(data,session){if(this instanceof Statics){this.data=(data||result).slice(0);if(session){this.session={id:session.id,end:session.end,start:session.start}}}else{return new Statics(data,session)}}Statics.prototype={statics:function(format){var temp,report,passed=[],failed=[];format=format||"text";for(var i=0,l=this.data.length;i<l;i++){temp=this.data[i];if(typeof temp==="number"){temp=result[temp+""]}temp.pass&&passed.push(temp);temp.fail&&failed.push(temp)}if(format==="text"){report=[];report.push("***"+(this.session?" Session("+this.session.id+")":"")+" Test Report ***");report.push(" Cost: "+(this.session?(this.session.end-this.session.start)/1000:(end-start)/1000)+" seconds");report.push(" Total: "+this.data.length);report.push("Passed: "+passed.length);report.push("Failed: "+failed.length);report.push("Percet: "+percentage(passed.length/this.data.length));if(failed.length>0){report.push("Detail:");for(var i=0,l=failed.length;i<l;i++){temp=failed[i];if(temp.fail.message){report.push(i+1+")."+" >>>EXCEPTION THROWN<<< in test("+temp.description+") "+temp.fail.message)}else{report.push(i+1+")."+" >>>VALUE NOT MATCH<<< in test("+temp.description+") "+" expected "+temp.fail.expect+" actual "+temp.fail.actual)}}}return report.join("\n")}}}function session_start(){session=new Session();session.start=+new Date;}function session_end(){session&&(session.end=+new Date)}function session_destory(){session=null}function Session(){this.id=QQWB.uid();this.idPool=[];}Session.prototype={_addId:function(id){this.idPool.push(id)},add:function(procedure,expected,description){this._addId(poolAdd(procedure,expected,description));return this},run:function(){var temp,statics,results=[];for(var i=0,l=this.idPool.length;i<l;i++){temp=poolRun(this.idPool[i]);temp&&results.push(temp)}session_end();statics=Statics(results,session);session_destory();return statics}};QQWB.extend("test",{add:function(procedure,expected,description){session_start();session._addId(poolAdd(procedure,expected,description));return session},run:function(){session_destory();start=+new Date;for(var id in pool){if(id!=='length'&&pool.hasOwnProperty(id)){poolRun(id)}}end=+new Date;return Statics()},remains:function(){return pool.length}})}()); 

これは、スクリプトパッカー編集 http://dean.edwards.name/packer/

がある

(function(){ 

    var 
     session, // test session 
     start, // start time of call test.run() 
     end, // end time of test.run() 
     pool = {length:0}, // pool of all the tests removed from pool when test done 
     result = [], // pool of the result of test 
     id = 0; // test unique id auto increment 

    /** 
    * Add a test item to pool 
    * 
    * @access private 
    * @return {Number} the index in the pool 
    */ 
    function poolAdd(procedure, expected, description) { 
     pool[id+++""] = { 
       "description": description || "No description" 
      ,"procedure": procedure 
      ,"expected": expected 
     }; 
     pool["length"]++; // maintain the length property of pool 
     return id - 1; // id of current test 
    } 

    /** 
    * Run a test 
    * 
    * Test item will be marked as pass or fail then move from 
    * test's pool to result's pool 
    * 
    * @access private 
    * @param id {Number} the index in the test pool 
    * @return {Number} the index in the result pool 
    */ 
    function poolRun(id) { 
     var 
      actual, // actual value 
      expect, // expected value 
      pass, // indicate test whether passed 
      test = pool[id]; // the test object 

     if (test) { 
      try{ 
       actual = typeof test.procedure === "function" ? test.procedure() : test.procedure; // run test procedure 
       expect = typeof test.expected === "function" ? test.expected() : test.expected; // run expect procedure 
       pass = actual === expect; 
       if (pass) { 
        test["pass"] = true; 
       } else { 
        test["fail"] = { 
         "actual": actual 
         ,"expect": expect 
        } 
       } 
      } catch (e) { 
       test["fail"] = { 
        "message": e.toString() 
       } 
      } finally { 
       delete pool[id]; // remove from pool 
       pool.length--; // maintain the length property of pool 
       return result.push(test) - 1; // the index in the result array for current test item 
      } 
     } 
     return -1; // id not valid 
    } 

    /** 
    * Float to percentage string 
    * 
    * @access private 
    * @param fraction {Number} float number 
    * @return {String} percentage string 
    */ 
    function percentage (fraction) { 
     return !(fraction >= 0 && fraction <= 1) ? "Not available" : (fraction * 100 + "").substr(0,5) + "%"; 
    } 

    /** 
    * Statics constructor 
    * 
    * Self invoke constructor 
    * 
    * Note: 
    * If data is passed in,it means the statics running in a session 
    * Data contains *position* of result pool 
    * 
    * @access private 
    * @param data {Array} partial result keys array or the result 
    * @return {Statics} a statics instance 
    */ 
    function Statics(data, session) { 
     if (this instanceof Statics) { 
      this.data = (data || result).slice(0); // clone array 
      if (session) { 
       this.session = { 
        id: session.id 
        ,end: session.end 
        ,start: session.start 
       }; 
      } 
     } else { 
      return new Statics(data, session); 
     } 
    } 

    Statics.prototype = { 
     /** 
     * Get statics 
     * 
     * Currently only support text statics 
     * 
     * @access public 
     * @param format {String} text,xml,json etc. 
     * @return {Mixed} result statics 
     */ 
     statics: function (format) { 
      var 
       temp, // temp value 
       report, // statics report 
       passed = [], // passed tests pool 
       failed = []; // failed tests pool 

      format = format || "text"; // default report type is text 

      for (var i=0,l=this.data.length; i<l; i++) { 
       temp = this.data[i]; 
       if (typeof temp === "number") { // convert key to its value 
        temp = result[temp+""]; 
       } 
       temp.pass && passed.push(temp); 
       temp.fail && failed.push(temp); 
      } 

      if (format === "text") { 
       report = []; 
       report.push("***" + (this.session ? " Session(" + this.session.id +")":"") + " Test Report ***"); 
       report.push(" Cost: " + (this.session ? (this.session.end - this.session.start)/1000 : (end - start)/1000) + " seconds"); 
       report.push(" Total: " + this.data.length); 
       report.push("Passed: " + passed.length); 
       report.push("Failed: " + failed.length); 
       report.push("Percet: " + percentage(passed.length/this.data.length)); 
       if (failed.length > 0) { 
        report.push("Detail:"); 
        for (var i=0,l=failed.length; i<l; i++) { 
         temp = failed[i]; 
         if (temp.fail.message) { 
          report.push(i + 1 + ")." + " >>>EXCEPTION THROWN<<< in test(" + temp.description + ") " + temp.fail.message); 
         } else { 
          report.push(i + 1 + ")." + " >>>VALUE NOT MATCH<<< in test(" + temp.description + ") " + " expected " + temp.fail.expect + " actual " + temp.fail.actual); 
         } 
        } 
       } 
       return report.join("\n"); 
      } 
     } 
    } 

    /** 
    * Start a new test session 
    * 
    * @access private 
    * @return {Void} 
    */ 
    function session_start() { 
    // if checked T.test.add(...); T.test.add(...); will be treated as one session till run is called 
    // if (!session) { 
      session = new Session(); 
      session.start = + new Date; 
    // } 
    } 

    /** 
    * End current session 
    * 
    * @access private 
    * @return {Void} 
    */ 
    function session_end() { 
     session && (session.end = + new Date); 
    } 

    /** 
    * Destory current session 
    * 
    * @access private 
    * @return {Void} 
    */ 
    function session_destory() { 
     session = null; 
    } 

    /** 
    * Session constructor 
    * 
    * @access private 
    * @return {Session} session instance 
    */ 
    function Session() { 
     this.id = QQWB.uid(); // random session id 
     this.idPool = []; // contains id of test 
    } 

    Session.prototype = { 
     /** 
     * Add test id to session 
     * 
     * @access private 
     * @param id {Number} test id 
     * @return {Void} 
     */ 
     _addId: function (id) { 
      this.idPool.push(id); 
     } 

     /** 
     * Add test item to session 
     * 
     * Note: 
     * Test item added to global pool 
     * Session just store the position of test in the pool 
     * 
     * Example usage: 
     * T.test 
     *  .add(...) //add a test to session(and pool) 
     *  .add(...) //add a test to session(and pool) 
     *  ... 
     * 
     * 
     * @access public 
     * @param procedure {Mixed} the procedure to finish this test 
     *       if procedure is a function it will 
     *       be executed automaticlly 
     * @param expected {Mixed} the expected value of this test 
     *       if expected is a function it will 
     *       be executed automaticlly 
     * @param description {String} speak more about this test 
     * @return {Session} the current session  
     */ 
     ,add: function (procedure, expected, description) { 
      this._addId(poolAdd(procedure, expected, description)); 
      return this; 
     } 

     /** 
     * Run the tests in current session 
     * 
     * Example usage: 
     * T.test 
     *  .add(...) //add a test to session(and pool) 
     *  .add(...) //add a test to session(and pool) 
     *  ... 
     *  .run() // run the test in this session 
     *  .statics() // get statics for this session 
     * 
     * @access public 
     * @return {Statics} statics object 
     */ 
     ,run: function() { // run in session 
      var temp, 
       statics, 
       results = []; 
      for (var i=0,l=this.idPool.length; i<l; i++) { 
       temp = poolRun(this.idPool[i]); 
       temp && results.push(temp); 
      } 
      session_end(); // record the time of this session end 
      statics = Statics(results,session); 
      session_destory();// destory test session 
      return statics; 
     } 
    }; 

    QQWB.extend("test",{ 

     /** 
     * Add test item to session 
     * 
     * Note: 
     * Test item added to global pool 
     * Current session will store the position of test in the pool 
     * 
     * Example usage: 
     * T.test 
     *  .add(...) //add a test to session(and pool) 
     *  .add(...) //add a test to session(and pool) 
     *  ... 
     * 
     * @access public 
     * @param procedure {Mixed} the procedure to finish this test 
     *       if procedure is a function it will 
     *       be executed automaticlly 
     * @param expected {Mixed} the expected value of this test 
     *       if expected is a function it will 
     *       be executed automaticlly 
     * @param description {String} speak more about this test 
     * @return {Session} the current session  
     */ 
     add: function (procedure, expected, description) { 
      session_start(); // spawn a new session object 
      session._addId(poolAdd(procedure, expected, description)); 
      return session; 
     } 

     /** 
     * Run all the tests except the test already done 
     * 
     * Example usage: 
     * T.test 
     *  .add(...) //add a test to session(and pool) 
     *  .add(...) //add a test to session(and pool) 
     *  ... 
     * 
     * T.test 
     *  .run() // run all the tests except already done 
     *  .statics() //get full statics of all the tests 
     * 
     * @access public 
     * @return {Statics} statics object 
     */ 
     ,run: function() { 
      session_destory(); // destory current session 
      start = + new Date; // start time of global test 
      for (var id in pool) { 
       if (id !== 'length' && pool.hasOwnProperty(id)) { 
        poolRun(id); 
       } 
      } 
      end = + new Date; // end time of global test 
      return Statics(); 
     } 
     /** 
     * Get count of tests left in the pool 
     * 
     * @access public 
     * @return {Number} count of tests unfinished yet 
     */ 
     ,remains: function() { 
      return pool.length; 
     } 

    }); 

}()); 

私の元のコードを追加しました。最終的にStatics.prototypeの定義がSytaxErrorの原因となったセミコロンで終わっていないことがわかります。

+0

まだ圧縮されていないコードはありますか?変更やデバッグのために、オリジナルを常に保持する必要があります。 – Paulpro

+0

@PaulPRO私の元のコードは – bajie

+0

が最初に 'jsbeautifier.org'を使って' jslint.com'を使うと、間違いなく多くの人に役立つかもしれません。 – diEcho

答えて

0

私はhttp://jsfiddle.net/にjavascriptをコピーしてからJSLintをクリックしてみました。すべてのエラーが表示されました。

圧縮にはどのようなツールを使用していますか?

私の推測にはセミコロンがありません。例えば

test["fail"] = { 
    "message": e.toString() 
} 

が閉じ括弧の後にセミコロンを持っている必要があります。

+0

これはスクリプトパッカーhttp://dean.edwards.name/packer/ – bajie

+0

ここに記載されている他のツールを試してみてください:http: //jquery-howto.blogspot.com/2009/01/minimize-and-pack-your-javascript-code.htmlスマートコンプレッサーは、欠けているセミコロンを処理できなければなりません(もし問題があれば)それらを追加する傷つける。 – Ariel

関連する問題