source: webkit/trunk/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp@ 65295

Last change on this file since 65295 was 65295, checked in by [email protected], 15 years ago

Unify UString::UTF8String() & String::utf8() methods,
remove UString::cost() & make atArrayIndex a free function.

Reviewed by Sam Weinig

JavaScriptCore:

(JSC::constantName):
(JSC::idName):
(JSC::CodeBlock::registerName):
(JSC::regexpName):
(JSC::printGlobalResolveInfo):
(JSC::printStructureStubInfo):
(JSC::CodeBlock::printStructure):
(JSC::CodeBlock::printStructures):

  • jsc.cpp:

(functionPrint):
(functionDebug):
(runInteractive):
(fillBufferWithContentsOfFile):

  • pcre/pcre_exec.cpp:

(Histogram::~Histogram):

  • profiler/CallIdentifier.h:

(JSC::CallIdentifier::c_str):

  • profiler/Profile.cpp:

(JSC::Profile::debugPrintDataSampleStyle):

  • profiler/ProfileGenerator.cpp:

(JSC::ProfileGenerator::willExecute):
(JSC::ProfileGenerator::didExecute):

  • profiler/ProfileNode.cpp:

(JSC::ProfileNode::debugPrintData):
(JSC::ProfileNode::debugPrintDataSampleStyle):

  • runtime/Arguments.cpp:

(JSC::Arguments::getOwnPropertySlot):
(JSC::Arguments::getOwnPropertyDescriptor):
(JSC::Arguments::put):
(JSC::Arguments::deleteProperty):

  • runtime/DateConversion.cpp:

(JSC::parseDate):

  • runtime/Identifier.h:

(JSC::Identifier::toStrictUInt32):

  • runtime/JSArray.cpp:

(JSC::JSArray::getOwnPropertySlot):
(JSC::JSArray::getOwnPropertyDescriptor):
(JSC::JSArray::put):
(JSC::JSArray::deleteProperty):

  • runtime/JSArray.h:

(JSC::toArrayIndex):

  • runtime/JSGlobalObjectFunctions.cpp:

(JSC::encode):
(JSC::parseInt):
(JSC::globalFuncJSCPrint):

  • runtime/JSString.h:

(JSC::RopeBuilder::JSString):

  • runtime/UString.cpp:

(JSC::UString::toDouble):
(JSC::putUTF8Triple):
(JSC::UString::utf8):

  • runtime/UString.h:

(JSC::UString::~UString):
(JSC::UString::isNull):
(JSC::UString::isEmpty):
(JSC::UString::impl):

  • wtf/text/WTFString.cpp:

(WTF::String::utf8):

  • wtf/text/WTFString.h:

(WTF::String::~String):
(WTF::String::swap):
(WTF::String::isNull):
(WTF::String::isEmpty):
(WTF::String::impl):
(WTF::String::length):
(WTF::String::String):
(WTF::String::isHashTableDeletedValue):

WebCore:

  • WebCore.xcodeproj/project.pbxproj:
  • bindings/js/JSDOMWindowCustom.cpp:

(WebCore::JSDOMWindow::getOwnPropertySlot):
(WebCore::JSDOMWindow::getOwnPropertyDescriptor):

  • bridge/NP_jsobject.cpp:

(_NPN_Enumerate):

  • bridge/c/c_utility.cpp:

(JSC::Bindings::convertValueToNPVariant):

  • bridge/jni/JNIBridge.cpp:

(JavaParameter::JavaParameter):
(JavaMethod::JavaMethod):
(JavaMethod::signature):
(JavaMethod::methodID):

  • bridge/jni/JNIBridge.h:

(JSC::Bindings::JavaString::utf8):
(JSC::Bindings::JavaParameter::type):
(JSC::Bindings::JavaMethod::returnType):

  • bridge/jni/jni_jsobject.mm:

(JavaJSObject::call):
(JavaJSObject::eval):
(JavaJSObject::getMember):
(JavaJSObject::setMember):
(JavaJSObject::removeMember):
(JavaJSObject::convertJObjectToValue):

  • bridge/jni/jsc/JNIBridgeJSC.cpp:

(JavaField::JavaField):
(JavaField::valueFromInstance):
(JavaField::setValueToInstance):

  • bridge/jni/jsc/JNIBridgeJSC.h:

(JSC::Bindings::JavaField::type):

  • bridge/jni/jsc/JavaInstanceJSC.cpp:

(JavaInstance::invokeMethod):

  • bridge/jni/jsc/JavaStringJSC.h:

(JSC::Bindings::JavaStringImpl::utf8):

  • bridge/runtime_array.cpp:

(JSC::RuntimeArray::getOwnPropertySlot):
(JSC::RuntimeArray::getOwnPropertyDescriptor):
(JSC::RuntimeArray::put):

WebKit/mac:

  • Plugins/Hosted/NetscapePluginInstanceProxy.mm:

(WebKit::NetscapePluginInstanceProxy::enumerate):

WebKit/wx:

  • WebFrame.cpp:

(wxWebFrame::RunScript):

WebKit2:

  • WebProcess/Plugins/JSNPObject.cpp:

(WebKit::npIdentifierFromIdentifier):

  • WebProcess/Plugins/NPJSObject.cpp:

(WebKit::NPJSObject::enumerate):

  • WebProcess/Plugins/NPRuntimeObjectMap.cpp:

(WebKit::NPRuntimeObjectMap::convertJSValueToNPVariant):

  • Property svn:eol-style set to native
File size: 14.2 KB
Line 
1/*
2 * Copyright (C) 1999-2002 Harri Porten ([email protected])
3 * Copyright (C) 2001 Peter Kelly ([email protected])
4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
5 * Copyright (C) 2007 Cameron Zwarich ([email protected])
6 * Copyright (C) 2007 Maks Orlovich
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 *
23 */
24
25#include "config.h"
26#include "JSGlobalObjectFunctions.h"
27
28#include "CallFrame.h"
29#include "GlobalEvalFunction.h"
30#include "Interpreter.h"
31#include "JSGlobalObject.h"
32#include "JSString.h"
33#include "JSStringBuilder.h"
34#include "Lexer.h"
35#include "LiteralParser.h"
36#include "Nodes.h"
37#include "Parser.h"
38#include "StringBuilder.h"
39#include "dtoa.h"
40#include <stdio.h>
41#include <stdlib.h>
42#include <wtf/ASCIICType.h>
43#include <wtf/Assertions.h>
44#include <wtf/MathExtras.h>
45#include <wtf/StringExtras.h>
46#include <wtf/unicode/UTF8.h>
47
48using namespace WTF;
49using namespace Unicode;
50
51namespace JSC {
52
53static JSValue encode(ExecState* exec, const char* doNotEscape)
54{
55 UString str = exec->argument(0).toString(exec);
56 CString cstr = str.utf8(true);
57 if (!cstr.data())
58 return throwError(exec, createURIError(exec, "String contained an illegal UTF-16 sequence."));
59
60 JSStringBuilder builder;
61 const char* p = cstr.data();
62 for (size_t k = 0; k < cstr.length(); k++, p++) {
63 char c = *p;
64 if (c && strchr(doNotEscape, c))
65 builder.append(c);
66 else {
67 char tmp[4];
68 snprintf(tmp, sizeof(tmp), "%%%02X", static_cast<unsigned char>(c));
69 builder.append(tmp);
70 }
71 }
72 return builder.build(exec);
73}
74
75static JSValue decode(ExecState* exec, const char* doNotUnescape, bool strict)
76{
77 JSStringBuilder builder;
78 UString str = exec->argument(0).toString(exec);
79 int k = 0;
80 int len = str.length();
81 const UChar* d = str.characters();
82 UChar u = 0;
83 while (k < len) {
84 const UChar* p = d + k;
85 UChar c = *p;
86 if (c == '%') {
87 int charLen = 0;
88 if (k <= len - 3 && isASCIIHexDigit(p[1]) && isASCIIHexDigit(p[2])) {
89 const char b0 = Lexer::convertHex(p[1], p[2]);
90 const int sequenceLen = UTF8SequenceLength(b0);
91 if (sequenceLen != 0 && k <= len - sequenceLen * 3) {
92 charLen = sequenceLen * 3;
93 char sequence[5];
94 sequence[0] = b0;
95 for (int i = 1; i < sequenceLen; ++i) {
96 const UChar* q = p + i * 3;
97 if (q[0] == '%' && isASCIIHexDigit(q[1]) && isASCIIHexDigit(q[2]))
98 sequence[i] = Lexer::convertHex(q[1], q[2]);
99 else {
100 charLen = 0;
101 break;
102 }
103 }
104 if (charLen != 0) {
105 sequence[sequenceLen] = 0;
106 const int character = decodeUTF8Sequence(sequence);
107 if (character < 0 || character >= 0x110000)
108 charLen = 0;
109 else if (character >= 0x10000) {
110 // Convert to surrogate pair.
111 builder.append(static_cast<UChar>(0xD800 | ((character - 0x10000) >> 10)));
112 u = static_cast<UChar>(0xDC00 | ((character - 0x10000) & 0x3FF));
113 } else
114 u = static_cast<UChar>(character);
115 }
116 }
117 }
118 if (charLen == 0) {
119 if (strict)
120 return throwError(exec, createURIError(exec, "URI error"));
121 // The only case where we don't use "strict" mode is the "unescape" function.
122 // For that, it's good to support the wonky "%u" syntax for compatibility with WinIE.
123 if (k <= len - 6 && p[1] == 'u'
124 && isASCIIHexDigit(p[2]) && isASCIIHexDigit(p[3])
125 && isASCIIHexDigit(p[4]) && isASCIIHexDigit(p[5])) {
126 charLen = 6;
127 u = Lexer::convertUnicode(p[2], p[3], p[4], p[5]);
128 }
129 }
130 if (charLen && (u == 0 || u >= 128 || !strchr(doNotUnescape, u))) {
131 c = u;
132 k += charLen - 1;
133 }
134 }
135 k++;
136 builder.append(c);
137 }
138 return builder.build(exec);
139}
140
141bool isStrWhiteSpace(UChar c)
142{
143 switch (c) {
144 // ECMA-262-5th 7.2 & 7.3
145 case 0x0009:
146 case 0x000A:
147 case 0x000B:
148 case 0x000C:
149 case 0x000D:
150 case 0x0020:
151 case 0x00A0:
152 case 0x2028:
153 case 0x2029:
154 case 0xFEFF:
155 return true;
156 default:
157 return c > 0xff && isSeparatorSpace(c);
158 }
159}
160
161static int parseDigit(unsigned short c, int radix)
162{
163 int digit = -1;
164
165 if (c >= '0' && c <= '9')
166 digit = c - '0';
167 else if (c >= 'A' && c <= 'Z')
168 digit = c - 'A' + 10;
169 else if (c >= 'a' && c <= 'z')
170 digit = c - 'a' + 10;
171
172 if (digit >= radix)
173 return -1;
174 return digit;
175}
176
177double parseIntOverflow(const char* s, int length, int radix)
178{
179 double number = 0.0;
180 double radixMultiplier = 1.0;
181
182 for (const char* p = s + length - 1; p >= s; p--) {
183 if (radixMultiplier == Inf) {
184 if (*p != '0') {
185 number = Inf;
186 break;
187 }
188 } else {
189 int digit = parseDigit(*p, radix);
190 number += digit * radixMultiplier;
191 }
192
193 radixMultiplier *= radix;
194 }
195
196 return number;
197}
198
199double parseIntOverflow(const UChar* s, int length, int radix)
200{
201 double number = 0.0;
202 double radixMultiplier = 1.0;
203
204 for (const UChar* p = s + length - 1; p >= s; p--) {
205 if (radixMultiplier == Inf) {
206 if (*p != '0') {
207 number = Inf;
208 break;
209 }
210 } else {
211 int digit = parseDigit(*p, radix);
212 number += digit * radixMultiplier;
213 }
214
215 radixMultiplier *= radix;
216 }
217
218 return number;
219}
220
221static double parseInt(const UString& s, int radix)
222{
223 int length = s.length();
224 const UChar* data = s.characters();
225 int p = 0;
226
227 while (p < length && isStrWhiteSpace(data[p]))
228 ++p;
229
230 double sign = 1;
231 if (p < length) {
232 if (data[p] == '+')
233 ++p;
234 else if (data[p] == '-') {
235 sign = -1;
236 ++p;
237 }
238 }
239
240 if ((radix == 0 || radix == 16) && length - p >= 2 && data[p] == '0' && (data[p + 1] == 'x' || data[p + 1] == 'X')) {
241 radix = 16;
242 p += 2;
243 } else if (radix == 0) {
244 if (p < length && data[p] == '0')
245 radix = 8;
246 else
247 radix = 10;
248 }
249
250 if (radix < 2 || radix > 36)
251 return NaN;
252
253 int firstDigitPosition = p;
254 bool sawDigit = false;
255 double number = 0;
256 while (p < length) {
257 int digit = parseDigit(data[p], radix);
258 if (digit == -1)
259 break;
260 sawDigit = true;
261 number *= radix;
262 number += digit;
263 ++p;
264 }
265
266 if (number >= mantissaOverflowLowerBound) {
267 if (radix == 10)
268 number = WTF::strtod(s.substr(firstDigitPosition, p - firstDigitPosition).utf8().data(), 0);
269 else if (radix == 2 || radix == 4 || radix == 8 || radix == 16 || radix == 32)
270 number = parseIntOverflow(s.substr(firstDigitPosition, p - firstDigitPosition).utf8().data(), p - firstDigitPosition, radix);
271 }
272
273 if (!sawDigit)
274 return NaN;
275
276 return sign * number;
277}
278
279static double parseFloat(const UString& s)
280{
281 // Check for 0x prefix here, because toDouble allows it, but we must treat it as 0.
282 // Need to skip any whitespace and then one + or - sign.
283 int length = s.length();
284 const UChar* data = s.characters();
285 int p = 0;
286 while (p < length && isStrWhiteSpace(data[p]))
287 ++p;
288
289 if (p < length && (data[p] == '+' || data[p] == '-'))
290 ++p;
291
292 if (length - p >= 2 && data[p] == '0' && (data[p + 1] == 'x' || data[p + 1] == 'X'))
293 return 0;
294
295 return s.toDouble(true /*tolerant*/, false /* NaN for empty string */);
296}
297
298EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec)
299{
300 JSObject* thisObject = exec->hostThisValue().toThisObject(exec);
301 JSObject* unwrappedObject = thisObject->unwrappedObject();
302 if (!unwrappedObject->isGlobalObject() || static_cast<JSGlobalObject*>(unwrappedObject)->evalFunction() != exec->callee())
303 return throwVMError(exec, createEvalError(exec, "The \"this\" value passed to eval must be the global object from which eval originated"));
304
305 JSValue x = exec->argument(0);
306 if (!x.isString())
307 return JSValue::encode(x);
308
309 UString s = x.toString(exec);
310
311 LiteralParser preparser(exec, s, LiteralParser::NonStrictJSON);
312 if (JSValue parsedObject = preparser.tryLiteralParse())
313 return JSValue::encode(parsedObject);
314
315 RefPtr<EvalExecutable> eval = EvalExecutable::create(exec, makeSource(s));
316 JSObject* error = eval->compile(exec, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node());
317 if (error)
318 return throwVMError(exec, error);
319
320 return JSValue::encode(exec->interpreter()->execute(eval.get(), exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node(), exec->exceptionSlot()));
321}
322
323EncodedJSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec)
324{
325 JSValue value = exec->argument(0);
326 int32_t radix = exec->argument(1).toInt32(exec);
327
328 if (radix != 0 && radix != 10)
329 return JSValue::encode(jsNumber(exec, parseInt(value.toString(exec), radix)));
330
331 if (value.isInt32())
332 return JSValue::encode(value);
333
334 if (value.isDouble()) {
335 double d = value.asDouble();
336 if (isfinite(d))
337 return JSValue::encode(jsNumber(exec, (d > 0) ? floor(d) : ceil(d)));
338 if (isnan(d) || isinf(d))
339 return JSValue::encode(jsNaN(exec));
340 return JSValue::encode(jsNumber(exec, 0));
341 }
342
343 return JSValue::encode(jsNumber(exec, parseInt(value.toString(exec), radix)));
344}
345
346EncodedJSValue JSC_HOST_CALL globalFuncParseFloat(ExecState* exec)
347{
348 return JSValue::encode(jsNumber(exec, parseFloat(exec->argument(0).toString(exec))));
349}
350
351EncodedJSValue JSC_HOST_CALL globalFuncIsNaN(ExecState* exec)
352{
353 return JSValue::encode(jsBoolean(isnan(exec->argument(0).toNumber(exec))));
354}
355
356EncodedJSValue JSC_HOST_CALL globalFuncIsFinite(ExecState* exec)
357{
358 double n = exec->argument(0).toNumber(exec);
359 return JSValue::encode(jsBoolean(!isnan(n) && !isinf(n)));
360}
361
362EncodedJSValue JSC_HOST_CALL globalFuncDecodeURI(ExecState* exec)
363{
364 static const char do_not_unescape_when_decoding_URI[] =
365 "#$&+,/:;=?@";
366
367 return JSValue::encode(decode(exec, do_not_unescape_when_decoding_URI, true));
368}
369
370EncodedJSValue JSC_HOST_CALL globalFuncDecodeURIComponent(ExecState* exec)
371{
372 return JSValue::encode(decode(exec, "", true));
373}
374
375EncodedJSValue JSC_HOST_CALL globalFuncEncodeURI(ExecState* exec)
376{
377 static const char do_not_escape_when_encoding_URI[] =
378 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
379 "abcdefghijklmnopqrstuvwxyz"
380 "0123456789"
381 "!#$&'()*+,-./:;=?@_~";
382
383 return JSValue::encode(encode(exec, do_not_escape_when_encoding_URI));
384}
385
386EncodedJSValue JSC_HOST_CALL globalFuncEncodeURIComponent(ExecState* exec)
387{
388 static const char do_not_escape_when_encoding_URI_component[] =
389 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
390 "abcdefghijklmnopqrstuvwxyz"
391 "0123456789"
392 "!'()*-._~";
393
394 return JSValue::encode(encode(exec, do_not_escape_when_encoding_URI_component));
395}
396
397EncodedJSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec)
398{
399 static const char do_not_escape[] =
400 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
401 "abcdefghijklmnopqrstuvwxyz"
402 "0123456789"
403 "*+-./@_";
404
405 JSStringBuilder builder;
406 UString str = exec->argument(0).toString(exec);
407 const UChar* c = str.characters();
408 for (unsigned k = 0; k < str.length(); k++, c++) {
409 int u = c[0];
410 if (u > 255) {
411 char tmp[7];
412 snprintf(tmp, sizeof(tmp), "%%u%04X", u);
413 builder.append(tmp);
414 } else if (u != 0 && strchr(do_not_escape, static_cast<char>(u)))
415 builder.append(c, 1);
416 else {
417 char tmp[4];
418 snprintf(tmp, sizeof(tmp), "%%%02X", u);
419 builder.append(tmp);
420 }
421 }
422
423 return JSValue::encode(builder.build(exec));
424}
425
426EncodedJSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec)
427{
428 StringBuilder builder;
429 UString str = exec->argument(0).toString(exec);
430 int k = 0;
431 int len = str.length();
432 while (k < len) {
433 const UChar* c = str.characters() + k;
434 UChar u;
435 if (c[0] == '%' && k <= len - 6 && c[1] == 'u') {
436 if (isASCIIHexDigit(c[2]) && isASCIIHexDigit(c[3]) && isASCIIHexDigit(c[4]) && isASCIIHexDigit(c[5])) {
437 u = Lexer::convertUnicode(c[2], c[3], c[4], c[5]);
438 c = &u;
439 k += 5;
440 }
441 } else if (c[0] == '%' && k <= len - 3 && isASCIIHexDigit(c[1]) && isASCIIHexDigit(c[2])) {
442 u = UChar(Lexer::convertHex(c[1], c[2]));
443 c = &u;
444 k += 2;
445 }
446 k++;
447 builder.append(*c);
448 }
449
450 return JSValue::encode(jsString(exec, builder.build()));
451}
452
453#ifndef NDEBUG
454EncodedJSValue JSC_HOST_CALL globalFuncJSCPrint(ExecState* exec)
455{
456 CString string = exec->argument(0).toString(exec).utf8();
457 puts(string.data());
458 return JSValue::encode(jsUndefined());
459}
460#endif
461
462} // namespace JSC
Note: See TracBrowser for help on using the repository browser.