-
-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Adding WindowsBinding reading #1018
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we loop until we have some data we don't need to reque any more work.
@@ -681,6 +731,7 @@ extern "C" { | |||
Nan::SetMethod(target, "open", Open); | |||
Nan::SetMethod(target, "update", Update); | |||
Nan::SetMethod(target, "write", Write); | |||
Nan::SetMethod(target, "read", Read); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we move all of this to serialport_win.cpp
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to leave it since serialport_uwp will also use it. I can use ifdef WIN32 since the macro is defined when UWP is used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or maybe I could keep it in a 'common' cpp file. I could avoid using an ifdef if there was something like a SetExtraMethods() in the init function where native bindings could add extra methods (in this case read) or just do nothing. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets just ifdef win32
but make sure to put the after read in this file too
@@ -26,6 +26,10 @@ NAN_METHOD(Write); | |||
void EIO_Write(uv_work_t* req); | |||
void EIO_AfterWrite(uv_work_t* req); | |||
|
|||
NAN_METHOD(Read); | |||
void EIO_Read(uv_work_t* req); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And this stuff inside an ifdef
if (data->errorString[0]) { | ||
argv[0] = Nan::Error(data->errorString); | ||
argv[1] = argv[2] = Nan::Undefined(); | ||
Sleep(100); // prevent the errors from occurring too fast |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this left over from when we used to loop endlessly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Is the sleep still needed? I didn't want to take it out in case it was there for a good reason.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously we'd emit c++ buffers as fast as we could, now we take a js buffer write to it and return. I can't imagine why we'd want to sleep. You have my blessing to rip out anything you don't understand.
} else { | ||
argv[0] = Nan::Null(); | ||
argv[1] = Nan::New<v8::Integer>((int)data->bytesRead); | ||
argv[2] = Nan::NewBuffer(data->bufferData, data->bufferLength, FinalizerCallback, req).ToLocalChecked(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, we have a buffer from js land, this path seems not needed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was following the readcallback signature. Should I just leave it undefined or is there a way to assign the buffer pointer to argv[2]? ...not sure how to do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. That path isn't needed. I hadn't initially realized that the callback is actually the onRead function in push-methods :-|
👏👌 |
@@ -141,6 +145,17 @@ struct QueuedWrite { | |||
} | |||
}; | |||
|
|||
struct ReadBaton { | |||
int fd; | |||
char* bufferData; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I think the crux of the change will be to make this a pointer to a v8::Local<v8::Object> buffer
object, that way we can pass it all the way through. Write to it and then pass it to the callback. I don't know how to write to a buffer as if it were a char[]
maybe @indutny can throw us some pointers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd say Persistent
rather than Local
. Local
is for something on-stack.
- Fix CI failure to build - Tests (including read) now pass locally - Changes based on review feedback
@reconbot could you take a look at the latest updates when you get a chance. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking pretty good!
@Zensey brought up CreateIoCompletionPort
s which should be on our radar for future PRs.
I'd like to land this soon =)
WindowsBinding.prototype.read = require('./read-unix'); | ||
WindowsBinding.prototype.read = function(buffer, offset, length, cb) { | ||
if (!Buffer.isBuffer(buffer)) { | ||
throw new TypeError('"buffer" is not a Buffer'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm pretty sure your c++ throws would bubble up just fine for type checking
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah seems like overkill
argv[1] = Nan::Undefined(); | ||
} else { | ||
argv[0] = Nan::Null(); | ||
argv[1] = Nan::New<v8::Integer>((int)data->bytesRead); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be calling the read callback with the buffer as the 3rd arg. The decision was to stay in party with fs.read
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. I had left it out since the push-methods _read wasn't using that parameter - https://github.com/EmergingTechnologyAdvisors/node-serialport/blob/master/lib/push-methods.js#L31
DWORD bytesReadSync = 0; | ||
if (!ReadFile((HANDLE)data->fd, offsetPtr, data->bytesToRead, &bytesReadSync, &ov)) { | ||
errorCode = GetLastError(); | ||
if (errorCode != ERROR_IO_PENDING) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might be worth looking at #1020
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I'll keep my eye on it. Looks like someone's still able to repro with the proposed fix.
I realized the comments I made aren't blocking, so lets land this. =) |
Adding WindowsBinding reading
@reconbot I took a stab at #994 today.
I've only done minimal testing but I wanted to open the PR early and get your feedback.