@@ -27,9 +27,11 @@ using v8::HandleScope;
2727using v8::Integer;
2828using v8::Isolate;
2929using v8::Local;
30+ using v8::MaybeLocal;
3031using v8::Null;
3132using v8::Object;
3233using v8::String;
34+ using v8::TryCatch;
3335using v8::Undefined;
3436using v8::Value;
3537
@@ -1226,6 +1228,29 @@ namespace url {
12261228 }
12271229 }
12281230
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+
12291254 static void Parse (Environment* env,
12301255 Local<Value> recv,
12311256 const char * input,
@@ -1267,23 +1292,7 @@ namespace url {
12671292 undef,
12681293 undef,
12691294 };
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);
12871296 (void )cb->Call (context, recv, arraysize (argv), argv);
12881297 } else if (error_cb->IsFunction ()) {
12891298 Local<Value> argv[2 ] = { undef, undef };
@@ -1418,6 +1427,58 @@ namespace url {
14181427 v8::NewStringType::kNormal ).ToLocalChecked ());
14191428 }
14201429
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+
14211482 static void Init (Local<Object> target,
14221483 Local<Value> unused,
14231484 Local<Context> context,
@@ -1428,6 +1489,7 @@ namespace url {
14281489 env->SetMethod (target, " toUSVString" , ToUSVString);
14291490 env->SetMethod (target, " domainToASCII" , DomainToASCII);
14301491 env->SetMethod (target, " domainToUnicode" , DomainToUnicode);
1492+ env->SetMethod (target, " setURLConstructor" , SetURLConstructor);
14311493
14321494#define XX (name, _ ) NODE_DEFINE_CONSTANT(target, name);
14331495 FLAGS (XX)
0 commit comments