-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
Node 10.0.0 fs.close is called with a second undefined
argument.
#20335
Comments
cc @nodejs/fs |
In general, I would also only expect the callback to be called with a single argument. However, the language actually considers Nevertheless, I think we should fix it and only return a single argument in the error case as we state in the documentation. |
@joyeecheung maybe it's a side-effect of moving the errors from C++? |
Trying to fix it but I keep getting a crash caused by
See patchdiff --git a/src/node_file.cc b/src/node_file.cc
index 89c53afc5b..8aec109e1a 100644
--- a/src/node_file.cc
+++ b/src/node_file.cc
@@ -413,6 +413,14 @@ void FSReqWrap::ResolveStat(const uv_stat_t* stat) {
Resolve(node::FillGlobalStatsArray(env(), stat));
}
+void FSReqWrap::Resolve() {
+ Local<Value> argv[1] {
+ Null(env()->isolate())
+ };
+ MakeCallback(env()->oncomplete_string(), arraysize(argv), argv);
+}
+
+
void FSReqWrap::Resolve(Local<Value> value) {
Local<Value> argv[2] {
Null(env()->isolate()),
@@ -475,7 +483,7 @@ void AfterNoArgs(uv_fs_t* req) {
FSReqAfterScope after(req_wrap, req);
if (after.Proceed())
- req_wrap->Resolve(Undefined(req_wrap->env()->isolate()));
+ req_wrap->Resolve();
}
void AfterStat(uv_fs_t* req) {
diff --git a/src/node_file.h b/src/node_file.h
index d6c8aa443c..54de533801 100644
--- a/src/node_file.h
+++ b/src/node_file.h
@@ -62,6 +62,7 @@ class FSReqBase : public ReqWrap<uv_fs_t> {
}
virtual void Reject(Local<Value> reject) = 0;
+ virtual void Resolve() = 0;
virtual void Resolve(Local<Value> value) = 0;
virtual void ResolveStat(const uv_stat_t* stat) = 0;
virtual void SetReturnValue(const FunctionCallbackInfo<Value>& args) = 0;
@@ -90,6 +91,7 @@ class FSReqWrap : public FSReqBase {
: FSReqBase(env, req, AsyncWrap::PROVIDER_FSREQWRAP) { }
void Reject(Local<Value> reject) override;
+ void Resolve() override;
void Resolve(Local<Value> value) override;
void ResolveStat(const uv_stat_t* stat) override;
void SetReturnValue(const FunctionCallbackInfo<Value>& args) override;
@@ -128,6 +130,18 @@ class FSReqPromise : public FSReqBase {
resolver->Reject(env()->context(), reject).FromJust();
}
+ void Resolve() override {
+ finished_ = true;
+ HandleScope scope(env()->isolate());
+ InternalCallbackScope callback_scope(this);
+ Local<Value> val =
+ object()->Get(env()->context(),
+ env()->promise_string()).ToLocalChecked();
+ Local<Promise::Resolver> resolver = val.As<Promise::Resolver>();
+ resolver->Resolve(env()->context(),
+ Undefined(env()->isolate())).FromJust();
+ }
+
void Resolve(Local<Value> value) override {
finished_ = true;
HandleScope scope(env()->isolate()); See test'use strict';
// This tests that the fs APIs only passes error to the completion callback
// if it's the only callback argument documented.
const common = require('../common');
const assert = require('assert');
const fs = require('fs');
const tmpdir = require('../common/tmpdir');
const path = require('path');
tmpdir.refresh();
const nonexistent = path.join(tmpdir.path, 'noexistent');
fs.open(nonexistent, 'r', common.mustCall(function(...args) {
assert.strictEqual(args.length, 1);
common.expectsError({
type: Error,
code: 'ENOENT'
})(args[0]);
}));
const file = path.join(tmpdir.path, 'file.txt');
const content = Buffer.from('test');
function onOpen(...args) {
assert.deepStrictEqual(args[0], null);
assert.strictEqual(args.length, 2);
const fd = args[1];
assert.strictEqual(typeof fd, 'number');
fs.write(fd, content, common.mustCall(function(...args) {
assert.deepStrictEqual(args, [null, content.length, content]);
fs.close(args[1], common.mustCall(function(...args) {
assert.deepStrictEqual(fs.readFileSync(file), content);
assert.deepStrictEqual(args, [null]);
}));
}));
}
fs.open(file, 'w+', common.mustCall(onOpen)); |
Assign to myself so I don't forget, although I am kind of puzzled by the |
In the document for fs, there are several functions that state "No arguments other than a possible exception are given to the completion callback." (ex> fs.access, fs.chmod, fs.close, ..) But, the functions are invoking the callback with two parameters (err, undefined) It causes problems in using several API like [async.waterfall](https://caolan.github.io/async/docs.html#waterfall). Fixes: nodejs#20335
In the document for fs, there are several functions that state "No arguments other than a possible exception are given to the completion callback." (ex> fs.access, fs.chmod, fs.close, ..) But, the functions are invoking the callback with two parameters (err, undefined) It causes problems in using several API like [async.waterfall](https://caolan.github.io/async/docs.html#waterfall). PR-URL: #20629 Fixes: #20335 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
The documentation for fs.close states "No arguments other than a possible exception are given to the completion callback."
When used in conjunction with API's like async.waterfall, it is important that the callback is called with exactly one argument (err) because additional arguments are passed on to the next task.
I have found that in node 10.0.0 fs.close is invoking the callback with two arguments (err, undefined) here: https://github.com/nodejs/node/blob/v10.x/lib/fs.js#L506
I initially thought the issue might be due to recent changes in the
makeCallback
function, but that is not the case. Theoncomplete
handler is being called with a secondundefined
argument.I see that there have been many changes to
FSReqWrap
in native land. Maybe the issue is in there somewhere?I made this JS patch as a workaround: v10.x...digitalbazaar:v10.x
tracking: digitalbazaar/bedrock#25
The text was updated successfully, but these errors were encountered: