diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..173f8a6a --- /dev/null +++ b/.clang-format @@ -0,0 +1,2 @@ +BasedOnStyle: LLVM +ColumnLimit: 120 diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 00000000..5645602c --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,4 @@ +FROM mcr.microsoft.com/devcontainers/javascript-node:24 + +# need to run update and install at the same time to prevent stale update layer +RUN apt-get update && apt-get install -y gdb clang-format openjdk-21-jdk maven diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..fb149f0e --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,17 @@ +{ + "build": { + "dockerfile": "Dockerfile" + }, + "runArgs": [], + "customizations": { + "vscode": { + "extensions": [ + "streetsidesoftware.code-spell-checker", + "bierner.markdown-emoji", + "smulyono.reveal", + "ms-azuretools.vscode-docker", + "ms-vscode.cpptools-extension-pack" + ] + } + } +} \ No newline at end of file diff --git a/.gitattributes b/.gitattributes index 12b7161f..424e53c3 100644 --- a/.gitattributes +++ b/.gitattributes @@ -7,3 +7,5 @@ *.jpg -text *.jpeg -text *.ico -text +*.jar -text +*.class -text diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml index 016bbb14..fbfa09d2 100644 --- a/.github/workflows/master.yml +++ b/.github/workflows/master.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - nodeVersion: [ 16, 18, 20 ] + nodeVersion: [ 20, 22, 24 ] jdkVersion: [ openjdk9, openjdk10, openjdk11, openjdk21 ] steps: - name: Checkout source code @@ -19,5 +19,11 @@ jobs: node-version: ${{ matrix.nodeVersion }} - name: npm ci run: npm ci + - name: npm run format-cpp + run: npm run format-cpp + - name: npm run format + run: npm run format + - name: npm run lint + run: npm run lint - name: Unit test run: npm test diff --git a/.github/workflows/pull-requests.yml b/.github/workflows/pull-requests.yml index c5fd0d69..2d20d7f7 100644 --- a/.github/workflows/pull-requests.yml +++ b/.github/workflows/pull-requests.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - nodeVersion: [ 16, 18, 20 ] + nodeVersion: [ 20, 22, 24 ] jdkVersion: [ openjdk9, openjdk10, openjdk11, openjdk21 ] steps: - name: Checkout source code @@ -20,5 +20,11 @@ jobs: node-version: ${{ matrix.nodeVersion }} - name: npm ci run: npm ci + - name: npm run format-cpp + run: npm run format-cpp + - name: npm run format + run: npm run format + - name: npm run lint + run: npm run lint - name: Unit test run: npm test diff --git a/.gitignore b/.gitignore index 92159f55..633ce199 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,6 @@ node-java.cbp *.iml *.kdev4 */.kdev_include_paths -.vscode CMakeLists.txt cmake-build-debug/ +hs_err* \ No newline at end of file diff --git a/.npmignore b/.npmignore index 4c82cca7..5c81151b 100644 --- a/.npmignore +++ b/.npmignore @@ -1,3 +1,4 @@ +/test /testIntegration /.idea /build diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..60c971ca --- /dev/null +++ b/.prettierignore @@ -0,0 +1,23 @@ +**/*.cpp +**/*.h +**/*.ppt +**/*.jar +**/*.class +**/*.java +**/*.sh +**/*.html +**/*.json +**/*.png +**/*.md +**/*.rule +**/*.rules +**/*.gyp +**/*.yml +**/Dockerfile +.clang-format +.prettierrc +.prettierignore +.npmignore +.gitignore +.gitattributes +LICENSE diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..53fee0e9 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,10 @@ +{ + "parser": "typescript", + "semi": true, + "singleQuote": false, + "tabWidth": 2, + "trailingComma": "es5", + "useTabs": false, + "printWidth": 120, + "endOfLine": "lf" +} diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 00000000..5c437f51 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,19 @@ +{ + "configurations": [ + { + "name": "Linux", + "includePath": [ + "${workspaceFolder}/**", + "/usr/local/include/node", + "/usr/lib/jvm/java-17-openjdk-amd64/include/", + "/usr/lib/jvm/java-17-openjdk-amd64/include/linux" + ], + "defines": [], + "compilerPath": "/usr/bin/gcc", + "cStandard": "c17", + "cppStandard": "gnu++17", + "intelliSenseMode": "linux-gcc-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..8b4e243e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,26 @@ +{ + "cSpell.words": [ + "clazz", + "clazzclazz", + "Ferner", + "jarray", + "javac", + "jboolean", + "jbyte", + "jchar", + "jclass", + "jdouble", + "jfloat", + "jint", + "jlong", + "jmethod", + "jobj", + "jobject", + "jshort", + "jsize", + "jthrowable", + "jvalue", + "Ljava", + "varargs" + ] +} \ No newline at end of file diff --git a/LICENSE b/LICENSE index cbe71a99..3e23b3ec 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2023 Joe Ferner +Copyright (c) 2025 Joe Ferner Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/README.md b/README.md index 6462c5f1..c10cc364 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ Bridge API to connect with existing Java APIs. ### Other projects that might be helpful * [node-java-maven](https://github.com/joeferner/node-java-maven) - manages your node-java classpath by using maven dependency management. +* [ts-java](https://github.com/RedSeal-co/ts-java) - Create TypeScript declaration files for Java packages. ## Installation @@ -20,7 +21,7 @@ Notes: * node-gyp requires python 2.x not python 3.x. See https://github.com/TooTallNate/node-gyp/issues/155 for more details. * If you see an error such as "Call to 'node findJavaHome.js' returned exit status 1" - Try running `node findJavaHome.js` in the node-java directory to see the full failure message. + Try running `node ./scripts/findJavaHome.js` in the node-java directory to see the full failure message. * If you are having problems finding 'jni.h'. Make sure you have the JDK installed not just the JRE. If you are using OpenJDK you want the openjdk-7-jdk package, not openjdk-7-jre. _Mavericks users see [Issue #86](https://github.com/nearinfinity/node-java/issues/86) if you run into this._ @@ -62,7 +63,7 @@ GYP_DEFINES="armv7=0" CCFLAGS='-march=armv6' CXXFLAGS='-march=armv6' npm install ## Manual compile (Using node-gyp) ```bash -./compile-java-code.sh +./scripts/compile-java.sh node-gyp configure build npm test ``` @@ -92,8 +93,8 @@ npm install --unsafe-perm java Then create a file called `test.js` with the following contents ``` -var java = require('java'); -var javaLangSystem = java.import('java.lang.System'); +const java = require('java'); +const javaLangSystem = java.import('java.lang.System'); javaLangSystem.out.printlnSync('Hello World'); ``` @@ -104,19 +105,6 @@ Then run node test.js ``` -### Java 1.8 support - -Manual compilation for Java 1.8 support requires additional steps: - -```bash -./compile-java-code.sh -./compile-java8-code.sh -node-gyp configure build -npm test -``` - -Java 1.8 language features can be used in Java classes only if a Java 1.8 JRE is available. The script compile-java8-code.sh is used only to compile java classes used in the 'test8' unit tests, but these classes are checked into the test8/ directory. Note that unit tests in the test8/ directory will pass (by design) if run against a Java 1.7 JRE, provided that a java.lang.UnsupportedClassVersionError is caught with the message 'Unsupported major.minor version 52.0' (the expected behavior when Java 1.8 language features are used in an older JRE). - ## Installation node-webkit ```bash @@ -143,10 +131,10 @@ Then create the following module javaInit: ```javascript "use strict"; -var fs = require("fs"); -var java = require("java"); -var baseDir = "./target/dependency"; -var dependencies = fs.readdirSync(baseDir); +const fs = require("fs"); +const java = require("java"); +const baseDir = "./target/dependency"; +const dependencies = fs.readdirSync(baseDir); dependencies.forEach(function(dependency){ java.classpath.push(baseDir + "/" + dependency); @@ -164,8 +152,8 @@ and then in the consuming class write: ```javascript -var javaInit = require('./javaInit'); -var java = javaInit.getJavaInstance(); +const javaInit = require('./javaInit'); +const java = javaInit.getJavaInstance(); //your code goes here ``` @@ -175,11 +163,11 @@ var java = javaInit.getJavaInstance(); ## Quick Examples ```javascript -var java = require("java"); -java.classpath.push("commons-lang3-3.1.jar"); +const java = require("java"); +java.classpath.push("commons-lang3-3.19.0.jar"); java.classpath.push("commons-io.jar"); -var list1 = java.newInstanceSync("java.util.ArrayList"); +const list1 = java.newInstanceSync("java.util.ArrayList"); console.log(list1.sizeSync()); // 0 list1.addSync('item1'); console.log(list1.sizeSync()); // 1 @@ -190,8 +178,8 @@ java.newInstance("java.util.ArrayList", function(err, list2) { console.log(list2.toStringSync()); // [item1, item2] }); -var ArrayList = java.import('java.util.ArrayList'); -var list3 = new ArrayList(); +const ArrayList = java.import('java.util.ArrayList'); +const list3 = new ArrayList(); list3.addSync('item1'); list3.equalsSync(list1); // true ``` @@ -199,13 +187,13 @@ list3.equalsSync(list1); // true ### Create a char array ```javascript -var charArray = java.newArray("char", "hello world\n".split('')); +const charArray = java.newArray("char", "hello world\n".split('')); ``` ### Create a byte array ```javascript -var byteArray = java.newArray( +const byteArray = java.newArray( "byte", "hello world\n" .split('') @@ -220,7 +208,7 @@ a property off of the result called "longValue" which contains the un-truncated If you are calling a method that takes a long you must create it using [java.newInstance](#javaNewInstance). ```javascript -var javaLong = java.newInstanceSync("java.lang.Long", 5); +const javaLong = java.newInstanceSync("java.lang.Long", 5); console.log('Possibly truncated long value: ' + javaLong); console.log('Original long value (as a string): ' + javaLong.longValue); java.callStaticMethodSync("Test", "staticMethodThatTakesALong", javaLong); @@ -249,14 +237,13 @@ As of release 0.4.5 it became possible to create async methods that return promi Example: ```javascript -var java = require("java"); +const java = require("java"); java.asyncOptions = { asyncSuffix: undefined, // Don't generate node-style methods taking callbacks syncSuffix: "", // Sync methods use the base name(!!) promiseSuffix: "Promise", // Generate methods returning promises, using the suffix Promise. - promisify: require('util').promisify // Needs Node.js version 8 or greater, see comment below }; -java.classpath.push("commons-lang3-3.1.jar"); +java.classpath.push("commons-lang3-3.19.0.jar"); java.classpath.push("commons-io.jar"); java.import("java.util.ArrayList"); // see NOTE below @@ -271,15 +258,12 @@ java.newInstancePromise("java.util.ArrayList") * If you want the defacto standard behavior, simply don't set java.asyncOptions. * If you do provide asyncOptions, be aware that this module will not generate method variants of a given flavor if you don't provide a string value for the corresponding suffix (`asyncSuffix`, `syncSuffix`, `promiseSuffix`). In the example above, the application is configured to omit the method variants using node-style async callback functions. -* If you provide `asyncOptions.promiseSuffix` then you must also set `asyncOptions.promisify` to a function that *promisifies* a node-style async function. I.e. the provided function must take as input a function whose last argument is a node callback function, and it must return an equivalent promise-returning function. Several Promises/A+ libraries provide such functions, but it may be necessary to provide a wrapper function. See `testHelpers.js` for an example. -* For `promisify` implementation, if you are using Node.js version 8.0.0 or newer then `promisify: require('util').promisify` will work out of the box. If you need to support and older Node.js version then an implementation needs to be provided, for example, `promisify: require("when/node").lift` -* If you provide `asyncOptions.promisify` then you must provide a *non-empty* string for `asyncOptions.promiseSuffix`. * Either (but not both) `asyncSuffix` or `syncSuffix` can be the empty string. If you want the defacto standard behavior for no suffix on async methods, you must provide an empty string for `asyncSuffix`. * We've tested promises with five Promises/A+ implementations. See `testHelpers.js` for more information. * NOTE: Due to specifics of initialization order, the methods `java.newInstancePromise`, `java.callMethodPromise`, and `java.callStaticMethodPromise` are not available until the JVM has been created. You may need to call some other java method such as `java.import()` to finalize java initialization, or even better, the function `java.ensureJvm()`. ##### Special note about the exported module functions `newInstance`, `callMethod`, and `callStaticMethod`. -These methods come in both async and sync variants. If you provide the `promisify` and `promiseSuffix` attributes in asyncOptions then you'll also get the Promises/A+ variant for these three functions. However, if you change the defacto conventions for the `syncSuffix` (i.e. 'Sync') and/or `asyncSuffix` (i.e. '') it will not affect the naming for these three functions. I.e. no matter what you specify in asyncOptions, the async variants are named `newInstance`, `callMethod`, and `callStaticMethod`, and the sync variants are named `newInstanceSync`, `callMethodSync`, and `callStaticMethodSync`. +These methods come in both async and sync variants. If you provide the `promiseSuffix` attributes in asyncOptions then you'll also get the Promises/A+ variant for these three functions. However, if you change the defacto conventions for the `syncSuffix` (i.e. 'Sync') and/or `asyncSuffix` (i.e. '') it will not affect the naming for these three functions. I.e. no matter what you specify in asyncOptions, the async variants are named `newInstance`, `callMethod`, and `callStaticMethod`, and the sync variants are named `newInstanceSync`, `callMethodSync`, and `callStaticMethodSync`. ## Varargs support @@ -387,7 +371,6 @@ java.asyncOptions = { asyncSuffix: undefined, // Don't generate node-style methods taking callbacks syncSuffix: "", // Sync methods use the base name(!!) promiseSuffix: "Promise", // Generate methods returning promises, using the suffix Promise. - promisify: require('util').promisify // Needs Node.js version 8 or greater, see comment below ifReadOnlySuffix: "_alt" }; ``` @@ -395,7 +378,6 @@ java.asyncOptions = { * `asyncSuffix` Suffix for callback-based async method call signatures. * `syncSuffix` Suffix for synchronous method call signatures. * `promiseSuffix` Suffix for promise-based async method call signatures - * `promisify` Callback-to-promise transform implementation. From Node.js version 8 one can just use Node.js implementation: `promisify: require('util').promisify`. * `ifReadOnlySuffix` See [Static Member Name Conflicts](#staticMemberNameConflicts). See [Async Options](#asyncOptionsDetails) for details. @@ -414,13 +396,13 @@ __Arguments__ __Example__ - var Test = java.import('Test'); + const Test = java.import('Test'); Test.someStaticMethodSync(5); console.log(Test.someStaticField); - var value1 = Test.NestedEnum.Value1; + const value1 = Test.NestedEnum.Value1; - var test = new Test(); + const test = new Test(); list.instanceMethodSync('item1'); ## newInstance @@ -441,7 +423,7 @@ __Arguments__ __Example__ - var list = java.newInstanceSync("java.util.ArrayList"); + const list = java.newInstanceSync("java.util.ArrayList"); java.newInstance("java.util.ArrayList", function(err, list) { if(err) { console.error(err); return; } @@ -463,7 +445,7 @@ __Arguments__ __Example__ - var obj = java.newInstanceSync("my.package.SubClass"); + const obj = java.newInstanceSync("my.package.SubClass"); if(java.instanceOf(obj, "my.package.SuperClass")) { console.log("obj is an instance of SuperClass"); @@ -477,8 +459,7 @@ __Example__ **java.callStaticMethodSync(className, methodName, [args...]) : result** -Calls a static method on the specified class. If you are using the sync method an exception will be throw if an error occurs, -otherwise it will be the first argument in the callback. +Calls a static method on the specified class. If you are using the sync method an exception will be throw if an error occurs, otherwise it will be the first argument in the callback. __Arguments__ @@ -488,7 +469,7 @@ __Arguments__ __Example__ - var result = java.callStaticMethodSync("com.nearinfinty.MyClass", "doSomething", 42, "test"); + const result = java.callStaticMethodSync("com.nearinfinty.MyClass", "doSomething", 42, "test"); java.callStaticMethod("com.nearinfinty.MyClass", "doSomething", 42, "test", function(err, results) { if(err) { console.error(err); return; } @@ -514,11 +495,11 @@ __Arguments__ __Example__ - var instance = java.newInstanceSync("com.nearinfinty.MyClass"); + const instance = java.newInstanceSync("com.nearinfinty.MyClass"); - var result = java.callMethodSync("com.nearinfinty.MyClass", "doSomething", 42, "test"); + const result = java.callMethodSync("com.nearinfinty.MyClass", "doSomething", 42, "test"); - java.callMethodSync(instance, "doSomething", 42, "test", function(err, results) { + java.callMethod(instance, "doSomething", 42, "test", function(err, results) { if(err) { console.error(err); return; } // results from doSomething }); @@ -538,7 +519,7 @@ __Arguments__ __Example__ - var data = java.getStaticFieldValue("com.nearinfinty.MyClass", "data"); + const data = java.getStaticFieldValue("com.nearinfinty.MyClass", "data"); ## setStaticFieldValue @@ -573,7 +554,7 @@ __Arguments__ __Example__ - var newArray = java.newArray("java.lang.String", ["item1", "item2", "item3"]); + const newArray = java.newArray("java.lang.String", ["item1", "item2", "item3"]); ## newByte @@ -589,7 +570,7 @@ __Arguments__ __Example__ - var b = java.newByte(12); + const b = java.newByte(12); ## newShort @@ -605,7 +586,7 @@ __Arguments__ __Example__ - var s = java.newShort(12); + const s = java.newShort(12); ## newLong @@ -621,7 +602,7 @@ __Arguments__ __Example__ - var s = java.newLong(12); + const s = java.newLong(12); ## newChar @@ -637,7 +618,7 @@ __Arguments__ __Example__ - var ch = java.newChar('a'); + const ch = java.newChar('a'); ## newDouble @@ -653,7 +634,7 @@ __Arguments__ __Example__ - var d = java.newDouble(3.14); + const d = java.newDouble(3.14); ## newFloat @@ -669,7 +650,7 @@ __Arguments__ __Example__ - var f = java.newFloat(3.14); + const f = java.newFloat(3.14); ## newProxy @@ -689,14 +670,14 @@ __Arguments__ __Example__ - var myProxy = java.newProxy('java.lang.Runnable', { + const myProxy = java.newProxy('java.lang.Runnable', { run: function () { // This is actually run on the v8 thread and not the new java thread console.log("hello from thread"); } }); - var thread = java.newInstanceSync("java.lang.Thread", myProxy); + const thread = java.newInstanceSync("java.lang.Thread", myProxy); thread.start(); ## isJvmCreated @@ -755,7 +736,7 @@ __Arguments__ __Example__ - var list = java.newInstanceSync("java.util.ArrayList"); + const list = java.newInstanceSync("java.util.ArrayList"); list.addSync("item1"); list.add("item2", function(err, result) { if(err) { console.error(err); return; } @@ -774,9 +755,9 @@ field values. __Example__ - var list = java.newInstanceSync("com.nearinfinty.MyClass"); + const list = java.newInstanceSync("com.nearinfinty.MyClass"); list.data = "test"; - var data = list.data; + const data = list.data; ## Getting the Full Method Signature @@ -829,9 +810,9 @@ public class ShutdownHookHelper { Compile ShutdownHookHelper and then use it as follows. ```javascript -var java = require('./'); +const java = require('./'); java.classpath.push('.'); -var ShutdownHookHelper = java.import('ShutdownHookHelper'); +const ShutdownHookHelper = java.import('ShutdownHookHelper'); ShutdownHookHelper.setShutdownHookSync(java.newProxy('java.lang.Runnable', { run: function () { @@ -852,12 +833,12 @@ When you call a Java method through node-java, any arguments (V8/JavaScript obje The JavaScript object returned by `java.import(classname)` is a JavaScript constructor Function, implemented such that you can create instances of the Java class. For example: ```javascript -var Test = java.import('Test'); -var test = new Test(); +const Test = java.import('Test'); +const test = new Test(); Test.someStaticMethod(function(err, result) { ... }); -var value1 = Test.NestedEnum.Value1; +const value1 = Test.NestedEnum.Value1; ``` But JavaScript reserves a few property names of Function objects: `name`, `arguments`, and `caller`. If your class has public static members (either methods or fields) with these names, node-java is unable to create the necessary property to implement the class's API. For example, suppose your class `Test` implements a static method named `caller`, or has a `NestedEnum` with a value `name`: @@ -873,15 +854,15 @@ public class Test { In JavaScript, you would expect to be able to use those static members like this: ```javascript -var Test = java.import('Test'); +const Test = java.import('Test'); Test.caller(function(err, result) { ... }); // ERROR -var value = Test.NestedEnum.name; // ERROR +const value = Test.NestedEnum.name; // ERROR ``` Node-java can't create those properties, so the above code won't work. Instead, node-java appends a suffix to the name. The default suffix is simply an underscore `_`, but you can change the suffix using `asyncOptions`: ```javascript -var java = require('java'); +const java = require('java'); java.asyncOptions = { asyncSuffix: "", @@ -889,22 +870,22 @@ java.asyncOptions = { ifReadOnlySuffix: "_alt" }; -var Test = java.import('Test'); +const Test = java.import('Test'); Test.caller_alt(function(err, result) { ... }); // OK -var value = Test.NestedEnum.name_alt; // OK +const value = Test.NestedEnum.name_alt; // OK ``` # Troubleshooting ## Error: Cannot find module '../build/jvm_dll_path.json' -Either `postInstall.js` didn't run or there was a problem detecting java. Try running `postInstall.js` manually. +Either `./scripts/postInstall.js` didn't run or there was a problem detecting java. Try running `./scripts/postInstall.js` manually. ## Debugging npm install - node-gyp build --debug - gdb --args `which node` ./node_modules/.bin/nodeunit test + npx node-gyp build --debug + gdb --args "$(which node)" ./node_modules/.bin/vitest test ## License diff --git a/binding.gyp b/binding.gyp index 06117502..25fa488c 100644 --- a/binding.gyp +++ b/binding.gyp @@ -13,13 +13,13 @@ 'target_arch': 's390' }], ['OS=="win"', { - 'javahome%': '=8.0.0" + } + }, + "node_modules/@types/find-root": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/find-root/-/find-root-1.1.4.tgz", + "integrity": "sha512-2EXK/+gVhVgtt4JqThbEncORvpYJKzi9tQGmI3EkU2jTgMzQsrPm/hbd5xe5uPdeFzIW5gh2PRvvPjaUsI8vpg==", + "dev": true, + "license": "MIT" + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "license": "MIT" + }, + "node_modules/java": { + "resolved": "../..", + "link": true + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + } + } +} diff --git a/examples/lucene/package.json b/examples/lucene/package.json new file mode 100644 index 00000000..b436b24c --- /dev/null +++ b/examples/lucene/package.json @@ -0,0 +1,17 @@ +{ + "name": "java-example-lucene", + "private": true, + "scripts": { + "build": "tsc --build", + "build:watch": "tsc --build --watch", + "start": "node build/example.js" + }, + "dependencies": { + "find-root": "^1.1.0", + "java": "file:../.." + }, + "devDependencies": { + "@types/find-root": "^1.1.4", + "typescript": "^5.8.3" + } +} diff --git a/examples/lucene/tsconfig.json b/examples/lucene/tsconfig.json new file mode 100644 index 00000000..53c363e6 --- /dev/null +++ b/examples/lucene/tsconfig.json @@ -0,0 +1,113 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "libReplacement": true, /* Enable lib replacement. */ + // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + // "rewriteRelativeImportExtensions": true, /* Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files. */ + // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ + // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ + // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "noUncheckedSideEffectImports": true, /* Check side effect imports. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./build", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ + // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ + // "erasableSyntaxOnly": true, /* Do not allow runtime constructs that are not part of ECMAScript. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "strictBuiltinIteratorReturn": true, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": false /* Skip type checking all .d.ts files. */ + } +} diff --git a/examples/mixJavaAndNode/runMyClass.js b/examples/mixJavaAndNode/runMyClass.js index d3fb834f..8c285c94 100755 --- a/examples/mixJavaAndNode/runMyClass.js +++ b/examples/mixJavaAndNode/runMyClass.js @@ -1,11 +1,9 @@ #!/usr/bin/env node -var java = require("../../"); +const java = require("../../"); java.classpath.push("./src"); -var MyClass = java.import("com.nearinfinity.nodeJava.MyClass"); +const MyClass = java.import("com.nearinfinity.nodeJava.MyClass"); -var result = MyClass.addNumbersSync(1, 2); +const result = MyClass.addNumbersSync(1, 2); console.log(result); - - diff --git a/findJavaHome.js b/findJavaHome.js deleted file mode 100644 index a4b1c821..00000000 --- a/findJavaHome.js +++ /dev/null @@ -1,7 +0,0 @@ -require('find-java-home')(function(err, home){ - if (err || !home) { - if (!err) err = Error('Unable to determine Java home location'); - process.exit(1); - } - process.stdout.write(home); -}); diff --git a/index.js b/index.js index f9e0d85a..73442826 100644 --- a/index.js +++ b/index.js @@ -1,2 +1 @@ - -module.exports = require("./lib/nodeJavaBridge"); +module.exports = require("./src-node/nodeJavaBridge"); diff --git a/jarjar-1.4.jar b/jarjar-1.4.jar deleted file mode 100644 index 68b9db9a..00000000 Binary files a/jarjar-1.4.jar and /dev/null differ diff --git a/jarjar.rule b/jarjar.rule deleted file mode 100644 index 35923389..00000000 --- a/jarjar.rule +++ /dev/null @@ -1 +0,0 @@ -rule org.apache.commons.lang3.** com.nearinfinity.org.apache.commons.lang3.@1 diff --git a/java.d.ts b/java.d.ts new file mode 100644 index 00000000..c2248377 --- /dev/null +++ b/java.d.ts @@ -0,0 +1,343 @@ +/* eslint-disable @typescript-eslint/no-unsafe-function-type */ +/* eslint-disable @typescript-eslint/no-explicit-any */ +declare const NodeJavaCore: NodeJavaCore.Java; +export = NodeJavaCore; + +declare namespace NodeJavaCore { + type JavaObject = any; + type JavaError = Error & { cause?: JavaObject }; + + export interface Callback { + (err?: Error, result?: T): void; + } + + export interface JavaCallback { + (err?: JavaError, result?: T): void; + } + + interface AsyncOptions { + /** + * Suffix for synchronous method call signatures. + */ + syncSuffix: string; + + /** + * Suffix for callback-based async method call signatures. + */ + asyncSuffix?: string | undefined; + + /** + * Suffix for promise-based async method call signatures + */ + promiseSuffix?: string | undefined; + + /** + * The JavaScript object returned by `java.import(classname)` is a JavaScript constructor + * Function, implemented such that you can create instances of the Java class. For example: + */ + ifReadOnlySuffix?: string | undefined; + } + + interface ProxyFunctions { + [index: string]: Function; + } + + interface Java { + /** + * Array of paths or jars to pass to the creation of the JVM. + * + * All items must be added to the classpath before calling any other node-java methods. + * + * @example + * java.classpath.push('commons.io.jar'); + * java.classpath.push('src'); + */ + classpath: string[]; + + /** + * Array of options to pass to the creation of the JVM. + * + * All items must be added to the options before calling any other node-java methods. + * + * @example + * java.options.push('-Djava.awt.headless=true'); + * java.options.push('-Xmx1024m'); + */ + options: string[]; + + /** + * @see AsyncOptions + */ + asyncOptions: AsyncOptions; + + /** + * Location of nodejavabridge_bindings.node + */ + nativeBindingLocation: string; + + /** + * Calls a method on the specified instance. If you are using the sync method an exception + * will be throw if an error occurs, otherwise it will be the first argument in the callback. + * + * @param instance An instance of the class from newInstance. + * @param methodName The name of the method to call. The method name can include the full + * signature (see [Getting the full method signature](README.md#getFullMethodSignature)). + * @param args The arguments to pass to the method, the last argument will be the callback to the function + * + * @example + * const instance = java.newInstanceSync("com.nearinfinty.MyClass"); + * java.callMethod(instance, "doSomething", 42, "test", function(err, results) { + * if(err) { console.error(err); return; } + * // results from doSomething + * }); + */ + callMethod(instance: JavaObject, methodName: string, ...args: any[]): void; + + /** + * Calls a method on the specified instance. If you are using the sync method an exception + * will be throw if an error occurs, otherwise it will be the first argument in the callback. + * + * @param instance An instance of the class from newInstance. + * @param methodName The name of the method to call. The method name can include the full + * signature (see [Getting the full method signature](README.md#getFullMethodSignature)). + * @param args The arguments to pass to the method + * @returns The result of the method call + * + * @example + * const instance = java.newInstanceSync("com.nearinfinty.MyClass"); + * const result = java.callMethodSync("com.nearinfinty.MyClass", "doSomething", 42, "test"); + */ + callMethodSync(instance: JavaObject, methodName: string, ...args: any[]): any; + + /** + * Calls a static method on the specified class. If you are using the sync method an exception will be + * throw if an error occurs, otherwise it will be the first argument in the callback. + * + * @param className The name of the class to call the method on. Separate nested classes + * using `'$'` (eg. `com.nearinfinty.MyClass$NestedClass`). + * @param methodName The name of the method to call. The method name can include the full + * signature (see [Getting the full method signature](README.md#getFullMethodSignature)). + * @param args The arguments to pass to the method, the last argument will be the callback to the function + */ + callStaticMethod(className: string, methodName: string, ...args: any[]): void; + + /** + * Calls a static method on the specified class. If you are using the sync method an exception will be + * throw if an error occurs, otherwise it will be the first argument in the callback. + * + * @param className The name of the class to call the method on. Separate nested classes + * using `'$'` (eg. `com.nearinfinty.MyClass$NestedClass`). + * @param methodName The name of the method to call. The method name can include the full + * signature (see [Getting the full method signature](README.md#getFullMethodSignature)). + * @param args The arguments to pass to the method + * @returns The result of the method call + */ + callStaticMethodSync(className: string, methodName: string, ...args: any[]): any; + + /** + * Finds the class with the specified binary name. This method should be overridden by class loader + * implementations that follow the delegation model for loading classes, and will be invoked by the + * loadClass method after checking the parent class loader for the requested class. The default + * implementation throws a ClassNotFoundException. + * + * @param className The binary name of the class + * @returns The resulting Class object + */ + findClassSync(className: string): JavaObject; + + /** + * Gets a static field value from the specified class. + * + * @param className The name of the class to get the value from. Separate nested classes + * using `'$'` (eg. `com.nearinfinty.MyClass$NestedClass`). + * @param fieldName The name of the field to get the value from. + * @returns The valid of the static field + */ + getStaticFieldValue(className: string, fieldName: string): any; + + /** + * Sets a static field value on the specified class. + * + * @param className The name of the class to set the value on. Separate nested classes + * using `'$'` (eg. `com.nearinfinty.MyClass$NestedClass`). + * @param fieldName The name of the field to set the value on. + * @param newValue The new value to assign to the field. + */ + setStaticFieldValue(className: string, fieldName: string, newValue: any): void; + + /** + * Determines of a javaObject is an instance of a class. + * + * @param javaObject Instance of a java object returned from a method or from newInstance. + * @param className A string class name. + * + * @example + * const obj = java.newInstanceSync("my.package.SubClass"); + * if(java.instanceOf(obj, "my.package.SuperClass")) { + * console.log("obj is an instance of SuperClass"); + * } + */ + instanceOf(javaObject: JavaObject, className: string): boolean; + + /** + * Register that a client wants to be called back immediately before and/or immediately + * after the JVM is created. If used, this function must be called before the JVM has been + * created. The before function is typically used to add to the classpath. The function may + * execute asynchronous operations (such as a async glob function). The after function is + * sometimes useful for doing one-time initialization that requires the JVM to first be + * initialized. If either function is unnecessary, use `null` or `undefined`. See also + * `registerClientP` and `ensureJvm`. See the unit tests in `testAsyncOptions` for examples. + */ + registerClient( + before: ((cb: Callback) => void) | undefined | null, + after?: (cb: Callback) => void + ): void; + + /** + * Register that a client wants to be called back immediately before and/or immediately + * after the JVM is created. If used, this function must be called before the JVM has been + * created. The before function is typically used to add to the classpath. The function may + * execute asynchronous operations (such as a async glob function). The after function is + * sometimes useful for doing one-time initialization that requires the JVM to first be + * initialized. If either function is unnecessary, use `null` or `undefined`. See also + * `registerClientP` and `ensureJvm`. See the unit tests in `testAsyncOptions` for examples. + */ + registerClientP(beforeP: (() => Promise) | undefined | null, afterP?: () => Promise): void; + + /** + * If the JVM has not yet been created, execute the full JVM initialization process, then + * call callback function when initialization is complete. If the JVM has been created, just + * call the callback. Note that the full initialization process includes: 1) executing all + * registered client *before* hooks, 2) creating the JVM, then 3) executing all registered + * client *after* hooks. + */ + ensureJvm(done: Callback): void; + + /** + * If the JVM has not yet been created, execute the full JVM initialization process, then + * call callback function when initialization is complete. If the JVM has been created, just + * call the callback. Note that the full initialization process includes: 1) executing all + * registered client *before* hooks, 2) creating the JVM, then 3) executing all registered + * client *after* hooks. + */ + ensureJvm(): Promise; + + /** + * Returns true if the JVM has been created. The JVM can only be created once. + */ + isJvmCreated(): boolean; + + /** + * Creates a new java byte. This is needed because JavaScript does not have the concept of a byte. + */ + newByte(val: number): JavaObject; + + /** + * Creates a new java short. This is needed because JavaScript does not have the concept of a short. + */ + newShort(val: number): JavaObject; + + /** + * Creates a new java long. This is needed because JavaScript does not have the concept of a long. + */ + newLong(val: number): JavaObject; + + /** + * Creates a new java char. This is needed because JavaScript does not have the concept of a char. + */ + newChar(val: string | number): JavaObject; + + /** + * Creates a new java float. This is needed to force JavaScript's number to a float to call some methods. + */ + newFloat(val: number): JavaObject; + + /** + * Creates a new java double. This is needed to force JavaScript's number to a double to call some methods. + */ + newDouble(val: number): JavaObject; + + /** + * Loads the class given by className such that it acts and feels like a JavaScript object. + * + * @param className The name of the class to create. Separate nested classes + * using `'$'` (eg. `com.nearinfinty.MyClass$NestedClass`). + * + * @example + * const Test = java.import('Test'); + * Test.someStaticMethodSync(5); + * console.log(Test.someStaticField); + * + * const value1 = Test.NestedEnum.Value1; + * + * const test = new Test(); + * list.instanceMethodSync('item1'); + */ + import(className: string): JavaObject; + + /** + * Creates an instance of the specified class. If you are using the sync method an exception will + * be throw if an error occurs, otherwise it will be the first argument in the callback. + * + * @param className The name of the class to create. Separate nested classes + * using `'$'` (eg. `com.nearinfinty.MyClass$NestedClass`). + * @param args Arguments to pass to the constructor, the last argument is a callback function + */ + newInstance(className: string, ...args: any[]): void; + + /** + * Creates an instance of the specified class. If you are using the sync method an exception will + * be throw if an error occurs, otherwise it will be the first argument in the callback. + * + * @param className The name of the class to create. Separate nested classes + * using `'$'` (eg. `com.nearinfinty.MyClass$NestedClass`). + * @param args Arguments to pass to the constructor + */ + newInstanceSync(className: string, ...args: any[]): JavaObject; + + /** + * Creates a new java array of given glass type. To create array of primitive types + * like `char`, `byte`, etc, pass the primitive typename + * (eg. `java.newArray("char", "hello world\n".split(''))`). + * + * @param className The name of the type of array elements. Separate nested classes + * using `'$'` (eg. `com.nearinfinty.MyClass$NestedClass`). + * @param arg A JavaScript array of values to assign to the java array. + */ + newArray(className: string, arg: any[]): JavaObject; + + /** + * Get the current class loader + */ + getClassLoader(): JavaObject; + + /** + * Creates a new java Proxy for the given interface. Functions passed in will run on the v8 + * main thread and not a new thread. + * + * The returned object has a method unref() which you can use to free the object for garbage + * collection. + * + * @param interfaceName The name of the interface to proxy. Separate nested classes + * using `'$'` (eg. `com.nearinfinty.MyClass$NestedClass`). + * @param functions A hash of functions matching the function in the interface. + * + * @example + * const myProxy = java.newProxy('java.lang.Runnable', { + * run: function () { + * // This is actually run on the v8 thread and not the new java thread + * console.log("hello from thread"); + * } + * }); + * + * const thread = java.newInstanceSync("java.lang.Thread", myProxy); + * thread.start(); + */ + newProxy(interfaceName: string, functions: ProxyFunctions): JavaObject; + + /** + * Stops the running event loop + */ + stop(): void; + } +} diff --git a/lib/nodeJavaBridge.js b/lib/nodeJavaBridge.js deleted file mode 100644 index 560b69e0..00000000 --- a/lib/nodeJavaBridge.js +++ /dev/null @@ -1,317 +0,0 @@ -'use strict'; - -process.env.PATH += require('../build/jvm_dll_path.json'); - -var async = require('async'); -var path = require('path'); -var fs = require('fs'); -var binaryPath = null; -try { - if(fs.statSync && fs.statSync(path.join(__dirname, "../build/Debug/nodejavabridge_bindings.node")).isFile()) { - binaryPath = path.resolve(path.join(__dirname, "../build/Debug/nodejavabridge_bindings.node")); - console.log('****** NODE-JAVA RUNNING IN DEBUG MODE ******'); - } -} catch(e) { - // do nothing fs.statSync just couldn't find the file -} -if (!binaryPath) { - binaryPath = path.resolve(path.join(__dirname, "../build/Release/nodejavabridge_bindings.node")); -} -var bindings = require(binaryPath); - -var java = module.exports = new bindings.Java(); -java.classpath.push(path.resolve(__dirname, "../commons-lang3-node-java.jar")); -java.classpath.push(path.resolve(__dirname, __dirname, "../src-java")); -java.classpath.pushDir = function(dir) { - fs.readdirSync(dir).forEach(function(file) { - java.classpath.push(path.resolve(dir, file)); - }); -}; -java.nativeBindingLocation = binaryPath; - -var callStaticMethod = java.callStaticMethod; -var callStaticMethodSync = java.callStaticMethodSync; -var newInstanceSync = java.newInstanceSync; - -var syncSuffix = undefined; -var asyncSuffix = undefined; -var ifReadOnlySuffix = '_'; - -var SyncCall = function(obj, method) { - if (syncSuffix === undefined) - throw new Error('Sync call made before jvm created'); - var syncMethodName = method + syncSuffix; - if (syncMethodName in obj) - return obj[syncMethodName].bind(obj); - else - throw new Error('Sync method not found:' + syncMethodName); -} - -java.isJvmCreated = function() { - return typeof java.onJvmCreated !== 'function'; -} - -var clients = []; - -// We provide two methods for 'clients' of node-java to 'register' their use of java. -// By registering, a client gets the opportunity to be called asynchronously just before the JVM is created, -// and just after the JVM is created. The before hook function will typically be used to add to java.classpath. -// The function may peform asynchronous operations, such as async [glob](https://github.com/isaacs/node-glob) -// resolutions of wild-carded file system paths, and then notify when it has finished via either calling -// a node-style callback function, or by resolving a promise. - -// A client can register function hooks to be called before and after the JVM is created. -// If the client doesn't need to be called back for either function, it can pass null or undefined. -// Both before and after here are assumed to be functions that accept one argument that is a node-callback function. -java.registerClient = function(before, after) { - var before_, after_; - if (java.isJvmCreated()) { - throw new Error('java.registerClient() called after JVM already created.'); - } - before_ = (before && before.length === 0) ? - function(cb) { before(); cb(); } : - before; - - after_ = (after && after.length === 0) ? - function(cb) { after(); cb(); } : - after; - - clients.push({before: before_, after: after_}); -} - -// A client can register function hooks to be called before and after the JVM is created. -// If the client doesn't need to be called back for either function, it can pass null or undefined. -// Both before and after here are assumed to be functions that return Promises/A+ `thenable` objects. -java.registerClientP = function(beforeP, afterP) { - if (java.isJvmCreated()) { - throw new Error('java.registerClient() called after JVM already created.'); - } - clients.push({beforeP: beforeP, afterP: afterP}); -} - -function runBeforeHooks(done) { - function iterator(client, cb) { - try { - if (client.before) { - client.before(cb); - } - else if (client.beforeP) { - client.beforeP().then(function(ignored) { cb(); }, function(err) { cb(err); }); - } - else { - cb(); - } - } - catch (err) { - cb(err); - } - } - async.each(clients, iterator, done); -} - -function createJVMAsync(callback) { - var ignore = java.newLong(0); // called just for the side effect that it will create the JVM - callback(); -} - -function runAfterHooks(done) { - function iterator(client, cb) { - try { - if (client.after) { - client.after(cb); - } - else if (client.afterP) { - client.afterP().then(function(ignored) { cb(); }, function(err) { cb(err); }); - } - else { - cb(); - } - } - catch (err) { - cb(err); - } - } - async.each(clients, iterator, done); -} - -function initializeAll(done) { - async.series([runBeforeHooks, createJVMAsync, runAfterHooks], done); -} - -// This function ensures that the JVM has been launched, asynchronously. The application can be notified -// when the JVM is fully created via either a node callback function, or via a promise. -// If the parameter `callback` is provided, it is assume be a node callback function. -// If the parameter is not provided, and java.asyncOptions.promisify has been specified, -// then this function will return a promise, by promisifying itself and then calling that -// promisified function. -// This function may be called multiple times -- the 2nd and subsequent calls are no-ops. -// However, once this method has been called (or the JVM is launched as a side effect of calling other java -// methods), then clients can no longer use the registerClient API. -java.ensureJvm = function(callback) { - - // First see if the promise-style API should be used. - // This must be done first in order to ensure the proper API is used. - if (typeof callback === 'undefined' && java.asyncOptions && typeof java.asyncOptions.promisify === 'function') { - // Create a promisified version of this function. - var launchJvmPromise = java.asyncOptions.promisify(java.ensureJvm.bind(java)); - // Call the promisified function, returning its result, which should be a promise. - return launchJvmPromise(); - } - - // If we get here, callback must be a node-style callback function. If not, throw an error. - else if (typeof callback !== 'function') { - throw new Error('java.launchJvm(cb) requires its one argument to be a callback function.'); - } - - // Now check if the JVM has already been created. If so, we assume that the jvm was already successfully - // launched, and we can just implement idempotent behavior, i.e. silently notify that the JVM has been created. - else if (java.isJvmCreated()) { - return setImmediate(callback); - } - - // Finally, queue the initializeAll function. - else { - return setImmediate(initializeAll, callback); - } -} - -java.onJvmCreated = function() { - if (java.asyncOptions) { - syncSuffix = java.asyncOptions.syncSuffix; - asyncSuffix = java.asyncOptions.asyncSuffix; - if (typeof syncSuffix !== 'string') { - throw new Error('In asyncOptions, syncSuffix must be defined and must a string'); - } - var promiseSuffix = java.asyncOptions.promiseSuffix; - var promisify = java.asyncOptions.promisify; - if (typeof promiseSuffix === 'string' && typeof promisify === 'function') { - var methods = ['newInstance', 'callMethod', 'callStaticMethod']; - methods.forEach(function (name) { - java[name + promiseSuffix] = promisify(java[name]); - }); - } else if (typeof promiseSuffix === 'undefined' && typeof promisify === 'undefined') { - // no promises - } else { - throw new Error('In asyncOptions, if either promiseSuffix or promisify is defined, both most be.'); - } - - if (typeof java.asyncOptions.ifReadOnlySuffix === 'string' && java.asyncOptions.ifReadOnlySuffix !== '') { - ifReadOnlySuffix = java.asyncOptions.ifReadOnlySuffix; - } - } else { - syncSuffix = 'Sync'; - asyncSuffix = ''; - } -} - -var MODIFIER_PUBLIC = 1; -var MODIFIER_STATIC = 8; - -function isWritable(prop) { - // If the property has no descriptor, or wasn't explicitly marked as not writable or not configurable, assume it is. - // We check both desc.writable and desc.configurable, since checking desc.writable alone is not sufficient - // (e.g. for either .caller or .arguments). - // It may be that checking desc.configurable is sufficient, but the specification doesn't make this definitive, - // and there is no harm in checking both. - if (prop === 'caller' || prop === 'arguments') { return false; } - - var desc = Object.getOwnPropertyDescriptor(function() {}, prop) || {}; - return desc.writable !== false && desc.configurable !== false; -} - -function usableName(name) { - if (!isWritable(name)) { - name = name + ifReadOnlySuffix; - } - return name; -} - -java.import = function(name) { - var clazz = java.findClassSync(name); // TODO: change to Class.forName when classloader issue is resolved. - var result = function javaClassConstructorProxy() { - var args = [name]; - for (var i = 0; i < arguments.length; i++) { - args.push(arguments[i]); - } - return newInstanceSync.apply(java, args); - }; - var i; - - result.class = clazz; - - // copy static fields - var fields = SyncCall(clazz, 'getDeclaredFields')(); - for (i = 0; i < fields.length; i++) { - var modifiers = SyncCall(fields[i], 'getModifiers')(); - if (((modifiers & MODIFIER_PUBLIC) === MODIFIER_PUBLIC) - && ((modifiers & MODIFIER_STATIC) === MODIFIER_STATIC)) { - var fieldName = SyncCall(fields[i], 'getName')(); - var jsfieldName = usableName(fieldName); - result.__defineGetter__(jsfieldName, function(name, fieldName) { - return java.getStaticFieldValue(name, fieldName); - }.bind(this, name, fieldName)); - result.__defineSetter__(jsfieldName, function(name, fieldName, val) { - java.setStaticFieldValue(name, fieldName, val); - }.bind(this, name, fieldName)); - } - } - - var promisify = undefined; - var promiseSuffix; - if (java.asyncOptions && java.asyncOptions.promisify) { - promisify = java.asyncOptions.promisify; - promiseSuffix = java.asyncOptions.promiseSuffix; - } - - // copy static methods - var methods = SyncCall(clazz, 'getDeclaredMethods')(); - for (i = 0; i < methods.length; i++) { - var modifiers = SyncCall(methods[i], 'getModifiers')(); - if (((modifiers & MODIFIER_PUBLIC) === MODIFIER_PUBLIC) - && ((modifiers & MODIFIER_STATIC) === MODIFIER_STATIC)) { - var methodName = SyncCall(methods[i], 'getName')(); - - if (typeof syncSuffix === 'string') { - var syncName = usableName(methodName + syncSuffix); - result[syncName] = callStaticMethodSync.bind(java, name, methodName); - } - - if (typeof asyncSuffix === 'string') { - var asyncName = usableName(methodName + asyncSuffix); - result[asyncName] = callStaticMethod.bind(java, name, methodName); - } - - if (promisify && typeof promiseSuffix === 'string') { - var promiseName = usableName(methodName + promiseSuffix); - result[promiseName] = promisify(callStaticMethod.bind(java, name, methodName)); - } - } - } - - // copy static classes/enums - var classes = SyncCall(clazz, 'getDeclaredClasses')(); - for (i = 0; i < classes.length; i++) { - var modifiers = SyncCall(classes[i], 'getModifiers')(); - if (((modifiers & MODIFIER_PUBLIC) === MODIFIER_PUBLIC) - && ((modifiers & MODIFIER_STATIC) === MODIFIER_STATIC)) { - var className = SyncCall(classes[i], 'getName')(); - var simpleName = SyncCall(classes[i], 'getSimpleName')(); - Object.defineProperty(result, simpleName, { - get: function(result, simpleName, className) { - var c = java.import(className); - - // memoize the import - var d = Object.getOwnPropertyDescriptor(result, simpleName); - d.get = function(c) { return c; }.bind(null, c); - Object.defineProperty(result, simpleName, d); - - return c; - }.bind(this, result, simpleName, className), - enumerable: true, - configurable: true - }); - } - } - - return result; -}; diff --git a/package-lock.json b/package-lock.json index 497e5991..fb5faeba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,1070 +1,1657 @@ { "name": "java", - "version": "0.14.0", + "version": "0.18.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "java", - "version": "0.14.0", + "version": "0.18.0", "hasInstallScript": true, "license": "MIT", "dependencies": { - "async": "^3.2.5", "find-java-home": "^2.0.0", - "glob": "^10.3.10", - "nan": "^2.18.0", - "node-gyp": "^10.0.1" + "glob": "^11.0.3", + "nan": "^2.23.0", + "node-gyp": "^11.5.0" }, "devDependencies": { - "chalk": "2.4.1", - "nodeunit": "0.11.3", - "when": "3.7.8" - }, + "@eslint/js": "^9.37.0", + "@types/find-root": "^1.1.4", + "@types/node": "^24.8.0", + "chalk": "^5.6.2", + "eslint": "^9.37.0", + "find-root": "^1.1.0", + "globals": "^16.4.0", + "prettier": "^3.6.2", + "typescript": "^5.9.3", + "typescript-eslint": "^8.46.1", + "vitest": "^3.2.4" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.11.tgz", + "integrity": "sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=7.0.0" + "node": ">=18" } }, - "node_modules/@babel/code-frame": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.4.tgz", - "integrity": "sha512-r1IONyb6Ia+jYR2vvIDhdWdlTGhqbBoFqLTQidzZ4kepUFH15ejXvFHxCVbtl7BOXIudsIubf4E81xeA3h3IXA==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, + "license": "Apache-2.0", "engines": { - "node": ">=4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@babel/generator": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.4.tgz", - "integrity": "sha512-esuS49Cga3HcThFNebGhlgsrVLkvhqvYDTzgjfFFlHJcIfLe5jFmRRfCQ1KuBfc4Jrtn3ndLgKWAKjBE+IraYQ==", + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, - "dependencies": { - "@babel/types": "^7.23.4", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "node_modules/@eslint/config-helpers": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.0.tgz", + "integrity": "sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" + "@eslint/core": "^0.16.0" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "node_modules/@eslint/core": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.16.0.tgz", + "integrity": "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/types": "^7.22.5" + "@types/json-schema": "^7.0.15" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.5" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "node_modules/@eslint/js": { + "version": "9.37.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.37.0.tgz", + "integrity": "sha512-jaS+NJ+hximswBG6pjNX0uEJZkrT0zwpVi3BA3vX22aFGjJjmgSTSmPpZCRKmoBL5VY/M6p0xsSJx7rk7sy5gg==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" } }, - "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - }, + "license": "Apache-2.0", "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/@eslint/plugin-kit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.0.tgz", + "integrity": "sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "@eslint/core": "^0.16.0", + "levn": "^0.4.1" }, "engines": { - "node": ">=4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.4.tgz", - "integrity": "sha512-vf3Xna6UEprW+7t6EtOmFpHNAuxw3xqPZghy+brsnusscJRW5BMUzzHZc5ICjULee81WeUV2jjakG09MDglJXQ==", + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, + "license": "Apache-2.0", "engines": { - "node": ">=6.0.0" + "node": ">=18.18.0" } }, - "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.18.0" } }, - "node_modules/@babel/traverse": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.4.tgz", - "integrity": "sha512-IYM8wSUwunWTB6tFC2dkKZhxbIjHoWemdK+3f8/wq8aKhbUscxD5MX72ubd90fxvFknaLPeGw5ycU84V1obHJg==", + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", "dev": true, - "dependencies": { - "@babel/code-frame": "^7.23.4", - "@babel/generator": "^7.23.4", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.4", - "@babel/types": "^7.23.4", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, + "license": "Apache-2.0", "engines": { - "node": ">=6.9.0" + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@babel/types": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.4.tgz", - "integrity": "sha512-7uIFwVYpoplT5jp/kVv6EF93VaJ8H+Yn5IczYiaAi98ajzjfoZfslet/e0sLh+wVBjb2qqIut1b0S26VSafsSQ==", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - }, + "license": "Apache-2.0", "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + "node": ">=12.22" }, - "engines": { - "node": ">=12" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=12" + "node": ">=18.18" }, "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": "20 || >=22" } }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", + "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "license": "MIT", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "@isaacs/balanced-match": "^4.0.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "20 || >=22" } }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", "dependencies": { - "ansi-regex": "^6.0.1" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" + "minipass": "^7.0.4" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">=18.0.0" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } + "license": "MIT" }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, "engines": { - "node": ">=6.0.0" + "node": ">= 8" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6.0.0" + "node": ">= 8" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" } }, "node_modules/@npmcli/agent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.0.tgz", - "integrity": "sha512-2yThA1Es98orMkpSLVqlDZAMPK3jHJhifP2gnNUdk1754uZ8yI5c+ulCoVG+WlntQA6MzhrURMXjSd9Z7dJ2/Q==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-3.0.0.tgz", + "integrity": "sha512-S79NdEgDQd/NGCay6TCoVzXSj74skRZIKJcpJjC5lOq34SZzyI6MqtiiWoiVWoVrTcGjNeC4ipbh1VIHlpfF5Q==", + "license": "ISC", "dependencies": { "agent-base": "^7.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.1", "lru-cache": "^10.0.1", - "socks-proxy-agent": "^8.0.1" + "socks-proxy-agent": "^8.0.3" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/agent/node_modules/lru-cache": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", - "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", - "engines": { - "node": "14 || >=16.14" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" }, "node_modules/@npmcli/fs": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", - "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-4.0.0.tgz", + "integrity": "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==", + "license": "ISC", "dependencies": { "semver": "^7.3.5" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", "optional": true, "engines": { "node": ">=14" } }, - "node_modules/abbrev": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", - "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.4.tgz", + "integrity": "sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "node_modules/@types/chai": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", + "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", + "dev": true, + "license": "MIT", "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" + "@types/deep-eql": "*" } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/find-root": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/find-root/-/find-root-1.1.4.tgz", + "integrity": "sha512-2EXK/+gVhVgtt4JqThbEncORvpYJKzi9tQGmI3EkU2jTgMzQsrPm/hbd5xe5uPdeFzIW5gh2PRvvPjaUsI8vpg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.8.0.tgz", + "integrity": "sha512-5x08bUtU8hfboMTrJ7mEO4CpepS9yBwAqcL52y86SWNmbPX8LVbNs3EP4cNrIZgdjk2NAlP2ahNihozpoZIxSg==", + "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" + "undici-types": "~7.14.0" } }, - "node_modules/ajv": { - "version": "6.12.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", - "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.1.tgz", + "integrity": "sha512-rUsLh8PXmBjdiPY+Emjz9NX2yHvhS11v0SR6xNJkm5GM1MO9ea/1GoDKlHHZGrOJclL/cZ2i/vRUYVtjRhrHVQ==", "dev": true, + "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.46.1", + "@typescript-eslint/type-utils": "8.46.1", + "@typescript-eslint/utils": "8.46.1", + "@typescript-eslint/visitor-keys": "8.46.1", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.46.1", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 4" } }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/@typescript-eslint/parser": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.1.tgz", + "integrity": "sha512-6JSSaBZmsKvEkbRUkf7Zj7dru/8ZCrJxAqArcLaVMee5907JdtEbKGsZ7zNiIm/UAkpGUkaSMZEXShnN2D1HZA==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "color-convert": "^1.9.0" + "@typescript-eslint/scope-manager": "8.46.1", + "@typescript-eslint/types": "8.46.1", + "@typescript-eslint/typescript-estree": "8.46.1", + "@typescript-eslint/visitor-keys": "8.46.1", + "debug": "^4.3.4" }, "engines": { - "node": ">=4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/append-transform": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", - "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", + "node_modules/@typescript-eslint/project-service": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.1.tgz", + "integrity": "sha512-FOIaFVMHzRskXr5J4Jp8lFVV0gz5ngv3RHmn+E4HYxSJ3DgDzU7fVI1/M7Ijh1zf6S7HIoaIOtln1H5y8V+9Zg==", "dev": true, + "license": "MIT", "dependencies": { - "default-require-extensions": "^2.0.0" + "@typescript-eslint/tsconfig-utils": "^8.46.1", + "@typescript-eslint/types": "^8.46.1", + "debug": "^4.3.4" }, "engines": { - "node": ">=4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.1.tgz", + "integrity": "sha512-weL9Gg3/5F0pVQKiF8eOXFZp8emqWzZsOJuWRUNtHT+UNV2xSJegmpCNQHy37aEQIbToTq7RHKhWvOsmbM680A==", "dev": true, + "license": "MIT", "dependencies": { - "sprintf-js": "~1.0.2" + "@typescript-eslint/types": "8.46.1", + "@typescript-eslint/visitor-keys": "8.46.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.1.tgz", + "integrity": "sha512-X88+J/CwFvlJB+mK09VFqx5FE4H5cXD+H/Bdza2aEWkSb8hnWIQorNcscRl4IEo1Cz9VI/+/r/jnGWkbWPx54g==", "dev": true, - "dependencies": { - "safer-buffer": "~2.1.0" + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "node_modules/@typescript-eslint/type-utils": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.1.tgz", + "integrity": "sha512-+BlmiHIiqufBxkVnOtFwjah/vrkF4MtKKvpXrKSPLCkCtAp8H01/VV43sfqA98Od7nJpDcFnkwgyfQbOG0AMvw==", "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.46.1", + "@typescript-eslint/typescript-estree": "8.46.1", + "@typescript-eslint/utils": "8.46.1", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, "engines": { - "node": ">=0.8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/async": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", - "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "node_modules/@typescript-eslint/types": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.1.tgz", + "integrity": "sha512-C+soprGBHwWBdkDpbaRC4paGBrkIXxVlNohadL5o0kfhsXqOC6GYH2S/Obmig+I0HTDl8wMaRySwrfrXVP8/pQ==", "dev": true, + "license": "MIT", "engines": { - "node": "*" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/aws4": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", - "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==", - "dev": true - }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.1.tgz", + "integrity": "sha512-uIifjT4s8cQKFQ8ZBXXyoUODtRoAd7F7+G8MKmtzj17+1UbdzFl52AzRyZRyKqPHhgzvXunnSckVu36flGy8cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.46.1", + "@typescript-eslint/tsconfig-utils": "8.46.1", + "@typescript-eslint/types": "8.46.1", + "@typescript-eslint/visitor-keys": "8.46.1", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, + "license": "MIT", "dependencies": { - "tweetnacl": "^0.14.3" + "balanced-match": "^1.0.0" } }, - "node_modules/bind-obj-methods": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bind-obj-methods/-/bind-obj-methods-2.0.0.tgz", - "integrity": "sha512-3/qRXczDi2Cdbz6jE+W3IflJOutRVica8frpBn14de1mBOkzDo+6tY33kNhvkw54Kn3PzRRD2VnGbGPcTAk4sw==", - "dev": true + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.1.tgz", + "integrity": "sha512-vkYUy6LdZS7q1v/Gxb2Zs7zziuXN0wxqsetJdeZdRe/f5dwJFglmuvZBfTUivCtjH725C1jWCDfpadadD95EDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.46.1", + "@typescript-eslint/types": "8.46.1", + "@typescript-eslint/typescript-estree": "8.46.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.1.tgz", + "integrity": "sha512-ptkmIf2iDkNUjdeu2bQqhFPV1m6qTnFFjg7PPDjxKWaMaP0Z6I9l30Jr3g5QqbZGdw8YdYvLp+XnqnWWZOg/NA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.46.1", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@vitest/expect": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", + "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", + "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.2.4", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", + "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "3.2.4", + "pathe": "^2.0.3", + "strip-literal": "^3.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", + "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.4", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", + "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^4.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", + "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.4", + "loupe": "^3.1.4", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/abbrev": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.1.tgz", + "integrity": "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==", + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, - "node_modules/browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", - "dev": true + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } }, "node_modules/cacache": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.0.tgz", - "integrity": "sha512-I7mVOPl3PUCeRub1U8YoGz2Lqv9WOBpobZ8RyWFXmReuILz+3OAyTa5oH3QPdtKZD7N0Yk00aLfzn0qvp8dZ1w==", + "version": "19.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-19.0.1.tgz", + "integrity": "sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ==", + "license": "ISC", "dependencies": { - "@npmcli/fs": "^3.1.0", + "@npmcli/fs": "^4.0.0", "fs-minipass": "^3.0.0", "glob": "^10.2.2", "lru-cache": "^10.0.1", "minipass": "^7.0.3", - "minipass-collect": "^1.0.2", + "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" + "p-map": "^7.0.2", + "ssri": "^12.0.0", + "tar": "^7.4.3", + "unique-filename": "^4.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/cacache/node_modules/lru-cache": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", - "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", - "engines": { - "node": "14 || >=16.14" + "node_modules/cacache/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" } }, - "node_modules/cacache/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "node_modules/cacache/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/cacache/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/caching-transform": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", - "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==", - "dev": true, + "node_modules/cacache/node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", "dependencies": { - "hasha": "^3.0.0", - "make-dir": "^2.0.0", - "package-hash": "^3.0.0", - "write-file-atomic": "^2.4.2" + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=6" + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/capture-stack-trace": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", - "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==", + "node_modules/chai": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, "node_modules/chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">= 16" } }, "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=6" + "node": ">=7.0.0" } }, - "node_modules/clean-yaml-object": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/clean-yaml-object/-/clean-yaml-object-0.1.0.tgz", - "integrity": "sha1-Y/sRDcLOGoTcIfbZM0h20BCui2g=", + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, - "node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", "dependencies": { - "color-name": "1.1.3" + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", "dev": true, - "bin": { - "color-support": "bin.js" + "license": "MIT", + "engines": { + "node": ">=6" } }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, + "license": "MIT" + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "license": "MIT", + "optional": true, "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" + "iconv-lite": "^0.6.2" } }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "engines": { + "node": ">=6" + } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "license": "MIT" }, - "node_modules/convert-source-map": { + "node_modules/es-module-lexer": { "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } + "license": "MIT" }, - "node_modules/convert-source-map/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "node_modules/esbuild": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.11.tgz", + "integrity": "sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.11", + "@esbuild/android-arm": "0.25.11", + "@esbuild/android-arm64": "0.25.11", + "@esbuild/android-x64": "0.25.11", + "@esbuild/darwin-arm64": "0.25.11", + "@esbuild/darwin-x64": "0.25.11", + "@esbuild/freebsd-arm64": "0.25.11", + "@esbuild/freebsd-x64": "0.25.11", + "@esbuild/linux-arm": "0.25.11", + "@esbuild/linux-arm64": "0.25.11", + "@esbuild/linux-ia32": "0.25.11", + "@esbuild/linux-loong64": "0.25.11", + "@esbuild/linux-mips64el": "0.25.11", + "@esbuild/linux-ppc64": "0.25.11", + "@esbuild/linux-riscv64": "0.25.11", + "@esbuild/linux-s390x": "0.25.11", + "@esbuild/linux-x64": "0.25.11", + "@esbuild/netbsd-arm64": "0.25.11", + "@esbuild/netbsd-x64": "0.25.11", + "@esbuild/openbsd-arm64": "0.25.11", + "@esbuild/openbsd-x64": "0.25.11", + "@esbuild/openharmony-arm64": "0.25.11", + "@esbuild/sunos-x64": "0.25.11", + "@esbuild/win32-arm64": "0.25.11", + "@esbuild/win32-ia32": "0.25.11", + "@esbuild/win32-x64": "0.25.11" + } }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/coveralls": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.1.1.tgz", - "integrity": "sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww==", + "node_modules/eslint": { + "version": "9.37.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.37.0.tgz", + "integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==", "dev": true, - "dependencies": { - "js-yaml": "^3.13.1", - "lcov-parse": "^1.0.0", - "log-driver": "^1.2.7", - "minimist": "^1.2.5", - "request": "^2.88.2" + "license": "MIT", + "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.4.0", + "@eslint/core": "^0.16.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.37.0", + "@eslint/plugin-kit": "^0.4.0", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" }, "bin": { - "coveralls": "bin/coveralls.js" + "eslint": "bin/eslint.js" }, "engines": { - "node": ">=6" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, - "node_modules/cp-file": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz", - "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==", + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "graceful-fs": "^4.1.2", - "make-dir": "^2.0.0", - "nested-error-stacks": "^2.0.0", - "pify": "^4.0.1", - "safe-buffer": "^5.0.1" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">=6" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/cross-spawn": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", - "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, - "dependencies": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/cross-spawn/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { - "isexe": "^2.0.0" + "color-convert": "^2.0.1" }, - "bin": { - "which": "bin/which" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { - "assert-plus": "^1.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=0.10" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "ms": "2.1.2" + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": ">=6.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=0.10" } }, - "node_modules/default-require-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", - "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "strip-bom": "^3.0.0" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=4" + "node": ">=4.0" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">=0.4.0" + "node": ">=4.0" } }, - "node_modules/diff": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", - "integrity": "sha512-VzVc42hMZbYU9Sx/ltb7KYuQ6pqAw+cbFWVy4XKdkuEL2CFaRLGEnISPs7YdzaUGpi+CpIqvRmu7hPQ4T7EQ5w==", + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">=0.3.1" + "node": ">=0.10.0" } }, - "node_modules/domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "node_modules/expect-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.1.tgz", + "integrity": "sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=0.4", - "npm": ">=1.2" + "node": ">=12.0.0" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + "node_modules/exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==" }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } + "license": "MIT" }, - "node_modules/ejs": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz", - "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==", + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, - "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8.6.0" } }, - "node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "optional": true, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "is-glob": "^4.0.1" + }, "engines": { - "node": ">=6" + "node": ">= 6" } }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } + "license": "MIT" }, - "node_modules/es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dev": true, - "engines": { - "node": ">=0.8.0" + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" } }, - "node_modules/esm": { - "version": "3.2.25", - "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", - "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", - "dev": true, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=16.0.0" } }, - "node_modules/events-to-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/events-to-array/-/events-to-array-1.1.2.tgz", - "integrity": "sha1-LUH1Y+H+QA7Uli/hpNXGp1Od9/Y=", - "dev": true - }, - "node_modules/exponential-backoff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", - "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==" - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true, - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" + "to-regex-range": "^5.0.1" }, "engines": { - "node": ">=6" + "node": ">=8" } }, "node_modules/find-java-home": { @@ -1076,61 +1663,72 @@ "winreg": "~1.2.2" } }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "dev": true, + "license": "MIT" + }, "node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { - "locate-path": "^3.0.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/foreground-child": { - "version": "1.5.6", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", - "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=", + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, + "license": "MIT", "dependencies": { - "cross-spawn": "^4", - "signal-exit": "^3.0.0" - } - }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true, + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, "engines": { - "node": "*" + "node": ">=16" } }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "dev": true, + "license": "ISC" + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">= 0.12" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/fs-exists-cached": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-exists-cached/-/fs-exists-cached-1.0.0.tgz", - "integrity": "sha1-zyVVTKBQ3EmuZla0HeQiWJidy84=", - "dev": true - }, "node_modules/fs-minipass": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, @@ -1138,228 +1736,104 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/function-loop": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/function-loop/-/function-loop-1.0.2.tgz", - "integrity": "sha512-Iw4MzMfS3udk/rqxTiDDCllhGwlOrsr50zViTOO/W6lS/9y6B1J0BD2VZzrnWUYBJsl3aeqjgR5v7bWWhZSYbA==", - "dev": true - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - } - }, "node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz", + "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.0.3", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/glob/node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/glob/node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=10.13.0" } }, "node_modules/glob/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", + "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", + "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "@isaacs/brace-expansion": "^5.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/glob/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "engines": { - "node": ">=14" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/glob/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", + "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true, - "engines": { - "node": ">=4" - } + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true, - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } + "license": "MIT" }, "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/hasha": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz", - "integrity": "sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "dependencies": { - "is-stream": "^1.0.1" - }, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause" }, "node_modules/http-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", - "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "license": "MIT", "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -1368,27 +1842,13 @@ "node": ">= 14" } }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, "node_modules/https-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", - "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", "dependencies": { - "agent-base": "^7.0.2", + "agent-base": "^7.1.2", "debug": "4" }, "engines": { @@ -1399,6 +1859,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", "optional": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -1407,465 +1868,294 @@ "node": ">=0.10.0" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==" - }, - "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true, - "optional": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "node_modules/istanbul-lib-coverage": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", - "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 4" } }, - "node_modules/istanbul-lib-hook": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz", - "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==", + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, + "license": "MIT", "dependencies": { - "append-transform": "^1.0.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { "node": ">=6" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", - "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", - "dev": true, - "dependencies": { - "@babel/generator": "^7.4.0", - "@babel/parser": "^7.4.3", - "@babel/template": "^7.4.0", - "@babel/traverse": "^7.4.3", - "@babel/types": "^7.4.0", - "istanbul-lib-coverage": "^2.0.5", - "semver": "^6.0.0" }, - "engines": { - "node": ">=6" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "engines": { + "node": ">=0.8.19" } }, - "node_modules/istanbul-lib-report": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", - "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", - "dev": true, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "license": "MIT", "dependencies": { - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "supports-color": "^6.1.0" + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" }, "engines": { - "node": ">=6" + "node": ">= 12" } }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/istanbul-lib-source-maps": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", - "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "rimraf": "^2.6.3", - "source-map": "^0.6.1" - }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/istanbul-lib-source-maps/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/istanbul-reports": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz", - "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "dependencies": { - "html-escaper": "^2.0.0" - }, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=0.12.0" } }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", + "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, "engines": { - "node": ">=14" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" } }, "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true, + "license": "MIT" }, "node_modules/js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "license": "MIT" }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true + "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", "dev": true, - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } + "license": "MIT" }, - "node_modules/jsprim/node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true - }, - "node_modules/lcov-parse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", - "integrity": "sha1-6w1GtUER68VhrLTECO+TY73I9+A=", + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true, - "bin": { - "lcov-parse": "bin/cli.js" - } + "license": "MIT" }, - "node_modules/load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" + "json-buffer": "3.0.1" } }, - "node_modules/load-json-file/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, "engines": { - "node": ">=4" + "node": ">= 0.8.0" } }, "node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", - "dev": true - }, - "node_modules/log-driver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", - "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true, - "engines": { - "node": ">=0.8.6" - } + "license": "MIT" }, - "node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "node_modules/loupe": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", "dev": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } + "license": "MIT" }, - "node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, + "node_modules/lru-cache": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.1.0.tgz", + "integrity": "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==", + "license": "ISC", "engines": { - "node": ">=6" + "node": "20 || >=22" } }, - "node_modules/make-dir/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "node_modules/magic-string": { + "version": "0.30.19", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz", + "integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==", "dev": true, - "bin": { - "semver": "bin/semver" + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, "node_modules/make-fetch-happen": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz", - "integrity": "sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz", + "integrity": "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==", + "license": "ISC", "dependencies": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", + "@npmcli/agent": "^3.0.0", + "cacache": "^19.0.1", "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", + "minipass-fetch": "^4.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", + "negotiator": "^1.0.0", + "proc-log": "^5.0.0", "promise-retry": "^2.0.1", - "ssri": "^10.0.0" + "ssri": "^12.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/make-fetch-happen/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">= 8" } }, - "node_modules/merge-source-map": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", - "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { - "source-map": "^0.6.1" - } - }, - "node_modules/merge-source-map/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8.6" } }, - "node_modules/mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "dev": true, - "dependencies": { - "mime-db": "1.44.0" + "node": ">=8.6" }, - "engines": { - "node": ">= 0.6" + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/minimatch": { @@ -1873,6 +2163,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -1880,80 +2171,49 @@ "node": "*" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dependencies": { - "minipass": "^3.0.0" - }, + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", "engines": { - "node": ">= 8" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/minipass-collect/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/minipass-collect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", + "license": "ISC", "dependencies": { - "yallist": "^4.0.0" + "minipass": "^7.0.3" }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/minipass-collect/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/minipass-fetch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-4.0.1.tgz", + "integrity": "sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ==", + "license": "MIT", "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" + "minizlib": "^3.0.1" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" }, "optionalDependencies": { "encoding": "^0.1.13" } }, - "node_modules/minipass-fetch/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/minipass-flush": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "license": "ISC", "dependencies": { "minipass": "^3.0.0" }, @@ -1965,6 +2225,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -1975,12 +2236,14 @@ "node_modules/minipass-flush/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" }, "node_modules/minipass-pipeline": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "license": "ISC", "dependencies": { "minipass": "^3.0.0" }, @@ -1992,6 +2255,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -2002,12 +2266,14 @@ "node_modules/minipass-pipeline/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" }, "node_modules/minipass-sized": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "license": "ISC", "dependencies": { "minipass": "^3.0.0" }, @@ -2019,6 +2285,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -2029,118 +2296,121 @@ "node_modules/minipass-sized/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/minipass/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" }, "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", + "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "minipass": "^7.1.2" }, "engines": { - "node": ">=8" + "node": ">= 18" } }, - "node_modules/minizlib/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "license": "MIT", "bin": { - "mkdirp": "bin/cmd.js" + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/nan": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", - "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==" + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.23.0.tgz", + "integrity": "sha512-1UxuyYGdoQHcGg87Lkqm3FzefucTa0NAiOcuRsDmysep3c1LVCRK2krrUDafMWtjSG04htvAmvg96+SDknOmgQ==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" }, "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, - "node_modules/nested-error-stacks": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz", - "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==", - "dev": true - }, "node_modules/node-gyp": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.0.1.tgz", - "integrity": "sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg==", + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-11.5.0.tgz", + "integrity": "sha512-ra7Kvlhxn5V9Slyus0ygMa2h+UqExPqUIkfk7Pc8QTLT956JLSy51uWFwHtIYy0vI8cB4BDhc/S03+880My/LQ==", + "license": "MIT", "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", - "glob": "^10.3.10", "graceful-fs": "^4.2.6", - "make-fetch-happen": "^13.0.0", - "nopt": "^7.0.0", - "proc-log": "^3.0.0", + "make-fetch-happen": "^14.0.3", + "nopt": "^8.0.0", + "proc-log": "^5.0.0", "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^4.0.0" + "tar": "^7.4.3", + "tinyglobby": "^0.2.12", + "which": "^5.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/node-gyp/node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, "node_modules/node-gyp/node_modules/isexe": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "license": "ISC", "engines": { "node": ">=16" } }, "node_modules/node-gyp/node_modules/which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", + "license": "ISC", "dependencies": { "isexe": "^3.1.1" }, @@ -2148,262 +2418,113 @@ "node-which": "bin/which.js" }, "engines": { - "node": "^16.13.0 || >=18.0.0" - } - }, - "node_modules/nodeunit": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/nodeunit/-/nodeunit-0.11.3.tgz", - "integrity": "sha512-gDNxrDWpx07BxYNO/jn1UrGI1vNhDQZrIFphbHMcTCDc5mrrqQBWfQMXPHJ5WSgbFwD1D6bv4HOsqtTrPG03AA==", - "deprecated": "you are strongly encouraged to use other testing options", - "dev": true, - "dependencies": { - "ejs": "^2.5.2", - "tap": "^12.0.1" - }, - "bin": { - "nodeunit": "bin/nodeunit" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/nopt": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", - "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.1.0.tgz", + "integrity": "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==", + "license": "ISC", "dependencies": { - "abbrev": "^2.0.0" + "abbrev": "^3.0.0" }, "bin": { "nopt": "bin/nopt.js" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/nyc": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.1.tgz", - "integrity": "sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw==", - "dev": true, - "dependencies": { - "archy": "^1.0.0", - "caching-transform": "^3.0.2", - "convert-source-map": "^1.6.0", - "cp-file": "^6.2.0", - "find-cache-dir": "^2.1.0", - "find-up": "^3.0.0", - "foreground-child": "^1.5.6", - "glob": "^7.1.3", - "istanbul-lib-coverage": "^2.0.5", - "istanbul-lib-hook": "^2.0.7", - "istanbul-lib-instrument": "^3.3.0", - "istanbul-lib-report": "^2.0.8", - "istanbul-lib-source-maps": "^3.0.6", - "istanbul-reports": "^2.2.4", - "js-yaml": "^3.13.1", - "make-dir": "^2.1.0", - "merge-source-map": "^1.1.0", - "resolve-from": "^4.0.0", - "rimraf": "^2.6.3", - "signal-exit": "^3.0.2", - "spawn-wrap": "^1.4.2", - "test-exclude": "^5.2.3", - "uuid": "^3.3.2", - "yargs": "^13.2.2", - "yargs-parser": "^13.0.0" - }, - "bin": { - "nyc": "bin/nyc.js" - }, - "engines": { - "node": ">=6" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/nyc/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/opener": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz", - "integrity": "sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==", - "dev": true, - "bin": { - "opener": "bin/opener-bin.js" - } - }, - "node_modules/os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/own-or": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/own-or/-/own-or-1.0.0.tgz", - "integrity": "sha1-Tod/vtqaLsgAD7wLyuOWRe6L+Nw=", - "dev": true - }, - "node_modules/own-or-env": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/own-or-env/-/own-or-env-1.0.1.tgz", - "integrity": "sha512-y8qULRbRAlL6x2+M0vIe7jJbJx/kmUTzYonRAa2ayesR2qWLswninkVyeJe4x3IEXhdgoNodzjQRKAoEs6Fmrw==", - "dev": true, - "dependencies": { - "own-or": "^1.0.0" + "node": ">= 0.8.0" } }, "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { - "p-limit": "^2.0.0" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dependencies": { - "aggregate-error": "^3.0.0" - }, + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", + "integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==", + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" }, - "node_modules/package-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-3.0.0.tgz", - "integrity": "sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA==", + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "license": "MIT", "dependencies": { - "graceful-fs": "^4.1.15", - "hasha": "^3.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" + "callsites": "^3.0.0" }, "engines": { "node": ">=6" } }, - "node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/path-key": { @@ -2414,110 +2535,128 @@ "node": ">=8" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "license": "BlueOak-1.0.0", "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", - "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", - "engines": { - "node": "14 || >=16.14" - } + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" }, - "node_modules/path-scurry/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "node_modules/pathval": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">= 14.16" } }, - "node_modules/path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, - "dependencies": { - "pify": "^3.0.0" - }, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "license": "MIT", + "peer": true, "engines": { - "node": ">=4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/path-type/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, "engines": { - "node": ">=4" + "node": "^10 || ^12 || >=14" } }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 0.8.0" } }, - "node_modules/pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, - "dependencies": { - "find-up": "^3.0.0" + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=6" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz", + "integrity": "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==", + "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "optional": true - }, "node_modules/promise-retry": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "license": "MIT", "dependencies": { "err-code": "^2.0.2", "retry": "^0.12.0" @@ -2526,162 +2665,43 @@ "node": ">=10" } }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, - "dependencies": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", - "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, - "dependencies": { - "find-up": "^3.0.0", - "read-pkg": "^3.0.0" - }, + "license": "MIT", "engines": { "node": ">=6" - } - }, - "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "optional": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "optional": true - }, - "node_modules/release-zalgo": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", - "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", - "dev": true, - "dependencies": { - "es6-error": "^4.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dev": true, - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true + } }, - "node_modules/resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, - "dependencies": { - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -2690,46 +2710,68 @@ "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "license": "MIT", "engines": { "node": ">= 4" } }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/rollup": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.4.tgz", + "integrity": "sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ==", "dev": true, + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" }, "engines": { - "node": "*" + "node": ">=18.0.0", + "npm": ">=8.0.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.52.4", + "@rollup/rollup-android-arm64": "4.52.4", + "@rollup/rollup-darwin-arm64": "4.52.4", + "@rollup/rollup-darwin-x64": "4.52.4", + "@rollup/rollup-freebsd-arm64": "4.52.4", + "@rollup/rollup-freebsd-x64": "4.52.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.52.4", + "@rollup/rollup-linux-arm-musleabihf": "4.52.4", + "@rollup/rollup-linux-arm64-gnu": "4.52.4", + "@rollup/rollup-linux-arm64-musl": "4.52.4", + "@rollup/rollup-linux-loong64-gnu": "4.52.4", + "@rollup/rollup-linux-ppc64-gnu": "4.52.4", + "@rollup/rollup-linux-riscv64-gnu": "4.52.4", + "@rollup/rollup-linux-riscv64-musl": "4.52.4", + "@rollup/rollup-linux-s390x-gnu": "4.52.4", + "@rollup/rollup-linux-x64-gnu": "4.52.4", + "@rollup/rollup-linux-x64-musl": "4.52.4", + "@rollup/rollup-openharmony-arm64": "4.52.4", + "@rollup/rollup-win32-arm64-msvc": "4.52.4", + "@rollup/rollup-win32-ia32-msvc": "4.52.4", + "@rollup/rollup-win32-x64-gnu": "4.52.4", + "@rollup/rollup-win32-x64-msvc": "4.52.4", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ { @@ -2744,21 +2786,24 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "devOptional": true + "license": "MIT", + "optional": true }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -2766,28 +2811,6 @@ "node": ">=10" } }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -2807,212 +2830,120 @@ "node": ">=8" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, "node_modules/smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" } }, "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz", + "integrity": "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==", + "license": "MIT", "dependencies": { - "ip": "^2.0.0", + "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" }, "engines": { - "node": ">= 10.13.0", + "node": ">= 10.0.0", "npm": ">= 3.0.0" } }, "node_modules/socks-proxy-agent": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", - "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "license": "MIT", "dependencies": { - "agent-base": "^7.0.2", + "agent-base": "^7.1.2", "debug": "^4.3.4", - "socks": "^2.7.1" + "socks": "^2.8.3" }, "engines": { "node": ">= 14" } }, - "node_modules/source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, - "node_modules/spawn-wrap": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz", - "integrity": "sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw==", - "dev": true, - "dependencies": { - "foreground-child": "^1.5.6", - "mkdirp": "^0.5.0", - "os-homedir": "^1.0.1", - "rimraf": "^2.6.2", - "signal-exit": "^3.0.2", - "which": "^1.3.0" - } - }, - "node_modules/spawn-wrap/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "license": "BSD-3-Clause" }, "node_modules/ssri": { - "version": "10.0.5", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", - "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-12.0.0.tgz", + "integrity": "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==", + "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/ssri/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/stack-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", - "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true, - "optional": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } + "license": "MIT" }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "node_modules/std-env": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", + "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", "dev": true, - "optional": true + "license": "MIT" }, "node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/string-width-cjs": { @@ -3020,6 +2951,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3029,23 +2961,26 @@ "node": ">=8" } }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, "node_modules/string-width-cjs/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -3054,15 +2989,18 @@ } }, "node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", "dependencies": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/strip-ansi-cjs": { @@ -3070,6 +3008,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -3077,508 +3016,422 @@ "node": ">=8" } }, - "node_modules/strip-ansi/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/tap": { - "version": "12.7.0", - "resolved": "https://registry.npmjs.org/tap/-/tap-12.7.0.tgz", - "integrity": "sha512-SjglJmRv0pqrQQ7d5ZBEY8ZOqv3nYDBXEX51oyycOH7piuhn82JKT/yDNewwmOsodTD/RZL9MccA96EjDgK+Eg==", - "dev": true, - "dependencies": { - "bind-obj-methods": "^2.0.0", - "browser-process-hrtime": "^1.0.0", - "capture-stack-trace": "^1.0.0", - "clean-yaml-object": "^0.1.0", - "color-support": "^1.1.0", - "coveralls": "^3.0.2", - "domain-browser": "^1.2.0", - "esm": "^3.2.5", - "foreground-child": "^1.3.3", - "fs-exists-cached": "^1.0.0", - "function-loop": "^1.0.1", - "glob": "^7.1.3", - "isexe": "^2.0.0", - "js-yaml": "^3.13.1", - "minipass": "^2.3.5", - "mkdirp": "^0.5.1", - "nyc": "^14.0.0", - "opener": "^1.5.1", - "os-homedir": "^1.0.2", - "own-or": "^1.0.0", - "own-or-env": "^1.0.1", - "rimraf": "^2.6.3", - "signal-exit": "^3.0.0", - "source-map-support": "^0.5.10", - "stack-utils": "^1.0.2", - "tap-mocha-reporter": "^3.0.9", - "tap-parser": "^7.0.0", - "tmatch": "^4.0.0", - "trivial-deferred": "^1.0.1", - "ts-node": "^8.0.2", - "tsame": "^2.0.1", - "typescript": "^3.3.3", - "write-file-atomic": "^2.4.2", - "yapool": "^1.0.0" - }, - "bin": { - "tap": "bin/run.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/tap-mocha-reporter": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/tap-mocha-reporter/-/tap-mocha-reporter-3.0.9.tgz", - "integrity": "sha512-VO07vhC9EG27EZdOe7bWBj1ldbK+DL9TnRadOgdQmiQOVZjFpUEQuuqO7+rNSO2kfmkq5hWeluYXDWNG/ytXTQ==", - "dev": true, - "dependencies": { - "color-support": "^1.1.0", - "debug": "^2.1.3", - "diff": "^1.3.2", - "escape-string-regexp": "^1.0.3", - "glob": "^7.0.5", - "js-yaml": "^3.3.1", - "tap-parser": "^5.1.0", - "unicode-length": "^1.0.0" - }, - "bin": { - "tap-mocha-reporter": "index.js" - }, - "optionalDependencies": { - "readable-stream": "^2.1.5" - } - }, - "node_modules/tap-mocha-reporter/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/tap-mocha-reporter/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/tap-mocha-reporter/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/tap-mocha-reporter/node_modules/tap-parser": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-5.4.0.tgz", - "integrity": "sha512-BIsIaGqv7uTQgTW1KLTMNPSEQf4zDDPgYOBRdgOfuB+JFOLRBfEu6cLa/KvMvmqggu1FKXDfitjLwsq4827RvA==", - "dev": true, - "dependencies": { - "events-to-array": "^1.0.1", - "js-yaml": "^3.2.7" - }, - "bin": { - "tap-parser": "bin/cmd.js" - }, - "optionalDependencies": { - "readable-stream": "^2" - } - }, - "node_modules/tap-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-7.0.0.tgz", - "integrity": "sha512-05G8/LrzqOOFvZhhAk32wsGiPZ1lfUrl+iV7+OkKgfofZxiceZWMHkKmow71YsyVQ8IvGBP2EjcIjE5gL4l5lA==", - "dev": true, - "dependencies": { - "events-to-array": "^1.0.1", - "js-yaml": "^3.2.7", - "minipass": "^2.2.0" - }, - "bin": { - "tap-parser": "bin/cmd.js" + "node": ">=8" } }, - "node_modules/tap/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, + "license": "MIT", "engines": { - "node": "*" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tar/node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "node_modules/strip-literal": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz", + "integrity": "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==", + "dev": true, + "license": "MIT", "dependencies": { - "minipass": "^3.0.0" + "js-tokens": "^9.0.1" }, - "engines": { - "node": ">= 8" + "funding": { + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/tar/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "bin": { - "mkdirp": "bin/cmd.js" + "node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/tar/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/test-exclude": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", - "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", "dev": true, - "dependencies": { - "glob": "^7.1.3", - "minimatch": "^3.0.4", - "read-pkg-up": "^4.0.0", - "require-main-filename": "^2.0.0" - }, - "engines": { - "node": ">=6" - } + "license": "MIT" }, - "node_modules/test-exclude/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { - "node": "*" + "node": ">=12.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/tmatch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tmatch/-/tmatch-4.0.0.tgz", - "integrity": "sha512-Ynn2Gsp+oCvYScQXeV+cCs7citRDilq0qDXA6tuvFwDgiYyyaq7D5vKUlAPezzZR5NDobc/QMeN6e5guOYmvxg==", - "dev": true + "node_modules/tinypool": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } }, - "node_modules/to-fast-properties": { + "node_modules/tinyrainbow": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=14.0.0" } }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "node_modules/tinyspy": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz", + "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==", "dev": true, - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, + "license": "MIT", "engines": { - "node": ">=0.8" + "node": ">=14.0.0" } }, - "node_modules/trivial-deferred": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trivial-deferred/-/trivial-deferred-1.0.1.tgz", - "integrity": "sha1-N21NKdlR1jaKb3oK6FwvTV4GWPM=", - "dev": true - }, - "node_modules/ts-node": { - "version": "8.10.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz", - "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==", + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { - "arg": "^4.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "source-map-support": "^0.5.17", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" + "is-number": "^7.0.0" }, "engines": { - "node": ">=6.0.0" - }, - "peerDependencies": { - "typescript": ">=2.7" + "node": ">=8.0" } }, - "node_modules/ts-node/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.3.1" + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" } }, - "node_modules/tsame": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/tsame/-/tsame-2.0.1.tgz", - "integrity": "sha512-jxyxgKVKa4Bh5dPcO42TJL22lIvfd9LOVJwdovKOnJa4TLLrHxquK+DlGm4rkGmrcur+GRx+x4oW00O2pY/fFw==", - "dev": true - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { - "safe-buffer": "^5.0.1" + "prelude-ls": "^1.2.1" }, "engines": { - "node": "*" + "node": ">= 0.8.0" } }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, "node_modules/typescript": { - "version": "3.9.7", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", - "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, + "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, - "node_modules/unicode-length": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/unicode-length/-/unicode-length-1.0.3.tgz", - "integrity": "sha1-Wtp6f+1RhBpBijKM8UlHisg1irs=", + "node_modules/typescript-eslint": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.46.1.tgz", + "integrity": "sha512-VHgijW803JafdSsDO8I761r3SHrgk4T00IdyQ+/UsthtgPRsBWQLqoSxOolxTpxRKi1kGXK0bSz4CoAc9ObqJA==", "dev": true, + "license": "MIT", "dependencies": { - "punycode": "^1.3.2", - "strip-ansi": "^3.0.1" - } - }, - "node_modules/unicode-length/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true, + "@typescript-eslint/eslint-plugin": "8.46.1", + "@typescript-eslint/parser": "8.46.1", + "@typescript-eslint/typescript-estree": "8.46.1", + "@typescript-eslint/utils": "8.46.1" + }, "engines": { - "node": ">=0.10.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/unicode-length/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "node_modules/unicode-length/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "node_modules/undici-types": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.14.0.tgz", + "integrity": "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==", "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, "node_modules/unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-4.0.0.tgz", + "integrity": "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==", + "license": "ISC", "dependencies": { - "unique-slug": "^4.0.0" + "unique-slug": "^5.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-5.0.0.tgz", + "integrity": "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==", + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true, - "optional": true - }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "node_modules/vite": { + "version": "7.1.10", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.10.tgz", + "integrity": "sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA==", "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, "bin": { - "uuid": "bin/uuid" + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } } }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "node_modules/vite-node": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", + "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", "dev": true, + "license": "MIT", "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "cac": "^6.7.14", + "debug": "^4.4.1", + "es-module-lexer": "^1.7.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "node_modules/vitest": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", + "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dev": true, - "engines": [ - "node >=0.6.0" - ], + "license": "MIT", "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "@types/chai": "^5.2.2", + "@vitest/expect": "3.2.4", + "@vitest/mocker": "3.2.4", + "@vitest/pretty-format": "^3.2.4", + "@vitest/runner": "3.2.4", + "@vitest/snapshot": "3.2.4", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "debug": "^4.4.1", + "expect-type": "^1.2.1", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "picomatch": "^4.0.2", + "std-env": "^3.9.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.14", + "tinypool": "^1.1.1", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", + "vite-node": "3.2.4", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.2.4", + "@vitest/ui": "3.2.4", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } } }, - "node_modules/when": { - "version": "3.7.8", - "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", - "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", - "dev": true - }, "node_modules/which": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/which/-/which-1.0.9.tgz", @@ -3587,29 +3440,53 @@ "which": "bin/which" } }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } }, "node_modules/winreg": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/winreg/-/winreg-1.2.4.tgz", "integrity": "sha1-ugZWKbepJRMOFXeRCM9UCZDpjRs=" }, - "node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/wrap-ansi-cjs": { @@ -3617,6 +3494,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -3629,10 +3507,20 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -3643,39 +3531,17 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/wrap-ansi-cjs/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" }, "node_modules/wrap-ansi-cjs/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3689,6 +3555,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -3696,76 +3563,26 @@ "node": ">=8" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, "node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "node_modules/yapool": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yapool/-/yapool-1.0.0.tgz", - "integrity": "sha1-9pPymjFbUNmp2iZGp6ZkXJaYW2o=", - "dev": true - }, - "node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } } } diff --git a/package.json b/package.json index e096d870..df60ce65 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,9 @@ "jvm", "bridge" ], - "version": "0.14.0", + "version": "0.18.0", "engines": { - "node": ">=7.0.0" + "node": ">=8.0.0" }, "maintainers": [ { @@ -26,21 +26,36 @@ "url": "https://github.com/joeferner/node-java.git" }, "dependencies": { - "async": "^3.2.5", "find-java-home": "^2.0.0", - "glob": "^10.3.10", - "nan": "^2.18.0", - "node-gyp": "^10.0.1" + "glob": "^11.0.3", + "nan": "^2.23.0", + "node-gyp": "^11.5.0" }, "devDependencies": { - "chalk": "2.4.1", - "nodeunit": "0.11.3", - "when": "3.7.8" + "@eslint/js": "^9.37.0", + "@types/find-root": "^1.1.4", + "@types/node": "^24.8.0", + "chalk": "^5.6.2", + "eslint": "^9.37.0", + "find-root": "^1.1.0", + "globals": "^16.4.0", + "prettier": "^3.6.2", + "typescript": "^5.9.3", + "typescript-eslint": "^8.46.1", + "vitest": "^3.2.4" }, "scripts": { "install": "node-gyp rebuild", - "test": "node testRunner.js", - "postinstall": "node postInstall.js" + "clean": "rm -rf build", + "test": "tsc && node ./build/ts/scripts/testRunner.js", + "postinstall": "node ./scripts/postInstall.js", + "lint": "eslint --ext js,ts,tsx --report-unused-disable-directives --max-warnings 0 .", + "format": "prettier --write .", + "format-cpp": "clang-format --version; find src-cpp/ -iname '*.h' -o -iname '*.cpp' | xargs clang-format -i", + "build-ts": "tsc", + "build-ts:watch": "tsc --watch", + "precommit": "npm run format-cpp && npm run format && npm run lint && npm run build-ts && npm test" }, - "main": "./index.js" + "main": "./index.js", + "types": "./java.d.ts" } diff --git a/postInstall.js b/postInstall.js deleted file mode 100644 index 2701913c..00000000 --- a/postInstall.js +++ /dev/null @@ -1,70 +0,0 @@ -var glob = require('glob'); -var fs = require('fs'); -var path = require('path'); -var os = require('os'); - -require('find-java-home')(function(err, home){ - var dll; - var dylib; - var so,soFiles; - var binary; - - if(home){ - dll = glob.sync('**/jvm.dll', {cwd: home})[0]; - dylib = glob.sync('**/libjli.dylib', {cwd: home})[0]; - soFiles = glob.sync('**/libjvm.so', {cwd: home}); - - if(soFiles.length>0) - so = getCorrectSoForPlatform(soFiles); - - binary = dll || dylib || so; - - fs.writeFileSync( - path.resolve(__dirname, './build/jvm_dll_path.json'), - binary - ? JSON.stringify( - path.delimiter - + path.dirname(path.resolve(home, binary)) - ) - : '""' - ); - } -}); - -function getCorrectSoForPlatform(soFiles){ - var so = _getCorrectSoForPlatform(soFiles); - if (so) { - so = removeDuplicateJre(so); - } - return so; -} - -function removeDuplicateJre(filePath){ - while(filePath.indexOf('jre/jre')>=0){ - filePath = filePath.replace('jre/jre','jre'); - } - return filePath; -} - -function _getCorrectSoForPlatform(soFiles){ - - var architectureFolderNames = { - 'ia32': 'i386', - 'x64': 'amd64' - }; - - if(os.platform() != 'sunos') - return soFiles[0]; - - var requiredFolderName = architectureFolderNames[os.arch()]; - - for (var i = 0; i < soFiles.length; i++) { - var so = soFiles[i]; - - if(so.indexOf('server')>0) - if(so.indexOf(requiredFolderName)>0) - return so; - } - - return soFiles[0]; -} diff --git a/scripts/commons-lang/.gitignore b/scripts/commons-lang/.gitignore new file mode 100644 index 00000000..8b8c81d7 --- /dev/null +++ b/scripts/commons-lang/.gitignore @@ -0,0 +1,2 @@ +target/ +dependency-reduced-pom.xml diff --git a/scripts/commons-lang/pom.xml b/scripts/commons-lang/pom.xml new file mode 100644 index 00000000..11c3470b --- /dev/null +++ b/scripts/commons-lang/pom.xml @@ -0,0 +1,40 @@ + + 4.0.0 + commons-lang + commons-lang + 1 + + + + org.apache.commons + commons-lang3 + 3.19.0 + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.6.0 + + + package + + shade + + + + + org.apache + nodejava.org.apache + + + + + + + + + \ No newline at end of file diff --git a/scripts/compile-java.sh b/scripts/compile-java.sh new file mode 100755 index 00000000..ba590fe8 --- /dev/null +++ b/scripts/compile-java.sh @@ -0,0 +1,17 @@ +#!/bin/sh +set -eu + +SCRIPT_DIR=$(dirname "$0") +cd "${SCRIPT_DIR}/.." + +if [ -z "${JAVA_HOME:-}" ] && [ -e "/usr/libexec/java_home" ]; then + export JAVA_HOME=$(/usr/libexec/java_home -v 11) +fi + +echo "Using $(javac -version)." +set -x + +javac -source 1.8 -target 1.8 src-java/node/*.java +javac -source 1.8 -target 1.8 test/*.java +javac -classpath src-java -h ./src-cpp src-java/node/NodeDynamicProxyClass.java +echo "complete!" diff --git a/scripts/findJavaHome.js b/scripts/findJavaHome.js new file mode 100644 index 00000000..53ffa337 --- /dev/null +++ b/scripts/findJavaHome.js @@ -0,0 +1,9 @@ +require("find-java-home")(function (err, home) { + if (err || !home) { + if (!err) { + err = Error("Unable to determine Java home location"); + } + process.exit(1); + } + process.stdout.write(home); +}); diff --git a/find_java_libdir.sh b/scripts/find_java_libdir.sh similarity index 96% rename from find_java_libdir.sh rename to scripts/find_java_libdir.sh index 47c4b203..f638569e 100755 --- a/find_java_libdir.sh +++ b/scripts/find_java_libdir.sh @@ -1,7 +1,9 @@ #!/usr/bin/env bash - set -eu +SCRIPT_DIR=$(dirname "$0") +cd "${SCRIPT_DIR}/.." + error() { echo "error: $*" >&2 exit 1 @@ -12,7 +14,7 @@ main () { local os=$2 local java_home full_java_version java_version - java_home=$(node findJavaHome.js) + java_home=$(node ./scripts/findJavaHome.js) full_java_version=$(${java_home}/bin/java -version 2>&1 | grep version | sed -e 's/.*version "\(.*\)"\(.*\)/\1/; 1q') if [[ "${full_java_version}" = "1."* ]] diff --git a/scripts/postInstall.js b/scripts/postInstall.js new file mode 100644 index 00000000..50d3ec95 --- /dev/null +++ b/scripts/postInstall.js @@ -0,0 +1,61 @@ +const glob = require("glob"); +const fs = require("fs"); +const path = require("path"); +const os = require("os"); + +require("find-java-home")((err, home) => { + if (home) { + const dll = glob.sync("**/jvm.dll", { cwd: home })[0]; + const dylib = glob.sync("**/libjli.dylib", { cwd: home })[0]; + const soFiles = glob.sync("**/libjvm.so", { cwd: home }); + + let so; + if (soFiles.length > 0) { + so = getCorrectSoForPlatform(soFiles); + } + + const binary = dll ?? dylib ?? so; + + fs.writeFileSync( + path.resolve(__dirname, "../build/jvm_dll_path.json"), + binary ? JSON.stringify(path.delimiter + path.dirname(path.resolve(home, binary))) : '""' + ); + } +}); + +function getCorrectSoForPlatform(soFiles) { + let so = _getCorrectSoForPlatform(soFiles); + if (so) { + so = removeDuplicateJre(so); + } + return so; +} + +function removeDuplicateJre(filePath) { + while (filePath.indexOf("jre/jre") >= 0) { + filePath = filePath.replace("jre/jre", "jre"); + } + return filePath; +} + +function _getCorrectSoForPlatform(soFiles) { + const architectureFolderNames = { + ia32: "i386", + x64: "amd64", + }; + + if (os.platform() != "sunos") { + return soFiles[0]; + } + + const requiredFolderName = architectureFolderNames[os.arch()]; + + for (let i = 0; i < soFiles.length; i++) { + const so = soFiles[i]; + if (so.indexOf("server") > 0 && so.indexOf(requiredFolderName) > 0) { + return so; + } + } + + return soFiles[0]; +} diff --git a/scripts/testRunner.ts b/scripts/testRunner.ts new file mode 100644 index 00000000..fe36d289 --- /dev/null +++ b/scripts/testRunner.ts @@ -0,0 +1,55 @@ +// testRunner.js + +// This is a custom test runner. All tests are run with vitest, but in separate +// processes, which allows us to test java with different configuration options. + +import chalk from "chalk"; +import findRoot from "find-root"; +import * as glob from "glob"; +import childProcess, { ExecException } from "node:child_process"; +import path from "node:path"; + +const root = findRoot(__dirname); + +const tests = glob + .sync("*.test.ts", { cwd: path.join(root, "testAsyncOptions") }) + .sort((a: string, b: string) => a.toLocaleLowerCase().localeCompare(b.toLocaleLowerCase())); + +tests.unshift("test"); // Arrange to run the primary tests first, in a single process + +async function runTest(testIndex: number, testArgs: string): Promise { + const vitest = path.join("node_modules", ".bin", "vitest"); + const cmd = testArgs === "test" ? `vitest --dir test` : `${vitest} ${testArgs}`; + console.log(chalk.cyan(`(${testIndex + 1}/${tests.length}) running "${cmd}"...`)); + return new Promise((resolve, reject) => { + childProcess.exec(cmd, (error: ExecException | null, stdout: string, stderr: string) => { + const errText = stderr.toString(); + if (errText !== "") { + console.error(chalk.bold.red(errText)); + } + + process.stdout.write(stdout.toString()); + if (error) { + return reject(error); + } + resolve(); + }); + }); +} + +console.log("test to run", tests); +async function runAll(): Promise { + for (let i = 0; i < tests.length; i++) { + const test = tests[i]; + await runTest(i, test); + } +} + +runAll() + .then(() => { + console.log(chalk.green("Tests completed successfully!")); + }) + .catch((err) => { + console.error(chalk.bold.red(err)); + process.exit(1); + }); diff --git a/scripts/update-commons-lang.sh b/scripts/update-commons-lang.sh new file mode 100755 index 00000000..e3eb71ae --- /dev/null +++ b/scripts/update-commons-lang.sh @@ -0,0 +1,9 @@ +#!/bin/sh +set -eu +SCRIPT_DIR=$(dirname $(realpath $0)) + +cd "${SCRIPT_DIR}/commons-lang" +mvn package +cp "${SCRIPT_DIR}/commons-lang/target/commons-lang-1.jar" "${SCRIPT_DIR}/../src-java/commons-lang3-node-java.jar" + +echo "complete!" diff --git a/src/java.cpp b/src-cpp/java.cpp similarity index 76% rename from src/java.cpp rename to src-cpp/java.cpp index fb5cfbd5..e124b4dc 100644 --- a/src/java.cpp +++ b/src-cpp/java.cpp @@ -2,26 +2,27 @@ #include #ifdef WIN32 #else - #include +#include #endif #include "javaObject.h" #include "javaScope.h" #include "methodCallBaton.h" #include "node_NodeDynamicProxyClass.h" +#include #include #include #include -#include #define DYNAMIC_PROXY_JS_ERROR -4 #ifdef WIN32 - typedef long threadId; +typedef long threadId; #else - typedef pthread_t threadId; +typedef pthread_t threadId; #endif threadId v8ThreadId; +bool isDefaultLoopRunning = false; std::queue queue_dynamicProxyJsCallData; uv_mutex_t uvMutex_dynamicProxyJsCall; @@ -60,7 +61,7 @@ void uvAsyncCb_dynamicProxyJsCall(uv_async_t *handle) { DynamicProxyJsCallData *callData; do { uv_mutex_lock(&uvMutex_dynamicProxyJsCall); - if(!queue_dynamicProxyJsCallData.empty()) { + if (!queue_dynamicProxyJsCallData.empty()) { callData = queue_dynamicProxyJsCallData.front(); queue_dynamicProxyJsCallData.pop(); } else { @@ -68,19 +69,19 @@ void uvAsyncCb_dynamicProxyJsCall(uv_async_t *handle) { } uv_mutex_unlock(&uvMutex_dynamicProxyJsCall); - if(callData) { + if (callData) { EIO_CallJs(callData); } - } while(callData); + } while (callData); } /*static*/ void Java::Init(v8::Local target) { Nan::HandleScope scope; v8ThreadId = my_getThreadId(); + isDefaultLoopRunning = false; // init as false uv_mutex_init(&uvMutex_dynamicProxyJsCall); - uv_async_init(uv_default_loop(), &uvAsync_dynamicProxyJsCall, uvAsyncCb_dynamicProxyJsCall); v8::Local t = Nan::New(New); s_ct.Reset(t); @@ -106,6 +107,7 @@ void uvAsyncCb_dynamicProxyJsCall(uv_async_t *handle) { Nan::SetPrototypeMethod(t, "getStaticFieldValue", getStaticFieldValue); Nan::SetPrototypeMethod(t, "setStaticFieldValue", setStaticFieldValue); Nan::SetPrototypeMethod(t, "instanceOf", instanceOf); + Nan::SetPrototypeMethod(t, "stop", stop); Nan::Set(target, Nan::New("Java").ToLocalChecked(), Nan::GetFunction(t).ToLocalChecked()); @@ -115,12 +117,18 @@ void uvAsyncCb_dynamicProxyJsCall(uv_async_t *handle) { NAN_METHOD(Java::New) { Nan::HandleScope scope; + if (!isDefaultLoopRunning) { + uv_async_init(uv_default_loop(), &uvAsync_dynamicProxyJsCall, uvAsyncCb_dynamicProxyJsCall); + isDefaultLoopRunning = true; + } + Java *self = new Java(); self->Wrap(info.This()); Nan::Set(self->handle(), Nan::New("classpath").ToLocalChecked(), Nan::New()); Nan::Set(self->handle(), Nan::New("options").ToLocalChecked(), Nan::New()); - Nan::Set(self->handle(), Nan::New("nativeBindingLocation").ToLocalChecked(), Nan::New("Not Set").ToLocalChecked()); + Nan::Set(self->handle(), Nan::New("nativeBindingLocation").ToLocalChecked(), + Nan::New("Not Set").ToLocalChecked()); Nan::Set(self->handle(), Nan::New("asyncOptions").ToLocalChecked(), Nan::Null()); info.GetReturnValue().Set(info.This()); @@ -137,12 +145,10 @@ Java::Java() { doPromise = false; } -Java::~Java() { - this->destroyJVM(&this->m_jvm, &this->m_env); -} +Java::~Java() { this->destroyJVM(&this->m_jvm, &this->m_env); } v8::Local Java::ensureJvm() { - if(!m_jvm) { + if (!m_jvm) { v8::Local result = createJVM(&this->m_jvm, &this->m_env); assert(result->IsNull()); return result; @@ -151,7 +157,7 @@ v8::Local Java::ensureJvm() { return Nan::Null(); } -void Java::configureAsync(v8::Local& asyncOptions) { +void Java::configureAsync(v8::Local &asyncOptions) { v8::Local asyncOptionsObj = asyncOptions.As(); m_SyncSuffix = "invalid"; @@ -161,7 +167,8 @@ void Java::configureAsync(v8::Local& asyncOptions) { doAsync = false; doPromise = false; - v8::MaybeLocal maybeSuffixValue = Nan::Get(asyncOptionsObj, Nan::New("syncSuffix").ToLocalChecked()); + v8::MaybeLocal maybeSuffixValue = + Nan::Get(asyncOptionsObj, Nan::New("syncSuffix").ToLocalChecked()); v8::Local suffixValue; if (maybeSuffixValue.ToLocal(&suffixValue) && suffixValue->IsString()) { v8::Local suffix = suffixValue->ToString(Nan::GetCurrentContext()).ToLocalChecked(); @@ -183,12 +190,6 @@ void Java::configureAsync(v8::Local& asyncOptions) { v8::Local suffix = suffixValue->ToString(Nan::GetCurrentContext()).ToLocalChecked(); Nan::Utf8String utf8(suffix); m_PromiseSuffix.assign(*utf8); - v8::MaybeLocal maybePromisify = Nan::Get(asyncOptionsObj, Nan::New("promisify").ToLocalChecked()); - v8::Local promisify; - if (maybePromisify.ToLocal(&promisify) && !promisify->IsFunction()) { - fprintf(stderr, "asyncOptions.promisify must be a function"); - assert(promisify->IsFunction()); - } doPromise = true; } @@ -205,8 +206,9 @@ void Java::configureAsync(v8::Local& asyncOptions) { m_asyncOptions.Reset(asyncOptionsObj); } -v8::Local Java::createJVM(JavaVM** jvm, JNIEnv** env) { - v8::MaybeLocal maybeAsyncOptions = Nan::Get(this->handle(), Nan::New("asyncOptions").ToLocalChecked()); +v8::Local Java::createJVM(JavaVM **jvm, JNIEnv **env) { + v8::MaybeLocal maybeAsyncOptions = + Nan::Get(this->handle(), Nan::New("asyncOptions").ToLocalChecked()); v8::Local asyncOptions; if (maybeAsyncOptions.ToLocal(&asyncOptions) && asyncOptions->IsObject()) { configureAsync(asyncOptions); @@ -216,23 +218,24 @@ v8::Local Java::createJVM(JavaVM** jvm, JNIEnv** env) { std::ostringstream classPath; classPath << "-Djava.class.path="; - v8::MaybeLocal maybeClassPathValue = Nan::Get(this->handle(), Nan::New("classpath").ToLocalChecked()); + v8::MaybeLocal maybeClassPathValue = + Nan::Get(this->handle(), Nan::New("classpath").ToLocalChecked()); v8::Local classPathValue; - if(!maybeClassPathValue.ToLocal(&classPathValue) || !classPathValue->IsArray()) { + if (!maybeClassPathValue.ToLocal(&classPathValue) || !classPathValue->IsArray()) { return Nan::TypeError("Classpath must be an array"); } v8::Local classPathArrayTemp = v8::Local::Cast(classPathValue); m_classPathArray.Reset(classPathArrayTemp); - for(uint32_t i=0; iLength(); i++) { - if(i != 0) { - #ifdef WIN32 - classPath << ";"; - #else - classPath << ":"; - #endif + for (uint32_t i = 0; i < classPathArrayTemp->Length(); i++) { + if (i != 0) { +#ifdef WIN32 + classPath << ";"; +#else + classPath << ":"; +#endif } v8::Local arrayItemValue = classPathArrayTemp->Get(Nan::GetCurrentContext(), i).ToLocalChecked(); - if(!arrayItemValue->IsString()) { + if (!arrayItemValue->IsString()) { return Nan::TypeError("Classpath must only contain strings"); } v8::Local arrayItem = arrayItemValue->ToString(Nan::GetCurrentContext()).ToLocalChecked(); @@ -241,13 +244,16 @@ v8::Local Java::createJVM(JavaVM** jvm, JNIEnv** env) { } // set the native binding location - v8::Local v8NativeBindingLocation = Nan::Get(this->handle(), Nan::New("nativeBindingLocation").ToLocalChecked()).FromMaybe(v8::Local()); + v8::Local v8NativeBindingLocation = + Nan::Get(this->handle(), Nan::New("nativeBindingLocation").ToLocalChecked()) + .FromMaybe(v8::Local()); Nan::Utf8String nativeBindingLocationStr(v8NativeBindingLocation); s_nativeBindingLocation = *nativeBindingLocationStr; // get other options - v8::Local optionsValue = Nan::Get(this->handle(), Nan::New("options").ToLocalChecked()).FromMaybe(v8::Local()); - if(!optionsValue->IsArray()) { + v8::Local optionsValue = + Nan::Get(this->handle(), Nan::New("options").ToLocalChecked()).FromMaybe(v8::Local()); + if (!optionsValue->IsArray()) { return Nan::TypeError("options must be an array"); } v8::Local optionsArrayTemp = v8::Local::Cast(optionsValue); @@ -255,18 +261,18 @@ v8::Local Java::createJVM(JavaVM** jvm, JNIEnv** env) { // create vm options int vmOptionsCount = optionsArrayTemp->Length() + 1; - JavaVMOption* vmOptions = new JavaVMOption[vmOptionsCount]; - //printf("classPath: %s\n", classPath.str().c_str()); + JavaVMOption *vmOptions = new JavaVMOption[vmOptionsCount]; + // printf("classPath: %s\n", classPath.str().c_str()); vmOptions[0].optionString = strdup(classPath.str().c_str()); - for(uint32_t i=0; iLength(); i++) { + for (uint32_t i = 0; i < optionsArrayTemp->Length(); i++) { v8::Local arrayItemValue = optionsArrayTemp->Get(Nan::GetCurrentContext(), i).ToLocalChecked(); - if(!arrayItemValue->IsString()) { + if (!arrayItemValue->IsString()) { delete[] vmOptions; return Nan::TypeError("options must only contain strings"); } v8::Local arrayItem = arrayItemValue->ToString(Nan::GetCurrentContext()).ToLocalChecked(); Nan::Utf8String arrayItemStr(arrayItem); - vmOptions[i+1].optionString = strdup(*arrayItemStr); + vmOptions[i + 1].optionString = strdup(*arrayItemStr); } JavaVMInitArgs args; @@ -290,22 +296,29 @@ v8::Local Java::createJVM(JavaVM** jvm, JNIEnv** env) { args.options = vmOptions; args.nOptions = vmOptionsCount; - JavaVM* jvmTemp; + JavaVM *jvmTemp; JNI_CreateJavaVM(&jvmTemp, (void **)env, &args); *jvm = jvmTemp; - delete [] vmOptions; + delete[] vmOptions; m_classLoader = getSystemClassLoader(*env); - v8::Local onJvmCreated = Nan::Get(this->handle(), Nan::New("onJvmCreated").ToLocalChecked()).FromMaybe(v8::Local()); - - // TODO: this handles sets put doesn't prevent modifing the underlying data. So java.classpath.push will still work which is invalid. - Nan::SetAccessor(this->handle(), Nan::New("classpath").ToLocalChecked(), AccessorProhibitsOverwritingGetter, AccessorProhibitsOverwritingSetter); - Nan::SetAccessor(this->handle(), Nan::New("options").ToLocalChecked(), AccessorProhibitsOverwritingGetter, AccessorProhibitsOverwritingSetter); - Nan::SetAccessor(this->handle(), Nan::New("nativeBindingLocation").ToLocalChecked(), AccessorProhibitsOverwritingGetter, AccessorProhibitsOverwritingSetter); - Nan::SetAccessor(this->handle(), Nan::New("asyncOptions").ToLocalChecked(), AccessorProhibitsOverwritingGetter, AccessorProhibitsOverwritingSetter); - Nan::SetAccessor(this->handle(), Nan::New("onJvmCreated").ToLocalChecked(), AccessorProhibitsOverwritingGetter, AccessorProhibitsOverwritingSetter); + v8::Local onJvmCreated = + Nan::Get(this->handle(), Nan::New("onJvmCreated").ToLocalChecked()).FromMaybe(v8::Local()); + + // TODO: this handles sets put doesn't prevent modifing the underlying data. So java.classpath.push will still work + // which is invalid. + Nan::SetAccessor(this->handle(), Nan::New("classpath").ToLocalChecked(), + AccessorProhibitsOverwritingGetter, AccessorProhibitsOverwritingSetter); + Nan::SetAccessor(this->handle(), Nan::New("options").ToLocalChecked(), AccessorProhibitsOverwritingGetter, + AccessorProhibitsOverwritingSetter); + Nan::SetAccessor(this->handle(), Nan::New("nativeBindingLocation").ToLocalChecked(), + AccessorProhibitsOverwritingGetter, AccessorProhibitsOverwritingSetter); + Nan::SetAccessor(this->handle(), Nan::New("asyncOptions").ToLocalChecked(), + AccessorProhibitsOverwritingGetter, AccessorProhibitsOverwritingSetter); + Nan::SetAccessor(this->handle(), Nan::New("onJvmCreated").ToLocalChecked(), + AccessorProhibitsOverwritingGetter, AccessorProhibitsOverwritingSetter); if (onJvmCreated->IsFunction()) { v8::Local onJvmCreatedFunc = onJvmCreated.As(); @@ -317,22 +330,22 @@ v8::Local Java::createJVM(JavaVM** jvm, JNIEnv** env) { } NAN_GETTER(Java::AccessorProhibitsOverwritingGetter) { - Java* self = Nan::ObjectWrap::Unwrap(info.This()); + Java *self = Nan::ObjectWrap::Unwrap(info.This()); Nan::HandleScope scope; Nan::Utf8String nameStr(property); - if(!strcmp("classpath", *nameStr)) { + if (!strcmp("classpath", *nameStr)) { info.GetReturnValue().Set(Nan::New(self->m_classPathArray)); return; - } else if(!strcmp("options", *nameStr)) { + } else if (!strcmp("options", *nameStr)) { info.GetReturnValue().Set(Nan::New(self->m_optionsArray)); return; - } else if(!strcmp("nativeBindingLocation", *nameStr)) { + } else if (!strcmp("nativeBindingLocation", *nameStr)) { info.GetReturnValue().Set(Nan::New(Java::s_nativeBindingLocation.c_str()).ToLocalChecked()); return; - } else if(!strcmp("asyncOptions", *nameStr)) { + } else if (!strcmp("asyncOptions", *nameStr)) { info.GetReturnValue().Set(Nan::New(self->m_asyncOptions)); return; - } else if(!strcmp("onJvmCreated", *nameStr)) { + } else if (!strcmp("onJvmCreated", *nameStr)) { // There is no good reason to get onJvmCreated, so just fall through to error below. } @@ -348,7 +361,7 @@ NAN_SETTER(Java::AccessorProhibitsOverwritingSetter) { Nan::ThrowError(errStr.str().c_str()); } -void Java::destroyJVM(JavaVM** jvm, JNIEnv** env) { +void Java::destroyJVM(JavaVM **jvm, JNIEnv **env) { (*jvm)->DestroyJavaVM(); *jvm = NULL; *env = NULL; @@ -356,17 +369,18 @@ void Java::destroyJVM(JavaVM** jvm, JNIEnv** env) { NAN_METHOD(Java::getClassLoader) { Nan::HandleScope scope; - Java* self = Nan::ObjectWrap::Unwrap(info.This()); + Java *self = Nan::ObjectWrap::Unwrap(info.This()); v8::Local ensureJvmResults = self->ensureJvm(); - if(!ensureJvmResults->IsNull()) { + if (!ensureJvmResults->IsNull()) { info.GetReturnValue().Set(ensureJvmResults); return; } - JNIEnv* env = self->getJavaEnv(); + JNIEnv *env = self->getJavaEnv(); JavaScope javaScope(env); jclass classClazz = env->FindClass("java/lang/ClassLoader"); - jmethodID class_getClassLoader = env->GetStaticMethodID(classClazz, "getSystemClassLoader", "()Ljava/lang/ClassLoader;"); + jmethodID class_getClassLoader = + env->GetStaticMethodID(classClazz, "getSystemClassLoader", "()Ljava/lang/ClassLoader;"); jobject classLoader = env->CallStaticObjectMethod(classClazz, class_getClassLoader); checkJavaException(env); @@ -376,13 +390,13 @@ NAN_METHOD(Java::getClassLoader) { NAN_METHOD(Java::newInstance) { Nan::HandleScope scope; - Java* self = Nan::ObjectWrap::Unwrap(info.This()); + Java *self = Nan::ObjectWrap::Unwrap(info.This()); v8::Local ensureJvmResults = self->ensureJvm(); - if(!ensureJvmResults->IsNull()) { + if (!ensureJvmResults->IsNull()) { info.GetReturnValue().Set(ensureJvmResults); return; } - JNIEnv* env = self->getJavaEnv(); + JNIEnv *env = self->getJavaEnv(); JavaScope javaScope(env); int argsStart = 0; @@ -394,7 +408,7 @@ NAN_METHOD(Java::newInstance) { // find class jclass clazz = javaFindClass(env, className); - if(clazz == NULL) { + if (clazz == NULL) { EXCEPTION_CALL_CALLBACK(self, "Could not find class " << className.c_str()); info.GetReturnValue().SetUndefined(); return; @@ -403,7 +417,7 @@ NAN_METHOD(Java::newInstance) { // get method jobjectArray methodArgs = v8ToJava(env, info, argsStart, argsEnd); jobject method = javaFindConstructor(env, clazz, methodArgs); - if(method == NULL) { + if (method == NULL) { std::string msg = methodNotFoundToString(env, clazz, className, true, info, argsStart, argsEnd); EXCEPTION_CALL_CALLBACK(self, msg); info.GetReturnValue().SetUndefined(); @@ -411,21 +425,22 @@ NAN_METHOD(Java::newInstance) { } // run - NewInstanceBaton* baton = new NewInstanceBaton(self, clazz, method, methodArgs, callback); + NewInstanceBaton *baton = new NewInstanceBaton(self, clazz, method, methodArgs, callback); baton->run(); - END_CALLBACK_FUNCTION("\"Constructor for class '" << className << "' called without a callback did you mean to use the Sync version?\""); + END_CALLBACK_FUNCTION("\"Constructor for class '" + << className << "' called without a callback did you mean to use the Sync version?\""); } NAN_METHOD(Java::newInstanceSync) { Nan::HandleScope scope; - Java* self = Nan::ObjectWrap::Unwrap(info.This()); + Java *self = Nan::ObjectWrap::Unwrap(info.This()); v8::Local ensureJvmResults = self->ensureJvm(); - if(!ensureJvmResults->IsNull()) { + if (!ensureJvmResults->IsNull()) { info.GetReturnValue().Set(ensureJvmResults); return; } - JNIEnv* env = self->getJavaEnv(); + JNIEnv *env = self->getJavaEnv(); JavaScope javaScope(env); int argsStart = 0; @@ -436,7 +451,7 @@ NAN_METHOD(Java::newInstanceSync) { // find class jclass clazz = javaFindClass(env, className); - if(clazz == NULL) { + if (clazz == NULL) { std::ostringstream errStr; errStr << "Could not create class " << className.c_str(); return Nan::ThrowError(javaExceptionToV8(self, env, errStr.str())); @@ -445,17 +460,17 @@ NAN_METHOD(Java::newInstanceSync) { // find method jobjectArray methodArgs = v8ToJava(env, info, argsStart, argsEnd); jobject method = javaFindConstructor(env, clazz, methodArgs); - if(method == NULL) { + if (method == NULL) { std::string msg = methodNotFoundToString(env, clazz, className, true, info, argsStart, argsEnd); return Nan::ThrowError(javaExceptionToV8(self, env, msg)); } // run v8::Local callback = Nan::Null(); - NewInstanceBaton* baton = new NewInstanceBaton(self, clazz, method, methodArgs, callback); + NewInstanceBaton *baton = new NewInstanceBaton(self, clazz, method, methodArgs, callback); v8::Local result = baton->runSync(); delete baton; - if(result->IsNativeError()) { + if (result->IsNativeError()) { return Nan::ThrowError(result); } info.GetReturnValue().Set(result); @@ -463,13 +478,13 @@ NAN_METHOD(Java::newInstanceSync) { NAN_METHOD(Java::newProxy) { Nan::HandleScope scope; - Java* self = Nan::ObjectWrap::Unwrap(info.This()); + Java *self = Nan::ObjectWrap::Unwrap(info.This()); v8::Local ensureJvmResults = self->ensureJvm(); - if(!ensureJvmResults->IsNull()) { + if (!ensureJvmResults->IsNull()) { info.GetReturnValue().Set(ensureJvmResults); return; } - JNIEnv* env = self->getJavaEnv(); + JNIEnv *env = self->getJavaEnv(); JavaScope javaScope(env); int argsStart = 0; @@ -477,7 +492,7 @@ NAN_METHOD(Java::newProxy) { ARGS_FRONT_STRING(interfaceName); ARGS_FRONT_OBJECT(functions); - DynamicProxyData* dynamicProxyData = new DynamicProxyData(); + DynamicProxyData *dynamicProxyData = new DynamicProxyData(); dynamicProxyData->markerStart = DYNAMIC_PROXY_DATA_MARKER_START; dynamicProxyData->markerEnd = DYNAMIC_PROXY_DATA_MARKER_END; dynamicProxyData->java = self; @@ -487,7 +502,7 @@ NAN_METHOD(Java::newProxy) { // find NodeDynamicProxyClass std::string className = "node.NodeDynamicProxyClass"; jclass clazz = javaFindClass(env, className); - if(clazz == NULL) { + if (clazz == NULL) { std::ostringstream errStr; errStr << "Could not create class node/NodeDynamicProxyClass"; delete dynamicProxyData; @@ -497,10 +512,11 @@ NAN_METHOD(Java::newProxy) { // find constructor jclass objectClazz = env->FindClass("java/lang/Object"); jobjectArray methodArgs = env->NewObjectArray(2, objectClazz, NULL); - env->SetObjectArrayElement(methodArgs, 0, v8ToJava(env, Nan::New(s_nativeBindingLocation.c_str()).ToLocalChecked())); + env->SetObjectArrayElement(methodArgs, 0, + v8ToJava(env, Nan::New(s_nativeBindingLocation.c_str()).ToLocalChecked())); env->SetObjectArrayElement(methodArgs, 1, longToJavaLongObj(env, (jlong)dynamicProxyData)); jobject method = javaFindConstructor(env, clazz, methodArgs); - if(method == NULL) { + if (method == NULL) { std::ostringstream errStr; errStr << "Could not find constructor for class node/NodeDynamicProxyClass"; return Nan::ThrowError(javaExceptionToV8(self, env, errStr.str())); @@ -508,20 +524,21 @@ NAN_METHOD(Java::newProxy) { // create the NodeDynamicProxyClass jclass constructorClazz = env->FindClass("java/lang/reflect/Constructor"); - jmethodID constructor_newInstance = env->GetMethodID(constructorClazz, "newInstance", "([Ljava/lang/Object;)Ljava/lang/Object;"); + jmethodID constructor_newInstance = + env->GetMethodID(constructorClazz, "newInstance", "([Ljava/lang/Object;)Ljava/lang/Object;"); - //printf("invoke: %s\n", javaMethodCallToString(env, m_method, constructor_newInstance, m_args).c_str()); + // printf("invoke: %s\n", javaMethodCallToString(env, m_method, constructor_newInstance, m_args).c_str()); // run constructor jobject dynamicProxy = env->CallObjectMethod(method, constructor_newInstance, methodArgs); - if(env->ExceptionCheck()) { + if (env->ExceptionCheck()) { std::ostringstream errStr; errStr << "Error creating class"; return Nan::ThrowError(javaExceptionToV8(self, env, errStr.str())); } jclass dynamicInterface = javaFindClass(env, interfaceName); - if(dynamicInterface == NULL) { + if (dynamicInterface == NULL) { std::ostringstream errStr; errStr << "Could not find interface "; errStr << interfaceName; @@ -529,7 +546,7 @@ NAN_METHOD(Java::newProxy) { } jclass classClazz = env->FindClass("java/lang/Class"); jobjectArray classArray = env->NewObjectArray(1, classClazz, NULL); - if(classArray == NULL) { + if (classArray == NULL) { std::ostringstream errStr; errStr << "Could not create class array for Proxy"; return Nan::ThrowError(javaExceptionToV8(self, env, errStr.str())); @@ -540,7 +557,7 @@ NAN_METHOD(Java::newProxy) { jobject classLoader = env->CallObjectMethod(dynamicInterface, class_getClassLoader); assertNoException(env); - if(classLoader == NULL) { + if (classLoader == NULL) { jclass objectClazz = env->FindClass("java/lang/Object"); jmethodID object_getClass = env->GetMethodID(objectClazz, "getClass", "()Ljava/lang/Class;"); jobject jobjClass = env->CallObjectMethod(dynamicProxy, object_getClass); @@ -548,7 +565,7 @@ NAN_METHOD(Java::newProxy) { classLoader = env->CallObjectMethod(jobjClass, class_getClassLoader); checkJavaException(env); } - if(classLoader == NULL) { + if (classLoader == NULL) { std::ostringstream errStr; errStr << "Could not get classloader for Proxy"; return Nan::ThrowError(javaExceptionToV8(self, env, errStr.str())); @@ -556,9 +573,12 @@ NAN_METHOD(Java::newProxy) { // create proxy instance jclass proxyClass = env->FindClass("java/lang/reflect/Proxy"); - jmethodID proxy_newProxyInstance = env->GetStaticMethodID(proxyClass, "newProxyInstance", "(Ljava/lang/ClassLoader;[Ljava/lang/Class;Ljava/lang/reflect/InvocationHandler;)Ljava/lang/Object;"); - jobject proxyInstance = env->CallStaticObjectMethod(proxyClass, proxy_newProxyInstance, classLoader, classArray, dynamicProxy); - if(env->ExceptionCheck()) { + jmethodID proxy_newProxyInstance = env->GetStaticMethodID( + proxyClass, "newProxyInstance", + "(Ljava/lang/ClassLoader;[Ljava/lang/Class;Ljava/lang/reflect/InvocationHandler;)Ljava/lang/Object;"); + jobject proxyInstance = + env->CallStaticObjectMethod(proxyClass, proxy_newProxyInstance, classLoader, classArray, dynamicProxy); + if (env->ExceptionCheck()) { std::ostringstream errStr; errStr << "Error creating java.lang.reflect.Proxy"; return Nan::ThrowError(javaExceptionToV8(self, env, errStr.str())); @@ -572,13 +592,13 @@ NAN_METHOD(Java::newProxy) { NAN_METHOD(Java::callStaticMethod) { Nan::HandleScope scope; - Java* self = Nan::ObjectWrap::Unwrap(info.This()); + Java *self = Nan::ObjectWrap::Unwrap(info.This()); v8::Local ensureJvmResults = self->ensureJvm(); - if(!ensureJvmResults->IsNull()) { + if (!ensureJvmResults->IsNull()) { info.GetReturnValue().Set(ensureJvmResults); return; } - JNIEnv* env = self->getJavaEnv(); + JNIEnv *env = self->getJavaEnv(); JavaScope javaScope(env); int argsStart = 0; @@ -591,7 +611,7 @@ NAN_METHOD(Java::callStaticMethod) { // find class jclass clazz = javaFindClass(env, className); - if(clazz == NULL) { + if (clazz == NULL) { EXCEPTION_CALL_CALLBACK(self, "Could not create class " << className.c_str()); info.GetReturnValue().SetUndefined(); return; @@ -600,7 +620,7 @@ NAN_METHOD(Java::callStaticMethod) { // find method jobjectArray methodArgs = v8ToJava(env, info, argsStart, argsEnd); jobject method = javaFindMethod(env, clazz, methodName, methodArgs); - if(method == NULL) { + if (method == NULL) { std::string msg = methodNotFoundToString(env, clazz, methodName, false, info, argsStart, argsEnd); EXCEPTION_CALL_CALLBACK(self, msg); info.GetReturnValue().SetUndefined(); @@ -608,21 +628,22 @@ NAN_METHOD(Java::callStaticMethod) { } // run - StaticMethodCallBaton* baton = new StaticMethodCallBaton(self, clazz, method, methodArgs, callback); + StaticMethodCallBaton *baton = new StaticMethodCallBaton(self, clazz, method, methodArgs, callback); baton->run(); - END_CALLBACK_FUNCTION("\"Static method '" << methodName << "' called without a callback did you mean to use the Sync version?\""); + END_CALLBACK_FUNCTION("\"Static method '" << methodName + << "' called without a callback did you mean to use the Sync version?\""); } NAN_METHOD(Java::callStaticMethodSync) { Nan::HandleScope scope; - Java* self = Nan::ObjectWrap::Unwrap(info.This()); + Java *self = Nan::ObjectWrap::Unwrap(info.This()); v8::Local ensureJvmResults = self->ensureJvm(); - if(!ensureJvmResults->IsNull()) { + if (!ensureJvmResults->IsNull()) { info.GetReturnValue().Set(ensureJvmResults); return; } - JNIEnv* env = self->getJavaEnv(); + JNIEnv *env = self->getJavaEnv(); JavaScope javaScope(env); int argsStart = 0; @@ -634,7 +655,7 @@ NAN_METHOD(Java::callStaticMethodSync) { // find class jclass clazz = javaFindClass(env, className); - if(clazz == NULL) { + if (clazz == NULL) { std::ostringstream errStr; errStr << "Could not create class " << className.c_str(); return Nan::ThrowError(javaExceptionToV8(self, env, errStr.str())); @@ -643,17 +664,17 @@ NAN_METHOD(Java::callStaticMethodSync) { // find method jobjectArray methodArgs = v8ToJava(env, info, argsStart, argsEnd); jobject method = javaFindMethod(env, clazz, methodName, methodArgs); - if(method == NULL) { + if (method == NULL) { std::string msg = methodNotFoundToString(env, clazz, methodName, false, info, argsStart, argsEnd); return Nan::ThrowError(javaExceptionToV8(self, env, msg)); } // run v8::Local callback = Nan::Null(); - StaticMethodCallBaton* baton = new StaticMethodCallBaton(self, clazz, method, methodArgs, callback); + StaticMethodCallBaton *baton = new StaticMethodCallBaton(self, clazz, method, methodArgs, callback); v8::Local result = baton->runSync(); delete baton; - if(result->IsNativeError()) { + if (result->IsNativeError()) { Nan::ThrowError(result); return; } @@ -662,13 +683,13 @@ NAN_METHOD(Java::callStaticMethodSync) { NAN_METHOD(Java::callMethodSync) { Nan::HandleScope scope; - Java* self = Nan::ObjectWrap::Unwrap(info.This()); + Java *self = Nan::ObjectWrap::Unwrap(info.This()); v8::Local ensureJvmResults = self->ensureJvm(); - if(!ensureJvmResults->IsNull()) { + if (!ensureJvmResults->IsNull()) { info.GetReturnValue().Set(ensureJvmResults); return; } - JNIEnv* env = self->getJavaEnv(); + JNIEnv *env = self->getJavaEnv(); JavaScope javaScope(env); int argsStart = 0; @@ -678,23 +699,23 @@ NAN_METHOD(Java::callMethodSync) { ARGS_FRONT_OBJECT(instanceObj); ARGS_FRONT_STRING(methodName); - JavaObject* javaObj = Nan::ObjectWrap::Unwrap(instanceObj); + JavaObject *javaObj = Nan::ObjectWrap::Unwrap(instanceObj); // find method jclass clazz = javaObj->getClass(); jobjectArray methodArgs = v8ToJava(env, info, argsStart, argsEnd); jobject method = javaFindMethod(env, clazz, methodName, methodArgs); - if(method == NULL) { + if (method == NULL) { std::string msg = methodNotFoundToString(env, clazz, methodName, false, info, argsStart, argsEnd); return Nan::ThrowError(javaExceptionToV8(self, env, msg)); } // run v8::Local callback = Nan::Null(); - InstanceMethodCallBaton* baton = new InstanceMethodCallBaton(self, javaObj, method, methodArgs, callback); + InstanceMethodCallBaton *baton = new InstanceMethodCallBaton(self, javaObj, method, methodArgs, callback); v8::Local result = baton->runSync(); delete baton; - if(result->IsNativeError()) { + if (result->IsNativeError()) { return Nan::ThrowError(result); } info.GetReturnValue().Set(result); @@ -702,13 +723,13 @@ NAN_METHOD(Java::callMethodSync) { NAN_METHOD(Java::callMethod) { Nan::HandleScope scope; - Java* self = Nan::ObjectWrap::Unwrap(info.This()); + Java *self = Nan::ObjectWrap::Unwrap(info.This()); v8::Local ensureJvmResults = self->ensureJvm(); - if(!ensureJvmResults->IsNull()) { + if (!ensureJvmResults->IsNull()) { info.GetReturnValue().Set(ensureJvmResults); return; } - JNIEnv* env = self->getJavaEnv(); + JNIEnv *env = self->getJavaEnv(); JavaScope javaScope(env); int argsStart = 0; @@ -719,13 +740,13 @@ NAN_METHOD(Java::callMethod) { ARGS_FRONT_STRING(methodName); ARGS_BACK_CALLBACK(); - JavaObject* javaObj = Nan::ObjectWrap::Unwrap(instanceObj); + JavaObject *javaObj = Nan::ObjectWrap::Unwrap(instanceObj); // find method jclass clazz = javaObj->getClass(); jobjectArray methodArgs = v8ToJava(env, info, argsStart, argsEnd); jobject method = javaFindMethod(env, clazz, methodName, methodArgs); - if(method == NULL) { + if (method == NULL) { std::string msg = methodNotFoundToString(env, clazz, methodName, false, info, argsStart, argsEnd); EXCEPTION_CALL_CALLBACK(self, msg); info.GetReturnValue().SetUndefined(); @@ -733,21 +754,22 @@ NAN_METHOD(Java::callMethod) { } // run - InstanceMethodCallBaton* baton = new InstanceMethodCallBaton(self, javaObj, method, methodArgs, callback); + InstanceMethodCallBaton *baton = new InstanceMethodCallBaton(self, javaObj, method, methodArgs, callback); baton->run(); - END_CALLBACK_FUNCTION("\"method '" << methodName << "' called without a callback did you mean to use the Sync version?\""); + END_CALLBACK_FUNCTION("\"method '" << methodName + << "' called without a callback did you mean to use the Sync version?\""); } NAN_METHOD(Java::findClassSync) { Nan::HandleScope scope; - Java* self = Nan::ObjectWrap::Unwrap(info.This()); + Java *self = Nan::ObjectWrap::Unwrap(info.This()); v8::Local ensureJvmResults = self->ensureJvm(); - if(!ensureJvmResults->IsNull()) { + if (!ensureJvmResults->IsNull()) { info.GetReturnValue().Set(ensureJvmResults); return; } - JNIEnv* env = self->getJavaEnv(); + JNIEnv *env = self->getJavaEnv(); JavaScope javaScope(env); int argsStart = 0; @@ -757,7 +779,7 @@ NAN_METHOD(Java::findClassSync) { // find class jclass clazz = javaFindClass(env, className); - if(clazz == NULL) { + if (clazz == NULL) { std::ostringstream errStr; errStr << "Could not create class " << className.c_str(); return Nan::ThrowError(javaExceptionToV8(self, env, errStr.str())); @@ -770,13 +792,13 @@ NAN_METHOD(Java::findClassSync) { NAN_METHOD(Java::newArray) { Nan::HandleScope scope; - Java* self = Nan::ObjectWrap::Unwrap(info.This()); + Java *self = Nan::ObjectWrap::Unwrap(info.This()); v8::Local ensureJvmResults = self->ensureJvm(); - if(!ensureJvmResults->IsNull()) { + if (!ensureJvmResults->IsNull()) { info.GetReturnValue().Set(ensureJvmResults); return; } - JNIEnv* env = self->getJavaEnv(); + JNIEnv *env = self->getJavaEnv(); JavaScope javaScope(env); int argsStart = 0; @@ -785,18 +807,18 @@ NAN_METHOD(Java::newArray) { ARGS_FRONT_CLASSNAME(); // argument - array - if(info.Length() < argsStart+1 || !info[argsStart]->IsArray()) { + if (info.Length() < argsStart + 1 || !info[argsStart]->IsArray()) { std::ostringstream errStr; - errStr << "Argument " << (argsStart+1) << " must be an array"; + errStr << "Argument " << (argsStart + 1) << " must be an array"; return Nan::ThrowError(Nan::TypeError(errStr.str().c_str())); } v8::Local arrayObj = v8::Local::Cast(info[argsStart]); // find class and method jarray results; - if(strcmp(className.c_str(), "byte") == 0) { + if (strcmp(className.c_str(), "byte") == 0) { results = env->NewByteArray(arrayObj->Length()); - for(uint32_t i=0; iLength(); i++) { + for (uint32_t i = 0; i < arrayObj->Length(); i++) { v8::Local item = arrayObj->Get(Nan::GetCurrentContext(), i).ToLocalChecked(); jobject val = v8ToJava(env, item); jclass byteClazz = env->FindClass("java/lang/Byte"); @@ -808,9 +830,9 @@ NAN_METHOD(Java::newArray) { } } - else if(strcmp(className.c_str(), "char") == 0) { + else if (strcmp(className.c_str(), "char") == 0) { results = env->NewCharArray(arrayObj->Length()); - for(uint32_t i=0; iLength(); i++) { + for (uint32_t i = 0; i < arrayObj->Length(); i++) { v8::Local item = arrayObj->Get(Nan::GetCurrentContext(), i).ToLocalChecked(); jobject val = v8ToJava(env, item); jclass stringClazz = env->FindClass("java/lang/String"); @@ -822,9 +844,9 @@ NAN_METHOD(Java::newArray) { } } - else if(strcmp(className.c_str(), "short") == 0) { + else if (strcmp(className.c_str(), "short") == 0) { results = env->NewShortArray(arrayObj->Length()); - for(uint32_t i=0; iLength(); i++) { + for (uint32_t i = 0; i < arrayObj->Length(); i++) { v8::Local item = arrayObj->Get(Nan::GetCurrentContext(), i).ToLocalChecked(); jobject val = v8ToJava(env, item); jclass shortClazz = env->FindClass("java/lang/Short"); @@ -836,9 +858,9 @@ NAN_METHOD(Java::newArray) { } } - else if(strcmp(className.c_str(), "double") == 0) { + else if (strcmp(className.c_str(), "double") == 0) { results = env->NewDoubleArray(arrayObj->Length()); - for(uint32_t i=0; iLength(); i++) { + for (uint32_t i = 0; i < arrayObj->Length(); i++) { v8::Local item = arrayObj->Get(Nan::GetCurrentContext(), i).ToLocalChecked(); jobject val = v8ToJava(env, item); jclass doubleClazz = env->FindClass("java/lang/Double"); @@ -850,9 +872,9 @@ NAN_METHOD(Java::newArray) { } } - else if(strcmp(className.c_str(), "int") == 0) { + else if (strcmp(className.c_str(), "int") == 0) { results = env->NewIntArray(arrayObj->Length()); - for(uint32_t i=0; iLength(); i++) { + for (uint32_t i = 0; i < arrayObj->Length(); i++) { v8::Local item = arrayObj->Get(Nan::GetCurrentContext(), i).ToLocalChecked(); jobject val = v8ToJava(env, item); jclass integerClazz = env->FindClass("java/lang/Integer"); @@ -864,9 +886,9 @@ NAN_METHOD(Java::newArray) { } } - else if(strcmp(className.c_str(), "float") == 0) { + else if (strcmp(className.c_str(), "float") == 0) { results = env->NewFloatArray(arrayObj->Length()); - for(uint32_t i=0; iLength(); i++) { + for (uint32_t i = 0; i < arrayObj->Length(); i++) { v8::Local item = arrayObj->Get(Nan::GetCurrentContext(), i).ToLocalChecked(); jobject val = v8ToJava(env, item); jclass floatClazz = env->FindClass("java/lang/Float"); @@ -878,9 +900,9 @@ NAN_METHOD(Java::newArray) { } } - else if(strcmp(className.c_str(), "boolean") == 0) { + else if (strcmp(className.c_str(), "boolean") == 0) { results = env->NewBooleanArray(arrayObj->Length()); - for(uint32_t i=0; iLength(); i++) { + for (uint32_t i = 0; i < arrayObj->Length(); i++) { v8::Local item = arrayObj->Get(Nan::GetCurrentContext(), i).ToLocalChecked(); jobject val = v8ToJava(env, item); jclass booleanClazz = env->FindClass("java/lang/Boolean"); @@ -892,10 +914,9 @@ NAN_METHOD(Java::newArray) { } } - else - { + else { jclass clazz = javaFindClass(env, className); - if(clazz == NULL) { + if (clazz == NULL) { std::ostringstream errStr; errStr << "Could not create class " << className.c_str(); return Nan::ThrowError(javaExceptionToV8(self, env, errStr.str())); @@ -904,11 +925,11 @@ NAN_METHOD(Java::newArray) { // create array results = env->NewObjectArray(arrayObj->Length(), clazz, NULL); - for(uint32_t i=0; iLength(); i++) { + for (uint32_t i = 0; i < arrayObj->Length(); i++) { v8::Local item = arrayObj->Get(Nan::GetCurrentContext(), i).ToLocalChecked(); jobject val = v8ToJava(env, item); env->SetObjectArrayElement((jobjectArray)results, i, val); - if(env->ExceptionOccurred()) { + if (env->ExceptionOccurred()) { std::ostringstream errStr; Nan::Utf8String valStr(item); errStr << "Could not add item \"" << *valStr << "\" to array."; @@ -922,21 +943,21 @@ NAN_METHOD(Java::newArray) { NAN_METHOD(Java::newByte) { Nan::HandleScope scope; - Java* self = Nan::ObjectWrap::Unwrap(info.This()); + Java *self = Nan::ObjectWrap::Unwrap(info.This()); v8::Local ensureJvmResults = self->ensureJvm(); - if(!ensureJvmResults->IsNull()) { + if (!ensureJvmResults->IsNull()) { info.GetReturnValue().Set(ensureJvmResults); return; } - JNIEnv* env = self->getJavaEnv(); + JNIEnv *env = self->getJavaEnv(); JavaScope javaScope(env); - if(info.Length() != 1) { + if (info.Length() != 1) { return Nan::ThrowError(Nan::TypeError("newByte only takes 1 argument")); } // argument - value - if(!info[0]->IsNumber()) { + if (!info[0]->IsNumber()) { return Nan::ThrowError(Nan::TypeError("Argument 1 must be a number")); } @@ -952,21 +973,21 @@ NAN_METHOD(Java::newByte) { NAN_METHOD(Java::newShort) { Nan::HandleScope scope; - Java* self = Nan::ObjectWrap::Unwrap(info.This()); + Java *self = Nan::ObjectWrap::Unwrap(info.This()); v8::Local ensureJvmResults = self->ensureJvm(); - if(!ensureJvmResults->IsNull()) { + if (!ensureJvmResults->IsNull()) { info.GetReturnValue().Set(ensureJvmResults); return; } - JNIEnv* env = self->getJavaEnv(); + JNIEnv *env = self->getJavaEnv(); JavaScope javaScope(env); - if(info.Length() != 1) { + if (info.Length() != 1) { return Nan::ThrowError(Nan::TypeError("newShort only takes 1 argument")); } // argument - value - if(!info[0]->IsNumber()) { + if (!info[0]->IsNumber()) { return Nan::ThrowError(Nan::TypeError("Argument 1 must be a number")); } @@ -981,21 +1002,21 @@ NAN_METHOD(Java::newShort) { NAN_METHOD(Java::newLong) { Nan::HandleScope scope; - Java* self = Nan::ObjectWrap::Unwrap(info.This()); + Java *self = Nan::ObjectWrap::Unwrap(info.This()); v8::Local ensureJvmResults = self->ensureJvm(); - if(!ensureJvmResults->IsNull()) { + if (!ensureJvmResults->IsNull()) { info.GetReturnValue().Set(ensureJvmResults); return; } - JNIEnv* env = self->getJavaEnv(); + JNIEnv *env = self->getJavaEnv(); JavaScope javaScope(env); - if(info.Length() != 1) { + if (info.Length() != 1) { return Nan::ThrowError(Nan::TypeError("newLong only takes 1 argument")); } // argument - value - if(!info[0]->IsNumber()) { + if (!info[0]->IsNumber()) { return Nan::ThrowError(Nan::TypeError("Argument 1 must be a number")); } @@ -1010,26 +1031,26 @@ NAN_METHOD(Java::newLong) { NAN_METHOD(Java::newChar) { Nan::HandleScope scope; - Java* self = Nan::ObjectWrap::Unwrap(info.This()); + Java *self = Nan::ObjectWrap::Unwrap(info.This()); v8::Local ensureJvmResults = self->ensureJvm(); - if(!ensureJvmResults->IsNull()) { + if (!ensureJvmResults->IsNull()) { info.GetReturnValue().Set(ensureJvmResults); return; } - JNIEnv* env = self->getJavaEnv(); + JNIEnv *env = self->getJavaEnv(); JavaScope javaScope(env); - if(info.Length() != 1) { + if (info.Length() != 1) { return Nan::ThrowError(Nan::TypeError("newChar only takes 1 argument")); } // argument - value jchar charVal; - if(info[0]->IsNumber()) { + if (info[0]->IsNumber()) { charVal = (jchar)Nan::To(info[0]).FromJust(); - } else if(info[0]->IsString()) { + } else if (info[0]->IsString()) { v8::Local val = info[0]->ToString(Nan::GetCurrentContext()).ToLocalChecked(); - if(val->Length() != 1) { + if (val->Length() != 1) { return Nan::ThrowError(Nan::TypeError("Argument 1 must be a string of 1 character.")); } std::string strVal = std::string(*Nan::Utf8String(val)); @@ -1047,18 +1068,18 @@ NAN_METHOD(Java::newChar) { NAN_METHOD(Java::newFloat) { Nan::HandleScope scope; - Java* self = Nan::ObjectWrap::Unwrap(info.This()); + Java *self = Nan::ObjectWrap::Unwrap(info.This()); v8::Local ensureJvmResults = self->ensureJvm(); - if(!ensureJvmResults->IsNull()) { + if (!ensureJvmResults->IsNull()) { info.GetReturnValue().Set(ensureJvmResults); return; } - JNIEnv* env = self->getJavaEnv(); + JNIEnv *env = self->getJavaEnv(); JavaScope javaScope(env); - if(info.Length() != 1) { + if (info.Length() != 1) { return Nan::ThrowError(Nan::TypeError("newFloat only takes 1 argument")); - } else if(!info[0]->IsNumber()) { + } else if (!info[0]->IsNumber()) { return Nan::ThrowError(Nan::TypeError("Argument 1 must be a number")); } jfloat val = (jfloat)Nan::To(info[0]).FromJust(); @@ -1072,18 +1093,18 @@ NAN_METHOD(Java::newFloat) { NAN_METHOD(Java::newDouble) { Nan::HandleScope scope; - Java* self = Nan::ObjectWrap::Unwrap(info.This()); + Java *self = Nan::ObjectWrap::Unwrap(info.This()); v8::Local ensureJvmResults = self->ensureJvm(); - if(!ensureJvmResults->IsNull()) { + if (!ensureJvmResults->IsNull()) { info.GetReturnValue().Set(ensureJvmResults); return; } - JNIEnv* env = self->getJavaEnv(); + JNIEnv *env = self->getJavaEnv(); JavaScope javaScope(env); - if(info.Length() != 1) { + if (info.Length() != 1) { return Nan::ThrowError(Nan::TypeError("newDouble only takes 1 argument")); - } else if(!info[0]->IsNumber()) { + } else if (!info[0]->IsNumber()) { return Nan::ThrowError(Nan::TypeError("Argument 1 must be a number")); } @@ -1098,13 +1119,13 @@ NAN_METHOD(Java::newDouble) { NAN_METHOD(Java::getStaticFieldValue) { Nan::HandleScope scope; - Java* self = Nan::ObjectWrap::Unwrap(info.This()); + Java *self = Nan::ObjectWrap::Unwrap(info.This()); v8::Local ensureJvmResults = self->ensureJvm(); - if(!ensureJvmResults->IsNull()) { + if (!ensureJvmResults->IsNull()) { info.GetReturnValue().Set(ensureJvmResults); return; } - JNIEnv* env = self->getJavaEnv(); + JNIEnv *env = self->getJavaEnv(); JavaScope javaScope(env); int argsStart = 0; @@ -1115,7 +1136,7 @@ NAN_METHOD(Java::getStaticFieldValue) { // find the class jclass clazz = javaFindClass(env, className); - if(clazz == NULL) { + if (clazz == NULL) { std::ostringstream errStr; errStr << "Could not create class " << className.c_str(); return Nan::ThrowError(javaExceptionToV8(self, env, errStr.str())); @@ -1123,7 +1144,7 @@ NAN_METHOD(Java::getStaticFieldValue) { // get the field jobject field = javaFindField(env, clazz, fieldName); - if(field == NULL) { + if (field == NULL) { std::ostringstream errStr; errStr << "Could not find field \"" << fieldName.c_str() << "\" on class \"" << className.c_str() << "\""; return Nan::ThrowError(javaExceptionToV8(self, env, errStr.str())); @@ -1134,7 +1155,7 @@ NAN_METHOD(Java::getStaticFieldValue) { // get field value jobject val = env->CallObjectMethod(field, field_get, NULL); - if(env->ExceptionOccurred()) { + if (env->ExceptionOccurred()) { std::ostringstream errStr; errStr << "Could not get field " << fieldName.c_str() << " on class " << className.c_str(); return Nan::ThrowError(javaExceptionToV8(self, env, errStr.str())); @@ -1145,13 +1166,13 @@ NAN_METHOD(Java::getStaticFieldValue) { NAN_METHOD(Java::setStaticFieldValue) { Nan::HandleScope scope; - Java* self = Nan::ObjectWrap::Unwrap(info.This()); + Java *self = Nan::ObjectWrap::Unwrap(info.This()); v8::Local ensureJvmResults = self->ensureJvm(); - if(!ensureJvmResults->IsNull()) { + if (!ensureJvmResults->IsNull()) { info.GetReturnValue().Set(ensureJvmResults); return; } - JNIEnv* env = self->getJavaEnv(); + JNIEnv *env = self->getJavaEnv(); JavaScope javaScope(env); int argsStart = 0; @@ -1161,9 +1182,9 @@ NAN_METHOD(Java::setStaticFieldValue) { ARGS_FRONT_STRING(fieldName); // argument - new value - if(info.Length() < argsStart+1) { + if (info.Length() < argsStart + 1) { std::ostringstream errStr; - errStr << "setStaticFieldValue requires " << (argsStart+1) << " arguments"; + errStr << "setStaticFieldValue requires " << (argsStart + 1) << " arguments"; Nan::ThrowError(Nan::TypeError(errStr.str().c_str())); return; } @@ -1172,7 +1193,7 @@ NAN_METHOD(Java::setStaticFieldValue) { // find the class jclass clazz = javaFindClass(env, className); - if(clazz == NULL) { + if (clazz == NULL) { std::ostringstream errStr; errStr << "Could not create class " << className.c_str(); Nan::ThrowError(javaExceptionToV8(self, env, errStr.str())); @@ -1181,7 +1202,7 @@ NAN_METHOD(Java::setStaticFieldValue) { // get the field jobject field = javaFindField(env, clazz, fieldName); - if(field == NULL) { + if (field == NULL) { std::ostringstream errStr; errStr << "Could not find field \"" << fieldName.c_str() << "\" on class \"" << className.c_str() << "\""; Nan::ThrowError(javaExceptionToV8(self, env, errStr.str())); @@ -1191,11 +1212,11 @@ NAN_METHOD(Java::setStaticFieldValue) { jclass fieldClazz = env->FindClass("java/lang/reflect/Field"); jmethodID field_set = env->GetMethodID(fieldClazz, "set", "(Ljava/lang/Object;Ljava/lang/Object;)V"); - //printf("newValue: %s\n", javaObjectToString(env, newValue).c_str()); + // printf("newValue: %s\n", javaObjectToString(env, newValue).c_str()); // set field value env->CallObjectMethod(field, field_set, NULL, newValue); - if(env->ExceptionOccurred()) { + if (env->ExceptionOccurred()) { std::ostringstream errStr; errStr << "Could not set field " << fieldName.c_str() << " on class " << className.c_str(); Nan::ThrowError(javaExceptionToV8(self, env, errStr.str())); @@ -1207,13 +1228,13 @@ NAN_METHOD(Java::setStaticFieldValue) { NAN_METHOD(Java::instanceOf) { Nan::HandleScope scope; - Java* self = Nan::ObjectWrap::Unwrap(info.This()); + Java *self = Nan::ObjectWrap::Unwrap(info.This()); v8::Local ensureJvmResults = self->ensureJvm(); - if(!ensureJvmResults->IsNull()) { + if (!ensureJvmResults->IsNull()) { info.GetReturnValue().Set(ensureJvmResults); return; } - JNIEnv* env = self->getJavaEnv(); + JNIEnv *env = self->getJavaEnv(); JavaScope javaScope(env); int argsStart = 0; @@ -1228,7 +1249,7 @@ NAN_METHOD(Java::instanceOf) { } jclass clazz = javaFindClass(env, className); - if(!clazz) { + if (!clazz) { std::ostringstream errStr; errStr << "Could not find class " << className.c_str(); Nan::ThrowError(javaExceptionToV8(self, env, errStr.str())); @@ -1239,25 +1260,30 @@ NAN_METHOD(Java::instanceOf) { info.GetReturnValue().Set(Nan::New(res)); } -template -std::string to_string(T value) { +NAN_METHOD(Java::stop) { + if (isDefaultLoopRunning) { + uv_close((uv_handle_t *)&uvAsync_dynamicProxyJsCall, NULL); + } +} + +template std::string to_string(T value) { std::ostringstream os; os << value; return os.str(); } void EIO_CallJs(DynamicProxyJsCallData *callData) { - DynamicProxyData* dynamicProxyData = callData->dynamicProxyData; + DynamicProxyData *dynamicProxyData = callData->dynamicProxyData; assert(callData->done == 0); - if(!dynamicProxyDataVerify(dynamicProxyData)) { + if (!dynamicProxyDataVerify(dynamicProxyData)) { return; } callData->result = NULL; - JNIEnv* env; - int ret = dynamicProxyData->java->getJvm()->GetEnv((void**)&env, JNI_BEST_VERSION); + JNIEnv *env; + int ret = dynamicProxyData->java->getJvm()->GetEnv((void **)&env, JNI_BEST_VERSION); if (ret != JNI_OK) { callData->throwableClass = "java/lang/IllegalStateException"; callData->throwableMessage = "Could not retrieve JNIEnv: jvm->GetEnv returned " + to_string(ret); @@ -1266,23 +1292,26 @@ void EIO_CallJs(DynamicProxyJsCallData *callData) { } Nan::HandleScope scope; - v8::Array* v8Args; + v8::Array *v8Args; v8::Local fn; - v8::Local* argv; + v8::Local *argv; int argc; int i; v8::Local v8Result; jobject javaResult; v8::Local dynamicProxyDataFunctions = Nan::New(dynamicProxyData->functions); - v8::Local fnObj = dynamicProxyDataFunctions->Get(Nan::GetCurrentContext(), Nan::New(callData->methodName.c_str()).ToLocalChecked()).ToLocalChecked(); - if(fnObj->IsUndefined() || fnObj->IsNull()) { + v8::Local fnObj = + dynamicProxyDataFunctions + ->Get(Nan::GetCurrentContext(), Nan::New(callData->methodName.c_str()).ToLocalChecked()) + .ToLocalChecked(); + if (fnObj->IsUndefined() || fnObj->IsNull()) { callData->throwableClass = "java/lang/NoSuchMethodError"; callData->throwableMessage = "Could not find js function " + callData->methodName; callData->done = DYNAMIC_PROXY_JS_ERROR; return; } - if(!fnObj->IsFunction()) { + if (!fnObj->IsFunction()) { callData->throwableClass = "java/lang/IllegalStateException"; callData->throwableMessage = callData->methodName + " is not a function"; callData->done = DYNAMIC_PROXY_JS_ERROR; @@ -1291,14 +1320,14 @@ void EIO_CallJs(DynamicProxyJsCallData *callData) { fn = fnObj.As(); - if(callData->args) { + if (callData->args) { v8Args = v8::Array::Cast(*javaArrayToV8(dynamicProxyData->java, env, callData->args)); argc = v8Args->Length(); } else { argc = 0; } argv = new v8::Local[argc]; - for(i=0; iGet(Nan::GetCurrentContext(), i).ToLocalChecked(); } @@ -1315,12 +1344,12 @@ void EIO_CallJs(DynamicProxyJsCallData *callData) { return; } - if(!dynamicProxyDataVerify(dynamicProxyData)) { + if (!dynamicProxyDataVerify(dynamicProxyData)) { return; } javaResult = v8ToJava(env, v8Result); - if(javaResult == NULL) { + if (javaResult == NULL) { callData->result = NULL; } else { callData->result = env->NewGlobalRef(javaResult); @@ -1329,7 +1358,7 @@ void EIO_CallJs(DynamicProxyJsCallData *callData) { callData->done = true; } -void throwNewThrowable(JNIEnv* env, const char * excClassName, std::string msg) { +void throwNewThrowable(JNIEnv *env, const char *excClassName, std::string msg) { jclass newExcCls = env->FindClass(excClassName); jthrowable throwable = env->ExceptionOccurred(); if (throwable != NULL) { @@ -1338,12 +1367,13 @@ void throwNewThrowable(JNIEnv* env, const char * excClassName, std::string msg) env->ThrowNew(newExcCls, msg.c_str()); } -JNIEXPORT jobject JNICALL Java_node_NodeDynamicProxyClass_callJs(JNIEnv *env, jobject src, jlong ptr, jobject method, jobjectArray args) { +JNIEXPORT jobject JNICALL Java_node_NodeDynamicProxyClass_callJs(JNIEnv *env, jobject src, jlong ptr, jobject method, + jobjectArray args) { threadId myThreadId = my_getThreadId(); bool hasArgsGlobalRef = false; - DynamicProxyData* dynamicProxyData = (DynamicProxyData*)ptr; + DynamicProxyData *dynamicProxyData = (DynamicProxyData *)ptr; // args needs to be global, you can't send env across thread boundaries DynamicProxyJsCallData callData; @@ -1359,12 +1389,12 @@ JNIEXPORT jobject JNICALL Java_node_NodeDynamicProxyClass_callJs(JNIEnv *env, jo callData.methodName = javaObjectToString(env, env->CallObjectMethod(method, method_getName)); assertNoException(env); - if(v8ThreadIdEquals(myThreadId, v8ThreadId)) { + if (v8ThreadIdEquals(myThreadId, v8ThreadId)) { EIO_CallJs(&callData); } else { if (args) { // if args is not null and we have to kick this across the thread boundary, make it a global ref - callData.args = (jobjectArray) env->NewGlobalRef(args); + callData.args = (jobjectArray)env->NewGlobalRef(args); hasArgsGlobalRef = true; } @@ -1373,15 +1403,15 @@ JNIEXPORT jobject JNICALL Java_node_NodeDynamicProxyClass_callJs(JNIEnv *env, jo uv_mutex_unlock(&uvMutex_dynamicProxyJsCall); uv_async_send(&uvAsync_dynamicProxyJsCall); - while(!callData.done) { + while (!callData.done) { my_sleep(100); } } - if(!dynamicProxyDataVerify(dynamicProxyData)) { + if (!dynamicProxyDataVerify(dynamicProxyData)) { throwNewThrowable(env, "java/lang/IllegalStateException", "dynamicProxyData was corrupted"); } - if(hasArgsGlobalRef) { + if (hasArgsGlobalRef) { env->DeleteGlobalRef(callData.args); } @@ -1390,7 +1420,7 @@ JNIEXPORT jobject JNICALL Java_node_NodeDynamicProxyClass_callJs(JNIEnv *env, jo } jobject result = NULL; - if(callData.result) { + if (callData.result) { // need to retain a local ref so that we can return it, otherwise the returned object gets corrupted result = env->NewLocalRef(callData.result); env->DeleteGlobalRef(callData.result); @@ -1399,6 +1429,6 @@ JNIEXPORT jobject JNICALL Java_node_NodeDynamicProxyClass_callJs(JNIEnv *env, jo } JNIEXPORT void JNICALL Java_node_NodeDynamicProxyClass_unref(JNIEnv *env, jobject src, jlong ptr) { - DynamicProxyData* dynamicProxyData = (DynamicProxyData*)ptr; + DynamicProxyData *dynamicProxyData = (DynamicProxyData *)ptr; unref(dynamicProxyData); } diff --git a/src/java.h b/src-cpp/java.h similarity index 82% rename from src/java.h rename to src-cpp/java.h index 7f03657f..83c5cfcd 100644 --- a/src/java.h +++ b/src-cpp/java.h @@ -2,11 +2,11 @@ #ifndef _node_java_h_ #define _node_java_h_ -#include -#include #include -#include #include +#include +#include +#include #ifdef JNI_VERSION_1_8 #define JNI_BEST_VERSION JNI_VERSION_1_8 @@ -17,8 +17,10 @@ class Java : public Nan::ObjectWrap { public: static void Init(v8::Local target); - JavaVM* getJvm() { return m_jvm; } - JNIEnv* getJavaEnv() { return m_env; } // can only be used safely by the main thread as this is the thread it belongs to + JavaVM *getJvm() { return m_jvm; } + JNIEnv *getJavaEnv() { + return m_env; + } // can only be used safely by the main thread as this is the thread it belongs to jobject getClassLoader() { return m_classLoader; } public: @@ -32,9 +34,9 @@ class Java : public Nan::ObjectWrap { private: Java(); ~Java(); - v8::Local createJVM(JavaVM** jvm, JNIEnv** env); - void destroyJVM(JavaVM** jvm, JNIEnv** env); - void configureAsync(v8::Local& asyncOptions); + v8::Local createJVM(JavaVM **jvm, JNIEnv **env); + void destroyJVM(JavaVM **jvm, JNIEnv **env); + void configureAsync(v8::Local &asyncOptions); static NAN_METHOD(New); static NAN_METHOD(getClassLoader); @@ -56,13 +58,14 @@ class Java : public Nan::ObjectWrap { static NAN_METHOD(getStaticFieldValue); static NAN_METHOD(setStaticFieldValue); static NAN_METHOD(instanceOf); + static NAN_METHOD(stop); static NAN_GETTER(AccessorProhibitsOverwritingGetter); static NAN_SETTER(AccessorProhibitsOverwritingSetter); v8::Local ensureJvm(); static Nan::Persistent s_ct; - JavaVM* m_jvm; - JNIEnv* m_env; // can only be used safely by the main thread as this is the thread it belongs to + JavaVM *m_jvm; + JNIEnv *m_env; // can only be used safely by the main thread as this is the thread it belongs to jobject m_classLoader; std::string m_classPath; static std::string s_nativeBindingLocation; diff --git a/src/javaObject.cpp b/src-cpp/javaObject.cpp similarity index 78% rename from src/javaObject.cpp rename to src-cpp/javaObject.cpp index 0d67aa8a..0dd23920 100644 --- a/src/javaObject.cpp +++ b/src-cpp/javaObject.cpp @@ -2,13 +2,12 @@ #include "java.h" #include "javaScope.h" #include "utils.h" -#include #include +#include -/*static*/ std::map*> JavaObject::sFunctionTemplates; +/*static*/ std::map *> JavaObject::sFunctionTemplates; -/*static*/ void JavaObject::Init(v8::Local target) { -} +/*static*/ void JavaObject::Init(v8::Local target) {} /*static*/ v8::Local JavaObject::New(Java *java, jobject obj) { Nan::EscapableHandleScope scope; @@ -28,18 +27,20 @@ className = "nodeJava_" + className; v8::Local promisify; - if(java->DoPromise()) { - v8::Local asyncOptions = java->handle()->Get(Nan::GetCurrentContext(), Nan::New("asyncOptions").ToLocalChecked()).ToLocalChecked().As(); - v8::Local promisifyValue = asyncOptions->Get(Nan::GetCurrentContext(), Nan::New("promisify").ToLocalChecked()).ToLocalChecked(); + if (java->DoPromise()) { + v8::Local promisifyValue = + java->handle() + ->Get(Nan::GetCurrentContext(), Nan::New("promisify").ToLocalChecked()) + .ToLocalChecked(); promisify = promisifyValue.As(); } v8::Local funcTemplate; - if(sFunctionTemplates.find(className) != sFunctionTemplates.end()) { - //printf("existing className: %s\n", className.c_str()); + if (sFunctionTemplates.find(className) != sFunctionTemplates.end()) { + // printf("existing className: %s\n", className.c_str()); funcTemplate = Nan::New(*sFunctionTemplates[className]); } else { - //printf("create className: %s\n", className.c_str()); + // printf("create className: %s\n", className.c_str()); funcTemplate = Nan::New(); funcTemplate->InstanceTemplate()->SetInternalFieldCount(1); @@ -50,7 +51,7 @@ javaReflectionGetMethods(env, objClazz, &methods, false); jclass methodClazz = env->FindClass("java/lang/reflect/Method"); jmethodID method_getName = env->GetMethodID(methodClazz, "getName", "()Ljava/lang/String;"); - for(std::list::iterator it = methods.begin(); it != methods.end(); ++it) { + for (std::list::iterator it = methods.begin(); it != methods.end(); ++it) { jstring methodNameJava = (jstring)env->CallObjectMethod(*it, method_getName); assertNoException(env); std::string methodNameStr = javaToString(env, methodNameJava); @@ -58,27 +59,29 @@ v8::Local baseMethodName = Nan::New(methodNameStr.c_str()).ToLocalChecked(); std::string methodNameAsyncStr = methodNameStr; - const char* methodNameAsync = methodNameAsyncStr.append(java->AsyncSuffix()).c_str(); + const char *methodNameAsync = methodNameAsyncStr.append(java->AsyncSuffix()).c_str(); v8::Local methodCallTemplate = Nan::New(methodCall, baseMethodName); Nan::SetPrototypeTemplate(funcTemplate, methodNameAsync, methodCallTemplate); std::string methodNameSyncStr = methodNameStr; - const char* methodNameSync = methodNameSyncStr.append(java->SyncSuffix()).c_str(); - v8::Local methodCallSyncTemplate = Nan::New(methodCallSync, baseMethodName); + const char *methodNameSync = methodNameSyncStr.append(java->SyncSuffix()).c_str(); + v8::Local methodCallSyncTemplate = + Nan::New(methodCallSync, baseMethodName); Nan::SetPrototypeTemplate(funcTemplate, methodNameSync, methodCallSyncTemplate); if (java->DoPromise()) { v8::Local recv = Nan::New(); - v8::Local argv[] = { methodCallTemplate->GetFunction(Nan::GetCurrentContext()).ToLocalChecked() }; + v8::Local argv[] = {methodCallTemplate->GetFunction(Nan::GetCurrentContext()).ToLocalChecked()}; v8::Local result = Nan::Call(promisify, recv, 1, argv).FromMaybe(v8::Local()); if (!result->IsFunction()) { - fprintf(stderr, "Promisified result is not a function -- asyncOptions.promisify must return a function.\n"); + fprintf(stderr, "Promisified result is not a function.\n"); assert(result->IsFunction()); } v8::Local promFunction = result.As(); - v8::Local promFunctionTemplate = Nan::New(methodCallPromise, promFunction); + v8::Local promFunctionTemplate = + Nan::New(methodCallPromise, promFunction); std::string methodNamePromiseStr = methodNameStr; - const char* methodNamePromise = methodNamePromiseStr.append(java->PromiseSuffix()).c_str(); + const char *methodNamePromise = methodNamePromiseStr.append(java->PromiseSuffix()).c_str(); Nan::SetPrototypeTemplate(funcTemplate, methodNamePromise, promFunctionTemplate); } } @@ -88,7 +91,7 @@ javaReflectionGetFields(env, objClazz, &fields); jclass fieldClazz = env->FindClass("java/lang/reflect/Field"); jmethodID field_getName = env->GetMethodID(fieldClazz, "getName", "()Ljava/lang/String;"); - for(std::list::iterator it = fields.begin(); it != fields.end(); ++it) { + for (std::list::iterator it = fields.begin(); it != fields.end(); ++it) { jstring fieldNameJava = (jstring)env->CallObjectMethod(*it, field_getName); checkJavaException(env); std::string fieldNameStr = javaToString(env, fieldNameJava); @@ -100,21 +103,22 @@ // copy array methods to template jmethodID class_isArray = env->GetMethodID(classClazz, "isArray", "()Z"); jboolean isArray = env->CallBooleanMethod(objClazz, class_isArray); - if(isArray) { + if (isArray) { v8::Local fieldName = Nan::New("length").ToLocalChecked(); Nan::SetAccessor(funcTemplate->InstanceTemplate(), fieldName, fieldGetter, NULL); Nan::SetIndexedPropertyHandler(funcTemplate->InstanceTemplate(), indexGetter); } - Nan::Persistent* persistentFuncTemplate = new Nan::Persistent(); + Nan::Persistent *persistentFuncTemplate = new Nan::Persistent(); persistentFuncTemplate->Reset(funcTemplate); sFunctionTemplates[className] = persistentFuncTemplate; } v8::Local ctor = Nan::GetFunction(funcTemplate).ToLocalChecked(); v8::Local javaObjectObj = Nan::NewInstance(ctor).ToLocalChecked(); - SetHiddenValue(javaObjectObj, Nan::New(V8_HIDDEN_MARKER_JAVA_OBJECT).ToLocalChecked(), Nan::New(true)); + SetHiddenValue(javaObjectObj, Nan::New(V8_HIDDEN_MARKER_JAVA_OBJECT).ToLocalChecked(), + Nan::New(true)); JavaObject *self = new JavaObject(java, obj); self->Wrap(javaObjectObj); @@ -136,7 +140,7 @@ JavaObject::~JavaObject() { NAN_METHOD(JavaObject::methodCall) { Nan::HandleScope scope; - JavaObject* self = Nan::ObjectWrap::Unwrap(info.This()); + JavaObject *self = Nan::ObjectWrap::Unwrap(info.This()); JNIEnv *env = self->m_java->getJavaEnv(); JavaScope javaScope(env); @@ -149,14 +153,14 @@ NAN_METHOD(JavaObject::methodCall) { // arguments ARGS_BACK_CALLBACK(); - if(!callbackProvided && methodNameStr == "toString") { + if (!callbackProvided && methodNameStr == "toString") { return methodCallSync(info); } jobjectArray methodArgs = v8ToJava(env, info, argsStart, argsEnd); jobject method = javaFindMethod(env, self->m_class, methodNameStr, methodArgs); - if(method == NULL) { + if (method == NULL) { std::string msg = methodNotFoundToString(env, self->m_class, methodNameStr, false, info, argsStart, argsEnd); EXCEPTION_CALL_CALLBACK(self->m_java, msg); info.GetReturnValue().SetUndefined(); @@ -164,15 +168,16 @@ NAN_METHOD(JavaObject::methodCall) { } // run - InstanceMethodCallBaton* baton = new InstanceMethodCallBaton(self->m_java, self, method, methodArgs, callback); + InstanceMethodCallBaton *baton = new InstanceMethodCallBaton(self->m_java, self, method, methodArgs, callback); baton->run(); - END_CALLBACK_FUNCTION("\"Method '" << methodNameStr << "' called without a callback did you mean to use the Sync version?\""); + END_CALLBACK_FUNCTION("\"Method '" << methodNameStr + << "' called without a callback did you mean to use the Sync version?\""); } NAN_METHOD(JavaObject::methodCallSync) { Nan::HandleScope scope; - JavaObject* self = Nan::ObjectWrap::Unwrap(info.This()); + JavaObject *self = Nan::ObjectWrap::Unwrap(info.This()); JNIEnv *env = self->m_java->getJavaEnv(); JavaScope javaScope(env); @@ -185,7 +190,7 @@ NAN_METHOD(JavaObject::methodCallSync) { jobjectArray methodArgs = v8ToJava(env, info, argsStart, argsEnd); jobject method = javaFindMethod(env, self->m_class, methodNameStr, methodArgs); - if(method == NULL) { + if (method == NULL) { std::string msg = methodNotFoundToString(env, self->m_class, methodNameStr, false, info, argsStart, argsEnd); v8::Local ex = javaExceptionToV8(self->m_java, env, msg); Nan::ThrowError(ex); @@ -194,11 +199,11 @@ NAN_METHOD(JavaObject::methodCallSync) { // run v8::Local callback = Nan::Undefined(); - InstanceMethodCallBaton* baton = new InstanceMethodCallBaton(self->m_java, self, method, methodArgs, callback); + InstanceMethodCallBaton *baton = new InstanceMethodCallBaton(self->m_java, self, method, methodArgs, callback); v8::Local result = baton->runSync(); delete baton; - if(result->IsNativeError()) { + if (result->IsNativeError()) { Nan::ThrowError(result); return; } @@ -209,15 +214,15 @@ NAN_METHOD(JavaObject::methodCallSync) { NAN_METHOD(JavaObject::methodCallPromise) { Nan::HandleScope scope; v8::Local fn = info.Data().As(); - v8::Local* argv = new v8::Local[info.Length()]; - for (int i = 0 ; i < info.Length(); i++) { + v8::Local *argv = new v8::Local[info.Length()]; + for (int i = 0; i < info.Length(); i++) { argv[i] = info[i]; } - + v8::MaybeLocal result = Nan::Call(fn, info.This(), info.Length(), argv); - + delete[] argv; - + if (!result.IsEmpty()) { info.GetReturnValue().Set(result.ToLocalChecked()); } @@ -225,24 +230,24 @@ NAN_METHOD(JavaObject::methodCallPromise) { NAN_GETTER(JavaObject::fieldGetter) { Nan::HandleScope scope; - JavaObject* self = Nan::ObjectWrap::Unwrap(info.This()); + JavaObject *self = Nan::ObjectWrap::Unwrap(info.This()); JNIEnv *env = self->m_java->getJavaEnv(); JavaScope javaScope(env); Nan::Utf8String propertyCStr(property); std::string propertyStr = *propertyCStr; jobject field = javaFindField(env, self->m_class, propertyStr); - if(field == NULL) { - if(propertyStr == "length") { + if (field == NULL) { + if (propertyStr == "length") { jclass classClazz = env->FindClass("java/lang/Class"); jmethodID class_isArray = env->GetMethodID(classClazz, "isArray", "()Z"); jboolean isArray = env->CallBooleanMethod(self->m_class, class_isArray); - if(isArray) { + if (isArray) { jclass arrayClass = env->FindClass("java/lang/reflect/Array"); jmethodID array_getLength = env->GetStaticMethodID(arrayClass, "getLength", "(Ljava/lang/Object;)I"); jint arrayLength = env->CallStaticIntMethod(arrayClass, array_getLength, self->m_obj); assertNoException(env); - info.GetReturnValue().Set(arrayLength); + info.GetReturnValue().Set(Nan::New(static_cast(arrayLength))); return; } } @@ -259,7 +264,7 @@ NAN_GETTER(JavaObject::fieldGetter) { // get field value jobject val = env->CallObjectMethod(field, field_get, self->m_obj); - if(env->ExceptionOccurred()) { + if (env->ExceptionOccurred()) { std::ostringstream errStr; errStr << "Could not get field " << propertyStr; v8::Local ex = javaExceptionToV8(self->m_java, env, errStr.str()); @@ -274,7 +279,7 @@ NAN_GETTER(JavaObject::fieldGetter) { NAN_SETTER(JavaObject::fieldSetter) { Nan::HandleScope scope; - JavaObject* self = Nan::ObjectWrap::Unwrap(info.This()); + JavaObject *self = Nan::ObjectWrap::Unwrap(info.This()); JNIEnv *env = self->m_java->getJavaEnv(); JavaScope javaScope(env); @@ -283,7 +288,7 @@ NAN_SETTER(JavaObject::fieldSetter) { Nan::Utf8String propertyCStr(property); std::string propertyStr = *propertyCStr; jobject field = javaFindField(env, self->m_class, propertyStr); - if(field == NULL) { + if (field == NULL) { std::ostringstream errStr; errStr << "Could not find field \"" << propertyStr << "\" for set"; v8::Local error = javaExceptionToV8(self->m_java, env, errStr.str()); @@ -294,11 +299,11 @@ NAN_SETTER(JavaObject::fieldSetter) { jclass fieldClazz = env->FindClass("java/lang/reflect/Field"); jmethodID field_set = env->GetMethodID(fieldClazz, "set", "(Ljava/lang/Object;Ljava/lang/Object;)V"); - //printf("newValue: %s\n", javaObjectToString(env, newValue).c_str()); + // printf("newValue: %s\n", javaObjectToString(env, newValue).c_str()); // set field value env->CallObjectMethod(field, field_set, self->m_obj, newValue); - if(env->ExceptionOccurred()) { + if (env->ExceptionOccurred()) { std::ostringstream errStr; errStr << "Could not set field " << propertyStr; v8::Local error = javaExceptionToV8(self->m_java, env, errStr.str()); @@ -309,7 +314,7 @@ NAN_SETTER(JavaObject::fieldSetter) { NAN_INDEX_GETTER(JavaObject::indexGetter) { Nan::HandleScope scope; - JavaObject* self = Nan::ObjectWrap::Unwrap(info.This()); + JavaObject *self = Nan::ObjectWrap::Unwrap(info.This()); JNIEnv *env = self->m_java->getJavaEnv(); JavaScope javaScope(env); @@ -320,7 +325,7 @@ NAN_INDEX_GETTER(JavaObject::indexGetter) { assertNoException(env); if ((jint)index >= arrayLength) { info.GetReturnValue().SetUndefined(); - return; + RETURN_INTERCEPTED_YES; } jmethodID array_get = env->GetStaticMethodID(arrayClass, "get", "(Ljava/lang/Object;I)Ljava/lang/Object;"); @@ -328,6 +333,7 @@ NAN_INDEX_GETTER(JavaObject::indexGetter) { assertNoException(env); v8::Local result = javaToV8(self->m_java, env, item); info.GetReturnValue().Set(result); + RETURN_INTERCEPTED_YES; } /*static*/ Nan::Persistent JavaProxyObject::s_proxyCt; @@ -344,30 +350,31 @@ NAN_INDEX_GETTER(JavaObject::indexGetter) { Nan::SetAccessor(t->InstanceTemplate(), fieldName, invocationHandlerGetter); } -v8::Local JavaProxyObject::New(Java *java, jobject obj, DynamicProxyData* dynamicProxyData) { +v8::Local JavaProxyObject::New(Java *java, jobject obj, DynamicProxyData *dynamicProxyData) { Nan::EscapableHandleScope scope; v8::Local ctor = Nan::New(s_proxyCt)->GetFunction(Nan::GetCurrentContext()).ToLocalChecked(); v8::Local javaObjectObj = Nan::NewInstance(ctor).ToLocalChecked(); - SetHiddenValue(javaObjectObj, Nan::New(V8_HIDDEN_MARKER_JAVA_OBJECT).ToLocalChecked(), Nan::New(true)); + SetHiddenValue(javaObjectObj, Nan::New(V8_HIDDEN_MARKER_JAVA_OBJECT).ToLocalChecked(), + Nan::New(true)); JavaProxyObject *self = new JavaProxyObject(java, obj, dynamicProxyData); self->Wrap(javaObjectObj); return scope.Escape(javaObjectObj); } -JavaProxyObject::JavaProxyObject(Java *java, jobject obj, DynamicProxyData* dynamicProxyData) : JavaObject(java, obj) { +JavaProxyObject::JavaProxyObject(Java *java, jobject obj, DynamicProxyData *dynamicProxyData) : JavaObject(java, obj) { m_dynamicProxyData = dynamicProxyData; } JavaProxyObject::~JavaProxyObject() { - if(dynamicProxyDataVerify(m_dynamicProxyData)) { + if (dynamicProxyDataVerify(m_dynamicProxyData)) { unref(m_dynamicProxyData); } } NAN_METHOD(JavaProxyObject::doUnref) { - JavaProxyObject* self = Nan::ObjectWrap::Unwrap(info.This()); + JavaProxyObject *self = Nan::ObjectWrap::Unwrap(info.This()); if (dynamicProxyDataVerify(self->m_dynamicProxyData)) { unref(self->m_dynamicProxyData); } @@ -375,12 +382,12 @@ NAN_METHOD(JavaProxyObject::doUnref) { } NAN_GETTER(JavaProxyObject::invocationHandlerGetter) { - Nan::HandleScope scope; - - JavaProxyObject* self = Nan::ObjectWrap::Unwrap(info.This()); - if (!dynamicProxyDataVerify(self->m_dynamicProxyData)) { - Nan::ThrowError("dynamicProxyData has been destroyed or corrupted"); - return; - } - info.GetReturnValue().Set(Nan::New(self->m_dynamicProxyData->functions)); + Nan::HandleScope scope; + + JavaProxyObject *self = Nan::ObjectWrap::Unwrap(info.This()); + if (!dynamicProxyDataVerify(self->m_dynamicProxyData)) { + Nan::ThrowError("dynamicProxyData has been destroyed or corrupted"); + return; + } + info.GetReturnValue().Set(Nan::New(self->m_dynamicProxyData->functions)); } diff --git a/src/javaObject.h b/src-cpp/javaObject.h similarity index 70% rename from src/javaObject.h rename to src-cpp/javaObject.h index 14b5dfd7..b3dc6529 100644 --- a/src/javaObject.h +++ b/src-cpp/javaObject.h @@ -2,20 +2,20 @@ #ifndef _javaobject_h_ #define _javaobject_h_ -#include -#include +#include "methodCallBaton.h" #include #include #include -#include "methodCallBaton.h" +#include +#include class Java; class JavaObject : public Nan::ObjectWrap { public: static void Init(v8::Local target); - static v8::Local New(Java* java, jobject obj); - static v8::Local NewProxy(Java* java, jobject obj, DynamicProxyData* dynamicProxyData); + static v8::Local New(Java *java, jobject obj); + static v8::Local NewProxy(Java *java, jobject obj, DynamicProxyData *dynamicProxyData); jobject getObject() { return m_obj; } jclass getClass() { return m_class; } @@ -24,7 +24,7 @@ class JavaObject : public Nan::ObjectWrap { void Unref() { Nan::ObjectWrap::Unref(); } protected: - JavaObject(Java* java, jobject obj); + JavaObject(Java *java, jobject obj); ~JavaObject(); private: @@ -35,8 +35,8 @@ class JavaObject : public Nan::ObjectWrap { static NAN_SETTER(fieldSetter); static NAN_INDEX_GETTER(indexGetter); - static std::map*> sFunctionTemplates; - Java* m_java; + static std::map *> sFunctionTemplates; + Java *m_java; jobject m_obj; jclass m_class; }; @@ -44,17 +44,16 @@ class JavaObject : public Nan::ObjectWrap { class JavaProxyObject : public JavaObject { public: static void init(); - static v8::Local New(Java* java, jobject obj, DynamicProxyData* dynamicProxyData); + static v8::Local New(Java *java, jobject obj, DynamicProxyData *dynamicProxyData); private: - JavaProxyObject(Java* java, jobject obj, DynamicProxyData* dynamicProxyData); + JavaProxyObject(Java *java, jobject obj, DynamicProxyData *dynamicProxyData); ~JavaProxyObject(); static NAN_METHOD(doUnref); static NAN_GETTER(invocationHandlerGetter); static Nan::Persistent s_proxyCt; - DynamicProxyData* m_dynamicProxyData; + DynamicProxyData *m_dynamicProxyData; }; #endif - diff --git a/src/javaScope.cpp b/src-cpp/javaScope.cpp similarity index 78% rename from src/javaScope.cpp rename to src-cpp/javaScope.cpp index 7074fb64..5c8b46bb 100644 --- a/src/javaScope.cpp +++ b/src-cpp/javaScope.cpp @@ -7,9 +7,7 @@ JavaScope::JavaScope(JNIEnv *env) { m_env->PushLocalFrame(LOCAL_FRAME_SIZE); } -JavaScope::~JavaScope() { - m_env->PopLocalFrame(m_result); -} +JavaScope::~JavaScope() { m_env->PopLocalFrame(m_result); } jobject JavaScope::Close(jobject result) { m_result = result; diff --git a/src/javaScope.h b/src-cpp/javaScope.h similarity index 100% rename from src/javaScope.h rename to src-cpp/javaScope.h diff --git a/src/methodCallBaton.cpp b/src-cpp/methodCallBaton.cpp similarity index 67% rename from src/methodCallBaton.cpp rename to src-cpp/methodCallBaton.cpp index 8b4902e8..7f2d1836 100644 --- a/src/methodCallBaton.cpp +++ b/src-cpp/methodCallBaton.cpp @@ -6,15 +6,15 @@ jmethodID MethodCallBaton::m_methodInvokeMethodId = 0; -Nan::Callback* toNanCallback(v8::Local& callback) { - if(callback->IsFunction()) { +Nan::Callback *toNanCallback(v8::Local &callback) { + if (callback->IsFunction()) { return new Nan::Callback(callback.As()); } return NULL; } -MethodCallBaton::MethodCallBaton(Java* java, jobject method, jarray args, v8::Local& callback) : - Nan::AsyncWorker(toNanCallback(callback)) { +MethodCallBaton::MethodCallBaton(Java *java, jobject method, jarray args, v8::Local &callback) + : Nan::AsyncWorker(toNanCallback(callback)) { JNIEnv *env = java->getJavaEnv(); m_java = java; m_args = (jarray)env->NewGlobalRef(args); @@ -26,12 +26,12 @@ MethodCallBaton::MethodCallBaton(Java* java, jobject method, jarray args, v8::Lo MethodCallBaton::~MethodCallBaton() { JNIEnv *env = m_java->getJavaEnv(); - if(m_result) { + if (m_result) { env->DeleteGlobalRef(m_result); m_result = NULL; } - if(m_error) { + if (m_error) { env->DeleteGlobalRef(m_error); m_error = NULL; } @@ -44,26 +44,25 @@ MethodCallBaton::~MethodCallBaton() { } jmethodID MethodCallBaton::getMethodInvokeMethodId(JNIEnv *env) { - if(m_methodInvokeMethodId == 0) { + if (m_methodInvokeMethodId == 0) { jclass methodClazz = env->FindClass("java/lang/reflect/Method"); - m_methodInvokeMethodId = env->GetMethodID(methodClazz, "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"); + m_methodInvokeMethodId = + env->GetMethodID(methodClazz, "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"); } return m_methodInvokeMethodId; } -void MethodCallBaton::run() { - Nan::AsyncQueueWorker(this); -} +void MethodCallBaton::run() { Nan::AsyncQueueWorker(this); } v8::Local MethodCallBaton::runSync() { - JNIEnv* env = m_java->getJavaEnv(); + JNIEnv *env = m_java->getJavaEnv(); ExecuteInternal(env); return resultsToV8(env); } // called by NanAsyncWorker. This will be on a worker thread void MethodCallBaton::Execute() { - JNIEnv* env = javaGetEnv(this->m_java->getJvm(), this->m_java->getClassLoader()); + JNIEnv *env = javaGetEnv(this->m_java->getJvm(), this->m_java->getClassLoader()); JavaScope javaScope(env); ExecuteInternal(env); } @@ -72,20 +71,15 @@ void MethodCallBaton::Execute() { void MethodCallBaton::WorkComplete() { Nan::HandleScope scope; - if(callback) { - JNIEnv* env = javaGetEnv(this->m_java->getJvm(), this->m_java->getClassLoader()); + if (callback) { + JNIEnv *env = javaGetEnv(this->m_java->getJvm(), this->m_java->getClassLoader()); JavaScope javaScope(env); v8::Local result = resultsToV8(env); if (result->IsNativeError()) { - v8::Local argv[] = { - result - }; + v8::Local argv[] = {result}; callback->Call(1, argv, async_resource); } else { - v8::Local argv[] = { - Nan::Undefined(), - result - }; + v8::Local argv[] = {Nan::Undefined(), result}; callback->Call(2, argv, async_resource); } @@ -97,7 +91,7 @@ void MethodCallBaton::WorkComplete() { v8::Local MethodCallBaton::resultsToV8(JNIEnv *env) { Nan::EscapableHandleScope scope; - if(m_error) { + if (m_error) { jthrowable cause = m_error; // if we've caught an InvocationTargetException exception, @@ -115,17 +109,18 @@ v8::Local MethodCallBaton::resultsToV8(JNIEnv *env) { return scope.Escape(err); } - return scope.Escape(javaToV8(m_java, env, m_result)); + return scope.Escape(javaToV8(m_java, env, m_result)); } -void NewInstanceBaton::ExecuteInternal(JNIEnv* env) { +void NewInstanceBaton::ExecuteInternal(JNIEnv *env) { jclass batonClazz = env->FindClass("node/MethodCallBaton"); - jmethodID newInstance = env->GetStaticMethodID(batonClazz, "newInstance", "(Ljava/lang/reflect/Constructor;[Ljava/lang/Object;)Ljava/lang/Object;"); + jmethodID newInstance = env->GetStaticMethodID( + batonClazz, "newInstance", "(Ljava/lang/reflect/Constructor;[Ljava/lang/Object;)Ljava/lang/Object;"); jarray args = javaGetArgsForConstructor(env, m_method, m_args); jobject result = env->CallStaticObjectMethod(batonClazz, newInstance, m_method, args); - if(env->ExceptionCheck()) { + if (env->ExceptionCheck()) { jthrowable ex = env->ExceptionOccurred(); env->ExceptionClear(); m_error = (jthrowable)env->NewGlobalRef(ex); @@ -136,7 +131,7 @@ void NewInstanceBaton::ExecuteInternal(JNIEnv* env) { m_result = env->NewGlobalRef(result); } -void StaticMethodCallBaton::ExecuteInternal(JNIEnv* env) { +void StaticMethodCallBaton::ExecuteInternal(JNIEnv *env) { /* printf("calling %s\n", javaObjectToString(env, m_method).c_str()); printf("arguments\n"); @@ -148,12 +143,14 @@ void StaticMethodCallBaton::ExecuteInternal(JNIEnv* env) { */ jclass batonClazz = env->FindClass("node/MethodCallBaton"); - jmethodID invokeMethod = env->GetStaticMethodID(batonClazz, env->GetVersion() >= 0x90000 ? "invokeMethod9" : "invokeMethod", "(Ljava/lang/reflect/Method;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"); + jmethodID invokeMethod = + env->GetStaticMethodID(batonClazz, env->GetVersion() >= 0x90000 ? "invokeMethod9" : "invokeMethod", + "(Ljava/lang/reflect/Method;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"); jarray args = javaGetArgsForMethod(env, m_method, m_args); jobject result = env->CallStaticObjectMethod(batonClazz, invokeMethod, m_method, NULL, args); - if(env->ExceptionCheck()) { + if (env->ExceptionCheck()) { jthrowable ex = env->ExceptionOccurred(); env->ExceptionClear(); m_error = (jthrowable)env->NewGlobalRef(ex); @@ -164,7 +161,7 @@ void StaticMethodCallBaton::ExecuteInternal(JNIEnv* env) { m_result = env->NewGlobalRef(result); } -void InstanceMethodCallBaton::ExecuteInternal(JNIEnv* env) { +void InstanceMethodCallBaton::ExecuteInternal(JNIEnv *env) { /* printf("calling %s\n", javaObjectToString(env, m_method).c_str()); printf("arguments\n"); @@ -174,12 +171,14 @@ void InstanceMethodCallBaton::ExecuteInternal(JNIEnv* env) { */ jclass batonClazz = env->FindClass("node/MethodCallBaton"); - jmethodID invokeMethod = env->GetStaticMethodID(batonClazz, env->GetVersion() >= 0x90000 ? "invokeMethod9" : "invokeMethod", "(Ljava/lang/reflect/Method;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"); + jmethodID invokeMethod = + env->GetStaticMethodID(batonClazz, env->GetVersion() >= 0x90000 ? "invokeMethod9" : "invokeMethod", + "(Ljava/lang/reflect/Method;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"); jarray args = javaGetArgsForMethod(env, m_method, m_args); jobject result = env->CallStaticObjectMethod(batonClazz, invokeMethod, m_method, m_javaObject->getObject(), args); - if(env->ExceptionCheck()) { + if (env->ExceptionCheck()) { jthrowable ex = env->ExceptionOccurred(); env->ExceptionClear(); m_error = (jthrowable)env->NewGlobalRef(ex); @@ -187,19 +186,16 @@ void InstanceMethodCallBaton::ExecuteInternal(JNIEnv* env) { return; } - if(result == NULL) { + if (result == NULL) { m_result = NULL; } else { m_result = env->NewGlobalRef(result); } } -NewInstanceBaton::NewInstanceBaton( - Java* java, - jclass clazz, - jobject method, - jarray args, - v8::Local& callback) : MethodCallBaton(java, method, args, callback) { +NewInstanceBaton::NewInstanceBaton(Java *java, jclass clazz, jobject method, jarray args, + v8::Local &callback) + : MethodCallBaton(java, method, args, callback) { JNIEnv *env = m_java->getJavaEnv(); m_clazz = (jclass)env->NewGlobalRef(clazz); } @@ -210,12 +206,9 @@ NewInstanceBaton::~NewInstanceBaton() { m_clazz = NULL; } -StaticMethodCallBaton::StaticMethodCallBaton( - Java* java, - jclass clazz, - jobject method, - jarray args, - v8::Local& callback) : MethodCallBaton(java, method, args, callback) { +StaticMethodCallBaton::StaticMethodCallBaton(Java *java, jclass clazz, jobject method, jarray args, + v8::Local &callback) + : MethodCallBaton(java, method, args, callback) { JNIEnv *env = m_java->getJavaEnv(); m_clazz = (jclass)env->NewGlobalRef(clazz); } @@ -226,12 +219,9 @@ StaticMethodCallBaton::~StaticMethodCallBaton() { m_clazz = NULL; } -InstanceMethodCallBaton::InstanceMethodCallBaton( - Java* java, - JavaObject* obj, - jobject method, - jarray args, - v8::Local& callback) : MethodCallBaton(java, method, args, callback) { +InstanceMethodCallBaton::InstanceMethodCallBaton(Java *java, JavaObject *obj, jobject method, jarray args, + v8::Local &callback) + : MethodCallBaton(java, method, args, callback) { m_javaObject = obj; m_javaObject->Ref(); } diff --git a/src/methodCallBaton.h b/src-cpp/methodCallBaton.h similarity index 61% rename from src/methodCallBaton.h rename to src-cpp/methodCallBaton.h index 504d00d8..ee4102fa 100644 --- a/src/methodCallBaton.h +++ b/src-cpp/methodCallBaton.h @@ -3,18 +3,18 @@ #define _methodcallbaton_h_ #include "utils.h" -#include -#include -#include #include #include +#include +#include +#include class Java; class JavaObject; class MethodCallBaton : public Nan::AsyncWorker { public: - MethodCallBaton(Java* java, jobject method, jarray args, v8::Local& callback); + MethodCallBaton(Java *java, jobject method, jarray args, v8::Local &callback); virtual ~MethodCallBaton(); void run(); @@ -24,10 +24,10 @@ class MethodCallBaton : public Nan::AsyncWorker { v8::Local resultsToV8(JNIEnv *env); virtual void Execute(); virtual void WorkComplete(); - virtual void ExecuteInternal(JNIEnv* env) = 0; + virtual void ExecuteInternal(JNIEnv *env) = 0; static jmethodID getMethodInvokeMethodId(JNIEnv *env); - Java* m_java; + Java *m_java; jthrowable m_error; std::string m_errorString; jarray m_args; @@ -40,33 +40,33 @@ class MethodCallBaton : public Nan::AsyncWorker { class InstanceMethodCallBaton : public MethodCallBaton { public: - InstanceMethodCallBaton(Java* java, JavaObject* obj, jobject method, jarray args, v8::Local& callback); + InstanceMethodCallBaton(Java *java, JavaObject *obj, jobject method, jarray args, v8::Local &callback); virtual ~InstanceMethodCallBaton(); protected: - virtual void ExecuteInternal(JNIEnv* env); + virtual void ExecuteInternal(JNIEnv *env); - JavaObject* m_javaObject; + JavaObject *m_javaObject; }; class NewInstanceBaton : public MethodCallBaton { public: - NewInstanceBaton(Java* java, jclass clazz, jobject method, jarray args, v8::Local& callback); + NewInstanceBaton(Java *java, jclass clazz, jobject method, jarray args, v8::Local &callback); virtual ~NewInstanceBaton(); protected: - virtual void ExecuteInternal(JNIEnv* env); + virtual void ExecuteInternal(JNIEnv *env); jclass m_clazz; }; class StaticMethodCallBaton : public MethodCallBaton { public: - StaticMethodCallBaton(Java* java, jclass clazz, jobject method, jarray args, v8::Local& callback); + StaticMethodCallBaton(Java *java, jclass clazz, jobject method, jarray args, v8::Local &callback); virtual ~StaticMethodCallBaton(); protected: - virtual void ExecuteInternal(JNIEnv* env); + virtual void ExecuteInternal(JNIEnv *env); jclass m_clazz; }; diff --git a/src-cpp/nodeJavaBridge.cpp b/src-cpp/nodeJavaBridge.cpp new file mode 100644 index 00000000..55b6bb41 --- /dev/null +++ b/src-cpp/nodeJavaBridge.cpp @@ -0,0 +1,18 @@ + +#include "java.h" +#include "javaObject.h" + +extern "C" { +static void init(v8::Local target, v8::Local, void *) { + Java::Init(target); + JavaObject::Init(target); +} + +NODE_MODULE(nodejavabridge_bindings, init); +} + +#ifdef WIN32 + +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { return TRUE; } + +#endif diff --git a/src/node_NodeDynamicProxyClass.h b/src-cpp/node_NodeDynamicProxyClass.h similarity index 80% rename from src/node_NodeDynamicProxyClass.h rename to src-cpp/node_NodeDynamicProxyClass.h index 93b414d2..d201a5d0 100644 --- a/src/node_NodeDynamicProxyClass.h +++ b/src-cpp/node_NodeDynamicProxyClass.h @@ -12,16 +12,14 @@ extern "C" { * Method: callJs * Signature: (JLjava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object; */ -JNIEXPORT jobject JNICALL Java_node_NodeDynamicProxyClass_callJs - (JNIEnv *, jobject, jlong, jobject, jobjectArray); +JNIEXPORT jobject JNICALL Java_node_NodeDynamicProxyClass_callJs(JNIEnv *, jobject, jlong, jobject, jobjectArray); /* * Class: node_NodeDynamicProxyClass * Method: unref * Signature: (J)V */ -JNIEXPORT void JNICALL Java_node_NodeDynamicProxyClass_unref - (JNIEnv *, jobject, jlong); +JNIEXPORT void JNICALL Java_node_NodeDynamicProxyClass_unref(JNIEnv *, jobject, jlong); #ifdef __cplusplus } diff --git a/src/utils.cpp b/src-cpp/utils.cpp similarity index 50% rename from src/utils.cpp rename to src-cpp/utils.cpp index 780a291c..8b3784c5 100644 --- a/src/utils.cpp +++ b/src-cpp/utils.cpp @@ -1,17 +1,24 @@ #include "utils.h" -#include +#include "java.h" +#include "javaObject.h" #include -#include #include -#include "javaObject.h" -#include "java.h" +#include +#include #define MODIFIER_STATIC 9 -jobject v8ToJava_javaObject(JNIEnv* env, v8::Local obj); -jobject v8ToJava_javaLong(JNIEnv* env, v8::Local obj); +jobject v8ToJava_javaObject(JNIEnv *env, v8::Local obj); +jobject v8ToJava_javaLong(JNIEnv *env, v8::Local obj); + +bool hasSetFailed(Nan::Maybe v) { + if (v.IsNothing()) { + return false; + } + return v.ToChecked() == false; +} -void javaReflectionGetMethods(JNIEnv *env, jclass clazz, std::list* methods, bool includeStatic) { +void javaReflectionGetMethods(JNIEnv *env, jclass clazz, std::list *methods, bool includeStatic) { jclass clazzclazz = env->FindClass("java/lang/Class"); jmethodID clazz_getMethods = env->GetMethodID(clazzclazz, "getMethods", "()[Ljava/lang/reflect/Method;"); jclass methodClazz = env->FindClass("java/lang/reflect/Method"); @@ -20,31 +27,32 @@ void javaReflectionGetMethods(JNIEnv *env, jclass clazz, std::list* met jobjectArray methodObjects = (jobjectArray)env->CallObjectMethod(clazz, clazz_getMethods); checkJavaException(env); jsize methodCount = env->GetArrayLength(methodObjects); - for(jsize i=0; iGetObjectArrayElement(methodObjects, i); jint methodModifiers = env->CallIntMethod(method, method_getModifiers); assertNoException(env); - if(!includeStatic && (methodModifiers & MODIFIER_STATIC) == MODIFIER_STATIC) { + if (!includeStatic && (methodModifiers & MODIFIER_STATIC) == MODIFIER_STATIC) { continue; } methods->push_back(method); } } -void javaReflectionGetConstructors(JNIEnv *env, jclass clazz, std::list* methods) { +void javaReflectionGetConstructors(JNIEnv *env, jclass clazz, std::list *methods) { jclass clazzclazz = env->FindClass("java/lang/Class"); - jmethodID clazz_getConstructors = env->GetMethodID(clazzclazz, "getConstructors", "()[Ljava/lang/reflect/Constructor;"); + jmethodID clazz_getConstructors = + env->GetMethodID(clazzclazz, "getConstructors", "()[Ljava/lang/reflect/Constructor;"); jobjectArray constructorObjects = (jobjectArray)env->CallObjectMethod(clazz, clazz_getConstructors); checkJavaException(env); jsize constructorCount = env->GetArrayLength(constructorObjects); - for(jsize i=0; iGetObjectArrayElement(constructorObjects, i); methods->push_back(constructor); } } -void javaReflectionGetFields(JNIEnv *env, jclass clazz, std::list* fields) { +void javaReflectionGetFields(JNIEnv *env, jclass clazz, std::list *fields) { jclass clazzclazz = env->FindClass("java/lang/Class"); jmethodID clazz_getFields = env->GetMethodID(clazzclazz, "getFields", "()[Ljava/lang/reflect/Field;"); jclass fieldClazz = env->FindClass("java/lang/reflect/Field"); @@ -53,11 +61,11 @@ void javaReflectionGetFields(JNIEnv *env, jclass clazz, std::list* fiel jobjectArray fieldObjects = (jobjectArray)env->CallObjectMethod(clazz, clazz_getFields); assertNoException(env); jsize fieldCount = env->GetArrayLength(fieldObjects); - for(jsize i=0; iGetObjectArrayElement(fieldObjects, i); jint fieldModifiers = env->CallIntMethod(field, field_getModifiers); checkJavaException(env); - if((fieldModifiers & MODIFIER_STATIC) == MODIFIER_STATIC) { + if ((fieldModifiers & MODIFIER_STATIC) == MODIFIER_STATIC) { continue; } fields->push_back(field); @@ -72,10 +80,10 @@ std::string javaToString(JNIEnv *env, jstring str) { jbyteArray stringJbytes = (jbyteArray)env->CallObjectMethod(str, methodId, charsetName); env->DeleteLocalRef(charsetName); - jbyte* pBytes = env->GetByteArrayElements(stringJbytes, NULL); + jbyte *pBytes = env->GetByteArrayElements(stringJbytes, NULL); const jsize length = env->GetArrayLength(stringJbytes); - std::string results((const char*)pBytes, length); + std::string results((const char *)pBytes, length); env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT); env->DeleteLocalRef(stringJbytes); @@ -84,15 +92,15 @@ std::string javaToString(JNIEnv *env, jstring str) { } std::string javaArrayToString(JNIEnv *env, jobjectArray arr) { - if(arr == NULL) { + if (arr == NULL) { return "(null)"; } std::ostringstream result; result << "["; jsize count = env->GetArrayLength(arr); - for(jsize i=0; iGetObjectArrayElement(arr, i); @@ -103,7 +111,7 @@ std::string javaArrayToString(JNIEnv *env, jobjectArray arr) { } std::string javaObjectToString(JNIEnv *env, jobject obj) { - if(obj == NULL) { + if (obj == NULL) { return "(null)"; } jclass objClazz = env->GetObjectClass(obj); @@ -126,8 +134,8 @@ std::string javaMethodCallToString(JNIEnv *env, jobject obj, jmethodID methodId, result << temp; result << ": ("; jsize arraySize = env->GetArrayLength(args); - for(int i=0; iGetObjectArrayElement((jobjectArray)args, i); @@ -138,20 +146,21 @@ std::string javaMethodCallToString(JNIEnv *env, jobject obj, jmethodID methodId, return result.str(); } -JNIEnv* javaGetEnv(JavaVM* jvm, jobject classLoader) { +JNIEnv *javaGetEnv(JavaVM *jvm, jobject classLoader) { JNIEnv *env = NULL; - int ret = jvm->GetEnv((void**)&env, JNI_BEST_VERSION); + int ret = jvm->GetEnv((void **)&env, JNI_BEST_VERSION); if (ret == JNI_EDETACHED) { JavaVMAttachArgs attachArgs; attachArgs.version = JNI_BEST_VERSION; attachArgs.name = NULL; attachArgs.group = NULL; - jvm->AttachCurrentThread((void**)&env, &attachArgs); + jvm->AttachCurrentThread((void **)&env, &attachArgs); jclass threadClazz = env->FindClass("java/lang/Thread"); jmethodID thread_currentThread = env->GetStaticMethodID(threadClazz, "currentThread", "()Ljava/lang/Thread;"); - jmethodID thread_setContextClassLoader = env->GetMethodID(threadClazz, "setContextClassLoader", "(Ljava/lang/ClassLoader;)V"); + jmethodID thread_setContextClassLoader = + env->GetMethodID(threadClazz, "setContextClassLoader", "(Ljava/lang/ClassLoader;)V"); jobject currentThread = env->CallStaticObjectMethod(threadClazz, thread_currentThread); checkJavaException(env); env->CallObjectMethod(currentThread, thread_setContextClassLoader, classLoader); @@ -167,7 +176,8 @@ JNIEnv* javaGetEnv(JavaVM* jvm, jobject classLoader) { jobject getSystemClassLoader(JNIEnv *env) { jclass threadClazz = env->FindClass("java/lang/Thread"); jmethodID thread_currentThread = env->GetStaticMethodID(threadClazz, "currentThread", "()Ljava/lang/Thread;"); - jmethodID thread_getContextClassLoader = env->GetMethodID(threadClazz, "getContextClassLoader", "()Ljava/lang/ClassLoader;"); + jmethodID thread_getContextClassLoader = + env->GetMethodID(threadClazz, "getContextClassLoader", "()Ljava/lang/ClassLoader;"); jobject currentThread = env->CallStaticObjectMethod(threadClazz, thread_currentThread); checkJavaException(env); jobject result = env->CallObjectMethod(currentThread, thread_getContextClassLoader); @@ -181,60 +191,62 @@ jvalueType javaGetType(JNIEnv *env, jclass type) { jboolean isArray = env->CallBooleanMethod(type, class_isArray); assertNoException(env); - if(isArray) { + if (isArray) { return TYPE_ARRAY; } else { // TODO: has to be a better way std::string str = javaObjectToString(env, type); const char *typeStr = str.c_str(); - //printf("javaGetType: %s\n", typeStr); - if(strcmp(typeStr, "void") == 0) { + // printf("javaGetType: %s\n", typeStr); + if (strcmp(typeStr, "void") == 0) { return TYPE_VOID; - } else if(strcmp(typeStr, "char") == 0 || strcmp(typeStr, "class java.lang.Character") == 0) { + } else if (strcmp(typeStr, "char") == 0 || strcmp(typeStr, "class java.lang.Character") == 0) { return TYPE_CHAR; - } else if(strcmp(typeStr, "int") == 0 || strcmp(typeStr, "class java.lang.Integer") == 0) { + } else if (strcmp(typeStr, "int") == 0 || strcmp(typeStr, "class java.lang.Integer") == 0) { return TYPE_INT; - } else if(strcmp(typeStr, "double") == 0 || strcmp(typeStr, "class java.lang.Double") == 0) { + } else if (strcmp(typeStr, "double") == 0 || strcmp(typeStr, "class java.lang.Double") == 0) { return TYPE_DOUBLE; - } else if(strcmp(typeStr, "float") == 0 || strcmp(typeStr, "class java.lang.Float") == 0) { + } else if (strcmp(typeStr, "float") == 0 || strcmp(typeStr, "class java.lang.Float") == 0) { return TYPE_FLOAT; - } else if(strcmp(typeStr, "long") == 0 || strcmp(typeStr, "class java.lang.Long") == 0) { + } else if (strcmp(typeStr, "long") == 0 || strcmp(typeStr, "class java.lang.Long") == 0) { return TYPE_LONG; - } else if(strcmp(typeStr, "boolean") == 0 || strcmp(typeStr, "class java.lang.Boolean") == 0) { + } else if (strcmp(typeStr, "boolean") == 0 || strcmp(typeStr, "class java.lang.Boolean") == 0) { return TYPE_BOOLEAN; - } else if(strcmp(typeStr, "short") == 0 || strcmp(typeStr, "class java.lang.Short") == 0) { + } else if (strcmp(typeStr, "short") == 0 || strcmp(typeStr, "class java.lang.Short") == 0) { return TYPE_SHORT; - } else if(strcmp(typeStr, "byte") == 0 || strcmp(typeStr, "class java.lang.Byte") == 0) { + } else if (strcmp(typeStr, "byte") == 0 || strcmp(typeStr, "class java.lang.Byte") == 0) { return TYPE_BYTE; - } else if(strcmp(typeStr, "class java.lang.String") == 0) { + } else if (strcmp(typeStr, "class java.lang.String") == 0) { return TYPE_STRING; } return TYPE_OBJECT; } } -jclass javaFindClass(JNIEnv* env, const std::string& className) { +jclass javaFindClass(JNIEnv *env, const std::string &className) { std::string searchClassName = className; std::replace(searchClassName.begin(), searchClassName.end(), '.', '/'); -// Alternate find class trying to fix Class.forName -// jclass threadClazz = env->FindClass("java/lang/Thread"); -// jmethodID thread_getCurrentThread = env->GetStaticMethodID(threadClazz, "currentThread", "()Ljava/lang/Thread;"); -// jmethodID thread_getContextClassLoader = env->GetMethodID(threadClazz, "getContextClassLoader", "()Ljava/lang/ClassLoader;"); -// -// jclass classLoaderClazz = env->FindClass("java/lang/ClassLoader"); -// jmethodID classLoader_loadClass = env->GetMethodID(classLoaderClazz, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); -// -// jobject currentThread = env->CallObjectMethod(threadClazz, thread_getCurrentThread); -// jobject classLoader = env->CallObjectMethod(currentThread, thread_getContextClassLoader); -// jstring searchClassNameJava = env->NewStringUTF(className.c_str()); -// jclass clazz = (jclass)env->CallObjectMethod(classLoader, classLoader_loadClass, searchClassNameJava); + // Alternate find class trying to fix Class.forName + // jclass threadClazz = env->FindClass("java/lang/Thread"); + // jmethodID thread_getCurrentThread = env->GetStaticMethodID(threadClazz, "currentThread", "()Ljava/lang/Thread;"); + // jmethodID thread_getContextClassLoader = env->GetMethodID(threadClazz, "getContextClassLoader", + // "()Ljava/lang/ClassLoader;"); + // + // jclass classLoaderClazz = env->FindClass("java/lang/ClassLoader"); + // jmethodID classLoader_loadClass = env->GetMethodID(classLoaderClazz, "loadClass", + // "(Ljava/lang/String;)Ljava/lang/Class;"); + // + // jobject currentThread = env->CallObjectMethod(threadClazz, thread_getCurrentThread); + // jobject classLoader = env->CallObjectMethod(currentThread, thread_getContextClassLoader); + // jstring searchClassNameJava = env->NewStringUTF(className.c_str()); + // jclass clazz = (jclass)env->CallObjectMethod(classLoader, classLoader_loadClass, searchClassNameJava); jclass clazz = env->FindClass(searchClassName.c_str()); return clazz; } -jobject javaFindField(JNIEnv* env, jclass clazz, const std::string& fieldName) { +jobject javaFindField(JNIEnv *env, jclass clazz, const std::string &fieldName) { jobject result = NULL; jclass clazzclazz = env->GetObjectClass(clazz); jclass fieldClazz = env->FindClass("java/lang/reflect/Field"); @@ -244,13 +256,13 @@ jobject javaFindField(JNIEnv* env, jclass clazz, const std::string& fieldName) { checkJavaException(env); jsize fieldCount = env->GetArrayLength(fieldObjects); - for(jsize i=0; iGetObjectArrayElement(fieldObjects, i); jstring fieldNameJava = (jstring)env->CallObjectMethod(field, field_getName); checkJavaException(env); std::string itFieldName = javaToString(env, fieldNameJava); - if(strcmp(itFieldName.c_str(), fieldName.c_str()) == 0) { + if (strcmp(itFieldName.c_str(), fieldName.c_str()) == 0) { result = field; break; } @@ -274,71 +286,66 @@ static std::string getArrayElementType(v8::Local array, uint32_t arra return kObject; } - for(uint32_t i=0; i arg = array->Get(Nan::GetCurrentContext(), i).ToLocalChecked(); if (arg->IsArray()) { return kObject; // We can exit as soon as we know java/lang/Object is required. - } - else if(arg->IsString()) { + } else if (arg->IsString()) { types.insert(kString); - } - else if(arg->IsInt32() || arg->IsUint32()) { + } else if (arg->IsInt32() || arg->IsUint32()) { types.insert(kInteger); - } - else if(arg->IsNumber()) { + } else if (arg->IsNumber()) { types.insert(kDouble); - } - else if(arg->IsBoolean()) { + } else if (arg->IsBoolean()) { types.insert(kBoolean); - } - else if(arg->IsObject()) { + } else if (arg->IsObject()) { v8::Local obj = v8::Local::Cast(arg); - v8::Local isJavaLong = GetHiddenValue(obj, Nan::New(V8_HIDDEN_MARKER_JAVA_LONG).ToLocalChecked()); - if(!isJavaLong.IsEmpty() && isJavaLong->IsBoolean()) { + v8::Local isJavaLong = + GetHiddenValue(obj, Nan::New(V8_HIDDEN_MARKER_JAVA_LONG).ToLocalChecked()); + if (!isJavaLong.IsEmpty() && isJavaLong->IsBoolean()) { types.insert(kLong); - } - else { + } else { return kObject; // We can exit as soon as we know java/lang/Object is required. } } } - if(types.size() == 1) { + if (types.size() == 1) { return *(types.begin()); } assert(types.size() >= 1); - assert(types.find(kObject)==types.end()); + assert(types.find(kObject) == types.end()); // We have an array with two or more types. All types can be converted to Object, but there is one other // case we support, which is when all the types are numeric types. // We currently have only two non-numeric types. If neither is present in the set, the rest must be numeric. - if (types.find(kString)==types.end() && types.find(kBoolean)==types.end()) { + if (types.find(kString) == types.end() && types.find(kBoolean) == types.end()) { return kNumber; } return kObject; } -jobject v8ToJava(JNIEnv* env, v8::Local arg) { - if(arg.IsEmpty() || arg->IsNull() || arg->IsUndefined()) { +jobject v8ToJava(JNIEnv *env, v8::Local arg) { + if (arg.IsEmpty() || arg->IsNull() || arg->IsUndefined()) { return NULL; } - if(arg->IsArray()) { + if (arg->IsArray()) { v8::Local array = v8::Local::Cast(arg); uint32_t arraySize = array->Length(); std::string arrayType = getArrayElementType(array, arraySize); jclass objectClazz = env->FindClass(arrayType.c_str()); jobjectArray result = env->NewObjectArray(arraySize, objectClazz, NULL); - for(uint32_t i=0; iGet(Nan::GetCurrentContext(), i).ToLocalChecked()); env->SetObjectArrayElement(result, i, val); } return result; } - if(arg->IsString()) { + if (arg->IsString()) { #if NODE_MAJOR_VERSION > 7 v8::String::Value val(v8::Isolate::GetCurrent(), arg->ToString(Nan::GetCurrentContext()).ToLocalChecked()); #else @@ -347,37 +354,39 @@ jobject v8ToJava(JNIEnv* env, v8::Local arg) { return env->NewString(*val, val.length()); } - if(arg->IsInt32() || arg->IsUint32()) { + if (arg->IsInt32() || arg->IsUint32()) { jint val = Nan::To(arg).FromJust(); jclass clazz = env->FindClass("java/lang/Integer"); jmethodID constructor = env->GetMethodID(clazz, "", "(I)V"); return env->NewObject(clazz, constructor, val); } - if(arg->IsNumber()) { + if (arg->IsNumber()) { jdouble val = Nan::To(arg).FromJust(); jclass clazz = env->FindClass("java/lang/Double"); jmethodID constructor = env->GetMethodID(clazz, "", "(D)V"); return env->NewObject(clazz, constructor, val); } - if(arg->IsBoolean()) { + if (arg->IsBoolean()) { jboolean val = Nan::To(arg).FromJust(); jclass clazz = env->FindClass("java/lang/Boolean"); jmethodID constructor = env->GetMethodID(clazz, "", "(Z)V"); return env->NewObject(clazz, constructor, val); } - if(arg->IsObject()) { + if (arg->IsObject()) { v8::Local obj = v8::Local::Cast(arg); - v8::Local isJavaObject = GetHiddenValue(obj, Nan::New(V8_HIDDEN_MARKER_JAVA_OBJECT).ToLocalChecked()); - if(!isJavaObject.IsEmpty() && isJavaObject->IsBoolean()) { + v8::Local isJavaObject = + GetHiddenValue(obj, Nan::New(V8_HIDDEN_MARKER_JAVA_OBJECT).ToLocalChecked()); + if (!isJavaObject.IsEmpty() && isJavaObject->IsBoolean()) { return v8ToJava_javaObject(env, obj); } - v8::Local isJavaLong = GetHiddenValue(obj, Nan::New(V8_HIDDEN_MARKER_JAVA_LONG).ToLocalChecked()); - if(!isJavaLong.IsEmpty() && isJavaLong->IsBoolean()) { + v8::Local isJavaLong = + GetHiddenValue(obj, Nan::New(V8_HIDDEN_MARKER_JAVA_LONG).ToLocalChecked()); + if (!isJavaLong.IsEmpty() && isJavaLong->IsBoolean()) { return v8ToJava_javaLong(env, obj); } } @@ -388,13 +397,13 @@ jobject v8ToJava(JNIEnv* env, v8::Local arg) { return NULL; } -jobject v8ToJava_javaObject(JNIEnv* env, v8::Local obj) { - JavaObject* javaObject = Nan::ObjectWrap::Unwrap(obj); +jobject v8ToJava_javaObject(JNIEnv *env, v8::Local obj) { + JavaObject *javaObject = Nan::ObjectWrap::Unwrap(obj); return javaObject->getObject(); } -void checkJavaException(JNIEnv* env) { - if(env->ExceptionCheck()) { +void checkJavaException(JNIEnv *env) { + if (env->ExceptionCheck()) { jthrowable ex = env->ExceptionOccurred(); env->ExceptionClear(); @@ -404,19 +413,20 @@ void checkJavaException(JNIEnv* env) { } } -jobject v8ToJava_javaLong(JNIEnv* env, v8::Local obj) { - jobject longValue = v8ToJava(env, obj->Get(Nan::GetCurrentContext(), Nan::New("longValue").ToLocalChecked()).ToLocalChecked()); +jobject v8ToJava_javaLong(JNIEnv *env, v8::Local obj) { + jobject longValue = v8ToJava( + env, obj->Get(Nan::GetCurrentContext(), Nan::New("longValue").ToLocalChecked()).ToLocalChecked()); jclass longClazz = env->FindClass("java/lang/Long"); jmethodID long_constructor = env->GetMethodID(longClazz, "", "(Ljava/lang/String;)V"); jobject jobj = env->NewObject(longClazz, long_constructor, longValue); return jobj; } -jobjectArray v8ToJava(JNIEnv* env, Nan::NAN_METHOD_ARGS_TYPE args, int start, int end) { +jobjectArray v8ToJava(JNIEnv *env, Nan::NAN_METHOD_ARGS_TYPE args, int start, int end) { jclass clazz = env->FindClass("java/lang/Object"); - jobjectArray results = env->NewObjectArray(end-start, clazz, NULL); + jobjectArray results = env->NewObjectArray(end - start, clazz, NULL); - for(int i=start; iSetObjectArrayElement(results, i - start, val); } @@ -424,7 +434,7 @@ jobjectArray v8ToJava(JNIEnv* env, Nan::NAN_METHOD_ARGS_TYPE args, int start, in return results; } -std::string javaExceptionToString(JNIEnv* env, jthrowable ex) { +std::string javaExceptionToString(JNIEnv *env, jthrowable ex) { jclass stringWriterClazz = env->FindClass("java/io/StringWriter"); jmethodID stringWriter_constructor = env->GetMethodID(stringWriterClazz, "", "()V"); jmethodID stringWriter_toString = env->GetMethodID(stringWriterClazz, "toString", "()Ljava/lang/String;"); @@ -444,22 +454,26 @@ std::string javaExceptionToString(JNIEnv* env, jthrowable ex) { return javaToString(env, strObj); } -v8::Local javaExceptionToV8(Java* java, JNIEnv* env, jthrowable ex, const std::string& alternateMessage) { +v8::Local javaExceptionToV8(Java *java, JNIEnv *env, jthrowable ex, const std::string &alternateMessage) { std::ostringstream msg; msg << alternateMessage; - if(ex) { + if (ex) { msg << "\n" << javaExceptionToString(env, ex); v8::Local v8ex = v8::Exception::Error(Nan::New(msg.str().c_str()).ToLocalChecked()); - ((v8::Object*)*v8ex)->Set(Nan::GetCurrentContext(), Nan::New("cause").ToLocalChecked(), javaToV8(java, env, ex)); + if (hasSetFailed(((v8::Object *)*v8ex) + ->Set(Nan::GetCurrentContext(), Nan::New("cause").ToLocalChecked(), + javaToV8(java, env, ex)))) { + return v8::Exception::Error(Nan::New("could not set cause").ToLocalChecked()); + } return v8ex; } return v8::Exception::Error(Nan::New(msg.str().c_str()).ToLocalChecked()); } -v8::Local javaExceptionToV8(Java* java, JNIEnv* env, const std::string& alternateMessage) { +v8::Local javaExceptionToV8(Java *java, JNIEnv *env, const std::string &alternateMessage) { jthrowable ex = env->ExceptionOccurred(); env->ExceptionClear(); return javaExceptionToV8(java, env, ex, alternateMessage); @@ -482,17 +496,17 @@ jvalueType javaGetArrayComponentType(JNIEnv *env, jobjectArray array) { } #if NODE_VERSION_AT_LEAST(13, 0, 0) - v8::Local newArrayBuffer(void* elems, size_t length) { - v8::Local ab = v8::ArrayBuffer::New(v8::Isolate::GetCurrent(), length); - memcpy(ab->GetBackingStore()->Data(), elems, length); - return ab; - } +v8::Local newArrayBuffer(void *elems, size_t length) { + v8::Local ab = v8::ArrayBuffer::New(v8::Isolate::GetCurrent(), length); + memcpy(ab->GetBackingStore()->Data(), elems, length); + return ab; +} #elif NODE_VERSION_AT_LEAST(4, 0, 0) - v8::Local newArrayBuffer(void* elems, size_t length) { - v8::Local ab = v8::ArrayBuffer::New(v8::Isolate::GetCurrent(), length); - memcpy(ab->GetContents().Data(), elems, length); - return ab; - } +v8::Local newArrayBuffer(void *elems, size_t length) { + v8::Local ab = v8::ArrayBuffer::New(v8::Isolate::GetCurrent(), length); + memcpy(ab->GetContents().Data(), elems, length); + return ab; +} #endif v8::Local javaCharToV8String(jchar c) { @@ -505,157 +519,140 @@ v8::Local javaCharToV8String(jchar c) { #endif } -v8::Local javaArrayToV8(Java* java, JNIEnv* env, jobjectArray objArray) { - if(objArray == NULL) { +v8::Local javaArrayToV8(Java *java, JNIEnv *env, jobjectArray objArray) { + if (objArray == NULL) { return Nan::Null(); } jvalueType arrayComponentType = javaGetArrayComponentType(env, objArray); - //printf("javaArrayToV8: %d %s\n", arrayComponentType, javaObjectToString(env, objArray).c_str()); + // printf("javaArrayToV8: %d %s\n", arrayComponentType, javaObjectToString(env, objArray).c_str()); jsize arraySize = env->GetArrayLength(objArray); - //printf("array size: %d\n", arraySize); + // printf("array size: %d\n", arraySize); v8::Local result = Nan::New(arraySize); // http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html - switch(arrayComponentType) { - case TYPE_CHAR: - { - jchar* elems = env->GetCharArrayElements((jcharArray)objArray, 0); + switch (arrayComponentType) { + case TYPE_CHAR: { + jchar *elems = env->GetCharArrayElements((jcharArray)objArray, 0); #if (NODE_VERSION_AT_LEAST(4, 0, 0)) - size_t byteLength = arraySize * 2; - v8::Local ab = newArrayBuffer(elems, byteLength); - env->ReleaseCharArrayElements((jcharArray)objArray, elems, 0); - return v8::Uint16Array::New(ab, 0, arraySize); + size_t byteLength = arraySize * 2; + v8::Local ab = newArrayBuffer(elems, byteLength); + env->ReleaseCharArrayElements((jcharArray)objArray, elems, 0); + return v8::Uint16Array::New(ab, 0, arraySize); #else - jchar str; - for(jsize i=0; iSet(i, javaCharToV8String(str)); - } - env->ReleaseCharArrayElements((jcharArray)objArray, elems, 0); -#endif + jchar str; + for (jsize i = 0; i < arraySize; i++) { + str = elems[i]; + result->Set(i, javaCharToV8String(str)); } - break; + env->ReleaseCharArrayElements((jcharArray)objArray, elems, 0); +#endif + } break; - case TYPE_INT: - { - jint* elems = env->GetIntArrayElements((jintArray)objArray, 0); + case TYPE_INT: { + jint *elems = env->GetIntArrayElements((jintArray)objArray, 0); #if (NODE_VERSION_AT_LEAST(4, 0, 0)) - size_t byteLength = arraySize * 4; - v8::Local ab = newArrayBuffer(elems, byteLength); - env->ReleaseIntArrayElements((jintArray)objArray, elems, 0); - return v8::Int32Array::New(ab, 0, arraySize); + size_t byteLength = arraySize * 4; + v8::Local ab = newArrayBuffer(elems, byteLength); + env->ReleaseIntArrayElements((jintArray)objArray, elems, 0); + return v8::Int32Array::New(ab, 0, arraySize); #else - for(jsize i=0; iSet(i, Nan::New(elems[i])); - } - env->ReleaseIntArrayElements((jintArray)objArray, elems, 0); -#endif + for (jsize i = 0; i < arraySize; i++) { + result->Set(i, Nan::New(elems[i])); } - break; + env->ReleaseIntArrayElements((jintArray)objArray, elems, 0); +#endif + } break; - case TYPE_BYTE: - { - jbyte* elems = env->GetByteArrayElements((jbyteArray)objArray, 0); + case TYPE_BYTE: { + jbyte *elems = env->GetByteArrayElements((jbyteArray)objArray, 0); #if (NODE_VERSION_AT_LEAST(4, 0, 0)) - size_t byteLength = arraySize; - v8::Local ab = newArrayBuffer(elems, byteLength); - env->ReleaseByteArrayElements((jbyteArray)objArray, elems, 0); - return v8::Int8Array::New(ab, 0, arraySize); + size_t byteLength = arraySize; + v8::Local ab = newArrayBuffer(elems, byteLength); + env->ReleaseByteArrayElements((jbyteArray)objArray, elems, 0); + return v8::Int8Array::New(ab, 0, arraySize); #else - for(jsize i=0; iSet(i, Nan::New(elems[i])); - } - env->ReleaseByteArrayElements((jbyteArray)objArray, elems, 0); -#endif + for (jsize i = 0; i < arraySize; i++) { + result->Set(i, Nan::New(elems[i])); } - break; + env->ReleaseByteArrayElements((jbyteArray)objArray, elems, 0); +#endif + } break; - case TYPE_BOOLEAN: - { - jboolean* elems = env->GetBooleanArrayElements((jbooleanArray)objArray, 0); -#if (NODE_VERSION_AT_LEAST(4, 0, 0)) - size_t byteLength = arraySize; - v8::Local ab = newArrayBuffer(elems, byteLength); - env->ReleaseBooleanArrayElements((jbooleanArray)objArray, elems, 0); - return v8::Uint8Array::New(ab, 0, arraySize); -#else - for(jsize i=0; iSet(i, Nan::New(elems[i])); + case TYPE_BOOLEAN: { + jboolean *elems = env->GetBooleanArrayElements((jbooleanArray)objArray, 0); + for (jsize i = 0; i < arraySize; i++) { + if (hasSetFailed(result->Set(Nan::GetCurrentContext(), i, Nan::New(elems[i])))) { + return v8::Exception::Error(Nan::New("set array element failed").ToLocalChecked()); } - env->ReleaseBooleanArrayElements((jbooleanArray)objArray, elems, 0); -#endif } - break; + env->ReleaseBooleanArrayElements((jbooleanArray)objArray, elems, 0); + } break; - case TYPE_SHORT: - { - jshort* elems = env->GetShortArrayElements((jshortArray)objArray, 0); + case TYPE_SHORT: { + jshort *elems = env->GetShortArrayElements((jshortArray)objArray, 0); #if (NODE_VERSION_AT_LEAST(4, 0, 0)) - size_t byteLength = arraySize * 2; - v8::Local ab = newArrayBuffer(elems, byteLength); - env->ReleaseShortArrayElements((jshortArray)objArray, elems, 0); - return v8::Int16Array::New(ab, 0, arraySize); + size_t byteLength = arraySize * 2; + v8::Local ab = newArrayBuffer(elems, byteLength); + env->ReleaseShortArrayElements((jshortArray)objArray, elems, 0); + return v8::Int16Array::New(ab, 0, arraySize); #else - for(jsize i=0; iSet(i, Nan::New(elems[i])); - } - env->ReleaseShortArrayElements((jshortArray)objArray, elems, 0); -#endif + for (jsize i = 0; i < arraySize; i++) { + result->Set(i, Nan::New(elems[i])); } - break; + env->ReleaseShortArrayElements((jshortArray)objArray, elems, 0); +#endif + } break; - case TYPE_DOUBLE: - { - jdouble* elems = env->GetDoubleArrayElements((jdoubleArray)objArray, 0); + case TYPE_DOUBLE: { + jdouble *elems = env->GetDoubleArrayElements((jdoubleArray)objArray, 0); #if (NODE_VERSION_AT_LEAST(4, 0, 0)) - size_t byteLength = arraySize * 8; - v8::Local ab = newArrayBuffer(elems, byteLength); - env->ReleaseDoubleArrayElements((jdoubleArray)objArray, elems, 0); - return v8::Float64Array::New(ab, 0, arraySize); + size_t byteLength = arraySize * 8; + v8::Local ab = newArrayBuffer(elems, byteLength); + env->ReleaseDoubleArrayElements((jdoubleArray)objArray, elems, 0); + return v8::Float64Array::New(ab, 0, arraySize); #else - for(jsize i=0; iSet(i, Nan::New(elems[i])); - } - env->ReleaseDoubleArrayElements((jdoubleArray)objArray, elems, 0); -#endif + for (jsize i = 0; i < arraySize; i++) { + result->Set(i, Nan::New(elems[i])); } - break; + env->ReleaseDoubleArrayElements((jdoubleArray)objArray, elems, 0); +#endif + } break; - case TYPE_FLOAT: - { - jfloat* elems = env->GetFloatArrayElements((jfloatArray)objArray, 0); + case TYPE_FLOAT: { + jfloat *elems = env->GetFloatArrayElements((jfloatArray)objArray, 0); #if (NODE_VERSION_AT_LEAST(4, 0, 0)) - size_t byteLength = arraySize * 4; - v8::Local ab = newArrayBuffer(elems, byteLength); - env->ReleaseFloatArrayElements((jfloatArray)objArray, elems, 0); - return v8::Float32Array::New(ab, 0, arraySize); + size_t byteLength = arraySize * 4; + v8::Local ab = newArrayBuffer(elems, byteLength); + env->ReleaseFloatArrayElements((jfloatArray)objArray, elems, 0); + return v8::Float32Array::New(ab, 0, arraySize); #else - for(jsize i=0; iSet(i, Nan::New(elems[i])); - } - env->ReleaseFloatArrayElements((jfloatArray)objArray, elems, 0); -#endif + for (jsize i = 0; i < arraySize; i++) { + result->Set(i, Nan::New(elems[i])); } - break; - - case TYPE_LONG: - { - jlong* elems = env->GetLongArrayElements((jlongArray)objArray, 0); - for(jsize i=0; iSet(Nan::GetCurrentContext(), i, JavaObject::New(java, obj)); + env->ReleaseFloatArrayElements((jfloatArray)objArray, elems, 0); +#endif + } break; + + case TYPE_LONG: { + jlong *elems = env->GetLongArrayElements((jlongArray)objArray, 0); + for (jsize i = 0; i < arraySize; i++) { + jobject obj = longToJavaLongObj(env, elems[i]); + if (hasSetFailed(result->Set(Nan::GetCurrentContext(), i, JavaObject::New(java, obj)))) { + return v8::Exception::Error(Nan::New("could not set array element").ToLocalChecked()); } - env->ReleaseLongArrayElements((jlongArray)objArray, elems, 0); } - break; + env->ReleaseLongArrayElements((jlongArray)objArray, elems, 0); + } break; default: - for(jsize i=0; iGetObjectArrayElement(objArray, i); - v8::Local item = javaToV8(java, env, obj); - result->Set(Nan::GetCurrentContext(), i, item); + for (jsize i = 0; i < arraySize; i++) { + jobject obj = env->GetObjectArrayElement(objArray, i); + v8::Local item = javaToV8(java, env, obj); + if (hasSetFailed(result->Set(Nan::GetCurrentContext(), i, item))) { + return v8::Exception::Error(Nan::New("could not set array element").ToLocalChecked()); + } } break; } @@ -663,110 +660,104 @@ v8::Local javaArrayToV8(Java* java, JNIEnv* env, jobjectArray objArra return result; } -v8::Local javaToV8(Java* java, JNIEnv* env, jobject obj) { - return javaToV8(java, env, obj, NULL); -} +v8::Local javaToV8(Java *java, JNIEnv *env, jobject obj) { return javaToV8(java, env, obj, NULL); } -v8::Local javaToV8(Java* java, JNIEnv* env, jobject obj, DynamicProxyData* dynamicProxyData) { - if(obj == NULL) { +v8::Local javaToV8(Java *java, JNIEnv *env, jobject obj, DynamicProxyData *dynamicProxyData) { + if (obj == NULL) { return Nan::Null(); } jclass objClazz = env->GetObjectClass(obj); jvalueType resultType = javaGetType(env, objClazz); - //printf("javaToV8: %d %s\n", resultType, javaObjectToString(env, obj).c_str()); + // printf("javaToV8: %d %s\n", resultType, javaObjectToString(env, obj).c_str()); - switch(resultType) { - case TYPE_ARRAY: - { - v8::Local result = javaArrayToV8(java, env, (jobjectArray)obj); - return result; - } - case TYPE_VOID: - return Nan::Undefined(); - case TYPE_CHAR: - { - jclass charClazz = env->FindClass("java/lang/Character"); - jmethodID char_charValue = env->GetMethodID(charClazz, "charValue", "()C"); - jchar c = env->CallCharMethod(obj, char_charValue); - checkJavaException(env); - return javaCharToV8String(c); - } - case TYPE_BOOLEAN: - { - jclass booleanClazz = env->FindClass("java/lang/Boolean"); - jmethodID boolean_booleanValue = env->GetMethodID(booleanClazz, "booleanValue", "()Z"); - bool result = env->CallBooleanMethod(obj, boolean_booleanValue); - assertNoException(env); - return Nan::New(result); - } - case TYPE_BYTE: - { - jclass byteClazz = env->FindClass("java/lang/Byte"); - jmethodID byte_byteValue = env->GetMethodID(byteClazz, "byteValue", "()B"); - jbyte result = env->CallByteMethod(obj, byte_byteValue); - checkJavaException(env); - return Nan::New(result); - } - case TYPE_LONG: - { - jclass longClazz = env->FindClass("java/lang/Long"); - jmethodID long_longValue = env->GetMethodID(longClazz, "longValue", "()J"); - jlong result = env->CallLongMethod(obj, long_longValue); - checkJavaException(env); - std::string strValue = javaObjectToString(env, obj); - v8::Local v8Result = Nan::New((double)result); - v8::NumberObject* v8ResultNumberObject = v8::NumberObject::Cast(*v8Result); - v8ResultNumberObject->Set(Nan::GetCurrentContext(), Nan::New("longValue").ToLocalChecked(), Nan::New(strValue.c_str()).ToLocalChecked()); - SetHiddenValue(v8ResultNumberObject, Nan::New(V8_HIDDEN_MARKER_JAVA_LONG).ToLocalChecked(), Nan::New(true)); - return v8Result; - } - case TYPE_INT: - { - jclass integerClazz = env->FindClass("java/lang/Integer"); - jmethodID integer_intValue = env->GetMethodID(integerClazz, "intValue", "()I"); - jint result = env->CallIntMethod(obj, integer_intValue); - checkJavaException(env); - return Nan::New(result); - } - case TYPE_SHORT: - { - jclass shortClazz = env->FindClass("java/lang/Short"); - jmethodID short_shortValue = env->GetMethodID(shortClazz, "shortValue", "()S"); - jshort result = env->CallShortMethod(obj, short_shortValue); - assertNoException(env); - return Nan::New(result); - } - case TYPE_DOUBLE: - { - jclass doubleClazz = env->FindClass("java/lang/Double"); - jmethodID double_doubleValue = env->GetMethodID(doubleClazz, "doubleValue", "()D"); - jdouble result = env->CallDoubleMethod(obj, double_doubleValue); - checkJavaException(env); - return Nan::New(result); - } - case TYPE_FLOAT: - { - jclass floatClazz = env->FindClass("java/lang/Float"); - jmethodID float_floatValue = env->GetMethodID(floatClazz, "floatValue", "()F"); - jfloat result = env->CallFloatMethod(obj, float_floatValue); - assertNoException(env); - return Nan::New(result); - } - case TYPE_STRING: - { - std::string str = javaObjectToString(env, obj); - return Nan::New(str.c_str(), str.length()).ToLocalChecked(); - } - case TYPE_OBJECT: - if (dynamicProxyData != NULL) { - return JavaProxyObject::New(java, obj, dynamicProxyData); - } - return JavaObject::New(java, obj); - default: - printf("javaToV8: unhandled type: 0x%03x\n", resultType); - return JavaObject::New(java, obj); + switch (resultType) { + case TYPE_ARRAY: { + v8::Local result = javaArrayToV8(java, env, (jobjectArray)obj); + return result; + } + case TYPE_VOID: + return Nan::Undefined(); + case TYPE_CHAR: { + jclass charClazz = env->FindClass("java/lang/Character"); + jmethodID char_charValue = env->GetMethodID(charClazz, "charValue", "()C"); + jchar c = env->CallCharMethod(obj, char_charValue); + checkJavaException(env); + return javaCharToV8String(c); + } + case TYPE_BOOLEAN: { + jclass booleanClazz = env->FindClass("java/lang/Boolean"); + jmethodID boolean_booleanValue = env->GetMethodID(booleanClazz, "booleanValue", "()Z"); + bool result = env->CallBooleanMethod(obj, boolean_booleanValue); + assertNoException(env); + return Nan::New(result); + } + case TYPE_BYTE: { + jclass byteClazz = env->FindClass("java/lang/Byte"); + jmethodID byte_byteValue = env->GetMethodID(byteClazz, "byteValue", "()B"); + jbyte result = env->CallByteMethod(obj, byte_byteValue); + checkJavaException(env); + return Nan::New(result); + } + case TYPE_LONG: { + jclass longClazz = env->FindClass("java/lang/Long"); + jmethodID long_longValue = env->GetMethodID(longClazz, "longValue", "()J"); + jlong result = env->CallLongMethod(obj, long_longValue); + checkJavaException(env); + std::string strValue = javaObjectToString(env, obj); + v8::Local v8Result = Nan::New((double)result); + v8::NumberObject *v8ResultNumberObject = v8::NumberObject::Cast(*v8Result); + if (hasSetFailed(v8ResultNumberObject->Set(Nan::GetCurrentContext(), + Nan::New("longValue").ToLocalChecked(), + Nan::New(strValue.c_str()).ToLocalChecked()))) { + return v8::Exception::Error(Nan::New("could not set longValue").ToLocalChecked()); + } + SetHiddenValue(v8ResultNumberObject, Nan::New(V8_HIDDEN_MARKER_JAVA_LONG).ToLocalChecked(), + Nan::New(true)); + return v8Result; + } + case TYPE_INT: { + jclass integerClazz = env->FindClass("java/lang/Integer"); + jmethodID integer_intValue = env->GetMethodID(integerClazz, "intValue", "()I"); + jint result = env->CallIntMethod(obj, integer_intValue); + checkJavaException(env); + // <-- use the Int32 factory, not the generic Integer one + return Nan::New(static_cast(result)); + } + case TYPE_SHORT: { + jclass shortClazz = env->FindClass("java/lang/Short"); + jmethodID short_shortValue = env->GetMethodID(shortClazz, "shortValue", "()S"); + jshort result = env->CallShortMethod(obj, short_shortValue); + assertNoException(env); + return Nan::New(result); + } + case TYPE_DOUBLE: { + jclass doubleClazz = env->FindClass("java/lang/Double"); + jmethodID double_doubleValue = env->GetMethodID(doubleClazz, "doubleValue", "()D"); + jdouble result = env->CallDoubleMethod(obj, double_doubleValue); + checkJavaException(env); + return Nan::New(result); + } + case TYPE_FLOAT: { + jclass floatClazz = env->FindClass("java/lang/Float"); + jmethodID float_floatValue = env->GetMethodID(floatClazz, "floatValue", "()F"); + jfloat result = env->CallFloatMethod(obj, float_floatValue); + assertNoException(env); + return Nan::New(result); + } + case TYPE_STRING: { + std::string str = javaObjectToString(env, obj); + return Nan::New(str.c_str(), str.length()).ToLocalChecked(); + } + case TYPE_OBJECT: + if (dynamicProxyData != NULL) { + return JavaProxyObject::New(java, obj, dynamicProxyData); + } + return JavaObject::New(java, obj); + default: + printf("javaToV8: unhandled type: 0x%03x\n", resultType); + return JavaObject::New(java, obj); } return Nan::Undefined(); @@ -776,9 +767,9 @@ jobjectArray javaObjectArrayToClasses(JNIEnv *env, jobjectArray objs) { jclass clazzClazz = env->FindClass("java/lang/Class"); jsize objsLength = env->GetArrayLength(objs); jobjectArray results = env->NewObjectArray(objsLength, clazzClazz, NULL); - for(jsize i=0; iGetObjectArrayElement(objs, i); - if(elem == NULL) { + if (elem == NULL) { env->SetObjectArrayElement(results, i, NULL); } else { jclass objClazz = env->GetObjectClass(elem); @@ -789,29 +780,31 @@ jobjectArray javaObjectArrayToClasses(JNIEnv *env, jobjectArray objs) { return results; } -jobject javaFindMethod(JNIEnv *env, jclass clazz, const std::string& methodName, jobjectArray methodArgs) { +jobject javaFindMethod(JNIEnv *env, jclass clazz, const std::string &methodName, jobjectArray methodArgs) { std::string::size_type parenLoc = methodName.find("("); - if(parenLoc != std::string::npos) { + if (parenLoc != std::string::npos) { jobject method = NULL; std::string methodSig = methodName.substr(parenLoc); std::string methodRealName = methodName.substr(0, parenLoc); jmethodID methodID = env->GetStaticMethodID(clazz, methodRealName.c_str(), methodSig.c_str()); - env->ExceptionClear(); // If GetStaticMethodID can't find the method it throws an exception and we need to just return NULL - if(methodID != 0) { + env->ExceptionClear(); // If GetStaticMethodID can't find the method it throws an exception and we need to just + // return NULL + if (methodID != 0) { method = env->ToReflectedMethod(clazz, methodID, true); } else { methodID = env->GetMethodID(clazz, methodRealName.c_str(), methodSig.c_str()); - env->ExceptionClear(); // If GetMethodID can't find the method it throws an exception and we need to just return NULL - if(methodID != 0) { + env->ExceptionClear(); // If GetMethodID can't find the method it throws an exception and we need to just return + // NULL + if (methodID != 0) { method = env->ToReflectedMethod(clazz, methodID, true); } } // cast arguments - if(method != NULL) { + if (method != NULL) { javaCastArguments(env, methodArgs, method); - if(env->ExceptionCheck()) { + if (env->ExceptionCheck()) { env->ExceptionClear(); method = NULL; } @@ -820,11 +813,14 @@ jobject javaFindMethod(JNIEnv *env, jclass clazz, const std::string& methodName, return method; } else { jclass methodUtilsClazz = env->FindClass("nodejava/org/apache/commons/lang3/reflect/MethodUtils"); - jmethodID methodUtils_getMatchingAccessibleMethod = env->GetStaticMethodID(methodUtilsClazz, "getMatchingAccessibleMethod", "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;"); + jmethodID methodUtils_getMatchingAccessibleMethod = + env->GetStaticMethodID(methodUtilsClazz, "getMatchingAccessibleMethod", + "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;"); const char *methodNameCStr = methodName.c_str(); jstring methodNameJavaStr = env->NewStringUTF(methodNameCStr); jobjectArray methodArgClasses = javaObjectArrayToClasses(env, methodArgs); - jobject method = env->CallStaticObjectMethod(methodUtilsClazz, methodUtils_getMatchingAccessibleMethod, clazz, methodNameJavaStr, methodArgClasses); + jobject method = env->CallStaticObjectMethod(methodUtilsClazz, methodUtils_getMatchingAccessibleMethod, clazz, + methodNameJavaStr, methodArgClasses); checkJavaException(env); return method; } @@ -832,15 +828,19 @@ jobject javaFindMethod(JNIEnv *env, jclass clazz, const std::string& methodName, void javaCastArguments(JNIEnv *env, jobjectArray methodArgs, jobject method) { jclass castingUtilsClazz = env->FindClass("node/CastingUtils"); - jmethodID castingUtilsClazz_cast = env->GetStaticMethodID(castingUtilsClazz, "cast", "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)V"); + jmethodID castingUtilsClazz_cast = + env->GetStaticMethodID(castingUtilsClazz, "cast", "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)V"); env->CallStaticObjectMethod(castingUtilsClazz, castingUtilsClazz_cast, method, methodArgs); } jobject javaFindConstructor(JNIEnv *env, jclass clazz, jobjectArray methodArgs) { jclass constructorUtilsClazz = env->FindClass("nodejava/org/apache/commons/lang3/reflect/ConstructorUtils"); - jmethodID constructorUtils_getMatchingAccessibleConstructor = env->GetStaticMethodID(constructorUtilsClazz, "getMatchingAccessibleConstructor", "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/reflect/Constructor;"); + jmethodID constructorUtils_getMatchingAccessibleConstructor = + env->GetStaticMethodID(constructorUtilsClazz, "getMatchingAccessibleConstructor", + "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/reflect/Constructor;"); jobjectArray methodArgClasses = javaObjectArrayToClasses(env, methodArgs); - jobject method = env->CallStaticObjectMethod(constructorUtilsClazz, constructorUtils_getMatchingAccessibleConstructor, clazz, methodArgClasses); + jobject method = env->CallStaticObjectMethod(constructorUtilsClazz, constructorUtils_getMatchingAccessibleConstructor, + clazz, methodArgClasses); assertNoException(env); return method; } @@ -852,16 +852,19 @@ jobject longToJavaLongObj(JNIEnv *env, jlong val) { return result; } -int dynamicProxyDataVerify(DynamicProxyData* data) { - if(data->markerStart == DYNAMIC_PROXY_DATA_MARKER_START && data->markerEnd == DYNAMIC_PROXY_DATA_MARKER_END) { +int dynamicProxyDataVerify(DynamicProxyData *data) { + if (data->markerStart == DYNAMIC_PROXY_DATA_MARKER_START && data->markerEnd == DYNAMIC_PROXY_DATA_MARKER_END) { return 1; } - printf("*** ERROR: Lost reference to the dynamic proxy. You must maintain a reference in javascript land using ref() and unref(). (%p) ***\n", data); + printf("*** ERROR: Lost reference to the dynamic proxy. You must maintain a reference in javascript land using ref() " + "and unref(). (%p) ***\n", + data); return 0; } -std::string methodNotFoundToString(JNIEnv *env, jclass clazz, const std::string& methodNameSig, bool constructor, Nan::NAN_METHOD_ARGS_TYPE args, int argStart, int argEnd) { +std::string methodNotFoundToString(JNIEnv *env, jclass clazz, const std::string &methodNameSig, bool constructor, + Nan::NAN_METHOD_ARGS_TYPE args, int argStart, int argEnd) { std::ostringstream startOfMessage; std::ostringstream msg; std::string methodName = methodNameSig.substr(0, methodNameSig.find('(')); @@ -875,12 +878,12 @@ std::string methodNotFoundToString(JNIEnv *env, jclass clazz, const std::string& startOfMessage << "Could not find method \"" << methodName.c_str() << "("; } - for(int i=argStart; iGetObjectClass(val); @@ -891,7 +894,7 @@ std::string methodNotFoundToString(JNIEnv *env, jclass clazz, const std::string& } } - startOfMessage << ")\" on class \""<< javaObjectToString(env, clazz).c_str() << "\"."; + startOfMessage << ")\" on class \"" << javaObjectToString(env, clazz).c_str() << "\"."; msg << startOfMessage.str() << " Possible matches:\n"; @@ -899,24 +902,24 @@ std::string methodNotFoundToString(JNIEnv *env, jclass clazz, const std::string& jmethodID member_getName = env->GetMethodID(memberClazz, "getName", "()Ljava/lang/String;"); std::list methods; - if(constructor) { + if (constructor) { javaReflectionGetConstructors(env, clazz, &methods); } else { javaReflectionGetMethods(env, clazz, &methods, true); } int count = 0; - for(std::list::iterator it = methods.begin(); it != methods.end(); ++it) { + for (std::list::iterator it = methods.begin(); it != methods.end(); ++it) { jstring methodNameTestJava = (jstring)env->CallObjectMethod(*it, member_getName); assertNoException(env); std::string methodNameTest = javaToString(env, methodNameTestJava); - if(methodNameTest == methodName) { + if (methodNameTest == methodName) { msg << " " << javaObjectToString(env, *it).c_str() << "\n"; count++; } } - if(count == 0) { + if (count == 0) { std::ostringstream noMethodsMsg; noMethodsMsg << startOfMessage.str() << " No methods with that name."; return noMethodsMsg.str(); @@ -925,8 +928,8 @@ std::string methodNotFoundToString(JNIEnv *env, jclass clazz, const std::string& return msg.str(); } -void unref(DynamicProxyData* dynamicProxyData) { - if(!dynamicProxyDataVerify(dynamicProxyData)) { +void unref(DynamicProxyData *dynamicProxyData) { + if (!dynamicProxyDataVerify(dynamicProxyData)) { return; } dynamicProxyData->jsObject.Reset(); @@ -938,7 +941,8 @@ void unref(DynamicProxyData* dynamicProxyData) { jarray javaGetArgsForMethod(JNIEnv *env, jobject method, jarray args) { jclass varArgsClazz = env->FindClass("node/VarArgs"); - jmethodID method_getVarArgs = env->GetStaticMethodID(varArgsClazz, "getVarArgs", "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)[Ljava/lang/Object;"); + jmethodID method_getVarArgs = env->GetStaticMethodID( + varArgsClazz, "getVarArgs", "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)[Ljava/lang/Object;"); jarray result = (jarray)env->CallStaticObjectMethod(varArgsClazz, method_getVarArgs, method, args); checkJavaException(env); return result; @@ -946,55 +950,56 @@ jarray javaGetArgsForMethod(JNIEnv *env, jobject method, jarray args) { jarray javaGetArgsForConstructor(JNIEnv *env, jobject method, jarray args) { jclass varArgsClazz = env->FindClass("node/VarArgs"); - jmethodID method_getVarArgs = env->GetStaticMethodID(varArgsClazz, "getVarArgs", "(Ljava/lang/reflect/Constructor;[Ljava/lang/Object;)[Ljava/lang/Object;"); + jmethodID method_getVarArgs = env->GetStaticMethodID( + varArgsClazz, "getVarArgs", "(Ljava/lang/reflect/Constructor;[Ljava/lang/Object;)[Ljava/lang/Object;"); jarray result = (jarray)env->CallStaticObjectMethod(varArgsClazz, method_getVarArgs, method, args); checkJavaException(env); return result; } #if (NODE_MODULE_VERSION > 48) - // The two methods below were copied from - // https://github.com/electron/electron?branch=master&filepath=atom/common/api/atom_api_v8_util.cc - // Copyright (c) 2013 GitHub, Inc. - // Use of this source code is governed by the MIT license. - - v8::Local GetHiddenValue(v8::Local object, v8::Local key) { - v8::Local context = v8::Isolate::GetCurrent()->GetCurrentContext(); - v8::Local privateKey = v8::Private::ForApi(v8::Isolate::GetCurrent(), key); - v8::Local value; - v8::Maybe result = object->HasPrivate(context, privateKey); - if (!(result.IsJust() && result.FromJust())) - return v8::Local(); - if (object->GetPrivate(context, privateKey).ToLocal(&value)) - return value; +// The two methods below were copied from +// https://github.com/electron/electron?branch=master&filepath=atom/common/api/atom_api_v8_util.cc +// Copyright (c) 2013 GitHub, Inc. +// Use of this source code is governed by the MIT license. + +v8::Local GetHiddenValue(v8::Local object, v8::Local key) { + v8::Local context = v8::Isolate::GetCurrent()->GetCurrentContext(); + v8::Local privateKey = v8::Private::ForApi(v8::Isolate::GetCurrent(), key); + v8::Local value; + v8::Maybe result = object->HasPrivate(context, privateKey); + if (!(result.IsJust() && result.FromJust())) return v8::Local(); - } + if (object->GetPrivate(context, privateKey).ToLocal(&value)) + return value; + return v8::Local(); +} - void SetHiddenValue(v8::NumberObject* object, v8::Local key, v8::Local value) { - if (value.IsEmpty()) - return; - v8::Local context = v8::Isolate::GetCurrent()->GetCurrentContext(); - v8::Local privateKey = v8::Private::ForApi(v8::Isolate::GetCurrent(), key); - object->SetPrivate(context, privateKey, value); - } +void SetHiddenValue(v8::NumberObject *object, v8::Local key, v8::Local value) { + if (value.IsEmpty()) + return; + v8::Local context = v8::Isolate::GetCurrent()->GetCurrentContext(); + v8::Local privateKey = v8::Private::ForApi(v8::Isolate::GetCurrent(), key); + object->SetPrivate(context, privateKey, value); +} - void SetHiddenValue(v8::Local object, v8::Local key, v8::Local value) { - if (value.IsEmpty()) - return; - v8::Local context = v8::Isolate::GetCurrent()->GetCurrentContext(); - v8::Local privateKey = v8::Private::ForApi(v8::Isolate::GetCurrent(), key); - object->SetPrivate(context, privateKey, value); - } +void SetHiddenValue(v8::Local object, v8::Local key, v8::Local value) { + if (value.IsEmpty()) + return; + v8::Local context = v8::Isolate::GetCurrent()->GetCurrentContext(); + v8::Local privateKey = v8::Private::ForApi(v8::Isolate::GetCurrent(), key); + object->SetPrivate(context, privateKey, value); +} #else - v8::Local GetHiddenValue(v8::Local object, v8::Local key) { - return object->GetHiddenValue(key); - } +v8::Local GetHiddenValue(v8::Local object, v8::Local key) { + return object->GetHiddenValue(key); +} - void SetHiddenValue(v8::NumberObject* object, v8::Local key, v8::Local value) { - object->SetHiddenValue(key, value); - } +void SetHiddenValue(v8::NumberObject *object, v8::Local key, v8::Local value) { + object->SetHiddenValue(key, value); +} - void SetHiddenValue(v8::Local object, v8::Local key, v8::Local value) { - object->SetHiddenValue(key, value); - } +void SetHiddenValue(v8::Local object, v8::Local key, v8::Local value) { + object->SetHiddenValue(key, value); +} #endif diff --git a/src-cpp/utils.h b/src-cpp/utils.h new file mode 100644 index 00000000..bc7cc171 --- /dev/null +++ b/src-cpp/utils.h @@ -0,0 +1,175 @@ + +#ifndef _utils_h_ +#define _utils_h_ + +#define BUILDING_NODE_EXTENSION 1 +#include +#include +#include +#include +#include +#include +#include + +class Java; + +#define V8_HIDDEN_MARKER_JAVA_LONG "__isJavaLong" +#define V8_HIDDEN_MARKER_JAVA_OBJECT "__isJavaObject" + +#if NODE_MAJOR_VERSION >= 23 + #define RETURN_INTERCEPTED_YES return v8::Intercepted::kYes + #define RETURN_INTERCEPTED_NO return v8::Intercepted::kNo +#else + #define RETURN_INTERCEPTED_YES return + #define RETURN_INTERCEPTED_NO return +#endif + +typedef enum _jvalueType { + TYPE_VOID = 1, + TYPE_INT = 2, + TYPE_LONG = 3, + TYPE_OBJECT = 4, + TYPE_STRING = 5, + TYPE_BOOLEAN = 6, + TYPE_SHORT = 7, + TYPE_BYTE = 8, + TYPE_DOUBLE = 9, + TYPE_FLOAT = 10, + TYPE_ARRAY = 11, + TYPE_CHAR = 12 +} jvalueType; + +struct DynamicProxyData { + unsigned int markerStart; + Java *java; + std::string interfaceName; + Nan::Persistent functions; + Nan::Persistent jsObject; + unsigned int markerEnd; +}; + +struct DynamicProxyJsCallData { + DynamicProxyData *dynamicProxyData; + std::string methodName; + jobjectArray args; + jobject result; + std::string throwableClass; + std::string throwableMessage; + int done; +}; + +#define DYNAMIC_PROXY_DATA_MARKER_START 0x12345678 +#define DYNAMIC_PROXY_DATA_MARKER_END 0x87654321 + +int dynamicProxyDataVerify(DynamicProxyData *data); + +void javaReflectionGetMethods(JNIEnv *env, jclass clazz, std::list *methods, bool includeStatic); +void javaReflectionGetConstructors(JNIEnv *env, jclass clazz, std::list *methods); +void javaReflectionGetFields(JNIEnv *env, jclass clazz, std::list *fields); +std::string javaToString(JNIEnv *env, jstring str); +std::string javaObjectToString(JNIEnv *env, jobject obj); +std::string javaArrayToString(JNIEnv *env, jobjectArray arr); +std::string javaMethodCallToString(JNIEnv *env, jobject obj, jmethodID methodId, jarray args); +JNIEnv *javaGetEnv(JavaVM *jvm, jobject classLoader); +jobject getSystemClassLoader(JNIEnv *env); +jvalueType javaGetArrayComponentType(JNIEnv *env, jobjectArray array); +jvalueType javaGetType(JNIEnv *env, jclass type); +jobjectArray v8ToJava(JNIEnv *env, Nan::NAN_METHOD_ARGS_TYPE args, int start, int end); +jobject v8ToJava(JNIEnv *env, v8::Local arg); +v8::Local javaExceptionToV8(Java *java, JNIEnv *env, const std::string &alternateMessage); +v8::Local javaExceptionToV8(Java *java, JNIEnv *env, jthrowable ex, const std::string &alternateMessage); +std::string javaExceptionToString(JNIEnv *env, jthrowable ex); +void checkJavaException(JNIEnv *env); +v8::Local javaArrayToV8(Java *java, JNIEnv *env, jobjectArray objArray); +v8::Local javaToV8(Java *java, JNIEnv *env, jobject obj); +v8::Local javaToV8(Java *java, JNIEnv *env, jobject obj, DynamicProxyData *dynamicProxyData); +jobjectArray javaObjectArrayToClasses(JNIEnv *env, jobjectArray objs); +jobject longToJavaLongObj(JNIEnv *env, jlong l); +jarray javaGetArgsForMethod(JNIEnv *env, jobject method, jarray args); +jarray javaGetArgsForConstructor(JNIEnv *env, jobject method, jarray args); + +jclass javaFindClass(JNIEnv *env, const std::string &className); +jobject javaFindField(JNIEnv *env, jclass clazz, const std::string &fieldName); +jobject javaFindMethod(JNIEnv *env, jclass clazz, const std::string &methodName, jobjectArray methodArgs); +jobject javaFindConstructor(JNIEnv *env, jclass clazz, jobjectArray methodArgs); +void javaCastArguments(JNIEnv *env, jobjectArray methodArgs, jobject method); + +// TODO remove these functions after node nan gets updated +v8::Local GetHiddenValue(v8::Local object, v8::Local key); +void SetHiddenValue(v8::Local object, v8::Local key, v8::Local value); +void SetHiddenValue(v8::NumberObject *, v8::Local key, v8::Local value); + +#define assertNoException(env) \ + if (env->ExceptionCheck()) { \ + env->ExceptionDescribe(); \ + assert(false); \ + } + +std::string methodNotFoundToString(JNIEnv *env, jclass clazz, const std::string &methodNameSig, bool constructor, + Nan::NAN_METHOD_ARGS_TYPE args, int argStart, int argEnd); + +void unref(DynamicProxyData *dynamicProxyData); + +#define UNUSED_VARIABLE(var) var = var; + +#define ARGS_FRONT_OBJECT(ARGNAME) \ + if (info.Length() < argsStart + 1 || !info[argsStart]->IsObject()) { \ + std::ostringstream errStr; \ + errStr << "Argument " << (argsStart + 1) << " must be an object"; \ + Nan::ThrowError(Nan::TypeError(errStr.str().c_str())); \ + return; \ + } \ + v8::Local ARGNAME = v8::Local::Cast(info[argsStart]); \ + argsStart++; + +#define ARGS_FRONT_STRING(ARGNAME) \ + if (info.Length() < argsStart + 1 || !info[argsStart]->IsString()) { \ + std::ostringstream errStr; \ + errStr << "Argument " << (argsStart + 1) << " must be a string"; \ + Nan::ThrowError(Nan::TypeError(errStr.str().c_str())); \ + return; \ + } \ + v8::Local _##ARGNAME##_obj = v8::Local::Cast(info[argsStart]); \ + Nan::Utf8String _##ARGNAME##_val(_##ARGNAME##_obj); \ + std::string ARGNAME = *_##ARGNAME##_val; \ + argsStart++; + +#define ARGS_FRONT_CLASSNAME() ARGS_FRONT_STRING(className) + +#define ARGS_BACK_CALLBACK() \ + bool callbackProvided; \ + v8::Local callback; \ + if (info[info.Length() - 1]->IsFunction()) { \ + callback = info[argsEnd - 1]; \ + argsEnd--; \ + callbackProvided = true; \ + } else { \ + callback = Nan::Null(); \ + callbackProvided = false; \ + } + +#define EXCEPTION_CALL_CALLBACK(JAVA, STRBUILDER) \ + std::ostringstream errStr; \ + errStr << STRBUILDER; \ + v8::Local error = javaExceptionToV8(JAVA, env, errStr.str()); \ + v8::Local argv[2]; \ + argv[0] = error; \ + argv[1] = Nan::Undefined(); \ + Nan::Call(callback.As(), Nan::GetCurrentContext()->Global(), 2, argv); + +#define END_CALLBACK_FUNCTION(MSG) \ + if (callbackProvided) { \ + info.GetReturnValue().SetUndefined(); \ + return; \ + } else { \ + std::ostringstream str; \ + str << MSG; \ + info.GetReturnValue().Set(Nan::New(str.str().c_str()).ToLocalChecked()); \ + return; \ + } + +#ifndef UNUSED_VARIABLE +#define UNUSED_VARIABLE(a) a = a; +#endif + +#endif diff --git a/src-java/commons-lang3-node-java.jar b/src-java/commons-lang3-node-java.jar new file mode 100644 index 00000000..11e9172f Binary files /dev/null and b/src-java/commons-lang3-node-java.jar differ diff --git a/src-java/node/CastingUtils.class b/src-java/node/CastingUtils.class index de535982..a449276b 100644 Binary files a/src-java/node/CastingUtils.class and b/src-java/node/CastingUtils.class differ diff --git a/src-java/node/MethodCallBaton.class b/src-java/node/MethodCallBaton.class index 9cc4e4df..efb946b6 100644 Binary files a/src-java/node/MethodCallBaton.class and b/src-java/node/MethodCallBaton.class differ diff --git a/src-java/node/NodeDynamicProxyClass.class b/src-java/node/NodeDynamicProxyClass.class index 9eed5b23..95373a4b 100644 Binary files a/src-java/node/NodeDynamicProxyClass.class and b/src-java/node/NodeDynamicProxyClass.class differ diff --git a/src-java/node/NodeJsException.class b/src-java/node/NodeJsException.class index a19d4db4..1697d05e 100644 Binary files a/src-java/node/NodeJsException.class and b/src-java/node/NodeJsException.class differ diff --git a/src-java/node/VarArgs.class b/src-java/node/VarArgs.class index ecd67e02..6f990ec7 100644 Binary files a/src-java/node/VarArgs.class and b/src-java/node/VarArgs.class differ diff --git a/src-node/nodeJavaBridge.js b/src-node/nodeJavaBridge.js new file mode 100644 index 00000000..01f39978 --- /dev/null +++ b/src-node/nodeJavaBridge.js @@ -0,0 +1,327 @@ +"use strict"; + +process.env.PATH += require("../build/jvm_dll_path.json"); + +const path = require("path"); +const fs = require("fs"); +const util = require("util"); + +let binaryPath = null; +try { + if (fs.statSync && fs.statSync(path.join(__dirname, "../build/Debug/nodejavabridge_bindings.node")).isFile()) { + binaryPath = path.resolve(path.join(__dirname, "../build/Debug/nodejavabridge_bindings.node")); + console.log("****** NODE-JAVA RUNNING IN DEBUG MODE ******"); + } +} catch (_err) { + // do nothing fs.statSync just couldn't find the file +} +if (!binaryPath) { + binaryPath = path.resolve(path.join(__dirname, "../build/Release/nodejavabridge_bindings.node")); +} +const bindings = require(binaryPath); + +const java = (module.exports = new bindings.Java()); +java.promisify = util.promisify; +java.classpath.push(path.resolve(__dirname, "../src-java/commons-lang3-node-java.jar")); +java.classpath.push(path.resolve(__dirname, __dirname, "../src-java")); +java.classpath.pushDir = function (dir) { + fs.readdirSync(dir).forEach(function (file) { + java.classpath.push(path.resolve(dir, file)); + }); +}; +java.nativeBindingLocation = binaryPath; + +const callStaticMethod = java.callStaticMethod; +const callStaticMethodSync = java.callStaticMethodSync; +const newInstanceSync = java.newInstanceSync; + +let syncSuffix = undefined; +let asyncSuffix = undefined; +let ifReadOnlySuffix = "_"; + +const SyncCall = function (obj, method) { + if (syncSuffix === undefined) { + throw new Error("Sync call made before jvm created"); + } + const syncMethodName = method + syncSuffix; + if (syncMethodName in obj) { + return obj[syncMethodName].bind(obj); + } else { + throw new Error("Sync method not found:" + syncMethodName); + } +}; + +java.isJvmCreated = function () { + return typeof java.onJvmCreated !== "function"; +}; + +const clients = []; + +// We provide two methods for 'clients' of node-java to 'register' their use of java. +// By registering, a client gets the opportunity to be called asynchronously just before the JVM is created, +// and just after the JVM is created. The before hook function will typically be used to add to java.classpath. +// The function may peform asynchronous operations, such as async [glob](https://github.com/isaacs/node-glob) +// resolutions of wild-carded file system paths, and then notify when it has finished via either calling +// a node-style callback function, or by resolving a promise. + +// A client can register function hooks to be called before and after the JVM is created. +// If the client doesn't need to be called back for either function, it can pass null or undefined. +// Both before and after here are assumed to be functions that accept one argument that is a node-callback function. +java.registerClient = function (before, after) { + if (java.isJvmCreated()) { + throw new Error("java.registerClient() called after JVM already created."); + } + const before_ = + before && before.length === 0 + ? function (cb) { + before(); + cb(); + } + : before; + + const after_ = + after && after.length === 0 + ? function (cb) { + after(); + cb(); + } + : after; + + clients.push({ before: before_, after: after_ }); +}; + +// A client can register function hooks to be called before and after the JVM is created. +// If the client doesn't need to be called back for either function, it can pass null or undefined. +// Both before and after here are assumed to be functions that return Promises/A+ `thenable` objects. +java.registerClientP = function (beforeP, afterP) { + if (java.isJvmCreated()) { + throw new Error("java.registerClient() called after JVM already created."); + } + clients.push({ beforeP: beforeP, afterP: afterP }); +}; + +async function runBeforeHooks() { + for (const client of clients) { + if (client.before) { + await new Promise((resolve, reject) => { + client.before((err) => { + if (err) { + return reject(err); + } + return resolve(); + }); + }); + } + if (client.beforeP) { + await client.beforeP(); + } + } +} + +function createJVMAsync() { + const _ignore = java.newLong(0); // called just for the side effect that it will create the JVM +} + +async function runAfterHooks() { + for (const client of clients) { + if (client.after) { + await new Promise((resolve, reject) => { + client.after((err) => { + if (err) { + return reject(err); + } + return resolve(); + }); + }); + } + if (client.afterP) { + await client.afterP(); + } + } +} + +async function initializeAll() { + await runBeforeHooks(); + createJVMAsync(); + await runAfterHooks(); +} + +// This function ensures that the JVM has been launched, asynchronously. The application can be notified +// when the JVM is fully created via either a node callback function, or via a promise. +// If the parameter `callback` is provided, it is assume be a node callback function. +// This function may be called multiple times -- the 2nd and subsequent calls are no-ops. +// However, once this method has been called (or the JVM is launched as a side effect of calling other java +// methods), then clients can no longer use the registerClient API. +java.ensureJvm = function (callback) { + // First see if the promise-style API should be used. + // This must be done first in order to ensure the proper API is used. + if (typeof callback === "undefined") { + // Create a promisified version of this function. + const launchJvmPromise = util.promisify(java.ensureJvm.bind(java)); + // Call the promisified function, returning its result, which should be a promise. + return launchJvmPromise(); + } + + // If we get here, callback must be a node-style callback function. If not, throw an error. + else if (typeof callback !== "function") { + throw new Error("java.launchJvm(cb) requires its one argument to be a callback function."); + } + + // Now check if the JVM has already been created. If so, we assume that the jvm was already successfully + // launched, and we can just implement idempotent behavior, i.e. silently notify that the JVM has been created. + else if (java.isJvmCreated()) { + return setImmediate(callback); + } + + // Finally, queue the initializeAll function. + else { + return setImmediate(async () => { + try { + await initializeAll(); + callback(); + } catch (err) { + callback(err); + } + }); + } +}; + +java.onJvmCreated = function () { + if (java.asyncOptions) { + syncSuffix = java.asyncOptions.syncSuffix; + asyncSuffix = java.asyncOptions.asyncSuffix; + if (typeof syncSuffix !== "string") { + throw new Error("In asyncOptions, syncSuffix must be defined and must a string"); + } + const promiseSuffix = java.asyncOptions.promiseSuffix; + if (typeof promiseSuffix === "string") { + const methods = ["newInstance", "callMethod", "callStaticMethod"]; + methods.forEach(function (name) { + java[name + promiseSuffix] = util.promisify(java[name]); + }); + } + + if (typeof java.asyncOptions.ifReadOnlySuffix === "string" && java.asyncOptions.ifReadOnlySuffix !== "") { + ifReadOnlySuffix = java.asyncOptions.ifReadOnlySuffix; + } + } else { + syncSuffix = "Sync"; + asyncSuffix = ""; + } +}; + +const MODIFIER_PUBLIC = 1; +const MODIFIER_STATIC = 8; + +function isWritable(prop) { + // If the property has no descriptor, or wasn't explicitly marked as not writable or not configurable, assume it is. + // We check both desc.writable and desc.configurable, since checking desc.writable alone is not sufficient + // (e.g. for either .caller or .arguments). + // It may be that checking desc.configurable is sufficient, but the specification doesn't make this definitive, + // and there is no harm in checking both. + if (prop === "caller" || prop === "arguments") { + return false; + } + + const desc = Object.getOwnPropertyDescriptor(function () {}, prop) || {}; + return desc.writable !== false && desc.configurable !== false; +} + +function usableName(name) { + if (!isWritable(name)) { + name = name + ifReadOnlySuffix; + } + return name; +} + +java.import = function (name) { + const clazz = java.findClassSync(name); // TODO: change to Class.forName when classloader issue is resolved. + const result = function javaClassConstructorProxy() { + const args = [name]; + for (let i = 0; i < arguments.length; i++) { + args.push(arguments[i]); + } + return newInstanceSync.apply(java, args); + }; + + result.class = clazz; + + // copy static fields + const fields = SyncCall(clazz, "getDeclaredFields")(); + for (let i = 0; i < fields.length; i++) { + const modifiers = SyncCall(fields[i], "getModifiers")(); + if ((modifiers & MODIFIER_PUBLIC) === MODIFIER_PUBLIC && (modifiers & MODIFIER_STATIC) === MODIFIER_STATIC) { + const fieldName = SyncCall(fields[i], "getName")(); + const jsfieldName = usableName(fieldName); + result.__defineGetter__( + jsfieldName, + function (name, fieldName) { + return java.getStaticFieldValue(name, fieldName); + }.bind(this, name, fieldName) + ); + result.__defineSetter__( + jsfieldName, + function (name, fieldName, val) { + java.setStaticFieldValue(name, fieldName, val); + }.bind(this, name, fieldName) + ); + } + } + + let promiseSuffix; + if (java.asyncOptions) { + promiseSuffix = java.asyncOptions.promiseSuffix; + } + + // copy static methods + const methods = SyncCall(clazz, "getDeclaredMethods")(); + for (let i = 0; i < methods.length; i++) { + const modifiers = SyncCall(methods[i], "getModifiers")(); + if ((modifiers & MODIFIER_PUBLIC) === MODIFIER_PUBLIC && (modifiers & MODIFIER_STATIC) === MODIFIER_STATIC) { + const methodName = SyncCall(methods[i], "getName")(); + + if (typeof syncSuffix === "string") { + const syncName = usableName(methodName + syncSuffix); + result[syncName] = callStaticMethodSync.bind(java, name, methodName); + } + + if (typeof asyncSuffix === "string") { + const asyncName = usableName(methodName + asyncSuffix); + result[asyncName] = callStaticMethod.bind(java, name, methodName); + } + + if (typeof promiseSuffix === "string") { + const promiseName = usableName(methodName + promiseSuffix); + result[promiseName] = util.promisify(callStaticMethod.bind(java, name, methodName)); + } + } + } + + // copy static classes/enums + const classes = SyncCall(clazz, "getDeclaredClasses")(); + for (let i = 0; i < classes.length; i++) { + const modifiers = SyncCall(classes[i], "getModifiers")(); + if ((modifiers & MODIFIER_PUBLIC) === MODIFIER_PUBLIC && (modifiers & MODIFIER_STATIC) === MODIFIER_STATIC) { + const className = SyncCall(classes[i], "getName")(); + const simpleName = SyncCall(classes[i], "getSimpleName")(); + Object.defineProperty(result, simpleName, { + get: function (result, simpleName, className) { + const c = java.import(className); + + // memoize the import + const d = Object.getOwnPropertyDescriptor(result, simpleName); + d.get = function (c) { + return c; + }.bind(null, c); + Object.defineProperty(result, simpleName, d); + + return c; + }.bind(this, result, simpleName, className), + enumerable: true, + configurable: true, + }); + } + } + + return result; +}; diff --git a/src/nodeJavaBridge.cpp b/src/nodeJavaBridge.cpp deleted file mode 100644 index 51124401..00000000 --- a/src/nodeJavaBridge.cpp +++ /dev/null @@ -1,20 +0,0 @@ - -#include "java.h" -#include "javaObject.h" - -extern "C" { - static void init(v8::Local target, v8::Local, void*) { - Java::Init(target); - JavaObject::Init(target); - } - - NODE_MODULE(nodejavabridge_bindings, init); -} - -#ifdef WIN32 - -BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { - return TRUE; -} - -#endif diff --git a/src/utils.h b/src/utils.h deleted file mode 100644 index 6b96b60c..00000000 --- a/src/utils.h +++ /dev/null @@ -1,166 +0,0 @@ - -#ifndef _utils_h_ -#define _utils_h_ - -#define BUILDING_NODE_EXTENSION 1 -#include -#include -#include -#include -#include -#include -#include - -class Java; - -#define V8_HIDDEN_MARKER_JAVA_LONG "__isJavaLong" -#define V8_HIDDEN_MARKER_JAVA_OBJECT "__isJavaObject" - -typedef enum _jvalueType { - TYPE_VOID = 1, - TYPE_INT = 2, - TYPE_LONG = 3, - TYPE_OBJECT = 4, - TYPE_STRING = 5, - TYPE_BOOLEAN = 6, - TYPE_SHORT = 7, - TYPE_BYTE = 8, - TYPE_DOUBLE = 9, - TYPE_FLOAT = 10, - TYPE_ARRAY = 11, - TYPE_CHAR = 12 -} jvalueType; - -struct DynamicProxyData { - unsigned int markerStart; - Java* java; - std::string interfaceName; - Nan::Persistent functions; - Nan::Persistent jsObject; - unsigned int markerEnd; -}; - -struct DynamicProxyJsCallData { - DynamicProxyData *dynamicProxyData; - std::string methodName; - jobjectArray args; - jobject result; - std::string throwableClass; - std::string throwableMessage; - int done; -}; - -#define DYNAMIC_PROXY_DATA_MARKER_START 0x12345678 -#define DYNAMIC_PROXY_DATA_MARKER_END 0x87654321 - -int dynamicProxyDataVerify(DynamicProxyData* data); - -void javaReflectionGetMethods(JNIEnv *env, jclass clazz, std::list* methods, bool includeStatic); -void javaReflectionGetConstructors(JNIEnv *env, jclass clazz, std::list* methods); -void javaReflectionGetFields(JNIEnv *env, jclass clazz, std::list* fields); -std::string javaToString(JNIEnv *env, jstring str); -std::string javaObjectToString(JNIEnv *env, jobject obj); -std::string javaArrayToString(JNIEnv *env, jobjectArray arr); -std::string javaMethodCallToString(JNIEnv *env, jobject obj, jmethodID methodId, jarray args); -JNIEnv* javaGetEnv(JavaVM* jvm, jobject classLoader); -jobject getSystemClassLoader(JNIEnv *env); -jvalueType javaGetArrayComponentType(JNIEnv *env, jobjectArray array); -jvalueType javaGetType(JNIEnv *env, jclass type); -jobjectArray v8ToJava(JNIEnv* env, Nan::NAN_METHOD_ARGS_TYPE args, int start, int end); -jobject v8ToJava(JNIEnv* env, v8::Local arg); -v8::Local javaExceptionToV8(Java* java, JNIEnv* env, const std::string& alternateMessage); -v8::Local javaExceptionToV8(Java* java, JNIEnv* env, jthrowable ex, const std::string& alternateMessage); -std::string javaExceptionToString(JNIEnv* env, jthrowable ex); -void checkJavaException(JNIEnv* env); -v8::Local javaArrayToV8(Java* java, JNIEnv* env, jobjectArray objArray); -v8::Local javaToV8(Java* java, JNIEnv* env, jobject obj); -v8::Local javaToV8(Java* java, JNIEnv* env, jobject obj, DynamicProxyData* dynamicProxyData); -jobjectArray javaObjectArrayToClasses(JNIEnv *env, jobjectArray objs); -jobject longToJavaLongObj(JNIEnv *env, jlong l); -jarray javaGetArgsForMethod(JNIEnv *env, jobject method, jarray args); -jarray javaGetArgsForConstructor(JNIEnv *env, jobject method, jarray args); - -jclass javaFindClass(JNIEnv* env, const std::string& className); -jobject javaFindField(JNIEnv* env, jclass clazz, const std::string& fieldName); -jobject javaFindMethod(JNIEnv *env, jclass clazz, const std::string& methodName, jobjectArray methodArgs); -jobject javaFindConstructor(JNIEnv *env, jclass clazz, jobjectArray methodArgs); -void javaCastArguments(JNIEnv *env, jobjectArray methodArgs, jobject method); - -// TODO remove these functions after node nan gets updated -v8::Local GetHiddenValue(v8::Local object, v8::Local key); -void SetHiddenValue(v8::Local object, v8::Local key, v8::Local value); -void SetHiddenValue(v8::NumberObject*, v8::Local key, v8::Local value); - -#define assertNoException(env) \ - if (env->ExceptionCheck()) { \ - env->ExceptionDescribe(); \ - assert(false); \ - } - -std::string methodNotFoundToString(JNIEnv *env, jclass clazz, const std::string& methodNameSig, bool constructor, Nan::NAN_METHOD_ARGS_TYPE args, int argStart, int argEnd); - -void unref(DynamicProxyData* dynamicProxyData); - -#define UNUSED_VARIABLE(var) var = var; - -#define ARGS_FRONT_OBJECT(ARGNAME) \ - if(info.Length() < argsStart+1 || !info[argsStart]->IsObject()) { \ - std::ostringstream errStr; \ - errStr << "Argument " << (argsStart+1) << " must be an object"; \ - Nan::ThrowError(Nan::TypeError(errStr.str().c_str())); \ - return; \ - } \ - v8::Local ARGNAME = v8::Local::Cast(info[argsStart]); \ - argsStart++; - -#define ARGS_FRONT_STRING(ARGNAME) \ - if(info.Length() < argsStart+1 || !info[argsStart]->IsString()) { \ - std::ostringstream errStr; \ - errStr << "Argument " << (argsStart+1) << " must be a string"; \ - Nan::ThrowError(Nan::TypeError(errStr.str().c_str())); \ - return; \ - } \ - v8::Local _##ARGNAME##_obj = v8::Local::Cast(info[argsStart]); \ - Nan::Utf8String _##ARGNAME##_val(_##ARGNAME##_obj); \ - std::string ARGNAME = *_##ARGNAME##_val; \ - argsStart++; - -#define ARGS_FRONT_CLASSNAME() ARGS_FRONT_STRING(className) - -#define ARGS_BACK_CALLBACK() \ - bool callbackProvided; \ - v8::Local callback; \ - if(info[info.Length()-1]->IsFunction()) { \ - callback = info[argsEnd-1]; \ - argsEnd--; \ - callbackProvided = true; \ - } else { \ - callback = Nan::Null(); \ - callbackProvided = false; \ - } - -#define EXCEPTION_CALL_CALLBACK(JAVA, STRBUILDER) \ - std::ostringstream errStr; \ - errStr << STRBUILDER; \ - v8::Local error = javaExceptionToV8(JAVA, env, errStr.str()); \ - v8::Local argv[2]; \ - argv[0] = error; \ - argv[1] = Nan::Undefined(); \ - Nan::Call(callback.As(), Nan::GetCurrentContext()->Global(), 2, argv); - -#define END_CALLBACK_FUNCTION(MSG) \ - if(callbackProvided) { \ - info.GetReturnValue().SetUndefined(); \ - return; \ - } else { \ - std::ostringstream str; \ - str << MSG; \ - info.GetReturnValue().Set(Nan::New(str.str().c_str()).ToLocalChecked()); \ - return; \ - } - -#ifndef UNUSED_VARIABLE - #define UNUSED_VARIABLE(a) a = a; -#endif - -#endif diff --git a/test/ListenerInterface.class b/test/ListenerInterface.class index c93ba7b9..88929b2c 100644 Binary files a/test/ListenerInterface.class and b/test/ListenerInterface.class differ diff --git a/test/ListenerTester.class b/test/ListenerTester.class index f47674d6..0fe29fa5 100644 Binary files a/test/ListenerTester.class and b/test/ListenerTester.class differ diff --git a/test/RunInterface$1.class b/test/RunInterface$1.class index 968bfc78..12eae837 100644 Binary files a/test/RunInterface$1.class and b/test/RunInterface$1.class differ diff --git a/test/RunInterface$Interface0Arg.class b/test/RunInterface$Interface0Arg.class index 1f5d02e1..907fdae8 100644 Binary files a/test/RunInterface$Interface0Arg.class and b/test/RunInterface$Interface0Arg.class differ diff --git a/test/RunInterface$Interface1Arg.class b/test/RunInterface$Interface1Arg.class index 5be2e13d..2008751c 100644 Binary files a/test/RunInterface$Interface1Arg.class and b/test/RunInterface$Interface1Arg.class differ diff --git a/test/RunInterface$InterfaceWithReturn.class b/test/RunInterface$InterfaceWithReturn.class index ae8a20a8..6257cc81 100644 Binary files a/test/RunInterface$InterfaceWithReturn.class and b/test/RunInterface$InterfaceWithReturn.class differ diff --git a/test/RunInterface.class b/test/RunInterface.class index c0d30e95..1404e1a2 100644 Binary files a/test/RunInterface.class and b/test/RunInterface.class differ diff --git a/test/Test$Enum.class b/test/Test$Enum.class index 4e9a1d61..5f851f69 100644 Binary files a/test/Test$Enum.class and b/test/Test$Enum.class differ diff --git a/test/Test$StaticEnum.class b/test/Test$StaticEnum.class index d63e7f54..a474b9f7 100644 Binary files a/test/Test$StaticEnum.class and b/test/Test$StaticEnum.class differ diff --git a/test/Test$SubClass.class b/test/Test$SubClass.class index e2f79c68..dba56514 100644 Binary files a/test/Test$SubClass.class and b/test/Test$SubClass.class differ diff --git a/test/Test$SuperClass.class b/test/Test$SuperClass.class index 35b83864..f3004faf 100644 Binary files a/test/Test$SuperClass.class and b/test/Test$SuperClass.class differ diff --git a/test/Test.class b/test/Test.class index 1559c37a..87fd03f1 100644 Binary files a/test/Test.class and b/test/Test.class differ diff --git a/test/TestExceptions.class b/test/TestExceptions.class index 3db31837..4d30c505 100644 Binary files a/test/TestExceptions.class and b/test/TestExceptions.class differ diff --git a/test/TestLambda$IntegerMath.class b/test/TestLambda$IntegerMath.class new file mode 100644 index 00000000..44893917 Binary files /dev/null and b/test/TestLambda$IntegerMath.class differ diff --git a/test/TestLambda.class b/test/TestLambda.class new file mode 100644 index 00000000..60c082be Binary files /dev/null and b/test/TestLambda.class differ diff --git a/test8/TestLambda.java b/test/TestLambda.java similarity index 100% rename from test8/TestLambda.java rename to test/TestLambda.java diff --git a/test/TestLambda.test.ts b/test/TestLambda.test.ts new file mode 100644 index 00000000..0b7a8ab8 --- /dev/null +++ b/test/TestLambda.test.ts @@ -0,0 +1,31 @@ +import { beforeAll, describe, expect, test } from "vitest"; +import { expectJavaError, getJava } from "../testHelpers"; +import { Java } from "../java"; + +describe("Java8", () => { + let java!: Java; + + beforeAll(async () => { + java = await getJava(); + }); + + test("call methods of a class that uses lambda expressions", () => { + try { + const TestLambda = java.import("TestLambda"); + const lambda = new TestLambda(); + const sum = lambda.testLambdaAdditionSync(23, 42); + expect(sum).toBe(65); + const diff = lambda.testLambdaSubtractionSync(23, 42); + expect(diff).toBe(-19); + } catch (err) { + expectJavaError(err); + const unsupportedVersion = java.instanceOf(err.cause, "java.lang.UnsupportedClassVersionError"); + if (unsupportedVersion) { + console.log("JRE 1.8 not available"); + } else { + console.error("Java8 test failed with unknown error:", err); + throw err; + } + } + }); +}); diff --git a/test/awt-test.js b/test/awt-test.js deleted file mode 100644 index e0c4e3bb..00000000 --- a/test/awt-test.js +++ /dev/null @@ -1,18 +0,0 @@ - -var java = require("../testHelpers").java; - -var nodeunit = require("nodeunit"); -var util = require("util"); -var path = require('path'); - -exports['AWT'] = nodeunit.testCase({ - "calling AWT method (see issue 1)": function(test) { - var headlessVal = java.callStaticMethodSync("java.lang.System", "getProperty", "java.awt.headless"); - console.log("java.awt.headless =", headlessVal); - test.equal(headlessVal, 'true'); - var filename = path.join(path.dirname(__filename), "nodejs.png"); - var file = java.newInstanceSync("java.io.File", filename); - var image = java.callStaticMethodSync("javax.imageio.ImageIO", "read", file); - test.done(); - } -}); diff --git a/test/awt.test.ts b/test/awt.test.ts new file mode 100644 index 00000000..9c8a0520 --- /dev/null +++ b/test/awt.test.ts @@ -0,0 +1,22 @@ +import path from "node:path"; +import { beforeAll, describe, expect, test } from "vitest"; +import { Java } from "../java"; +import { getJava } from "../testHelpers"; + +describe("AWT", () => { + let java!: Java; + + beforeAll(async () => { + java = await getJava(); + }); + + test("calling AWT method (see issue 1)", () => { + const headlessVal = java.callStaticMethodSync("java.lang.System", "getProperty", "java.awt.headless"); + console.log("java.awt.headless =", headlessVal); + expect(headlessVal).toBe("true"); + const filename = path.join(path.dirname(__filename), "nodejs.png"); + const file = java.newInstanceSync("java.io.File", filename); + const image = java.callStaticMethodSync("javax.imageio.ImageIO", "read", file); + expect(image).toBeTruthy(); + }); +}); diff --git a/test/commons-lang3-3.1.jar b/test/commons-lang3-3.1.jar deleted file mode 100644 index a85e539b..00000000 Binary files a/test/commons-lang3-3.1.jar and /dev/null differ diff --git a/test/commons-lang3-3.18.0.jar b/test/commons-lang3-3.18.0.jar new file mode 100644 index 00000000..9359e524 Binary files /dev/null and b/test/commons-lang3-3.18.0.jar differ diff --git a/test/dynamicProxy-test.js b/test/dynamicProxy-test.js deleted file mode 100644 index aef5fab7..00000000 --- a/test/dynamicProxy-test.js +++ /dev/null @@ -1,298 +0,0 @@ -'use strict'; - -var java = require("../testHelpers").java; -var nodeunit = require("nodeunit"); -var util = require("util"); - -exports['Dynamic Proxy'] = nodeunit.testCase({ - "0 Arguments": function (test) { - var callCount = 0; - - var myProxy = java.newProxy('RunInterface$Interface0Arg', { - run: function () { - callCount++; - } - }); - - var runInterface = java.newInstanceSync("RunInterface"); - runInterface.run0ArgsSync(myProxy); - - test.equals(callCount, 2); - - test.done(); - }, - - "1 Arguments": function (test) { - var runData = ''; - - var myProxy = java.newProxy('RunInterface$Interface1Arg', { - run: function (str) { - runData += str; - } - }); - - var runInterface = java.newInstanceSync("RunInterface"); - runInterface.run1ArgsSync(myProxy); - - test.equals(runData, 'test1test1'); - - test.done(); - }, - - "1 Arguments with return data": function (test) { - var myProxy = java.newProxy('RunInterface$InterfaceWithReturn', { - run: function (i) { - return i + 1; - } - }); - - var runInterface = java.newInstanceSync("RunInterface"); - var result = runInterface.runWithReturnSync(myProxy); - - test.equals(result, 43); - - test.done(); - }, - - "Listener test": function (test) { - var runData = ''; - - var myProxy = java.newProxy('ListenerInterface', { - onEvent: function (list, runtime) { - runData = 'onEvent'; - } - }); - - var listenerTester = java.newInstanceSync("ListenerTester"); - listenerTester.setListenerSync(myProxy); - listenerTester.raiseEventSync(); - - test.equals(runData, 'onEvent'); - - test.done(); - }, - - "thread": function (test) { - var callCount = 0; - - var myProxy = java.newProxy('java.lang.Runnable', { - run: function () { - callCount++; - } - }); - - var thread = java.newInstanceSync("java.lang.Thread", myProxy); - thread.startSync(); - - var timeout = 50; - - function waitForThread() { - if (callCount === 1) { - return test.done(); - } - timeout--; - if (timeout < 0) { - test.done(new Error("Timeout")); - } - setTimeout(waitForThread, 100); - } - - waitForThread(); - }, - - "thread issue #143": function (test) { - var myProxy = java.newProxy('RunInterface$InterfaceWithReturn', { - run: function (i) { - return i - 1; - } - }); - - var runInterface = java.newInstanceSync("RunInterface"); - runInterface.runInAnotherThread(myProxy, function(err, result) { - test.equals(result, 45); - - test.done(); - }); - }, - - "java equals()": function (test) { - var myProxy = java.newProxy('RunInterface$InterfaceWithReturn', { - }); - - var runInterface = java.newInstanceSync("RunInterface"); - var result = runInterface.runEqualsSync(myProxy); - - test.equals(result, false); - - test.done(); - }, - - "java equals() same instance": function (test) { - var myProxy = java.newProxy('RunInterface$InterfaceWithReturn', { - }); - - var runInterface = java.newInstanceSync("RunInterface"); - runInterface.setInstanceSync(myProxy); - var result = runInterface.runEqualsInstanceSync(myProxy); - - test.equals(result, true); - - test.done(); - }, - - "java equals() different instance": function (test) { - var myProxy = java.newProxy('RunInterface$InterfaceWithReturn', {}); - var myProxy2 = java.newProxy('RunInterface$InterfaceWithReturn', {}); - - var runInterface = java.newInstanceSync("RunInterface"); - runInterface.setInstanceSync(myProxy); - var result = runInterface.runEqualsInstanceSync(myProxy2); - - test.equals(result, false); - - test.done(); - }, - - "js equals()": function (test) { - var myProxy = java.newProxy('RunInterface$InterfaceWithReturn', { - equals: function (obj) { - return true; - } - }); - - var runInterface = java.newInstanceSync("RunInterface"); - var result = runInterface.runEqualsSync(myProxy); - - test.equals(result, true); - - test.done(); - }, - - "java hashCode()": function (test) { - var myProxy = java.newProxy('RunInterface$InterfaceWithReturn', { - }); - - var runInterface = java.newInstanceSync("RunInterface"); - var result = runInterface.runHashCodeSync(myProxy); - var result2 = runInterface.runHashCodeSync(myProxy); - var systemHashCode = java.callStaticMethodSync("java.lang.System", "identityHashCode", myProxy); - - test.equals(result, result2); - test.equals(result, systemHashCode); - - test.done(); - }, - - "js hashCode()": function (test) { - var myProxy = java.newProxy('RunInterface$InterfaceWithReturn', { - hashCode: function() { - return 1234; - } - }); - - var runInterface = java.newInstanceSync("RunInterface"); - var result = runInterface.runHashCodeSync(myProxy); - - test.equals(result, 1234); - - test.done(); - }, - - "java toString()": function (test) { - var myProxy = java.newProxy('RunInterface$InterfaceWithReturn', {}); - - var runInterface = java.newInstanceSync("RunInterface"); - var result = runInterface.runToStringSync(myProxy); - - test.equals(result, "[object Object]"); - - test.done(); - }, - - "js toString()": function (test) { - var myProxy = java.newProxy('RunInterface$InterfaceWithReturn', { - toString: function() { - return "myRunInterface"; - } - }); - - var runInterface = java.newInstanceSync("RunInterface"); - var result = runInterface.runToStringSync(myProxy); - - test.equals(result, "myRunInterface"); - - test.done(); - }, - - "js string error": function (test) { - var myProxy = java.newProxy('RunInterface$InterfaceWithReturn', { - run: function (i) { - throw 'myError'; - } - }); - - var runInterface = java.newInstanceSync("RunInterface"); - try { - runInterface.runWithReturnSync(myProxy); - test.fail("Exception was not thrown"); - } catch (e) { - test.equals(e.cause.getClassSync().getNameSync(), "java.lang.RuntimeException"); - test.ok(/Caused by: node\.NodeJsException:.*myError/.test(e.message)); - } - - test.done(); - }, - - "js Error": function (test) { - var myProxy = java.newProxy('RunInterface$InterfaceWithReturn', { - run: function (i) { - throw new Error('newError'); - } - }); - - var runInterface = java.newInstanceSync("RunInterface"); - try { - runInterface.runWithReturnSync(myProxy); - test.fail("Exception was not thrown"); - } catch (e) { - test.equals(e.cause.getClassSync().getNameSync(), "java.lang.RuntimeException"); - test.ok(/Caused by: node\.NodeJsException:.*newError/.test(e.message)); - } - - test.done(); - }, - - "invocationHandler": function (test) { - var myProxy = java.newProxy('RunInterface$InterfaceWithReturn', { - run: function (i) { - return i + 2; - } - }); - - var result = myProxy.invocationHandler.run(42); - - test.equals(result, 44); - - test.done(); - }, - - "unref": function (test) { - var myProxy = java.newProxy('RunInterface$InterfaceWithReturn', { - run: function (i) { - return i + 1; - } - }); - - myProxy.unref(); - - try { - myProxy.invocationHandler.run(42); - } catch (e) { - test.equals(e.message, "dynamicProxyData has been destroyed or corrupted"); - } - - // call again - myProxy.unref(); - test.done(); - } -}); diff --git a/test/dynamicProxy.test.ts b/test/dynamicProxy.test.ts new file mode 100644 index 00000000..e82ba58b --- /dev/null +++ b/test/dynamicProxy.test.ts @@ -0,0 +1,276 @@ +import { beforeAll, describe, expect, test } from "vitest"; +import { Java, JavaObject } from "../java"; +import { expectJavaError, getJava } from "../testHelpers"; + +describe("Dynamic Proxy", () => { + let java!: Java; + + beforeAll(async () => { + java = await getJava(); + }); + + test("0 Arguments", () => { + let callCount = 0; + + const myProxy = java.newProxy("RunInterface$Interface0Arg", { + run: function () { + callCount++; + }, + }); + + const runInterface = java.newInstanceSync("RunInterface"); + runInterface.run0ArgsSync(myProxy); + + expect(callCount).toBe(2); + }); + + test("1 Arguments", () => { + let runData = ""; + + const myProxy = java.newProxy("RunInterface$Interface1Arg", { + run: (str: string) => { + runData += str; + }, + }); + + const runInterface = java.newInstanceSync("RunInterface"); + runInterface.run1ArgsSync(myProxy); + + expect(runData).toBe("test1test1"); + }); + + test("1 Arguments with return data", () => { + const myProxy = java.newProxy("RunInterface$InterfaceWithReturn", { + run: (i: number) => { + return i + 1; + }, + }); + + const runInterface = java.newInstanceSync("RunInterface"); + const result = runInterface.runWithReturnSync(myProxy); + + expect(result).toBe(43); + }); + + test("Listener test", () => { + let runData = ""; + + const myProxy = java.newProxy("ListenerInterface", { + onEvent: (_list: JavaObject, _runtime: JavaObject) => { + runData = "onEvent"; + }, + }); + + const listenerTester = java.newInstanceSync("ListenerTester"); + listenerTester.setListenerSync(myProxy); + listenerTester.raiseEventSync(); + + expect(runData).toBe("onEvent"); + }); + + test("thread", async () => { + await new Promise((resolve, reject) => { + let callCount = 0; + + const myProxy = java.newProxy("java.lang.Runnable", { + run: function () { + callCount++; + }, + }); + + const thread = java.newInstanceSync("java.lang.Thread", myProxy); + thread.startSync(); + + let timeout = 50; + + function waitForThread(): void { + if (callCount === 1) { + return resolve(); + } + timeout--; + if (timeout < 0) { + return reject(new Error("Timeout")); + } + setTimeout(waitForThread, 100); + } + + waitForThread(); + }); + }); + + test("thread issue #143", async () => { + await new Promise((resolve) => { + const myProxy = java.newProxy("RunInterface$InterfaceWithReturn", { + run: (i: number) => { + return i - 1; + }, + }); + + const runInterface = java.newInstanceSync("RunInterface"); + runInterface.runInAnotherThread(myProxy, (err: Error | undefined, result: number) => { + expect(err).toBeUndefined(); + expect(result).toBe(45); + resolve(); + }); + }); + }); + + test("java equals()", () => { + const myProxy = java.newProxy("RunInterface$InterfaceWithReturn", {}); + + const runInterface = java.newInstanceSync("RunInterface"); + const result = runInterface.runEqualsSync(myProxy); + + expect(result).toBe(false); + }); + + test("java equals() same instance", () => { + const myProxy = java.newProxy("RunInterface$InterfaceWithReturn", {}); + + const runInterface = java.newInstanceSync("RunInterface"); + runInterface.setInstanceSync(myProxy); + const result = runInterface.runEqualsInstanceSync(myProxy); + + expect(result).toBe(true); + }); + + test("java equals() different instance", () => { + const myProxy = java.newProxy("RunInterface$InterfaceWithReturn", {}); + const myProxy2 = java.newProxy("RunInterface$InterfaceWithReturn", {}); + + const runInterface = java.newInstanceSync("RunInterface"); + runInterface.setInstanceSync(myProxy); + const result = runInterface.runEqualsInstanceSync(myProxy2); + + expect(result).toBe(false); + }); + + test("js equals()", () => { + const myProxy = java.newProxy("RunInterface$InterfaceWithReturn", { + equals: (_obj: JavaObject) => { + return true; + }, + }); + + const runInterface = java.newInstanceSync("RunInterface"); + const result = runInterface.runEqualsSync(myProxy); + + expect(result).toBe(true); + }); + + test("java hashCode()", () => { + const myProxy = java.newProxy("RunInterface$InterfaceWithReturn", {}); + + const runInterface = java.newInstanceSync("RunInterface"); + const result = runInterface.runHashCodeSync(myProxy); + const result2 = runInterface.runHashCodeSync(myProxy); + const systemHashCode = java.callStaticMethodSync("java.lang.System", "identityHashCode", myProxy); + + expect(result).toBe(result2); + expect(result).toBe(systemHashCode); + }); + + test("js hashCode()", () => { + const myProxy = java.newProxy("RunInterface$InterfaceWithReturn", { + hashCode: function () { + return 1234; + }, + }); + + const runInterface = java.newInstanceSync("RunInterface"); + const result = runInterface.runHashCodeSync(myProxy); + + expect(result).toBe(1234); + }); + + test("java toString()", () => { + const myProxy = java.newProxy("RunInterface$InterfaceWithReturn", {}); + + const runInterface = java.newInstanceSync("RunInterface"); + const result = runInterface.runToStringSync(myProxy); + + expect(result).toBe("[object Object]"); + }); + + test("js toString()", () => { + const myProxy = java.newProxy("RunInterface$InterfaceWithReturn", { + toString: () => { + return "myRunInterface"; + }, + }); + + const runInterface = java.newInstanceSync("RunInterface"); + const result = runInterface.runToStringSync(myProxy); + + expect(result).toBe("myRunInterface"); + }); + + test("js string error", () => { + const myProxy = java.newProxy("RunInterface$InterfaceWithReturn", { + run: (_i: JavaObject) => { + // eslint-disable-next-line @typescript-eslint/only-throw-error + throw "myError"; + }, + }); + + const runInterface = java.newInstanceSync("RunInterface"); + try { + runInterface.runWithReturnSync(myProxy); + throw new Error("Exception was not thrown"); + } catch (e) { + expectJavaError(e); + expect(e.cause.getClassSync().getNameSync()).toBe("java.lang.RuntimeException"); + expect(e.message).toMatch(/Caused by: node\.NodeJsException:.*myError/); + } + }); + + test("js Error", () => { + const myProxy = java.newProxy("RunInterface$InterfaceWithReturn", { + run: (_i: JavaObject) => { + throw new Error("newError"); + }, + }); + + const runInterface = java.newInstanceSync("RunInterface"); + try { + runInterface.runWithReturnSync(myProxy); + throw new Error("Exception was not thrown"); + } catch (e) { + expectJavaError(e); + expect(e.cause.getClassSync().getNameSync()).toBe("java.lang.RuntimeException"); + expect(e.message).toMatch(/Caused by: node\.NodeJsException:.*newError/); + } + }); + + test("invocationHandler", () => { + const myProxy = java.newProxy("RunInterface$InterfaceWithReturn", { + run: (i: number) => { + return i + 2; + }, + }); + + const result = myProxy.invocationHandler.run(42); + + expect(result).toBe(44); + }); + + test("unref", () => { + const myProxy = java.newProxy("RunInterface$InterfaceWithReturn", { + run: (i: number) => { + return i + 1; + }, + }); + + myProxy.unref(); + + try { + myProxy.invocationHandler.run(42); + } catch (e) { + expectJavaError(e); + expect(e.message).toBe("dynamicProxyData has been destroyed or corrupted"); + } + + // call again + myProxy.unref(); + }); +}); diff --git a/test/importClass-test.js b/test/importClass-test.js deleted file mode 100644 index 1fc66d01..00000000 --- a/test/importClass-test.js +++ /dev/null @@ -1,67 +0,0 @@ -'use strict'; - -var java = require("../testHelpers").java; -var nodeunit = require("nodeunit"); -var util = require("util"); - -exports['Import Class'] = nodeunit.testCase({ - tearDown: function (callback) { - java.setStaticFieldValue("Test", "staticFieldInt", 42); - callback(); - }, - - "import": function (test) { - var Test = java.import('Test'); - test.equals(42, Test.staticFieldInt); - Test.staticFieldInt = 200; - test.equals(200, Test.staticFieldInt); - - test.equals(100, Test.staticMethodSync(99)); - Test.staticMethod(99, function (err, result) { - test.ok(!err); - test.equals(100, result); - - var testObj = new Test(5); - test.equals(5, testObj.getIntSync()); - test.done(); - }); - }, - - "import TestEnum with unsable name": function (test) { - test.expect(5); - var TestEnum = java.import('Test$Enum'); - - // 'foo' and 'bar' are valid enum names - test.strictEqual(TestEnum.foo.toStringSync(), "foo"); - test.strictEqual(TestEnum.bar.toStringSync(), "bar"); - - ['name', 'arguments', 'caller'].forEach(function(prop) { - test.throws( - function() { - // The enum also defines 'name', 'caller', and 'attributes', but Javascript prevents us from using them, - // since these are unwritable properties of Function. - var x = TestEnum[prop].toStringSync(); - }, - TypeError - ); - }); - test.done(); - }, - - "import TestEnum and use alternate name": function (test) { - test.expect(5); - var TestEnum = java.import('Test$Enum'); - - // 'foo' and 'bar' are valid enum names - test.strictEqual(TestEnum.foo.toStringSync(), "foo"); - test.strictEqual(TestEnum.bar.toStringSync(), "bar"); - - // 'name', 'caller', and 'arguments' are not, so we must use e.g. 'name_' to reference the enum. - // But note that the value is still e.g. "name". - test.strictEqual(TestEnum.name_.toStringSync(), "name"); - test.strictEqual(TestEnum.arguments_.toStringSync(), "arguments"); - test.strictEqual(TestEnum.caller_.toStringSync(), "caller"); - test.done(); - } - -}); diff --git a/test/importClass.test.ts b/test/importClass.test.ts new file mode 100644 index 00000000..5086eb85 --- /dev/null +++ b/test/importClass.test.ts @@ -0,0 +1,64 @@ +import { afterEach, beforeAll, describe, expect, test } from "vitest"; +import { getJava } from "../testHelpers"; +import { Java } from "../java"; + +describe("Import Class", () => { + let java!: Java; + + beforeAll(async () => { + java = await getJava(); + }); + + afterEach(() => { + java.setStaticFieldValue("Test", "staticFieldInt", 42); + }); + + test("import", async () => { + const Test = java.import("Test"); + expect(Test.staticFieldInt).toBe(42); + Test.staticFieldInt = 200; + expect(Test.staticFieldInt).toBe(200); + + expect(Test.staticMethodSync(99)).toBe(100); + await new Promise((resolve) => { + Test.staticMethod(99, (err: Error | undefined, result: number | undefined) => { + expect(err).toBeFalsy(); + expect(result).toBe(100); + + const testObj = new Test(5); + expect(testObj.getIntSync()).toBe(5); + resolve(); + }); + }); + }); + + test("import TestEnum with unsable name", () => { + const TestEnum = java.import("Test$Enum"); + + // 'foo' and 'bar' are valid enum names + expect(TestEnum.foo.toStringSync()).toBe("foo"); + expect(TestEnum.bar.toStringSync()).toBe("bar"); + + ["name", "arguments", "caller"].forEach(function (prop) { + expect(() => { + // The enum also defines 'name', 'caller', and 'attributes', but Javascript prevents us from using them, + // since these are unwritable properties of Function. + TestEnum[prop].toStringSync(); + }).toThrow(TypeError); + }); + }); + + test("import TestEnum and use alternate name", () => { + const TestEnum = java.import("Test$Enum"); + + // 'foo' and 'bar' are valid enum names + expect(TestEnum.foo.toStringSync()).toBe("foo"); + expect(TestEnum.bar.toStringSync()).toBe("bar"); + + // 'name', 'caller', and 'arguments' are not, so we must use e.g. 'name_' to reference the enum. + // But note that the value is still e.g. "name". + expect(TestEnum.name_.toStringSync()).toBe("name"); + expect(TestEnum.arguments_.toStringSync()).toBe("arguments"); + expect(TestEnum.caller_.toStringSync()).toBe("caller"); + }); +}); diff --git a/test/instanceof-test.js b/test/instanceof-test.js deleted file mode 100644 index f90720e1..00000000 --- a/test/instanceof-test.js +++ /dev/null @@ -1,32 +0,0 @@ -var java = require("../testHelpers").java; - -var nodeunit = require("nodeunit"); -var util = require("util"); - -exports['instanceOf'] = nodeunit.testCase({ - "working": function(test) { - var subclass = java.newInstanceSync("Test$SubClass"); - if (!java.instanceOf(subclass, "Test$SuperClass")) { - test.fail(subclass.getNameSync() + " should be an instance of Test$SuperClass"); - } - test.done(); - }, - - "non-java object": function(test) { - if (java.instanceOf({}, "Test$SuperClass")) { - test.fail("javascript objects are not instances of anything"); - } - test.done(); - }, - - "bad type": function(test) { - var subclass = java.newInstanceSync("Test$SubClass"); - try { - java.instanceOf(subclass, "BadClassName"); - test.fail("should have thrown an exception.") - } catch (e) { - // OK - } - test.done(); - } -}); diff --git a/test/instanceof.test.ts b/test/instanceof.test.ts new file mode 100644 index 00000000..679a3d3d --- /dev/null +++ b/test/instanceof.test.ts @@ -0,0 +1,31 @@ +import { beforeAll, describe, expect, test } from "vitest"; +import { getJava } from "../testHelpers"; +import { Java } from "../java"; + +describe("instanceOf", () => { + let java!: Java; + + beforeAll(async () => { + java = await getJava(); + }); + + test("working", () => { + const subclass = java.newInstanceSync("Test$SubClass"); + if (!java.instanceOf(subclass, "Test$SuperClass")) { + throw new Error(subclass.getNameSync() + " should be an instance of Test$SuperClass"); + } + }); + + test("non-java object", () => { + if (java.instanceOf({}, "Test$SuperClass")) { + throw new Error("javascript objects are not instances of anything"); + } + }); + + test("bad type", () => { + const subclass = java.newInstanceSync("Test$SubClass"); + expect(() => { + java.instanceOf(subclass, "BadClassName"); + }).toThrow(); + }); +}); diff --git a/test/java-ambiguousMethod-test.js b/test/java-ambiguousMethod-test.js deleted file mode 100644 index 7dd0c146..00000000 --- a/test/java-ambiguousMethod-test.js +++ /dev/null @@ -1,106 +0,0 @@ -var java = require("../testHelpers").java; - -var nodeunit = require("nodeunit"); -var util = require("util"); - -exports['Java - Call Ambiguous Method'] = nodeunit.testCase({ - "staticMethodAmbiguous (sync) - int passed to double": function(test) { - var result = java.callStaticMethodSync('Test', 'staticMethodAmbiguous(Ljava/lang/Double;)I', 1); - test.equal(result, 1); - test.done(); - }, - - "staticMethodAmbiguous (sync) - double passed to int": function(test) { - var result = java.callStaticMethodSync('Test', 'staticMethodAmbiguous(Ljava/lang/Integer;)I', 1.1); - test.equal(result, 2); - test.done(); - }, - - "staticMethodAmbiguous (sync) - method not found wrong argument type": function(test) { - try { - java.callStaticMethodSync('Test', 'staticMethodAmbiguous(Ljava/lang/String;)I', 1); - test.fail("should throw"); - } catch (e) { - console.log(e); - } - test.done(); - }, - - "staticMethodAmbiguous (sync) - method failed because argument count mismatch": function(test) { - try { - java.callStaticMethodSync('Test', 'staticMethodAmbiguous(Ljava/lang/Integer;)I', 1, 2); - test.fail("should throw argument length mismatch"); - } catch (e) { - console.log(e); - } - test.done(); - }, - - "staticMethodAmbiguous - int passed to double": function(test) { - java.callStaticMethod('Test', 'staticMethodAmbiguous(Ljava/lang/Double;)I', 1, function(err, result) { - test.ok(!err); - test.equal(result, 1); - test.done(); - }) - }, - - "staticMethodAmbiguous - double passed to int": function(test) { - java.callStaticMethod('Test', 'staticMethodAmbiguous(Ljava/lang/Integer;)I', 1.1, function(err, result) { - test.ok(!err); - test.equal(result, 2); - test.done(); - }); - }, - - "staticMethodAmbiguous - method not found": function(test) { - java.callStaticMethod('Test', 'staticMethodAmbiguous(Ljava/lang/String;)I', 1, function(err, result) { - test.ok(err); - console.log(err); - test.done(); - }); - }, - - "staticMethodAmbiguous - method argument count mismatch": function(test) { - java.callStaticMethod('Test', 'staticMethodAmbiguous(Ljava/lang/Integer;)I', 1, 2, function(err, result) { - test.ok(err); - console.log(err); - test.done(); - }); - }, - - "methodAmbiguous (sync) - int passed to double": function(test) { - var myTest = java.newInstanceSync("Test"); - var result = java.callMethodSync(myTest, 'methodAmbiguous(Ljava/lang/Double;)I', 1); - test.equal(result, 1); - test.done(); - }, - - "methodAmbiguous (sync) - double passed to int": function(test) { - var myTest = java.newInstanceSync("Test"); - var result = java.callMethodSync(myTest, 'methodAmbiguous(Ljava/lang/Integer;)I', 1.1); - test.equal(result, 2); - test.done(); - }, - - "methodAmbiguous (sync) - method not found wrong argument type": function(test) { - var myTest = java.newInstanceSync("Test"); - try { - java.callMethodSync(myTest, 'methodAmbiguous(Ljava/lang/String;)I', 1); - test.fail("should throw"); - } catch (e) { - console.log(e); - } - test.done(); - }, - - "methodAmbiguous (sync) - method failed because argument count mismatch": function(test) { - var myTest = java.newInstanceSync("Test"); - try { - java.callMethodSync(myTest, 'methodAmbiguous(Ljava/lang/Integer;)I', 1, 2); - test.fail("should throw argument length mismatch"); - } catch (e) { - console.log(e); - } - test.done(); - } -}); diff --git a/test/java-ambiguousMethod.test.ts b/test/java-ambiguousMethod.test.ts new file mode 100644 index 00000000..88237732 --- /dev/null +++ b/test/java-ambiguousMethod.test.ts @@ -0,0 +1,120 @@ +import { beforeAll, describe, expect, test } from "vitest"; +import { Java } from "../java"; +import { getJava } from "../testHelpers"; + +describe("Java - Call Ambiguous Method", () => { + let java!: Java; + + beforeAll(async () => { + java = await getJava(); + }); + + test("staticMethodAmbiguous (sync) - int passed to double", () => { + const result = java.callStaticMethodSync("Test", "staticMethodAmbiguous(Ljava/lang/Double;)I", 1); + expect(result).toBe(1); + }); + + test("staticMethodAmbiguous (sync) - double passed to int", () => { + const result = java.callStaticMethodSync("Test", "staticMethodAmbiguous(Ljava/lang/Integer;)I", 1.1); + expect(result).toBe(2); + }); + + test("staticMethodAmbiguous (sync) - method not found wrong argument type", () => { + expect(() => { + java.callStaticMethodSync("Test", "staticMethodAmbiguous(Ljava/lang/String;)I", 1); + }).toThrow(); + }); + + test("staticMethodAmbiguous (sync) - method failed because argument count mismatch", () => { + expect(() => { + java.callStaticMethodSync("Test", "staticMethodAmbiguous(Ljava/lang/Integer;)I", 1, 2); + }).toThrow(); + }); + + test("staticMethodAmbiguous - int passed to double", async () => { + await new Promise((resolve) => { + java.callStaticMethod( + "Test", + "staticMethodAmbiguous(Ljava/lang/Double;)I", + 1, + (err: Error | undefined, result: number | undefined) => { + expect(err).toBeFalsy(); + expect(result).toBe(1); + resolve(); + } + ); + }); + }); + + test("staticMethodAmbiguous - double passed to int", async () => { + await new Promise((resolve) => { + java.callStaticMethod( + "Test", + "staticMethodAmbiguous(Ljava/lang/Integer;)I", + 1.1, + (err: Error | undefined, result: number | undefined) => { + expect(err).toBeFalsy(); + expect(result).toBe(2); + resolve(); + } + ); + }); + }); + + test("staticMethodAmbiguous - method not found", async () => { + await new Promise((resolve) => { + java.callStaticMethod( + "Test", + "staticMethodAmbiguous(Ljava/lang/String;)I", + 1, + (err: Error | undefined, result: number | undefined) => { + expect(err).toBeTruthy(); + expect(result).toBeFalsy(); + resolve(); + } + ); + }); + }); + + test("staticMethodAmbiguous - method argument count mismatch", async () => { + await new Promise((resolve) => { + java.callStaticMethod( + "Test", + "staticMethodAmbiguous(Ljava/lang/Integer;)I", + 1, + 2, + (err: Error | undefined, result: number | undefined) => { + expect(err).toBeTruthy(); + expect(result).toBeFalsy(); + resolve(); + } + ); + }); + }); + + test("methodAmbiguous (sync) - int passed to double", () => { + const myTest = java.newInstanceSync("Test"); + const result = java.callMethodSync(myTest, "methodAmbiguous(Ljava/lang/Double;)I", 1); + expect(result).toBe(1); + }); + + test("methodAmbiguous (sync) - double passed to int", () => { + const myTest = java.newInstanceSync("Test"); + const result = java.callMethodSync(myTest, "methodAmbiguous(Ljava/lang/Integer;)I", 1.1); + expect(result).toBe(2); + }); + + test("methodAmbiguous (sync) - method not found wrong argument type", () => { + const myTest = java.newInstanceSync("Test"); + expect(() => { + java.callMethodSync(myTest, "methodAmbiguous(Ljava/lang/String;)I", 1); + }).toThrow(); + }); + + test("methodAmbiguous (sync) - method failed because argument count mismatch", () => { + const myTest = java.newInstanceSync("Test"); + expect(() => { + java.callMethodSync(myTest, "methodAmbiguous(Ljava/lang/Integer;)I", 1, 2); + }).toThrow(); + }); +}); diff --git a/test/java-callStaticMethod-test.js b/test/java-callStaticMethod-test.js deleted file mode 100644 index 0e9bf17e..00000000 --- a/test/java-callStaticMethod-test.js +++ /dev/null @@ -1,292 +0,0 @@ -var java = require("../testHelpers").java; - -var nodeunit = require("nodeunit"); -var util = require("util"); - -exports['Java - Call Static Method'] = nodeunit.testCase({ - "callStaticMethod": function(test) { - java.callStaticMethod("Test", "staticMethod", function(err, result) { - test.ok(result); - test.equal(result, "staticMethod called"); - test.done(); - }); - }, - - "callStaticMethod without a callback": function(test) { - var result = java.callStaticMethod("Test", "staticMethod"); - console.log("callStaticMethod without a callback result message", result); - test.done(); - }, - - "callStaticMethodSync": function(test) { - var result = java.callStaticMethodSync("Test", "staticMethod"); - test.ok(result); - test.equal(result, "staticMethod called"); - test.done(); - }, - - "callStaticMethod with args": function(test) { - java.callStaticMethod("Test", "staticMethod", 42, function(err, result) { - if (err) { - return test.done(err); - } - test.ok(result); - test.equal(result, 43); - test.done(); - }); - }, - - "callStaticMethodSync with args": function(test) { - var result = java.callStaticMethodSync("Test", "staticMethod", 42); - test.ok(result); - test.equal(result, 43); - test.done(); - }, - - "callStaticMethodSync with BigDecimal": function(test) { - var bigDecimal = java.newInstanceSync("java.math.BigDecimal", 100.1); - var result = java.callStaticMethodSync("Test", "staticBigDecimalToString", bigDecimal); - test.ok(result); - test.ok(Math.abs(parseFloat(result) - 100.1) < 0.0001); - test.done(); - }, - - "callStaticMethod bad class name": function(test) { - java.callStaticMethod("BadClassName", "staticMethod", function(err, result) { - test.ok(err); - test.ok(!result); - test.done(); - }); - }, - - - "callStaticMethodSync bad class name": function(test) { - test.throws(function() { - java.callStaticMethodSync("BadClassName", "staticMethod"); - }); - test.done(); - }, - - "callStaticMethod bad arg types": function(test) { - java.callStaticMethod("Test", "staticMethod", "z", function(err, result) { - test.ok(err); - test.ok(!result); - test.done(); - }); - }, - - "callStaticMethodSync bad arg types": function(test) { - test.throws(function() { - java.callStaticMethodSync("Test", "staticMethod", "z"); - }); - test.done(); - }, - - "callStaticMethod bad number of args": function(test) { - java.callStaticMethod("Test", "staticMethod", 42, "z", function(err, result) { - test.ok(err); - test.equals(undefined, result); - test.done(); - }); - }, - - "callStaticMethodSync bad number of args": function(test) { - test.throws(function() { - java.callStaticMethodSync("Test", "staticMethod", 42, "z"); - }); - test.done(); - }, - - "callStaticMethod bad method name": function(test) { - java.callStaticMethod("Test", "badMethodName", function(err, result) { - test.ok(err); - test.ok(!result); - test.done(); - }); - }, - - "callStaticMethodSync bad method name": function(test) { - test.throws(function() { - java.callStaticMethodSync("Test", "badMethodName"); - }); - test.done(); - }, - - "callStaticMethod exception thrown from method (sync)": function(test) { - var ex = java.newInstanceSync("java.lang.Exception", "my exception"); - var result; - try { - result = java.callStaticMethodSync("Test", "staticMethodThrows", ex); - } catch (err) { - test.ok(err); - test.equals('my exception', err.cause.getMessageSync()); - test.ok(err.toString().match(/my exception/)); - test.ok(!result); - test.done(); - } - }, - - "staticMethodThrows exception thrown from method (sync)": function(test) { - var ex = java.newInstanceSync("java.lang.Exception", "my exception"); - try { - java.callStaticMethodSync("Test", "staticMethodThrows", ex); - test.fail("should throw"); - } catch (err) { - test.ok(err.toString().match(/my exception/)); - } - test.done(); - }, - - "staticMethodThrows exception thrown from method": function(test) { - var ex = java.newInstanceSync("java.lang.Exception", "my exception"); - java.callStaticMethod("Test", "staticMethodThrows", ex, function(err, result) { - test.ok(err); - test.equals('my exception', err.cause.getMessageSync()); - test.ok(err.toString().match(/my exception/)); - test.ok(!result); - test.done(); - }); - }, - - "staticMethodThrowsNewException exception thrown from method (sync)": function(test) { - try { - java.callStaticMethodSync("Test", "staticMethodThrowsNewException"); - test.fail("should throw"); - } catch (err) { - test.ok(err.toString().match(/my exception/)); - } - test.done(); - }, - - "staticMethodThrowsNewException exception thrown from method": function(test) { - java.callStaticMethod("Test", "staticMethodThrowsNewException", function(err, result) { - test.ok(err); - test.equals('my exception', err.cause.getMessageSync()); - test.ok(err.toString().match(/my exception/)); - test.ok(!result); - test.done(); - }); - }, - - "methodThrows exception thrown from method (sync)": function(test) { - var ex = java.newInstanceSync("java.lang.Exception", "my exception"); - var myTest = java.newInstanceSync("Test"); - try { - myTest.methodThrowsSync(ex); - test.fail("should throw"); - } catch (err) { - test.ok(err.toString().match(/my exception/)); - } - test.done(); - }, - - "methodThrows exception thrown from method": function(test) { - var ex = java.newInstanceSync("java.lang.Exception", "my exception"); - var myTest = java.newInstanceSync("Test"); - return myTest.methodThrows(ex, function(err) { - test.ok(err.toString().match(/my exception/)); - test.done(); - }); - }, - - "methodThrowsNewException exception thrown from method (sync)": function(test) { - var myTest = java.newInstanceSync("Test"); - try { - myTest.methodThrowsNewExceptionSync(); - test.fail("should throw"); - } catch (err) { - test.ok(err.toString().match(/my exception/)); - } - test.done(); - }, - - "methodThrowsNewException exception thrown from method": function(test) { - var myTest = java.newInstanceSync("Test"); - return myTest.methodThrowsNewException(function(err) { - test.ok(err.toString().match(/my exception/)); - test.done(); - }); - }, - - "char array": function(test) { - var charArray = java.newArray("char", "hello world\n".split('')); - java.callStaticMethod("Test", "staticMethodCharArrayToString", charArray, function(err, result) { - if (err) { - return test.done(err); - } - test.ok(result); - test.equal(result, "hello world\n"); - test.done(); - }); - }, - - "String passed in for Object": function(test) { - java.callStaticMethod("Test", "static2Objects", "1", "2", function(err, result) { - if (err) { - return test.done(err); - } - test.equal(result, false); - test.done(); - }); - }, - - "java.lang.Long addition": function(test) { - var javaLong = java.newInstanceSync("java.lang.Long", 5); - test.equal(javaLong.toString(), '5'); - var result = javaLong + 1; - test.equal(result, 6); - test.done(); - }, - - "java.lang.Long calls (java Long)": function(test) { - var javaLong = java.newInstanceSync("java.lang.Long", 5); - java.callStaticMethod("Test", "staticMethodLongToString", javaLong, function(err, result) { - if (err) { - return test.done(err); - } - test.ok(result); - test.equal(result, "5"); - test.done(); - }); - }, - - "Call method that returns a long": function(test) { - java.callStaticMethod("Test", "staticMethodReturnLong", function(err, result) { - if (err) { - return test.done(err); - } - test.ok(result); - test.equal(result.longValue, "9223372036854775807"); - test.done(); - }); - }, - - "Call method with nested enum value": function(test) { - var Test = java.import("Test"); - Test.staticEnumToStringSync(Test.StaticEnum.Value1); - var str = Test.staticEnumToStringSync(Test.StaticEnum.Value1); // call it twice to ensure memo-ize is working - test.equal(str, "Value1"); - test.done(); - }, - - "Call static method with varargs": function(test) { - var Test = java.import("Test"); - - var str = Test.staticVarargsSync(5, java.newArray('java.lang.String', ['a', 'b', 'c'])); - test.equal(str, "5abc"); - - str = Test.staticVarargsSync(5, 'a', 'b', 'c'); - test.equal(str, "5abc"); - - test.done(); - }, - - "Call static method named name_": function(test) { - test.expect(1); - var Test = java.import("Test"); - Test.name_(function(err) { - test.ifError(err); - test.done(); - }); - } -}); diff --git a/test/java-callStaticMethod.test.ts b/test/java-callStaticMethod.test.ts new file mode 100644 index 00000000..1ad3eb4b --- /dev/null +++ b/test/java-callStaticMethod.test.ts @@ -0,0 +1,329 @@ +import { beforeAll, describe, expect, test } from "vitest"; +import { expectJavaError, getJava } from "../testHelpers"; +import { Java } from "../java"; + +describe("Java - Call Static Method", () => { + let java!: Java; + + beforeAll(async () => { + java = await getJava(); + }); + + test("callStaticMethod", async () => { + await new Promise((resolve) => { + java.callStaticMethod("Test", "staticMethod", (err: Error | undefined, result: string | undefined) => { + expect(err).toBeFalsy(); + expect(result).toBeTruthy(); + expect(result).toBe("staticMethod called"); + resolve(); + }); + }); + }); + + test("callStaticMethod without a callback", () => { + const result = java.callStaticMethod("Test", "staticMethod"); + expect(result).toBe( + `"Static method 'staticMethod' called without a callback did you mean to use the Sync version?"` + ); + }); + + test("callStaticMethodSync", () => { + const result = java.callStaticMethodSync("Test", "staticMethod"); + expect(result).toBeTruthy(); + expect(result).toBe("staticMethod called"); + }); + + test("callStaticMethod with args", async () => { + await new Promise((resolve) => { + java.callStaticMethod("Test", "staticMethod", 42, (err: Error | undefined, result: string | undefined) => { + expect(err).toBeFalsy(); + expect(result).toBeTruthy(); + expect(result).toBe(43); + resolve(); + }); + }); + }); + + test("callStaticMethodSync with args", () => { + const result = java.callStaticMethodSync("Test", "staticMethod", 42); + expect(result).toBeTruthy(); + expect(result).toBe(43); + }); + + test("callStaticMethodSync with BigDecimal", () => { + const bigDecimal = java.newInstanceSync("java.math.BigDecimal", 100.1); + const result = java.callStaticMethodSync("Test", "staticBigDecimalToString", bigDecimal); + expect(result).toBeTruthy(); + expect(Math.abs(parseFloat(result) - 100.1) < 0.0001).toBeTruthy(); + }); + + test("callStaticMethod bad class name", async () => { + await new Promise((resolve) => { + java.callStaticMethod("BadClassName", "staticMethod", (err: Error | undefined, result: string | undefined) => { + expect(err).toBeTruthy(); + expect(result).toBeFalsy(); + resolve(); + }); + }); + }); + + test("callStaticMethodSync bad class name", () => { + expect(() => { + java.callStaticMethodSync("BadClassName", "staticMethod"); + }).toThrow(); + }); + + test("callStaticMethod bad arg types", async () => { + await new Promise((resolve) => { + java.callStaticMethod("Test", "staticMethod", "z", (err: Error | undefined, result: string | undefined) => { + expect(err).toBeTruthy(); + expect(result).toBeFalsy(); + resolve(); + }); + }); + }); + + test("callStaticMethodSync bad arg types", () => { + expect(() => { + java.callStaticMethodSync("Test", "staticMethod", "z"); + }).toThrow(); + }); + + test("callStaticMethod bad number of args", async () => { + await new Promise((resolve) => { + java.callStaticMethod("Test", "staticMethod", 42, "z", (err: Error | undefined, result: string | undefined) => { + expect(err).toBeTruthy(); + expect(result).toBeFalsy(); + resolve(); + }); + }); + }); + + test("callStaticMethodSync bad number of args", () => { + expect(() => { + java.callStaticMethodSync("Test", "staticMethod", 42, "z"); + }).toThrow(); + }); + + test("callStaticMethod bad method name", async () => { + await new Promise((resolve) => { + java.callStaticMethod("Test", "badMethodName", (err: Error | undefined, result: string | undefined) => { + expect(err).toBeTruthy(); + expect(result).toBeFalsy(); + resolve(); + }); + }); + }); + + test("callStaticMethodSync bad method name", () => { + expect(() => { + java.callStaticMethodSync("Test", "badMethodName"); + }).toThrow(); + }); + + test("callStaticMethod exception thrown from method (sync)", () => { + const ex = java.newInstanceSync("java.lang.Exception", "my exception"); + let result; + try { + result = java.callStaticMethodSync("Test", "staticMethodThrows", ex); + throw new Error("expected error"); + } catch (err) { + expectJavaError(err); + expect(err.cause?.getMessageSync()).toBe("my exception"); + expect(err.toString()).toMatch(/my exception/); + expect(result).toBeFalsy(); + } + }); + + test("staticMethodThrows exception thrown from method (sync)", () => { + const ex = java.newInstanceSync("java.lang.Exception", "my exception"); + try { + java.callStaticMethodSync("Test", "staticMethodThrows", ex); + throw new Error("should throw"); + } catch (err) { + expectJavaError(err); + expect(err.toString()).toMatch(/my exception/); + } + }); + + test("staticMethodThrows exception thrown from method", async () => { + const ex = java.newInstanceSync("java.lang.Exception", "my exception"); + await new Promise((resolve) => { + java.callStaticMethod("Test", "staticMethodThrows", ex, (err: Error | undefined, result: string | undefined) => { + expectJavaError(err); + expect(err.cause.getMessageSync()).toBe("my exception"); + expect(err.toString()).toMatch(/my exception/); + expect(result).toBeFalsy(); + resolve(); + }); + }); + }); + + test("staticMethodThrowsNewException exception thrown from method (sync)", () => { + try { + java.callStaticMethodSync("Test", "staticMethodThrowsNewException"); + throw new Error("should throw"); + } catch (err) { + expectJavaError(err); + expect(err.toString()).toMatch(/my exception/); + } + }); + + test("staticMethodThrowsNewException exception thrown from method", async () => { + await new Promise((resolve) => { + java.callStaticMethod( + "Test", + "staticMethodThrowsNewException", + (err: Error | undefined, result: string | undefined) => { + expectJavaError(err); + expect(err.cause.getMessageSync()).toBe("my exception"); + expect(err.toString()).toMatch(/my exception/); + expect(result).toBeFalsy(); + resolve(); + } + ); + }); + }); + + test("methodThrows exception thrown from method (sync)", () => { + const ex = java.newInstanceSync("java.lang.Exception", "my exception"); + const myTest = java.newInstanceSync("Test"); + try { + myTest.methodThrowsSync(ex); + throw new Error("should throw"); + } catch (err) { + expectJavaError(err); + expect(err.toString()).toMatch(/my exception/); + } + }); + + test("methodThrows exception thrown from method", async () => { + const ex = java.newInstanceSync("java.lang.Exception", "my exception"); + const myTest = java.newInstanceSync("Test"); + await new Promise((resolve) => { + return myTest.methodThrows(ex, (err: Error | undefined) => { + expectJavaError(err); + expect(err.toString()).toMatch(/my exception/); + resolve(); + }); + }); + }); + + test("methodThrowsNewException exception thrown from method (sync)", () => { + const myTest = java.newInstanceSync("Test"); + try { + myTest.methodThrowsNewExceptionSync(); + throw new Error("should throw"); + } catch (err) { + expectJavaError(err); + expect(err.toString()).toMatch(/my exception/); + } + }); + + test("methodThrowsNewException exception thrown from method", async () => { + const myTest = java.newInstanceSync("Test"); + await new Promise((resolve) => { + myTest.methodThrowsNewException((err: Error | undefined) => { + expectJavaError(err); + expect(err.toString()).toMatch(/my exception/); + resolve(); + }); + }); + }); + + test("char array", async () => { + const charArray = java.newArray("char", "hello world\n".split("")); + await new Promise((resolve) => { + java.callStaticMethod( + "Test", + "staticMethodCharArrayToString", + charArray, + (err: Error | undefined, result: string | undefined) => { + expect(err).toBeFalsy(); + expect(result).toBeTruthy(); + expect(result).toBe("hello world\n"); + resolve(); + } + ); + }); + }); + + test("String passed in for Object", async () => { + await new Promise((resolve) => { + java.callStaticMethod( + "Test", + "static2Objects", + "1", + "2", + (err: Error | undefined, result: boolean | undefined) => { + expect(err).toBeFalsy(); + expect(result).toBe(false); + resolve(); + } + ); + }); + }); + + test("java.lang.Long addition", () => { + const javaLong = java.newInstanceSync("java.lang.Long", 5); + expect(javaLong.toString()).toBe("5"); + const result = javaLong + 1; + expect(result).toBe(6); + }); + + test("java.lang.Long calls (java Long)", async () => { + const javaLong = java.newInstanceSync("java.lang.Long", 5); + await new Promise((resolve) => { + java.callStaticMethod( + "Test", + "staticMethodLongToString", + javaLong, + (err: Error | undefined, result: string | undefined) => { + expect(err).toBeFalsy(); + expect(result).toBeTruthy(); + expect(result).toBe("5"); + resolve(); + } + ); + }); + }); + + test("Call method that returns a long", () => { + java.callStaticMethod( + "Test", + "staticMethodReturnLong", + (err: Error | undefined, result: { longValue: string } | undefined) => { + expect(err).toBeFalsy(); + expect(result).toBeTruthy(); + expect(result?.longValue).toBe("9223372036854775807"); + } + ); + }); + + test("Call method with nested enum value", () => { + const Test = java.import("Test"); + Test.staticEnumToStringSync(Test.StaticEnum.Value1); + const str = Test.staticEnumToStringSync(Test.StaticEnum.Value1); // call it twice to ensure memo-ize is working + expect(str).toBe("Value1"); + }); + + test("Call static method with varargs", () => { + const Test = java.import("Test"); + + let str = Test.staticVarargsSync(5, java.newArray("java.lang.String", ["a", "b", "c"])); + expect(str).toBe("5abc"); + + str = Test.staticVarargsSync(5, "a", "b", "c"); + expect(str).toBe("5abc"); + }); + + test("Call static method named name_", async () => { + await new Promise((resolve) => { + const Test = java.import("Test"); + Test.name_((err: Error | undefined) => { + expect(err).toBeFalsy(); + resolve(); + }); + }); + }); +}); diff --git a/test/java-newInstance-test.js b/test/java-newInstance-test.js deleted file mode 100644 index 393bafba..00000000 --- a/test/java-newInstance-test.js +++ /dev/null @@ -1,121 +0,0 @@ - -var java = require("../testHelpers").java; - -var nodeunit = require("nodeunit"); -var util = require("util"); - -exports['Java - New Instance'] = nodeunit.testCase({ - "newInstance": function(test) { - java.newInstance("Test", function(err, result) { - test.ok(result); - test.equal(result.getClassSync().toStringSync(), "class Test"); - test.ok(result.getInt); - test.ok(result.getIntSync); - test.ok(!result.staticMethod); - test.ok(!result.staticMethodSync); - test.equal(result.nonstaticInt, 42); - test.done(); - }); - }, - - "newInstanceSync": function(test) { - var result = java.newInstanceSync("Test"); - test.ok(result); - test.equal(result.getClassSync().toStringSync(), "class Test"); - test.done(); - }, - - "newInstance with args": function(test) { - java.newInstance("Test", 42, function(err, result) { - test.ok(result); - test.equal(result.getIntSync(), 42); - test.done(); - }); - }, - - "newInstanceSync with args": function(test) { - var result = java.newInstanceSync("Test", 42); - test.ok(result); - test.equal(result.getIntSync(), 42); - test.done(); - }, - - "newInstance bad class name": function(test) { - java.newInstance("BadClassName", function(err, result) { - test.ok(err); - test.ok(!result); - test.done(); - }); - }, - - "newInstanceSync bad class name": function(test) { - test.throws(function() { - java.newInstanceSync("BadClassName"); - }); - test.done(); - }, - - "newInstance bad arg types": function(test) { - java.newInstance("Test", 'a', function(err, result) { - test.ok(err); - test.ok(!result); - test.done(); - }); - }, - - "newInstanceSync bad arg types": function(test) { - test.throws(function() { - java.newInstanceSync("Test", 'a'); - }); - test.done(); - }, - - "newInstance bad number of args": function(test) { - java.newInstance("Test", 42, 15, function(err, result) { - test.ok(err); - test.ok(!result); - test.done(); - }); - }, - - "newInstanceSync bad number of args": function(test) { - test.throws(function() { - java.newInstanceSync("Test", 42, 15); - }); - test.done(); - }, - - "newInstance exception thrown from constructor": function(test) { - var ex = java.newInstanceSync("java.lang.Exception", "my exception"); - java.newInstance("TestExceptions", ex, function(err, result) { - test.ok(err); - test.ok(err.toString().match(/my exception/)); - test.ok(!result); - test.done(); - }); - }, - - "newInstanceSync exception thrown from constructor": function(test) { - var ex = java.newInstanceSync("java.lang.Exception", "my exception"); - try { - java.newInstanceSync("TestExceptions", ex); - test.fail("should throw"); - } catch(err) { - test.ok(err.toString().match(/my exception/)); - } - test.done(); - }, - - "newInstanceSync with varargs": function(test) { - var result = java.newInstanceSync("Test", 42, java.newArray('java.lang.String', ["a", "b"])); - test.ok(result); - - result = java.newInstanceSync("Test", 42, "a"); - test.ok(result); - - result = java.newInstanceSync("Test", 42, "a", "b", "c"); - test.ok(result); - - test.done(); - } -}); diff --git a/test/java-newInstance.test.ts b/test/java-newInstance.test.ts new file mode 100644 index 00000000..f0ccece4 --- /dev/null +++ b/test/java-newInstance.test.ts @@ -0,0 +1,126 @@ +import { beforeAll, describe, expect, test } from "vitest"; +import { Java, JavaObject } from "../java"; +import { getJava } from "../testHelpers"; + +describe("Java - New Instance", () => { + let java!: Java; + + beforeAll(async () => { + java = await getJava(); + }); + + test("newInstance", async () => { + await new Promise((resolve) => { + java.newInstance("Test", (err: Error | undefined, result: JavaObject | undefined) => { + expect(err).toBeFalsy(); + expect(result).toBeTruthy(); + expect(result.getClassSync().toStringSync()).toBe("class Test"); + expect(result.getInt).toBeTruthy(); + expect(result.getIntSync).toBeTruthy(); + expect(result.staticMethod).toBeFalsy(); + expect(result.staticMethodSync).toBeFalsy(); + expect(result.nonstaticInt).toBe(42); + resolve(); + }); + }); + }); + + test("newInstanceSync", () => { + const result = java.newInstanceSync("Test"); + expect(result).toBeTruthy(); + expect(result.getClassSync().toStringSync()).toBe("class Test"); + }); + + test("newInstance with args", async () => { + await new Promise((resolve) => { + java.newInstance("Test", 42, (err: Error | undefined, result: JavaObject | undefined) => { + expect(err).toBeFalsy(); + expect(result).toBeTruthy(); + expect(result.getIntSync()).toBe(42); + resolve(); + }); + }); + }); + + test("newInstanceSync with args", () => { + const result = java.newInstanceSync("Test", 42); + expect(result).toBeTruthy(); + expect(result.getIntSync()).toBe(42); + }); + + test("newInstance bad class name", async () => { + await new Promise((resolve) => { + java.newInstance("BadClassName", (err: Error | undefined, result: JavaObject | undefined) => { + expect(err).toBeTruthy(); + expect(result).toBeFalsy(); + resolve(); + }); + }); + }); + + test("newInstanceSync bad class name", () => { + expect(() => { + java.newInstanceSync("BadClassName"); + }).toThrow(); + }); + + test("newInstance bad arg types", async () => { + await new Promise((resolve) => { + java.newInstance("Test", "a", (err: Error | undefined, result: JavaObject | undefined) => { + expect(err).toBeTruthy(); + expect(result).toBeFalsy(); + resolve(); + }); + }); + }); + + test("newInstanceSync bad arg types", () => { + expect(() => { + java.newInstanceSync("Test", "a"); + }).toThrow(); + }); + + test("newInstance bad number of args", async () => { + await new Promise((resolve) => { + java.newInstance("Test", 42, 15, (err: Error | undefined, result: JavaObject | undefined) => { + expect(err).toBeTruthy(); + expect(result).toBeFalsy(); + resolve(); + }); + }); + }); + + test("newInstanceSync bad number of args", () => { + expect(() => { + java.newInstanceSync("Test", 42, 15); + }).toThrow(); + }); + + test("newInstance exception thrown from constructor", async () => { + const ex = java.newInstanceSync("java.lang.Exception", "my exception"); + await new Promise((resolve) => { + java.newInstance("TestExceptions", ex, (err: Error | undefined, result: JavaObject | undefined) => { + expect(err).toBeTruthy(); + expect(err?.toString()).toMatch(/my exception/); + expect(result).toBeFalsy(); + resolve(); + }); + }); + }); + + test("newInstanceSync exception thrown from constructor", () => { + const ex = java.newInstanceSync("java.lang.Exception", "my exception"); + expect(() => java.newInstanceSync("TestExceptions", ex)).toThrowError(/my exception/); + }); + + test("newInstanceSync with varargs", () => { + let result = java.newInstanceSync("Test", 42, java.newArray("java.lang.String", ["a", "b"])); + expect(result).toBeTruthy(); + + result = java.newInstanceSync("Test", 42, "a"); + expect(result).toBeTruthy(); + + result = java.newInstanceSync("Test", 42, "a", "b", "c"); + expect(result).toBeTruthy(); + }); +}); diff --git a/test/java-staticField-test.js b/test/java-staticField-test.js deleted file mode 100644 index d3f4fad0..00000000 --- a/test/java-staticField-test.js +++ /dev/null @@ -1,45 +0,0 @@ - -var java = require("../testHelpers").java; - -var nodeunit = require("nodeunit"); -var util = require("util"); - -exports['Java - Static Field'] = nodeunit.testCase({ - tearDown: function (callback) { - java.setStaticFieldValue("Test", "staticFieldInt", 42); - callback(); - }, - - "getStaticFieldValue int": function(test) { - var val = java.getStaticFieldValue("Test", "staticFieldInt"); - test.equal(val, 42); - test.done(); - }, - - "setStaticFieldValue int": function(test) { - java.setStaticFieldValue("Test", "staticFieldInt", 112); - var val = java.getStaticFieldValue("Test", "staticFieldInt"); - test.equal(val, 112); - test.done(); - }, - - "getStaticFieldValue double": function(test) { - var val = java.getStaticFieldValue("Test", "staticFieldDouble"); - test.equal(val, 42.5); - test.done(); - }, - - "setStaticFieldValue double": function(test) { - java.setStaticFieldValue("Test", "staticFieldDouble", 112.12); - var val = java.getStaticFieldValue("Test", "staticFieldDouble"); - test.equal(val, 112.12); - test.done(); - }, - - "setStaticFieldValue double (set int)": function(test) { - java.setStaticFieldValue("Test", "staticFieldDouble", 112); - var val = java.getStaticFieldValue("Test", "staticFieldDouble"); - test.equal(val, 112); - test.done(); - }, -}); diff --git a/test/java-staticField.test.ts b/test/java-staticField.test.ts new file mode 100644 index 00000000..cda57ab1 --- /dev/null +++ b/test/java-staticField.test.ts @@ -0,0 +1,43 @@ +import { afterEach, beforeAll, describe, expect, test } from "vitest"; +import { getJava } from "../testHelpers"; +import { Java } from "../java"; + +describe("Java - Static Field", () => { + let java!: Java; + + beforeAll(async () => { + java = await getJava(); + }); + + afterEach(() => { + java.setStaticFieldValue("Test", "staticFieldInt", 42); + }); + + test("getStaticFieldValue int", () => { + const val = java.getStaticFieldValue("Test", "staticFieldInt"); + expect(val).toBe(42); + }); + + test("setStaticFieldValue int", () => { + java.setStaticFieldValue("Test", "staticFieldInt", 112); + const val = java.getStaticFieldValue("Test", "staticFieldInt"); + expect(val).toBe(112); + }); + + test("getStaticFieldValue double", () => { + const val = java.getStaticFieldValue("Test", "staticFieldDouble"); + expect(val).toBe(42.5); + }); + + test("setStaticFieldValue double", () => { + java.setStaticFieldValue("Test", "staticFieldDouble", 112.12); + const val = java.getStaticFieldValue("Test", "staticFieldDouble"); + expect(val).toBe(112.12); + }); + + test("setStaticFieldValue double (set int)", () => { + java.setStaticFieldValue("Test", "staticFieldDouble", 112); + const val = java.getStaticFieldValue("Test", "staticFieldDouble"); + expect(val).toBe(112); + }); +}); diff --git a/test/javaObject-test.js b/test/javaObject-test.js deleted file mode 100644 index c99ec95f..00000000 --- a/test/javaObject-test.js +++ /dev/null @@ -1,19 +0,0 @@ - -var java = require("../testHelpers").java; - -var nodeunit = require("nodeunit"); -var util = require("util"); - -exports['Java Object'] = nodeunit.testCase({ - setUp: function(callback) { - this.testObj = java.newInstanceSync("Test"); - callback(); - }, - - "field": function(test) { - test.equal(this.testObj.nonstaticInt, 42); - this.testObj.nonstaticInt = 112; - test.equal(this.testObj.nonstaticInt, 112); - test.done(); - } -}); diff --git a/test/javaObject.test.ts b/test/javaObject.test.ts new file mode 100644 index 00000000..c3569f22 --- /dev/null +++ b/test/javaObject.test.ts @@ -0,0 +1,19 @@ +import { beforeEach, describe, expect, test } from "vitest"; +import { getJava } from "../testHelpers"; +import { Java, JavaObject } from "../java"; + +describe("Java Object", () => { + let testObj: JavaObject; + let java!: Java; + + beforeEach(async () => { + java = await getJava(); + testObj = java.newInstanceSync("Test"); + }); + + test("field", () => { + expect(testObj.nonstaticInt).toBe(42); + testObj.nonstaticInt = 112; + expect(testObj.nonstaticInt).toBe(112); + }); +}); diff --git a/test/promises-test.js b/test/promises-test.js deleted file mode 100644 index 9bf82480..00000000 --- a/test/promises-test.js +++ /dev/null @@ -1,151 +0,0 @@ -var java = require("../testHelpers").java; - -var nodeunit = require("nodeunit"); -var util = require("util"); - -function isOpenJDK() { - var javaVendor = java.callStaticMethodSync('java.lang.System', 'getProperty', 'java.vendor'); - var javaVersion = java.callStaticMethodSync('java.lang.System', 'getProperty', 'java.version'); - return /Sun Microsystems Inc/.test(javaVendor) && /^1\.6/.test(javaVersion); -} - -exports['Promises'] = nodeunit.testCase({ - "create an instance of a class and call methods (getClassPromise & getNamePromise)": function(test) { - // Adapted from a test in simple-test.js - java.newInstance("java.util.ArrayList", function(err, list) { - test.ifError(err); - test.ok(list); - list.getClassPromise() - .then(function(clazz) { - test.ok(clazz); - return clazz.getNamePromise(); - }) - .then(function(name) { - test.strictEqual(name, "java.util.ArrayList"); - }) - .catch(function(err) { - test.ifError(err); - }) - .then(function() { - test.expect(4); - test.done(); - }); - }); - }, - - "import and execute promisified static method": function (test) { - var Test = java.import('Test'); - Test.staticMethodPromise(99) - .then(function (result) { - test.strictEqual(100, result); - }) - .catch(function (err) { - test.ifError(err); - }) - .then(function() { - test.expect(1); - test.done(); - }); - }, - - "run promisified method of Java module (newInstancePromise)": function (test) { - java.newInstancePromise("java.util.ArrayList") - .then(function(list) { - test.ok(list); - return list.getClassPromise(); - }) - .then(function(clazz) { - test.ok(clazz); - return clazz.getNamePromise(); - }) - .then(function(name) { - test.strictEqual(name, "java.util.ArrayList"); - }) - .catch(function(err) { - test.ifError(err); - }) - .then(function() { - test.expect(3); - test.done(); - }); - }, - - "run chained promisified methods (of class java.util.ArrayList)": function (test) { - var openJDK = isOpenJDK(); - if (openJDK) { - // This test exposes a latent node-java bug with OpenJDK 1.6. - // See https://github.com/joeferner/node-java/issues/186 - // For now, we simply don't run this test on OpenJDK 1.6. - test.done(); - return; - } - var list; - var it; - var expectException = false; - java.newInstancePromise("java.util.ArrayList") - .then(function(_list) { - test.ok(_list); - list = _list; - return list.getClassPromise(); - }) - .then(function(clazz) { - test.ok(clazz); - return clazz.getNamePromise(); - }) - .then(function(name) { - test.strictEqual(name, "java.util.ArrayList"); - }) - .then(function() { - return list.addPromise('hello'); - }) - .then(function() { - return list.addPromise('world'); - }) - .then(function() { - return list.addPromise('boo'); - }) - .then(function() { - return list.iteratorPromise(); - }) - .then(function(_it) { - test.ok(_it); - it = _it; - return it.nextPromise(); - }) - .then(function(val) { - test.ok(val); - console.log(typeof val, val); - test.strictEqual(val, 'hello'); // java.lang.InternalError exception thrown here with OpenJDK - return it.nextPromise(); - }) - .then(function(val) { - test.ok(val); - console.log(typeof val, val); - test.strictEqual(val, 'world'); - return it.nextPromise(); - }) - .then(function(val) { - test.ok(val); - console.log(typeof val, val); - test.strictEqual(val, 'boo'); - return it.hasNextPromise(); - }) - .then(function(more) { - console.log(typeof more, more); - test.strictEqual(more, false); - expectException = true; - return it.nextPromise(); - }) - .catch(function(err) { - console.log("DEBUG: expectException is %s. err = %s", - expectException, err); - test.ok(expectException); - }) - .then(function() { - test.expect(12); - test.done(); - }); - } - -}); - diff --git a/test/promises.test.ts b/test/promises.test.ts new file mode 100644 index 00000000..2f757630 --- /dev/null +++ b/test/promises.test.ts @@ -0,0 +1,81 @@ +import { beforeAll, describe, expect, test } from "vitest"; +import { Java } from "../java"; +import { getJava } from "../testHelpers"; + +describe("Promises", () => { + let java!: Java; + + beforeAll(async () => { + java = await getJava(); + }); + + test("create an instance of a class and call methods (getClassPromise & getNamePromise)", async () => { + // Adapted from a test in simple-test.js + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const list = await (java as any).newInstancePromise("java.util.ArrayList"); + expect(list).toBeTruthy(); + + const clazz = await list.getClassPromise(); + expect(clazz).toBeTruthy(); + + const name = await clazz.getNamePromise(); + expect(name).toBe("java.util.ArrayList"); + }); + + test("import and execute promisified static method", async () => { + const Test = java.import("Test"); + const result = await Test.staticMethodPromise(99); + expect(result).toBe(100); + }); + + test("run promisified method of Java module (newInstancePromise)", async () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const list = await (java as any).newInstancePromise("java.util.ArrayList"); + expect(list).toBeTruthy(); + + const clazz = await list.getClassPromise(); + expect(clazz).toBeTruthy(); + + const name = await clazz.getNamePromise(); + expect(name).toBe("java.util.ArrayList"); + }); + + test("run chained promisified methods (of class java.util.ArrayList)", async () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const list = await (java as any).newInstancePromise("java.util.ArrayList"); + expect(list).toBeTruthy(); + + const clazz = await list.getClassPromise(); + expect(clazz).toBeTruthy(); + + const name = await clazz.getNamePromise(); + expect(name).toBe("java.util.ArrayList"); + + await list.addPromise("hello"); + await list.addPromise("world"); + await list.addPromise("boo"); + const it = await list.iteratorPromise(); + expect(it).toBeTruthy(); + + let val = await it.nextPromise(); + expect(val).toBeTruthy(); + console.log(typeof val, val); + expect(val).toBe("hello"); // java.lang.InternalError exception thrown here with OpenJDK + + val = await it.nextPromise(); + expect(val).toBeTruthy(); + console.log(typeof val, val); + expect(val).toBe("world"); + + val = await it.nextPromise(); + expect(val).toBeTruthy(); + console.log(typeof val, val); + expect(val).toBe("boo"); + + const more = await it.hasNextPromise(); + console.log(typeof more, more); + expect(more).toBeFalsy(); + + await expect(async () => await it.nextPromise()).rejects.toThrowError(); + }); +}); diff --git a/test/simple-test.js b/test/simple-test.js deleted file mode 100644 index bcf87a84..00000000 --- a/test/simple-test.js +++ /dev/null @@ -1,375 +0,0 @@ -var java = require("../testHelpers").java; - -var nodeunit = require("nodeunit"); -var util = require("util"); - -exports['Simple'] = nodeunit.testCase({ - "test classpath commons lang": function(test) { - var result = java.callStaticMethodSync("org.apache.commons.lang3.ObjectUtils", "toString", "test"); - console.log("org.apache.commons.lang3.ObjectUtils.toString:", result); - test.equal(result, "test"); - test.done(); - }, - - "test adding to classpath after other calls are made": function(test) { - java.callStaticMethodSync("java.lang.System", "currentTimeMillis"); - try { - console.log('classpath', java.classpath); - java.classpath = ["test/"]; - test.fail("Exception should be thrown"); - } catch (e) { - // ok - } - test.done(); - }, - - "test changing options after other calls are made": function(test) { - java.callStaticMethodSync("java.lang.System", "currentTimeMillis"); - try { - console.log('options', java.options); - java.options = ["newoption"]; - test.fail("Exception should be thrown"); - } catch (e) { - // ok - } - test.done(); - }, - - "test changing nativeBindingLocation after other calls are made": function(test) { - java.callStaticMethodSync("java.lang.System", "currentTimeMillis"); - try { - console.log('nativeBindingLocation', java.nativeBindingLocation); - java.nativeBindingLocation = "newNativeBindingLocation"; - test.fail("Exception should be thrown"); - } catch (e) { - // ok - } - test.done(); - }, - - "test static calls": function(test) { - var result = java.callStaticMethodSync("java.lang.System", "currentTimeMillis"); - console.log("currentTimeMillis:", result); - test.ok(result); - test.done(); - }, - - "test static calls single argument": function(test) { - var result = java.callStaticMethodSync("java.lang.System", "getProperty", "os.version"); - console.log("os.version:", result); - test.ok(result); - test.done(); - }, - - "test method does not exists (sync)": function(test) { - test.throws( - function() { - java.callStaticMethodSync("java.lang.System", "badMethod"); - } - ); - test.done(); - }, - - "test method does not exists (async)": function(test) { - java.callStaticMethod("java.lang.System", "badMethod", function(err, result) { - if (err) { - test.done(); - return; - } - test.done(new Error("should throw exception")); - }); - }, - - "create an instance of a class and call methods (getName) (async)": function(test) { - java.newInstance("java.util.ArrayList", function(err, list) { - if (err) { - console.log(err); - return; - } - test.ok(list); - if (list) { - list.getClass(function(err, result) { - if (err) { - console.log(err); - return; - } - result.getName(function(err, result) { - if (err) { - console.log(err); - return; - } - test.equal(result, "java.util.ArrayList"); - test.done(); - }); - }); - } - }); - }, - - "create an instance of a class and call methods (getName) (sync)": function(test) { - var list = java.newInstanceSync("java.util.ArrayList"); - test.equal(list.sizeSync(), 0); - list.addSync("hello"); - list.addSync("world"); - test.equal(list.sizeSync(), 2); - var item0 = list.getSync(0); - test.equal(item0, "hello"); - var clazz = list.getClassSync(); - var result = clazz.getNameSync(); - test.equal(result, "java.util.ArrayList"); - test.done(); - }, - - "create an instance of a class and call methods (size) (async)": function(test) { - java.newInstance("java.util.ArrayList", function(err, list) { - if (err) { - console.log(err); - return; - } - test.ok(list); - if (list) { - list.size(function(err, result) { - if (err) { - console.log(err); - return; - } - test.equal(result, 0); - test.done(); - }); - } - }); - }, - - "passing objects to methods": function(test) { - var dataArray = "hello world\n".split('').map(function(c) { return java.newByte(c.charCodeAt(0)); }); - var data = java.newArray("byte", dataArray); - //console.log("data", data.toStringSync()); - var stream = java.newInstanceSync("java.io.ByteArrayInputStream", data); - //console.log("stream", stream); - var reader = java.newInstanceSync("java.io.InputStreamReader", stream); - //console.log("reader", reader); - var bufferedReader = java.newInstanceSync("java.io.BufferedReader", reader); - var str = bufferedReader.readLineSync(); - console.log("bufferedReader.readLineSync", str); - test.equal(str, "hello world"); - test.done(); - }, - - "method returning an array of ints sync": function(test) { - var arr = java.callStaticMethodSync("Test", "getArrayOfInts"); - console.log(arr); - test.done(); - }, - - "method returning an array of bytes sync": function(test) { - var arr = java.callStaticMethodSync("Test", "getArrayOfBytes"); - console.log(arr); - test.done(); - }, - - "method returning an array of bools sync": function(test) { - var arr = java.callStaticMethodSync("Test", "getArrayOfBools"); - console.log(arr); - test.done(); - }, - - "method returning an array of doubles sync": function(test) { - var arr = java.callStaticMethodSync("Test", "getArrayOfDoubles"); - console.log(arr); - test.done(); - }, - - "method returning an array of floats sync": function(test) { - var arr = java.callStaticMethodSync("Test", "getArrayOfFloats"); - console.log(arr); - test.done(); - }, - - "method returning an array of longs sync": function(test) { - var arr = java.callStaticMethodSync("Test", "getArrayOfLongs"); - arr = arr.map(function(l) { - return l.toStringSync(); - }); - console.log(arr); - test.done(); - }, - - "method returning a string (Unicode BMP)": function(test) { - var s = java.callStaticMethodSync("Test", "getUnicodeBMP"); - console.log(s); - test.equal("\u2605", s); - test.done(); - }, - - "method returning a string (Unicode SMP)": function(test) { - var s = java.callStaticMethodSync("Test", "getUnicodeSMP"); - console.log(s); - // The below string is U+1F596, represented as surrogate pairs - test.equal("\uD83D\uDD96", s); - test.done(); - }, - - "method returning a string (NULL char)": function(test) { - var s = java.callStaticMethodSync("Test", "getUnicodeNull"); - console.log(s); - test.equal("\0", s); - test.done(); - }, - - "method taking a byte": function(test) { - var b = java.newByte(1); - test.equal('java.lang.Byte', b.getClassSync().getNameSync()); - test.equal('1', b.toStringSync()); - var r = java.callStaticMethodSync("Test", "staticByte", b); - console.log(r); - test.equal(r, 1); - test.done(); - }, - - "method taking a short": function(test) { - var s = java.newShort(1); - test.equal('java.lang.Short', s.getClassSync().getNameSync()); - test.equal('1', s.toStringSync()); - var r = java.callStaticMethodSync("Test", "staticShort", s); - console.log(r); - test.equal(r, 1); - test.done(); - }, - - "method taking a double": function(test) { - var s = java.newDouble(3.14); - test.equal('java.lang.Double', s.getClassSync().getNameSync()); - test.equal('3.14', s.toStringSync()); - var r = java.callStaticMethodSync("Test", "staticDouble", s); - console.log(r); - test.ok(Math.abs(r - 3.14) < 0.0001, r + " != 3.14"); - test.done(); - }, - - "method taking a float": function(test) { - var s = java.newFloat(3.14); - test.equal('java.lang.Float', s.getClassSync().getNameSync()); - test.equal('3.14', s.toStringSync()); - var r = java.callStaticMethodSync("Test", "staticFloat", s); - console.log(r); - test.ok(Math.abs(r - 3.14) < 0.0001, r + " != 3.14"); - test.done(); - }, - - "method taking a long": function(test) { - var l = java.newLong(1); - test.equal('java.lang.Long', l.getClassSync().getNameSync()); - test.equal('1', l.toStringSync()); - var r = java.callStaticMethodSync("Test", "staticLong", l); - console.log(r); - test.equal(r, 1); - test.done(); - }, - - "method taking a char (number)": function(test) { - var ch = java.newChar(97); // 'a' - test.equal('java.lang.Character', ch.getClassSync().getNameSync()); - test.equal('a', ch.toStringSync()); - var r = java.callStaticMethodSync("Test", "staticChar", ch); - console.log(r); - test.equal(r, 97); - test.done(); - }, - - "method taking a char (string)": function(test) { - var ch = java.newChar('a'); - test.equal('java.lang.Character', ch.getClassSync().getNameSync()); - test.equal('a', ch.toStringSync()); - var r = java.callStaticMethodSync("Test", "staticChar", ch); - console.log(r); - test.equal(r, 97); - test.done(); - }, - - "method taking a string (Unicode BMP)": function(test) { - var s = "\u2605"; - var r = java.callStaticMethodSync("Test", "staticString", s); - console.log(r); - test.equal(r, s); - test.done(); - }, - - "method taking a string (Unicode SMP)": function(test) { - // The below string is U+1F596, represented as surrogate pairs - var s = "\uD83D\uDD96"; - var r = java.callStaticMethodSync("Test", "staticString", s); - console.log(r); - test.equal(r, s); - test.done(); - }, - - "method taking a string (with null char)": function(test) { - var s = "\0"; - var r = java.callStaticMethodSync("Test", "staticString", s); - console.log(r); - test.equal(r, s); - test.done(); - }, - - "new boolean array object": function(test) { - var booleanArray = java.newArray("java.lang.Boolean", [true, false]); - var r = java.callStaticMethodSync("Test", "staticBooleanArray", booleanArray); - test.equal(r.length, 2); - test.equal(r[0], true); - test.equal(r[1], false); - test.done(); - }, - "new byte array object": function(test) { - var byteArray = java.newArray("byte", [1, 2, 3]); - test.equal(byteArray.length, 3); - test.equal(byteArray[0], 1); - test.equal(byteArray[1], 2); - test.equal(byteArray[2], 3); - test.done(); - }, - "new boolean array": function(test) { - var booleanArray = java.newArray("boolean", [true, false]); - var r = java.callStaticMethodSync("Test", "staticBooleanArray", booleanArray); - test.equal(r.length, 2); - test.equal(r[0], true); - test.equal(r[1], false); - test.done(); - }, - - "new int array": function(test) { - var intArray = java.newArray("int", [1, 2]); - var r = java.callStaticMethodSync("Test", "staticIntArray", intArray); - test.equal(r.length, 2); - test.equal(r[0], 1); - test.equal(r[1], 2); - test.done(); - }, - - "new double array": function(test) { - var doubleArray = java.newArray("double", [1.2, 4]); - var r = java.callStaticMethodSync("Test", "staticDoubleArray", doubleArray); - test.equal(r.length, 2); - test.equal(r[0], 1.2); - test.equal(r[1], 4); - test.done(); - }, - - "new short array objects": function(test) { - var shortArray = java.newArray("java.lang.Short", [1, 2].map(function(c) { return java.newShort(c); })); - var r = java.callStaticMethodSync("Test", "staticShortArray", shortArray); - test.equal(r.length, 2); - test.equal(r[0], 1); - test.equal(r[1], 2); - test.done(); - }, - - "new short array": function(test) { - var shortArray = java.newArray("short", [1, 2]); - var r = java.callStaticMethodSync("Test", "staticShortArray", shortArray); - test.equal(r.length, 2); - test.equal(r[0], 1); - test.equal(r[1], 2); - test.done(); - } -}); - diff --git a/test/simple.test.ts b/test/simple.test.ts new file mode 100644 index 00000000..be4733c1 --- /dev/null +++ b/test/simple.test.ts @@ -0,0 +1,368 @@ +import { beforeAll, describe, expect, test } from "vitest"; +import { Java, JavaObject } from "../java"; +import { getJava } from "../testHelpers"; + +describe("Simple", () => { + let java!: Java; + + beforeAll(async () => { + java = await getJava(); + }); + + test("test classpath commons lang", () => { + const result = java.callStaticMethodSync("org.apache.commons.lang3.ObjectUtils", "toString", "test"); + console.log("org.apache.commons.lang3.ObjectUtils.toString:", result); + expect(result).toBe("test"); + }); + + test("test adding to classpath after other calls are made", () => { + java.callStaticMethodSync("java.lang.System", "currentTimeMillis"); + expect(() => { + console.log("classpath", java.classpath); + java.classpath = ["test/"]; + }).toThrow(); + }); + + test("test changing options after other calls are made", () => { + java.callStaticMethodSync("java.lang.System", "currentTimeMillis"); + expect(() => { + console.log("options", java.options); + java.options = ["newoption"]; + }).toThrow(); + }); + + test("test changing nativeBindingLocation after other calls are made", () => { + java.callStaticMethodSync("java.lang.System", "currentTimeMillis"); + expect(() => { + console.log("nativeBindingLocation", java.nativeBindingLocation); + java.nativeBindingLocation = "newNativeBindingLocation"; + }).toThrow(); + }); + + test("test static calls", () => { + const result = java.callStaticMethodSync("java.lang.System", "currentTimeMillis"); + console.log("currentTimeMillis:", result); + expect(result).toBeTruthy(); + }); + + test("test static calls single argument", () => { + const result = java.callStaticMethodSync("java.lang.System", "getProperty", "os.version"); + console.log("os.version:", result); + expect(result).toBeTruthy(); + }); + + test("test method does not exists (sync)", () => { + expect(() => { + java.callStaticMethodSync("java.lang.System", "badMethod"); + }).toThrow(); + }); + + test("test method does not exists (async)", () => { + java.callStaticMethod("java.lang.System", "badMethod", (err: Error | undefined) => { + if (err) { + return; + } + new Error("should throw exception"); + }); + }); + + test("create an instance of a class and call methods (getName) (async)", async () => { + await new Promise((resolve) => { + java.newInstance("java.util.ArrayList", (err: Error | undefined, list: JavaObject | undefined) => { + expect(err).toBeFalsy(); + expect(list).toBeTruthy(); + list.getClass((err: Error | undefined, result: JavaObject | undefined) => { + expect(err).toBeFalsy(); + result.getName((err: Error | undefined, result: JavaObject | undefined) => { + expect(err).toBeFalsy(); + expect(result).toBe("java.util.ArrayList"); + resolve(); + }); + }); + }); + }); + }); + + test("findClassSync", async () => { + const arrayListClass = java.findClassSync("java.util.ArrayList"); + expect(arrayListClass).toBeTruthy(); + expect(arrayListClass.getNameSync()).toBe("java.util.ArrayList"); + }); + + test("findClassSync not found", async () => { + expect(() => { + java.findClassSync("java.util.MissingClass"); + }).toThrowError(/Could not create class java.util.MissingClass/); + }); + + test("call method", async () => { + const list = java.newInstanceSync("java.util.ArrayList"); + await new Promise((resolve) => { + java.callMethod(list, "add", "test", (err: Error | undefined) => { + expect(err).toBeFalsy(); + expect(list.sizeSync()).toBe(1); + resolve(); + }); + }); + }); + + test("call method (sync)", async () => { + const list = java.newInstanceSync("java.util.ArrayList"); + java.callMethodSync(list, "add", ["test"]); + expect(list.sizeSync()).toBe(1); + }); + + test("create an instance of a class and call methods (getName) (sync)", () => { + const list = java.newInstanceSync("java.util.ArrayList"); + expect(list.sizeSync()).toBe(0); + list.addSync("hello"); + list.addSync("world"); + expect(list.sizeSync()).toBe(2); + const item0 = list.getSync(0); + expect(item0).toBe("hello"); + const clazz = list.getClassSync(); + const result = clazz.getNameSync(); + expect(result).toBe("java.util.ArrayList"); + }); + + test("create an instance of a class and call methods (size) (async)", async () => { + await new Promise((resolve) => { + java.newInstance("java.util.ArrayList", (err: Error | undefined, list: JavaObject | undefined) => { + expect(err).toBeFalsy(); + expect(list).toBeTruthy(); + list.size((err: Error | undefined, result: number | undefined) => { + expect(err).toBeFalsy(); + expect(result).toBe(0); + resolve(); + }); + }); + }); + }); + + test("passing objects to methods", () => { + const dataArray = "hello world\n".split("").map(function (c) { + return java.newByte(c.charCodeAt(0)); + }); + const data = java.newArray("byte", dataArray); + const stream = java.newInstanceSync("java.io.ByteArrayInputStream", data); + const reader = java.newInstanceSync("java.io.InputStreamReader", stream); + const bufferedReader = java.newInstanceSync("java.io.BufferedReader", reader); + const str = bufferedReader.readLineSync(); + expect(str).toBe("hello world"); + }); + + test("method returning an array of ints sync", () => { + const arr = java.callStaticMethodSync("Test", "getArrayOfInts"); + expect(arr.length).toBe(5); + expect(arr[0]).toBe(1); + expect(arr[1]).toBe(2); + expect(arr[2]).toBe(3); + expect(arr[3]).toBe(4); + expect(arr[4]).toBe(5); + }); + + test("method returning an array of bytes sync", () => { + const arr = java.callStaticMethodSync("Test", "getArrayOfBytes"); + expect(arr.length).toBe(5); + expect(arr[0]).toBe(1); + expect(arr[1]).toBe(2); + expect(arr[2]).toBe(3); + expect(arr[3]).toBe(4); + expect(arr[4]).toBe(5); + }); + + test("method returning an array of bools sync", () => { + const arr = java.callStaticMethodSync("Test", "getArrayOfBools"); + expect(arr.length).toBe(5); + expect(arr[0]).toBe(true); + expect(arr[1]).toBe(true); + expect(arr[2]).toBe(false); + expect(arr[3]).toBe(true); + expect(arr[4]).toBe(false); + }); + + test("method returning an array of doubles sync", () => { + const arr = java.callStaticMethodSync("Test", "getArrayOfDoubles"); + expect(arr.length).toBe(5); + expect(arr[0]).toBe(1); + expect(arr[1]).toBe(2); + expect(arr[2]).toBe(3); + expect(arr[3]).toBe(4); + expect(arr[4]).toBe(5); + }); + + test("method returning an array of floats sync", () => { + const arr = java.callStaticMethodSync("Test", "getArrayOfFloats"); + expect(arr.length).toBe(5); + expect(arr[0]).toBe(1); + expect(arr[1]).toBe(2); + expect(arr[2]).toBe(3); + expect(arr[3]).toBe(4); + expect(arr[4]).toBe(5); + }); + + test("method returning an array of longs sync", () => { + let arr = java.callStaticMethodSync("Test", "getArrayOfLongs"); + arr = arr.map((l: JavaObject) => { + return l.toStringSync(); + }); + expect(arr.length).toBe(5); + expect(arr[0]).toBe("9223372036854775807"); + expect(arr[1]).toBe("-9223372036854775808"); + expect(arr[2]).toBe("3"); + expect(arr[3]).toBe("4"); + expect(arr[4]).toBe("5"); + }); + + test("method returning a string (Unicode BMP)", () => { + const s = java.callStaticMethodSync("Test", "getUnicodeBMP"); + expect(s).toBe("\u2605"); + }); + + test("method returning a string (Unicode SMP)", () => { + const s = java.callStaticMethodSync("Test", "getUnicodeSMP"); + // The below string is U+1F596, represented as surrogate pairs + expect(s).toBe("\uD83D\uDD96"); + }); + + test("method returning a string (NULL char)", () => { + const s = java.callStaticMethodSync("Test", "getUnicodeNull"); + expect(s).toBe("\0"); + }); + + test("method taking a byte", () => { + const b = java.newByte(1); + expect(b.getClassSync().getNameSync()).toBe("java.lang.Byte"); + expect(b.toStringSync()).toBe("1"); + const r = java.callStaticMethodSync("Test", "staticByte", b); + expect(r).toBe(1); + }); + + test("method taking a short", () => { + const s = java.newShort(1); + expect(s.getClassSync().getNameSync()).toBe("java.lang.Short"); + expect(s.toStringSync()).toBe("1"); + const r = java.callStaticMethodSync("Test", "staticShort", s); + expect(r).toBe(1); + }); + + test("method taking a double", () => { + const s = java.newDouble(3.14); + expect(s.getClassSync().getNameSync()).toBe("java.lang.Double"); + expect(s.toStringSync()).toBe("3.14"); + const r = java.callStaticMethodSync("Test", "staticDouble", s); + expect(Math.abs(r - 3.14) < 0.0001, r + " != 3.14").toBeTruthy(); + }); + + test("method taking a float", () => { + const s = java.newFloat(3.14); + expect(s.getClassSync().getNameSync()).toBe("java.lang.Float"); + expect(s.toStringSync()).toBe("3.14"); + const r = java.callStaticMethodSync("Test", "staticFloat", s); + expect(Math.abs(r - 3.14) < 0.0001, r + " != 3.14").toBeTruthy(); + }); + + test("method taking a long", () => { + const l = java.newLong(1); + expect(l.getClassSync().getNameSync()).toBe("java.lang.Long"); + expect(l.toStringSync()).toBe("1"); + const r = java.callStaticMethodSync("Test", "staticLong", l); + expect(r).toBe(1); + }); + + test("method taking a char (number)", () => { + const ch = java.newChar(97); // 'a' + expect(ch.getClassSync().getNameSync()).toBe("java.lang.Character"); + expect(ch.toStringSync()).toBe("a"); + const r = java.callStaticMethodSync("Test", "staticChar", ch); + expect(r).toBe(97); + }); + + test("method taking a char (string)", () => { + const ch = java.newChar("a"); + expect(ch.getClassSync().getNameSync()).toBe("java.lang.Character"); + expect(ch.toStringSync()).toBe("a"); + const r = java.callStaticMethodSync("Test", "staticChar", ch); + expect(r).toBe(97); + }); + + test("method taking a string (Unicode BMP)", () => { + const s = "\u2605"; + const r = java.callStaticMethodSync("Test", "staticString", s); + expect(r).toBe(s); + }); + + test("method taking a string (Unicode SMP)", () => { + // The below string is U+1F596, represented as surrogate pairs + const s = "\uD83D\uDD96"; + const r = java.callStaticMethodSync("Test", "staticString", s); + expect(r).toBe(s); + }); + + test("method taking a string (with null char)", () => { + const s = "\0"; + const r = java.callStaticMethodSync("Test", "staticString", s); + expect(r).toBe(s); + }); + + test("new boolean array object", () => { + const booleanArray = java.newArray("java.lang.Boolean", [true, false]); + const r = java.callStaticMethodSync("Test", "staticBooleanArray", booleanArray); + expect(r.length).toBe(2); + expect(r[0]).toBe(true); + expect(r[1]).toBe(false); + }); + + test("new byte array object", () => { + const byteArray = java.newArray("byte", [1, 2, 3]); + expect(byteArray.length).toBe(3); + expect(byteArray[0]).toBe(1); + expect(byteArray[1]).toBe(2); + expect(byteArray[2]).toBe(3); + }); + + test("new boolean array", () => { + const booleanArray = java.newArray("boolean", [true, false]); + const r = java.callStaticMethodSync("Test", "staticBooleanArray", booleanArray); + expect(r.length).toBe(2); + expect(r[0]).toBe(true); + expect(r[1]).toBe(false); + }); + + test("new int array", () => { + const intArray = java.newArray("int", [1, 2]); + const r = java.callStaticMethodSync("Test", "staticIntArray", intArray); + expect(r.length).toBe(2); + expect(r[0]).toBe(1); + expect(r[1]).toBe(2); + }); + + test("new double array", () => { + const doubleArray = java.newArray("double", [1.2, 4]); + const r = java.callStaticMethodSync("Test", "staticDoubleArray", doubleArray); + expect(r.length).toBe(2); + expect(r[0]).toBe(1.2); + expect(r[1]).toBe(4); + }); + + test("new short array objects", () => { + const shortArray = java.newArray( + "java.lang.Short", + [1, 2].map(function (c) { + return java.newShort(c); + }) + ); + const r = java.callStaticMethodSync("Test", "staticShortArray", shortArray); + expect(r.length).toBe(2); + expect(r[0]).toBe(1); + expect(r[1]).toBe(2); + }); + + test("new short array", () => { + const shortArray = java.newArray("short", [1, 2]); + const r = java.callStaticMethodSync("Test", "staticShortArray", shortArray); + expect(r.length).toBe(2); + expect(r[0]).toBe(1); + expect(r[1]).toBe(2); + }); +}); diff --git a/test/utils-types-test.js b/test/utils-types-test.js deleted file mode 100644 index 327e7d3e..00000000 --- a/test/utils-types-test.js +++ /dev/null @@ -1,70 +0,0 @@ - -var java = require("../testHelpers").java; - -var nodeunit = require("nodeunit"); -var util = require("util"); - -exports['Utils - Types'] = nodeunit.testCase({ - "Array of Objects": function(test) { - var val = java.getStaticFieldValue("Test", "staticArrayObjects"); - test.equal(null, val); - - java.setStaticFieldValue("Test", "staticArrayObjects", java.newArray("Test", [ - java.newInstanceSync("Test", 1), - java.newInstanceSync("Test", 2), - java.newInstanceSync("Test", 3) - ])); - - val = java.getStaticFieldValue("Test", "staticArrayObjects"); - test.ok(val); - test.equal(val.length, 3); - test.equal(val[0].getIntSync(), 1); - test.equal(val[1].getIntSync(), 2); - test.equal(val[2].getIntSync(), 3); - test.done(); - }, - - "Static Method Overload": function(test) { - var result = java.callStaticMethodSync("Test", "staticMethodOverload", "a"); - test.equal(result, 1); - result = java.callStaticMethodSync("Test", "staticMethodOverload", 1); - test.equal(result, 2); - result = java.callStaticMethodSync("Test", "staticMethodOverload", java.newInstanceSync("Test$SuperClass")); - test.equal(result, 3); - result = java.callStaticMethodSync("Test", "staticMethodOverload", java.newInstanceSync("Test$SubClass")); - test.equal(result, 4); - test.done(); - }, - - "Method Overload": function(test) { - var testObj = java.newInstanceSync("Test"); - var result = testObj.methodOverloadSync("a"); - test.equal(result, 1); - result = testObj.methodOverloadSync(1); - test.equal(result, 2); - result = testObj.methodOverloadSync(java.newInstanceSync("Test$SuperClass")); - test.equal(result, 3); - result = testObj.methodOverloadSync(java.newInstanceSync("Test$SubClass")); - test.equal(result, 4); - test.done(); - }, - - "Char array": function(test) { - var originalArray = "hello 世界\n".split(''); - var Arrays = java.import("java.util.Arrays"); - var arr1 = java.newArray("char", originalArray); - var list = Arrays.asListSync(arr1); - var arr2 = list.toArraySync(); - test.equal(arr2.length, 1); - test.equal(arr2[0].length, 9); - var isTypedArrayReturn = !(typeof arr2[0][0] === 'string'); - for(var i=0; i { + let java!: Java; + + beforeAll(async () => { + java = await getJava(); + }); + + test("Array of Objects", () => { + let val = java.getStaticFieldValue("Test", "staticArrayObjects"); + expect(val).toBeNull(); + + java.setStaticFieldValue( + "Test", + "staticArrayObjects", + java.newArray("Test", [ + java.newInstanceSync("Test", 1), + java.newInstanceSync("Test", 2), + java.newInstanceSync("Test", 3), + ]) + ); + + val = java.getStaticFieldValue("Test", "staticArrayObjects"); + expect(val).toBeTruthy(); + expect(val.length).toBe(3); + expect(val[0].getIntSync()).toBe(1); + expect(val[1].getIntSync()).toBe(2); + expect(val[2].getIntSync()).toBe(3); + }); + + test("Static Method Overload", () => { + let result = java.callStaticMethodSync("Test", "staticMethodOverload", "a"); + expect(result).toBe(1); + result = java.callStaticMethodSync("Test", "staticMethodOverload", 1); + expect(result).toBe(2); + result = java.callStaticMethodSync("Test", "staticMethodOverload", java.newInstanceSync("Test$SuperClass")); + expect(result).toBe(3); + result = java.callStaticMethodSync("Test", "staticMethodOverload", java.newInstanceSync("Test$SubClass")); + expect(result).toBe(4); + }); + + test("Method Overload", () => { + const testObj = java.newInstanceSync("Test"); + let result = testObj.methodOverloadSync("a"); + expect(result).toBe(1); + result = testObj.methodOverloadSync(1); + expect(result).toBe(2); + result = testObj.methodOverloadSync(java.newInstanceSync("Test$SuperClass")); + expect(result).toBe(3); + result = testObj.methodOverloadSync(java.newInstanceSync("Test$SubClass")); + expect(result).toBe(4); + }); + + test("Char array", () => { + const originalArray = "hello 世界\n".split(""); + const Arrays = java.import("java.util.Arrays"); + const arr1 = java.newArray("char", originalArray); + const list = Arrays.asListSync(arr1); + const arr2 = list.toArraySync(); + expect(arr2.length).toBe(1); + expect(arr2[0].length).toBe(9); + const isTypedArrayReturn = !(typeof arr2[0][0] === "string"); + for (let i = 0; i < originalArray.length; i++) { + if (isTypedArrayReturn) { + expect(arr2[0][i]).toBe(originalArray[i].charCodeAt(0)); + } else { + expect(arr2[0][i]).toBe(originalArray[i]); + } + } + }); +}); diff --git a/test/varargs-test.js b/test/varargs-test.js deleted file mode 100644 index 3db1776c..00000000 --- a/test/varargs-test.js +++ /dev/null @@ -1,109 +0,0 @@ -'use strict'; - -var java = require('../testHelpers').java; - -var nodeunit = require('nodeunit'); -var util = require('util'); - -exports['varargs'] = nodeunit.testCase({ - - 'array signature inferrence': function(test) { - test.expect(9); - var Test = java.import('Test'); - test.strictEqual(Test.varArgsSignatureSync([]), 'Object...'); - test.strictEqual(Test.varArgsSignatureSync(['a', 'b']), 'String...'); - test.strictEqual(Test.varArgsSignatureSync([1, 2]), 'Integer...'); - test.strictEqual(Test.varArgsSignatureSync([1.1, 2]), 'Number...'); - test.strictEqual(Test.varArgsSignatureSync([1.1, 'a']), 'Object...'); - test.strictEqual(Test.varArgsSignatureSync([true, 'a']), 'Object...'); - test.strictEqual(Test.varArgsSignatureSync([true, 1]), 'Object...'); - test.strictEqual(Test.varArgsSignatureSync([true, 1.1]), 'Object...'); - test.strictEqual(Test.varArgsSignatureSync([true, false]), 'Boolean...'); - test.done(); - }, - - 'variadic signature inferrence': function(test) { - test.expect(9); - var Test = java.import('Test'); - test.strictEqual(Test.varArgsSignatureSync(), 'Object...'); - test.strictEqual(Test.varArgsSignatureSync('a', 'b'), 'String...'); - test.strictEqual(Test.varArgsSignatureSync(1, 2), 'Integer...'); - test.strictEqual(Test.varArgsSignatureSync(1.1, 2), 'Number...'); - test.strictEqual(Test.varArgsSignatureSync(1.1, 'a'), 'Object...'); - test.strictEqual(Test.varArgsSignatureSync(true, 'a'), 'Object...'); - test.strictEqual(Test.varArgsSignatureSync(true, 1), 'Object...'); - test.strictEqual(Test.varArgsSignatureSync(true, 1.1), 'Object...'); - test.strictEqual(Test.varArgsSignatureSync(true, false), 'Boolean...'); - test.done(); - }, - - 'variadic no args': function(test) { - test.expect(1); - var String = java.import('java.lang.String'); - test.strictEqual(String.formatSync('nothing'), 'nothing'); - test.done(); - }, - - 'variadic one args': function(test) { - test.expect(1); - var String = java.import('java.lang.String'); - test.strictEqual(String.formatSync('%s', 'hello'), 'hello'); - test.done(); - }, - - 'variadic two args': function(test) { - test.expect(1); - var String = java.import('java.lang.String'); - test.strictEqual(String.formatSync('%s--%s', 'hello', 'world'), 'hello--world'); - test.done(); - }, - - 'newArray(Object) no args passed': function(test) { - test.expect(1); - var String = java.import('java.lang.String'); - test.strictEqual(String.formatSync('nothing', java.newArray('java.lang.Object', [])), 'nothing'); - test.done(); - }, - - 'newArray(Object) one args': function(test) { - test.expect(1); - var String = java.import('java.lang.String'); - test.strictEqual(String.formatSync('%s', java.newArray('java.lang.Object', ['hello'])), 'hello'); - test.done(); - }, - - 'newArray(Object) two args': function(test) { - test.expect(1); - var String = java.import('java.lang.String'); - test.strictEqual(String.formatSync('%s--%s', java.newArray('java.lang.Object', ['hello', 'world'])), 'hello--world'); - test.done(); - }, - - 'Call static method with variadic varargs': function(test) { - test.expect(4); - var Test = java.import('Test'); - test.equal(Test.staticVarargsSync(5), '5'); - test.equal(Test.staticVarargsSync(5, 'a'), '5a'); - test.equal(Test.staticVarargsSync(5, 'a', 'b'), '5ab'); - test.equal(Test.staticVarargsSync(5, 'a', 'b', 'c'), '5abc'); - test.done(); - }, - - 'Call static varargs method with plain array': function(test) { - test.expect(3); - var Test = java.import('Test'); - test.equal(Test.staticVarargsSync(5, ['a']), '5a'); - test.equal(Test.staticVarargsSync(5, ['a', 'b']), '5ab'); - test.equal(Test.staticVarargsSync(5, ['a', 'b', 'c']), '5abc'); - test.done(); - }, - - 'Call static varags method with newArray': function(test) { - test.expect(2); - var Test = java.import('Test'); - test.equal(Test.staticVarargsSync(5, java.newArray('java.lang.String', ['a'])), '5a'); - test.equal(Test.staticVarargsSync(5, java.newArray('java.lang.String', ['a', 'b', 'c'])), '5abc'); - test.done(); - } - -}); diff --git a/test/varargs.test.ts b/test/varargs.test.ts new file mode 100644 index 00000000..991229e5 --- /dev/null +++ b/test/varargs.test.ts @@ -0,0 +1,88 @@ +import { beforeAll, describe, expect, test } from "vitest"; +import { getJava } from "../testHelpers"; +import { Java } from "../java"; + +describe("varargs", () => { + let java!: Java; + + beforeAll(async () => { + java = await getJava(); + }); + + test("array signature inference", () => { + const Test = java.import("Test"); + expect(Test.varArgsSignatureSync([])).toBe("Object..."); + expect(Test.varArgsSignatureSync(["a", "b"])).toBe("String..."); + expect(Test.varArgsSignatureSync([1, 2])).toBe("Integer..."); + expect(Test.varArgsSignatureSync([1.1, 2])).toBe("Number..."); + expect(Test.varArgsSignatureSync([1.1, "a"])).toBe("Object..."); + expect(Test.varArgsSignatureSync([true, "a"])).toBe("Object..."); + expect(Test.varArgsSignatureSync([true, 1])).toBe("Object..."); + expect(Test.varArgsSignatureSync([true, 1.1])).toBe("Object..."); + expect(Test.varArgsSignatureSync([true, false])).toBe("Boolean..."); + }); + + test("variadic signature inference", () => { + const Test = java.import("Test"); + expect(Test.varArgsSignatureSync()).toBe("Object..."); + expect(Test.varArgsSignatureSync("a", "b")).toBe("String..."); + expect(Test.varArgsSignatureSync(1, 2)).toBe("Integer..."); + expect(Test.varArgsSignatureSync(1.1, 2)).toBe("Number..."); + expect(Test.varArgsSignatureSync(1.1, "a")).toBe("Object..."); + expect(Test.varArgsSignatureSync(true, "a")).toBe("Object..."); + expect(Test.varArgsSignatureSync(true, 1)).toBe("Object..."); + expect(Test.varArgsSignatureSync(true, 1.1)).toBe("Object..."); + expect(Test.varArgsSignatureSync(true, false)).toBe("Boolean..."); + }); + + test("variadic no args", () => { + const String = java.import("java.lang.String"); + expect(String.formatSync("nothing")).toBe("nothing"); + }); + + test("variadic one args", () => { + const String = java.import("java.lang.String"); + expect(String.formatSync("%s", "hello")).toBe("hello"); + }); + + test("variadic two args", () => { + const String = java.import("java.lang.String"); + expect(String.formatSync("%s--%s", "hello", "world")).toBe("hello--world"); + }); + + test("newArray(Object) no args passed", () => { + const String = java.import("java.lang.String"); + expect(String.formatSync("nothing", java.newArray("java.lang.Object", []))).toBe("nothing"); + }); + + test("newArray(Object) one args", () => { + const String = java.import("java.lang.String"); + expect(String.formatSync("%s", java.newArray("java.lang.Object", ["hello"]))).toBe("hello"); + }); + + test("newArray(Object) two args", () => { + const String = java.import("java.lang.String"); + expect(String.formatSync("%s--%s", java.newArray("java.lang.Object", ["hello", "world"]))).toBe("hello--world"); + }); + + test("Call static method with variadic varargs", () => { + const Test = java.import("Test"); + expect(Test.staticVarargsSync(5)).toBe("5"); + expect(Test.staticVarargsSync(5, "a")).toBe("5a"); + expect(Test.staticVarargsSync(5, "a", "b")).toBe("5ab"); + expect(Test.staticVarargsSync(5, "a", "b", "c")).toBe("5abc"); + }); + + test("Call static varargs method with plain array", () => { + const Test = java.import("Test"); + expect(Test.staticVarargsSync(5, ["a"])).toBe("5a"); + expect(Test.staticVarargsSync(5, ["a", "b"])).toBe("5ab"); + expect(Test.staticVarargsSync(5, ["a", "b", "c"])).toBe("5abc"); + }); + + test("Call static varags method with newArray", () => { + const Test = java.import("Test"); + expect(Test.staticVarargsSync(5, java.newArray("java.lang.String", ["a"]))).toBe("5a"); + expect(Test.staticVarargsSync(5, java.newArray("java.lang.String", ["a", "b", "c"]))).toBe("5abc"); + }); +}); diff --git a/test8/TestLambda$IntegerMath.class b/test8/TestLambda$IntegerMath.class deleted file mode 100644 index 715fed7d..00000000 Binary files a/test8/TestLambda$IntegerMath.class and /dev/null differ diff --git a/test8/TestLambda.class b/test8/TestLambda.class deleted file mode 100644 index a56ab0ac..00000000 Binary files a/test8/TestLambda.class and /dev/null differ diff --git a/test8/testLambda.js b/test8/testLambda.js deleted file mode 100644 index 994ad026..00000000 --- a/test8/testLambda.js +++ /dev/null @@ -1,27 +0,0 @@ -var java = require("../testHelpers").java; - -var nodeunit = require("nodeunit"); -var util = require("util"); - -exports['Java8'] = nodeunit.testCase({ - "call methods of a class that uses lambda expressions": function(test) { - try { - var TestLambda = java.import('TestLambda'); - var lambda = new TestLambda(); - var sum = lambda.testLambdaAdditionSync(23, 42); - test.equal(sum, 65); - var diff = lambda.testLambdaSubtractionSync(23, 42); - test.equal(diff, -19); - } - catch (err) { - var unsupportedVersion = java.instanceOf(err.cause, 'java.lang.UnsupportedClassVersionError'); - test.ok(unsupportedVersion); - if (unsupportedVersion) - console.log('JRE 1.8 not available'); - else - console.error('Java8 test failed with unknown error:', err); - } - test.done(); - } -}); - diff --git a/testAsyncOptions/allThreeSuffix.test.ts b/testAsyncOptions/allThreeSuffix.test.ts new file mode 100644 index 00000000..72ebe81c --- /dev/null +++ b/testAsyncOptions/allThreeSuffix.test.ts @@ -0,0 +1,98 @@ +// All three variants have non-empty suffix, i.e a suffix is required for any variant. + +import { Java } from "../java"; +import { getJava } from "../testHelpers"; +import { describe, test, expect, beforeAll } from "vitest"; + +describe("allThreeSuffix", () => { + let java!: Java; + + beforeAll(async () => { + java = await getJava({ + syncSuffix: "Sync", + asyncSuffix: "Async", + promiseSuffix: "Promise", + }); + }); + + test("api", () => { + const arrayList = java.newInstanceSync("java.util.ArrayList"); + expect(arrayList).toBeDefined(); + expect(java.instanceOf(arrayList, "java.util.ArrayList")).toBeTruthy(); + + expect(typeof arrayList.addSync !== "undefined", "Expected `addSync` to be present, but it is NOT.").toBeTruthy(); + expect(typeof arrayList.addAsync !== "undefined", "Expected `addAsync` to be present, but it is NOT.").toBeTruthy(); + expect( + typeof arrayList.addPromise !== "undefined", + "Expected `addPromise` to be present, but it is NOT." + ).toBeTruthy(); + expect(typeof arrayList.add === "undefined", "Expected `add` to NOT be present, but it is.").toBeTruthy(); + }); + + test("importClass", () => { + // Note: java.import executes javascript code in src-node/nodeJavaBridge that makes sync calls to java classes. + const ArrayList = java.import("java.util.ArrayList"); + expect(ArrayList).toBeTruthy(); + const arrayList = new ArrayList(); + expect(arrayList).toBeTruthy(); + expect(arrayList.sizeSync()).toBe(0); + }); + + test("staticAPI", () => { + const String = java.import("java.lang.String"); + expect(String).toBeTruthy(); + + const api = Object.keys(String).filter((key) => typeof String[key] === "function"); + expect(api.includes("formatSync"), "Expected `formatSync` to be present, but it is NOT.").toBeTruthy(); + expect(api.includes("formatAsync"), "Expected `formatAsync` to be present, but it is NOT.").toBeTruthy(); + expect(api.includes("formatPromise"), "Expected `formatPromise` to be present, but it is NOT.").toBeTruthy(); + expect(!api.includes("format"), "Expected `format` to NOT be present, but it is.").toBeTruthy(); + expect(!api.includes("formatundefined"), "Expected `formatundefined` to NOT be present, but it is.").toBeTruthy(); + }); + + test("syncCalls", () => { + const arrayList = java.newInstanceSync("java.util.ArrayList"); + arrayList.addSync("hello"); + arrayList.addSync("world"); + expect(arrayList.sizeSync()).toBe(2); + }); + + test("staticSyncCalls", () => { + // Note: java.import executes javascript code in src-node/nodeJavaBridge that makes sync calls to java classes. + // Among other things, java.import creates Sync functions for static methods. + const String = java.import("java.lang.String"); + expect(String.formatSync("%s--%s", "hello", "world")).toBe("hello--world"); + }); + + test("asyncCalls", async () => { + const arrayList = java.newInstanceSync("java.util.ArrayList"); + await new Promise((resolve) => { + arrayList.addAsync("hello", (err: Error | undefined) => { + expect(err).toBeUndefined(); + arrayList.addAsync("world", (err: Error | undefined) => { + expect(err).toBeUndefined(); + arrayList.sizeAsync((err: Error | undefined, size: number) => { + expect(err).toBeUndefined(); + expect(size).toBe(2); + resolve(); + }); + }); + }); + }); + }); + + test("promiseCalls", async () => { + const arrayList = java.newInstanceSync("java.util.ArrayList"); + await arrayList + .addPromise("hello") + .then(() => { + return arrayList.addPromise("world"); + }) + .then(() => { + return arrayList.sizePromise(); + }) + .then((size: number) => { + expect(size).toBe(2); + }); + }); +}); diff --git a/testAsyncOptions/asyncSuffixSyncDefault.test.ts b/testAsyncOptions/asyncSuffixSyncDefault.test.ts new file mode 100644 index 00000000..6504c1d6 --- /dev/null +++ b/testAsyncOptions/asyncSuffixSyncDefault.test.ts @@ -0,0 +1,150 @@ +// Use "Async" for the asyncSuffix, and "" for the syncSuffix. + +import { beforeAll, describe, expect, test } from "vitest"; +import { getJava } from "../testHelpers"; +import { Java } from "../java"; + +describe("asyncSuffixSyncDefault", () => { + let java!: Java; + + beforeAll(async () => { + let beforeCalled = false; + let afterCalled = false; + + java = await getJava( + { + syncSuffix: "", + asyncSuffix: "Async", + ifReadOnlySuffix: "_alt", + }, + { + beforeInit: async (java) => { + function before(callback: () => void): void { + beforeCalled = true; + java.classpath.push("test/"); + expect(java.isJvmCreated()).toBeFalsy(); + callback(); + } + + function after(callback: () => void): void { + afterCalled = true; + expect(java.isJvmCreated()).toBeTruthy(); + callback(); + } + + java.registerClient(before, after); + + await new Promise((resolve) => { + java.ensureJvm((err) => { + expect(err).toBeFalsy(); + expect(java.isJvmCreated()).toBeTruthy(); + resolve(); + }); + }); + }, + } + ); + + expect(beforeCalled).toBeTruthy(); + expect(afterCalled).toBeTruthy(); + }); + + test("api", () => { + const arrayList = java.newInstanceSync("java.util.ArrayList"); + expect(arrayList).toBeTruthy(); + expect(java.instanceOf(arrayList, "java.util.ArrayList")).toBeTruthy(); + + expect(typeof arrayList.addAsync !== "undefined", "Expected `addAsync` to be present, but it is NOT.").toBeTruthy(); + expect(typeof arrayList.add !== "undefined", "Expected `add` to be present, but it is NOT.").toBeTruthy(); + expect( + typeof arrayList.addPromise === "undefined", + "Expected `addPromise` to NOT be present, but it is." + ).toBeTruthy(); + }); + + test("importClass", () => { + // Note: java.import executes javascript code in src-node/nodeJavaBridge that makes sync calls to java classes. + const ArrayList = java.import("java.util.ArrayList"); + expect(ArrayList).toBeTruthy(); + const arrayList = new ArrayList(); + expect(arrayList).toBeTruthy(); + expect(arrayList.size()).toBe(0); + }); + + test("staticAPI", () => { + const String = java.import("java.lang.String"); + expect(String).toBeTruthy(); + + const api = Object.keys(String).filter((key) => typeof String[key] === "function"); + expect(api.includes("format"), "Expected `format` to be present, but it is NOT.").toBeTruthy(); + expect(api.includes("formatAsync"), "Expected `formatAsync` to be present, but it is NOT.").toBeTruthy(); + expect(!api.includes("formatSync"), "Expected `formatSync` to NOT be present, but it is.").toBeTruthy(); + expect(!api.includes("formatPromise"), "Expected `formatPromise` to NOT be present, but it is.").toBeTruthy(); + expect(!api.includes("formatundefined"), "Expected `formatundefined` to NOT be present, but it is.").toBeTruthy(); + }); + + test("syncCalls", () => { + const arrayList = java.newInstanceSync("java.util.ArrayList"); + arrayList.add("hello"); + arrayList.add("world"); + expect(arrayList.size()).toBe(2); + }); + + test("staticSyncCalls", () => { + // Note: java.import executes javascript code in src-node/nodeJavaBridge that makes sync calls to java classes. + // Among other things, java.import creates Sync functions for static methods. + const String = java.import("java.lang.String"); + expect(String.format("%s--%s", "hello", "world")).toBe("hello--world"); + }); + + test("asyncCalls", async () => { + const arrayList = java.newInstanceSync("java.util.ArrayList"); + await new Promise((resolve) => { + arrayList.addAsync("hello", (err: Error | undefined) => { + expect(err).toBeUndefined(); + arrayList.addAsync("world", (err: Error | undefined) => { + expect(err).toBeUndefined(); + arrayList.sizeAsync((err: Error | undefined, size: number | undefined) => { + expect(err).toBeUndefined(); + expect(size).toBe(2); + resolve(); + }); + }); + }); + }); + }); + + // See testUnusableMethodName.js for the purpose of these last two tests. + // In that test, Test.name_alt() is an async method. + // In this test, it is a sync method. + test("unusableMethodNameThrows", () => { + const Test = java.import("Test"); + expect(Test).toBeTruthy(); + expect(() => Test.name()).toThrowError(TypeError); + }); + + test("alternateMethodNameWorks", () => { + const Test = java.import("Test"); + expect(Test).toBeTruthy(); + expect(Test.name_alt()).toBe("name"); + expect(Test.caller_alt()).toBe("caller"); + expect(Test.arguments_alt()).toBe("arguments"); + }); + + test("reservedFieldName", () => { + const TestEnum = java.import("Test$Enum"); + expect(TestEnum).toBeTruthy(); + + // 'foo' and 'bar' are valid enum names + expect(TestEnum.foo.toString()).toBe("foo"); + expect(TestEnum.bar.toString()).toBe("bar"); + + // TestEnum.name is actually the name of the proxy constructor function. + expect(TestEnum.name).toBe("javaClassConstructorProxy"); + + // Instead we need to access TestEnum.name_alt + expect(TestEnum.name_alt.toString()).toBe("name"); + expect(TestEnum.caller_alt.toString()).toBe("caller"); + expect(TestEnum.arguments_alt.toString()).toBe("arguments"); + }); +}); diff --git a/testAsyncOptions/clientBeforeError.test.ts b/testAsyncOptions/clientBeforeError.test.ts new file mode 100644 index 00000000..187e13a2 --- /dev/null +++ b/testAsyncOptions/clientBeforeError.test.ts @@ -0,0 +1,35 @@ +import { describe, expect, test } from "vitest"; +import { getJava } from "../testHelpers"; + +describe("clientBeforeError", () => { + test("clientBeforeError", async () => { + await getJava( + { + syncSuffix: "Sync", + }, + { + beforeInit: async (java) => { + expect(java.isJvmCreated()).toBeFalsy(); + + function before(callback: (err: Error) => void): void { + expect(java.isJvmCreated()).toBeFalsy(); + callback(new Error("dummy error")); + } + + java.registerClient(before); + + await new Promise((resolve) => { + java.ensureJvm((err) => { + expect(err).toBeTruthy(); + expect(typeof err).toBe("object"); + expect(err).toBeInstanceOf(Error); + expect(err?.message).toBe("dummy error"); + expect(java.isJvmCreated()).toBeFalsy(); + resolve(); + }); + }); + }, + } + ); + }); +}); diff --git a/testAsyncOptions/clientBeforeSyncThrows.test.ts b/testAsyncOptions/clientBeforeSyncThrows.test.ts new file mode 100644 index 00000000..5277fc17 --- /dev/null +++ b/testAsyncOptions/clientBeforeSyncThrows.test.ts @@ -0,0 +1,33 @@ +import { describe, expect, test } from "vitest"; +import { getJava } from "../testHelpers"; + +describe("clientBeforeSyncThrows", () => { + test("clientBeforeSyncThrows", async () => { + await getJava( + { + syncSuffix: "Sync", + }, + { + beforeInit: async (java) => { + expect(java.isJvmCreated()).toBeFalsy(); + + function before(): void { + expect(java.isJvmCreated()).toBeFalsy(); + throw new Error("dummy error"); + } + java.registerClient(before); + + await new Promise((resolve) => { + java.ensureJvm((err: Error | undefined) => { + expect(err && typeof err === "object").toBeTruthy(); + expect(err).instanceOf(Error); + expect(err?.message).toBe("dummy error"); + expect(java.isJvmCreated()).toBeFalsy(); + resolve(); + }); + }); + }, + } + ); + }); +}); diff --git a/testAsyncOptions/clientBeforeThrows.test.ts b/testAsyncOptions/clientBeforeThrows.test.ts new file mode 100644 index 00000000..ef493fa7 --- /dev/null +++ b/testAsyncOptions/clientBeforeThrows.test.ts @@ -0,0 +1,33 @@ +import { describe, expect, test } from "vitest"; +import { getJava } from "../testHelpers"; + +describe("clientBeforeThrows", () => { + test("clientBeforeThrows", async () => { + await getJava( + { + syncSuffix: "Sync", + }, + { + beforeInit: async (java) => { + expect(java.isJvmCreated()).toBeFalsy(); + + function before(): void { + expect(java.isJvmCreated()).toBeFalsy(); + throw new Error("dummy error"); + } + java.registerClient(before); + + await new Promise((resolve) => { + java.ensureJvm((err: Error | undefined) => { + expect(err && typeof err === "object").toBeTruthy(); + expect(err).instanceOf(Error); + expect(err?.message).toBe("dummy error"); + expect(java.isJvmCreated()).toBeFalsy(); + resolve(); + }); + }); + }, + } + ); + }); +}); diff --git a/testAsyncOptions/clientPBeforeError.test.ts b/testAsyncOptions/clientPBeforeError.test.ts new file mode 100644 index 00000000..0d8e4986 --- /dev/null +++ b/testAsyncOptions/clientPBeforeError.test.ts @@ -0,0 +1,41 @@ +import { describe, expect, test } from "vitest"; +import { getJava } from "../testHelpers"; + +describe("clientPBeforeError", () => { + test("clientPBeforeError", async () => { + await getJava( + { + syncSuffix: "Sync", + promiseSuffix: "Promise", + }, + { + beforeInit: async (java) => { + expect(java.isJvmCreated()).toBeFalsy(); + + function beforeP(): Promise { + return new Promise((_resolve, reject) => { + expect(java.isJvmCreated()).toBeFalsy(); + reject(new Error("dummy error")); + }); + } + java.registerClientP(beforeP); + + await new Promise((resolve) => { + java.ensureJvm().then( + () => { + throw new Error("expect error"); + }, + (err: Error | undefined) => { + expect(err && typeof err === "object").toBeTruthy(); + expect(err).instanceOf(Error); + expect(err?.message).toBe("dummy error"); + expect(java.isJvmCreated()).toBeFalsy(); + resolve(); + } + ); + }); + }, + } + ); + }); +}); diff --git a/testAsyncOptions/clientPBeforeThrows.test.ts b/testAsyncOptions/clientPBeforeThrows.test.ts new file mode 100644 index 00000000..cb7d725a --- /dev/null +++ b/testAsyncOptions/clientPBeforeThrows.test.ts @@ -0,0 +1,42 @@ +import { describe, expect, test } from "vitest"; +import { getJava } from "../testHelpers"; + +describe("clientPBeforeThrows", () => { + test("clientPBeforeThrows", async () => { + await getJava( + { + syncSuffix: "Sync", + promiseSuffix: "Promise", + }, + { + beforeInit: async (java) => { + expect(java.isJvmCreated()).toBeFalsy(); + + function beforeP(): Promise { + return new Promise(() => { + expect(java.isJvmCreated()).toBeFalsy(); + throw new Error("dummy error"); + }); + } + + java.registerClientP(beforeP); + + await new Promise((resolve) => { + java.ensureJvm().then( + () => { + throw new Error("expected error"); + }, + (err: Error | undefined) => { + expect(err && typeof err === "object").toBeTruthy(); + expect(err).instanceOf(Error); + expect(err?.message).toBe("dummy error"); + expect(java.isJvmCreated()).toBeFalsy(); + resolve(); + } + ); + }); + }, + } + ); + }); +}); diff --git a/testAsyncOptions/defacto.test.ts b/testAsyncOptions/defacto.test.ts new file mode 100644 index 00000000..e9fc148e --- /dev/null +++ b/testAsyncOptions/defacto.test.ts @@ -0,0 +1,113 @@ +// In the defacto case, the developer sets asyncOptions, but specifies the defacto standard behavior. + +import { beforeAll, describe, expect, test } from "vitest"; +import { Java } from "../java"; +import { getJava } from "../testHelpers"; + +describe("defacto", () => { + let java!: Java; + + beforeAll(async () => { + java = await getJava( + { + syncSuffix: "Sync", + asyncSuffix: "", + }, + { + beforeInit: async (java) => { + expect(java.isJvmCreated()).toBeFalsy(); + + function before(): void { + expect(java.isJvmCreated()).toBeFalsy(); + } + + function after(): void { + expect(java.isJvmCreated()).toBeTruthy(); + } + + java.registerClient(before, after); + java.registerClient(undefined, after); + java.registerClient(before, undefined); + + await new Promise((resolve) => { + java.ensureJvm(function (err) { + expect(err).toBeFalsy(); + expect(java.isJvmCreated()).toBeTruthy(); + + // Verify that ensureJvm is idempotent + java.ensureJvm(function (err) { + expect(err).toBeFalsy(); + resolve(); + }); + }); + }); + }, + } + ); + }); + + test("api", () => { + const arrayList = java.newInstanceSync("java.util.ArrayList"); + expect(arrayList).toBeTruthy(); + expect(java.instanceOf(arrayList, "java.util.ArrayList")).toBeTruthy(); + + expect(typeof arrayList.addSync !== "undefined", "Expected `addSync` to be present, but it is NOT.").toBeTruthy(); + expect(typeof arrayList.add !== "undefined", "Expected `add` to be present, but it is NOT.").toBeTruthy(); + expect( + typeof arrayList.addPromise === "undefined", + "Expected `addPromise` to NOT be present, but it is." + ).toBeTruthy(); + }); + + test("importClass", () => { + // Note: java.import executes javascript code in src-node/nodeJavaBridge that makes sync calls to java classes. + const ArrayList = java.import("java.util.ArrayList"); + expect(ArrayList).toBeTruthy(); + const arrayList = new ArrayList(); + expect(arrayList).toBeTruthy(); + expect(arrayList.sizeSync()).toBe(0); + }); + + test("staticAPI", () => { + const String = java.import("java.lang.String"); + expect(String).toBeTruthy(); + + const api = Object.keys(String).filter((key) => typeof String[key] === "function"); + expect(api.includes("format"), "Expected `format` to be present, but it is NOT.").toBeTruthy(); + expect(api.includes("formatSync"), "Expected `formatSync` to be present, but it is NOT.").toBeTruthy(); + expect(api.includes("formatAsync"), "Expected `formatAsync` to NOT be present, but it is.").toBeFalsy(); + expect(api.includes("formatPromise"), "Expected `formatPromise` to NOT be present, but it is.").toBeFalsy(); + expect(api.includes("formatundefined"), "Expected `formatundefined` to NOT be present, but it is.").toBeFalsy(); + }); + + test("syncCalls", () => { + const arrayList = java.newInstanceSync("java.util.ArrayList"); + arrayList.addSync("hello"); + arrayList.addSync("world"); + expect(arrayList.sizeSync()).toBe(2); + }); + + test("staticSyncCalls", () => { + // Note: java.import executes javascript code in src-node/nodeJavaBridge that makes sync calls to java classes. + // Among other things, java.import creates Sync functions for static methods. + const String = java.import("java.lang.String"); + expect(String.formatSync("%s--%s", "hello", "world")).toBe("hello--world"); + }); + + test("asyncCalls", async () => { + await new Promise((resolve) => { + const arrayList = java.newInstanceSync("java.util.ArrayList"); + arrayList.add("hello", (err: Error | undefined) => { + expect(err).toBeFalsy(); + arrayList.add("world", (err: Error | undefined) => { + expect(err).toBeFalsy(); + arrayList.size((err: Error | undefined, size: number | undefined) => { + expect(err).toBeFalsy(); + expect(size).toBe(2); + resolve(); + }); + }); + }); + }); + }); +}); diff --git a/testAsyncOptions/defactoPlusPromise.test.ts b/testAsyncOptions/defactoPlusPromise.test.ts new file mode 100644 index 00000000..d41a4b2b --- /dev/null +++ b/testAsyncOptions/defactoPlusPromise.test.ts @@ -0,0 +1,121 @@ +// The defacto case but with promises also enabled. + +import { beforeAll, describe, expect, test } from "vitest"; +import { Java } from "../java"; +import { getJava } from "../testHelpers"; + +describe("defactoPlusPromise", () => { + let java!: Java; + + beforeAll(async () => { + java = await getJava( + { + syncSuffix: "Sync", + asyncSuffix: "", + promiseSuffix: "Promise", + }, + { + beforeInit: (java) => { + expect(java.isJvmCreated()).toBeFalsy(); + + function before(callback: () => void): void { + expect(java.isJvmCreated()).toBeFalsy(); + callback(); + } + + function after(callback: () => void): void { + expect(java.isJvmCreated()).toBeTruthy(); + callback(); + } + + java.registerClient(before, after); + java.registerClient(null, after); + java.registerClient(before); + }, + } + ); + + await java.ensureJvm(); + expect(java.isJvmCreated()).toBeTruthy(); + }); + + test("api", () => { + const arrayList = java.newInstanceSync("java.util.ArrayList"); + expect(arrayList).toBeTruthy(); + expect(java.instanceOf(arrayList, "java.util.ArrayList")).toBeTruthy(); + + expect(arrayList.addSync !== "undefined", "Expected `addSync` to be present, but it is NOT.").toBeTruthy(); + expect(arrayList.add !== "undefined", "Expected `add` to be present, but it is NOT.").toBeTruthy(); + expect(arrayList.addPromise !== "undefined", "Expected `addPromise` to be present, but it is NOT.").toBeTruthy(); + }); + + test("importClass", () => { + // Note: java.import executes javascript code in src-node/nodeJavaBridge that makes sync calls to java classes. + const ArrayList = java.import("java.util.ArrayList"); + expect(ArrayList).toBeTruthy(); + const arrayList = new ArrayList(); + expect(arrayList).toBeTruthy(); + expect(arrayList.sizeSync()).toBe(0); + }); + + test("staticAPI", () => { + const String = java.import("java.lang.String"); + expect(String).toBeTruthy(); + + const api = Object.keys(String).filter((key) => typeof String[key] === "function"); + expect(api.includes("format"), "Expected `format` to be present, but it is NOT.").toBeTruthy(); + expect(api.includes("formatSync"), "Expected `formatSync` to be present, but it is NOT.").toBeTruthy(); + expect(api.includes("formatPromise"), "Expected `formatPromise` to be present, but it is NOT.").toBeTruthy(); + expect(api.includes("formatAsync"), "Expected `formatAsync` to NOT be present, but it is.").toBeFalsy(); + expect(api.includes("formatundefined"), "Expected `formatundefined` to NOT be present, but it is.").toBeFalsy(); + }); + + test("syncCalls", () => { + const arrayList = java.newInstanceSync("java.util.ArrayList"); + arrayList.addSync("hello"); + arrayList.addSync("world"); + expect(arrayList.sizeSync()).toBe(2); + }); + + test("staticSyncCalls", () => { + // Note: java.import executes javascript code in src-node/nodeJavaBridge that makes sync calls to java classes. + // Among other things, java.import creates Sync functions for static methods. + const String = java.import("java.lang.String"); + expect(String.formatSync("%s--%s", "hello", "world")).toBe("hello--world"); + }); + + test("asyncCalls", async () => { + await new Promise((resolve) => { + const arrayList = java.newInstanceSync("java.util.ArrayList"); + arrayList.add("hello", (err: Error | undefined) => { + expect(err).toBeFalsy(); + arrayList.add("world", (err: Error | undefined) => { + expect(err).toBeFalsy(); + arrayList.size((err: Error | undefined, size: number | undefined) => { + expect(err).toBeFalsy(); + expect(size).toBe(2); + resolve(); + }); + }); + }); + }); + }); + + test("promiseCalls", async () => { + await new Promise((resolve) => { + const arrayList = java.newInstanceSync("java.util.ArrayList"); + arrayList + .addPromise("hello") + .then(() => { + return arrayList.addPromise("world"); + }) + .then(() => { + return arrayList.sizePromise(); + }) + .then((size: number) => { + expect(size).toBe(2); + resolve(); + }); + }); + }); +}); diff --git a/testAsyncOptions/default.test.ts b/testAsyncOptions/default.test.ts new file mode 100644 index 00000000..ab7766d1 --- /dev/null +++ b/testAsyncOptions/default.test.ts @@ -0,0 +1,83 @@ +// In the default case, the developer does not set asyncOptions. +// We should get the defacto standard behavior. + +import { afterAll, beforeAll, describe, expect, test } from "vitest"; +import { Java } from "../java"; +import { getJava } from "../testHelpers"; + +describe("default", () => { + let java!: Java; + + beforeAll(async () => { + java = await getJava(null); + }); + + afterAll(() => { + java.stop(); + }); + + test("api", () => { + const arrayList = java.newInstanceSync("java.util.ArrayList"); + expect(arrayList).toBeTruthy(); + expect(java.instanceOf(arrayList, "java.util.ArrayList")).toBeTruthy(); + + expect(typeof arrayList.addSync !== "undefined", "Expected `addSync` to be present, but it is NOT.").toBeTruthy(); + expect(typeof arrayList.add !== "undefined", "Expected `add` to be present, but it is NOT.").toBeTruthy(); + expect( + typeof arrayList.addPromise === "undefined", + "Expected `addPromise` to NOT be present, but it is." + ).toBeTruthy(); + }); + + test("importClass", () => { + // Note: java.import executes javascript code in src-node/nodeJavaBridge that makes sync calls to java classes. + const ArrayList = java.import("java.util.ArrayList"); + expect(ArrayList).toBeTruthy(); + const arrayList = new ArrayList(); + expect(arrayList).toBeTruthy(); + expect(arrayList.sizeSync()).toBe(0); + }); + + test("staticAPI", () => { + const String = java.import("java.lang.String"); + expect(String).toBeTruthy(); + + const api = Object.keys(String).filter((key) => typeof String[key] === "function"); + expect(api.includes("format"), "Expected `format` to be present, but it is NOT.").toBeTruthy(); + expect(api.includes("formatSync"), "Expected `formatSync` to be present, but it is NOT.").toBeTruthy(); + expect(api.includes("formatAsync"), "Expected `formatAsync` to NOT be present, but it is.").toBeFalsy(); + expect(api.includes("formatPromise"), "Expected `formatPromise` to NOT be present, but it is.").toBeFalsy(); + expect(api.includes("formatundefined"), "Expected `formatundefined` to NOT be present, but it is.").toBeFalsy(); + }); + + test("syncCalls", () => { + const arrayList = java.newInstanceSync("java.util.ArrayList"); + arrayList.addSync("hello"); + arrayList.addSync("world"); + expect(arrayList.sizeSync()).toBe(2); + }); + + test("staticSyncCalls", () => { + // Note: java.import executes javascript code in src-node/nodeJavaBridge that makes sync calls to java classes. + // Among other things, java.import creates Sync functions for static methods. + const String = java.import("java.lang.String"); + expect(String.formatSync("%s--%s", "hello", "world")).toBe("hello--world"); + }); + + test("asyncCalls", async () => { + await new Promise((resolve) => { + const arrayList = java.newInstanceSync("java.util.ArrayList"); + arrayList.add("hello", (err: Error | undefined) => { + expect(err).toBeFalsy(); + arrayList.add("world", (err: Error | undefined) => { + expect(err).toBeFalsy(); + arrayList.size((err: Error | undefined, size: number | undefined) => { + expect(err).toBeFalsy(); + expect(size).toBe(2); + resolve(); + }); + }); + }); + }); + }); +}); diff --git a/testAsyncOptions/ensureJvmPromise.test.ts b/testAsyncOptions/ensureJvmPromise.test.ts new file mode 100644 index 00000000..6e56a711 --- /dev/null +++ b/testAsyncOptions/ensureJvmPromise.test.ts @@ -0,0 +1,20 @@ +import { describe, expect, test } from "vitest"; +import { getJava } from "../testHelpers"; + +describe("ensureJvmPromise", () => { + test("calling ensureJvm as a promise", async () => { + await getJava( + { + syncSuffix: "Sync", + asyncSuffix: "", + }, + { + beforeInit: async (java) => { + expect(java.isJvmCreated()).toBeFalsy(); + await java.ensureJvm(); + expect(java.isJvmCreated()).toBeTruthy(); + }, + } + ); + }); +}); diff --git a/testAsyncOptions/invalidLaunch.test.ts b/testAsyncOptions/invalidLaunch.test.ts new file mode 100644 index 00000000..53fefb7c --- /dev/null +++ b/testAsyncOptions/invalidLaunch.test.ts @@ -0,0 +1,42 @@ +import { describe, expect, test } from "vitest"; +import { getJava } from "../testHelpers"; + +describe("invalidLaunch", () => { + test("callbackNotAFunction", async () => { + await getJava( + { + syncSuffix: "", + promiseSuffix: "P", + }, + { + beforeInit: (java) => { + expect(java.isJvmCreated()).toBeFalsy(); + + expect(() => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (java as any).ensureJvm("foo"); + }).toThrow(/requires its one argument to be a callback function/); + + expect(java.isJvmCreated()).toBeFalsy(); + }, + } + ); + }); + + test("jvmCanStillBeLaunched", async () => { + await getJava( + { + syncSuffix: "", + promiseSuffix: "P", + }, + { + beforeInit: async (java) => { + expect(java.isJvmCreated()).toBeFalsy(); + + await java.ensureJvm(); + expect(java.isJvmCreated()).toBeTruthy(); + }, + } + ); + }); +}); diff --git a/testAsyncOptions/noAsync.test.ts b/testAsyncOptions/noAsync.test.ts new file mode 100644 index 00000000..d3b16e26 --- /dev/null +++ b/testAsyncOptions/noAsync.test.ts @@ -0,0 +1,111 @@ +// Just Sync and Promise, both with a non-empty suffix. + +import { beforeAll, describe, expect, test } from "vitest"; +import { Java } from "../java"; +import { getJava } from "../testHelpers"; + +describe("noAsync", () => { + let java!: Java; + + beforeAll(async () => { + java = await getJava( + { + syncSuffix: "Sync", + promiseSuffix: "Promise", + }, + { + beforeInit: (java) => { + expect(java.isJvmCreated()).toBeFalsy(); + + function beforeP(): Promise { + return new Promise((resolve) => { + expect(java.isJvmCreated()).toBeFalsy(); + resolve(); + }); + } + + function afterP(): Promise { + return new Promise((resolve) => { + expect(java.isJvmCreated()).toBeTruthy(); + resolve(); + }); + } + + java.registerClientP(beforeP, afterP); + java.registerClientP(null, afterP); + java.registerClientP(beforeP); + }, + } + ); + + await java.ensureJvm(); + expect(java.isJvmCreated()).toBeTruthy(); + }); + + test("api", () => { + const arrayList = java.newInstanceSync("java.util.ArrayList"); + expect(arrayList).toBeTruthy(); + expect(java.instanceOf(arrayList, "java.util.ArrayList")).toBeTruthy(); + + expect(typeof arrayList.addSync !== "undefined", "Expected `addSync` to be present, but it is NOT.").toBeTruthy(); + expect( + typeof arrayList.addPromise !== "undefined", + "Expected `addPromise` to be present, but it is NOT." + ).toBeTruthy(); + expect(typeof arrayList.add === "undefined", "Expected `add` to NOT be present, but it is.").toBeTruthy(); + expect(typeof arrayList.addAsync === "undefined", "Expected `addAsync` to NOT be present, but it is.").toBeTruthy(); + }); + + test("importClass", () => { + // Note: java.import executes javascript code in src-node/nodeJavaBridge that makes sync calls to java classes. + const ArrayList = java.import("java.util.ArrayList"); + expect(ArrayList).toBeTruthy(); + const arrayList = new ArrayList(); + expect(arrayList).toBeTruthy(); + expect(arrayList.sizeSync()).toBe(0); + }); + + test("staticAPI", () => { + const String = java.import("java.lang.String"); + expect(String).toBeTruthy(); + + const api = Object.keys(String).filter((key) => typeof String[key] === "function"); + expect(api.includes("formatSync"), "Expected `formatSync` to be present, but it is NOT.").toBeTruthy(); + expect(api.includes("formatPromise"), "Expected `formatPromise` to be present, but it is NOT.").toBeTruthy(); + expect(api.includes("format"), "Expected `format` to NOT be present, but it is.").toBeFalsy(); + expect(api.includes("formatAsync"), "Expected `formatAsync` to NOT be present, but it is.").toBeFalsy(); + expect(api.includes("formatundefined"), "Expected `formatundefined` to NOT be present, but it is.").toBeFalsy(); + }); + + test("syncCalls", () => { + const arrayList = java.newInstanceSync("java.util.ArrayList"); + arrayList.addSync("hello"); + arrayList.addSync("world"); + expect(arrayList.sizeSync()).toBe(2); + }); + + test("sStaticSyncCalls", () => { + // Note: java.import executes javascript code in src-node/nodeJavaBridge that makes sync calls to java classes. + // Among other things, java.import creates Sync functions for static methods. + const String = java.import("java.lang.String"); + expect(String.formatSync("%s--%s", "hello", "world")).toBe("hello--world"); + }); + + test("promiseCalls", async () => { + const arrayList = java.newInstanceSync("java.util.ArrayList"); + await new Promise((resolve) => { + arrayList + .addPromise("hello") + .then(() => { + return arrayList.addPromise("world"); + }) + .then(() => { + return arrayList.sizePromise(); + }) + .then((size: number) => { + expect(size).toBe(2); + resolve(); + }); + }); + }); +}); diff --git a/testAsyncOptions/syncDefaultPlusPromise.test.ts b/testAsyncOptions/syncDefaultPlusPromise.test.ts new file mode 100644 index 00000000..21e214ff --- /dev/null +++ b/testAsyncOptions/syncDefaultPlusPromise.test.ts @@ -0,0 +1,82 @@ +// Just Sync and Promise, with Sync the default (i.e. no suffix). +// This is the configuration that RedSeal wants for use with Tinkerpop/Gremlin. + +import { beforeAll, describe, expect, test } from "vitest"; +import { getJava } from "../testHelpers"; +import { Java } from "../java"; + +describe("syncDefaultPlusPromise", () => { + let java!: Java; + + beforeAll(async () => { + java = await getJava({ + syncSuffix: "", + promiseSuffix: "P", + }); + }); + + test("api", () => { + const arrayList = java.newInstanceSync("java.util.ArrayList"); + expect(arrayList).toBeTruthy(); + expect(java.instanceOf(arrayList, "java.util.ArrayList")).toBeTruthy(); + + expect(typeof arrayList.add !== "undefined", "Expected `add` to be present, but it is NOT.").toBeTruthy(); + expect(typeof arrayList.addP !== "undefined", "Expected `addP` to be present, but it is NOT.").toBeTruthy(); + expect(typeof arrayList.addSync === "undefined", "Expected `addSync` to NOT be present, but it is.").toBeTruthy(); + expect(typeof arrayList.addAsync === "undefined", "Expected `addAsync` to NOT be present, but it is.").toBeTruthy(); + }); + + test("importClass", () => { + // Note: java.import executes javascript code in src-node/nodeJavaBridge that makes sync calls to java classes. + // This test verifies the import runs without error. + const ArrayList = java.import("java.util.ArrayList"); + expect(ArrayList).toBeTruthy(); + const arrayList = new ArrayList(); + expect(arrayList).toBeTruthy(); + expect(arrayList.size()).toBe(0); + }); + + test("staticAPI", () => { + const String = java.import("java.lang.String"); + expect(String).toBeTruthy(); + + const api = Object.keys(String).filter((key) => typeof String[key] === "function"); + expect(api.includes("format"), "Expected `format` to be present, but it is NOT.").toBeTruthy(); + expect(api.includes("formatP"), "Expected `formatP` to be present, but it is NOT.").toBeTruthy(); + expect(api.includes("formatSync"), "Expected `formatSync` to NOT be present, but it is.").toBeFalsy(); + expect(api.includes("formatAsync"), "Expected `formatAsync` to NOT be present, but it is.").toBeFalsy(); + expect(api.includes("formatundefined"), "Expected `formatundefined` to NOT be present, but it is.").toBeFalsy(); + }); + + test("syncCalls", () => { + const arrayList = java.newInstanceSync("java.util.ArrayList"); + arrayList.add("hello"); + arrayList.add("world"); + expect(arrayList.size()).toBe(2); + }); + + test("staticSyncCalls", () => { + // Note: java.import executes javascript code in src-node/nodeJavaBridge that makes sync calls to java classes. + // Among other things, java.import creates Sync functions for static methods. + const String = java.import("java.lang.String"); + expect(String.format("%s--%s", "hello", "world")).toBe("hello--world"); + }); + + test("promiseCalls", async () => { + const arrayList = java.newInstanceSync("java.util.ArrayList"); + await new Promise((resolve) => { + arrayList + .addP("hello") + .then(() => { + return arrayList.addP("world"); + }) + .then(() => { + return arrayList.sizeP(); + }) + .then((size: number) => { + expect(size).toBe(2); + resolve(); + }); + }); + }); +}); diff --git a/testAsyncOptions/testAllThreeSuffix.js b/testAsyncOptions/testAllThreeSuffix.js deleted file mode 100644 index 7f610ce5..00000000 --- a/testAsyncOptions/testAllThreeSuffix.js +++ /dev/null @@ -1,99 +0,0 @@ -// testAllThreeSuffix.js - -// All three variants have non-empty suffix, i.e a suffix is required for any variant. - -var java = require("../"); -var assert = require("assert"); - -java.asyncOptions = { - syncSuffix: "Sync", - asyncSuffix: "Async", - promiseSuffix: 'Promise', - promisify: require('when/node').lift // https://github.com/cujojs/when -}; - -module.exports = { - testAPI: function(test) { - test.expect(6); - var arrayList = java.newInstanceSync("java.util.ArrayList"); - test.ok(arrayList); - test.ok(java.instanceOf(arrayList, "java.util.ArrayList")); - - test.ok(typeof arrayList.addSync !== 'undefined', 'Expected `addSync` to be present, but it is NOT.'); - test.ok(typeof arrayList.addAsync !== 'undefined', 'Expected `addAsync` to be present, but it is NOT.'); - test.ok(typeof arrayList.addPromise !== 'undefined', 'Expected `addPromise` to be present, but it is NOT.'); - test.ok(typeof arrayList.add === 'undefined', 'Expected `add` to NOT be present, but it is.'); - test.done(); - }, - - testImportClass: function(test) { - test.expect(3); - // Note: java.import executes javascript code in lib/nodeJavaBridge that makes sync calls to java classes. - var ArrayList = java.import("java.util.ArrayList"); - test.ok(ArrayList); - var arrayList = new ArrayList(); - test.ok(arrayList); - test.strictEqual(arrayList.sizeSync(), 0); - test.done(); - }, - - testStaticAPI: function(test) { - test.expect(6); - var String = java.import("java.lang.String"); - test.ok(String); - - var api = Object.keys(String).filter((key) => typeof String[key] === 'function'); - test.ok(api.includes('formatSync'), 'Expected `formatSync` to be present, but it is NOT.'); - test.ok(api.includes('formatAsync'), 'Expected `formatAsync` to be present, but it is NOT.'); - test.ok(api.includes('formatPromise'), 'Expected `formatPromise` to be present, but it is NOT.'); - test.ok(!api.includes('format'), 'Expected `format` to NOT be present, but it is.'); - test.ok(!api.includes('formatundefined'), 'Expected `formatundefined` to NOT be present, but it is.'); - test.done(); - }, - - testSyncCalls: function(test) { - test.expect(1); - var arrayList = java.newInstanceSync("java.util.ArrayList"); - arrayList.addSync("hello"); - arrayList.addSync("world"); - test.strictEqual(arrayList.sizeSync(), 2); - test.done(); - }, - - testStaticSyncCalls: function(test) { - test.expect(1); - // Note: java.import executes javascript code in lib/nodeJavaBridge that makes sync calls to java classes. - // Among other things, java.import creates Sync functions for static methods. - var String = java.import("java.lang.String"); - test.strictEqual(String.formatSync('%s--%s', "hello", "world"), "hello--world"); - test.done(); - }, - - testAsyncCalls: function(test) { - test.expect(4); - var arrayList = java.newInstanceSync("java.util.ArrayList"); - arrayList.addAsync("hello", function(err, result) { - test.ifError(err); - arrayList.addAsync("world", function(err, result) { - test.ifError(err); - arrayList.sizeAsync(function(err, size) { - test.ifError(err); - test.strictEqual(size, 2); - test.done(); - }); - }); - }); - }, - - testPromiseCalls: function(test) { - test.expect(1); - var arrayList = java.newInstanceSync("java.util.ArrayList"); - arrayList.addPromise("hello") - .then(function () { return arrayList.addPromise("world"); }) - .then(function () { return arrayList.sizePromise(); }) - .then(function (size) { - test.strictEqual(size, 2); - test.done(); - }); - } -} diff --git a/testAsyncOptions/testAsyncSuffixSyncDefault.js b/testAsyncOptions/testAsyncSuffixSyncDefault.js deleted file mode 100644 index 784b54ba..00000000 --- a/testAsyncOptions/testAsyncSuffixSyncDefault.js +++ /dev/null @@ -1,160 +0,0 @@ -// testAsyncSuffixSyncDefault.js - -// Use "Async" for the asyncSuffix, and "" for the syncSuffix. - -var java = require("../"); -var assert = require("assert"); - -module.exports = { - launch: function(test) { - test.expect(4); - java.asyncOptions = { - syncSuffix: "", - asyncSuffix: "Async", - ifReadOnlySuffix: "_alt" - }; - - function before(callback) { - java.classpath.push('test/'); - test.ok(!java.isJvmCreated()); - callback(); - } - - function after(callback) { - test.ok(java.isJvmCreated()); - callback(); - } - - java.registerClient(before, after); - - java.ensureJvm(function(err) { - test.ifError(err); - test.ok(java.isJvmCreated()); - test.done(); - }); - }, - - testAPI: function(test) { - test.expect(5); - var arrayList = java.newInstanceSync("java.util.ArrayList"); - test.ok(arrayList); - test.ok(java.instanceOf(arrayList, "java.util.ArrayList")); - - test.ok(typeof arrayList.addAsync !== 'undefined', 'Expected `addAsync` to be present, but it is NOT.'); - test.ok(typeof arrayList.add !== 'undefined', 'Expected `add` to be present, but it is NOT.'); - test.ok(typeof arrayList.addPromise === 'undefined', 'Expected `addPromise` to NOT be present, but it is.'); - test.done(); - }, - - testImportClass: function(test) { - test.expect(3); - // Note: java.import executes javascript code in lib/nodeJavaBridge that makes sync calls to java classes. - var ArrayList = java.import("java.util.ArrayList"); - test.ok(ArrayList); - var arrayList = new ArrayList(); - test.ok(arrayList); - test.strictEqual(arrayList.size(), 0); - test.done(); - }, - - testStaticAPI: function(test) { - test.expect(6); - var String = java.import("java.lang.String"); - test.ok(String); - - var api = Object.keys(String).filter((key) => typeof String[key] === 'function'); - test.ok(api.includes('format'), 'Expected `format` to be present, but it is NOT.'); - test.ok(api.includes('formatAsync'), 'Expected `formatAsync` to be present, but it is NOT.'); - test.ok(!api.includes('formatSync'), 'Expected `formatSync` to NOT be present, but it is.'); - test.ok(!api.includes('formatPromise'), 'Expected `formatPromise` to NOT be present, but it is.'); - test.ok(!api.includes('formatundefined'), 'Expected `formatundefined` to NOT be present, but it is.'); - test.done(); - }, - - testSyncCalls: function(test) { - test.expect(1); - var arrayList = java.newInstanceSync("java.util.ArrayList"); - arrayList.add("hello"); - arrayList.add("world"); - test.strictEqual(arrayList.size(), 2); - test.done(); - }, - - testStaticSyncCalls: function(test) { - test.expect(1); - // Note: java.import executes javascript code in lib/nodeJavaBridge that makes sync calls to java classes. - // Among other things, java.import creates Sync functions for static methods. - var String = java.import("java.lang.String"); - test.strictEqual(String.format('%s--%s', "hello", "world"), "hello--world"); - test.done(); - }, - - testAsyncCalls: function(test) { - test.expect(4); - var arrayList = java.newInstanceSync("java.util.ArrayList"); - arrayList.addAsync("hello", function(err, result) { - test.ifError(err); - arrayList.addAsync("world", function(err, result) { - test.ifError(err); - arrayList.sizeAsync(function(err, size) { - test.ifError(err); - test.strictEqual(size, 2); - test.done(); - }); - }); - }); - }, - - // See testUnusableMethodName.js for the purpose of these last two tests. - // In that test, Test.name_alt() is an async method. - // In this test, it is a sync method. - testUnusableMethodNameThrows: function(test) { - test.expect(1); - var Test = java.import("Test"); - test.ok(Test); - test.throws( - function() { - Test.name(); - }, - function(err) { - if (err instanceof TypeError) { - test.done(); - return true; - } else { - test.done(err); - return false; - } - } - ); - }, - - testAlternateMethodNameWorks: function(test) { - test.expect(4); - var Test = java.import("Test"); - test.ok(Test); - test.strictEqual(Test.name_alt(), "name"); - test.strictEqual(Test.caller_alt(), "caller"); - test.strictEqual(Test.arguments_alt(), "arguments"); - test.done(); - }, - - testReservedFieldName: function(test) { - test.expect(7); - var TestEnum = java.import("Test$Enum"); - test.ok(TestEnum); - - // 'foo' and 'bar' are valid enum names - test.strictEqual(TestEnum.foo.toString(), "foo"); - test.strictEqual(TestEnum.bar.toString(), "bar"); - - // TestEnum.name is actually the name of the proxy constructor function. - test.strictEqual(TestEnum.name, "javaClassConstructorProxy"); - - // Instead we need to acccess TestEnum.name_alt - test.strictEqual(TestEnum.name_alt.toString(), "name"); - test.strictEqual(TestEnum.caller_alt.toString(), "caller"); - test.strictEqual(TestEnum.arguments_alt.toString(), "arguments"); - - test.done(); - }, -} diff --git a/testAsyncOptions/testClientBeforeError.js b/testAsyncOptions/testClientBeforeError.js deleted file mode 100644 index cd3011ab..00000000 --- a/testAsyncOptions/testClientBeforeError.js +++ /dev/null @@ -1,32 +0,0 @@ -// testClientBeforeError.js - -var java = require("../"); -var nodeunit = require("nodeunit"); - -module.exports = { - - clientBeforeError: function(test) { - test.expect(6); - test.ok(!java.isJvmCreated()); - - java.asyncOptions = { - syncSuffix: "Sync", - }; - - function before(callback) { - test.ok(!java.isJvmCreated()); - callback(new Error('dummy error')); - } - - java.registerClient(before); - - java.ensureJvm(function(err) { - test.ok(err && typeof err === 'object'); - test.ok(err instanceof Error); - test.strictEqual(err.message, 'dummy error'); - test.ok(!java.isJvmCreated()); - test.done(); - }); - } - -} diff --git a/testAsyncOptions/testClientBeforeSyncThrows.js b/testAsyncOptions/testClientBeforeSyncThrows.js deleted file mode 100644 index 8d5d4bab..00000000 --- a/testAsyncOptions/testClientBeforeSyncThrows.js +++ /dev/null @@ -1,32 +0,0 @@ -// testClientBeforeSyncThrows.js - -var java = require("../"); -var nodeunit = require("nodeunit"); - -module.exports = { - - clientBeforeSyncThrows: function(test) { - test.expect(6); - test.ok(!java.isJvmCreated()); - - java.asyncOptions = { - syncSuffix: "Sync", - }; - - function before() { - test.ok(!java.isJvmCreated()); - throw new Error('dummy error'); - } - - java.registerClient(before); - - java.ensureJvm(function(err) { - test.ok(err && typeof err === 'object'); - test.ok(err instanceof Error); - test.strictEqual(err.message, 'dummy error'); - test.ok(!java.isJvmCreated()); - test.done(); - }); - } - -} diff --git a/testAsyncOptions/testClientBeforeThrows.js b/testAsyncOptions/testClientBeforeThrows.js deleted file mode 100644 index 79614aa2..00000000 --- a/testAsyncOptions/testClientBeforeThrows.js +++ /dev/null @@ -1,32 +0,0 @@ -// testClientBeforeThrows.js - -var java = require("../"); -var nodeunit = require("nodeunit"); - -module.exports = { - - clientBeforeThrows: function(test) { - test.expect(6); - test.ok(!java.isJvmCreated()); - - java.asyncOptions = { - syncSuffix: "Sync", - }; - - function before(callback) { - test.ok(!java.isJvmCreated()); - throw new Error('dummy error'); - } - - java.registerClient(before); - - java.ensureJvm(function(err) { - test.ok(err && typeof err === 'object'); - test.ok(err instanceof Error); - test.strictEqual(err.message, 'dummy error'); - test.ok(!java.isJvmCreated()); - test.done(); - }); - } - -} diff --git a/testAsyncOptions/testClientPBeforeError.js b/testAsyncOptions/testClientPBeforeError.js deleted file mode 100644 index 33a02f26..00000000 --- a/testAsyncOptions/testClientPBeforeError.js +++ /dev/null @@ -1,43 +0,0 @@ -// testClientPBeforeError.js - -var java = require("../"); -var nodeunit = require("nodeunit"); -var when = require('when'); - -module.exports = { - - clientPBeforeError: function(test) { - test.expect(6); - test.ok(!java.isJvmCreated()); - - java.asyncOptions = { - syncSuffix: "Sync", - promiseSuffix: 'Promise', - promisify: require('when/node').lift // https://github.com/cujojs/when - }; - - function beforeP() { - var promise = when.promise(function(resolve, reject) { - test.ok(!java.isJvmCreated()); - reject(new Error('dummy error')); - }); - return promise; - } - - java.registerClientP(beforeP); - - java.ensureJvm().done( - function () { - test.ok(false); - }, - function(err) { - test.ok(err && typeof err === 'object'); - test.ok(err instanceof Error); - test.strictEqual(err.message, 'dummy error'); - test.ok(!java.isJvmCreated()); - test.done(); - } - ); - } - -} diff --git a/testAsyncOptions/testClientPBeforeThrows.js b/testAsyncOptions/testClientPBeforeThrows.js deleted file mode 100644 index 5d58dab5..00000000 --- a/testAsyncOptions/testClientPBeforeThrows.js +++ /dev/null @@ -1,43 +0,0 @@ -// testClientPBeforeThrows.js - -var java = require("../"); -var nodeunit = require("nodeunit"); -var when = require('when'); - -module.exports = { - - clientPBeforeThrows: function(test) { - test.expect(6); - test.ok(!java.isJvmCreated()); - - java.asyncOptions = { - syncSuffix: "Sync", - promiseSuffix: 'Promise', - promisify: require('when/node').lift // https://github.com/cujojs/when - }; - - function beforeP() { - var promise = when.promise(function(resolve, reject) { - test.ok(!java.isJvmCreated()); - throw new Error('dummy error'); - }); - return promise; - } - - java.registerClientP(beforeP); - - java.ensureJvm().done( - function () { - test.ok(false); - }, - function(err) { - test.ok(err && typeof err === 'object'); - test.ok(err instanceof Error); - test.strictEqual(err.message, 'dummy error'); - test.ok(!java.isJvmCreated()); - test.done(); - } - ); - } - -} diff --git a/testAsyncOptions/testDefacto.js b/testAsyncOptions/testDefacto.js deleted file mode 100644 index 314a8ebd..00000000 --- a/testAsyncOptions/testDefacto.js +++ /dev/null @@ -1,115 +0,0 @@ -// testDefacto.js - -// In the defacto case, the developer sets asyncOptions, but specifies the defacto standard behavior. - -var java = require("../"); -var nodeunit = require("nodeunit"); - -module.exports = { - - launch: function(test) { - test.expect(9); - var api = Object.keys(java).filter((key) => typeof java[key] === 'function'); - test.ok(api.includes('isJvmCreated'), 'Expected `isJvmCreated` to be present, but it is NOT.'); - test.ok(!java.isJvmCreated()); - - java.asyncOptions = { - syncSuffix: "Sync", - asyncSuffix: "" - }; - - function before() { - test.ok(!java.isJvmCreated()); - } - - function after() { - test.ok(java.isJvmCreated()); - } - - java.registerClient(before, after); - java.registerClient(undefined, after); - java.registerClient(before, undefined); - - java.ensureJvm(function(err) { - test.ifError(err); - test.ok(java.isJvmCreated()); - - // Verify that ensureJvm is idempotent - java.ensureJvm(function(err) { - test.ifError(err); - test.done(); - }); - }); - }, - - testAPI: function(test) { - test.expect(5); - var arrayList = java.newInstanceSync("java.util.ArrayList"); - test.ok(arrayList); - test.ok(java.instanceOf(arrayList, "java.util.ArrayList")); - - test.ok(typeof arrayList.addSync !== 'undefined', 'Expected `addSync` to be present, but it is NOT.'); - test.ok(typeof arrayList.add !== 'undefined', 'Expected `add` to be present, but it is NOT.'); - test.ok(typeof arrayList.addPromise === 'undefined', 'Expected `addPromise` to NOT be present, but it is.'); - test.done(); - }, - - testImportClass: function(test) { - test.expect(3); - // Note: java.import executes javascript code in lib/nodeJavaBridge that makes sync calls to java classes. - var ArrayList = java.import("java.util.ArrayList"); - test.ok(ArrayList); - var arrayList = new ArrayList(); - test.ok(arrayList); - test.strictEqual(arrayList.sizeSync(), 0); - test.done(); - }, - - testStaticAPI: function(test) { - test.expect(6); - var String = java.import("java.lang.String"); - test.ok(String); - - var api = Object.keys(String).filter((key) => typeof String[key] === 'function'); - test.ok(api.includes('format'), 'Expected `format` to be present, but it is NOT.'); - test.ok(api.includes('formatSync'), 'Expected `formatSync` to be present, but it is NOT.'); - test.ok(!api.includes('formatAsync'), 'Expected `formatAsync` to NOT be present, but it is.'); - test.ok(!api.includes('formatPromise'), 'Expected `formatPromise` to NOT be present, but it is.'); - test.ok(!api.includes('formatundefined'), 'Expected `formatundefined` to NOT be present, but it is.'); - test.done(); - }, - - testSyncCalls: function(test) { - test.expect(1); - var arrayList = java.newInstanceSync("java.util.ArrayList"); - arrayList.addSync("hello"); - arrayList.addSync("world"); - test.strictEqual(arrayList.sizeSync(), 2); - test.done(); - }, - - testStaticSyncCalls: function(test) { - test.expect(1); - // Note: java.import executes javascript code in lib/nodeJavaBridge that makes sync calls to java classes. - // Among other things, java.import creates Sync functions for static methods. - var String = java.import("java.lang.String"); - test.strictEqual(String.formatSync('%s--%s', "hello", "world"), "hello--world"); - test.done(); - }, - - testAsyncCalls: function(test) { - test.expect(4); - var arrayList = java.newInstanceSync("java.util.ArrayList"); - arrayList.add("hello", function(err, result) { - test.ifError(err); - arrayList.add("world", function(err, result) { - test.ifError(err); - arrayList.size(function(err, size) { - test.ifError(err); - test.strictEqual(size, 2); - test.done(); - }); - }); - }); - } -} diff --git a/testAsyncOptions/testDefactoPlusPromise.js b/testAsyncOptions/testDefactoPlusPromise.js deleted file mode 100644 index 730c889d..00000000 --- a/testAsyncOptions/testDefactoPlusPromise.js +++ /dev/null @@ -1,124 +0,0 @@ -// testDefactoPlusPromise.js - -// The defacto case but with promises also enabled. - -var java = require("../"); -var assert = require("assert"); - -module.exports = { - launch: function(test) { - test.expect(7); - var api = Object.keys(java).filter((key) => typeof java[key] === 'function'); - test.ok(api.includes('isJvmCreated'), 'Expected `isJvmCreated` to be present, but it is NOT.'); - test.ok(!java.isJvmCreated()); - - java.asyncOptions = { - syncSuffix: "Sync", - asyncSuffix: "", - promiseSuffix: 'Promise', - promisify: require('when/node').lift // https://github.com/cujojs/when - }; - - function before(callback) { - test.ok(!java.isJvmCreated()); - callback(); - } - - function after(callback) { - test.ok(java.isJvmCreated()); - callback(); - } - - java.registerClient(before, after); - java.registerClient(null, after); - java.registerClient(before); - - java.ensureJvm().done(function() { - test.ok(java.isJvmCreated()); - test.done(); - }); - }, - - testAPI: function(test) { - test.expect(5); - var arrayList = java.newInstanceSync("java.util.ArrayList"); - test.ok(arrayList); - test.ok(java.instanceOf(arrayList, "java.util.ArrayList")); - - test.ok(arrayList.addSync !== 'undefined', 'Expected `addSync` to be present, but it is NOT.'); - test.ok(arrayList.add !== 'undefined', 'Expected `add` to be present, but it is NOT.'); - test.ok(arrayList.addPromise !== 'undefined', 'Expected `addPromise` to be present, but it is NOT.'); - test.done(); - }, - - testImportClass: function(test) { - test.expect(3); - // Note: java.import executes javascript code in lib/nodeJavaBridge that makes sync calls to java classes. - var ArrayList = java.import("java.util.ArrayList"); - test.ok(ArrayList); - var arrayList = new ArrayList(); - test.ok(arrayList); - test.strictEqual(arrayList.sizeSync(), 0); - test.done(); - }, - - testStaticAPI: function(test) { - test.expect(6); - var String = java.import("java.lang.String"); - test.ok(String); - - var api = Object.keys(String).filter((key) => typeof String[key] === 'function'); - test.ok(api.includes('format'), 'Expected `format` to be present, but it is NOT.'); - test.ok(api.includes('formatSync'), 'Expected `formatSync` to be present, but it is NOT.'); - test.ok(api.includes('formatPromise'), 'Expected `formatPromise` to be present, but it is NOT.'); - test.ok(!api.includes('formatAsync'), 'Expected `formatAsync` to NOT be present, but it is.'); - test.ok(!api.includes('formatundefined'), 'Expected `formatundefined` to NOT be present, but it is.'); - test.done(); - }, - - testSyncCalls: function(test) { - test.expect(1); - var arrayList = java.newInstanceSync("java.util.ArrayList"); - arrayList.addSync("hello"); - arrayList.addSync("world"); - test.strictEqual(arrayList.sizeSync(), 2); - test.done(); - }, - - testStaticSyncCalls: function(test) { - test.expect(1); - // Note: java.import executes javascript code in lib/nodeJavaBridge that makes sync calls to java classes. - // Among other things, java.import creates Sync functions for static methods. - var String = java.import("java.lang.String"); - test.strictEqual(String.formatSync('%s--%s', "hello", "world"), "hello--world"); - test.done(); - }, - - testAsyncCalls: function(test) { - test.expect(4); - var arrayList = java.newInstanceSync("java.util.ArrayList"); - arrayList.add("hello", function(err, result) { - test.ifError(err); - arrayList.add("world", function(err, result) { - test.ifError(err); - arrayList.size(function(err, size) { - test.ifError(err); - test.strictEqual(size, 2); - test.done(); - }); - }); - }); - }, - - testPromiseCalls: function(test) { - test.expect(1); - var arrayList = java.newInstanceSync("java.util.ArrayList"); - arrayList.addPromise("hello") - .then(function () { return arrayList.addPromise("world"); }) - .then(function () { return arrayList.sizePromise(); }) - .then(function (size) { - test.strictEqual(size, 2); - test.done(); - }); - } -} diff --git a/testAsyncOptions/testDefault.js b/testAsyncOptions/testDefault.js deleted file mode 100644 index e58a773f..00000000 --- a/testAsyncOptions/testDefault.js +++ /dev/null @@ -1,82 +0,0 @@ -// testDefault.js - -// In the default case, the developer does not set asyncOptions. -// We should get the defacto standard behavior. - -var java = require("../"); -var nodeunit = require("nodeunit"); - -java.asyncOptions = undefined; - -module.exports = { - testAPI: function(test) { - test.expect(5); - var arrayList = java.newInstanceSync("java.util.ArrayList"); - test.ok(arrayList); - test.ok(java.instanceOf(arrayList, "java.util.ArrayList")); - - test.ok(typeof arrayList.addSync !== 'undefined', 'Expected `addSync` to be present, but it is NOT.'); - test.ok(typeof arrayList.add !== 'undefined', 'Expected `add` to be present, but it is NOT.'); - test.ok(typeof arrayList.addPromise === 'undefined', 'Expected `addPromise` to NOT be present, but it is.'); - test.done(); - }, - - testImportClass: function(test) { - test.expect(3); - // Note: java.import executes javascript code in lib/nodeJavaBridge that makes sync calls to java classes. - var ArrayList = java.import("java.util.ArrayList"); - test.ok(ArrayList); - var arrayList = new ArrayList(); - test.ok(arrayList); - test.strictEqual(arrayList.sizeSync(), 0); - test.done(); - }, - - testStaticAPI: function(test) { - test.expect(6); - var String = java.import("java.lang.String"); - test.ok(String); - - var api = Object.keys(String).filter((key) => typeof String[key] === 'function'); - test.ok(api.includes('format'), 'Expected `format` to be present, but it is NOT.'); - test.ok(api.includes('formatSync'), 'Expected `formatSync` to be present, but it is NOT.'); - test.ok(!api.includes('formatAsync'), 'Expected `formatAsync` to NOT be present, but it is.'); - test.ok(!api.includes('formatPromise'), 'Expected `formatPromise` to NOT be present, but it is.'); - test.ok(!api.includes('formatundefined'), 'Expected `formatundefined` to NOT be present, but it is.'); - test.done(); - }, - - testSyncCalls: function(test) { - test.expect(1); - var arrayList = java.newInstanceSync("java.util.ArrayList"); - arrayList.addSync("hello"); - arrayList.addSync("world"); - test.strictEqual(arrayList.sizeSync(), 2); - test.done(); - }, - - testStaticSyncCalls: function(test) { - test.expect(1); - // Note: java.import executes javascript code in lib/nodeJavaBridge that makes sync calls to java classes. - // Among other things, java.import creates Sync functions for static methods. - var String = java.import("java.lang.String"); - test.strictEqual(String.formatSync('%s--%s', "hello", "world"), "hello--world"); - test.done(); - }, - - testAsyncCalls: function(test) { - test.expect(4); - var arrayList = java.newInstanceSync("java.util.ArrayList"); - arrayList.add("hello", function(err, result) { - test.ifError(err); - arrayList.add("world", function(err, result) { - test.ifError(err); - arrayList.size(function(err, size) { - test.ifError(err); - test.strictEqual(size, 2); - test.done(); - }); - }); - }); - } -} diff --git a/testAsyncOptions/testInvalidLaunch.js b/testAsyncOptions/testInvalidLaunch.js deleted file mode 100644 index 21c1bf33..00000000 --- a/testAsyncOptions/testInvalidLaunch.js +++ /dev/null @@ -1,58 +0,0 @@ -// testInvalidLaunch.js - -var java = require("../"); -var nodeunit = require("nodeunit"); - -module.exports = { - - failedLaunch: function(test) { - test.expect(3); - test.ok(!java.isJvmCreated()); - - java.asyncOptions = { - syncSuffix: "Sync", - asyncSuffix: "" - }; - - // First show that if asyncOptions.promisify is undefined, using the promise variant of ensureJvm throws an error. - test.throws(function() { java.ensureJvm(); }, Error, /requires its one argument to be a callback function/); - - test.ok(!java.isJvmCreated()); - test.done(); - }, - - callbackNotAFunction: function(test) { - test.expect(3); - test.ok(!java.isJvmCreated()); - - java.asyncOptions = { - syncSuffix: "", - promiseSuffix: 'P', - promisify: require('when/node').lift // https://github.com/cujojs/when - }; - - test.throws(function() { java.ensureJvm('foo'); }, Error, /requires its one argument to be a callback function/); - - test.ok(!java.isJvmCreated()); - test.done(); - }, - - jvmCanStillBeLaunched: function(test) { - // None of the previous tests should have caused the JVM to be created, so it should still be possible to create one. - - test.expect(2); - test.ok(!java.isJvmCreated()); - - java.asyncOptions = { - syncSuffix: "", - promiseSuffix: 'P', - promisify: require('when/node').lift // https://github.com/cujojs/when - }; - - java.ensureJvm().done(function() { - test.ok(java.isJvmCreated()); - test.done(); - }); - } - -} diff --git a/testAsyncOptions/testNoAsync.js b/testAsyncOptions/testNoAsync.js deleted file mode 100644 index 47f596c8..00000000 --- a/testAsyncOptions/testNoAsync.js +++ /dev/null @@ -1,115 +0,0 @@ -// testNoAsync.js - -// Just Sync and Promise, both with a non-empty suffix. - -var java = require("../"); -var assert = require("assert"); -var when = require('when'); - -module.exports = { - launch: function(test) { - test.expect(7); - var api = Object.keys(java).filter((key) => typeof java[key] === 'function'); - test.ok(api.includes('isJvmCreated'), 'Expected `isJvmCreated` to be present, but it is NOT.'); - test.ok(!java.isJvmCreated()); - - java.asyncOptions = { - syncSuffix: "Sync", - promiseSuffix: 'Promise', - promisify: require('when/node').lift - }; - - function before() { - var promise = when.promise(function(resolve, reject) { - test.ok(!java.isJvmCreated()); - resolve(); - }); - return promise; - } - - function after() { - var promise = when.promise(function(resolve, reject) { - test.ok(java.isJvmCreated()); - resolve(); - }); - return promise; - } - - java.registerClientP(before, after); - java.registerClientP(null, after); - java.registerClientP(before); - - java.ensureJvm().done(function() { - test.ok(java.isJvmCreated()); - test.done(); - }); - }, - - testAPI: function(test) { - test.expect(6); - var arrayList = java.newInstanceSync("java.util.ArrayList"); - test.ok(arrayList); - test.ok(java.instanceOf(arrayList, "java.util.ArrayList")); - - test.ok(typeof arrayList.addSync !== 'undefined', 'Expected `addSync` to be present, but it is NOT.'); - test.ok(typeof arrayList.addPromise !== 'undefined', 'Expected `addPromise` to be present, but it is NOT.'); - test.ok(typeof arrayList.add === 'undefined', 'Expected `add` to NOT be present, but it is.'); - test.ok(typeof arrayList.addAsync === 'undefined', 'Expected `addAsync` to NOT be present, but it is.'); - test.done(); - }, - - testImportClass: function(test) { - test.expect(3); - // Note: java.import executes javascript code in lib/nodeJavaBridge that makes sync calls to java classes. - var ArrayList = java.import("java.util.ArrayList"); - test.ok(ArrayList); - var arrayList = new ArrayList(); - test.ok(arrayList); - test.strictEqual(arrayList.sizeSync(), 0); - test.done(); - }, - - testStaticAPI: function(test) { - test.expect(6); - var String = java.import("java.lang.String"); - test.ok(String); - - var api = Object.keys(String).filter((key) => typeof String[key] === 'function'); - test.ok(api.includes('formatSync'), 'Expected `formatSync` to be present, but it is NOT.'); - test.ok(api.includes('formatPromise'), 'Expected `formatPromise` to be present, but it is NOT.'); - test.ok(!api.includes('format'), 'Expected `format` to NOT be present, but it is.'); - test.ok(!api.includes('formatAsync'), 'Expected `formatAsync` to NOT be present, but it is.'); - test.ok(!api.includes('formatundefined'), 'Expected `formatundefined` to NOT be present, but it is.'); - test.done(); - }, - - testSyncCalls: function(test) { - test.expect(1); - var arrayList = java.newInstanceSync("java.util.ArrayList"); - arrayList.addSync("hello"); - arrayList.addSync("world"); - test.strictEqual(arrayList.sizeSync(), 2); - test.done(); - }, - - testStaticSyncCalls: function(test) { - test.expect(1); - // Note: java.import executes javascript code in lib/nodeJavaBridge that makes sync calls to java classes. - // Among other things, java.import creates Sync functions for static methods. - var String = java.import("java.lang.String"); - test.strictEqual(String.formatSync('%s--%s', "hello", "world"), "hello--world"); - test.done(); - }, - - testPromiseCalls: function(test) { - test.expect(1); - var arrayList = java.newInstanceSync("java.util.ArrayList"); - arrayList.addPromise("hello") - .then(function () { return arrayList.addPromise("world"); }) - .then(function () { return arrayList.sizePromise(); }) - .then(function (size) { - test.strictEqual(size, 2); - test.done(); - }); - } -} diff --git a/testAsyncOptions/testSyncDefaultPlusPromise.js b/testAsyncOptions/testSyncDefaultPlusPromise.js deleted file mode 100644 index 113be49c..00000000 --- a/testAsyncOptions/testSyncDefaultPlusPromise.js +++ /dev/null @@ -1,85 +0,0 @@ -// testSyncDefaultPlusPromise.js - -// Just Sync and Promise, with Sync the default (i.e. no suffix). -// This is the configuration that RedSeal wants for use with Tinkerpop/Gremlin. - -var java = require("../"); -var assert = require("assert"); - -java.asyncOptions = { - syncSuffix: "", - promiseSuffix: 'P', - promisify: require('when/node').lift // https://github.com/cujojs/when -}; - -module.exports = { - testAPI: function(test) { - test.expect(6); - var arrayList = java.newInstanceSync("java.util.ArrayList"); - test.ok(arrayList); - test.ok(java.instanceOf(arrayList, "java.util.ArrayList")); - - test.ok(typeof arrayList.add !== 'undefined', 'Expected `add` to be present, but it is NOT.'); - test.ok(typeof arrayList.addP !== 'undefined', 'Expected `addP` to be present, but it is NOT.'); - test.ok(typeof arrayList.addSync === 'undefined', 'Expected `addSync` to NOT be present, but it is.'); - test.ok(typeof arrayList.addAsync === 'undefined', 'Expected `addAsync` to NOT be present, but it is.'); - test.done(); - }, - - testImportClass: function(test) { - test.expect(3); - // Note: java.import executes javascript code in lib/nodeJavaBridge that makes sync calls to java classes. - // This test verifies the import runs without error. - var ArrayList = java.import("java.util.ArrayList"); - test.ok(ArrayList); - var arrayList = new ArrayList(); - test.ok(arrayList); - test.strictEqual(arrayList.size(), 0); - test.done(); - }, - - testStaticAPI: function(test) { - test.expect(6); - var String = java.import("java.lang.String"); - test.ok(String); - - var api = Object.keys(String).filter((key) => typeof String[key] === 'function'); - test.ok(api.includes('format'), 'Expected `format` to be present, but it is NOT.'); - test.ok(api.includes('formatP'), 'Expected `formatP` to be present, but it is NOT.'); - test.ok(!api.includes('formatSync'), 'Expected `formatSync` to NOT be present, but it is.'); - test.ok(!api.includes('formatAsync'), 'Expected `formatAsync` to NOT be present, but it is.'); - test.ok(!api.includes('formatundefined'), 'Expected `formatundefined` to NOT be present, but it is.'); - test.done(); - }, - - testSyncCalls: function(test) { - test.expect(1); - var arrayList = java.newInstanceSync("java.util.ArrayList"); - arrayList.add("hello"); - arrayList.add("world"); - test.strictEqual(arrayList.size(), 2); - test.done(); - }, - - testStaticSyncCalls: function(test) { - test.expect(1); - // Note: java.import executes javascript code in lib/nodeJavaBridge that makes sync calls to java classes. - // Among other things, java.import creates Sync functions for static methods. - var String = java.import("java.lang.String"); - test.strictEqual(String.format('%s--%s', "hello", "world"), "hello--world"); - test.done(); - }, - - testPromiseCalls: function(test) { - test.expect(1); - var arrayList = java.newInstanceSync("java.util.ArrayList"); - arrayList.addP("hello") - .then(function () { return arrayList.addP("world"); }) - .then(function () { return arrayList.sizeP(); }) - .then(function (size) { - test.strictEqual(size, 2); - test.done(); - }); - } - -} diff --git a/testAsyncOptions/testUnusableMethodName.js b/testAsyncOptions/testUnusableMethodName.js deleted file mode 100644 index 1da67e4b..00000000 --- a/testAsyncOptions/testUnusableMethodName.js +++ /dev/null @@ -1,161 +0,0 @@ -// testUnusableMethodName.js - -// For any function, the property 'name' is an unwritable property. -// The value returned by java.import() is a constructor-like function that has the shape of the class. -// In particular, any static methods of the class will be added as properties of the function. -// If a class has a static method named 'name', then an exception woudld be thrown when -// node-java attempts to set assign the static method to the .name property of constructor-like function. -// As a workaround, node-java will append the `ifReadOnlySuffix` to the property name. - -var java = require("../"); -var nodeunit = require("nodeunit"); - -module.exports = { - - launch: function(test) { - test.expect(4); - java.asyncOptions = { - syncSuffix: "Sync", - asyncSuffix: "", - ifReadOnlySuffix: "_alt" - }; - - function before(callback) { - java.classpath.push('test/'); - test.ok(!java.isJvmCreated()); - callback(); - } - - function after(callback) { - test.ok(java.isJvmCreated()); - callback(); - } - - java.registerClient(before, after); - - java.ensureJvm(function(err) { - test.ifError(err); - test.ok(java.isJvmCreated()); - test.done(); - }); - }, - - testUnusableMethodName_nameThrows: function(test) { - test.expect(1); - var Test = java.import("Test"); - test.ok(Test); - test.throws( - function() { - Test.name(function(err) { - test.fail(); // should not get here - }); - }, - function(err) { - if (err instanceof TypeError) { - test.done(); - return true; - } else { - test.done(err); - return false; - } - } - ); - }, - - testUnusableMethodName_callerThrows: function(test) { - test.expect(1); - var Test = java.import("Test"); - test.ok(Test); - test.throws( - function() { - Test.caller(function(err) { - test.fail(); // should not get here - }); - }, - function(err) { - if (err instanceof TypeError) { - test.done(); - return true; - } else { - test.done(err); - return false; - } - } - ); - }, - - testUnusableMethodName_argumentsThrows: function(test) { - test.expect(1); - var Test = java.import("Test"); - test.ok(Test); - test.throws( - function() { - Test.arguments(function(err) { - test.fail(); // should not get here - }); - }, - function(err) { - if (err instanceof TypeError) { - test.done(); - return true; - } else { - test.done(err); - return false; - } - } - ); - }, - - testAlternateMethodName_name_altWorks: function(test) { - test.expect(3); - var Test = java.import("Test"); - test.ok(Test); - Test.name_alt(function(err, val) { - test.ifError(err); - test.strictEqual(val, "name"); - test.done(); - }); - }, - - testAlternateMethodName_caller_altWorks: function(test) { - test.expect(3); - var Test = java.import("Test"); - test.ok(Test); - Test.caller_alt(function(err, val) { - test.ifError(err); - test.strictEqual(val, "caller"); - test.done(); - }); - }, - - testAlternateMethodName_arguments_altWorks: function(test) { - test.expect(3); - var Test = java.import("Test"); - test.ok(Test); - Test.arguments_alt(function(err, val) { - test.ifError(err); - test.strictEqual(val, "arguments"); - test.done(); - }); - }, - - testReservedFieldName: function(test) { - test.expect(7); - var TestEnum = java.import("Test$Enum"); - test.ok(TestEnum); - - // 'foo' and 'bar' are valid enum names - test.strictEqual(TestEnum.foo.toStringSync(), "foo"); - test.strictEqual(TestEnum.bar.toStringSync(), "bar"); - - // TestEnum.name is actually the name of the proxy constructor function. - test.strictEqual(TestEnum.name, "javaClassConstructorProxy"); - - // Instead we need to acccess TestEnum.name_alt - test.strictEqual(TestEnum.name_alt.toString(), "name"); - test.strictEqual(TestEnum.caller_alt.toString(), "caller"); - test.strictEqual(TestEnum.arguments_alt.toString(), "arguments"); - - test.done(); - }, -} diff --git a/testAsyncOptions/unusableMethodName.test.ts b/testAsyncOptions/unusableMethodName.test.ts new file mode 100644 index 00000000..66232bab --- /dev/null +++ b/testAsyncOptions/unusableMethodName.test.ts @@ -0,0 +1,131 @@ +// For any function, the property 'name' is an unwritable property. +// The value returned by java.import() is a constructor-like function that has the shape of the class. +// In particular, any static methods of the class will be added as properties of the function. +// If a class has a static method named 'name', then an exception woudld be thrown when +// node-java attempts to set assign the static method to the .name property of constructor-like function. +// As a workaround, node-java will append the `ifReadOnlySuffix` to the property name. + +import { beforeAll, describe, expect, test } from "vitest"; +import { getJava } from "../testHelpers"; +import { Java } from "../java"; + +describe("unusableMethodName", () => { + let java!: Java; + + beforeAll(async () => { + java = await getJava( + { + syncSuffix: "Sync", + asyncSuffix: "", + ifReadOnlySuffix: "_alt", + }, + { + beforeInit: (java) => { + function before(callback: () => void): void { + java.classpath.push("test/"); + expect(java.isJvmCreated()).toBeFalsy(); + callback(); + } + + function after(callback: () => void): void { + expect(java.isJvmCreated()).toBeTruthy(); + callback(); + } + + java.registerClient(before, after); + }, + } + ); + + await new Promise((resolve) => { + java.ensureJvm(function (err: Error | undefined) { + expect(err).toBeFalsy(); + expect(java.isJvmCreated()).toBeTruthy(); + resolve(); + }); + }); + }); + + test("unusableMethodName_nameThrows", () => { + const Test = java.import("Test"); + expect(Test).toBeTruthy(); + expect(() => { + Test.name((_err: Error | undefined) => { + throw new Error("should not get here"); + }); + }).toThrowError(TypeError); + }); + + test("unusableMethodName_callerThrows", () => { + const Test = java.import("Test"); + expect(Test).toBeTruthy(); + expect(() => { + Test.caller((_err: Error | undefined) => { + throw new Error("should not get here"); + }); + }).toThrowError(TypeError); + }); + + test("unusableMethodName_argumentsThrows", () => { + const Test = java.import("Test"); + expect(Test).toBeTruthy(); + expect(() => { + Test.arguments((_err: Error | undefined) => { + throw new Error("should not get here"); + }); + }).toThrowError(TypeError); + }); + + test("alternateMethodName_name_altWorks", async () => { + const Test = java.import("Test"); + expect(Test).toBeTruthy(); + await new Promise((resolve) => { + Test.name_alt((err: Error | undefined, val: string | undefined) => { + expect(err).toBeFalsy(); + expect(val).toBe("name"); + resolve(); + }); + }); + }); + + test("alternateMethodName_caller_altWorks", async () => { + const Test = java.import("Test"); + expect(Test).toBeTruthy(); + await new Promise((resolve) => { + Test.caller_alt((err: Error | undefined, val: string | undefined) => { + expect(err).toBeFalsy(); + expect(val).toBe("caller"); + resolve(); + }); + }); + }); + + test("alternateMethodName_arguments_altWorks", async () => { + const Test = java.import("Test"); + expect(Test).toBeTruthy(); + await new Promise((resolve) => { + Test.arguments_alt((err: Error | undefined, val: string | undefined) => { + expect(err).toBeFalsy(); + expect(val).toBe("arguments"); + resolve(); + }); + }); + }); + + test("reservedFieldName", () => { + const TestEnum = java.import("Test$Enum"); + expect(TestEnum).toBeTruthy(); + + // 'foo' and 'bar' are valid enum names + expect(TestEnum.foo.toStringSync()).toBe("foo"); + expect(TestEnum.bar.toStringSync()).toBe("bar"); + + // TestEnum.name is actually the name of the proxy constructor function. + expect(TestEnum.name).toBe("javaClassConstructorProxy"); + + // Instead we need to access TestEnum.name_alt + expect(TestEnum.name_alt.toString()).toBe("name"); + expect(TestEnum.caller_alt.toString()).toBe("caller"); + expect(TestEnum.arguments_alt.toString()).toBe("arguments"); + }); +}); diff --git a/testHelpers.js b/testHelpers.js deleted file mode 100644 index 01d5b687..00000000 --- a/testHelpers.js +++ /dev/null @@ -1,32 +0,0 @@ -var java = require("./"); -java.options.push("-Djava.awt.headless=true"); -//java.options.push('-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005'); - -java.classpath.push("test/"); -java.classpath.push("test/commons-lang3-3.1.jar"); -java.classpath.push("test8/"); - -function promisifyQ(f) { - // Q doesn't provide a promisify function that works directly on a method. - // The .denodeify() (aka .nfbind()) function requires a bound function. - return function(/* arguments */) { - return require('q').nbind(f, this).apply(undefined, arguments); - } -} - -java.asyncOptions = { - syncSuffix: "Sync", - asyncSuffix: "", - promiseSuffix: 'Promise', - promisify: require('when/node').lift // https://github.com/cujojs/when - - -// We've tested with 5 different Promises/A+ implementations: -// promisify: require('bluebird').promisify // https://github.com/petkaantonov/bluebird/ -// promisify: require('promise').denodeify // https://github.com/then/promise -// promisify: require('vow-node').promisify // https://github.com/dfilatov/vow-node -// promisify: require('when/node').lift // https://github.com/cujojs/when -// promisify: promisifyQ // https://github.com/kriskowal/q requires wrapper promisifyQ. -}; - -module.exports.java = java; diff --git a/testHelpers.ts b/testHelpers.ts new file mode 100644 index 00000000..f5543a14 --- /dev/null +++ b/testHelpers.ts @@ -0,0 +1,44 @@ +import { AsyncOptions, Java, JavaError } from "./java"; +import findRoot from "find-root"; + +const root = findRoot(__dirname); +let java: Promise | undefined; + +export interface GetJavaOptions { + beforeInit?: (java: Java) => void | Promise; +} + +export async function getJava(asyncOptions?: AsyncOptions | null, options?: GetJavaOptions): Promise { + if (java) { + return java; + } + java = _getJava(asyncOptions, options); + return java; +} + +async function _getJava(asyncOptions?: AsyncOptions | null, options?: GetJavaOptions): Promise { + const java = (await import(root)).default as Java; + + java.options.push("-Djava.awt.headless=true"); + //java.options.push('-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005'); + + java.classpath.push("test/"); + java.classpath.push("test/commons-lang3-3.18.0.jar"); + + if (asyncOptions !== null) { + java.asyncOptions = asyncOptions ?? { + syncSuffix: "Sync", + asyncSuffix: "", + promiseSuffix: "Promise", + }; + } + + await options?.beforeInit?.(java); + + // force initialization + java.import("java.util.ArrayList"); + + return java; +} + +export function expectJavaError(error: unknown): asserts error is JavaError {} diff --git a/testIntegration/jdbc/enduranceTest.js b/testIntegration/jdbc/enduranceTest.js index 0a82e1c7..e1b2e0a6 100644 --- a/testIntegration/jdbc/enduranceTest.js +++ b/testIntegration/jdbc/enduranceTest.js @@ -1,66 +1,73 @@ -'use strict'; +"use strict"; -var memwatch = require('memwatch'); +const memwatch = require("memwatch"); -var dbServerName = '192.168.13.190'; -var dbPort = 1433; -var dbName = 'test'; -var dbUserId = 'test'; -var dbPassword = 'test'; -var dbConnectString = 'jdbc:sqlserver://' + dbServerName + ':' + dbPort + ';databaseName=' + dbName + ';selectMethod=direct;responseBuffering=adaptive;packetSize=0;programName=nodeJavaTest;hostProcess=nodeJavaTest;sendStringParametersAsUnicode=false;'; -var dbConnectionClass = 'com.microsoft.sqlserver.jdbc.SQLServerDriver'; +const dbServerName = "192.168.13.190"; +const dbPort = 1433; +const dbName = "test"; +const dbUserId = "test"; +const dbPassword = "test"; +const dbConnectString = + "jdbc:sqlserver://" + + dbServerName + + ":" + + dbPort + + ";databaseName=" + + dbName + + ";selectMethod=direct;responseBuffering=adaptive;packetSize=0;programName=nodeJavaTest;hostProcess=nodeJavaTest;sendStringParametersAsUnicode=false;"; +const dbConnectionClass = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; -//var dbUserId = 'test'; -//var dbPassword = 'test'; -//var dbConnectString = "jdbc:mysql://localhost/test"; -//var dbConnectionClass = 'com.mysql.jdbc.Driver'; +//const dbUserId = 'test'; +//const dbPassword = 'test'; +//const dbConnectString = "jdbc:mysql://localhost/test"; +//const dbConnectionClass = 'com.mysql.jdbc.Driver'; -var util = require('util'); -var path = require('path'); -var java = require('../../'); -java.classpath.push(path.join(__dirname, 'sqljdbc4.jar')); -java.classpath.push(path.join(__dirname, 'mysql-connector-java-5.1.22-bin.jar')); -var DriverManager = java.import('java.sql.DriverManager'); +const util = require("util"); +const path = require("path"); +const java = require("../../"); +java.classpath.push(path.join(__dirname, "sqljdbc4.jar")); +java.classpath.push(path.join(__dirname, "mysql-connector-java-5.1.22-bin.jar")); +const DriverManager = java.import("java.sql.DriverManager"); -setTimeout(function() { - console.log('start heap diff'); - var hd = new memwatch.HeapDiff(); - var loopStart = new Date(); - for (var loopCount = 0; loopCount < 500000; loopCount++) { - console.log('loopCount:', loopCount); +setTimeout(function () { + console.log("start heap diff"); + const hd = new memwatch.HeapDiff(); + const loopStart = new Date(); + for (let loopCount = 0; loopCount < 500000; loopCount++) { + console.log("loopCount:", loopCount); doLoop(); } - var loopEnd = new Date(); - console.log('end loop', loopEnd - loopStart); + const loopEnd = new Date(); + console.log("end loop", loopEnd - loopStart); memwatch.gc(); - var diff = hd.end(); + const diff = hd.end(); console.log(util.inspect(diff.change, false, 10, true)); console.log("done... waiting 30seconds"); - setTimeout(function() { + setTimeout(function () { console.log("really done"); }, 30 * 1000); }, 1); function doLoop() { java.findClassSync(dbConnectionClass); - var conn = DriverManager.getConnectionSync(dbConnectString, dbUserId, dbPassword); + const conn = DriverManager.getConnectionSync(dbConnectString, dbUserId, dbPassword); //console.log("connected"); - var statement = conn.createStatementSync(); - var queryString = "select * from Person"; - var rs = statement.executeQuerySync(queryString); - var metaData = rs.getMetaDataSync(); - var columnCount = metaData.getColumnCountSync(); + const statement = conn.createStatementSync(); + const queryString = "select * from Person"; + const rs = statement.executeQuerySync(queryString); + const metaData = rs.getMetaDataSync(); + const columnCount = metaData.getColumnCountSync(); while (rs.nextSync()) { - for (var i = 1; i <= columnCount; i++) { - var obj = rs.getObjectSync(i); + for (let i = 1; i <= columnCount; i++) { + const obj = rs.getObjectSync(i); if (obj) { - if (obj.hasOwnProperty('getClassSync')) { - if (obj.getClassSync().toString() == 'class java.math.BigDecimal') { + if (Object.prototype.hasOwnProperty.call(obj, "getClassSync")) { + if (obj.getClassSync().toString() == "class java.math.BigDecimal") { //console.log(obj.doubleValueSync()); continue; } - if (obj.getClassSync().toString() == 'class java.sql.Timestamp') { + if (obj.getClassSync().toString() == "class java.sql.Timestamp") { //console.log(obj.getTimeSync()); continue; } @@ -71,4 +78,4 @@ function doLoop() { } } conn.closeSync(); -} \ No newline at end of file +} diff --git a/testIntegration/jdbc/enduranceTestAsync.js b/testIntegration/jdbc/enduranceTestAsync.js index 039c52fe..87b8eea3 100644 --- a/testIntegration/jdbc/enduranceTestAsync.js +++ b/testIntegration/jdbc/enduranceTestAsync.js @@ -1,67 +1,67 @@ -'use strict'; +"use strict"; // Tests concurrent async jdbc connections. // TODO: a proper jdbc wrapper should be created to avoid ugly async code. -var memwatch = require('memwatch'); -var async = require('async'); +const memwatch = require("memwatch"); +const async = require("async"); // 1 - 23,305ms // 5 - 9,338ms // 10 - 8,846ms -var concurrency = 5; - -//var dbServerName = '192.168.13.190'; -//var dbPort = 1433; -//var dbName = 'test'; -//var dbUserId = 'test'; -//var dbPassword = 'test'; -//var dbConnectString = 'jdbc:sqlserver://' + dbServerName + ':' + dbPort + ';databaseName=' + dbName + ';selectMethod=direct;responseBuffering=adaptive;packetSize=0;programName=nodeJavaTest;hostProcess=nodeJavaTest;sendStringParametersAsUnicode=false;'; -//var dbConnectionClass = 'com.microsoft.sqlserver.jdbc.SQLServerDriver'; - -var dbUserId = 'test'; -var dbPassword = 'test'; -var dbConnectString = "jdbc:mysql://localhost/test"; -var dbConnectionClass = 'com.mysql.jdbc.Driver'; - -var util = require('util'); -var path = require('path'); -var java = require('../../'); -java.classpath.push(path.join(__dirname, 'sqljdbc4.jar')); -java.classpath.push(path.join(__dirname, 'mysql-connector-java-5.1.22-bin.jar')); -var DriverManager = java.import('java.sql.DriverManager'); - -setTimeout(function() { - console.log('start heap diff'); - var hd = new memwatch.HeapDiff(); - var loopStart = new Date(); +const concurrency = 5; + +//const dbServerName = '192.168.13.190'; +//const dbPort = 1433; +//const dbName = 'test'; +//const dbUserId = 'test'; +//const dbPassword = 'test'; +//const dbConnectString = 'jdbc:sqlserver://' + dbServerName + ':' + dbPort + ';databaseName=' + dbName + ';selectMethod=direct;responseBuffering=adaptive;packetSize=0;programName=nodeJavaTest;hostProcess=nodeJavaTest;sendStringParametersAsUnicode=false;'; +//const dbConnectionClass = 'com.microsoft.sqlserver.jdbc.SQLServerDriver'; + +const dbUserId = "test"; +const dbPassword = "test"; +const dbConnectString = "jdbc:mysql://localhost/test"; +const dbConnectionClass = "com.mysql.jdbc.Driver"; + +const util = require("util"); +const path = require("path"); +const java = require("../../"); +java.classpath.push(path.join(__dirname, "sqljdbc4.jar")); +java.classpath.push(path.join(__dirname, "mysql-connector-java-5.1.22-bin.jar")); +const DriverManager = java.import("java.sql.DriverManager"); + +setTimeout(function () { + console.log("start heap diff"); + const hd = new memwatch.HeapDiff(); + const loopStart = new Date(); java.findClassSync(dbConnectionClass); - var loopIterations = []; - for (var i = 0; i < 5000; i++) { + const loopIterations = []; + for (let i = 0; i < 5000; i++) { loopIterations.push(i); } async.forEachLimit( loopIterations, concurrency, - function(loopCount, callback) { - console.log('loopCount:', loopCount); + function (loopCount, callback) { + console.log("loopCount:", loopCount); return doLoop(callback); }, - function(err) { + function (err) { if (err) { console.log("fail", err); } - var loopEnd = new Date(); - console.log('end loop', loopEnd - loopStart); + const loopEnd = new Date(); + console.log("end loop", loopEnd - loopStart); memwatch.gc(); - var diff = hd.end(); + const diff = hd.end(); console.log(util.inspect(diff.change, false, 10, true)); console.log("done... waiting 30seconds"); - setTimeout(function() { + setTimeout(function () { console.log("really done"); }, 30 * 1000); } @@ -69,7 +69,7 @@ setTimeout(function() { }, 1); function doLoop(callback) { - var conn; + let conn; return DriverManager.getConnection(dbConnectString, dbUserId, dbPassword, getConnectionComplete); @@ -80,34 +80,41 @@ function doLoop(callback) { conn = _conn; //console.log("connected"); - var queryString = "select * from Person"; - return executeQuery(conn, queryString, function(row, callback) { - //console.log("row", row); - return callback(); - }, function(err) { - if (err) { - return callback(err); + const queryString = "select * from Person"; + return executeQuery( + conn, + queryString, + function (row, callback) { + //console.log("row", row); + return callback(); + }, + function (err) { + if (err) { + return callback(err); + } + //console.log("query complete"); + return callback(); } - //console.log("query complete"); - return callback(); - }); + ); } } function executeQuery(conn, sql, rowCallback, completeCallback) { - var statement = conn.createStatementSync(); - return statement.executeQuery(sql, function(err, rs) { + const statement = conn.createStatementSync(); + return statement.executeQuery(sql, function (err, rs) { if (err) { return completeCallback(err); } - var columnCount = rs.getMetaDataSync().getColumnCountSync(); + const columnCount = rs.getMetaDataSync().getColumnCountSync(); - var rsComplete = false; + let rsComplete = false; async.until( - function() { return rsComplete; }, - function(callback) { - return rs.next(function(err, rsNextResult) { + function () { + return rsComplete; + }, + function (callback) { + return rs.next(function (err, rsNextResult) { if (err) { return callback(err); } @@ -115,14 +122,14 @@ function executeQuery(conn, sql, rowCallback, completeCallback) { rsComplete = true; return callback(); } - var row = []; - for (var i = 1; i <= columnCount; i++) { + const row = []; + for (let i = 1; i <= columnCount; i++) { row.push(rs.getObjectSync(i)); } return rowCallback(row, callback); }); }, - function(err) { + function (err) { if (err) { return completeCallback(err); } @@ -130,4 +137,4 @@ function executeQuery(conn, sql, rowCallback, completeCallback) { } ); }); -} \ No newline at end of file +} diff --git a/testIntegration/poi/poi-3.9-20121203.jar b/testIntegration/poi/poi-3.9-20121203.jar index c5d731b0..0f462880 100644 Binary files a/testIntegration/poi/poi-3.9-20121203.jar and b/testIntegration/poi/poi-3.9-20121203.jar differ diff --git a/testIntegration/poi/poi-scratchpad-3.9-20121203.jar b/testIntegration/poi/poi-scratchpad-3.9-20121203.jar index acb8fd56..15208552 100644 Binary files a/testIntegration/poi/poi-scratchpad-3.9-20121203.jar and b/testIntegration/poi/poi-scratchpad-3.9-20121203.jar differ diff --git a/testIntegration/poi/poiTest.js b/testIntegration/poi/poiTest.js index ce516c0b..220a4a8a 100644 --- a/testIntegration/poi/poiTest.js +++ b/testIntegration/poi/poiTest.js @@ -1,20 +1,23 @@ -var java = require('../../'); +const java = require("../../"); java.classpath.push("poi-3.9-20121203.jar"); java.classpath.push("poi-scratchpad-3.9-20121203.jar"); -var stream = java.newInstanceSync("java.io.FileInputStream", 'presentation.ppt'); -var ppt = java.newInstanceSync('org.apache.poi.hslf.usermodel.SlideShow', stream); +const stream = java.newInstanceSync("java.io.FileInputStream", "presentation.ppt"); +const ppt = java.newInstanceSync("org.apache.poi.hslf.usermodel.SlideShow", stream); stream.close(); -var pgsize = ppt.getPageSizeSync(); +const pgsize = ppt.getPageSizeSync(); +console.log(`found page size ${pgsize.width}x${pgsize.height}`); -var slides = ppt.getSlidesSync(); +const slides = ppt.getSlidesSync(); +console.log(`found ${slides.length} slides`); -var TYPE_INT_RGB = java.getStaticFieldValue("java.awt.image.BufferedImage", "TYPE_INT_RGB"); +const TYPE_INT_RGB = java.getStaticFieldValue("java.awt.image.BufferedImage", "TYPE_INT_RGB"); -var img, graphics; -for (i = 0; i < slides.length; i++) { - img = java.newInstanceSync('java.awt.image.BufferedImage', pgsize.width, pgsize.height, TYPE_INT_RGB); - graphics = img.createGraphicsSync(); +for (let i = 0; i < slides.length; i++) { + console.log(`creating image: ${i}`); + const img = java.newInstanceSync("java.awt.image.BufferedImage", pgsize.width, pgsize.height, TYPE_INT_RGB); + img.createGraphicsSync(); } -console.log('done'); \ No newline at end of file +console.log("done"); +process.exit(0); diff --git a/testIntegration/webkit/main.js b/testIntegration/webkit/main.js index 403b5229..2cf9063e 100644 --- a/testIntegration/webkit/main.js +++ b/testIntegration/webkit/main.js @@ -1,5 +1,5 @@ -var java = require('../../'); +const java = require("../../"); -function runJavaMethod() { +export function runJavaMethod() { return java.callStaticMethodSync("java.lang.System", "getProperty", "java.version"); -} \ No newline at end of file +} diff --git a/testRunner.js b/testRunner.js deleted file mode 100644 index 7a990e67..00000000 --- a/testRunner.js +++ /dev/null @@ -1,38 +0,0 @@ -// testRunner.js - -// This is a custom test runner. All tests are run with nodeunit, but in separate -// processes, which allows us to test java with different configuration options. - -var async = require('async'); -var chalk = require('chalk'); -var childProcess = require('child_process'); -var glob = require('glob'); -var path = require('path'); - -var tests = glob.sync(path.join('testAsyncOptions', '*.js')); - -tests.unshift('test test8'); // Arrange to run the primary tests first, in a single process - -function runTest(testArgs, done) { - var cmd = 'node_modules/.bin/nodeunit '; - if(process.platform == "win32") - cmd = 'node_modules\\.bin\\nodeunit '; - cmd += testArgs; - childProcess.exec(cmd, function (error, stdout, stderr) { - // It appears that nodeunit merges error output into the stdout - // so these three lines are probably useless. - var errText = stderr.toString(); - if (errText !== '') - console.error(chalk.bold.red(errText)); - - process.stdout.write(stdout.toString()); - done(error); - }); -} - -async.eachSeries(tests, runTest, function(err) { - if (err) { - console.error(chalk.bold.red(err)); - process.exit(1); - } -}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..4ed39cb0 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,116 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "libReplacement": true, /* Enable lib replacement. */ + // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + // "rewriteRelativeImportExtensions": true, /* Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files. */ + // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ + // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ + // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "noUncheckedSideEffectImports": true, /* Check side effect imports. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./build/ts", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ + // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ + // "erasableSyntaxOnly": true, /* Do not allow runtime constructs that are not part of ECMAScript. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "strictBuiltinIteratorReturn": true, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + }, + "exclude": [ + "examples" + ] +} diff --git a/update-commons-lang.sh b/update-commons-lang.sh deleted file mode 100755 index 29250f57..00000000 --- a/update-commons-lang.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -ex - -if [ -d build/commons-lang ]; then - cd build/commons-lang - git pull -else - mkdir -p build - cd build - git clone --depth 1 git@github.com:apache/commons-lang.git - cd commons-lang -fi - -mvn clean compile package -DskipTests -java -jar ../../jarjar-1.4.jar process ../../commons-lang.jarjar.rules target/commons-lang3*-SNAPSHOT.jar ../../commons-lang3-node-java.jar -