mirror of
https://github.com/denoland/deno.git
synced 2025-01-21 21:50:00 -05:00
Partial implementation of node os polyfill based on currently available Deno functionality (#3821)
This commit is contained in:
parent
161adfc51b
commit
f0a6062012
5 changed files with 505 additions and 1 deletions
|
@ -23,7 +23,7 @@ deno standard library as it's a compatiblity module.
|
|||
- [ ] https
|
||||
- [x] module
|
||||
- [ ] net
|
||||
- [ ] os
|
||||
- [x] os _partly_
|
||||
- [x] path
|
||||
- [ ] perf_hooks
|
||||
- [x] process _partly_
|
||||
|
|
|
@ -25,6 +25,7 @@ import * as nodeFS from "./fs.ts";
|
|||
import * as nodeUtil from "./util.ts";
|
||||
import * as nodePath from "./path.ts";
|
||||
import * as nodeTimers from "./timers.ts";
|
||||
import * as nodeOs from "./os.ts";
|
||||
|
||||
import * as path from "../path/mod.ts";
|
||||
import { assert } from "../testing/asserts.ts";
|
||||
|
@ -582,6 +583,7 @@ nativeModulePolyfill.set("fs", createNativeModule("fs", nodeFS));
|
|||
nativeModulePolyfill.set("util", createNativeModule("util", nodeUtil));
|
||||
nativeModulePolyfill.set("path", createNativeModule("path", nodePath));
|
||||
nativeModulePolyfill.set("timers", createNativeModule("timers", nodeTimers));
|
||||
nativeModulePolyfill.set("os", createNativeModule("os", nodeOs));
|
||||
function loadNativeModule(
|
||||
_filename: string,
|
||||
request: string
|
||||
|
|
|
@ -42,3 +42,9 @@ test(function requireIndexJS() {
|
|||
const { isIndex } = require_("./tests/cjs");
|
||||
assert(isIndex);
|
||||
});
|
||||
|
||||
test(function requireNodeOs() {
|
||||
const os = require_("os");
|
||||
assert(os.arch);
|
||||
assert(typeof os.arch() == "string");
|
||||
});
|
||||
|
|
221
std/node/os.ts
Normal file
221
std/node/os.ts
Normal file
|
@ -0,0 +1,221 @@
|
|||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
import { notImplemented } from "./_utils.ts";
|
||||
|
||||
const SEE_GITHUB_ISSUE = "See https://github.com/denoland/deno/issues/3802";
|
||||
|
||||
interface CPUTimes {
|
||||
/** The number of milliseconds the CPU has spent in user mode */
|
||||
user: number;
|
||||
|
||||
/** The number of milliseconds the CPU has spent in nice mode */
|
||||
nice: number;
|
||||
|
||||
/** The number of milliseconds the CPU has spent in sys mode */
|
||||
sys: number;
|
||||
|
||||
/** The number of milliseconds the CPU has spent in idle mode */
|
||||
idle: number;
|
||||
|
||||
/** The number of milliseconds the CPU has spent in irq mode */
|
||||
irq: number;
|
||||
}
|
||||
|
||||
interface CPUCoreInfo {
|
||||
model: string;
|
||||
|
||||
/** in MHz */
|
||||
speed: number;
|
||||
|
||||
times: CPUTimes;
|
||||
}
|
||||
|
||||
interface NetworkAddress {
|
||||
/** The assigned IPv4 or IPv6 address */
|
||||
address: string;
|
||||
|
||||
/** The IPv4 or IPv6 network mask */
|
||||
netmask: string;
|
||||
|
||||
family: "IPv4" | "IPv6";
|
||||
|
||||
/** The MAC address of the network interface */
|
||||
mac: string;
|
||||
|
||||
/** true if the network interface is a loopback or similar interface that is not remotely accessible; otherwise false */
|
||||
internal: boolean;
|
||||
|
||||
/** The numeric IPv6 scope ID (only specified when family is IPv6) */
|
||||
scopeid?: number;
|
||||
|
||||
/** The assigned IPv4 or IPv6 address with the routing prefix in CIDR notation. If the netmask is invalid, this property is set to null. */
|
||||
cidr: string;
|
||||
}
|
||||
|
||||
interface NetworkInterfaces {
|
||||
[key: string]: NetworkAddress[];
|
||||
}
|
||||
|
||||
export interface UserInfoOptions {
|
||||
encoding: string;
|
||||
}
|
||||
|
||||
interface UserInfo {
|
||||
username: string;
|
||||
uid: number;
|
||||
gid: number;
|
||||
shell: string;
|
||||
homedir: string;
|
||||
}
|
||||
|
||||
/** Returns the operating system CPU architecture for which the Deno binary was compiled */
|
||||
export function arch(): string {
|
||||
return Deno.build.arch;
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function cpus(): CPUCoreInfo[] {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function endianness(): "BE" | "LE" {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function freemem(): number {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function getPriority(pid = 0): number {
|
||||
validateInt32(pid, "pid");
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Returns the string path of the current user's home directory. */
|
||||
export function homedir(): string {
|
||||
return Deno.dir("home");
|
||||
}
|
||||
|
||||
/** Returns the host name of the operating system as a string. */
|
||||
export function hostname(): string {
|
||||
return Deno.hostname();
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function loadavg(): number[] {
|
||||
if (Deno.build.os == "win") {
|
||||
return [0, 0, 0];
|
||||
}
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function networkInterfaces(): NetworkInterfaces {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function platform(): string {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function release(): string {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function setPriority(pid: number, priority?: number): void {
|
||||
/* The node API has the 'pid' as the first parameter and as optional.
|
||||
This makes for a problematic implementation in Typescript. */
|
||||
if (priority === undefined) {
|
||||
priority = pid;
|
||||
pid = 0;
|
||||
}
|
||||
validateInt32(pid, "pid");
|
||||
validateInt32(priority, "priority", -20, 19);
|
||||
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function tmpdir(): string {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function totalmem(): number {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function type(): string {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function uptime(): number {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function userInfo(
|
||||
/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
|
||||
options: UserInfoOptions = { encoding: "utf-8" }
|
||||
): UserInfo {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
export const constants = {
|
||||
// UV_UDP_REUSEADDR: 4, //see https://nodejs.org/docs/latest-v12.x/api/os.html#os_libuv_constants
|
||||
dlopen: {
|
||||
// see https://nodejs.org/docs/latest-v12.x/api/os.html#os_dlopen_constants
|
||||
},
|
||||
errno: {
|
||||
// see https://nodejs.org/docs/latest-v12.x/api/os.html#os_error_constants
|
||||
},
|
||||
signals: Deno.Signal,
|
||||
priority: {
|
||||
// see https://nodejs.org/docs/latest-v12.x/api/os.html#os_priority_constants
|
||||
}
|
||||
};
|
||||
|
||||
export const EOL = Deno.build.os == "win" ? "\r\n" : "\n";
|
||||
|
||||
const validateInt32 = (
|
||||
value: number,
|
||||
name: string,
|
||||
min = -2147483648,
|
||||
max = 2147483647
|
||||
): void => {
|
||||
// The defaults for min and max correspond to the limits of 32-bit integers.
|
||||
if (!Number.isInteger(value)) {
|
||||
throw new Error(`${name} must be 'an integer' but was ${value}`);
|
||||
}
|
||||
if (value < min || value > max) {
|
||||
throw new Error(
|
||||
`${name} must be >= ${min} && <= ${max}. Value was ${value}`
|
||||
);
|
||||
}
|
||||
};
|
275
std/node/os_test.ts
Normal file
275
std/node/os_test.ts
Normal file
|
@ -0,0 +1,275 @@
|
|||
import { test } from "../testing/mod.ts";
|
||||
import {
|
||||
assert,
|
||||
assertThrows,
|
||||
assertEquals,
|
||||
AssertionError
|
||||
} from "../testing/asserts.ts";
|
||||
import * as os from "./os.ts";
|
||||
|
||||
test({
|
||||
name: "build architecture is a string",
|
||||
fn() {
|
||||
assertEquals(typeof os.arch(), "string");
|
||||
}
|
||||
});
|
||||
|
||||
test({
|
||||
name: "home directory is a string",
|
||||
fn() {
|
||||
assertEquals(typeof os.homedir(), "string");
|
||||
}
|
||||
});
|
||||
|
||||
test({
|
||||
name: "hostname is a string",
|
||||
fn() {
|
||||
assertEquals(typeof os.hostname(), "string");
|
||||
}
|
||||
});
|
||||
|
||||
test({
|
||||
name: "getPriority(): PID must be a 32 bit integer",
|
||||
fn() {
|
||||
assertThrows(
|
||||
() => {
|
||||
os.getPriority(3.15);
|
||||
},
|
||||
Error,
|
||||
"pid must be 'an integer'"
|
||||
);
|
||||
assertThrows(
|
||||
() => {
|
||||
os.getPriority(9999999999);
|
||||
},
|
||||
Error,
|
||||
"must be >= -2147483648 && <= 2147483647"
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test({
|
||||
name: "setPriority(): PID must be a 32 bit integer",
|
||||
fn() {
|
||||
assertThrows(
|
||||
() => {
|
||||
os.setPriority(3.15, 0);
|
||||
},
|
||||
Error,
|
||||
"pid must be 'an integer'"
|
||||
);
|
||||
assertThrows(
|
||||
() => {
|
||||
os.setPriority(9999999999, 0);
|
||||
},
|
||||
Error,
|
||||
"pid must be >= -2147483648 && <= 2147483647"
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test({
|
||||
name: "setPriority(): priority must be an integer between -20 and 19",
|
||||
fn() {
|
||||
assertThrows(
|
||||
() => {
|
||||
os.setPriority(0, 3.15);
|
||||
},
|
||||
Error,
|
||||
"priority must be 'an integer'"
|
||||
);
|
||||
assertThrows(
|
||||
() => {
|
||||
os.setPriority(0, -21);
|
||||
},
|
||||
Error,
|
||||
"priority must be >= -20 && <= 19"
|
||||
);
|
||||
assertThrows(
|
||||
() => {
|
||||
os.setPriority(0, 20);
|
||||
},
|
||||
Error,
|
||||
"priority must be >= -20 && <= 19"
|
||||
);
|
||||
assertThrows(
|
||||
() => {
|
||||
os.setPriority(0, 9999999999);
|
||||
},
|
||||
Error,
|
||||
"priority must be >= -20 && <= 19"
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test({
|
||||
name:
|
||||
"setPriority(): if only one argument specified, then this is the priority, NOT the pid",
|
||||
fn() {
|
||||
assertThrows(
|
||||
() => {
|
||||
os.setPriority(3.15);
|
||||
},
|
||||
Error,
|
||||
"priority must be 'an integer'"
|
||||
);
|
||||
assertThrows(
|
||||
() => {
|
||||
os.setPriority(-21);
|
||||
},
|
||||
Error,
|
||||
"priority must be >= -20 && <= 19"
|
||||
);
|
||||
assertThrows(
|
||||
() => {
|
||||
os.setPriority(20);
|
||||
},
|
||||
Error,
|
||||
"priority must be >= -20 && <= 19"
|
||||
);
|
||||
assertThrows(
|
||||
() => {
|
||||
os.setPriority(9999999999);
|
||||
},
|
||||
Error,
|
||||
"priority must be >= -20 && <= 19"
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test({
|
||||
name: "Signals are as expected",
|
||||
fn() {
|
||||
// Test a few random signals for equality
|
||||
assertEquals(os.constants.signals.SIGKILL, Deno.Signal.SIGKILL);
|
||||
assertEquals(os.constants.signals.SIGCONT, Deno.Signal.SIGCONT);
|
||||
assertEquals(os.constants.signals.SIGXFSZ, Deno.Signal.SIGXFSZ);
|
||||
}
|
||||
});
|
||||
|
||||
test({
|
||||
name: "EOL is as expected",
|
||||
fn() {
|
||||
assert(os.EOL == "\r\n" || os.EOL == "\n");
|
||||
}
|
||||
});
|
||||
|
||||
// Method is currently implemented correctly for windows but not for any other os
|
||||
test({
|
||||
name: "Load average is an array of 3 numbers",
|
||||
fn() {
|
||||
try {
|
||||
const result = os.loadavg();
|
||||
assert(result.length == 3);
|
||||
assertEquals(typeof result[0], "number");
|
||||
assertEquals(typeof result[1], "number");
|
||||
assertEquals(typeof result[2], "number");
|
||||
} catch (error) {
|
||||
if (!(Object.getPrototypeOf(error) === Error.prototype)) {
|
||||
const errMsg = `Unexpected error class: ${error.name}`;
|
||||
throw new AssertionError(errMsg);
|
||||
} else if (!error.message.includes("Not implemented")) {
|
||||
throw new AssertionError(
|
||||
"Expected this error to contain 'Not implemented'"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test({
|
||||
name: "APIs not yet implemented",
|
||||
fn() {
|
||||
assertThrows(
|
||||
() => {
|
||||
os.cpus();
|
||||
},
|
||||
Error,
|
||||
"Not implemented"
|
||||
);
|
||||
assertThrows(
|
||||
() => {
|
||||
os.endianness();
|
||||
},
|
||||
Error,
|
||||
"Not implemented"
|
||||
);
|
||||
assertThrows(
|
||||
() => {
|
||||
os.freemem();
|
||||
},
|
||||
Error,
|
||||
"Not implemented"
|
||||
);
|
||||
assertThrows(
|
||||
() => {
|
||||
os.getPriority();
|
||||
},
|
||||
Error,
|
||||
"Not implemented"
|
||||
);
|
||||
assertThrows(
|
||||
() => {
|
||||
os.networkInterfaces();
|
||||
},
|
||||
Error,
|
||||
"Not implemented"
|
||||
);
|
||||
assertThrows(
|
||||
() => {
|
||||
os.platform();
|
||||
},
|
||||
Error,
|
||||
"Not implemented"
|
||||
);
|
||||
assertThrows(
|
||||
() => {
|
||||
os.release();
|
||||
},
|
||||
Error,
|
||||
"Not implemented"
|
||||
);
|
||||
assertThrows(
|
||||
() => {
|
||||
os.setPriority(0);
|
||||
},
|
||||
Error,
|
||||
"Not implemented"
|
||||
);
|
||||
assertThrows(
|
||||
() => {
|
||||
os.tmpdir();
|
||||
},
|
||||
Error,
|
||||
"Not implemented"
|
||||
);
|
||||
assertThrows(
|
||||
() => {
|
||||
os.totalmem();
|
||||
},
|
||||
Error,
|
||||
"Not implemented"
|
||||
);
|
||||
assertThrows(
|
||||
() => {
|
||||
os.type();
|
||||
},
|
||||
Error,
|
||||
"Not implemented"
|
||||
);
|
||||
assertThrows(
|
||||
() => {
|
||||
os.uptime();
|
||||
},
|
||||
Error,
|
||||
"Not implemented"
|
||||
);
|
||||
assertThrows(
|
||||
() => {
|
||||
os.userInfo();
|
||||
},
|
||||
Error,
|
||||
"Not implemented"
|
||||
);
|
||||
}
|
||||
});
|
Loading…
Add table
Reference in a new issue