diff --git a/app/current/src/main/scala/io/scalajs/nodejs/HasFileDescriptor.scala b/app/current/src/main/scala/io/scalajs/nodejs/HasFileDescriptor.scala new file mode 100644 index 000000000..62a54b8f7 --- /dev/null +++ b/app/current/src/main/scala/io/scalajs/nodejs/HasFileDescriptor.scala @@ -0,0 +1,7 @@ +package io.scalajs.nodejs + +import scala.scalajs.js + +trait HasFileDescriptor extends js.Object { + def fd: FileDescriptor +} diff --git a/app/current/src/main/scala/io/scalajs/nodejs/HasHandle.scala b/app/current/src/main/scala/io/scalajs/nodejs/HasHandle.scala new file mode 100644 index 000000000..4171f8020 --- /dev/null +++ b/app/current/src/main/scala/io/scalajs/nodejs/HasHandle.scala @@ -0,0 +1,7 @@ +package io.scalajs.nodejs + +import scala.scalajs.js + +trait HasHandle extends js.Object { + def _handle: js.Any +} diff --git a/app/current/src/main/scala/io/scalajs/nodejs/cluster/Address.scala b/app/current/src/main/scala/io/scalajs/nodejs/cluster/Address.scala index 6f7bce120..d4d4835b1 100644 --- a/app/current/src/main/scala/io/scalajs/nodejs/cluster/Address.scala +++ b/app/current/src/main/scala/io/scalajs/nodejs/cluster/Address.scala @@ -1,16 +1,14 @@ package io.scalajs.nodejs.cluster import scala.scalajs.js +import scala.scalajs.js.| -/** - * Address - */ @js.native trait Address extends js.Object { def address: String = js.native - def port: Integer = js.native + def port: Int = js.native /** * The addressType is one of: @@ -19,6 +17,6 @@ trait Address extends js.Object { * -1 (unix domain socket) * "udp4" or "udp6" (UDP v4 or v6) */ - def addressType: js.Any = js.native + def addressType: String | Int = js.native } diff --git a/app/current/src/main/scala/io/scalajs/nodejs/cluster/Cluster.scala b/app/current/src/main/scala/io/scalajs/nodejs/cluster/Cluster.scala index b6c7fab44..f52c10abc 100644 --- a/app/current/src/main/scala/io/scalajs/nodejs/cluster/Cluster.scala +++ b/app/current/src/main/scala/io/scalajs/nodejs/cluster/Cluster.scala @@ -85,7 +85,7 @@ trait Cluster extends IEventEmitter { * This can only be called from the master process. * @example cluster.disconnect([callback]) */ - def disconnect(callback: js.Function = null): Unit = js.native + def disconnect(callback: js.Function = js.native): Unit = js.native /** * Spawn a new worker process. @@ -93,7 +93,7 @@ trait Cluster extends IEventEmitter { * @return a new worker * @example cluster.fork([env]) */ - def fork(env: js.Any = null): Worker = js.native + def fork(env: js.Any = js.native): Worker = js.native /** * setupMaster is used to change the default 'fork' behavior. Once called, the settings will be present in cluster.settings. diff --git a/app/current/src/main/scala/io/scalajs/nodejs/cluster/ClusterSettings.scala b/app/current/src/main/scala/io/scalajs/nodejs/cluster/ClusterSettings.scala index b1d3305db..17e005c75 100644 --- a/app/current/src/main/scala/io/scalajs/nodejs/cluster/ClusterSettings.scala +++ b/app/current/src/main/scala/io/scalajs/nodejs/cluster/ClusterSettings.scala @@ -1,8 +1,11 @@ package io.scalajs.nodejs.cluster -import io.scalajs.util.ScalaJsHelper._ +import com.thoughtworks.enableIf +import io.scalajs.JsNumber +import io.scalajs.nodejs.{GID, UID} import scala.scalajs.js +import scala.scalajs.js.| /** * Cluster Settings @@ -11,35 +14,55 @@ import scala.scalajs.js trait ClusterSettings extends js.Object { /** list of string arguments passed to the Node.js executable. (Default=process.execArgv) */ - var execArgv: js.Array[js.Any] = js.native + var execArgv: js.Array[String] = js.native /** file path to worker file. (Default=process.argv[1]) */ var exec: String = js.native /** string arguments passed to worker. (Default=process.argv.slice(2)) */ - var args: js.Array[js.Any] = js.native + var args: js.Array[String] = js.native /** whether or not to send output to parent's stdio. (Default=false) */ var silent: Boolean = js.native /** Sets the user identity of the process. (See setuid(2).) */ - var uid: Integer = js.native + var uid: UID = js.native - /* Sets the group identity of the process. (See setgid(2).) */ - var gid: Integer = js.native + /** Sets the group identity of the process. (See setgid(2).) */ + var gid: GID = js.native + + var stdio: js.Array[js.Any] = js.native + + var inspectPort: JsNumber | js.Function = js.native + + @enableIf(io.scalajs.nodejs.CompilerSwitches.gteNodeJs10) + var cwd: String = js.native + + @enableIf(io.scalajs.nodejs.CompilerSwitches.gteNodeJs10) + var windowsHide: Boolean = js.native } /** * Cluster Settings Companion */ object ClusterSettings { - - def apply(exec: String = null, args: js.Array[js.Any] = null, silent: Boolean = false): ClusterSettings = { - val settings = New[ClusterSettings] - settings.exec = exec - settings.args = args - settings.silent = silent - settings + def apply(execArgv: js.Array[String] = null, + exec: String = null, + args: js.Array[String] = null, + silent: Boolean = false, + stdio: js.Array[js.Any] = null, + inspectPort: JsNumber | js.Function = null, + cwd: String = null, + windowsHide: Boolean = false): ClusterSettings = { + val settings = js.Dynamic.literal() + settings.updateDynamic("execArgv")(execArgv) + settings.updateDynamic("exec")(exec) + settings.updateDynamic("args")(args) + settings.updateDynamic("silent")(silent) + settings.updateDynamic("stdio")(stdio) + settings.updateDynamic("inspectPort")(inspectPort.asInstanceOf[js.Any]) + settings.updateDynamic("cwd")(cwd) + settings.updateDynamic("windowsHide")(windowsHide) + settings.asInstanceOf[ClusterSettings] } - } diff --git a/app/current/src/main/scala/io/scalajs/nodejs/cluster/Worker.scala b/app/current/src/main/scala/io/scalajs/nodejs/cluster/Worker.scala index edc00fc52..c072f5d3a 100644 --- a/app/current/src/main/scala/io/scalajs/nodejs/cluster/Worker.scala +++ b/app/current/src/main/scala/io/scalajs/nodejs/cluster/Worker.scala @@ -1,6 +1,7 @@ package io.scalajs.nodejs.cluster -import io.scalajs.nodejs.Process +import io.scalajs.nodejs.Handle +import io.scalajs.nodejs.child_process.ChildProcess import io.scalajs.nodejs.events.IEventEmitter import scala.scalajs.js @@ -22,13 +23,13 @@ trait Worker extends IEventEmitter { * The boolean worker.exitedAfterDisconnect lets you distinguish between voluntary and accidental exit, the master * may choose not to respawn a worker based on this value. */ - def exitedAfterDisconnect: Boolean = js.native + def exitedAfterDisconnect: js.UndefOr[Boolean] = js.native /** * Each new worker is given its own unique id, this id is stored in the id. * While a worker is alive, this is the key that indexes it in cluster.workers */ - def id: Integer = js.native + def id: Int = js.native /** * All workers are created using child_process.fork(), the returned object from this function is stored as .process. @@ -37,7 +38,7 @@ trait Worker extends IEventEmitter { * Note that workers will call process.exit(0) if the 'disconnect' event occurs on process and .exitedAfterDisconnect * is not true. This protects against accidental disconnection. */ - def process: Process = js.native + def process: ChildProcess = js.native /** * An alias to worker.exitedAfterDisconnect. @@ -100,7 +101,7 @@ trait Worker extends IEventEmitter { * @param signal the name of the kill signal to send to the worker process. * @example kill([signal='SIGTERM']) */ - def kill(signal: String = null): Unit = js.native + def kill(signal: String = js.native): Unit = js.native /** * Send a message to a worker or master, optionally with a handle. @@ -108,22 +109,6 @@ trait Worker extends IEventEmitter { * In a worker this sends a message to the master. It is identical to process.send(). * @example worker.send(message[, sendHandle][, callback]) */ - def send(message: Message, sendHandle: js.Function, callback: js.Function): Unit = js.native - - /** - * Send a message to a worker or master, optionally with a handle. - * In the master this sends a message to a specific worker. It is identical to ChildProcess.send(). - * In a worker this sends a message to the master. It is identical to process.send(). - * @example worker.send(message[, sendHandle][, callback]) - */ - def send(message: Message, callback: js.Function): Unit = js.native - - /** - * Send a message to a worker or master, optionally with a handle. - * In the master this sends a message to a specific worker. It is identical to ChildProcess.send(). - * In a worker this sends a message to the master. It is identical to process.send(). - * @example worker.send(message[, sendHandle][, callback]) - */ - def send(message: Message): Unit = js.native + def send(message: Message, sendHandle: Handle = js.native, callback: js.Function = js.native): Unit = js.native } diff --git a/app/current/src/main/scala/io/scalajs/nodejs/cluster/package.scala b/app/current/src/main/scala/io/scalajs/nodejs/cluster/package.scala index 62f4efb5c..4cb7b91de 100644 --- a/app/current/src/main/scala/io/scalajs/nodejs/cluster/package.scala +++ b/app/current/src/main/scala/io/scalajs/nodejs/cluster/package.scala @@ -21,7 +21,7 @@ package object cluster { * Cluster Events * @param cluster the given [[Cluster cluster]] */ - implicit class ClusterEvents(val cluster: Cluster) extends AnyVal { + implicit final class ClusterEvents(private val cluster: Cluster) extends AnyVal { /** * Emitted after the worker IPC channel has disconnected. This can occur when a worker exits gracefully, is killed, @@ -32,7 +32,7 @@ package object cluster { * @param callback the event handler */ @inline - def onDisconnect(callback: Worker => Any): cluster.type = cluster.on("disconnect", callback) + def onDisconnect(callback: Worker => Any): Cluster = cluster.on("disconnect", callback) /** * Similar to the cluster.on('exit') event, but specific to this worker. @@ -44,7 +44,7 @@ package object cluster { * */ @inline - def onExit(callback: (Worker, Int, String) => Any): cluster.type = cluster.on("exit", callback) + def onExit(callback: (Worker, Int, String) => Any): Cluster = cluster.on("exit", callback) /** * When a new worker is forked the cluster module will emit a 'fork' event. This can be used to log worker activity, @@ -52,7 +52,7 @@ package object cluster { * @param callback the event handler */ @inline - def onFork(callback: Worker => Any): cluster.type = cluster.on("fork", callback) + def onFork(callback: Worker => Any): Cluster = cluster.on("fork", callback) /** * After calling listen() from a worker, when the 'listening' event is emitted on the server, a 'listening' event @@ -64,7 +64,7 @@ package object cluster { * @param callback the event handler */ @inline - def onListening(callback: (Worker, Address) => Any): cluster.type = cluster.on("listening", callback) + def onListening(callback: (Worker, Address) => Any): Cluster = cluster.on("listening", callback) /** * Emitted when any worker receives a message. @@ -75,7 +75,7 @@ package object cluster { * @param callback the event handler */ @inline - def onMessage(callback: (Worker, Message, js.Any) => Any): cluster.type = cluster.on("message", callback) + def onMessage(callback: (Worker, Message, js.Any) => Any): Cluster = cluster.on("message", callback) /** * After forking a new worker, the worker should respond with an online message. When the master receives an online @@ -84,7 +84,7 @@ package object cluster { * @param callback the event handler */ @inline - def onOnline(callback: Worker => Any): cluster.type = cluster.on("online", callback) + def onOnline(callback: Worker => Any): Cluster = cluster.on("online", callback) /** * Emitted every time .setupMaster() is called. @@ -95,7 +95,7 @@ package object cluster { * @param callback the event handler */ @inline - def onSetup(callback: ClusterSettings => Any): cluster.type = cluster.on("setup", callback) + def onSetup(callback: ClusterSettings => Any): Cluster = cluster.on("setup", callback) } @@ -107,7 +107,7 @@ package object cluster { * Worker Events and Extensions * @param worker the given [[Worker worker]] */ - implicit class WorkerEvents(val worker: Worker) extends AnyVal { + implicit final class WorkerEvents(private val worker: Worker) extends AnyVal { ///////////////////////////////////////////////////////////////////////////////// // Worker Extensions @@ -131,7 +131,7 @@ package object cluster { * @param callback the event handler */ @inline - def onDisconnect(callback: () => Any): worker.type = worker.on("disconnect", callback) + def onDisconnect(callback: () => Any): Worker = worker.on("disconnect", callback) /** * This event is the same as the one provided by child_process.fork(). @@ -139,7 +139,7 @@ package object cluster { * @param callback the error handler */ @inline - def onError(callback: nodejs.Error => Any): worker.type = worker.on("error", callback) + def onError(callback: nodejs.Error => Any): Worker = worker.on("error", callback) /** * Similar to the cluster.on('exit') event, but specific to this worker. @@ -151,14 +151,14 @@ package object cluster { * */ @inline - def onExit(callback: (Worker, Int, String) => Any): worker.type = worker.on("exit", callback) + def onExit(callback: (Worker, Int, String) => Any): Worker = worker.on("exit", callback) /** * Similar to the cluster.on('listening') event, but specific to this worker. * @param callback the event handler */ @inline - def onListening(callback: Address => Any): worker.type = worker.on("listening", callback) + def onListening(callback: Address => Any): Worker = worker.on("listening", callback) /** * Similar to the cluster.on('message') event, but specific to this worker. @@ -167,14 +167,14 @@ package object cluster { * @param callback the event handler */ @inline - def onMessage(callback: Message => Any): worker.type = worker.on("message", callback) + def onMessage(callback: Message => Any): Worker = worker.on("message", callback) /** * Similar to the cluster.on('online') event, but specific to this worker. * @param callback the event handler */ @inline - def onOnline(callback: () => Any): worker.type = worker.on("online", callback) + def onOnline(callback: () => Any): Worker = worker.on("online", callback) } diff --git a/app/current/src/main/scala/io/scalajs/nodejs/net/Socket.scala b/app/current/src/main/scala/io/scalajs/nodejs/net/Socket.scala index f25192e29..a4e20bfb0 100644 --- a/app/current/src/main/scala/io/scalajs/nodejs/net/Socket.scala +++ b/app/current/src/main/scala/io/scalajs/nodejs/net/Socket.scala @@ -15,7 +15,7 @@ import scala.scalajs.js.| */ @js.native @JSImport("net", "Socket") -class Socket(options: SocketOptions | RawOptions = js.native) extends IDuplex { +class Socket(options: SocketOptions | RawOptions = js.native) extends IDuplex with HasHandle { ///////////////////////////////////////////////////////////////////////////////// // Properties @@ -218,6 +218,8 @@ class Socket(options: SocketOptions | RawOptions = js.native) extends IDuplex { */ def unref(): this.type = js.native + // TODO: test me + override def _handle: js.Any = js.native } /** diff --git a/app/current/src/main/scala/io/scalajs/nodejs/package.scala b/app/current/src/main/scala/io/scalajs/nodejs/package.scala index 2957ddadc..9ebe502d5 100644 --- a/app/current/src/main/scala/io/scalajs/nodejs/package.scala +++ b/app/current/src/main/scala/io/scalajs/nodejs/package.scala @@ -45,6 +45,9 @@ package object nodejs { type UID = Int + // The handle object can be either a server, a socket (anything with an underlying _handle member), or an object with an fd member that is a valid file descriptor. + type Handle = js.Function | HasHandle | HasFileDescriptor + ///////////////////////////////////////////////////////////////////////////////// // Built-in Properties ///////////////////////////////////////////////////////////////////////////////// diff --git a/core/src/main/scala/io/scalajs/util/ScalaJsHelper.scala b/core/src/main/scala/io/scalajs/util/ScalaJsHelper.scala index 8c843a217..a49b4e5b2 100644 --- a/core/src/main/scala/io/scalajs/util/ScalaJsHelper.scala +++ b/core/src/main/scala/io/scalajs/util/ScalaJsHelper.scala @@ -22,9 +22,6 @@ object ScalaJsHelper { @inline def isDefined(obj: js.Any): Boolean = obj != null && !js.isUndefined(obj) - @inline - def New[T <: js.Any]: T = new js.Object().asInstanceOf[T] - //////////////////////////////////////////////////////////////////////// // Implicit Definitions and Classes ////////////////////////////////////////////////////////////////////////