escape(_,0)
SpiderMonkey の escape()
は第二引数にビットフラグを受け取る。
Amazon の API 用にこんな関数を書いてて気付いた。
function amazEnc(str) encodeURIComponent(str).replace(/[!\'()]+/g, escape).replace(/[*]/g, '%2A');
amazEnc('unescape(_)') //=> Error: invalid string escape mask 8
この 8 は replace()
が escape()
に渡したマッチ位置。
該当ソースコードを見てみる。
/* * Contributions from the String class to the set of methods defined for the * global object. escape and unescape used to be defined in the Mocha library, * but as ECMA decided to spec them, they've been moved to the core engine * and made ECMA-compliant. (Incomplete escapes are interpreted as literal * characters by unescape.) */ /* * Stuff to emulate the old libmocha escape, which took a second argument * giving the type of escape to perform. Retained for compatibility, and * copied here to avoid reliance on net.h, mkparse.c/NET_EscapeBytes. */ #define URL_XALPHAS ((uint8) 1) #define URL_XPALPHAS ((uint8) 2) #define URL_PATH ((uint8) 4) static const uint8 urlCharType[256] = /* Bit 0 xalpha -- the alphas * Bit 1 xpalpha -- as xalpha but * converts spaces to plus and plus to %20 * Bit 2 ... path -- as xalphas but doesn't escape '/' */ /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1x */ 0,0,0,0,0,0,0,0,0,0,7,4,0,7,7,4, /* 2x !"#$%&'()*+,-./ */ 7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0, /* 3x 0123456789:;<=>? */ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, /* 4x @ABCDEFGHIJKLMNO */ 7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,7, /* 5X PQRSTUVWXYZ[\]^_ */ 0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, /* 6x `abcdefghijklmno */ 7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0, /* 7X pqrstuvwxyz{\}~ DEL */ 0, }; /* This matches the ECMA escape set when mask is 7 (default.) */ #define IS_OK(C, mask) (urlCharType[((uint8) (C))] & (mask))http://mxr.mozilla.org/mozilla-central/source/js/src/jsstr.cpp#304
なにやら歴史的理由も綴られているが,つまりは非エスケープ文字の制限を外せるようにしてあるらしい。
escape('0Aa*+-./') //=> 0Aa*+-./ escape('0Aa*+-./', 0) //=> %30%41%61%2A%2B%2D%2E%2F
数字アルファベットごと変換でき便利である。
冒頭の関数もシンプルになった。
function amazEnc(str)( encodeURIComponent(str).replace(/[!\'()*]+/g, function(s) escape(s, 0)));