Skip to content

Instantly share code, notes, and snippets.

@deepal
Created October 15, 2019 21:33
Show Gist options
  • Save deepal/23ddf2414cadc777c05adee6ad9f3c67 to your computer and use it in GitHub Desktop.
Save deepal/23ddf2414cadc777c05adee6ad9f3c67 to your computer and use it in GitHub Desktop.
Factory method to create worker instances
void Worker::New(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
CHECK(args.IsConstructCall());
if (env->isolate_data()->platform() == nullptr) {
THROW_ERR_MISSING_PLATFORM_FOR_WORKER(env);
return;
}
std::string url;
std::shared_ptr<PerIsolateOptions> per_isolate_opts = nullptr;
std::vector<std::string> exec_argv_out;
bool has_explicit_exec_argv = false;
CHECK_EQ(args.Length(), 2);
// Argument might be a string or URL
if (!args[0]->IsNullOrUndefined()) {
Utf8Value value(
args.GetIsolate(),
args[0]->ToString(env->context()).FromMaybe(Local<String>()));
url.append(value.out(), value.length());
std::cout << "node_worker.cc[Worker::New()] Creating new worker for " << url << "\n";
}
if (args[1]->IsArray()) {
// Check this out later
Local<Array> array = args[1].As<Array>();
// The first argument is reserved for program name, but we don't need it
// in workers.
has_explicit_exec_argv = true;
std::vector<std::string> exec_argv = {""};
uint32_t length = array->Length();
for (uint32_t i = 0; i < length; i++) {
Local<Value> arg;
if (!array->Get(env->context(), i).ToLocal(&arg)) {
return;
}
MaybeLocal<String> arg_v8_string =
arg->ToString(env->context());
if (arg_v8_string.IsEmpty()) {
return;
}
Utf8Value arg_utf8_value(
args.GetIsolate(),
arg_v8_string.FromMaybe(Local<String>()));
std::string arg_string(arg_utf8_value.out(), arg_utf8_value.length());
exec_argv.push_back(arg_string);
}
std::vector<std::string> invalid_args{};
std::vector<std::string> errors{};
per_isolate_opts.reset(new PerIsolateOptions());
// Using invalid_args as the v8_args argument as it stores unknown
// options for the per isolate parser.
options_parser::Parse(
&exec_argv,
&exec_argv_out,
&invalid_args,
per_isolate_opts.get(),
kDisallowedInEnvironment,
&errors);
// The first argument is program name.
invalid_args.erase(invalid_args.begin());
if (errors.size() > 0 || invalid_args.size() > 0) {
Local<Value> error;
if (!ToV8Value(env->context(),
errors.size() > 0 ? errors : invalid_args)
.ToLocal(&error)) {
return;
}
Local<String> key =
FIXED_ONE_BYTE_STRING(env->isolate(), "invalidExecArgv");
// Ignore the return value of Set() because exceptions bubble up to JS
// when we return anyway.
USE(args.This()->Set(env->context(), key, error));
return;
}
}
if (!has_explicit_exec_argv)
exec_argv_out = env->exec_argv();
new Worker(env, args.This(), url, per_isolate_opts, std::move(exec_argv_out));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment