Skip to content

lib: add navigator.onLine #50224

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions doc/api/globals.md
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,32 @@ logical processors available to the current Node.js instance.
console.log(`This process is running on ${navigator.hardwareConcurrency}`);
```

### `navigator.onLine`

<!-- YAML
added: REPLACEME
-->

* {boolean}

The [`navigator.onLine`](https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-online-dev)
read-only property returns the online status available
of the current Node.js instance. If the Node.js instance is not able to detect
to a local area network (LAN) or a router, it is offline; all other conditions
return true. So while you can assume that the Node.js instance is offline when
it returns a false value, you cannot assume that a true value necessarily
means that the Node.js instance can access the internet. You could be getting
false positives, such as in cases where the computer is running a
virtualization software that has virtual ethernet adapters that are always
"connected."

Therefore, if you really want to determine the online status of the Node.js
instance, you should develop additional means for checking.

```js
console.log(`This process is ${navigator.onLine ? 'online' : 'offline'}`);
```

## `PerformanceEntry`

<!-- YAML
Expand Down
9 changes: 9 additions & 0 deletions lib/internal/navigator.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const {

const {
getAvailableParallelism,
getOnLineStatus,
} = internalBinding('os');

const kInitialize = Symbol('kInitialize');
Expand All @@ -37,10 +38,18 @@ class Navigator {
this.#availableParallelism ??= getAvailableParallelism();
return this.#availableParallelism;
}

/**
* @return {boolean}
*/
get onLine() {
return getOnLineStatus();
}
}

ObjectDefineProperties(Navigator.prototype, {
hardwareConcurrency: kEnumerableProperty,
onLine: kEnumerableProperty,
});

module.exports = {
Expand Down
28 changes: 28 additions & 0 deletions src/node_os.cc
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,32 @@ static void GetInterfaceAddresses(const FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().Set(Array::New(isolate, result.data(), result.size()));
}

static void GetOnLineStatus(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
uv_interface_address_t* interfaces;
int count, i;

int err = uv_interface_addresses(&interfaces, &count);

if (err == UV_ENOSYS) return args.GetReturnValue().Set(false);

if (err) {
CHECK_GE(args.Length(), 1);
env->CollectUVExceptionInfo(
args[args.Length() - 1], errno, "uv_interface_addresses");
return args.GetReturnValue().Set(false);
}

for (i = 0; i < count; i++) {
if (interfaces[i].is_internal == false) {
uv_free_interface_addresses(interfaces, count);
return args.GetReturnValue().Set(true);
}
}

uv_free_interface_addresses(interfaces, count);
return args.GetReturnValue().Set(false);
}

static void GetHomeDirectory(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
Expand Down Expand Up @@ -403,6 +429,7 @@ void Initialize(Local<Object> target,
SetMethod(context, target, "getPriority", GetPriority);
SetMethod(
context, target, "getAvailableParallelism", GetAvailableParallelism);
SetMethod(context, target, "getOnLineStatus", GetOnLineStatus);
SetMethod(context, target, "getOSInformation", GetOSInformation);
target
->Set(context,
Expand All @@ -419,6 +446,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
registry->Register(GetFreeMemory);
registry->Register(GetCPUInfo);
registry->Register(GetInterfaceAddresses);
registry->Register(GetOnLineStatus);
registry->Register(GetHomeDirectory);
registry->Register(GetUserInfo);
registry->Register(SetPriority);
Expand Down
2 changes: 2 additions & 0 deletions test/parallel/test-navigator.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ const is = {
is.number(+navigator.hardwareConcurrency, 'hardwareConcurrency');
is.number(navigator.hardwareConcurrency, 'hardwareConcurrency');
assert.ok(navigator.hardwareConcurrency > 0);

assert.strictEqual(typeof navigator.onLine, 'boolean');
1 change: 1 addition & 0 deletions typings/internalBinding/os.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export interface OSBinding {
getFreeMem(): number;
getCPUs(): Array<string | number>;
getInterfaceAddresses(ctx: InternalOSBinding.OSContext): Array<string | number | boolean> | undefined;
getOnLineStatus(): boolean;
getHomeDirectory(ctx: InternalOSBinding.OSContext): string | undefined;
getUserInfo(options: { encoding?: string } | undefined, ctx: InternalOSBinding.OSContext): {
uid: number;
Expand Down