Skip to content
This repository was archived by the owner on Jul 30, 2024. It is now read-only.

Overhaul global module and top level objects #91

Merged
merged 1 commit into from
Oct 2, 2019
Merged
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
64 changes: 14 additions & 50 deletions app/current/src/main/scala/io/scalajs/nodejs/Global.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.scalajs.nodejs

import io.scalajs.nodejs.timers.{SetInterval, SetTimeout, UnRef, _}
import io.scalajs.nodejs.timers._

import scala.scalajs.js

Expand All @@ -10,78 +10,42 @@ import scala.scalajs.js
* var something inside an Node.js module will be local to that module.
*/
@js.native
@deprecated("Use io.scalajs.nodejs package object", "0.9.0")
trait Global extends js.Object {

/////////////////////////////////////////////////////////////////////////////////
// Global Classes
/////////////////////////////////////////////////////////////////////////////////

def DTRACE_NET_SERVER_CONNECTION: js.Function = js.native

def DTRACE_NET_STREAM_END: js.Function = js.native

def DTRACE_HTTP_SERVER_REQUEST: js.Function = js.native

def DTRACE_HTTP_SERVER_RESPONSE: js.Function = js.native

def DTRACE_HTTP_CLIENT_REQUEST: js.Function = js.native

def DTRACE_HTTP_CLIENT_RESPONSE: js.Function = js.native

/////////////////////////////////////////////////////////////////////////////////
// Global Constants
/////////////////////////////////////////////////////////////////////////////////

/**
* The name of the directory that the currently executing script resides in.
*/
def __dirname: String = js.native

/**
* The filename of the code being executed. This is the resolved absolute path of this code file. For a main program
* this is not necessarily the same filename used in the command line. The value inside a module is the path to that
* module file.
*/
def __filename: String = js.native

/**
* A reference to the module.exports that is shorter to type. See module system documentation for details on when
* to use exports and when to use module.exports.
*
* exports isn't actually a global but rather local to each module.
*/
val exports: js.Object = js.native
@deprecated("Use io.scalajs.nodejs.exports", "0.9.0")
def exports: js.UndefOr[js.Object] = js.native

/**
* A reference to the current module. In particular module.exports is used for defining what a module exports and
* makes available through require().
*
* module isn't actually a global but rather local to each module.
*/
val module: Module = js.native

/////////////////////////////////////////////////////////////////////////////////
// Global Objects
/////////////////////////////////////////////////////////////////////////////////
@deprecated("Use io.scalajs.nodejs.module", "0.9.0")
def module: Module = js.native

@deprecated("Use io.scalajs.nodejs.clearImmediate", "0.9.0")
def clearImmediate: ClearImmediate = js.native

@deprecated("Use io.scalajs.nodejs.clearInterval", "0.9.0")
def clearInterval: ClearInterval = js.native

@deprecated("Use io.scalajs.nodejs.clearTimeout", "0.9.0")
def clearTimeout: ClearTimeout = js.native

@deprecated("Use io.scalajs.nodejs.console", "0.9.0")
def console: console_module.Console = js.native

@deprecated("Use io.scalajs.nodejs.process", "0.9.0")
def process: io.scalajs.nodejs.process.Process = js.native

def ref: Ref = js.native

@deprecated("Use io.scalajs.nodejs.setImmediate", "0.9.0")
def setImmediate: SetImmediate = js.native

@deprecated("Use io.scalajs.nodejs.setInterval", "0.9.0")
def setInterval: SetInterval = js.native

@deprecated("Use io.scalajs.nodejs.setTimeout", "0.9.0")
def setTimeout: SetTimeout = js.native

def unref: UnRef = js.native

}
22 changes: 16 additions & 6 deletions app/current/src/main/scala/io/scalajs/nodejs/Module.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package io.scalajs.nodejs

import com.thoughtworks.enableIf

import scala.scalajs.js
import scala.scalajs.js.annotation.JSGlobal
import scala.scalajs.js.annotation.JSImport

/**
* In each module, the module free variable is a reference to the object representing the current module.
Expand Down Expand Up @@ -51,23 +53,31 @@ trait Module extends js.Object {
*/
var parent: js.Any = js.native

var paths: js.Array[String] = js.native

/**
* The module.require method provides a way to load a module as if require() was called from the original module.
* <p/><b>Note</b> that in order to do this, you must get a reference to the module object. Since require() returns the
* module.exports, and the module is typically only available within a specific module's code, it must be
* explicitly exported in order to be used.
*/
def require[T](id: String): T = js.native
def require[T <: js.Any](id: String): T = js.native

}

/**
* Module Companion
*/
object Module {
@js.native
@JSImport("module", JSImport.Namespace)
object Module extends Module {

@enableIf(io.scalajs.nodejs.CompilerSwitches.gteNodeJs10)
var builtinModules: js.Array[String] = js.native

@js.native
@JSGlobal("module")
implicit object module extends Module
@enableIf(io.scalajs.nodejs.CompilerSwitches.gteNodeJs12)
def createRequire(filename: String): Require = js.native

@enableIf(io.scalajs.nodejs.CompilerSwitches.gteNodeJs12)
def createRequire(filename: io.scalajs.nodejs.url.URL): Require = js.native
}
28 changes: 28 additions & 0 deletions app/current/src/main/scala/io/scalajs/nodejs/Require.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.scalajs.nodejs

import scala.scalajs.js
import scala.scalajs.js.annotation.JSGlobal

@js.native
sealed trait Require extends js.Object {
def apply(id: String): js.Any = js.native

val cache: js.Dictionary[js.Any] = js.native
val main: js.UndefOr[Module] = js.native
val resolve: RequireResolver = js.native
}

@js.native
@JSGlobal("require")
object Require extends Require

@js.native
trait RequireResolver extends js.Object {
def apply(request: String, options: ResolveOptions = js.native): js.Any = js.native

def paths(requiest: String): js.Array[String] = js.native
}

class ResolveOptions(
var paths: js.UndefOr[js.Array[String]] = js.undefined
) extends js.Object
4 changes: 4 additions & 0 deletions app/current/src/main/scala/io/scalajs/nodejs/fs/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ package object fs {
type Output = String | Buffer
type FileWriteOptions = FileAppendOptions

type ReaddirArrays = js.Array[String] | js.Array[Buffer]
@enableIf(io.scalajs.nodejs.CompilerSwitches.gteNodeJs10)
type ReaddirArrays2 = ReaddirArrays | js.Array[fs.Dirent]

@enableIf(io.scalajs.nodejs.CompilerSwitches.gteNodeJs10)
type Dirent = Fs.Dirent

Expand Down
99 changes: 13 additions & 86 deletions app/current/src/main/scala/io/scalajs/nodejs/package.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.scalajs

import com.thoughtworks.enableIf
import io.scalajs.nodejs.buffer.Buffer
import io.scalajs.nodejs.timers._

import scala.concurrent.duration.FiniteDuration
Expand Down Expand Up @@ -54,10 +53,6 @@ package object nodejs {
// 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

type ReaddirArrays = js.Array[String] | js.Array[Buffer]
@enableIf(io.scalajs.nodejs.CompilerSwitches.gteNodeJs10)
type ReaddirArrays2 = ReaddirArrays | js.Array[fs.Dirent]

/////////////////////////////////////////////////////////////////////////////////
// Built-in Properties
/////////////////////////////////////////////////////////////////////////////////
Expand All @@ -82,15 +77,18 @@ package object nodejs {
*/
def __filename: String = js.Dynamic.global.__filename.asInstanceOf[String]

/**
* In browsers, the top-level scope is the global scope. That means that in browsers if you're in the global scope
* var something will define a global variable. In Node.js this is different. The top-level scope is not the global
* scope; var something inside a Node.js module will be local to that module.
*/
@js.native
@JSGlobal("global")
@deprecated("Use objects in io.scalajs.nodejs", "0.9.0")
object global extends Global

@js.native
@enableIf(io.scalajs.nodejs.CompilerSwitches.gteNodeJs12)
@JSGlobal("queueMicrotask")
object queueMicrotask extends js.Function1[js.Function, Unit] {
override def apply(arg1: js.Function): Unit = js.native
}

/////////////////////////////////////////////////////////////////////////////////
// Timers
/////////////////////////////////////////////////////////////////////////////////
Expand All @@ -107,10 +105,6 @@ package object nodejs {
@JSGlobal("clearTimeout")
object clearTimeout extends ClearTimeout

@js.native
@JSGlobal("ref")
object ref extends Ref

@js.native
@JSGlobal("setImmediate")
object setImmediate extends SetImmediate
Expand All @@ -123,10 +117,6 @@ package object nodejs {
@JSGlobal("setTimeout")
object setTimeout extends SetTimeout

@js.native
@JSGlobal("unref")
object unref extends UnRef

/////////////////////////////////////////////////////////////////////////////////
// Implicit Conversions
/////////////////////////////////////////////////////////////////////////////////
Expand All @@ -136,86 +126,23 @@ package object nodejs {
* @param duration the given [[FiniteDuration duration]]
* @return the time in milliseconds as an integer
*/
@deprecated("Use io.scalajs.util.DurationHelper", "0.9.0")
implicit def duration2Int(duration: FiniteDuration): Int = duration.toMillis.toInt

/**
* Implicit conversion to translate durations into a double
* @param duration the given [[FiniteDuration duration]]
* @return the time in milliseconds as a double
*/
@deprecated("Use io.scalajs.util.DurationHelper", "0.9.0")
implicit def duration2Double(duration: FiniteDuration): Double = duration.toMillis.toDouble

/**
* Implicit conversion to transform Node [[Error]]s to [[Exception]]s
* @param error the given [[Error]]
* @return the resulting [[Exception]]
*/
implicit def error2Exception(error: Error): Exception = js.JavaScriptException(error.message)

/////////////////////////////////////////////////////////////////////////////////
// Exit Codes - Node.js will normally exit with a 0 status code when no more
// async operations are pending. The following status codes are
// used in other cases:
/////////////////////////////////////////////////////////////////////////////////

type ExitCode = Int

/**
* There was an uncaught exception, and it was not handled by a domain or an 'uncaughtException' event handler.
*/
val UncaughtFatalException: ExitCode = 1

/**
* The JavaScript source code internal in Node.js's bootstrapping process caused a parse error. This is extremely
* rare, and generally can only happen during development of Node.js itself.
*/
val InternalJavaScriptParseError: ExitCode = 3

/**
* The JavaScript source code internal in Node.js's bootstrapping process failed to return a function value when
* evaluated. This is extremely rare, and generally can only happen during development of Node.js itself.
*/
val InternalJavaScriptEvaluationFailure: ExitCode = 4

/**
* There was a fatal unrecoverable error in V8. Typically a message will be printed to stderr with the prefix FATAL ERROR.
*/
val FatalError: ExitCode = 5

/**
* There was an uncaught exception, but the internal fatal exception handler function was somehow set to a non-function,
* and could not be called.
*/
val NonFunctionInternalExceptionHandler: ExitCode = 6

/**
* There was an uncaught exception, and the internal fatal exception handler function itself threw an error while
* attempting to handle it. This can happen, for example, if a 'uncaughtException' or domain.on('error') handler
* throws an error.
*/
val InternalExceptionHandlerRunTimeFailure: ExitCode = 7

/**
* Either an unknown option was specified, or an option requiring a value was provided without a value.
*/
val InvalidArgument: ExitCode = 8

/**
* The JavaScript source code internal in Node.js's bootstrapping process threw an error when the bootstrapping
* function was called. This is extremely rare, and generally can only happen during development of Node.js itself.
*/
val InternalJavaScriptRunTimeFailure: ExitCode = 10

/**
* The --debug and/or --debug-brk options were set, but an invalid port number was chosen.
*/
val InvalidDebugArgument: ExitCode = 12

/**
* If Node.js receives a fatal signal such as SIGKILL or SIGHUP, then its exit code will be 128 plus the value of
* the signal code. This is a standard Unix practice, since exit codes are defined to be 7-bit integers, and signal
* exits set the high-order bit, and then contain the value of the signal code.
*/
val SignalExits: ExitCode = 128

@deprecated("Use toException extension method from io.scalajs.util.NodeJSConverters._", "0.9.0")
implicit def error2Exception(error: Error): Exception =
io.scalajs.util.NodeJSConverters.ErrorExtension(error).toException()
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ package object process {
type Environment = js.Dictionary[String]
// TODO: js.Set
type EnvironmentFlags = js.Any

type SendHandle = net.Socket | net.Server
type ExitCode = Int
type SendHandle = net.Socket | net.Server

@deprecated("use Process object instead", "0.9.0")
def allowedNodeEnvironmentFlags: EnvironmentFlags = Process.allowedNodeEnvironmentFlags
Expand Down
12 changes: 12 additions & 0 deletions app/current/src/main/scala/io/scalajs/util/NodeJSConverters.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.scalajs.util

import io.scalajs.nodejs.Error

import scala.scalajs.js

object NodeJSConverters {
implicit final class ErrorExtension(val error: Error) extends AnyVal {
@inline
def toException(): Exception = js.JavaScriptException(error.message)
}
}
14 changes: 14 additions & 0 deletions app/current/src/test/scala/io/scalajs/nodejs/TopLevelTest.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.scalajs.nodejs

import org.scalatest.FunSuite

import scala.scalajs.js

class TopLevelTest extends FunSuite {

test("queueMicrotask") {
assert(queueMicrotask.isInstanceOf[js.Function])
queueMicrotask(() => println("printed from queueMicrotask"))
}

}
Loading