mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-23 07:45:23 +00:00
Support code hot reloading for JavaScript projects (#7362)
* Support code hot reloading for JavaScript projects * Add some missing JavaScript symbols and APIs * fix the Travis build * (review changes) remove the js type from the standard library as it doesn't follow NEP-1 * more additions to the DOM module * Follow NEP-1 in jsffi; spell 'hot code reloading' correctly * introduce a jscore module * Document jscore module. * readded js type * Remove the '$' operator that doesn't behave
This commit is contained in:
91
lib/js/jscore.nim
Normal file
91
lib/js/jscore.nim
Normal file
@@ -0,0 +1,91 @@
|
||||
## This module wraps core JavaScript functions.
|
||||
##
|
||||
## Unless your application has very
|
||||
## specific requirements and solely targets JavaScript, you should be using
|
||||
## the relevant functions in the ``math``, ``json``, and ``times`` stdlib
|
||||
## modules instead.
|
||||
|
||||
when not defined(js) and not defined(Nimdoc):
|
||||
{.error: "This module only works on the JavaScript platform".}
|
||||
|
||||
type
|
||||
MathLib* = ref object
|
||||
JsonLib* = ref object
|
||||
DateLib* = ref object
|
||||
DateTime* = ref object
|
||||
|
||||
var
|
||||
Math* {.importc, nodecl.}: MathLib
|
||||
Date* {.importc, nodecl.}: DateLib
|
||||
JSON* {.importc, nodecl.}: JsonLib
|
||||
|
||||
{.push importcpp.}
|
||||
|
||||
# Math library
|
||||
proc abs*(m: MathLib, a: SomeNumber): SomeNumber
|
||||
proc acos*(m: MathLib, a: SomeNumber): float
|
||||
proc acosh*(m: MathLib, a: SomeNumber): float
|
||||
proc asin*(m: MathLib, a: SomeNumber): float
|
||||
proc asinh*(m: MathLib, a: SomeNumber): float
|
||||
proc atan*(m: MathLib, a: SomeNumber): float
|
||||
proc atan2*(m: MathLib, a: SomeNumber): float
|
||||
proc atanh*(m: MathLib, a: SomeNumber): float
|
||||
proc cbrt*(m: MathLib, f: SomeReal): SomeReal
|
||||
proc ceil*(m: MathLib, f: SomeReal): SomeReal
|
||||
proc clz32*(m: MathLib, f: SomeInteger): int
|
||||
proc cos*(m: MathLib, a: SomeNumber): float
|
||||
proc cosh*(m: MathLib, a: SomeNumber): float
|
||||
proc exp*(m: MathLib, a: SomeNumber): float
|
||||
proc expm1*(m: MathLib, a: SomeNumber): float
|
||||
proc floor*(m: MathLib, f: SomeReal): int
|
||||
proc fround*(m: MathLib, f: SomeReal): float32
|
||||
proc hypot*(m: MathLib, args: varargs[distinct SomeNumber]): float
|
||||
proc imul*(m: MathLib, a, b: int32): int32
|
||||
proc log*(m: MathLib, a: SomeNumber): float
|
||||
proc log10*(m: MathLib, a: SomeNumber): float
|
||||
proc log1p*(m: MathLib, a: SomeNumber): float
|
||||
proc log2*(m: MathLib, a: SomeNumber): float
|
||||
proc max*(m: MathLib, a, b: SomeNumber): SomeNumber
|
||||
proc min*[T: SomeNumber | JsRoot](m: MathLib, a, b: T): T
|
||||
proc pow*(m: MathLib, a, b: distinct SomeNumber): float
|
||||
proc random*(m: MathLib): float
|
||||
proc round*(m: MathLib, f: SomeReal): int
|
||||
proc sign*(m: MathLib, f: SomeNumber): int
|
||||
proc sin*(m: MathLib, a: SomeNumber): float
|
||||
proc sinh*(m: MathLib, a: SomeNumber): float
|
||||
proc sqrt*(m: MathLib, f: SomeReal): SomeReal
|
||||
proc tan*(m: MathLib, a: SomeNumber): float
|
||||
proc tanh*(m: MathLib, a: SomeNumber): float
|
||||
proc trunc*(m: MathLib, f: SomeReal): int
|
||||
|
||||
# Date library
|
||||
proc now*(d: DateLib): int
|
||||
proc UTC*(d: DateLib): int
|
||||
proc parse*(d: DateLib, s: cstring): int
|
||||
|
||||
proc newDate*(): DateTime {.
|
||||
importcpp: "new Date()".}
|
||||
|
||||
proc newDate*(date: int|string): DateTime {.
|
||||
importcpp: "new Date(#)".}
|
||||
|
||||
proc newDate*(year, month, day, hours, minutes,
|
||||
seconds, milliseconds: int): DateTime {.
|
||||
importcpp: "new Date(#,#,#,#,#,#,#)".}
|
||||
|
||||
proc getDay*(d: DateTime): int
|
||||
proc getFullYear*(d: DateTime): int
|
||||
proc getHours*(d: DateTime): int
|
||||
proc getMilliseconds*(d: DateTime): int
|
||||
proc getMinutes*(d: DateTime): int
|
||||
proc getMonth*(d: DateTime): int
|
||||
proc getSeconds*(d: DateTime): int
|
||||
proc getYear*(d: DateTime): int
|
||||
proc getTime*(d: DateTime): int
|
||||
proc toString*(d: DateTime): cstring
|
||||
|
||||
#JSON library
|
||||
proc stringify*(l: JsonLib, s: JsRoot): cstring
|
||||
proc parse*(l: JsonLib, s: cstring): JsRoot
|
||||
|
||||
{.pop.}
|
||||
@@ -70,22 +70,31 @@ template mangleJsName(name: cstring): cstring =
|
||||
"mangledName" & $nameCounter
|
||||
|
||||
type
|
||||
JsRoot* = ref object of RootObj
|
||||
## Root type of both JsObject and JsAssoc
|
||||
JsObject* = ref object of JsRoot
|
||||
## Dynamically typed wrapper around a JavaScript object.
|
||||
JsAssoc*[K, V] = ref object of JsRoot
|
||||
## Statically typed wrapper around a JavaScript object.
|
||||
|
||||
NotString = concept c
|
||||
c isnot string
|
||||
js* = JsObject
|
||||
|
||||
var jsarguments* {.importc: "arguments", nodecl}: JsObject
|
||||
## JavaScript's arguments pseudo-variable
|
||||
var
|
||||
jsArguments* {.importc: "arguments", nodecl}: JsObject
|
||||
## JavaScript's arguments pseudo-variable
|
||||
jsNull* {.importc: "null", nodecl.}: JsObject
|
||||
## JavaScript's null literal
|
||||
jsUndefined* {.importc: "undefined", nodecl.}: JsObject
|
||||
## JavaScript's undefined literal
|
||||
jsDirname* {.importc: "__dirname", nodecl.}: cstring
|
||||
## JavaScript's __dirname pseudo-variable
|
||||
jsFilename* {.importc: "__filename", nodecl.}: cstring
|
||||
## JavaScript's __filename pseudo-variable
|
||||
|
||||
# New
|
||||
proc newJsObject*: JsObject {. importcpp: "{@}" .}
|
||||
## Creates a new empty JsObject
|
||||
|
||||
proc newJsAssoc*[K, V]: JsAssoc[K, V] {. importcpp: "{@}" .}
|
||||
## Creates a new empty JsAssoc with key type `K` and value type `V`.
|
||||
|
||||
@@ -97,13 +106,16 @@ proc hasOwnProperty*(x: JsObject, prop: cstring): bool
|
||||
proc jsTypeOf*(x: JsObject): cstring {. importcpp: "typeof(#)" .}
|
||||
## Returns the name of the JsObject's JavaScript type as a cstring.
|
||||
|
||||
proc jsnew*(x: auto): JsObject {.importcpp: "(new #)".}
|
||||
proc jsNew*(x: auto): JsObject {.importcpp: "(new #)".}
|
||||
## Turns a regular function call into an invocation of the
|
||||
## JavaScript's `new` operator
|
||||
|
||||
proc jsdelete*(x: auto): JsObject {.importcpp: "(delete #)".}
|
||||
proc jsDelete*(x: auto): JsObject {.importcpp: "(delete #)".}
|
||||
## JavaScript's `delete` operator
|
||||
|
||||
proc require*(module: cstring): JsObject {.importc.}
|
||||
## JavaScript's `require` function
|
||||
|
||||
# Conversion to and from JsObject
|
||||
proc to*(x: JsObject, T: typedesc): T {. importcpp: "(#)" .}
|
||||
## Converts a JsObject `x` to type `T`.
|
||||
|
||||
@@ -649,6 +649,11 @@ when defined(nimNewRuntime):
|
||||
ESynch: Exception
|
||||
].}
|
||||
|
||||
when defined(js) or defined(nimdoc):
|
||||
type
|
||||
JsRoot* = ref object of RootObj
|
||||
## Root type of the JavaScript object hierarchy
|
||||
|
||||
proc unsafeNew*[T](a: var ref T, size: Natural) {.magic: "New", noSideEffect.}
|
||||
## creates a new object of type ``T`` and returns a safe (traced)
|
||||
## reference to it in ``a``. This is **unsafe** as it allocates an object
|
||||
@@ -4080,6 +4085,25 @@ template closureScope*(body: untyped): untyped =
|
||||
## myClosure() # outputs 3
|
||||
(proc() = body)()
|
||||
|
||||
template once*(body: untyped): untyped =
|
||||
## Executes a block of code only once (the first time the block is reached).
|
||||
## When hot code reloading is enabled, protects top-level code from being
|
||||
## re-executed on each module reload.
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## proc draw(t: Triangle) =
|
||||
## once:
|
||||
## graphicsInit()
|
||||
##
|
||||
## line(t.p1, t.p2)
|
||||
## line(t.p2, t.p3)
|
||||
## line(t.p3, t.p1)
|
||||
##
|
||||
var alreadyExecuted {.global.} = false
|
||||
if not alreadyExecuted:
|
||||
alreadyExecuted = true
|
||||
body
|
||||
|
||||
{.pop.} #{.push warning[GcMem]: off, warning[Uninit]: off.}
|
||||
|
||||
when defined(nimconfig):
|
||||
|
||||
Reference in New Issue
Block a user