-
Notifications
You must be signed in to change notification settings - Fork 504
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
Discuss a possible redesign of NanNew(...) #210
Conversation
Wow, you've been busy. I like it, it does look cleaner. I'm mostly concerned with corner cases, and cannot straight away tell if they will work or not, just by looking at the code. Can it distinguish between wanting to create a v8::Local<v8::Date> NanNew(double time) {
return v8::Date::New(v8::Isolate::GetCurrent(), time).As<v8::Date>();
} v8::Local<v8::Number> NanNew(double val) {
return v8::Number::New(v8::Isolate::GetCurrent(), val);
} in code like
How are default arguments handled? E.g. In the beginning everything seemed nice and elegant with the current approach, but as more and more stuff was added, ambiguities were observed and needed resolving somehow. Can you handle creation of bound and unbound scripts consistently, keeping in mind that they were the same on 0.10. I concluded that it was not possible, and had to break one constructor out ( What about What about |
If you have not seen it, #86 Contains most of the original concerns. |
Hehe... given the code above what do you suppose it should do? No, I'm afraid but overloading by return type is not part of the C++ language. The type of an expression is an inherent feature of the expression. Looking beyond the expression to deduce a type is not C++. For the same reason the ternary operator has to return one single type. ;)
Although I haven't tried it yet, default arguments should just work as expected. The compiler will pick the
Yes, I think so. There are techniques to deal with that but I think, given the small n, we should KISS. We want nan to be easy to use and easy to maintain. Let's not turn this into some template-hyper-macro-hotch-potch... until we have to. ;) BTW, they are not specializations but independent template functions. (I know, it's a PITA).
Relax. You really don't have to explain this. I know... believe me... I do...
I think we should throw it in. If I'm not mistaken all integer constructors return I'll look into the other stuff. |
I updated the code in question to make sense, it was a copypaste from another On Thursday 30 October 2014 08:06:17 David Siegel wrote:
|
Like this? |
Yes, it looks good. On Thursday 30 October 2014 08:31:46 David Siegel wrote:
|
And oh, I made the |
Hm, not sure NAN should interfere like that. Have to think about it. |
@kkoopa, could you tell me a bit about the string constructors? It looks like |
They are mainly treated that way because that's how v8 does it. ASCII is only a 7-bit subset of Latin1, without the high bit set. The name used here is ASCII for legacy reasons, v8 removed it precisely because it never was conformant ASCII. It always was sort of Latin1 (no particular encoding was actually used), just a 1-byte charset using all 8 bits. Treating them as signed makes no sense whatsoever, a character cannot be negative. The main point is that they really should not be used, if you absolutely have to and cannot make your program correct, then make it explicit and jump through the hoop. "This is a raw (unsigned) byte stream, I really, really, do want this." ASCII is a proper subset of UTF8, so if you actually have a proper ASCII-encoded string, it is also a proper UTF-8 encoded string, so you would just use that. However, if the high bit is set, it means it is a multi-byte character in UTF-8. It uses the Old versions had no proper way of doing wide strings. That horrible loop is the only way, which is why later versions made sure to fix the problem. |
Does the script test pass with both old and new version? I had the problem that bound and unbound scripts were the same in old v8, and doing |
Yes, it works. The key is not to do anything about unbound scripts in old versions. The typedef is enough to make the "normal" script functions match... which is what we want. |
Aha, but is it then impossible to make the names match? |
Regarding strings: I do get the difference between the encodings. So the idea is to treat everything as UTF8/ASCII except the user casts to What do you mean by "impossible to make the names match"? Like have a
Sure. Why not? It's still there. I just don't use it because I don't like it. :-D |
These are the correct signatures from v8: /** Allocates a new string from UTF-8 data.*/
static Local<String> NewFromUtf8(Isolate* isolate,
const char* data,
NewStringType type = kNormalString,
int length = -1);
/** Allocates a new string from Latin-1 data.*/
static Local<String> NewFromOneByte(
Isolate* isolate,
const uint8_t* data,
NewStringType type = kNormalString,
int length = -1);
/** Allocates a new string from UTF-16 data.*/
static Local<String> NewFromTwoByte(
Isolate* isolate,
const uint16_t* data,
NewStringType type = kNormalString,
int length = -1); From an end-user perspective it seems more intuitive to be able to use the name NanBoundScript if there is a NanUnboundScript. I like symmetry and consistency, that way you only need to remember one half, plus the fact that it is symmetric. |
Regarding the |
Sure, I can probably do that. Will take a closer look tomorrow. Thanks a million. But do add yourself to the list of contributors, this is certainly a major contribution. On November 3, 2014 10:59:05 PM EET, David Siegel notifications@github.com wrote:
|
Yes, I had that in mind. It most definitely is worth replacing the existing hack with. It is easier to maintain, easier to read and simply more correct. |
To help you guys to gain a little more trust in this here are a few... Design Notes:Let's ignore the convenience functions for a second and get right down to the core. Looking at The first approach was to use one, massively overloaded name. I don't have to explain this. You all have seen the header file. Now, what's the problem with that? Let the author speak for himself. @kkoopa said:
In other words: It was bad
So. scratch that. The massively overloaded name approach is an anti-pattern like the big ball of spaghetti. Back to the drawing board. Interestingly the key to this is the third point. If we can help the compiler to get a better grasp on what we want we improve the situation for both users and maintainers. Now, how do we do that? Let's start with the entry points. We define a cluster of template functions like so:
and so on. We now have a function that takes a type argument and has an arbitrary signature. Now, recall that the set of legal signatures depends on type
That changes things drastically. The compiler now first looks up
The code above enables calls like
On the user side things improve, too. If invoked with an invalid |
What he said. |
Ah, great explanation. Thanks for that. |
I think the best action plan would be: Release 1.4.1 with 9d8b270 and kkoopa/nan@e15c720 asap. Then I'll integrate this and #207 and we can call it 1.5.0. |
Am I correct in reading this that your pre-12 implementation always creates bound scripts? It should create unbound scripts (built through |
Possible. Let me check. |
Good catch. Fixed. |
Does the old caveat on
|
First things first: No such penalty. Calling That said, I'm not quite sure what the note is referring to:
It doesn't matter much, because it's a thing of the past. But if you have an example/article/stackoverflow at hand... |
It comes from here: e79e3d4 |
Hehe, yeah... Thing is: There is no implicit conversion in template land. If you don't specialize on Good thing we're using overloads now. |
Yeah, that's what I figured. Good, I can update the documentation in the onepointfive branch. |
I just noticed that I eliminated another superfluous copy by replacing |
Did you fully duplicate the (distinct) tests in news.cpp, or might there be some left out? So that I may remove the old nannew tests. |
No, I wrote my own test suite without looking at the other tests. Some types are missing in my test, though ( I wouldn't drop any test right now. Having a few dups doesn't hurt. It will be a lot easier to sort things out after/while refactoring the tests. You wanted to do that anyway at some point, right? |
Ok, good. I'll leave them in then. Maybe refactor tests for the next major version. |
Now that I think of it, I don't believe we have (m)any duplicates. Your tests make sure the right value arrives on the JavaScript side, while my tests focus on the C++ side. They do call the same functions but they test very different things. Regarding |
On second thought that wasn't a good idea. The right thing to do is to use |
I should remember to change this the 1.5 branch. |
Most def. It probably segfaults with some STLs... :-/ |
This is not a real PR. It's just a ticket with code.
UPDATE: Seems to be a real PR after all.
UPDATE 2: tldr? Read the Design Notes.
I took a minute and scribbled out a possible redesign of
NanNew(...)
. It's more flexible and allows for very fine grained control but at the same time adds more structure. It also is totally non-greedy and very portable. Please note the generic handling of all v8 integer types. Also note thatv8::External
now behaves as expected. The replacement is currently calledNanNew2(...)
so I can mix and match.It kind of evolved out of #209 and addresses concerns raised in the NAN 2 Discussion.
Sorry about the indentation. But ignoring that what do you guys think?