--- node/deps/v8/include/v8.h +++ node/deps/v8/include/v8.h @@ -1304,10 +1304,12 @@ kConsumeParserCache, kProduceCodeCache, kConsumeCodeCache }; + static Local EncloseParseToAst(Isolate* isolate, Local code); + /** * Compiles the specified script (context-independent). * Cached data as part of the source object can be optionally produced to be * consumed later to speed up compilation of identical source scripts. * @@ -6241,10 +6243,14 @@ */ static void SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags); + static void EncloseReadBytecode(const FunctionCallbackInfo& args); + static void EncloseWriteBytecode(); + static void CpuFeaturesProbeTrue(); + /** Get the version string. */ static const char* GetVersion(); /** Callback function for reporting failed access checks.*/ V8_INLINE static V8_DEPRECATED( --- node/deps/v8/src/api.cc +++ node/deps/v8/src/api.cc @@ -13,13 +13,15 @@ #include #include "include/v8-debug.h" #include "include/v8-experimental.h" #include "include/v8-profiler.h" #include "include/v8-testing.h" +#include "include/libplatform/libplatform.h" #include "src/accessors.h" #include "src/api-experimental.h" #include "src/api-natives.h" +#include "src/ast/prettyprinter.h" #include "src/assert-scope.h" #include "src/background-parsing-task.h" #include "src/base/functional.h" #include "src/base/platform/platform.h" #include "src/base/platform/time.h" @@ -64,10 +66,14 @@ #include "src/v8.h" #include "src/v8threads.h" #include "src/version.h" #include "src/vm-state-inl.h" +#ifdef V8_OS_WIN +#include // For _setmode +#include // For _setmode +#endif namespace v8 { #define LOG_API(isolate, expr) LOG(isolate, ApiEntryCall(expr)) @@ -455,10 +461,241 @@ void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) { i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags); } +void DumpException(Local context, Local message) { + String::Utf8Value message_string(message->Get()); + auto line_number = message->GetLineNumber(context); + auto message_line_value = message->GetSourceLine(context); + String::Utf8Value message_line(message_line_value.ToLocalChecked()); + base::OS::PrintError("%s at line %d\n", *message_string, line_number); + base::OS::PrintError("%s\n", *message_line); + for (int i = 0; i <= message->GetEndColumn(); ++i) { + int start_column = message->GetStartColumn(context).FromJust(); + base::OS::PrintError("%c", i < start_column ? ' ' : '^'); + } + base::OS::PrintError("\n"); +} + + +void FixScript(Isolate* v8_isolate, Local script) { + auto isolate = reinterpret_cast(v8_isolate); + auto obj = i::Handle::cast(Utils::OpenHandle(*script)); + i::Handle function_info( + i::SharedFunctionInfo::cast(*obj), obj->GetIsolate()); + auto s = reinterpret_cast(function_info->script()); + s->set_source(isolate->heap()->undefined_value()); +} + + +uint8_t* GetExtraFromStdin(uint8_t** pbuffer, int* psize) { + +#ifdef V8_OS_WIN + _setmode(_fileno(stdin), _O_BINARY); +#endif + + int read; + uint32_t length; + + read = static_cast(fread(&length, 1, sizeof(length), stdin)); + if (read != sizeof(length)) { + base::OS::PrintError("EncloseJS: Invalid stdin provided.\n"); + exit(1); + } + + *psize = static_cast(length); + auto dispose_me = i::NewArray(*psize); + + for (int i = 0; i < *psize;) { + read = static_cast(fread(&dispose_me[i], 1, *psize - i, stdin)); + if (ferror(stdin) != 0) { + base::OS::PrintError("EncloseJS: Error reading from stdin.\n"); + exit(1); + } + i += read; + } + + *pbuffer = dispose_me; + return dispose_me; + +} + + +void PutBytecodeToStdout(const uint8_t* buffer, int size) { + +#ifdef V8_OS_WIN + _setmode(_fileno(stdout), _O_BINARY); +#endif + + int written; + + for (int i = 0; i < size;) { + written = static_cast(fwrite(&buffer[i], 1, size - i, stdout)); + if (ferror(stdout) != 0) { + base::OS::PrintError("EncloseJS: Error writing to stdout.\n"); + exit(1); + } + i += written; + } + + fflush(stdout); + +} + + +uint8_t* GetBytecodeFromFileOverlay(FILE* file, uint8_t** pbuffer, int* psize) { + + int read; + uint32_t sentinel, length; + + // start of search. WARNING! THIS VALUE DIFFERS IN NODE BRANCHES + if (file == NULL || fseek(file, 12 * 1024 * 1024, SEEK_SET) != 0) { + base::OS::PrintError("EncloseJS: Error reading file.\n"); + exit(1); + } + + while (true) { + read = static_cast(fread(&sentinel, 1, sizeof(sentinel), file)); + if (read != sizeof(length)) { + base::OS::PrintError("EncloseJS: Invalid file provided.\n"); + exit(1); + } + if (sentinel != 0x26e0c928) continue; + fread(&length, 1, sizeof(length), file); + if ((sentinel^length) != 0x6713e24e) continue; // 0x26e0c928^0x41f32b66 + fread(&sentinel, 1, sizeof(sentinel), file); + if (sentinel != 0x3ea13ccf) continue; + break; + } + + fread(&length, 1, sizeof(length), file); + *psize = static_cast(length); + auto dispose_me = i::NewArray(*psize); + + for (int i = 0; i < *psize;) { + read = static_cast(fread(&dispose_me[i], 1, *psize - i, file)); + if (ferror(file) != 0) { + base::OS::PrintError("EncloseJS: Error reading from file.\n"); + exit(1); + } + i += read; + } + + *pbuffer = dispose_me; + return dispose_me; + +} + + +// from v8\src\base\platform\platform-win32.cc +int wfopen_s(FILE** pFile, const char* filename, const char* mode) { +#ifdef V8_OS_WIN + WCHAR filename_w[32768]; + WCHAR mode_w[16]; + if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, filename_w, sizeof(filename_w)) && + MultiByteToWideChar(CP_UTF8, 0, mode, -1, mode_w, sizeof(mode_w))) { + *pFile = _wfopen(filename_w, mode_w); + if (*pFile != NULL) return 0; + } +#endif + *pFile = fopen(filename, mode); + return *pFile != NULL ? 0 : 1; +} + + +// from v8\src\base\platform\platform-win32.cc +FILE* WFOpen(const char* path, const char* mode) { + FILE* result; + if (wfopen_s(&result, path, mode) == 0) { + return result; + } else { + return NULL; + } +} + + +void V8::EncloseReadBytecode(const FunctionCallbackInfo& args) { + + String::Utf8Value filename(args[0]); + auto file = WFOpen(*filename, "rb"); + uint8_t* buffer; int size; + auto dispose_me = GetBytecodeFromFileOverlay(file, &buffer, &size); + auto iso = Isolate::GetCurrent(); + + { + + Isolate::Scope iscope(iso); + HandleScope hscope(iso); + auto context = iso->GetCurrentContext(); + Context::Scope cscope(context); + + auto bp = ScriptCompiler::CachedData::BufferNotOwned; + auto data = new ScriptCompiler::CachedData(buffer, size, bp); + auto source_string = String::NewFromUtf8( + iso, "e", NewStringType::kNormal).ToLocalChecked(); + ScriptCompiler::Source source(source_string, data); + auto script = ScriptCompiler::CompileUnbound(iso, &source, + ScriptCompiler::kConsumeCodeCache); + + if (!data->rejected) { + FixScript(iso, script); + auto result = script->BindToCurrentContext() + ->Run(iso->GetCurrentContext()).ToLocalChecked(); + args.GetReturnValue().Set(result); + } + + } + + i::DeleteArray(dispose_me); + fclose(file); + +} + + +void V8::EncloseWriteBytecode() { + + // KLOPOV: dont log + i::FLAG_log_code = false; + // KLOPOV: ship harmony. disallow to change it at runtime + i::FLAG_harmony_shipping = true; + i::FLAG_logfile_per_isolate = false; + i::FLAG_serialize_toplevel = true; + i::FLAG_lazy = false; + + uint8_t* buffer; int size; + auto dispose_me = GetExtraFromStdin(&buffer, &size); + auto iso = Isolate::GetCurrent(); + + TryCatch try_catch; + + auto source_string = String::NewFromUtf8( + iso, (char*) buffer, NewStringType::kNormal, size).ToLocalChecked(); + auto origin_string = String::NewFromUtf8( + iso, "e", NewStringType::kNormal).ToLocalChecked(); + ScriptCompiler::Source source(source_string, ScriptOrigin(origin_string)); + ScriptCompiler::CompileUnbound(iso, &source, + ScriptCompiler::kProduceCodeCache); + + if (try_catch.HasCaught()) { + base::OS::PrintError("EncloseJS: compilation failed.\n"); + DumpException(iso->GetCurrentContext(), try_catch.Message()); + exit(1); + } + + auto data = source.GetCachedData(); + PutBytecodeToStdout(data->data, data->length); + i::DeleteArray(dispose_me); + +} + + +void V8::CpuFeaturesProbeTrue() { + i::CpuFeatures::Probe(true); +} + + RegisteredExtension* RegisteredExtension::first_extension_ = NULL; RegisteredExtension::RegisteredExtension(Extension* extension) : extension_(extension) { } @@ -2098,10 +2338,42 @@ ScriptOrigin origin(file_name); return Compile(context, source, &origin).FromMaybe(Local