diff --git a/deps/chakrashim/include/v8-version.h b/deps/chakrashim/include/v8-version.h
index ee6ccec7cec..133ee1f3f1b 100644
--- a/deps/chakrashim/include/v8-version.h
+++ b/deps/chakrashim/include/v8-version.h
@@ -11,7 +11,7 @@
#define V8_MAJOR_VERSION 6
#define V8_MINOR_VERSION 5
#define V8_BUILD_NUMBER 254
-#define V8_PATCH_LEVEL 38
+#define V8_PATCH_LEVEL 40
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h
index ee6ccec7cec..133ee1f3f1b 100644
--- a/deps/v8/include/v8-version.h
+++ b/deps/v8/include/v8-version.h
@@ -11,7 +11,7 @@
#define V8_MAJOR_VERSION 6
#define V8_MINOR_VERSION 5
#define V8_BUILD_NUMBER 254
-#define V8_PATCH_LEVEL 38
+#define V8_PATCH_LEVEL 40
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
diff --git a/deps/v8/src/wasm/wasm-code-manager.cc b/deps/v8/src/wasm/wasm-code-manager.cc
index 8e46f33b012..2b8f3097339 100644
--- a/deps/v8/src/wasm/wasm-code-manager.cc
+++ b/deps/v8/src/wasm/wasm-code-manager.cc
@@ -954,6 +954,8 @@ void WasmCodeManager::FreeNativeModuleMemories(NativeModule* native_module) {
Free(&vmem);
DCHECK(!vmem.IsReserved());
}
+ native_module->owned_memory_.clear();
+
// No need to tell the GC anything if we're destroying the heap,
// which we currently indicate by having the isolate_ as null
if (isolate_ == nullptr) return;
diff --git a/deps/v8/tools/whitespace.txt b/deps/v8/tools/whitespace.txt
index ed5e51f96a6..83f006688cd 100644
--- a/deps/v8/tools/whitespace.txt
+++ b/deps/v8/tools/whitespace.txt
@@ -8,5 +8,3 @@ The doubles heard this and started to unbox.
The Smi looked at them when a crazy v8-autoroll account showed up...
The autoroller bought a round of Himbeerbrause. Suddenly...
The bartender starts to shake the bottles.......................
-.
-.
diff --git a/doc/api/errors.md b/doc/api/errors.md
index f5190dc52bf..5c38dde4130 100644
--- a/doc/api/errors.md
+++ b/doc/api/errors.md
@@ -783,18 +783,6 @@ falsy value.
An invalid symlink type was passed to the [`fs.symlink()`][] or
[`fs.symlinkSync()`][] methods.
-
-### ERR_FS_WATCHER_ALREADY_STARTED
-
-An attempt was made to start a watcher returned by `fs.watch()` that has
-already been started.
-
-
-### ERR_FS_WATCHER_NOT_STARTED
-
-An attempt was made to initiate operations on a watcher returned by
-`fs.watch()` that has not yet been started.
-
### ERR_HTTP_HEADERS_SENT
diff --git a/doc/api/stream.md b/doc/api/stream.md
index 814acc69d6a..01405556674 100644
--- a/doc/api/stream.md
+++ b/doc/api/stream.md
@@ -1208,7 +1208,10 @@ print(fs.createReadStream('file')).catch(console.log);
If the loop terminates with a `break` or a `throw`, the stream will be
destroyed. In other terms, iterating over a stream will consume the stream
-fully.
+fully. The stream will be read in chunks of size equal to the `highWaterMark`
+option. In the code example above, data will be in a single chunk if the file
+has less then 64kb of data because no `highWaterMark` option is provided to
+[`fs.createReadStream()`][].
### Duplex and Transform Streams
diff --git a/lib/fs.js b/lib/fs.js
index 352d2fd1ffd..f6722921fc5 100644
--- a/lib/fs.js
+++ b/lib/fs.js
@@ -36,8 +36,6 @@ const fs = exports;
const { Buffer } = require('buffer');
const errors = require('internal/errors');
const {
- ERR_FS_WATCHER_ALREADY_STARTED,
- ERR_FS_WATCHER_NOT_STARTED,
ERR_INVALID_ARG_TYPE,
ERR_INVALID_CALLBACK,
ERR_OUT_OF_RANGE
@@ -1342,25 +1340,26 @@ util.inherits(FSWatcher, EventEmitter);
// FIXME(joyeecheung): this method is not documented.
// At the moment if filename is undefined, we
-// 1. Throw an Error from C++ land if it's the first time .start() is called
-// 2. Return silently from C++ land if .start() has already been called
+// 1. Throw an Error if it's the first time .start() is called
+// 2. Return silently if .start() has already been called
// on a valid filename and the wrap has been initialized
+// This method is a noop if the watcher has already been started.
FSWatcher.prototype.start = function(filename,
persistent,
recursive,
encoding) {
lazyAssert()(this._handle instanceof FSEvent, 'handle must be a FSEvent');
if (this._handle.initialized) {
- throw new ERR_FS_WATCHER_ALREADY_STARTED();
+ return;
}
filename = getPathFromURL(filename);
validatePath(filename, 'filename');
- var err = this._handle.start(pathModule.toNamespacedPath(filename),
- persistent,
- recursive,
- encoding);
+ const err = this._handle.start(pathModule.toNamespacedPath(filename),
+ persistent,
+ recursive,
+ encoding);
if (err) {
const error = errors.uvException({
errno: err,
@@ -1372,10 +1371,11 @@ FSWatcher.prototype.start = function(filename,
}
};
+// This method is a noop if the watcher has not been started.
FSWatcher.prototype.close = function() {
lazyAssert()(this._handle instanceof FSEvent, 'handle must be a FSEvent');
if (!this._handle.initialized) {
- throw new ERR_FS_WATCHER_NOT_STARTED();
+ return;
}
this._handle.close();
};
@@ -1449,18 +1449,43 @@ util.inherits(StatWatcher, EventEmitter);
// FIXME(joyeecheung): this method is not documented.
// At the moment if filename is undefined, we
-// 1. Throw an Error from C++ land if it's the first time .start() is called
-// 2. Return silently from C++ land if .start() has already been called
+// 1. Throw an Error if it's the first time .start() is called
+// 2. Return silently if .start() has already been called
// on a valid filename and the wrap has been initialized
+// This method is a noop if the watcher has already been started.
StatWatcher.prototype.start = function(filename, persistent, interval) {
+ lazyAssert()(this._handle instanceof binding.StatWatcher,
+ 'handle must be a StatWatcher');
+ if (this._handle.isActive) {
+ return;
+ }
+
filename = getPathFromURL(filename);
- nullCheck(filename, 'filename');
- this._handle.start(pathModule.toNamespacedPath(filename),
- persistent, interval);
+ validatePath(filename, 'filename');
+ validateUint32(interval, 'interval');
+ const err = this._handle.start(pathModule.toNamespacedPath(filename),
+ persistent, interval);
+ if (err) {
+ const error = errors.uvException({
+ errno: err,
+ syscall: 'watch',
+ path: filename
+ });
+ error.filename = filename;
+ throw error;
+ }
};
-
+// FIXME(joyeecheung): this method is not documented while there is
+// another documented fs.unwatchFile(). The counterpart in
+// FSWatcher is .close()
+// This method is a noop if the watcher has not been started.
StatWatcher.prototype.stop = function() {
+ lazyAssert()(this._handle instanceof binding.StatWatcher,
+ 'handle must be a StatWatcher');
+ if (!this._handle.isActive) {
+ return;
+ }
this._handle.stop();
};
diff --git a/lib/internal/errors.js b/lib/internal/errors.js
index 3d0b6cf9b39..d5260bd501f 100644
--- a/lib/internal/errors.js
+++ b/lib/internal/errors.js
@@ -654,10 +654,6 @@ E('ERR_FALSY_VALUE_REJECTION', 'Promise was rejected with falsy value', Error);
E('ERR_FS_INVALID_SYMLINK_TYPE',
'Symlink type must be one of "dir", "file", or "junction". Received "%s"',
Error); // Switch to TypeError. The current implementation does not seem right
-E('ERR_FS_WATCHER_ALREADY_STARTED',
- 'The watcher has already been started', Error);
-E('ERR_FS_WATCHER_NOT_STARTED',
- 'The watcher has not been started', Error);
E('ERR_HTTP2_ALTSVC_INVALID_ORIGIN',
'HTTP/2 ALTSVC frames require a valid origin', TypeError);
E('ERR_HTTP2_ALTSVC_LENGTH',
diff --git a/src/node_file.cc b/src/node_file.cc
index b6c9a277be2..11065082071 100644
--- a/src/node_file.cc
+++ b/src/node_file.cc
@@ -1538,7 +1538,6 @@ static void WriteString(const FunctionCallbackInfo& args) {
const auto enc = ParseEncoding(env->isolate(), args[3], UTF8);
- std::unique_ptr delete_on_return;
Local value = args[1];
char* buf = nullptr;
size_t len;
@@ -1566,24 +1565,42 @@ static void WriteString(const FunctionCallbackInfo& args) {
}
}
- if (buf == nullptr) {
+ if (is_async) { // write(fd, string, pos, enc, req)
+ CHECK_NE(req_wrap, nullptr);
len = StringBytes::StorageSize(env->isolate(), value, enc);
- buf = new char[len];
- // SYNC_CALL returns on error. Make sure to always free the memory.
- if (!is_async) delete_on_return.reset(buf);
+ FSReqBase::FSReqBuffer& stack_buffer =
+ req_wrap->Init("write", len, enc);
// StorageSize may return too large a char, so correct the actual length
// by the write size
- len = StringBytes::Write(env->isolate(), buf, len, args[1], enc);
- }
-
- uv_buf_t uvbuf = uv_buf_init(buf, len);
-
- if (is_async) { // write(fd, string, pos, enc, req)
- AsyncCall(env, req_wrap, args, "write", UTF8, AfterInteger,
- uv_fs_write, fd, &uvbuf, 1, pos);
+ len = StringBytes::Write(env->isolate(), *stack_buffer, len, args[1], enc);
+ stack_buffer.SetLengthAndZeroTerminate(len);
+ uv_buf_t uvbuf = uv_buf_init(*stack_buffer, len);
+ int err = uv_fs_write(env->event_loop(), req_wrap->req(),
+ fd, &uvbuf, 1, pos, AfterInteger);
+ req_wrap->Dispatched();
+ if (err < 0) {
+ uv_fs_t* uv_req = req_wrap->req();
+ uv_req->result = err;
+ uv_req->path = nullptr;
+ AfterInteger(uv_req); // after may delete req_wrap if there is an error
+ } else {
+ req_wrap->SetReturnValue(args);
+ }
} else { // write(fd, string, pos, enc, undefined, ctx)
CHECK_EQ(argc, 6);
fs_req_wrap req_wrap;
+ FSReqBase::FSReqBuffer stack_buffer;
+ if (buf == nullptr) {
+ len = StringBytes::StorageSize(env->isolate(), value, enc);
+ stack_buffer.AllocateSufficientStorage(len + 1);
+ // StorageSize may return too large a char, so correct the actual length
+ // by the write size
+ len = StringBytes::Write(env->isolate(), *stack_buffer,
+ len, args[1], enc);
+ stack_buffer.SetLengthAndZeroTerminate(len);
+ buf = *stack_buffer;
+ }
+ uv_buf_t uvbuf = uv_buf_init(buf, len);
int bytesWritten = SyncCall(env, args[5], &req_wrap, "write",
uv_fs_write, fd, &uvbuf, 1, pos);
args.GetReturnValue().Set(bytesWritten);
diff --git a/src/node_file.h b/src/node_file.h
index fa373d46ad0..1925e400f2d 100644
--- a/src/node_file.h
+++ b/src/node_file.h
@@ -24,6 +24,8 @@ namespace fs {
class FSReqBase : public ReqWrap {
public:
+ typedef MaybeStackBuffer FSReqBuffer;
+
FSReqBase(Environment* env, Local