Remove excessive headers from JavaScriptCore
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSGlobalObjectFunctions.cpp
1 /*
2  *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
4  *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
5  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
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 "CatchScope.h"
30 #include "EvalExecutable.h"
31 #include "Exception.h"
32 #include "IndirectEvalExecutable.h"
33 #include "Interpreter.h"
34 #include "JSCInlines.h"
35 #include "JSFunction.h"
36 #include "JSGlobalObject.h"
37 #include "JSInternalPromise.h"
38 #include "JSModuleLoader.h"
39 #include "JSPromise.h"
40 #include "JSPromiseDeferred.h"
41 #include "JSString.h"
42 #include "JSStringBuilder.h"
43 #include "Lexer.h"
44 #include "LiteralParser.h"
45 #include "Nodes.h"
46 #include "JSCInlines.h"
47 #include "ParseInt.h"
48 #include "Parser.h"
49 #include "StackVisitor.h"
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <wtf/ASCIICType.h>
53 #include <wtf/Assertions.h>
54 #include <wtf/HexNumber.h>
55 #include <wtf/MathExtras.h>
56 #include <wtf/StringExtras.h>
57 #include <wtf/dtoa.h>
58 #include <wtf/text/StringBuilder.h>
59 #include <wtf/unicode/UTF8.h>
60
61 using namespace WTF;
62 using namespace Unicode;
63
64 namespace JSC {
65
66 static const char* const ObjectProtoCalledOnNullOrUndefinedError = "Object.prototype.__proto__ called on null or undefined";
67
68 template<unsigned charactersCount>
69 static Bitmap<256> makeCharacterBitmap(const char (&characters)[charactersCount])
70 {
71     static_assert(charactersCount > 0, "Since string literal is null terminated, characterCount is always larger than 0");
72     Bitmap<256> bitmap;
73     for (unsigned i = 0; i < charactersCount - 1; ++i)
74         bitmap.set(characters[i]);
75     return bitmap;
76 }
77
78 template<typename CharacterType>
79 static JSValue encode(ExecState* exec, const Bitmap<256>& doNotEscape, const CharacterType* characters, unsigned length)
80 {
81     VM& vm = exec->vm();
82     auto scope = DECLARE_THROW_SCOPE(vm);
83
84     // 18.2.6.1.1 Runtime Semantics: Encode ( string, unescapedSet )
85     // https://tc39.github.io/ecma262/#sec-encode
86
87     auto throwException = [&scope, exec] {
88         return JSC::throwException(exec, scope, createURIError(exec, ASCIILiteral("String contained an illegal UTF-16 sequence.")));
89     };
90
91     StringBuilder builder;
92     builder.reserveCapacity(length);
93
94     // 4. Repeat
95     auto* end = characters + length;
96     for (auto* cursor = characters; cursor != end; ++cursor) {
97         auto character = *cursor;
98
99         // 4-c. If C is in unescapedSet, then
100         if (character < doNotEscape.size() && doNotEscape.get(character)) {
101             // 4-c-i. Let S be a String containing only the code unit C.
102             // 4-c-ii. Let R be a new String value computed by concatenating the previous value of R and S.
103             builder.append(static_cast<LChar>(character));
104             continue;
105         }
106
107         // 4-d-i. If the code unit value of C is not less than 0xDC00 and not greater than 0xDFFF, throw a URIError exception.
108         if (U16_IS_TRAIL(character))
109             return throwException();
110
111         // 4-d-ii. If the code unit value of C is less than 0xD800 or greater than 0xDBFF, then
112         // 4-d-ii-1. Let V be the code unit value of C.
113         UChar32 codePoint;
114         if (!U16_IS_LEAD(character))
115             codePoint = character;
116         else {
117             // 4-d-iii. Else,
118             // 4-d-iii-1. Increase k by 1.
119             ++cursor;
120
121             // 4-d-iii-2. If k equals strLen, throw a URIError exception.
122             if (cursor == end)
123                 return throwException();
124
125             // 4-d-iii-3. Let kChar be the code unit value of the code unit at index k within string.
126             auto trail = *cursor;
127
128             // 4-d-iii-4. If kChar is less than 0xDC00 or greater than 0xDFFF, throw a URIError exception.
129             if (!U16_IS_TRAIL(trail))
130                 return throwException();
131
132             // 4-d-iii-5. Let V be UTF16Decode(C, kChar).
133             codePoint = U16_GET_SUPPLEMENTARY(character, trail);
134         }
135
136         // 4-d-iv. Let Octets be the array of octets resulting by applying the UTF-8 transformation to V, and let L be the array size.
137         LChar utf8OctetsBuffer[U8_MAX_LENGTH];
138         unsigned utf8Length = 0;
139         // We can use U8_APPEND_UNSAFE here since codePoint is either
140         // 1. non surrogate one, correct code point.
141         // 2. correct code point generated from validated lead and trail surrogates.
142         U8_APPEND_UNSAFE(utf8OctetsBuffer, utf8Length, codePoint);
143
144         // 4-d-v. Let j be 0.
145         // 4-d-vi. Repeat, while j < L
146         for (unsigned index = 0; index < utf8Length; ++index) {
147             // 4-d-vi-1. Let jOctet be the value at index j within Octets.
148             // 4-d-vi-2. Let S be a String containing three code units "%XY" where XY are two uppercase hexadecimal digits encoding the value of jOctet.
149             // 4-d-vi-3. Let R be a new String value computed by concatenating the previous value of R and S.
150             builder.append(static_cast<LChar>('%'));
151             appendByteAsHex(utf8OctetsBuffer[index], builder);
152         }
153     }
154
155     return jsString(exec, builder.toString());
156 }
157
158 static JSValue encode(ExecState* exec, const Bitmap<256>& doNotEscape)
159 {
160     return toStringView(exec, exec->argument(0), [&] (StringView view) {
161         if (view.is8Bit())
162             return encode(exec, doNotEscape, view.characters8(), view.length());
163         return encode(exec, doNotEscape, view.characters16(), view.length());
164     });
165 }
166
167 template <typename CharType>
168 ALWAYS_INLINE
169 static JSValue decode(ExecState* exec, const CharType* characters, int length, const Bitmap<256>& doNotUnescape, bool strict)
170 {
171     VM& vm = exec->vm();
172     auto scope = DECLARE_THROW_SCOPE(vm);
173
174     JSStringBuilder builder;
175     int k = 0;
176     UChar u = 0;
177     while (k < length) {
178         const CharType* p = characters + k;
179         CharType c = *p;
180         if (c == '%') {
181             int charLen = 0;
182             if (k <= length - 3 && isASCIIHexDigit(p[1]) && isASCIIHexDigit(p[2])) {
183                 const char b0 = Lexer<CharType>::convertHex(p[1], p[2]);
184                 const int sequenceLen = UTF8SequenceLength(b0);
185                 if (sequenceLen && k <= length - sequenceLen * 3) {
186                     charLen = sequenceLen * 3;
187                     char sequence[5];
188                     sequence[0] = b0;
189                     for (int i = 1; i < sequenceLen; ++i) {
190                         const CharType* q = p + i * 3;
191                         if (q[0] == '%' && isASCIIHexDigit(q[1]) && isASCIIHexDigit(q[2]))
192                             sequence[i] = Lexer<CharType>::convertHex(q[1], q[2]);
193                         else {
194                             charLen = 0;
195                             break;
196                         }
197                     }
198                     if (charLen != 0) {
199                         sequence[sequenceLen] = 0;
200                         const int character = decodeUTF8Sequence(sequence);
201                         if (character < 0 || character >= 0x110000)
202                             charLen = 0;
203                         else if (character >= 0x10000) {
204                             // Convert to surrogate pair.
205                             builder.append(static_cast<UChar>(0xD800 | ((character - 0x10000) >> 10)));
206                             u = static_cast<UChar>(0xDC00 | ((character - 0x10000) & 0x3FF));
207                         } else
208                             u = static_cast<UChar>(character);
209                     }
210                 }
211             }
212             if (charLen == 0) {
213                 if (strict)
214                     return throwException(exec, scope, createURIError(exec, ASCIILiteral("URI error")));
215                 // The only case where we don't use "strict" mode is the "unescape" function.
216                 // For that, it's good to support the wonky "%u" syntax for compatibility with WinIE.
217                 if (k <= length - 6 && p[1] == 'u'
218                         && isASCIIHexDigit(p[2]) && isASCIIHexDigit(p[3])
219                         && isASCIIHexDigit(p[4]) && isASCIIHexDigit(p[5])) {
220                     charLen = 6;
221                     u = Lexer<UChar>::convertUnicode(p[2], p[3], p[4], p[5]);
222                 }
223             }
224             if (charLen && (u >= 128 || !doNotUnescape.get(static_cast<LChar>(u)))) {
225                 builder.append(u);
226                 k += charLen;
227                 continue;
228             }
229         }
230         k++;
231         builder.append(c);
232     }
233     return builder.build(exec);
234 }
235
236 static JSValue decode(ExecState* exec, const Bitmap<256>& doNotUnescape, bool strict)
237 {
238     return toStringView(exec, exec->argument(0), [&] (StringView view) {
239         if (view.is8Bit())
240             return decode(exec, view.characters8(), view.length(), doNotUnescape, strict);
241         return decode(exec, view.characters16(), view.length(), doNotUnescape, strict);
242     });
243 }
244
245 static const int SizeOfInfinity = 8;
246
247 template <typename CharType>
248 static bool isInfinity(const CharType* data, const CharType* end)
249 {
250     return (end - data) >= SizeOfInfinity
251         && data[0] == 'I'
252         && data[1] == 'n'
253         && data[2] == 'f'
254         && data[3] == 'i'
255         && data[4] == 'n'
256         && data[5] == 'i'
257         && data[6] == 't'
258         && data[7] == 'y';
259 }
260
261 // See ecma-262 6th 11.8.3
262 template <typename CharType>
263 static double jsBinaryIntegerLiteral(const CharType*& data, const CharType* end)
264 {
265     // Binary number.
266     data += 2;
267     const CharType* firstDigitPosition = data;
268     double number = 0;
269     while (true) {
270         number = number * 2 + (*data - '0');
271         ++data;
272         if (data == end)
273             break;
274         if (!isASCIIBinaryDigit(*data))
275             break;
276     }
277     if (number >= mantissaOverflowLowerBound)
278         number = parseIntOverflow(firstDigitPosition, data - firstDigitPosition, 2);
279
280     return number;
281 }
282
283 // See ecma-262 6th 11.8.3
284 template <typename CharType>
285 static double jsOctalIntegerLiteral(const CharType*& data, const CharType* end)
286 {
287     // Octal number.
288     data += 2;
289     const CharType* firstDigitPosition = data;
290     double number = 0;
291     while (true) {
292         number = number * 8 + (*data - '0');
293         ++data;
294         if (data == end)
295             break;
296         if (!isASCIIOctalDigit(*data))
297             break;
298     }
299     if (number >= mantissaOverflowLowerBound)
300         number = parseIntOverflow(firstDigitPosition, data - firstDigitPosition, 8);
301
302     return number;
303 }
304
305 // See ecma-262 6th 11.8.3
306 template <typename CharType>
307 static double jsHexIntegerLiteral(const CharType*& data, const CharType* end)
308 {
309     // Hex number.
310     data += 2;
311     const CharType* firstDigitPosition = data;
312     double number = 0;
313     while (true) {
314         number = number * 16 + toASCIIHexValue(*data);
315         ++data;
316         if (data == end)
317             break;
318         if (!isASCIIHexDigit(*data))
319             break;
320     }
321     if (number >= mantissaOverflowLowerBound)
322         number = parseIntOverflow(firstDigitPosition, data - firstDigitPosition, 16);
323
324     return number;
325 }
326
327 // See ecma-262 6th 11.8.3
328 template <typename CharType>
329 static double jsStrDecimalLiteral(const CharType*& data, const CharType* end)
330 {
331     RELEASE_ASSERT(data < end);
332
333     size_t parsedLength;
334     double number = parseDouble(data, end - data, parsedLength);
335     if (parsedLength) {
336         data += parsedLength;
337         return number;
338     }
339
340     // Check for [+-]?Infinity
341     switch (*data) {
342     case 'I':
343         if (isInfinity(data, end)) {
344             data += SizeOfInfinity;
345             return std::numeric_limits<double>::infinity();
346         }
347         break;
348
349     case '+':
350         if (isInfinity(data + 1, end)) {
351             data += SizeOfInfinity + 1;
352             return std::numeric_limits<double>::infinity();
353         }
354         break;
355
356     case '-':
357         if (isInfinity(data + 1, end)) {
358             data += SizeOfInfinity + 1;
359             return -std::numeric_limits<double>::infinity();
360         }
361         break;
362     }
363
364     // Not a number.
365     return PNaN;
366 }
367
368 template <typename CharType>
369 static double toDouble(const CharType* characters, unsigned size)
370 {
371     const CharType* endCharacters = characters + size;
372
373     // Skip leading white space.
374     for (; characters < endCharacters; ++characters) {
375         if (!isStrWhiteSpace(*characters))
376             break;
377     }
378
379     // Empty string.
380     if (characters == endCharacters)
381         return 0.0;
382
383     double number;
384     if (characters[0] == '0' && characters + 2 < endCharacters) {
385         if ((characters[1] | 0x20) == 'x' && isASCIIHexDigit(characters[2]))
386             number = jsHexIntegerLiteral(characters, endCharacters);
387         else if ((characters[1] | 0x20) == 'o' && isASCIIOctalDigit(characters[2]))
388             number = jsOctalIntegerLiteral(characters, endCharacters);
389         else if ((characters[1] | 0x20) == 'b' && isASCIIBinaryDigit(characters[2]))
390             number = jsBinaryIntegerLiteral(characters, endCharacters);
391         else
392             number = jsStrDecimalLiteral(characters, endCharacters);
393     } else
394         number = jsStrDecimalLiteral(characters, endCharacters);
395
396     // Allow trailing white space.
397     for (; characters < endCharacters; ++characters) {
398         if (!isStrWhiteSpace(*characters))
399             break;
400     }
401     if (characters != endCharacters)
402         return PNaN;
403
404     return number;
405 }
406
407 // See ecma-262 6th 11.8.3
408 double jsToNumber(StringView s)
409 {
410     unsigned size = s.length();
411
412     if (size == 1) {
413         UChar c = s[0];
414         if (isASCIIDigit(c))
415             return c - '0';
416         if (isStrWhiteSpace(c))
417             return 0;
418         return PNaN;
419     }
420
421     if (s.is8Bit())
422         return toDouble(s.characters8(), size);
423     return toDouble(s.characters16(), size);
424 }
425
426 static double parseFloat(StringView s)
427 {
428     unsigned size = s.length();
429
430     if (size == 1) {
431         UChar c = s[0];
432         if (isASCIIDigit(c))
433             return c - '0';
434         return PNaN;
435     }
436
437     if (s.is8Bit()) {
438         const LChar* data = s.characters8();
439         const LChar* end = data + size;
440
441         // Skip leading white space.
442         for (; data < end; ++data) {
443             if (!isStrWhiteSpace(*data))
444                 break;
445         }
446
447         // Empty string.
448         if (data == end)
449             return PNaN;
450
451         return jsStrDecimalLiteral(data, end);
452     }
453
454     const UChar* data = s.characters16();
455     const UChar* end = data + size;
456
457     // Skip leading white space.
458     for (; data < end; ++data) {
459         if (!isStrWhiteSpace(*data))
460             break;
461     }
462
463     // Empty string.
464     if (data == end)
465         return PNaN;
466
467     return jsStrDecimalLiteral(data, end);
468 }
469
470 EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec)
471 {
472     VM& vm = exec->vm();
473     auto scope = DECLARE_THROW_SCOPE(vm);
474
475     JSValue x = exec->argument(0);
476     if (!x.isString())
477         return JSValue::encode(x);
478
479     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
480     if (!globalObject->evalEnabled()) {
481         throwException(exec, scope, createEvalError(exec, globalObject->evalDisabledErrorMessage()));
482         return JSValue::encode(jsUndefined());
483     }
484
485     String s = asString(x)->value(exec);
486     RETURN_IF_EXCEPTION(scope, encodedJSValue());
487
488     if (s.is8Bit()) {
489         LiteralParser<LChar> preparser(exec, s.characters8(), s.length(), NonStrictJSON);
490         if (JSValue parsedObject = preparser.tryLiteralParse())
491             return JSValue::encode(parsedObject);
492     } else {
493         LiteralParser<UChar> preparser(exec, s.characters16(), s.length(), NonStrictJSON);
494         if (JSValue parsedObject = preparser.tryLiteralParse())
495             return JSValue::encode(parsedObject);
496     }
497
498     SourceOrigin sourceOrigin = exec->callerSourceOrigin();
499     JSGlobalObject* calleeGlobalObject = exec->jsCallee()->globalObject();
500     EvalExecutable* eval = IndirectEvalExecutable::create(exec, makeSource(s, sourceOrigin), false, DerivedContextType::None, false, EvalContextType::None);
501     if (!eval)
502         return JSValue::encode(jsUndefined());
503
504     return JSValue::encode(exec->interpreter()->execute(eval, exec, calleeGlobalObject->globalThis(), calleeGlobalObject->globalScope()));
505 }
506
507 EncodedJSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec)
508 {
509     JSValue value = exec->argument(0);
510     JSValue radixValue = exec->argument(1);
511
512     // Optimized handling for numbers:
513     // If the argument is 0 or a number in range 10^-6 <= n < INT_MAX+1, then parseInt
514     // results in a truncation to integer. In the case of -0, this is converted to 0.
515     //
516     // This is also a truncation for values in the range INT_MAX+1 <= n < 10^21,
517     // however these values cannot be trivially truncated to int since 10^21 exceeds
518     // even the int64_t range. Negative numbers are a little trickier, the case for
519     // values in the range -10^21 < n <= -1 are similar to those for integer, but
520     // values in the range -1 < n <= -10^-6 need to truncate to -0, not 0.
521     static const double tenToTheMinus6 = 0.000001;
522     static const double intMaxPlusOne = 2147483648.0;
523     if (value.isNumber()) {
524         double n = value.asNumber();
525         if (((n < intMaxPlusOne && n >= tenToTheMinus6) || !n) && radixValue.isUndefinedOrNull())
526             return JSValue::encode(jsNumber(static_cast<int32_t>(n)));
527     }
528
529     // If ToString throws, we shouldn't call ToInt32.
530     return toStringView(exec, value, [&] (StringView view) {
531         return JSValue::encode(jsNumber(parseInt(view, radixValue.toInt32(exec))));
532     });
533 }
534
535 EncodedJSValue JSC_HOST_CALL globalFuncParseFloat(ExecState* exec)
536 {
537     auto viewWithString = exec->argument(0).toString(exec)->viewWithUnderlyingString(exec);
538     return JSValue::encode(jsNumber(parseFloat(viewWithString.view)));
539 }
540
541 EncodedJSValue JSC_HOST_CALL globalFuncDecodeURI(ExecState* exec)
542 {
543     static Bitmap<256> doNotUnescapeWhenDecodingURI = makeCharacterBitmap(
544         "#$&+,/:;=?@"
545     );
546
547     return JSValue::encode(decode(exec, doNotUnescapeWhenDecodingURI, true));
548 }
549
550 EncodedJSValue JSC_HOST_CALL globalFuncDecodeURIComponent(ExecState* exec)
551 {
552     static Bitmap<256> emptyBitmap;
553     return JSValue::encode(decode(exec, emptyBitmap, true));
554 }
555
556 EncodedJSValue JSC_HOST_CALL globalFuncEncodeURI(ExecState* exec)
557 {
558     static Bitmap<256> doNotEscapeWhenEncodingURI = makeCharacterBitmap(
559         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
560         "abcdefghijklmnopqrstuvwxyz"
561         "0123456789"
562         "!#$&'()*+,-./:;=?@_~"
563     );
564
565     return JSValue::encode(encode(exec, doNotEscapeWhenEncodingURI));
566 }
567
568 EncodedJSValue JSC_HOST_CALL globalFuncEncodeURIComponent(ExecState* exec)
569 {
570     static Bitmap<256> doNotEscapeWhenEncodingURIComponent = makeCharacterBitmap(
571         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
572         "abcdefghijklmnopqrstuvwxyz"
573         "0123456789"
574         "!'()*-._~"
575     );
576
577     return JSValue::encode(encode(exec, doNotEscapeWhenEncodingURIComponent));
578 }
579
580 EncodedJSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec)
581 {
582     static Bitmap<256> doNotEscape = makeCharacterBitmap(
583         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
584         "abcdefghijklmnopqrstuvwxyz"
585         "0123456789"
586         "*+-./@_"
587     );
588
589     return JSValue::encode(toStringView(exec, exec->argument(0), [&] (StringView view) {
590         JSStringBuilder builder;
591         if (view.is8Bit()) {
592             const LChar* c = view.characters8();
593             for (unsigned k = 0; k < view.length(); k++, c++) {
594                 int u = c[0];
595                 if (doNotEscape.get(static_cast<LChar>(u)))
596                     builder.append(*c);
597                 else {
598                     builder.append(static_cast<LChar>('%'));
599                     appendByteAsHex(static_cast<LChar>(u), builder);
600                 }
601             }
602
603             return builder.build(exec);
604         }
605
606         const UChar* c = view.characters16();
607         for (unsigned k = 0; k < view.length(); k++, c++) {
608             UChar u = c[0];
609             if (u >= doNotEscape.size()) {
610                 builder.append(static_cast<LChar>('%'));
611                 builder.append(static_cast<LChar>('u'));
612                 appendByteAsHex(u >> 8, builder);
613                 appendByteAsHex(u & 0xFF, builder);
614             } else if (doNotEscape.get(static_cast<LChar>(u)))
615                 builder.append(*c);
616             else {
617                 builder.append(static_cast<LChar>('%'));
618                 appendByteAsHex(u, builder);
619             }
620         }
621
622         return builder.build(exec);
623     }));
624 }
625
626 EncodedJSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec)
627 {
628     return JSValue::encode(toStringView(exec, exec->argument(0), [&] (StringView view) {
629         // We use int for k and length intentionally since we would like to evaluate
630         // the condition `k <= length -6` even if length is less than 6.
631         int k = 0;
632         int length = view.length();
633
634         StringBuilder builder;
635         builder.reserveCapacity(length);
636
637         if (view.is8Bit()) {
638             const LChar* characters = view.characters8();
639             LChar convertedLChar;
640             while (k < length) {
641                 const LChar* c = characters + k;
642                 if (c[0] == '%' && k <= length - 6 && c[1] == 'u') {
643                     if (isASCIIHexDigit(c[2]) && isASCIIHexDigit(c[3]) && isASCIIHexDigit(c[4]) && isASCIIHexDigit(c[5])) {
644                         builder.append(Lexer<UChar>::convertUnicode(c[2], c[3], c[4], c[5]));
645                         k += 6;
646                         continue;
647                     }
648                 } else if (c[0] == '%' && k <= length - 3 && isASCIIHexDigit(c[1]) && isASCIIHexDigit(c[2])) {
649                     convertedLChar = LChar(Lexer<LChar>::convertHex(c[1], c[2]));
650                     c = &convertedLChar;
651                     k += 2;
652                 }
653                 builder.append(*c);
654                 k++;
655             }
656         } else {
657             const UChar* characters = view.characters16();
658
659             while (k < length) {
660                 const UChar* c = characters + k;
661                 UChar convertedUChar;
662                 if (c[0] == '%' && k <= length - 6 && c[1] == 'u') {
663                     if (isASCIIHexDigit(c[2]) && isASCIIHexDigit(c[3]) && isASCIIHexDigit(c[4]) && isASCIIHexDigit(c[5])) {
664                         convertedUChar = Lexer<UChar>::convertUnicode(c[2], c[3], c[4], c[5]);
665                         c = &convertedUChar;
666                         k += 5;
667                     }
668                 } else if (c[0] == '%' && k <= length - 3 && isASCIIHexDigit(c[1]) && isASCIIHexDigit(c[2])) {
669                     convertedUChar = UChar(Lexer<UChar>::convertHex(c[1], c[2]));
670                     c = &convertedUChar;
671                     k += 2;
672                 }
673                 k++;
674                 builder.append(*c);
675             }
676         }
677
678         return jsString(exec, builder.toString());
679     }));
680 }
681
682 EncodedJSValue JSC_HOST_CALL globalFuncThrowTypeError(ExecState* exec)
683 {
684     VM& vm = exec->vm();
685     auto scope = DECLARE_THROW_SCOPE(vm);
686     return throwVMTypeError(exec, scope);
687 }
688
689 EncodedJSValue JSC_HOST_CALL globalFuncThrowTypeErrorArgumentsCalleeAndCaller(ExecState* exec)
690 {
691     VM& vm = exec->vm();
692     auto scope = DECLARE_THROW_SCOPE(vm);
693     return throwVMTypeError(exec, scope, "'arguments', 'callee', and 'caller' cannot be accessed in this context.");
694 }
695
696 EncodedJSValue JSC_HOST_CALL globalFuncProtoGetter(ExecState* exec)
697 {
698     VM& vm = exec->vm();
699     auto scope = DECLARE_THROW_SCOPE(vm);
700
701     JSValue thisValue = exec->thisValue().toThis(exec, StrictMode);
702     if (thisValue.isUndefinedOrNull())
703         return throwVMTypeError(exec, scope, ASCIILiteral(ObjectProtoCalledOnNullOrUndefinedError));
704
705     JSObject* thisObject = jsDynamicCast<JSObject*>(vm, thisValue);
706     if (!thisObject) {
707         JSObject* prototype = exec->thisValue().synthesizePrototype(exec);
708         if (UNLIKELY(!prototype))
709             return JSValue::encode(JSValue());
710         return JSValue::encode(prototype);
711     }
712
713     return JSValue::encode(thisObject->getPrototype(vm, exec));
714 }
715
716 EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState* exec)
717 {
718     VM& vm = exec->vm();
719     auto scope = DECLARE_THROW_SCOPE(vm);
720
721     JSValue thisValue = exec->thisValue().toThis(exec, StrictMode);
722     if (thisValue.isUndefinedOrNull())
723         return throwVMTypeError(exec, scope, ASCIILiteral(ObjectProtoCalledOnNullOrUndefinedError));
724
725     JSValue value = exec->argument(0);
726
727     JSObject* thisObject = jsDynamicCast<JSObject*>(vm, thisValue);
728
729     // Setting __proto__ of a primitive should have no effect.
730     if (!thisObject)
731         return JSValue::encode(jsUndefined());
732
733     // Setting __proto__ to a non-object, non-null value is silently ignored to match Mozilla.
734     if (!value.isObject() && !value.isNull())
735         return JSValue::encode(jsUndefined());
736
737     bool shouldThrowIfCantSet = true;
738     thisObject->setPrototype(vm, exec, value, shouldThrowIfCantSet);
739     return JSValue::encode(jsUndefined());
740 }
741
742 EncodedJSValue JSC_HOST_CALL globalFuncHostPromiseRejectionTracker(ExecState* exec)
743 {
744     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
745     VM& vm = globalObject->vm();
746     auto scope = DECLARE_THROW_SCOPE(vm);
747
748     if (!globalObject->globalObjectMethodTable()->promiseRejectionTracker)
749         return JSValue::encode(jsUndefined());
750
751     JSPromise* promise = jsCast<JSPromise*>(exec->argument(0));
752     JSValue operationValue = exec->argument(1);
753
754     ASSERT(operationValue.isNumber());
755     auto operation = static_cast<JSPromiseRejectionOperation>(operationValue.toUInt32(exec));
756     ASSERT(operation == JSPromiseRejectionOperation::Reject || operation == JSPromiseRejectionOperation::Handle);
757     scope.assertNoException();
758
759     globalObject->globalObjectMethodTable()->promiseRejectionTracker(globalObject, exec, promise, operation);
760     RETURN_IF_EXCEPTION(scope, { });
761
762     return JSValue::encode(jsUndefined());
763 }
764
765 EncodedJSValue JSC_HOST_CALL globalFuncBuiltinLog(ExecState* exec)
766 {
767     dataLog(exec->argument(0).toWTFString(exec), "\n");
768     return JSValue::encode(jsUndefined());
769 }
770
771 EncodedJSValue JSC_HOST_CALL globalFuncImportModule(ExecState* exec)
772 {
773     VM& vm = exec->vm();
774     auto catchScope = DECLARE_CATCH_SCOPE(vm);
775
776     auto* globalObject = exec->lexicalGlobalObject();
777
778     auto* promise = JSPromiseDeferred::create(exec, globalObject);
779     RETURN_IF_EXCEPTION(catchScope, { });
780
781     auto sourceOrigin = exec->callerSourceOrigin();
782     RELEASE_ASSERT(exec->argumentCount() == 1);
783     auto* specifier = exec->uncheckedArgument(0).toString(exec);
784     if (Exception* exception = catchScope.exception()) {
785         catchScope.clearException();
786         promise->reject(exec, exception->value());
787         return JSValue::encode(promise->promise());
788     }
789
790     auto* internalPromise = globalObject->moduleLoader()->importModule(exec, specifier, sourceOrigin);
791     if (Exception* exception = catchScope.exception()) {
792         catchScope.clearException();
793         promise->reject(exec, exception->value());
794         return JSValue::encode(promise->promise());
795     }
796     promise->resolve(exec, internalPromise);
797
798     return JSValue::encode(promise->promise());
799 }
800
801 EncodedJSValue JSC_HOST_CALL globalFuncPropertyIsEnumerable(ExecState* exec)
802 {
803     VM& vm = exec->vm();
804     auto scope = DECLARE_THROW_SCOPE(vm);
805
806     RELEASE_ASSERT(exec->argumentCount() == 2);
807     JSObject* object = jsCast<JSObject*>(exec->uncheckedArgument(0));
808     auto propertyName = exec->uncheckedArgument(1).toPropertyKey(exec);
809     RETURN_IF_EXCEPTION(scope, encodedJSValue());
810
811     scope.release();
812     PropertyDescriptor descriptor;
813     bool enumerable = object->getOwnPropertyDescriptor(exec, propertyName, descriptor) && descriptor.enumerable();
814     return JSValue::encode(jsBoolean(enumerable));
815 }
816
817 } // namespace JSC