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