JavaScript Runtime
JavaScript Runtime
One of biggest features of Lynx is Dual-Thread Architecture(read Thinking in ReactLynx for more information), JavaScript code runs on two threads: the main thread and the background thread. The two threads use different JavaScript engines as their runtime.
Main Thread
The Lynx main thread is responsible for handling tasks that directly affect the screen pixel-pipeline, including executing main thread scripts, handling layout, and rendering graphics.
The main thread uses PrimJS, maintained by the Lynx team, as its runtime. PrimJS is a lightweight, high-performance JavaScript engine based on QuickJS, providing excellent runtime performance for the main thread.
Background Thread
As opposed to the main thread, Lynx's background threads handle tasks that do not directly affect the display of screen pixels. This includes scripts and tasks that run in the background, separate from the main thread. This allows the main thread to focus on handling user interaction and rendering, which improves overall performance.
- Android: for a combination of package size and performance considerations, we use PrimJS by default
- iOS: we use JavaScriptCore by default, unless you need to use the PrimJS for debugging
While these environments are very similar, you may end up hitting some inconsistencies. It is best to avoid relying on specifics of any runtime.
JavaScript Syntax Transformers
The Lynx dual-thread runtime supports the following maximum ECMAScript versions:
- Main thread: ECMAScript 2019 (ES10)
- Background thread: ECMAScript 2015 (ES6)
Of course, you can use new JavaScript syntax to write your code. During the build process, SWC will be used as Syntax Transformer to transform your code, so you don't have to wait for JavaScript runtime support.
JavaScript Polyfills
Only injects polyfills on iOS.
A full list of Lynx's polyfills can be found in Lynx repositoryBesides syntax transformers, many built-in objects and standard functions are also available. Including:
Built-in Objects
Array
- Array.prototype.concat
- Array.prototype.filter
- Array.prototype.flat
- Array.prototype.flatMap
- Array.prototype.includes
- Array.prototype[@@iterator]
- Array.prototype.map
- Array.prototype.reverse
- Array.prototype.slice
- Array.prototype.sort
- Array.prototype.species
- Array.prototype.splice
- Array.prototype[@@unscopables].flat
- Array.prototype[@@unscopables].flatMap
ArrayBuffer
Date
Number
Object
Promise
- Promise
- Promise.all
- Promise.race
- Promise.reject
- Promise.resolve
- Promise.prototype.catch
- Promise.prototype.finally
- Promise.prototype.then
Reflect
- Reflect.apply
- Reflect.construct
- Reflect.defineProperty
- Reflect.deleteProperty
- Reflect.get
- Reflect.getOwnPropertyDescriptors
- Reflect.getPrototypeOf
- Reflect.has
- Reflect.isExtensible
- Reflect.ownKeys
- Reflect.preventExtensions
- Reflect.set
- Reflect.setPrototypeOf
RegExp
- RegExp
- RegExp.prototype.exec
- RegExp.prototype.sticky
- RegExp.prototype.test
- RegExp.prototype.toString
String
- String.prototype.endsWith
- String.prototype.includes
- String.prototype.match
- String.prototype.matchAll
- String.prototype.padEnd
- String.prototype.padStart
- String.prototype.replace
- String.prototype.search
- String.prototype.split
- String.prototype.startsWith
- String.prototype.trim
- String.prototype.trimEnd
- String.prototype.trimStart
Symbol
- Symbol
- Symbol.prototype.description
- Symbol.asyncIterator
- Symbol.hasInstance
- Symbol.isConcatSpreadable
- Symbol.match
- Symbol.matchAll
- Symbol.replace
- Symbol.search
- Symbol.species
- Symbol.split
- Symbol.toPrimitive
- Symbol.toStringTag
Module
You can use JavaScript module when developing Lynx project.
Lynx currently supports ESModule and CommonJS. The usage of ESModule and CommonJS can be mixed.
It is recommended to use ESModule, which allows for better Tree Shaking.
Module Names
Both ESModule and CommonJS, a module name needs to be specified. It can be one of:
- Relative path:
./common.js - Name of a npm package:
lodash(C++ addon and NodeJS builtin packages are not supported) - Path with alias:
@common/foo.js
CommonJS
CommonJS uses require(path) to import a module. Uses module.exports or exports to export a module.
-
requirecan be anywhere in your code, not required to be at top. -
requirewill synchronously execute the target module. -
requirewill cache the returned object. Multiplerequireto the same path will return the same value. e.g:
ESModule
ESModule uses import to import a module. Uses export to export a module.
import and export must be placed at the top level of source file.
ESModule can also use import() to dynamically import a module.