NaiveJS is a personal experimental JavaScript engine. My primary goal is to learn the implementation of well-known features in JavaScript such as closures, event loops, objects, etc., rather than implementing the language strictly according to the ECMA specification. Having said that, I do hope to bring NaiveJS closer to the specification as time goes on.
NaiveJS can now run the Typescript 2.0.10 transpiler (test_typescript_2.0.10.js) ! Although it is still not a rigorous ES5 implementation, it at least produces the same results as QuickJS produces in my tests.
Running time comparison of running the Typescript 1 transpiler (The input is a very long piece of Typescript code):
- Node.js v18.15.0 : 0.48 s
- QuickJS : 1.93 s
- NaiveJS : 2.21 s
Running time comparison of running the Typescript 2 transpiler:
- Node.js v18.15.0 : 0.52 s
- QuickJS (built with clang 18) : 2.70 s
- NaiveJS (built with clang++ 18) : 3.18 s
This test involves a lot of string concatenation, which indirectly invokes memory copy and creates a lot of temporary strings. This slows down NaiveJS significantly. NaiveJS currently uses char16 arrays to represent strings, while QuickJS uses char8 arrays to represent strings when there are no wide characters in the string, making it more efficient.
The comparison is not a rigorous one. If NaiveJS were implemented strictly according to the ECMA specification, it would be expected to run even slower.
- Lexer, parser, and AST (adapted from this work)
- Static scope chain
- Bytecode generator
- Bytecode virtual machine
- Basic math operators and relational operators
- Logical operators (short-circuit evaluation)
- Member access expression (dot)
- Indexed access expression (subscript)
- If statement
- While loop, break, continue
- labelled statement
- For loop (regular, for-in, for-of)
- Iterator
-
JSValue
and basic JavaScript data types - Array literals, object literals
- Closures and variable capture
- Generational garbage collection
- Event loop and
setInterval
,setTimeout
- Third-party libraries for HTTP requests
- Runtime exception and error handling (try-catch-finally)
-
new
operator - Prototype chain
- Object property attributes, Object.defineProperty
- Regular expression
- Promise, async function
- Generator function
- Template literals
- Spread syntax
- Destructuring assignment
- Make eventloop work on Linux (using epoll)
- Utilizing the "label as value" technique in the VM
- Reorganize the parser code
- Compactly stored bytecode
- More peephole optimizations
- Improve error handling in the parser and code generator
- Use smart pointers instead of raw pointers in AST nodes. (This was previously found to cause performance degradation on macOS with Clang)
- GC and object system optimization: allowing GC to move objects safely
- fully managed memory: let objects be allocated on the GC heap as much as possible
- Use a more efficient hash table implementation
- String memory consumption optimization: store latin1 strings in char8_t arrays
- Inline cache
- Object shape and object property access optimization
- Atom strings GC
- JIT
eval
functionwith
statement
-
A great Javascript engine, small and fast. It supports the ES2023 specification.
-
An ES5 engine written from scratch.
-
A regular expression library created by the QuickJS project.