diff --git a/common.gypi b/common.gypi index 727d22d5ab6..5dece718026 100644 --- a/common.gypi +++ b/common.gypi @@ -29,7 +29,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.4', + 'v8_embedder_string': '-node.7', # Enable disassembler for `--print-code` v8 options 'v8_enable_disassembler': 1, diff --git a/deps/v8/src/heap/gc-tracer.cc b/deps/v8/src/heap/gc-tracer.cc index ddfcd07cc12..e14fbb4862e 100644 --- a/deps/v8/src/heap/gc-tracer.cc +++ b/deps/v8/src/heap/gc-tracer.cc @@ -490,6 +490,8 @@ void GCTracer::PrintNVP() const { "promotion_rate=%.1f%% " "semi_space_copy_rate=%.1f%% " "new_space_allocation_throughput=%.1f " + "unmapper_chunks=%d " + "unmapper_delayed_chunks=%d " "context_disposal_rate=%.1f\n", duration, spent_in_mutator, current_.TypeName(true), current_.reduce_memory, current_.scopes[Scope::HEAP_PROLOGUE], @@ -520,6 +522,8 @@ void GCTracer::PrintNVP() const { AverageSurvivalRatio(), heap_->promotion_rate_, heap_->semi_space_copied_rate_, NewSpaceAllocationThroughputInBytesPerMillisecond(), + heap_->memory_allocator()->unmapper()->NumberOfChunks(), + heap_->memory_allocator()->unmapper()->NumberOfDelayedChunks(), ContextDisposalRateInMilliseconds()); break; case Event::MINOR_MARK_COMPACTOR: @@ -654,6 +658,8 @@ void GCTracer::PrintNVP() const { "promotion_rate=%.1f%% " "semi_space_copy_rate=%.1f%% " "new_space_allocation_throughput=%.1f " + "unmapper_chunks=%d " + "unmapper_delayed_chunks=%d " "context_disposal_rate=%.1f " "compaction_speed=%.f\n", duration, spent_in_mutator, current_.TypeName(true), @@ -731,6 +737,8 @@ void GCTracer::PrintNVP() const { AverageSurvivalRatio(), heap_->promotion_rate_, heap_->semi_space_copied_rate_, NewSpaceAllocationThroughputInBytesPerMillisecond(), + heap_->memory_allocator()->unmapper()->NumberOfChunks(), + heap_->memory_allocator()->unmapper()->NumberOfDelayedChunks(), ContextDisposalRateInMilliseconds(), CompactionSpeedInBytesPerMillisecond()); break; diff --git a/deps/v8/src/heap/heap.cc b/deps/v8/src/heap/heap.cc index 0b5a90afb08..b13ec784f56 100644 --- a/deps/v8/src/heap/heap.cc +++ b/deps/v8/src/heap/heap.cc @@ -1885,6 +1885,12 @@ void Heap::Scavenge() { IncrementalMarking::PauseBlackAllocationScope pause_black_allocation( incremental_marking()); + if (mark_compact_collector()->sweeper().sweeping_in_progress() && + memory_allocator_->unmapper()->NumberOfDelayedChunks() > + static_cast(new_space_->MaximumCapacity() / Page::kPageSize)) { + mark_compact_collector()->EnsureSweepingCompleted(); + } + mark_compact_collector()->sweeper().EnsureNewSpaceCompleted(); SetGCState(SCAVENGE); diff --git a/deps/v8/src/heap/spaces.cc b/deps/v8/src/heap/spaces.cc index 66c63e58635..74fee75673c 100644 --- a/deps/v8/src/heap/spaces.cc +++ b/deps/v8/src/heap/spaces.cc @@ -408,6 +408,15 @@ void MemoryAllocator::Unmapper::ReconsiderDelayedChunks() { } } +int MemoryAllocator::Unmapper::NumberOfChunks() { + base::LockGuard guard(&mutex_); + size_t result = 0; + for (int i = 0; i < kNumberOfChunkQueues; i++) { + result += chunks_[i].size(); + } + return static_cast(result); +} + bool MemoryAllocator::CanFreeMemoryChunk(MemoryChunk* chunk) { MarkCompactCollector* mc = isolate_->heap()->mark_compact_collector(); // We cannot free a memory chunk in new space while the sweeper is running diff --git a/deps/v8/src/heap/spaces.h b/deps/v8/src/heap/spaces.h index d5dc5b1115c..4f4de139e45 100644 --- a/deps/v8/src/heap/spaces.h +++ b/deps/v8/src/heap/spaces.h @@ -1199,6 +1199,13 @@ class V8_EXPORT_PRIVATE MemoryAllocator { bool has_delayed_chunks() { return delayed_regular_chunks_.size() > 0; } + int NumberOfDelayedChunks() { + base::LockGuard guard(&mutex_); + return static_cast(delayed_regular_chunks_.size()); + } + + int NumberOfChunks(); + private: static const int kReservedQueueingSlots = 64; static const int kMaxUnmapperTasks = 24; diff --git a/lib/internal/loader/Loader.js b/lib/internal/loader/Loader.js index b1b99814f4f..f2c7fa0cfff 100644 --- a/lib/internal/loader/Loader.js +++ b/lib/internal/loader/Loader.js @@ -2,10 +2,7 @@ const { getURLFromFilePath } = require('internal/url'); -const { - getNamespaceOfModuleWrap, - createDynamicModule -} = require('internal/loader/ModuleWrap'); +const { createDynamicModule } = require('internal/loader/ModuleWrap'); const ModuleMap = require('internal/loader/ModuleMap'); const ModuleJob = require('internal/loader/ModuleJob'); @@ -100,7 +97,7 @@ class Loader { async import(specifier, parentURL = this.base) { const job = await this.getModuleJob(specifier, parentURL); const module = await job.run(); - return getNamespaceOfModuleWrap(module); + return module.namespace(); } } Object.setPrototypeOf(Loader.prototype, null); diff --git a/lib/internal/loader/ModuleWrap.js b/lib/internal/loader/ModuleWrap.js index 7e5d2be6166..bd1e1f27534 100644 --- a/lib/internal/loader/ModuleWrap.js +++ b/lib/internal/loader/ModuleWrap.js @@ -5,13 +5,6 @@ const debug = require('util').debuglog('esm'); const ArrayJoin = Function.call.bind(Array.prototype.join); const ArrayMap = Function.call.bind(Array.prototype.map); -const getNamespaceOfModuleWrap = (m) => { - const tmp = new ModuleWrap('import * as _ from "";_;', ''); - tmp.link(async () => m); - tmp.instantiate(); - return tmp.evaluate(); -}; - const createDynamicModule = (exports, url = '', evaluate) => { debug( `creating ESM facade for ${url} with exports: ${ArrayJoin(exports, ', ')}` @@ -56,6 +49,5 @@ const createDynamicModule = (exports, url = '', evaluate) => { module.exports = { createDynamicModule, - getNamespaceOfModuleWrap, ModuleWrap }; diff --git a/lib/module.js b/lib/module.js index e92c0b61d9e..921a57a8142 100644 --- a/lib/module.js +++ b/lib/module.js @@ -431,11 +431,12 @@ Module._load = function(request, parent, isMain) { ESMLoader = new Loader(); const userLoader = process.binding('config').userLoader; if (userLoader) { - const hooks = await new Loader().import(userLoader); + const hooks = await ESMLoader.import(userLoader); + ESMLoader = new Loader(); ESMLoader.hook(hooks); } } - await ESMLoader.import(getURLFromFilePath(request).href); + await ESMLoader.import(getURLFromFilePath(request).pathname); })() .catch((e) => { console.error(e); diff --git a/src/module_wrap.cc b/src/module_wrap.cc index bda760369e9..92dc9cf9179 100644 --- a/src/module_wrap.cc +++ b/src/module_wrap.cc @@ -207,6 +207,29 @@ void ModuleWrap::Evaluate(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(ret); } +void ModuleWrap::Namespace(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + auto isolate = args.GetIsolate(); + auto that = args.This(); + ModuleWrap* obj = Unwrap(that); + CHECK_NE(obj, nullptr); + + auto module = obj->module_.Get(isolate); + + switch (module->GetStatus()) { + default: + return env->ThrowError( + "cannot get namespace, Module has not been instantiated"); + case v8::Module::Status::kInstantiated: + case v8::Module::Status::kEvaluating: + case v8::Module::Status::kEvaluated: + break; + } + + auto result = module->GetModuleNamespace(); + args.GetReturnValue().Set(result); +} + MaybeLocal ModuleWrap::ResolveCallback(Local context, Local specifier, Local referrer) { @@ -520,6 +543,7 @@ void ModuleWrap::Initialize(Local target, env->SetProtoMethod(tpl, "link", Link); env->SetProtoMethod(tpl, "instantiate", Instantiate); env->SetProtoMethod(tpl, "evaluate", Evaluate); + env->SetProtoMethod(tpl, "namespace", Namespace); target->Set(FIXED_ONE_BYTE_STRING(isolate, "ModuleWrap"), tpl->GetFunction()); env->SetMethod(target, "resolve", node::loader::ModuleWrap::Resolve); diff --git a/src/module_wrap.h b/src/module_wrap.h index 82fd1d89ffd..ac2f90476d5 100644 --- a/src/module_wrap.h +++ b/src/module_wrap.h @@ -34,6 +34,7 @@ class ModuleWrap : public BaseObject { static void Link(const v8::FunctionCallbackInfo& args); static void Instantiate(const v8::FunctionCallbackInfo& args); static void Evaluate(const v8::FunctionCallbackInfo& args); + static void Namespace(const v8::FunctionCallbackInfo& args); static void GetUrl(v8::Local property, const v8::PropertyCallbackInfo& info); static void Resolve(const v8::FunctionCallbackInfo& args); diff --git a/src/node_http2.cc b/src/node_http2.cc index 568b59b5b4d..4b29013636b 100644 --- a/src/node_http2.cc +++ b/src/node_http2.cc @@ -824,7 +824,7 @@ int Http2Session::DoWrite(WriteWrap* req_wrap, return 0; } -void Http2Session::AllocateSend(size_t recommended, uv_buf_t* buf) { +void Http2Session::AllocateSend(uv_buf_t* buf) { buf->base = stream_alloc(); buf->len = kAllocBufferSize; } diff --git a/src/node_http2.h b/src/node_http2.h index 3e90c49cd77..e35c189ea68 100644 --- a/src/node_http2.h +++ b/src/node_http2.h @@ -331,7 +331,8 @@ class Http2Options { padding_strategy_type padding_strategy_ = PADDING_STRATEGY_NONE; }; -static const size_t kAllocBufferSize = 64 * 1024; +// This allows for 4 default-sized frames with their frame headers +static const size_t kAllocBufferSize = 4 * (16384 + 9); typedef uint32_t(*get_setting)(nghttp2_session* session, nghttp2_settings_id id); @@ -414,7 +415,7 @@ class Http2Session : public AsyncWrap, void OnFrameError(int32_t id, uint8_t type, int error_code) override; void OnTrailers(Nghttp2Stream* stream, const SubmitTrailers& submit_trailers) override; - void AllocateSend(size_t recommended, uv_buf_t* buf) override; + void AllocateSend(uv_buf_t* buf) override; int DoWrite(WriteWrap* w, uv_buf_t* bufs, size_t count, uv_stream_t* send_handle) override; diff --git a/src/node_http2_core-inl.h b/src/node_http2_core-inl.h index 9735e565b2f..5f6016a510e 100644 --- a/src/node_http2_core-inl.h +++ b/src/node_http2_core-inl.h @@ -490,7 +490,7 @@ inline void Nghttp2Session::SendPendingData() { return; uv_buf_t dest; - AllocateSend(SEND_BUFFER_RECOMMENDED_SIZE, &dest); + AllocateSend(&dest); size_t destLength = 0; // amount of data stored in dest size_t destRemaining = dest.len; // amount space remaining in dest size_t destOffset = 0; // current write offset of dest diff --git a/src/node_http2_core.h b/src/node_http2_core.h index bb536f1159d..a7808ea0492 100644 --- a/src/node_http2_core.h +++ b/src/node_http2_core.h @@ -42,7 +42,6 @@ class Nghttp2Stream; struct nghttp2_stream_write_t; #define MAX_BUFFER_COUNT 16 -#define SEND_BUFFER_RECOMMENDED_SIZE 4096 enum nghttp2_session_type { NGHTTP2_SESSION_SERVER, @@ -178,7 +177,7 @@ class Nghttp2Session { virtual ssize_t GetPadding(size_t frameLength, size_t maxFrameLength) { return 0; } virtual void OnFreeSession() {} - virtual void AllocateSend(size_t suggested_size, uv_buf_t* buf) = 0; + virtual void AllocateSend(uv_buf_t* buf) = 0; virtual bool HasGetPaddingCallback() { return false; } diff --git a/test/es-module/test-esm-loader-dependency.mjs b/test/es-module/test-esm-loader-dependency.mjs new file mode 100644 index 00000000000..5d05118dbf2 --- /dev/null +++ b/test/es-module/test-esm-loader-dependency.mjs @@ -0,0 +1,5 @@ +// Flags: --experimental-modules --loader ./test/fixtures/es-module-loaders/loader-with-dep.mjs +/* eslint-disable required-modules */ +import './test-esm-ok.mjs'; + +// We just test that this module doesn't fail loading diff --git a/test/fixtures/es-module-loaders/loader-dep.js b/test/fixtures/es-module-loaders/loader-dep.js new file mode 100644 index 00000000000..cf821afec16 --- /dev/null +++ b/test/fixtures/es-module-loaders/loader-dep.js @@ -0,0 +1 @@ +exports.format = 'esm'; diff --git a/test/fixtures/es-module-loaders/loader-with-dep.mjs b/test/fixtures/es-module-loaders/loader-with-dep.mjs new file mode 100644 index 00000000000..944e6e438c5 --- /dev/null +++ b/test/fixtures/es-module-loaders/loader-with-dep.mjs @@ -0,0 +1,7 @@ +import dep from './loader-dep.js'; +export function resolve (specifier, base, defaultResolve) { + return { + url: defaultResolve(specifier, base).url, + format: dep.format + }; +} diff --git a/test/parallel/test-module-main-extension-lookup.js b/test/parallel/test-module-main-extension-lookup.js new file mode 100644 index 00000000000..0a8cc47c77b --- /dev/null +++ b/test/parallel/test-module-main-extension-lookup.js @@ -0,0 +1,7 @@ +'use strict'; +require('../common'); +const { execFileSync } = require('child_process'); + +const node = process.argv[0]; + +execFileSync(node, ['--experimental-modules', 'test/es-module/test-esm-ok']); diff --git a/tools/cpplint.py b/tools/cpplint.py index 241195f0762..ca42ddeb7bc 100644 --- a/tools/cpplint.py +++ b/tools/cpplint.py @@ -1074,8 +1074,8 @@ def RepositoryName(self): """ fullname = self.FullName() # XXX(bnoordhuis) Expects that cpplint.py lives in the tools/ directory. - toplevel = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..')).replace('\\', '/') + toplevel = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) \ + .replace('\\', '/').decode('utf-8') prefix = os.path.commonprefix([fullname, toplevel]) return fullname[len(prefix) + 1:] @@ -6084,7 +6084,7 @@ def main(): _cpplint_state.ResetErrorCounts() for filename in filenames: - ProcessFile(filename, _cpplint_state.verbose_level) + ProcessFile(filename.decode('utf-8'), _cpplint_state.verbose_level) _cpplint_state.PrintErrorCounts() sys.exit(_cpplint_state.error_count > 0)