@@ -27,9 +27,11 @@ using v8::HandleScope;
27
27
using v8::Integer;
28
28
using v8::Isolate;
29
29
using v8::Local;
30
+ using v8::MaybeLocal;
30
31
using v8::Null;
31
32
using v8::Object;
32
33
using v8::String;
34
+ using v8::TryCatch;
33
35
using v8::Undefined;
34
36
using v8::Value;
35
37
@@ -1226,6 +1228,29 @@ namespace url {
1226
1228
}
1227
1229
}
1228
1230
1231
+ static inline void SetArgs (Environment* env,
1232
+ Local<Value> argv[],
1233
+ const struct url_data * url) {
1234
+ Isolate* isolate = env->isolate ();
1235
+ argv[ARG_FLAGS] = Integer::NewFromUnsigned (isolate, url->flags );
1236
+ if (url->flags & URL_FLAGS_HAS_SCHEME)
1237
+ argv[ARG_PROTOCOL] = OneByteString (isolate, url->scheme .c_str ());
1238
+ if (url->flags & URL_FLAGS_HAS_USERNAME)
1239
+ argv[ARG_USERNAME] = UTF8STRING (isolate, url->username );
1240
+ if (url->flags & URL_FLAGS_HAS_PASSWORD)
1241
+ argv[ARG_PASSWORD] = UTF8STRING (isolate, url->password );
1242
+ if (url->flags & URL_FLAGS_HAS_HOST)
1243
+ argv[ARG_HOST] = UTF8STRING (isolate, url->host );
1244
+ if (url->flags & URL_FLAGS_HAS_QUERY)
1245
+ argv[ARG_QUERY] = UTF8STRING (isolate, url->query );
1246
+ if (url->flags & URL_FLAGS_HAS_FRAGMENT)
1247
+ argv[ARG_FRAGMENT] = UTF8STRING (isolate, url->fragment );
1248
+ if (url->port > -1 )
1249
+ argv[ARG_PORT] = Integer::New (isolate, url->port );
1250
+ if (url->flags & URL_FLAGS_HAS_PATH)
1251
+ argv[ARG_PATH] = Copy (env, url->path );
1252
+ }
1253
+
1229
1254
static void Parse (Environment* env,
1230
1255
Local<Value> recv,
1231
1256
const char * input,
@@ -1267,23 +1292,7 @@ namespace url {
1267
1292
undef,
1268
1293
undef,
1269
1294
};
1270
- argv[ARG_FLAGS] = Integer::NewFromUnsigned (isolate, url.flags );
1271
- if (url.flags & URL_FLAGS_HAS_SCHEME)
1272
- argv[ARG_PROTOCOL] = OneByteString (isolate, url.scheme .c_str ());
1273
- if (url.flags & URL_FLAGS_HAS_USERNAME)
1274
- argv[ARG_USERNAME] = UTF8STRING (isolate, url.username );
1275
- if (url.flags & URL_FLAGS_HAS_PASSWORD)
1276
- argv[ARG_PASSWORD] = UTF8STRING (isolate, url.password );
1277
- if (url.flags & URL_FLAGS_HAS_HOST)
1278
- argv[ARG_HOST] = UTF8STRING (isolate, url.host );
1279
- if (url.flags & URL_FLAGS_HAS_QUERY)
1280
- argv[ARG_QUERY] = UTF8STRING (isolate, url.query );
1281
- if (url.flags & URL_FLAGS_HAS_FRAGMENT)
1282
- argv[ARG_FRAGMENT] = UTF8STRING (isolate, url.fragment );
1283
- if (url.port > -1 )
1284
- argv[ARG_PORT] = Integer::New (isolate, url.port );
1285
- if (url.flags & URL_FLAGS_HAS_PATH)
1286
- argv[ARG_PATH] = Copy (env, url.path );
1295
+ SetArgs (env, argv, &url);
1287
1296
(void )cb->Call (context, recv, arraysize (argv), argv);
1288
1297
} else if (error_cb->IsFunction ()) {
1289
1298
Local<Value> argv[2 ] = { undef, undef };
@@ -1418,6 +1427,58 @@ namespace url {
1418
1427
v8::NewStringType::kNormal ).ToLocalChecked ());
1419
1428
}
1420
1429
1430
+ // This function works by calling out to a JS function that creates and
1431
+ // returns the JS URL object. Be mindful of the JS<->Native boundary
1432
+ // crossing that is required.
1433
+ const Local<Value> URL::ToObject (Environment* env) const {
1434
+ Isolate* isolate = env->isolate ();
1435
+ Local<Context> context = env->context ();
1436
+ HandleScope handle_scope (isolate);
1437
+ Context::Scope context_scope (context);
1438
+
1439
+ const Local<Value> undef = Undefined (isolate);
1440
+
1441
+ if (context_.flags & URL_FLAGS_FAILED)
1442
+ return Local<Value>();
1443
+
1444
+ Local<Value> argv[9 ] = {
1445
+ undef,
1446
+ undef,
1447
+ undef,
1448
+ undef,
1449
+ undef,
1450
+ undef,
1451
+ undef,
1452
+ undef,
1453
+ undef,
1454
+ };
1455
+ SetArgs (env, argv, &context_);
1456
+
1457
+ TryCatch try_catch (isolate);
1458
+
1459
+ // The SetURLConstructor method must have been called already to
1460
+ // set the constructor function used below. SetURLConstructor is
1461
+ // called automatically when the internal/url.js module is loaded
1462
+ // during the internal/bootstrap_node.js processing.
1463
+ MaybeLocal<Value> ret =
1464
+ env->url_constructor_function ()
1465
+ ->Call (env->context (), undef, 9 , argv);
1466
+
1467
+ if (ret.IsEmpty ()) {
1468
+ ClearFatalExceptionHandlers (env);
1469
+ FatalException (isolate, try_catch);
1470
+ }
1471
+
1472
+ return ret.ToLocalChecked ();
1473
+ }
1474
+
1475
+ static void SetURLConstructor (const FunctionCallbackInfo<Value>& args) {
1476
+ Environment* env = Environment::GetCurrent (args);
1477
+ CHECK_EQ (args.Length (), 1 );
1478
+ CHECK (args[0 ]->IsFunction ());
1479
+ env->set_url_constructor_function (args[0 ].As <Function>());
1480
+ }
1481
+
1421
1482
static void Init (Local<Object> target,
1422
1483
Local<Value> unused,
1423
1484
Local<Context> context,
@@ -1428,6 +1489,7 @@ namespace url {
1428
1489
env->SetMethod (target, " toUSVString" , ToUSVString);
1429
1490
env->SetMethod (target, " domainToASCII" , DomainToASCII);
1430
1491
env->SetMethod (target, " domainToUnicode" , DomainToUnicode);
1492
+ env->SetMethod (target, " setURLConstructor" , SetURLConstructor);
1431
1493
1432
1494
#define XX (name, _ ) NODE_DEFINE_CONSTANT(target, name);
1433
1495
FLAGS (XX)
0 commit comments