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