Initial upgrade to v18

This commit is contained in:
Alex Hultman 2020-06-05 12:36:36 +02:00
parent 550c49d302
commit b4df9ebf5f
6 changed files with 147 additions and 16 deletions

View file

@ -20,6 +20,7 @@ void uWS_App_ws(const FunctionCallbackInfo<Value> &args) {
return;
}
UniquePersistent<Function> upgradePf;
UniquePersistent<Function> openPf;
UniquePersistent<Function> messagePf;
UniquePersistent<Function> drainPf;
@ -27,10 +28,6 @@ void uWS_App_ws(const FunctionCallbackInfo<Value> &args) {
UniquePersistent<Function> pingPf;
UniquePersistent<Function> pongPf;
struct PerSocketData {
UniquePersistent<Object> *socketPf;
};
/* Get the behavior object */
if (args.Length() == 2) {
Local<Object> behaviorObject = Local<Object>::Cast(args[1]);
@ -59,6 +56,8 @@ void uWS_App_ws(const FunctionCallbackInfo<Value> &args) {
behavior.maxBackpressure = maybeMaxBackpressure.ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).ToChecked();
}
/* Upgrade */
upgradePf.Reset(args.GetIsolate(), Local<Function>::Cast(behaviorObject->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "upgrade", NewStringType::kNormal).ToLocalChecked()).ToLocalChecked()));
/* Open */
openPf.Reset(args.GetIsolate(), Local<Function>::Cast(behaviorObject->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "open", NewStringType::kNormal).ToLocalChecked()).ToLocalChecked()));
/* Message */
@ -74,28 +73,58 @@ void uWS_App_ws(const FunctionCallbackInfo<Value> &args) {
}
/* Upgrade handler is always optional */
if (upgradePf != Undefined(isolate)) {
behavior.upgrade = [upgradePf = std::move(upgradePf), perContextData](auto *res, auto *req, auto *context) {
Isolate *isolate = perContextData->isolate;
HandleScope hs(isolate);
Local<Function> upgradeLf = Local<Function>::New(isolate, upgradePf);
Local<Object> resObject = perContextData->resTemplate[getAppTypeIndex<APP>()].Get(isolate)->Clone();
resObject->SetAlignedPointerInInternalField(0, res);
Local<Object> reqObject = perContextData->reqTemplate.Get(isolate)->Clone();
reqObject->SetAlignedPointerInInternalField(0, req);
Local<Value> argv[3] = {resObject, reqObject, External::New(isolate, (void *) context)};
CallJS(isolate, upgradeLf, 3, argv);
/* Properly invalidate req */
reqObject->SetAlignedPointerInInternalField(0, nullptr);
/* µWS itself will terminate if not responded and not attached
* onAborted handler, so we can assume it's done */
};
}
/* Open handler is NOT optional for the wrapper */
behavior.open = [openPf = std::move(openPf), perContextData](auto *ws, auto *req) {
behavior.open = [openPf = std::move(openPf), perContextData](auto *ws) {
Isolate *isolate = perContextData->isolate;
HandleScope hs(isolate);
printf("Open event called!\n");
/* Retrieve temporary userData object */
PerSocketData *perSocketData = (PerSocketData *) ws->getUserData();
// if socketPf is nullptr we have nothing to copy
Local<Object> userData = Local<Object>::New(isolate, *(perSocketData->socketPf));
/* Create a new websocket object */
Local<Object> wsObject = perContextData->wsTemplate[getAppTypeIndex<APP>()].Get(isolate)->Clone();
wsObject->SetAlignedPointerInInternalField(0, ws);
/* Create the HttpRequest wrapper */
Local<Object> reqObject = perContextData->reqTemplate.Get(isolate)->Clone();
reqObject->SetAlignedPointerInInternalField(0, req);
/* Copy entires from userData */
wsObject->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "userData"), userData);
/* Attach a new V8 object with pointer to us, to us */
PerSocketData *perSocketData = (PerSocketData *) ws->getUserData();
perSocketData->socketPf = new UniquePersistent<Object>;
perSocketData->socketPf->Reset(isolate, wsObject);
Local<Function> openLf = Local<Function>::New(isolate, openPf);
if (!openLf->IsUndefined()) {
Local<Value> argv[] = {wsObject, reqObject};
CallJS(isolate, openLf, 2, argv);
Local<Value> argv[] = {wsObject};
CallJS(isolate, openLf, 1, argv);
}
};

View file

@ -226,7 +226,7 @@ struct HttpResponseWrapper {
if (value.isInvalid(args)) {
return;
}
res->writeHeader(header.getString(),value.getString());
res->writeHeader(header.getString(), value.getString());
args.GetReturnValue().Set(args.Holder());
}
@ -248,6 +248,58 @@ struct HttpResponseWrapper {
}
}
template <bool SSL>
static void res_upgrade(const FunctionCallbackInfo<Value> &args) {
Isolate *isolate = args.GetIsolate();
auto *res = getHttpResponse<SSL>(args);
if (res) {
printf("Calling upgrade!\n");
if (args.Length() != 5) {
return;
}
/* We are being passed userData (wsObject) */
//Local<Object> wsObject = args[0];
//Local<String> secWebSocketKey = args[1];
//Local<String> secWebSocketProtocol = args[2];
//Local<String> secWebSocketExtensions = args[3];
//Local<External> context = args[4];
NativeString secWebSocketKey(args.GetIsolate(), args[1]);
if (secWebSocketKey.isInvalid(args)) {
return;
}
NativeString secWebSocketProtocol(args.GetIsolate(), args[2]);
if (secWebSocketProtocol.isInvalid(args)) {
return;
}
NativeString secWebSocketExtensions(args.GetIsolate(), args[3]);
if (secWebSocketExtensions.isInvalid(args)) {
return;
}
auto *context = (struct us_socket_context_t *) Local<External>::Cast(args[4])->Value();
invalidateResObject(args);
UniquePersistent<Object> userData;
userData.Reset(isolate, Local<Object>::Cast(args[0]));
printf("Upgrading now!\n");
res->template upgrade<PerSocketData>({
.socketPf = &userData
}, secWebSocketKey.getString(), secWebSocketProtocol.getString(),
secWebSocketExtensions.getString(), context);
/* Nothing is returned */
}
}
template <bool SSL>
static Local<Object> init(Isolate *isolate) {
Local<FunctionTemplate> resTemplateLocal = FunctionTemplate::New(isolate);
@ -271,10 +323,11 @@ struct HttpResponseWrapper {
resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "onData", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, res_onData<SSL>));
resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "getRemoteAddress", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, res_getRemoteAddress<SSL>));
resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "cork", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, res_cork<SSL>));
resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "upgrade", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, res_upgrade<SSL>));
/* Create our template */
Local<Object> resObjectLocal = resTemplateLocal->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
return resObjectLocal;
}
};

View file

@ -17,6 +17,10 @@ MaybeLocal<Value> CallJS(Isolate *isolate, Local<Function> f, int argc, Local<Va
}
}
struct PerSocketData {
UniquePersistent<Object> *socketPf = nullptr;
};
struct PerContextData {
Isolate *isolate;
UniquePersistent<Object> reqTemplate;