Changeset 189583 in webkit for trunk/Source/JavaScriptCore/jsc.cpp
- Timestamp:
- Sep 10, 2015, 12:19:15 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/jsc.cpp
r189439 r189583 566 566 } 567 567 568 static inline String stringFromUTF(const char* utf8) 569 { 570 return String::fromUTF8WithLatin1Fallback(utf8, strlen(utf8)); 571 } 572 573 static inline SourceCode jscSource(const char* utf8, const String& filename) 568 template<typename Vector> 569 static inline String stringFromUTF(const Vector& utf8) 570 { 571 return String::fromUTF8WithLatin1Fallback(utf8.data(), utf8.size()); 572 } 573 574 template<typename Vector> 575 static inline SourceCode jscSource(const Vector& utf8, const String& filename) 574 576 { 575 577 String str = stringFromUTF(utf8); … … 702 704 703 705 static JSInternalPromise* moduleLoaderResolve(JSGlobalObject*, ExecState*, JSValue, JSValue); 704 705 static JSInternalPromise* moduleLoaderFetch(JSGlobalObject* globalObject, ExecState* exec, JSValue key) 706 { 707 JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject); 708 String moduleKey = key.toString(exec)->value(exec); 709 if (exec->hadException()) { 710 JSValue exception = exec->exception(); 711 exec->clearException(); 712 return deferred->reject(exec, exception); 713 } 714 715 // Here, now we consider moduleKey as the fileName. 716 Vector<char> utf8; 717 if (!fillBufferWithContentsOfFile(moduleKey, utf8)) 718 return deferred->reject(exec, createError(exec, makeString("Could not open file '", moduleKey, "'."))); 719 720 return deferred->resolve(exec, jsString(exec, stringFromUTF(utf8.data()))); 721 } 706 static JSInternalPromise* moduleLoaderFetch(JSGlobalObject*, ExecState*, JSValue); 722 707 }; 723 708 … … 775 760 if (firstSeparatorPosition == lastSeparatorPosition) 776 761 directoryName.queryName = StringImpl::empty(); 777 else 778 directoryName.queryName = absolutePathToFile.substring(firstSeparatorPosition + 1, lastSeparatorPosition); // Not include the separator. 762 else { 763 size_t queryStartPosition = firstSeparatorPosition + 1; 764 size_t queryLength = lastSeparatorPosition - queryStartPosition; // Not include the last separator. 765 directoryName.queryName = absolutePathToFile.substring(queryStartPosition, queryLength); 766 } 779 767 return true; 780 768 } … … 783 771 { 784 772 #if OS(WINDOWS) 785 // https://msdn.microsoft.com/en-us/library/sf98bd4y.aspx 786 char* buffer = nullptr; 787 if (!(buffer = _getcwd(nullptr, 0))) 773 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364934.aspx 774 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath 775 // The _MAX_PATH in Windows is 260. If the path of the current working directory is longer than that, _getcwd truncates the result. 776 // And other I/O functions taking a path name also truncate it. To avoid this situation, 777 // 778 // (1). When opening the file in Windows for modules, we always use the abosolute path and add "\\?\" prefix to the path name. 779 // (2). When retrieving the current working directory, use GetCurrentDirectory instead of _getcwd. 780 // 781 // In the path utility functions inside the JSC shell, we does not handle the UNC and UNCW including the network host name. 782 DWORD bufferLength = ::GetCurrentDirectoryW(0, nullptr); 783 if (!bufferLength) 788 784 return false; 789 String directoryString = String::fromUTF8(buffer); 790 free(buffer); 785 // In Windows, wchar_t is the UTF-16LE. 786 // https://msdn.microsoft.com/en-us/library/dd374081.aspx 787 // https://msdn.microsoft.com/en-us/library/windows/desktop/ff381407.aspx 788 auto buffer = std::make_unique<wchar_t[]>(bufferLength); 789 DWORD lengthNotIncludingNull = ::GetCurrentDirectoryW(bufferLength, buffer.get()); 790 static_assert(sizeof(wchar_t) == sizeof(UChar), "In Windows, both are UTF-16LE"); 791 String directoryString = String(reinterpret_cast<UChar*>(buffer.get())); 792 // We don't support network path like \\host\share\<path name>. 793 if (directoryString.startsWith("\\\\")) 794 return false; 791 795 #else 792 796 auto buffer = std::make_unique<char[]>(PATH_MAX); … … 868 872 } 869 873 874 static void convertShebangToJSComment(Vector<char>& buffer) 875 { 876 if (buffer.size() >= 2) { 877 if (buffer[0] == '#' && buffer[1] == '!') 878 buffer[0] = buffer[1] = '/'; 879 } 880 } 881 882 static void fillBufferWithContentsOfFile(FILE* file, Vector<char>& buffer) 883 { 884 fseek(file, 0, SEEK_END); 885 size_t bufferCapacity = ftell(file); 886 fseek(file, 0, SEEK_SET); 887 buffer.resize(bufferCapacity); 888 fread(buffer.data(), 1, bufferCapacity, file); 889 } 890 891 static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer) 892 { 893 FILE* f = fopen(fileName.utf8().data(), "r"); 894 if (!f) { 895 fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data()); 896 return false; 897 } 898 899 fillBufferWithContentsOfFile(f, buffer); 900 fclose(f); 901 902 return true; 903 } 904 905 static bool fetchScriptFromLocalFileSystem(const String& fileName, Vector<char>& buffer) 906 { 907 if (!fillBufferWithContentsOfFile(fileName, buffer)) 908 return false; 909 convertShebangToJSComment(buffer); 910 return true; 911 } 912 913 static bool fetchModuleFromLocalFileSystem(const String& fileName, Vector<char>& buffer) 914 { 915 // We assume that fileName is always an absolute path. 916 #if OS(WINDOWS) 917 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath 918 // Use long UNC to pass the long path name to the Windows APIs. 919 String longUNCPathName = WTF::makeString("\\\\?\\", fileName); 920 static_assert(sizeof(wchar_t) == sizeof(UChar), "In Windows, both are UTF-16LE"); 921 auto utf16Vector = longUNCPathName.charactersWithNullTermination(); 922 FILE* f = _wfopen(reinterpret_cast<wchar_t*>(utf16Vector.data()), L"rb"); 923 #else 924 FILE* f = fopen(fileName.utf8().data(), "r"); 925 #endif 926 if (!f) { 927 fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data()); 928 return false; 929 } 930 931 fillBufferWithContentsOfFile(f, buffer); 932 convertShebangToJSComment(buffer); 933 fclose(f); 934 935 return true; 936 } 937 938 JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalObject, ExecState* exec, JSValue key) 939 { 940 JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject); 941 String moduleKey = key.toString(exec)->value(exec); 942 if (exec->hadException()) { 943 JSValue exception = exec->exception(); 944 exec->clearException(); 945 return deferred->reject(exec, exception); 946 } 947 948 // Here, now we consider moduleKey as the fileName. 949 Vector<char> utf8; 950 if (!fetchModuleFromLocalFileSystem(moduleKey, utf8)) 951 return deferred->reject(exec, createError(exec, makeString("Could not open file '", moduleKey, "'."))); 952 953 return deferred->resolve(exec, jsString(exec, stringFromUTF(utf8))); 954 } 955 956 870 957 EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec) 871 958 { … … 1077 1164 String fileName = exec->argument(0).toString(exec)->value(exec); 1078 1165 Vector<char> script; 1079 if (!f illBufferWithContentsOfFile(fileName, script))1166 if (!fetchScriptFromLocalFileSystem(fileName, script)) 1080 1167 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file.")))); 1081 1168 … … 1091 1178 StopWatch stopWatch; 1092 1179 stopWatch.start(); 1093 evaluate(globalObject->globalExec(), jscSource(script .data(), fileName), JSValue(), exception);1180 evaluate(globalObject->globalExec(), jscSource(script, fileName), JSValue(), exception); 1094 1181 stopWatch.stop(); 1095 1182 … … 1103 1190 1104 1191 EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec) 1192 { 1193 String fileName = exec->argument(0).toString(exec)->value(exec); 1194 Vector<char> script; 1195 if (!fetchScriptFromLocalFileSystem(fileName, script)) 1196 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file.")))); 1197 1198 JSGlobalObject* globalObject = exec->lexicalGlobalObject(); 1199 1200 NakedPtr<Exception> evaluationException; 1201 JSValue result = evaluate(globalObject->globalExec(), jscSource(script, fileName), JSValue(), evaluationException); 1202 if (evaluationException) 1203 exec->vm().throwException(exec, evaluationException); 1204 return JSValue::encode(result); 1205 } 1206 1207 EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState* exec) 1105 1208 { 1106 1209 String fileName = exec->argument(0).toString(exec)->value(exec); … … 1109 1212 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file.")))); 1110 1213 1111 JSGlobalObject* globalObject = exec->lexicalGlobalObject(); 1112 1113 NakedPtr<Exception> evaluationException; 1114 JSValue result = evaluate(globalObject->globalExec(), jscSource(script.data(), fileName), JSValue(), evaluationException); 1115 if (evaluationException) 1116 exec->vm().throwException(exec, evaluationException); 1117 return JSValue::encode(result); 1118 } 1119 1120 EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState* exec) 1214 return JSValue::encode(jsString(exec, stringFromUTF(script))); 1215 } 1216 1217 EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec) 1121 1218 { 1122 1219 String fileName = exec->argument(0).toString(exec)->value(exec); 1123 1220 Vector<char> script; 1124 if (!fillBufferWithContentsOfFile(fileName, script)) 1125 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file.")))); 1126 1127 return JSValue::encode(jsString(exec, stringFromUTF(script.data()))); 1128 } 1129 1130 EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec) 1131 { 1132 String fileName = exec->argument(0).toString(exec)->value(exec); 1133 Vector<char> script; 1134 if (!fillBufferWithContentsOfFile(fileName, script)) 1221 if (!fetchScriptFromLocalFileSystem(fileName, script)) 1135 1222 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file.")))); 1136 1223 … … 1141 1228 1142 1229 JSValue syntaxException; 1143 bool validSyntax = checkSyntax(globalObject->globalExec(), jscSource(script .data(), fileName), &syntaxException);1230 bool validSyntax = checkSyntax(globalObject->globalExec(), jscSource(script, fileName), &syntaxException); 1144 1231 stopWatch.stop(); 1145 1232 … … 1377 1464 String fileName = exec->argument(0).toString(exec)->value(exec); 1378 1465 Vector<char> script; 1379 if (!f illBufferWithContentsOfFile(fileName, script))1466 if (!fetchScriptFromLocalFileSystem(fileName, script)) 1380 1467 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file.")))); 1381 1468 … … 1529 1616 static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scripts, bool dump, bool module) 1530 1617 { 1531 const char* script;1532 1618 String fileName; 1533 1619 Vector<char> scriptBuffer; … … 1556 1642 promise = evaluateModule(globalObject->globalExec(), fileName); 1557 1643 else { 1558 if (!f illBufferWithContentsOfFile(fileName, scriptBuffer))1644 if (!fetchScriptFromLocalFileSystem(fileName, scriptBuffer)) 1559 1645 return false; // fail early so we can catch missing files 1560 script = scriptBuffer.data();1561 1646 } 1562 1647 } else { 1563 script = scripts[i].argument; 1648 size_t commandLineLength = strlen(scripts[i].argument); 1649 scriptBuffer.resize(commandLineLength); 1650 std::copy(scripts[i].argument, scripts[i].argument + commandLineLength, scriptBuffer.begin()); 1564 1651 fileName = ASCIILiteral("[Command Line]"); 1565 1652 } … … 1569 1656 if (module) { 1570 1657 if (!promise) 1571 promise = evaluateModule(globalObject->globalExec(), jscSource(script , fileName));1658 promise = evaluateModule(globalObject->globalExec(), jscSource(scriptBuffer, fileName)); 1572 1659 globalObject->globalExec()->clearException(); 1573 1660 promise->then(globalObject->globalExec(), nullptr, errorHandler); … … 1575 1662 } else { 1576 1663 NakedPtr<Exception> evaluationException; 1577 JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(script , fileName), JSValue(), evaluationException);1664 JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(scriptBuffer, fileName), JSValue(), evaluationException); 1578 1665 success = success && !evaluationException; 1579 1666 if (dump && !evaluationException) … … 1647 1734 if (line.isEmpty()) 1648 1735 break; 1649 line.append('\0');1650 1736 1651 1737 NakedPtr<Exception> evaluationException; 1652 JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(line .data(), interpreterName), JSValue(), evaluationException);1738 JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(line, interpreterName), JSValue(), evaluationException); 1653 1739 #endif 1654 1740 if (evaluationException) … … 1840 1926 } 1841 1927 1842 static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer)1843 {1844 FILE* f = fopen(fileName.utf8().data(), "r");1845 if (!f) {1846 fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());1847 return false;1848 }1849 1850 size_t bufferSize = 0;1851 size_t bufferCapacity = 1024;1852 1853 buffer.resize(bufferCapacity);1854 1855 while (!feof(f) && !ferror(f)) {1856 bufferSize += fread(buffer.data() + bufferSize, 1, bufferCapacity - bufferSize, f);1857 if (bufferSize == bufferCapacity) { // guarantees space for trailing '\0'1858 bufferCapacity *= 2;1859 buffer.resize(bufferCapacity);1860 }1861 }1862 fclose(f);1863 buffer[bufferSize] = '\0';1864 1865 if (buffer[0] == '#' && buffer[1] == '!')1866 buffer[0] = buffer[1] = '/';1867 1868 return true;1869 }1870 1871 1928 #if OS(WINDOWS) 1872 1929 extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(int argc, const char* argv[])
Note:
See TracChangeset
for help on using the changeset viewer.