OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This file contains support for URI manipulations written in | 5 // This file contains support for URI manipulations written in |
6 // JavaScript. | 6 // JavaScript. |
7 | 7 |
8 (function(global, utils) { | 8 (function(global, utils) { |
9 | 9 |
10 "use strict"; | 10 "use strict"; |
11 | 11 |
12 %CheckIsBootstrapping(); | 12 %CheckIsBootstrapping(); |
13 | 13 |
14 //- ------------------------------------------------------------------ | |
15 // Imports | |
16 | |
17 var GlobalObject = global.Object; | |
18 var InternalArray = utils.InternalArray; | |
19 var MakeURIError; | |
20 | |
21 utils.Import(function(from) { | |
22 MakeURIError = from.MakeURIError; | |
23 }); | |
24 | |
25 | |
26 // ------------------------------------------------------------------- | |
27 // Define internal helper functions. | |
28 | |
29 function HexValueOf(code) { | |
30 // 0-9 | |
31 if (code >= 48 && code <= 57) return code - 48; | |
32 // A-F | |
33 if (code >= 65 && code <= 70) return code - 55; | |
34 // a-f | |
35 if (code >= 97 && code <= 102) return code - 87; | |
36 | |
37 return -1; | |
38 } | |
39 | |
40 function URIHexCharsToCharCode(highChar, lowChar) { | |
41 var highCode = HexValueOf(highChar); | |
42 var lowCode = HexValueOf(lowChar); | |
43 if (highCode == -1 || lowCode == -1) throw MakeURIError(); | |
44 return (highCode << 4) | lowCode; | |
45 } | |
46 | |
47 // Callers must ensure that |result| is a sufficiently long sequential | |
48 // two-byte string! | |
49 function URIDecodeOctets(octets, result, index) { | |
50 var value; | |
51 var o0 = octets[0]; | |
52 if (o0 < 0x80) { | |
53 value = o0; | |
54 } else if (o0 < 0xc2) { | |
55 throw MakeURIError(); | |
56 } else { | |
57 var o1 = octets[1]; | |
58 if (o0 < 0xe0) { | |
59 var a = o0 & 0x1f; | |
60 if ((o1 < 0x80) || (o1 > 0xbf)) throw MakeURIError(); | |
61 var b = o1 & 0x3f; | |
62 value = (a << 6) + b; | |
63 if (value < 0x80 || value > 0x7ff) throw MakeURIError(); | |
64 } else { | |
65 var o2 = octets[2]; | |
66 if (o0 < 0xf0) { | |
67 var a = o0 & 0x0f; | |
68 if ((o1 < 0x80) || (o1 > 0xbf)) throw MakeURIError(); | |
69 var b = o1 & 0x3f; | |
70 if ((o2 < 0x80) || (o2 > 0xbf)) throw MakeURIError(); | |
71 var c = o2 & 0x3f; | |
72 value = (a << 12) + (b << 6) + c; | |
73 if ((value < 0x800) || (value > 0xffff)) throw MakeURIError(); | |
74 } else { | |
75 var o3 = octets[3]; | |
76 if (o0 < 0xf8) { | |
77 var a = (o0 & 0x07); | |
78 if ((o1 < 0x80) || (o1 > 0xbf)) throw MakeURIError(); | |
79 var b = (o1 & 0x3f); | |
80 if ((o2 < 0x80) || (o2 > 0xbf)) { | |
81 throw MakeURIError(); | |
82 } | |
83 var c = (o2 & 0x3f); | |
84 if ((o3 < 0x80) || (o3 > 0xbf)) throw MakeURIError(); | |
85 var d = (o3 & 0x3f); | |
86 value = (a << 18) + (b << 12) + (c << 6) + d; | |
87 if ((value < 0x10000) || (value > 0x10ffff)) throw MakeURIError(); | |
88 } else { | |
89 throw MakeURIError(); | |
90 } | |
91 } | |
92 } | |
93 } | |
94 if (0xD800 <= value && value <= 0xDFFF) throw MakeURIError(); | |
95 if (value < 0x10000) { | |
96 %_TwoByteSeqStringSetChar(index++, value, result); | |
97 } else { | |
98 %_TwoByteSeqStringSetChar(index++, (value >> 10) + 0xd7c0, result); | |
99 %_TwoByteSeqStringSetChar(index++, (value & 0x3ff) + 0xdc00, result); | |
100 } | |
101 return index; | |
102 } | |
103 | |
104 // ECMA-262, section 15.1.3 | |
105 function Decode(uri, reserved) { | |
106 uri = TO_STRING(uri); | |
107 var uriLength = uri.length; | |
108 var one_byte = %NewString(uriLength, NEW_ONE_BYTE_STRING); | |
109 var index = 0; | |
110 var k = 0; | |
111 | |
112 // Optimistically assume one-byte string. | |
113 for ( ; k < uriLength; k++) { | |
114 var code = %_StringCharCodeAt(uri, k); | |
115 if (code == 37) { // '%' | |
116 if (k + 2 >= uriLength) throw MakeURIError(); | |
117 var cc = URIHexCharsToCharCode(%_StringCharCodeAt(uri, k+1), | |
118 %_StringCharCodeAt(uri, k+2)); | |
119 if (cc >> 7) break; // Assumption wrong, two-byte string. | |
120 if (reserved(cc)) { | |
121 %_OneByteSeqStringSetChar(index++, 37, one_byte); // '%'. | |
122 %_OneByteSeqStringSetChar(index++, %_StringCharCodeAt(uri, k+1), | |
123 one_byte); | |
124 %_OneByteSeqStringSetChar(index++, %_StringCharCodeAt(uri, k+2), | |
125 one_byte); | |
126 } else { | |
127 %_OneByteSeqStringSetChar(index++, cc, one_byte); | |
128 } | |
129 k += 2; | |
130 } else { | |
131 if (code > 0x7f) break; // Assumption wrong, two-byte string. | |
132 %_OneByteSeqStringSetChar(index++, code, one_byte); | |
133 } | |
134 } | |
135 | |
136 one_byte = %TruncateString(one_byte, index); | |
137 if (k == uriLength) return one_byte; | |
138 | |
139 // Write into two byte string. | |
140 var two_byte = %NewString(uriLength - k, NEW_TWO_BYTE_STRING); | |
141 index = 0; | |
142 | |
143 for ( ; k < uriLength; k++) { | |
144 var code = %_StringCharCodeAt(uri, k); | |
145 if (code == 37) { // '%' | |
146 if (k + 2 >= uriLength) throw MakeURIError(); | |
147 var cc = URIHexCharsToCharCode(%_StringCharCodeAt(uri, ++k), | |
148 %_StringCharCodeAt(uri, ++k)); | |
149 if (cc >> 7) { | |
150 var n = 0; | |
151 while (((cc << ++n) & 0x80) != 0) { } | |
152 if (n == 1 || n > 4) throw MakeURIError(); | |
153 var octets = new InternalArray(n); | |
154 octets[0] = cc; | |
155 if (k + 3 * (n - 1) >= uriLength) throw MakeURIError(); | |
156 for (var i = 1; i < n; i++) { | |
157 if (uri[++k] != '%') throw MakeURIError(); | |
158 octets[i] = URIHexCharsToCharCode(%_StringCharCodeAt(uri, ++k), | |
159 %_StringCharCodeAt(uri, ++k)); | |
160 } | |
161 index = URIDecodeOctets(octets, two_byte, index); | |
162 } else if (reserved(cc)) { | |
163 %_TwoByteSeqStringSetChar(index++, 37, two_byte); // '%'. | |
164 %_TwoByteSeqStringSetChar(index++, %_StringCharCodeAt(uri, k - 1), | |
165 two_byte); | |
166 %_TwoByteSeqStringSetChar(index++, %_StringCharCodeAt(uri, k), | |
167 two_byte); | |
168 } else { | |
169 %_TwoByteSeqStringSetChar(index++, cc, two_byte); | |
170 } | |
171 } else { | |
172 %_TwoByteSeqStringSetChar(index++, code, two_byte); | |
173 } | |
174 } | |
175 | |
176 two_byte = %TruncateString(two_byte, index); | |
177 return one_byte + two_byte; | |
178 } | |
179 | |
180 // ------------------------------------------------------------------- | 14 // ------------------------------------------------------------------- |
181 // Define exported functions. | 15 // Define exported functions. |
182 | 16 |
183 // ECMA-262 - B.2.1. | 17 // ECMA-262 - B.2.1. |
184 function URIEscapeJS(s) { | 18 function URIEscapeJS(s) { |
185 return %URIEscape(s); | 19 return %URIEscape(s); |
186 } | 20 } |
187 | 21 |
188 // ECMA-262 - B.2.2. | 22 // ECMA-262 - B.2.2. |
189 function URIUnescapeJS(s) { | 23 function URIUnescapeJS(s) { |
190 return %URIUnescape(s); | 24 return %URIUnescape(s); |
191 } | 25 } |
192 | 26 |
193 // ECMA-262 - 15.1.3.1. | |
194 function URIDecode(uri) { | |
195 var reservedPredicate = function(cc) { | |
196 // #$ | |
197 if (35 <= cc && cc <= 36) return true; | |
198 // & | |
199 if (cc == 38) return true; | |
200 // +, | |
201 if (43 <= cc && cc <= 44) return true; | |
202 // / | |
203 if (cc == 47) return true; | |
204 // :; | |
205 if (58 <= cc && cc <= 59) return true; | |
206 // = | |
207 if (cc == 61) return true; | |
208 // ?@ | |
209 if (63 <= cc && cc <= 64) return true; | |
210 | |
211 return false; | |
212 }; | |
213 return Decode(uri, reservedPredicate); | |
214 } | |
215 | |
216 // ECMA-262 - 15.1.3.2. | |
217 function URIDecodeComponent(component) { | |
218 var reservedPredicate = function(cc) { return false; }; | |
219 return Decode(component, reservedPredicate); | |
220 } | |
221 | |
222 // ------------------------------------------------------------------- | 27 // ------------------------------------------------------------------- |
223 // Install exported functions. | 28 // Install exported functions. |
224 | 29 |
225 // Set up non-enumerable URI functions on the global object and set | 30 // Set up non-enumerable URI functions on the global object and set |
226 // their names. | 31 // their names. |
227 utils.InstallFunctions(global, DONT_ENUM, [ | 32 utils.InstallFunctions(global, DONT_ENUM, [ |
228 "escape", URIEscapeJS, | 33 "escape", URIEscapeJS, |
229 "unescape", URIUnescapeJS, | 34 "unescape", URIUnescapeJS |
230 "decodeURI", URIDecode, | |
231 "decodeURIComponent", URIDecodeComponent | |
232 ]); | 35 ]); |
233 | 36 |
234 }) | 37 }) |
OLD | NEW |