Remove node-addon-api because it is slower than native Node.js

This commit is contained in:
Asaki Yuki 2026-01-18 21:54:59 +07:00
parent 6b93909e7e
commit 6817734ed9
8 changed files with 5 additions and 300 deletions

View file

@ -1,15 +0,0 @@
{
"configurations": [
{
"name": "Win32",
"includePath": ["${workspaceFolder}/**"],
"defines": ["_DEBUG", "UNICODE", "_UNICODE"],
"windowsSdkVersion": "10.0.26100.0",
"compilerPath": "cl.exe",
"cStandard": "c17",
"cppStandard": "c++20",
"intelliSenseMode": "windows-msvc-x64"
}
],
"version": 4
}

View file

@ -1,20 +0,0 @@
{
"targets": [
{
"target_name": "asajs-compiler",
"sources": [
"src/native/main.cpp",
],
"dependencies": [
"<!(node -p \"require('node-addon-api').targets\"):node_addon_api",
],
"msvs_settings": {
"VCCLCompilerTool": {
"LanguageStandard": "stdcpp20"
}
}
}
]
}

48
package-lock.json generated
View file

@ -9,72 +9,29 @@
"version": "4.0.0", "version": "4.0.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@types/bindings": "^1.5.5", "jsonc-parser": "^3.3.1"
"bindings": "^1.5.0",
"jsonc-parser": "^3.3.1",
"node-addon-api": "^8.5.0"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^25.0.3", "@types/node": "^25.0.3",
"node-api-headers": "^1.7.0",
"typescript": "^5.9.3" "typescript": "^5.9.3"
} }
}, },
"node_modules/@types/bindings": {
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/@types/bindings/-/bindings-1.5.5.tgz",
"integrity": "sha512-y59PRZBTo2/HuN94qRjyJD+465vGoXMsqz9MMJDbtJL9oT5/B+tAL6c3k10epIinC2/BBkLqKzKC6keukl8wdQ==",
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "25.0.9", "version": "25.0.9",
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.9.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.9.tgz",
"integrity": "sha512-/rpCXHlCWeqClNBwUhDcusJxXYDjZTyE8v5oTO7WbL8eij2nKhUeU89/6xgjU7N4/Vh3He0BtyhJdQbDyhiXAw==", "integrity": "sha512-/rpCXHlCWeqClNBwUhDcusJxXYDjZTyE8v5oTO7WbL8eij2nKhUeU89/6xgjU7N4/Vh3He0BtyhJdQbDyhiXAw==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"undici-types": "~7.16.0" "undici-types": "~7.16.0"
} }
}, },
"node_modules/bindings": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"license": "MIT",
"dependencies": {
"file-uri-to-path": "1.0.0"
}
},
"node_modules/file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
"license": "MIT"
},
"node_modules/jsonc-parser": { "node_modules/jsonc-parser": {
"version": "3.3.1", "version": "3.3.1",
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz",
"integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/node-addon-api": {
"version": "8.5.0",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz",
"integrity": "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A==",
"license": "MIT",
"engines": {
"node": "^18 || ^20 || >= 21"
}
},
"node_modules/node-api-headers": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/node-api-headers/-/node-api-headers-1.7.0.tgz",
"integrity": "sha512-uJMGdkhVwu9+I3UsVvI3KW6ICAy/yDfsu5Br9rSnTtY3WpoaComXvKloiV5wtx0Md2rn0B9n29Ys2WMNwWxj9A==",
"dev": true,
"license": "MIT"
},
"node_modules/typescript": { "node_modules/typescript": {
"version": "5.9.3", "version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
@ -93,6 +50,7 @@
"version": "7.16.0", "version": "7.16.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
"dev": true,
"license": "MIT" "license": "MIT"
} }
} }

View file

@ -32,13 +32,9 @@
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^25.0.3", "@types/node": "^25.0.3",
"node-api-headers": "^1.7.0",
"typescript": "^5.9.3" "typescript": "^5.9.3"
}, },
"dependencies": { "dependencies": {
"@types/bindings": "^1.5.5", "jsonc-parser": "^3.3.1"
"bindings": "^1.5.0",
"jsonc-parser": "^3.3.1",
"node-addon-api": "^8.5.0"
} }
} }

View file

@ -1,8 +0,0 @@
import bindings from "bindings"
import { Token } from "./bindings/types.js"
export const {
Lexer,
}: {
Lexer: (input: string) => Token[]
} = bindings("asajs-compiler")

View file

@ -8,7 +8,4 @@ export * from "./components/Utils.js"
export * from "./types/enums/index.js" export * from "./types/enums/index.js"
export * as Properties from "./types/properties/index.js" export * as Properties from "./types/properties/index.js"
export { Lexer as NativeLexer } from "./compilers/Bindings.js"
export { Lexer } from "./compilers/bindings/Lexer.js"
export { ItemAuxID } from "./types/enums/Items.js" export { ItemAuxID } from "./types/enums/Items.js"

View file

@ -1,187 +0,0 @@
#include <napi.h>
#include <format>
#include <regex>
enum TokenKind {
VARIABLE,
NUMBER,
STRING,
TEMPLATE_STRING,
WORD,
OPEN_PARENTHESIS,
CLOSE_PARENTHESIS,
OPERATOR,
COMMA,
};
namespace Lexer {
bool isBlankChar(char c) {
std::regex pattern(R"(\s)");
return std::regex_match(std::string(1, c), pattern);
};
bool isWordChar(char c) {
std::regex pattern(R"(\w)");
return std::regex_match(std::string(1, c), pattern);
}
bool isNumberChar(char c) {
std::regex pattern(R"(\d)");
return std::regex_match(std::string(1, c), pattern);
}
Napi::Object makeToken(Napi::Env &env, const std::string &input, TokenKind kind, size_t start, size_t length = 1) {
Napi::Object token = Napi::Object::New(env);
token.Set(Napi::String::New(env, "start"), Napi::Number::New(env, start));
token.Set(Napi::String::New(env, "length"), Napi::Number::New(env, length));
token.Set(Napi::String::New(env, "kind"), Napi::Number::New(env, kind));
token.Set(Napi::String::New(env, "value"), Napi::String::New(env, input.substr(start, length)));
return token;
}
Napi::Array Lexer(const Napi::CallbackInfo &info) {
Napi::Env env = info.Env();
Napi::Function consoleLog = env.Global().Get("console").As<Napi::Object>().Get("log").As<Napi::Function>();
if (info.Length() != 1) {
Napi::TypeError::New(env, "One string argument required").ThrowAsJavaScriptException();
return Napi::Array::New(env, 0);
}
if (!info[0].IsString()) {
Napi::TypeError::New(env, "Input must be a string").ThrowAsJavaScriptException();
return Napi::Array::New(env, 0);
}
const std::string input = info[0].As<Napi::String>().Utf8Value();
const size_t length = input.size();
if (length == 0) {
return Napi::Array::New(env, 0);
}
std::vector<Napi::Object> tokens;
size_t index = 0;
while (index < length) {
char c = input[index];
switch (c) {
// Literals
case '#':
case '$': {
const size_t start = index++;
while (index < length) {
const char c = input[index];
if (Lexer::isWordChar(c)) index++;
else break;
}
tokens.push_back(makeToken(env, input, TokenKind::VARIABLE, start, index-- - start));
break;
} break;
case '\'': {
const size_t start = index++;
while (index < length) {
const char c = input[index];
if (c == '\'') break;
index++;
}
tokens.push_back(makeToken(env, input, TokenKind::STRING, start, index - start + 1));
} break;
case ',':
tokens.push_back(makeToken(env, input, TokenKind::COMMA, index));
break;
// Single operators
case '+':
case '-':
case '*':
case '/':
case '%':
tokens.push_back(makeToken(env, input, TokenKind::OPERATOR, index));
break;
case '(':
tokens.push_back(makeToken(env, input, TokenKind::OPEN_PARENTHESIS, index));
break;
case ')':
tokens.push_back(makeToken(env, input, TokenKind::CLOSE_PARENTHESIS, index));
break;
// Double operators
case '&':
case '|':
case '=':
if (input[index + 1] == input[index]) tokens.push_back(makeToken(env, input, TokenKind::OPERATOR, index++, 2));
else tokens.push_back(makeToken(env, input, TokenKind::OPERATOR, index));
break;
case '!':
case '>':
case '<':
if (input[index + 1] == '=') tokens.push_back(makeToken(env, input, TokenKind::OPERATOR, index++, 2));
else tokens.push_back(makeToken(env, input, TokenKind::OPERATOR, index));
break;
default: {
const size_t start = index;
if (Lexer::isNumberChar(c)) {
while (Lexer::isNumberChar(input[index + 1])) index++;
tokens.push_back(
Lexer::makeToken(env, input, TokenKind::NUMBER, start, index - start + 1)
);
} else if (Lexer::isWordChar(c)) {
while (Lexer::isWordChar(input[index + 1])) index++;
tokens.push_back(
Lexer::makeToken(env, input, TokenKind::WORD, start, index - start + 1)
);
} else if (!Lexer::isBlankChar(c)) {
std::string message = std::format(
"\x1b[31m{}>>>{}<<<{}\nInvalid character\x1b[0m",
input.substr(0, start),
input.substr(start, index - start + 1),
input.substr(index + 1)
);
Napi::TypeError::New(env, Napi::String::New(env, message)).ThrowAsJavaScriptException();
return Napi::Array::New(env, 0);
}
} break;
};
index++;
}
size_t tokenLength = tokens.size();
Napi::Array result = Napi::Array::New(env, tokenLength);
for (size_t i = 0; i < tokenLength; i++)
result.Set(i, tokens[i]);
return result;
}
};
Napi::Object Init(Napi::Env env, Napi::Object exports) {
exports.Set(
Napi::String::New(env, "Lexer"),
Napi::Function::New(env, Lexer::Lexer)
);
return exports;
}
NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)

View file

@ -1,17 +1 @@
import { Lexer, NativeLexer } from ".." import {} from ".."
const input = Array.from(
{ length: 50 },
() =>
"#test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <= #test $test 'abcde' test 123 + - * / % , ( ) & && | || = == ! != > >= < <=",
).join(" ")
const nn = performance.now()
NativeLexer(input)
const nt = performance.now()
const n = performance.now()
Lexer(input)
const t = performance.now()
console.log(`Native: ${nt - nn}ms, JS: ${t - n}ms`)