From db500e1d6d18a192358a432dc571844e0618923c Mon Sep 17 00:00:00 2001 From: bung87 Date: Tue, 20 Jul 2021 21:08:12 +0800 Subject: [PATCH 01/12] re-active --- .gitignore | 39 +++++++++++++++++++++++++++++---------- napibindings.nimble | 6 ++++++ src/napibindings.nim | 2 +- src/napibuild.nim | 5 ++++- test/config.nims | 1 + test/index.js | 10 +++++----- test/main.nim | 2 +- test/package.json | 3 +-- 8 files changed, 48 insertions(+), 20 deletions(-) create mode 100644 test/config.nims diff --git a/.gitignore b/.gitignore index 586e35c..4aec24e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,29 @@ -*~ -*.swp -*.swo -bin/napibuild -**/nimcache/ -**/build/ -**/node_modules/ -**/package-lock.json -**/binding.gyp - +* +!**/ +!*.* +test/build +binding.gyp +yarn.lock +node_modules +# Cache +nimcache/ +rnimcache/ +dnimcache/ +nimbledeps/ +*.o +!/icons/*.o +*.obj +*.ilk +*.exp +*.pdb +*.lib +*.dll +*.exe +*.so +*.dylib +*.zip +*.iss +*.log +*.pdb +.DS_Store +*.out \ No newline at end of file diff --git a/napibindings.nimble b/napibindings.nimble index ed944f0..c26f8bd 100644 --- a/napibindings.nimble +++ b/napibindings.nimble @@ -7,3 +7,9 @@ skipDirs = @["test", ".git"] bin = @["napibuild"] requires "https://github.com/docopt/docopt.nim#master" + +task test,"test": +# withDir "test": +# exec "yarn install " + exec "nim c -r src/napibuild.nim test/main.nim" + exec "node test/index.js" \ No newline at end of file diff --git a/src/napibindings.nim b/src/napibindings.nim index 83828a3..880ea06 100644 --- a/src/napibindings.nim +++ b/src/napibindings.nim @@ -334,7 +334,7 @@ proc callFunction*(fn: napi_value, args: openarray[napi_value] = [], this = %emp proc napi_call_function(env: napi_env, recv, fn: napi_value, argc: cint, argv, res: ptr napi_value): int {.header:"".} assessStatus napi_call_function(`env$`, this, fn, cint args.len, cast[ptr napi_value](args.toUnchecked()), addr result) -macro getIdentStr*(n: untyped): string = $ident(n) +macro getIdentStr*(n: untyped) = n template fn*(paramCt: int, name, cushy: untyped): untyped {.dirty.} = diff --git a/src/napibuild.nim b/src/napibuild.nim index 93629df..b70a889 100644 --- a/src/napibuild.nim +++ b/src/napibuild.nim @@ -1,5 +1,8 @@ import json, docopt, os, sequtils +const explicitSourcePath {.strdefine.} = os.parentDir(os.parentDir( os.getCurrentCompilerExe())) + +echo explicitSourcePath const doc = """ NodeBuild. @@ -15,7 +18,7 @@ let args = docopt(doc) var projectfile = $args[""] project = splitFile(projectfile) - nimbase = (findExe("nim") /../ "" /../ "lib") + nimbase = %* (explicitSourcePath / "lib" ) nimcache = project.dir / "nimcache"#$args[""] target = %* { "target_name": project.name } gyp = %* { "targets": [target] } diff --git a/test/config.nims b/test/config.nims new file mode 100644 index 0000000..e36139c --- /dev/null +++ b/test/config.nims @@ -0,0 +1 @@ +--path:"../src" \ No newline at end of file diff --git a/test/index.js b/test/index.js index a6a8e6e..afcc332 100644 --- a/test/index.js +++ b/test/index.js @@ -1,9 +1,9 @@ const assert = require('assert') const addon = require('bindings')('main') -assert.equal(addon.hello, "hello world"); -assert.equal(addon.addNums(3, 3, 3), 9); -assert.deepEqual(addon.createArray('jim', 'bob', 3), ['jim', 'bob', 3]) +assert.strictEqual(addon.hello, "hello world"); +assert.strictEqual(addon.addNums(3, 3, 3), 9); +assert.deepStrictEqual(addon.createArray('jim', 'bob', 3), ['jim', 'bob', 3]) -assert.equal(addon.getOrDefault([1, 2, 3], 0/*index*/, 'unexpected'/*default*/), 1) -assert.equal(addon.getOrDefault([1, 2, 3], 5/*index*/, 'expected'/*default*/), 'expected') +assert.strictEqual(addon.getOrDefault([1, 2, 3], 0/*index*/, 'unexpected'/*default*/), 1) +assert.strictEqual(addon.getOrDefault([1, 2, 3], 5/*index*/, 'expected'/*default*/), 'expected') diff --git a/test/main.nim b/test/main.nim index 97bbc21..dcb3bf1 100644 --- a/test/main.nim +++ b/test/main.nim @@ -1,4 +1,4 @@ -import ../napibindings, sequtils +import napibindings, sequtils init proc(exports: Module) = exports.register("hello", "hello world") diff --git a/test/package.json b/test/package.json index bf29200..09f5c31 100644 --- a/test/package.json +++ b/test/package.json @@ -10,6 +10,5 @@ "license": "ISC", "dependencies": { "bindings": "^1.3.0" - }, - "gypfile": true + } } From 83547b2899e3a355134cfc000c5a1b6a44a9cdc7 Mon Sep 17 00:00:00 2001 From: bung87 Date: Tue, 20 Jul 2021 21:15:50 +0800 Subject: [PATCH 02/12] o --- napibindings.nimble | 4 ++-- test/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/napibindings.nimble b/napibindings.nimble index c26f8bd..3c6a36a 100644 --- a/napibindings.nimble +++ b/napibindings.nimble @@ -9,7 +9,7 @@ bin = @["napibuild"] requires "https://github.com/docopt/docopt.nim#master" task test,"test": -# withDir "test": -# exec "yarn install " + withDir "test": + exec "yarn install --ignore-scripts" exec "nim c -r src/napibuild.nim test/main.nim" exec "node test/index.js" \ No newline at end of file diff --git a/test/package.json b/test/package.json index 09f5c31..0edfd29 100644 --- a/test/package.json +++ b/test/package.json @@ -9,6 +9,6 @@ "author": "", "license": "ISC", "dependencies": { - "bindings": "^1.3.0" + "bindings": "^1.5.0" } } From 1184d806c0dcfd009c7b61689cd9504587ac6101 Mon Sep 17 00:00:00 2001 From: bung87 Date: Tue, 20 Jul 2021 21:21:06 +0800 Subject: [PATCH 03/12] o --- napibindings.nimble | 2 +- src/napibuild.nim | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/napibindings.nimble b/napibindings.nimble index 3c6a36a..ba86bbe 100644 --- a/napibindings.nimble +++ b/napibindings.nimble @@ -6,7 +6,7 @@ srcDir = "src" skipDirs = @["test", ".git"] bin = @["napibuild"] -requires "https://github.com/docopt/docopt.nim#master" +requires "docopt" task test,"test": withDir "test": diff --git a/src/napibuild.nim b/src/napibuild.nim index b70a889..7c330d7 100644 --- a/src/napibuild.nim +++ b/src/napibuild.nim @@ -2,12 +2,10 @@ import json, docopt, os, sequtils const explicitSourcePath {.strdefine.} = os.parentDir(os.parentDir( os.getCurrentCompilerExe())) -echo explicitSourcePath - const doc = """ NodeBuild. Usage: - nodebuild [options] + napibuild [options] Options: -C do not recompile projectfile From 8e98fecc2a5158105cde81bf329fc732bb35a638 Mon Sep 17 00:00:00 2001 From: bung87 Date: Wed, 21 Jul 2021 10:24:34 +0800 Subject: [PATCH 04/12] clean --- src/napibindings.nim | 4 +--- src/napibuild.nim | 23 +++++++++-------------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/src/napibindings.nim b/src/napibindings.nim index 880ea06..9dd7881 100644 --- a/src/napibindings.nim +++ b/src/napibindings.nim @@ -334,8 +334,6 @@ proc callFunction*(fn: napi_value, args: openarray[napi_value] = [], this = %emp proc napi_call_function(env: napi_env, recv, fn: napi_value, argc: cint, argv, res: ptr napi_value): int {.header:"".} assessStatus napi_call_function(`env$`, this, fn, cint args.len, cast[ptr napi_value](args.toUnchecked()), addr result) -macro getIdentStr*(n: untyped) = n - template fn*(paramCt: int, name, cushy: untyped): untyped {.dirty.} = var name {.inject.}: napi_value @@ -354,7 +352,7 @@ template fn*(paramCt: int, name, cushy: untyped): untyped {.dirty.} = dealloc(`argv$`) cushy - name = createFn(`env$`, getIdentStr(name), `wrapper$`) + name = createFn(`env$`, name, `wrapper$`) template registerFn*(exports: Module, paramCt: int, name: string, cushy: untyped): untyped {.dirty.}= diff --git a/src/napibuild.nim b/src/napibuild.nim index 7c330d7..3c6606c 100644 --- a/src/napibuild.nim +++ b/src/napibuild.nim @@ -1,7 +1,7 @@ -import json, docopt, os, sequtils - -const explicitSourcePath {.strdefine.} = os.parentDir(os.parentDir( os.getCurrentCompilerExe())) +import json, docopt, os, osproc +const ExplicitSourcePath {.strdefine.} = os.parentDir(os.parentDir( os.getCurrentCompilerExe())) +const LibPath = ExplicitSourcePath / "lib" const doc = """ NodeBuild. Usage: @@ -11,25 +11,22 @@ Options: -C do not recompile projectfile -r release build """ + let args = docopt(doc) var projectfile = $args[""] project = splitFile(projectfile) - nimbase = %* (explicitSourcePath / "lib" ) + nimbase = LibPath nimcache = project.dir / "nimcache"#$args[""] target = %* { "target_name": project.name } gyp = %* { "targets": [target] } -template assess(name: string, cmd: string) = - var status = execShellCmd(cmd) - doAssert status == 0, "exit with nonzero status: " & $status & " for command " & cmd - - if not args["-C"]: var releaseFlag = if args["-r"]: "-d:release " else: "--embedsrc " - assess "nim c", "nim c --nimcache:" & nimcache & " " & releaseFlag & "--compileOnly --noMain " & projectfile + let r = execCmdEx "nim c --nimcache:" & nimcache & " " & releaseFlag & "--compileOnly --noMain " & projectfile + doAssert r.exitCode == 0, r.output target["include_dirs"] = %[ nimbase ] @@ -39,9 +36,6 @@ if args["-r"]: target["cflags"].add(%"-fno-strict-aliasing") target["linkflags"] = %["-ldl"] - -var compiledpf = (projectfile).changeFileExt(".c") - target["sources"] = %[] for targetobj in parsejson(readfile(nimcache / (project.name & ".json")))["link"]: target["sources"].add(% ("nimcache" / targetobj.getstr.splitFile.name)) @@ -53,4 +47,5 @@ writeFile(project.dir / "binding.gyp", gyp.pretty) var gypflags = "--directory=" & project.dir if not args["-r"]: gypflags.add(" --debug") -assess "node-gyp", "node-gyp rebuild " & gypflags +let gypRebuild = execCmdEx "node-gyp rebuild " & gypflags +doAssert gypRebuild.exitCode == 0 , gypRebuild.output From 68ef3115f4f229dd381c32a28be256e483f53e6e Mon Sep 17 00:00:00 2001 From: bung87 Date: Wed, 21 Jul 2021 10:25:15 +0800 Subject: [PATCH 05/12] o --- src/napibindings.nim | 120 ++++++++++++++++++++++++------------------- 1 file changed, 68 insertions(+), 52 deletions(-) diff --git a/src/napibindings.nim b/src/napibindings.nim index 9dd7881..a3aaf5d 100644 --- a/src/napibindings.nim +++ b/src/napibindings.nim @@ -11,14 +11,14 @@ var `env$`*: napi_env = nil type napi_value* = pointer type napi_callback* = proc(environment: napi_env, info: pointer): napi_value {.cdecl.} type napi_property_attributes* = int -type napi_property_descriptor {.header:"".} = object +type napi_property_descriptor {.header: "".} = object utf8name: cstring name, value: napi_value attributes: napi_property_attributes `method`, getter, setter: napi_callback data: pointer -type NapiKind* {.importc: "napi_valuetype", header:"".}= enum +type NapiKind* {.importc: "napi_valuetype", header: "".} = enum napi_undefined napi_null napi_boolean @@ -30,7 +30,7 @@ type NapiKind* {.importc: "napi_valuetype", header:"".}= enum napi_external napi_valuetype -type NapiStatus* {.importc: "napi_status", header:"".} = enum +type NapiStatus* {.importc: "napi_status", header: "".} = enum napi_ok napi_invalid_arg napi_object_expected @@ -47,7 +47,7 @@ type NapiStatus* {.importc: "napi_status", header:"".} = enum proc assessStatus*(status: int) {.raises: [NapiStatusError].} = - ##Asserts that a call returns correctly; + ##Asserts that a call returns correctly; if status != 0: raise newException(NapiStatusError, "NAPI call returned non-zero status (" & $status & ": " & $NapiStatus(status) & ")") @@ -67,50 +67,52 @@ proc newNodeValue*(val: napi_value, env: napi_env): Module = proc kind(env: napi_env, val: napi_value): NapiKind = proc napi_typeof (e: napi_env, v: napi_value, res: ptr NapiKind): int{.header: "".} - assessStatus ( napi_typeof(env, val, addr result) ) + assessStatus (napi_typeof(env, val, addr result)) ##Used internally, disregard -var napi_default {.header:"".}: napi_property_attributes +var napi_default {.header: "".}: napi_property_attributes proc create(env: napi_env, n: int32): napi_value = - proc napi_create_int32(env: napi_env, n: cint, val: ptr napi_value): int {.header:"".} - assessStatus ( napi_create_int32(env, n, addr result) ) + proc napi_create_int32(env: napi_env, n: cint, val: ptr napi_value): int {.header: "".} + assessStatus (napi_create_int32(env, n, addr result)) proc create(env: napi_env, n: int64): napi_value = - proc napi_create_int64(env: napi_env, n: int64, val: ptr napi_value): int {.header:"".} - assessStatus ( napi_create_int64(env, n, addr result) ) + proc napi_create_int64(env: napi_env, n: int64, val: ptr napi_value): int {.header: "".} + assessStatus (napi_create_int64(env, n, addr result)) proc create(env: napi_env, n: uint32): napi_value = - proc napi_create_uint32(env: napi_env, n: uint32, val: ptr napi_value): int {.header:"".} - assessStatus ( napi_create_uint32(env, n, addr result) ) + proc napi_create_uint32(env: napi_env, n: uint32, val: ptr napi_value): int {.header: "".} + assessStatus (napi_create_uint32(env, n, addr result)) proc create(env: napi_env, n: uint64): napi_value = - proc napi_create_uint64(env: napi_env, n: uint64, val: ptr napi_value): int {.header:"".} - assessStatus ( napi_create_uint64(env, n, addr result) ) + proc napi_create_uint64(env: napi_env, n: uint64, val: ptr napi_value): int {.header: "".} + assessStatus (napi_create_uint64(env, n, addr result)) proc create(env: napi_env, n: float64): napi_value = - proc napi_create_double(env: napi_env, n: float64, val: ptr napi_value): int {.header:"".} - assessStatus ( napi_create_double(env, n, addr result) ) + proc napi_create_double(env: napi_env, n: float64, val: ptr napi_value): int {.header: "".} + assessStatus (napi_create_double(env, n, addr result)) proc create(env: napi_env, s: string): napi_value = - proc napi_create_string_utf8(env: napi_env, str: cstring, length: csize, val: ptr napi_value): int {.header:"".} - assessStatus ( napi_create_string_utf8(env, s, s.len, addr result) ) + proc napi_create_string_utf8(env: napi_env, str: cstring, length: csize, val: ptr napi_value): int {. + header: "".} + assessStatus (napi_create_string_utf8(env, s, s.len, addr result)) proc create(env: napi_env, p: openarray[(string, napi_value)]): napi_value = - proc napi_create_object(env: napi_env, res: ptr napi_value): int {.header:"".} - proc napi_set_named_property(env: napi_env, obj: napi_value, utf8name: cstring, value: napi_value): int {.header:"".} + proc napi_create_object(env: napi_env, res: ptr napi_value): int {.header: "".} + proc napi_set_named_property(env: napi_env, obj: napi_value, utf8name: cstring, value: napi_value): int {. + header: "".} assessStatus napi_create_object(env, addr result) for name, val in items(p): assessStatus napi_set_named_property(env, result, name, val) proc create(env: napi_env, a: openarray[napi_value]): napi_value = - proc napi_create_array_with_length(e: napi_env, length: csize, res: ptr napi_value): int {.header:"".} - proc napi_set_element(e: napi_env, o: napi_value, index: csize, value: napi_value): int {.header:"".} - assessStatus( napi_create_array_with_length(env, a.len, addr result) ) + proc napi_create_array_with_length(e: napi_env, length: csize, res: ptr napi_value): int {.header: "".} + proc napi_set_element(e: napi_env, o: napi_value, index: csize, value: napi_value): int {.header: "".} + assessStatus(napi_create_array_with_length(env, a.len, addr result)) for i, elem in a.enumerate: assessStatus napi_set_element(env, result, i, a[i]) proc create[T: int | uint | string](env: napi_env, a: openarray[T]): napi_value = @@ -125,8 +127,9 @@ proc create[T: int | uint | string](env: napi_env, a: openarray[(string, T)]): n env.create(a) proc createFn*(env: napi_env, fname: string, cb: napi_callback): napi_value = - proc napi_create_function(env: napi_env, utf8name: cstring, length: csize, cb: napi_callback, data: pointer, res: napi_value): int {.header:"".} - assessStatus ( napi_create_function(env, fname, fname.len, cb, nil, addr result) ) + proc napi_create_function(env: napi_env, utf8name: cstring, length: csize, cb: napi_callback, data: pointer, + res: napi_value): int {.header: "".} + assessStatus (napi_create_function(env, fname, fname.len, cb, nil, addr result)) proc create(env: napi_env, v: napi_value): napi_value = v @@ -192,19 +195,21 @@ proc getStr*(n: napi_value, bufsize: int = 40): string = ##Retrieves utf8 encoded value from node; raises exception on failure ## ##Maximum return string length is equal to ``bufsize`` - proc napi_get_value_string_utf8(e: napi_env, v: napi_value, buf: cstring, bufsize: csize, res: ptr csize): int {.header: "".} - var + proc napi_get_value_string_utf8(e: napi_env, v: napi_value, buf: cstring, bufsize: csize, res: ptr csize): int {. + header: "".} + var buf = cast[cstring](alloc(bufsize)) res: csize assessStatus napi_get_value_string_utf8(`env$`, n, buf, bufsize, addr res) - return ($buf)[0..res-1] + return ($buf)[0..res-1] proc getStr*(n: napi_value, default: string, bufsize: int = 40): string = ##Retrieves utf8 encoded value from node; returns default on failure ##Maximum return string length is equal to ``bufsize`` - proc napi_get_value_string_utf8(e: napi_env, v: napi_value, buf: cstring, bufsize: csize, res: ptr csize): int {.header: "".} - var + proc napi_get_value_string_utf8(e: napi_env, v: napi_value, buf: cstring, bufsize: csize, res: ptr csize): int {. + header: "".} + var buf = cast[cstring](alloc(bufsize)) res: csize @@ -217,14 +222,16 @@ proc hasProperty*(obj: napi_value, key: string): bool {.raises: [ValueError, Nap ##Checks whether or not ``obj`` has a property ``key``; Panics if ``obj`` is not an object if kind(obj) != napi_object: raise newException(ValueError, "value is not an object") - proc napi_has_named_property(env: napi_env, obj: napi_value, key: cstring, res: ptr bool): int {.header:"".} + proc napi_has_named_property(env: napi_env, obj: napi_value, key: cstring, res: ptr bool): int {. + header: "".} assessStatus napi_has_named_property(`env$`, obj, (key), addr result) -proc getProperty*(obj: napi_value, key: string): napi_value {.raises: [KeyError, ValueError, NapiStatusError].}= +proc getProperty*(obj: napi_value, key: string): napi_value {.raises: [KeyError, ValueError, NapiStatusError].} = ##Retrieves property ``key`` from ``obj``; Panics if ``obj`` is not an object if not hasProperty(obj, key): raise newException(KeyError, "property not contained for key " & key) - proc napi_get_named_property(env: napi_env, obj: napi_value, key: cstring, res: ptr napi_value): int {.header:"".} + proc napi_get_named_property(env: napi_env, obj: napi_value, key: cstring, res: ptr napi_value): int {. + header: "".} assessStatus napi_get_named_property(`env$`, obj, (key), addr result) proc getProperty*(obj: napi_value, key: string, default: napi_value): napi_value = @@ -232,10 +239,11 @@ proc getProperty*(obj: napi_value, key: string, default: napi_value): napi_value try: obj.getProperty(key) except: default -proc setProperty*(obj: napi_value, key: string, value: napi_value) {.raises: [ValueError, NapiStatusError].}= +proc setProperty*(obj: napi_value, key: string, value: napi_value) {.raises: [ValueError, NapiStatusError].} = ##Sets property ``key`` in ``obj`` to ``value``; raises exception if ``obj`` is not an object if kind(obj) != napi_object: raise newException(ValueError, "value is not an object") - proc napi_set_named_property(env: napi_env, obj: napi_value, key: cstring, value: napi_value): int{.header: "".} + proc napi_set_named_property(env: napi_env, obj: napi_value, key: cstring, value: napi_value): int{. + header: "".} assessStatus napi_set_named_property(`env$`, obj, key, value) proc `[]`*(obj: napi_value, key: string): napi_value = @@ -260,7 +268,8 @@ proc hasElement*(obj: napi_value, index: int): bool = proc getElement*(obj: napi_value, index: int): napi_value = ##Retrieves value from ``index`` in ``obj``; raises exception if ``obj`` is not an array or ``index`` is out of bounds if not hasElement(obj, index): raise newException(IndexError, "index out of bounds") - proc napi_get_element(env: napi_env, obj: napi_value, index: uint32, res: ptr napi_value): int {.header: "".} + proc napi_get_element(env: napi_env, obj: napi_value, index: uint32, res: ptr napi_value): int {. + header: "".} assessStatus napi_get_element(`env$`, obj, uint32 index, addr result) proc getElement*(obj: napi_value, index: int, default: napi_value): napi_value = @@ -270,7 +279,8 @@ proc getElement*(obj: napi_value, index: int, default: napi_value): napi_value = proc setElement*(obj: napi_value, index: int, value: napi_value) = ##Sets value at ``index``; raises exception if ``obj`` is not an array if not isArray(obj): raise newException(ValueError, "value is not an array") - proc napi_set_element(env: napi_env, obj: napi_value, index: uint32, value: napi_value): int {.header: "".} + proc napi_set_element(env: napi_env, obj: napi_value, index: uint32, value: napi_value): int {. + header: "".} assessStatus napi_set_element(`env$`, obj, uint32 index, value) proc `[]`*(obj: napi_value, index: int): napi_value = @@ -292,8 +302,6 @@ proc undefined*: napi_value = - - proc registerBase(obj: Module, name: string, value: napi_value, attr: int) = obj.descriptors.add( napi_property_descriptor( @@ -309,12 +317,13 @@ proc register*[T: int | uint | string | napi_value](obj: Module, name: string, v proc register*[T: int | uint | string | napi_value](obj: Module, name: string, values: openarray[T], attr: int = 0) = ##Adds field to exports object ``obj`` - var elements = newSeq[napi_value]() + var elements = newSeq[napi_value]() for v in values: elements.add(obj.create(v)) obj.registerBase(name, create(obj.env, elements), attr) -proc register*[T: int | uint | string | napi_value](obj: Module, name: string, values: openarray[(string, T)], attr: int = 0) = +proc register*[T: int | uint | string | napi_value](obj: Module, name: string, values: openarray[(string, T)], + attr: int = 0) = ##Adds field to exports object ``obj`` var properties = newSeq[(string, napi_value)]() for v in values: properties.add((v[0], obj.create(v[1]))) @@ -331,16 +340,18 @@ proc `%`*[T](t: T): napi_value = const emptyArr: array[0, (string, napi_value)] = [] proc callFunction*(fn: napi_value, args: openarray[napi_value] = [], this = %emptyArr): napi_value = - proc napi_call_function(env: napi_env, recv, fn: napi_value, argc: cint, argv, res: ptr napi_value): int {.header:"".} - assessStatus napi_call_function(`env$`, this, fn, cint args.len, cast[ptr napi_value](args.toUnchecked()), addr result) + proc napi_call_function(env: napi_env, recv, fn: napi_value, argc: cint, argv, res: ptr napi_value): int {. + header: "".} + assessStatus napi_call_function(`env$`, this, fn, cint args.len, cast[ptr napi_value](args.toUnchecked()), addr result) template fn*(paramCt: int, name, cushy: untyped): untyped {.dirty.} = var name {.inject.}: napi_value block: - proc napi_get_cb_info(env: napi_env, cbinfo: pointer, argc: ptr csize, argv: pointer, this: napi_value, data: pointer = nil): int {.header:"".} + proc napi_get_cb_info(env: napi_env, cbinfo: pointer, argc: ptr csize, argv: pointer, this: napi_value, + data: pointer = nil): int {.header: "".} proc `wrapper$`(environment: napi_env, info: pointer): napi_value {.cdecl.} = - var + var `argv$` = cast[ptr UncheckedArray[napi_value]](alloc(paramCt * sizeof(napi_value))) argc: csize = paramCt this: napi_value @@ -355,11 +366,12 @@ template fn*(paramCt: int, name, cushy: untyped): untyped {.dirty.} = name = createFn(`env$`, name, `wrapper$`) -template registerFn*(exports: Module, paramCt: int, name: string, cushy: untyped): untyped {.dirty.}= +template registerFn*(exports: Module, paramCt: int, name: string, cushy: untyped): untyped {.dirty.} = block: - proc napi_get_cb_info(env: napi_env, cbinfo: pointer, argc: ptr csize, argv: pointer, this: napi_value, data: pointer = nil): int {.header:"".} + proc napi_get_cb_info(env: napi_env, cbinfo: pointer, argc: ptr csize, argv: pointer, this: napi_value, + data: pointer = nil): int {.header: "".} proc `wrapper$`(environment: napi_env, info: pointer): napi_value {.cdecl.} = - var + var `argv$` = cast[ptr UncheckedArray[napi_value]](alloc(paramCt * sizeof(napi_value))) argc: csize = paramCt this: napi_value @@ -375,8 +387,10 @@ template registerFn*(exports: Module, paramCt: int, name: string, cushy: untyped proc defineProperties*(obj: Module) = - proc napi_define_properties(env: napi_env, val: napi_value, property_count: csize, properties: ptr napi_property_descriptor): int {.header:"".} - assessStatus napi_define_properties(obj.env, obj.val, obj.descriptors.len, cast[ptr napi_property_descriptor](obj.descriptors.toUnchecked)) + proc napi_define_properties(env: napi_env, val: napi_value, property_count: csize, + properties: ptr napi_property_descriptor): int {.header: "".} + assessStatus napi_define_properties(obj.env, obj.val, obj.descriptors.len, cast[ptr napi_property_descriptor]( + obj.descriptors.toUnchecked)) @@ -416,7 +430,8 @@ macro init*(initHook: proc(exports: Module)): typed = nimmain.addPragma(ident("importc")) var cinit = newProc( name = ident("cinit"), - params = [ident("napi_value") , newIdentDefs(ident("environment"), ident("napi_env")), newIdentDefs(ident("exportsPtr"), ident("napi_value"))], + params = [ident("napi_value"), newIdentDefs(ident("environment"), ident("napi_env")), newIdentDefs(ident( + "exportsPtr"), ident("napi_value"))], body = newStmtList( nimmain, newCall("NimMain"), @@ -430,6 +445,7 @@ macro init*(initHook: proc(exports: Module)): typed = cinit.addPragma(ident("exportc")) result = newStmtList( cinit, - newNimNode(nnkPragma).add(newColonExpr(ident("emit"), newStrLitNode("""/*VARSECTION*/ NAPI_MODULE(NODE_GYP_MODULE_NAME, cinit)"""))), + newNimNode(nnkPragma).add(newColonExpr(ident("emit"), newStrLitNode( + """/*VARSECTION*/ NAPI_MODULE(NODE_GYP_MODULE_NAME, cinit)"""))), ) From e36fceacd78703653f2d35ad8979b5fece13a0ee Mon Sep 17 00:00:00 2001 From: bung87 Date: Wed, 21 Jul 2021 10:25:53 +0800 Subject: [PATCH 06/12] pretty --- src/napibuild.nim | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/napibuild.nim b/src/napibuild.nim index 3c6606c..cd48e03 100644 --- a/src/napibuild.nim +++ b/src/napibuild.nim @@ -1,7 +1,7 @@ import json, docopt, os, osproc -const ExplicitSourcePath {.strdefine.} = os.parentDir(os.parentDir( os.getCurrentCompilerExe())) -const LibPath = ExplicitSourcePath / "lib" +const ExplicitSourcePath {.strdefine.} = os.parentDir(os.parentDir(os.getCurrentCompilerExe())) +const LibPath = ExplicitSourcePath / "lib" const doc = """ NodeBuild. Usage: @@ -14,13 +14,13 @@ Options: let args = docopt(doc) -var +var projectfile = $args[""] project = splitFile(projectfile) nimbase = LibPath - nimcache = project.dir / "nimcache"#$args[""] - target = %* { "target_name": project.name } - gyp = %* { "targets": [target] } + nimcache = project.dir / "nimcache" #$args[""] + target = %* {"target_name": project.name} + gyp = %* {"targets": [target]} if not args["-C"]: @@ -29,7 +29,7 @@ if not args["-C"]: doAssert r.exitCode == 0, r.output -target["include_dirs"] = %[ nimbase ] +target["include_dirs"] = %[nimbase] target["cflags"] = %["-w"] if args["-r"]: target["cflags"].add(%"-O3") @@ -38,8 +38,7 @@ target["linkflags"] = %["-ldl"] target["sources"] = %[] for targetobj in parsejson(readfile(nimcache / (project.name & ".json")))["link"]: - target["sources"].add(% ("nimcache" / targetobj.getstr.splitFile.name)) - + target["sources"].add( % ("nimcache" / targetobj.getstr.splitFile.name)) writeFile(project.dir / "binding.gyp", gyp.pretty) @@ -47,5 +46,5 @@ writeFile(project.dir / "binding.gyp", gyp.pretty) var gypflags = "--directory=" & project.dir if not args["-r"]: gypflags.add(" --debug") -let gypRebuild = execCmdEx "node-gyp rebuild " & gypflags -doAssert gypRebuild.exitCode == 0 , gypRebuild.output +let gypRebuild = execCmdEx "node-gyp rebuild " & gypflags +doAssert gypRebuild.exitCode == 0, gypRebuild.output From a34afc7ff8d085df1411a7407114ddeb7ff401d1 Mon Sep 17 00:00:00 2001 From: bung87 Date: Sun, 1 Aug 2021 02:54:36 +0800 Subject: [PATCH 07/12] add error handle --- src/napibindings.nim | 43 ++++++++++++++++++++++++++++++------------- test/index.js | 8 ++++++++ test/main.nim | 7 +++++-- 3 files changed, 43 insertions(+), 15 deletions(-) diff --git a/src/napibindings.nim b/src/napibindings.nim index a3aaf5d..d00aa15 100644 --- a/src/napibindings.nim +++ b/src/napibindings.nim @@ -1,7 +1,5 @@ import macros -type NapiStatusError = object of Exception - type napi_env* = pointer var `env$`*: napi_env = nil @@ -45,13 +43,13 @@ type NapiStatus* {.importc: "napi_status", header: "".} = enum napi_cancelled napi_status_last +type NapiStatusError* = ref object of CatchableError + status*: NapiStatus proc assessStatus*(status: int) {.raises: [NapiStatusError].} = ##Asserts that a call returns correctly; if status != 0: - raise newException(NapiStatusError, "NAPI call returned non-zero status (" & $status & ": " & $NapiStatus(status) & ")") - - + raise NapiStatusError(msg: "NAPI call returned non-zero status", status: NapiStatus(status)) type Module* = ref object val*: napi_value @@ -361,7 +359,12 @@ template fn*(paramCt: int, name, cushy: untyped): untyped {.dirty.} = for i in 0..".} + discard napi_throw_error(`env$`, "".cstring, msg.cstring) + +proc propagateExceptionToJS*() = + let e = getCurrentException() + let frames = e.getStackTraceEntries() + var msg = e.msg + for i in countdown(frames.len - 2, 0): + let frame = frames[i] + msg = msg & "\n at " & + $frame.procname & " (" & + $frame.filename & ":" & + $frame.line & ")" + throwNapiError msg proc napiCreate*[T](t: T): napi_value = `env$`.create(t) diff --git a/test/index.js b/test/index.js index afcc332..376b3f7 100644 --- a/test/index.js +++ b/test/index.js @@ -7,3 +7,11 @@ assert.deepStrictEqual(addon.createArray('jim', 'bob', 3), ['jim', 'bob', 3]) assert.strictEqual(addon.getOrDefault([1, 2, 3], 0/*index*/, 'unexpected'/*default*/), 1) assert.strictEqual(addon.getOrDefault([1, 2, 3], 5/*index*/, 'expected'/*default*/), 'expected') + +try{ + addon.raiseError() +}catch(e){ + assert.strictEqual(e.name,'Error') + assert.strictEqual(e.message,'value error') +} + diff --git a/test/main.nim b/test/main.nim index dcb3bf1..45a3fcb 100644 --- a/test/main.nim +++ b/test/main.nim @@ -4,7 +4,7 @@ init proc(exports: Module) = exports.register("hello", "hello world") exports.registerFn(10, "addNums"): - %(args.mapIt(it.getInt).foldl(a + b)) + result = %(args.mapIt(it.getInt).foldl(a + b)) exports.registerFn(10, "createArray"): result = % [5] @@ -15,5 +15,8 @@ init proc(exports: Module) = ##``args[0]`` : array ##``args[1]`` : index ##``args[2]`` : default - args[0].getElement(args[1].getInt, args[2]) + result = args[0].getElement(args[1].getInt, args[2]) + + exports.registerFn(0,"raiseError"): + raise newException(ValueError,"value error") From cc18b49ee8b7f671c9c8ffb681e086bcf656eaa5 Mon Sep 17 00:00:00 2001 From: bung87 Date: Sun, 1 Aug 2021 03:01:43 +0800 Subject: [PATCH 08/12] add obj test --- test/index.js | 3 +++ test/main.nim | 3 +++ 2 files changed, 6 insertions(+) diff --git a/test/index.js b/test/index.js index 376b3f7..cf837a0 100644 --- a/test/index.js +++ b/test/index.js @@ -15,3 +15,6 @@ try{ assert.strictEqual(e.message,'value error') } + +const obj = addon.createObject() +assert.deepEqual(obj,{b:1}) diff --git a/test/main.nim b/test/main.nim index 45a3fcb..64f5517 100644 --- a/test/main.nim +++ b/test/main.nim @@ -5,6 +5,9 @@ init proc(exports: Module) = exports.registerFn(10, "addNums"): result = %(args.mapIt(it.getInt).foldl(a + b)) + + exports.registerFn(0, "createObject"): + result = %* {"b": 1} exports.registerFn(10, "createArray"): result = % [5] From d0ffe906352f8b56e7bc63e55e8abaf67640a813 Mon Sep 17 00:00:00 2001 From: bung87 Date: Sun, 1 Aug 2021 03:05:02 +0800 Subject: [PATCH 09/12] readme --- README.md | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/README.md b/README.md index 2e9ad62..453d54c 100644 --- a/README.md +++ b/README.md @@ -20,30 +20,8 @@ Consequently, `node-gyp` requires `python 2.x`, while version `2.7` is recommend ### Installing -To install this library and `napibuild` -```bash -git clone https://github.com/AjBreidenbach/napibindings.git -cd napibindings -nimble install -``` - -Enter `y` and you're finished - -To run all tests -```bash -cd test/ -npm install -napibuild main.nim -node index.js -cd ../ -``` -To view the documentation -```bash -nim doc napibindings.nim && google-chrome napibindings.html > /dev/null & - -``` - +`nimble install https://github.com/bung87/napibindings` ### Creating a new simple project Start by running `npm init` and entering information as prompted From 6e8edaa0a37fb1e580ee35b2931d75eeb2c85d5a Mon Sep 17 00:00:00 2001 From: bung87 Date: Sun, 1 Aug 2021 03:21:54 +0800 Subject: [PATCH 10/12] add ci and prebuild --- .github/workflows/build-test.yml | 41 ++++++++++++++++++++++++++++++++ test/package.json | 5 +++- 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/build-test.yml diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml new file mode 100644 index 0000000..558beb7 --- /dev/null +++ b/.github/workflows/build-test.yml @@ -0,0 +1,41 @@ +name: build-test + +on: + pull_request: + paths-ignore: + - '**.md' + push: + paths-ignore: + - '**.md' + +jobs: + build: + runs-on: ${{ matrix.operating-system }} + strategy: + matrix: + # 10.x, 12.x, + node-version: [ 12.x] + operating-system: [ubuntu-latest, windows-latest, macos-latest,'windows-7'] + steps: + - uses: actions/checkout@v2 + with: + submodules: true + - name: Install nim deps + uses: jiro4989/setup-nim-action@v1 + run: nimble install -d -y + - name: Setup node + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node }} + - name: Install node deps + run: | + yarn global add node-gyp + yarn install --ignore-scripts + working-directory: test + - name: test + run: nimble test + - name: publish + working-directory: test + env: + PREBUILD_TOKEN: ${{ secrets.PREBUILD_TOKEN }} + run: yarn prebuild --upload-all ${{ secrets.PREBUILD_TOKEN }} \ No newline at end of file diff --git a/test/package.json b/test/package.json index 0edfd29..ad1ed35 100644 --- a/test/package.json +++ b/test/package.json @@ -4,11 +4,14 @@ "description": "nim napi test", "main": "index.js", "scripts": { + "install": "prebuild-install", + "build": "prebuild -r node", "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { - "bindings": "^1.5.0" + "bindings": "^1.5.0", + "prebuild-install": "^6.0.0" } } From fb9cb87e94cf752b01249555b79f5a6b31c46bc3 Mon Sep 17 00:00:00 2001 From: bung87 Date: Sun, 1 Aug 2021 03:23:18 +0800 Subject: [PATCH 11/12] o --- .github/workflows/build-test.yml | 19 ++++++++++++++++--- .gitignore | 1 + napibindings.nimble | 9 ++++----- src/napibuild.nim | 7 ++++--- test/package.json | 20 +++++++++++++++++++- 5 files changed, 44 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 558beb7..341ba42 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -15,13 +15,16 @@ jobs: matrix: # 10.x, 12.x, node-version: [ 12.x] - operating-system: [ubuntu-latest, windows-latest, macos-latest,'windows-7'] + operating-system: [ubuntu-latest, windows-latest, macos-latest] steps: - uses: actions/checkout@v2 with: submodules: true + + - uses: jiro4989/setup-nim-action@v1 + with: + nim-version: '1.4.8' # default is - name: Install nim deps - uses: jiro4989/setup-nim-action@v1 run: nimble install -d -y - name: Setup node uses: actions/setup-node@v1 @@ -29,12 +32,22 @@ jobs: node-version: ${{ matrix.node }} - name: Install node deps run: | - yarn global add node-gyp + npm install -g node-gyp yarn install --ignore-scripts working-directory: test - name: test run: nimble test + + - name: Check if Git tag exists + run: echo "::set-env name=HEAD_TAG::$(git tag --points-at HEAD)" + env: + ACTIONS_ALLOW_UNSECURE_COMMANDS: true + - name: build + run: yarn build + if: env.HEAD_TAG != '' + working-directory: test - name: publish + if: env.HEAD_TAG != '' working-directory: test env: PREBUILD_TOKEN: ${{ secrets.PREBUILD_TOKEN }} diff --git a/.gitignore b/.gitignore index 4aec24e..057870d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ !**/ !*.* test/build +test/prebuilds binding.gyp yarn.lock node_modules diff --git a/napibindings.nimble b/napibindings.nimble index ba86bbe..3996a25 100644 --- a/napibindings.nimble +++ b/napibindings.nimble @@ -7,9 +7,8 @@ skipDirs = @["test", ".git"] bin = @["napibuild"] requires "docopt" - +import os task test,"test": - withDir "test": - exec "yarn install --ignore-scripts" - exec "nim c -r src/napibuild.nim test/main.nim" - exec "node test/index.js" \ No newline at end of file + exec findExe("yarn") & " install --ignore-scripts --cwd test" + selfExec "c -r " & "src" / "napibuild.nim" & " -r " & "test" / "main.nim" + exec findExe("node") & " " & "test" / "index.js" \ No newline at end of file diff --git a/src/napibuild.nim b/src/napibuild.nim index cd48e03..bafbe11 100644 --- a/src/napibuild.nim +++ b/src/napibuild.nim @@ -24,8 +24,9 @@ var if not args["-C"]: - var releaseFlag = if args["-r"]: "-d:release " else: "--embedsrc " - let r = execCmdEx "nim c --nimcache:" & nimcache & " " & releaseFlag & "--compileOnly --noMain " & projectfile + let releaseFlag = if args["-r"]: "-d:release " else: "--embedsrc " + let vccFlag = when defined(windows): " --cc:vcc " else: "" + let r = execCmdEx "nim c " & vccFlag & " --nimcache:" & nimcache & " " & releaseFlag & "--compileOnly --noMain " & projectfile doAssert r.exitCode == 0, r.output @@ -46,5 +47,5 @@ writeFile(project.dir / "binding.gyp", gyp.pretty) var gypflags = "--directory=" & project.dir if not args["-r"]: gypflags.add(" --debug") -let gypRebuild = execCmdEx "node-gyp rebuild " & gypflags +let gypRebuild = execCmdEx findExe("node-gyp") & " rebuild " & gypflags doAssert gypRebuild.exitCode == 0, gypRebuild.output diff --git a/test/package.json b/test/package.json index ad1ed35..f9d52ba 100644 --- a/test/package.json +++ b/test/package.json @@ -3,13 +3,31 @@ "version": "0.0.0", "description": "nim napi test", "main": "index.js", + "repository": { + "type": "git", + "url": "https://github.com/bung87/napibindings.git" + }, "scripts": { "install": "prebuild-install", - "build": "prebuild -r node", + "build": "prebuild", "test": "echo \"Error: no test specified\" && exit 1" }, + "binary": { + "napi_versions": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7 + ] + }, "author": "", "license": "ISC", + "devDependencies": { + "prebuild": "^10.0.1" + }, "dependencies": { "bindings": "^1.5.0", "prebuild-install": "^6.0.0" From 0f3efb3028769031c5636fdef6d663d4d77665fa Mon Sep 17 00:00:00 2001 From: bung87 Date: Sun, 1 Aug 2021 22:36:06 +0800 Subject: [PATCH 12/12] [skip CI] badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 453d54c..49f4127 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# NapiBindings +# NapiBindings [![build-test](https://github.com/bung87/napibindings/actions/workflows/build-test.yml/badge.svg)](https://github.com/bung87/napibindings/actions/workflows/build-test.yml) Bindings between Nim and N-API ## Getting started