Skip to content

stream: WritableBase without buffering #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 43 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
bc71278
events: lazy load perf_hooks for EventTarget
jasnell Jun 4, 2020
ff74e35
process: add unhandled-rejection throw and warn-with-error-code
dfabulich May 20, 2020
14d012e
quic: fix minor linting issue
jasnell Jun 16, 2020
ee7f0e3
doc,stream: split finish and end events into separate entries
Trott Jun 14, 2020
1e4187f
http2: add `invalidheaders` test
rexagod Apr 24, 2020
50fb019
n-api: document nextTick timing in callbacks
mafintosh Jun 9, 2020
e9145db
2020-06-17, Version 12.18.1 'Erbium' (LTS)
codebytere Jun 9, 2020
133a97f
quic: always copy stateless reset token
addaleax Jun 16, 2020
4b70f95
quic: use Check instead of FromJust in QuicStream
danbev Jun 16, 2020
272b46e
quic: skip test-quic-preferred-address-ipv6.js when no ipv6
jasnell Jun 17, 2020
a4f3206
events: improve listeners() performance
mscdex Jun 13, 2020
7407fc2
doc: update code language flag for internal doc
Trott Jun 17, 2020
0ef6956
tools: update remark-preset-lint-node@1.15.1 to 1.16.0
Trott Jun 11, 2020
bfbdc84
timers: allow promisified timeouts/immediates to be canceled
jasnell Jun 10, 2020
16116f5
quic: remove noop code
ronag Jun 16, 2020
d7d79f2
quic: avoid memory fragmentation issue
jasnell May 18, 2020
ea866dc
events: use property, primordials
benjamingr Jun 6, 2020
9dcde52
doc: specify default encoding in writable.write
rexagod Jun 6, 2020
ddfed69
doc: link readable._read in stream.md
rexagod Jun 6, 2020
56967af
deps: V8: cherry-pick eec10a2fd8fa
Qard Jun 6, 2020
1bd88a3
quic: fix up node_quic_stream includes
danbev Jun 17, 2020
88ef158
quic: remove unused string include http3_application
danbev Jun 17, 2020
f0fb511
dgram: allow typed arrays in .send()
SirR4T Aug 20, 2018
9918bdf
lib: replace charCodeAt with fixed Unicode
rickyes Apr 10, 2020
d1d412b
doc: use sentence-case for headings in docs
Trott Jun 14, 2020
563062e
doc: standardize on sentence case for headers
Trott Jun 15, 2020
2899588
src: simplify alignment-handling code
addaleax Jun 14, 2020
52de4cb
src: minor updates to FastHrtime
addaleax Jun 11, 2020
2c48647
util: gracefully handle unknown colors
BridgeAR Jun 8, 2020
59e6230
async_hooks: callback trampoline for MakeCallback
Qard Jun 6, 2020
646e5a4
domain: remove native domain code
Qard Jun 9, 2020
a86a295
lib: remove NodeError from the prototype of errors with code
targos Jun 12, 2020
8f000ea
deps: V8: cherry-pick 767e65f945e7
devsnek Jun 12, 2020
178e52a
lib: remove manual exception handling in queueMicrotask
devsnek Jun 12, 2020
e199fc5
module: fix error message about importing names from cjs
fabiosantoscode Jun 14, 2020
fdcd489
http2: always call callback on Http2ServerResponse#end
rexagod Jun 16, 2020
343cf1b
doc: update WASM code sample
pragyandas May 28, 2020
fdf10ad
meta: introduce codeowners again
jasnell Jun 15, 2020
eebec50
stream: implement WritableBase without buffering
ronag Apr 26, 2020
fbe7a31
fixup
ronag Jun 21, 2020
6069c26
fixup
ronag Jun 21, 2020
37adf2b
fixup
ronag Jun 21, 2020
545b780
fixup
ronag Jun 21, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Node.js Project Codeowners

# 1. Codeowners must always be teams, never individuals
# 2. Each codeowner team should contain at least one TSC member
# 3. PRs touching any code with a codeowner must be signed off by at least one
# person on the code owner team.

./.github/CODEOWNERS @nodejs/tsc

# net

# ./deps/cares @nodejs/net
# ./doc/api/dns.md @nodejs/net
# ./doc/api/dgram.md @nodejs/net
# ./doc/api/net.md @nodejs/net
# ./lib/dgram.js @nodejs/net
# ./lib/dns.js @nodejs/net
# ./lib/net.js @nodejs/net @nodejs/quic
# ./lib/internal/dgram.js @nodejs/net
# ./lib/internal/dns/* @nodejs/net
# ./lib/internal/net.js @nodejs/net
# ./lib/internal/socket_list.js @nodejs/net
# ./lib/internal/js_stream_socket.js @nodejs/net
# ./src/cares_wrap.h @nodejs/net
# ./src/connect_wrap.* @nodejs/net
# ./src/connection_wrap.* @nodejs/net
# ./src/node_sockaddr* @nodejs/net
# ./src/tcp_wrap.* @nodejs/net
# ./src/udp_wrap.* @nodejs/net

# tls/crypto

# ./lib/internal/crypto/* @nodejs/crypto
# ./lib/internal/tls.js @nodejs/crypto @nodejs/net
# ./lib/crypto.js @nodejs/crypto
# ./lib/tls.js @nodejs/crypto @nodejs/net
# ./src/node_crypto* @nodejs/crypto
# ./src/node_crypto_common* @nodejs/crypto @nodejs/quic

# http

# ./deps/llhttp/* @nodejs/http @nodejs/net
# ./doc/api/http.md @nodejs/http @nodejs/net
# ./doc/api/http2.md @nodejs/http @nodejs/net
# ./lib/_http_* @nodejs/http @nodejs/net
# ./lib/http.js @nodejs/http @nodejs/net
# ./lib/https.js @nodejs/crypto @nodejs/net @nodejs/http
# ./src/node_http_common* @nodejs/http @nodejs/http2 @nodejs/quic @nodejs/net
# ./src/node_http_parser.cc @nodejs/http @nodejs/net

# http2

# ./deps/nghttp2/* @nodejs/http2 @nodejs/net
# ./doc/api/http2.md @nodejs/http2 @nodejs/net
# ./lib/http2.js @nodejs/http2 @nodejs/net
# ./lib/internal/http2/* @nodejs/http2 @nodejs/net
# ./src/node_http2* @nodejs/http2 @nodejs/net
# ./src/node_mem* @nodejs/http2

# quic

./deps/ngtcp2/* @nodejs/quic
./deps/nghttp3/* @nodejs/quic
./doc/api/quic.md @nodejs/quic
./lib/internal/quic/* @nodejs/quic
./src/node_bob* @nodejs/quic
./src/quic/* @nodejs/quic

# modules

# ./doc/api/modules.md @nodejs/modules
# ./doc/api/esm.md @nodejs/modules
# ./lib/module.js @nodejs/modules
# ./lib/internal/modules/* @nodejs/modules
# ./lib/internal/bootstrap/loaders.js @nodejs/modules
# ./src/module_wrap* @nodejs/modules @nodejs/vm
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ release.
<a href="doc/changelogs/CHANGELOG_V13.md#13.0.0">13.0.0</a><br/>
</td>
<td valign="top">
<b><a href="doc/changelogs/CHANGELOG_V12.md#12.18.0">12.18.0</a></b><br/>
<b><a href="doc/changelogs/CHANGELOG_V12.md#12.18.1">12.18.1</a></b><br/>
<a href="doc/changelogs/CHANGELOG_V12.md#12.18.0">12.18.0</a><br/>
<a href="doc/changelogs/CHANGELOG_V12.md#12.17.0">12.17.0</a><br/>
<a href="doc/changelogs/CHANGELOG_V12.md#12.16.3">12.16.3</a><br/>
<a href="doc/changelogs/CHANGELOG_V12.md#12.16.2">12.16.2</a><br/>
Expand Down
2 changes: 1 addition & 1 deletion benchmark/events/ee-listeners.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function main({ n, listeners, raw }) {

for (let k = 0; k < listeners; k += 1) {
ee.on('dummy0', () => {});
ee.on('dummy1', () => {});
ee.once('dummy1', () => {});
}

if (raw === 'true') {
Expand Down
2 changes: 1 addition & 1 deletion common.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,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.19',
'v8_embedder_string': '-node.20',

##### V8 defaults for Node.js #####

Expand Down
9 changes: 8 additions & 1 deletion deps/v8/src/builtins/builtins-microtask-queue-gen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -198,11 +198,18 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask(
const TNode<Object> thenable = LoadObjectField(
microtask, PromiseResolveThenableJobTask::kThenableOffset);

RunPromiseHook(Runtime::kPromiseHookBefore, microtask_context,
CAST(promise_to_resolve));

{
ScopedExceptionHandler handler(this, &if_exception, &var_exception);
CallBuiltin(Builtins::kPromiseResolveThenableJob, native_context,
promise_to_resolve, thenable, then);
}

RunPromiseHook(Runtime::kPromiseHookAfter, microtask_context,
CAST(promise_to_resolve));

RewindEnteredContext(saved_entered_context_count);
SetCurrentContext(current_context);
Goto(&done);
Expand Down Expand Up @@ -320,7 +327,7 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask(
BIND(&if_exception);
{
// Report unhandled exceptions from microtasks.
CallRuntime(Runtime::kReportMessage, current_context,
CallRuntime(Runtime::kReportMessageFromMicrotask, current_context,
var_exception.value());
RewindEnteredContext(saved_entered_context_count);
SetCurrentContext(current_context);
Expand Down
14 changes: 2 additions & 12 deletions deps/v8/src/builtins/promise-reaction-job.tq
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@

#include 'src/builtins/builtins-promise-gen.h'

namespace runtime {
extern transitioning runtime
ReportMessage(implicit context: Context)(JSAny): JSAny;
}

namespace promise {

transitioning
Expand All @@ -30,13 +25,8 @@ namespace promise {
case (capability: PromiseCapability): {
// In the general case we need to call the (user provided)
// promiseCapability.[[Reject]] function.
try {
const reject = UnsafeCast<Callable>(capability.reject);
return Call(context, reject, Undefined, reason);
} catch (e) {
// Swallow the exception here.
return runtime::ReportMessage(e);
}
const reject = UnsafeCast<Callable>(capability.reject);
return Call(context, reject, Undefined, reason);
}
}
} else {
Expand Down
170 changes: 55 additions & 115 deletions deps/v8/src/execution/isolate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1412,6 +1412,8 @@ void Isolate::InvokeApiInterruptCallbacks() {
}
}

namespace {

void ReportBootstrappingException(Handle<Object> exception,
MessageLocation* location) {
base::OS::PrintError("Exception thrown during bootstrapping\n");
Expand Down Expand Up @@ -1467,6 +1469,36 @@ void ReportBootstrappingException(Handle<Object> exception,
#endif
}

} // anonymous namespace

Handle<JSMessageObject> Isolate::CreateMessageOrAbort(
Handle<Object> exception, MessageLocation* location) {
Handle<JSMessageObject> message_obj = CreateMessage(exception, location);

// If the abort-on-uncaught-exception flag is specified, and if the
// embedder didn't specify a custom uncaught exception callback,
// or if the custom callback determined that V8 should abort, then
// abort.
if (FLAG_abort_on_uncaught_exception) {
CatchType prediction = PredictExceptionCatcher();
if ((prediction == NOT_CAUGHT || prediction == CAUGHT_BY_EXTERNAL) &&
(!abort_on_uncaught_exception_callback_ ||
abort_on_uncaught_exception_callback_(
reinterpret_cast<v8::Isolate*>(this)))) {
// Prevent endless recursion.
FLAG_abort_on_uncaught_exception = false;
// This flag is intended for use by JavaScript developers, so
// print a user-friendly stack trace (not an internal one).
PrintF(stderr, "%s\n\nFROM\n",
MessageHandler::GetLocalizedMessage(this, message_obj).get());
PrintCurrentStackTrace(stderr);
base::OS::Abort();
}
}

return message_obj;
}

Object Isolate::Throw(Object raw_exception, MessageLocation* location) {
DCHECK(!has_pending_exception());

Expand Down Expand Up @@ -1538,38 +1570,14 @@ Object Isolate::Throw(Object raw_exception, MessageLocation* location) {
if (location == nullptr && ComputeLocation(&computed_location)) {
location = &computed_location;
}

if (bootstrapper()->IsActive()) {
// It's not safe to try to make message objects or collect stack traces
// while the bootstrapper is active since the infrastructure may not have
// been properly initialized.
ReportBootstrappingException(exception, location);
} else {
Handle<Object> message_obj = CreateMessage(exception, location);
Handle<Object> message_obj = CreateMessageOrAbort(exception, location);
thread_local_top()->pending_message_obj_ = *message_obj;

// For any exception not caught by JavaScript, even when an external
// handler is present:
// If the abort-on-uncaught-exception flag is specified, and if the
// embedder didn't specify a custom uncaught exception callback,
// or if the custom callback determined that V8 should abort, then
// abort.
if (FLAG_abort_on_uncaught_exception) {
CatchType prediction = PredictExceptionCatcher();
if ((prediction == NOT_CAUGHT || prediction == CAUGHT_BY_EXTERNAL) &&
(!abort_on_uncaught_exception_callback_ ||
abort_on_uncaught_exception_callback_(
reinterpret_cast<v8::Isolate*>(this)))) {
// Prevent endless recursion.
FLAG_abort_on_uncaught_exception = false;
// This flag is intended for use by JavaScript developers, so
// print a user-friendly stack trace (not an internal one).
PrintF(stderr, "%s\n\nFROM\n",
MessageHandler::GetLocalizedMessage(this, message_obj).get());
PrintCurrentStackTrace(stderr);
base::OS::Abort();
}
}
}
}

Expand Down Expand Up @@ -2106,7 +2114,7 @@ bool Isolate::ComputeLocationFromStackTrace(MessageLocation* target,
bool is_at_number_conversion =
elements->IsAsmJsWasmFrame(i) &&
elements->Flags(i).value() & FrameArray::kAsmJsAtNumberConversion;
if (elements->IsWasmCompiledFrame(i)) {
if (elements->IsWasmCompiledFrame(i) || elements->IsAsmJsWasmFrame(i)) {
// WasmCode* held alive by the {GlobalWasmCodeRef}.
wasm::WasmCode* code =
Managed<wasm::GlobalWasmCodeRef>::cast(elements->WasmCodeObject(i))
Expand Down Expand Up @@ -2230,9 +2238,28 @@ bool Isolate::IsExternalHandlerOnTop(Object exception) {
return (entry_handler > external_handler);
}

void Isolate::ReportPendingMessagesImpl(bool report_externally) {
std::vector<MemoryRange>* Isolate::GetCodePages() const {
return code_pages_.load(std::memory_order_acquire);
}

void Isolate::SetCodePages(std::vector<MemoryRange>* new_code_pages) {
code_pages_.store(new_code_pages, std::memory_order_release);
}

void Isolate::ReportPendingMessages() {
DCHECK(AllowExceptions::IsAllowed(this));

// The embedder might run script in response to an exception.
AllowJavascriptExecutionDebugOnly allow_script(this);

Object exception_obj = pending_exception();

// Try to propagate the exception to an external v8::TryCatch handler. If
// propagation was unsuccessful, then we will get another chance at reporting
// the pending message if the exception is re-thrown.
bool has_been_propagated = PropagatePendingExceptionToExternalTryCatch();
if (!has_been_propagated) return;

// Clear the pending message object early to avoid endless recursion.
Object message_obj = thread_local_top()->pending_message_obj_;
clear_pending_message();
Expand All @@ -2245,7 +2272,7 @@ void Isolate::ReportPendingMessagesImpl(bool report_externally) {
// depending on whether and external v8::TryCatch or an internal JavaScript
// handler is on top.
bool should_report_exception;
if (report_externally) {
if (IsExternalHandlerOnTop(exception_obj)) {
// Only report the exception if the external handler is verbose.
should_report_exception = try_catch_handler()->is_verbose_;
} else {
Expand All @@ -2271,93 +2298,6 @@ void Isolate::ReportPendingMessagesImpl(bool report_externally) {
}
}

std::vector<MemoryRange>* Isolate::GetCodePages() const {
return code_pages_.load(std::memory_order_acquire);
}

void Isolate::SetCodePages(std::vector<MemoryRange>* new_code_pages) {
code_pages_.store(new_code_pages, std::memory_order_release);
}

void Isolate::ReportPendingMessages() {
DCHECK(AllowExceptions::IsAllowed(this));

// The embedder might run script in response to an exception.
AllowJavascriptExecutionDebugOnly allow_script(this);

Object exception = pending_exception();

// Try to propagate the exception to an external v8::TryCatch handler. If
// propagation was unsuccessful, then we will get another chance at reporting
// the pending message if the exception is re-thrown.
bool has_been_propagated = PropagatePendingExceptionToExternalTryCatch();
if (!has_been_propagated) return;

ReportPendingMessagesImpl(IsExternalHandlerOnTop(exception));
}

void Isolate::ReportPendingMessagesFromJavaScript() {
DCHECK(AllowExceptions::IsAllowed(this));

auto IsHandledByJavaScript = [=]() {
// In this situation, the exception is always a non-terminating exception.

// Get the top-most JS_ENTRY handler, cannot be on top if it doesn't exist.
Address entry_handler = Isolate::handler(thread_local_top());
DCHECK_NE(entry_handler, kNullAddress);
entry_handler = StackHandler::FromAddress(entry_handler)->next_address();

// Get the address of the external handler so we can compare the address to
// determine which one is closer to the top of the stack.
Address external_handler = thread_local_top()->try_catch_handler_address();
if (external_handler == kNullAddress) return true;

return (entry_handler < external_handler);
};

auto IsHandledExternally = [=]() {
Address external_handler = thread_local_top()->try_catch_handler_address();
if (external_handler == kNullAddress) return false;

// Get the top-most JS_ENTRY handler, cannot be on top if it doesn't exist.
Address entry_handler = Isolate::handler(thread_local_top());
DCHECK_NE(entry_handler, kNullAddress);
entry_handler = StackHandler::FromAddress(entry_handler)->next_address();
return (entry_handler > external_handler);
};

auto PropagateToExternalHandler = [=]() {
if (IsHandledByJavaScript()) {
thread_local_top()->external_caught_exception_ = false;
return false;
}

if (!IsHandledExternally()) {
thread_local_top()->external_caught_exception_ = false;
return true;
}

thread_local_top()->external_caught_exception_ = true;
v8::TryCatch* handler = try_catch_handler();
DCHECK(thread_local_top()->pending_message_obj_.IsJSMessageObject() ||
thread_local_top()->pending_message_obj_.IsTheHole(this));
handler->can_continue_ = true;
handler->has_terminated_ = false;
handler->exception_ = reinterpret_cast<void*>(pending_exception().ptr());
// Propagate to the external try-catch only if we got an actual message.
if (thread_local_top()->pending_message_obj_.IsTheHole(this)) return true;

handler->message_obj_ =
reinterpret_cast<void*>(thread_local_top()->pending_message_obj_.ptr());
return true;
};

// Try to propagate to an external v8::TryCatch handler.
if (!PropagateToExternalHandler()) return;

ReportPendingMessagesImpl(true);
}

bool Isolate::OptionalRescheduleException(bool clear_exception) {
DCHECK(has_pending_exception());
PropagatePendingExceptionToExternalTryCatch();
Expand Down
Loading