@mikrojs/quickjs 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,310 @@
1
+ #ifdef UNICODE_GENERAL_CATEGORY
2
+ DEF(Cn, "Unassigned") /* must be zero */
3
+ DEF(Lu, "Uppercase_Letter")
4
+ DEF(Ll, "Lowercase_Letter")
5
+ DEF(Lt, "Titlecase_Letter")
6
+ DEF(Lm, "Modifier_Letter")
7
+ DEF(Lo, "Other_Letter")
8
+ DEF(Mn, "Nonspacing_Mark")
9
+ DEF(Mc, "Spacing_Mark")
10
+ DEF(Me, "Enclosing_Mark")
11
+ DEF(Nd, "Decimal_Number,digit")
12
+ DEF(Nl, "Letter_Number")
13
+ DEF(No, "Other_Number")
14
+ DEF(Sm, "Math_Symbol")
15
+ DEF(Sc, "Currency_Symbol")
16
+ DEF(Sk, "Modifier_Symbol")
17
+ DEF(So, "Other_Symbol")
18
+ DEF(Pc, "Connector_Punctuation")
19
+ DEF(Pd, "Dash_Punctuation")
20
+ DEF(Ps, "Open_Punctuation")
21
+ DEF(Pe, "Close_Punctuation")
22
+ DEF(Pi, "Initial_Punctuation")
23
+ DEF(Pf, "Final_Punctuation")
24
+ DEF(Po, "Other_Punctuation")
25
+ DEF(Zs, "Space_Separator")
26
+ DEF(Zl, "Line_Separator")
27
+ DEF(Zp, "Paragraph_Separator")
28
+ DEF(Cc, "Control,cntrl")
29
+ DEF(Cf, "Format")
30
+ DEF(Cs, "Surrogate")
31
+ DEF(Co, "Private_Use")
32
+ /* synthetic properties */
33
+ DEF(LC, "Cased_Letter")
34
+ DEF(L, "Letter")
35
+ DEF(M, "Mark,Combining_Mark")
36
+ DEF(N, "Number")
37
+ DEF(S, "Symbol")
38
+ DEF(P, "Punctuation,punct")
39
+ DEF(Z, "Separator")
40
+ DEF(C, "Other")
41
+ #endif
42
+
43
+ #ifdef UNICODE_SCRIPT
44
+ /* scripts aliases names in PropertyValueAliases.txt */
45
+ DEF(Unknown, "Zzzz")
46
+ DEF(Adlam, "Adlm")
47
+ DEF(Ahom, "Ahom")
48
+ DEF(Anatolian_Hieroglyphs, "Hluw")
49
+ DEF(Arabic, "Arab")
50
+ DEF(Armenian, "Armn")
51
+ DEF(Avestan, "Avst")
52
+ DEF(Balinese, "Bali")
53
+ DEF(Bamum, "Bamu")
54
+ DEF(Bassa_Vah, "Bass")
55
+ DEF(Batak, "Batk")
56
+ DEF(Bengali, "Beng")
57
+ DEF(Beria_Erfe, "Berf")
58
+ DEF(Bhaiksuki, "Bhks")
59
+ DEF(Bopomofo, "Bopo")
60
+ DEF(Brahmi, "Brah")
61
+ DEF(Braille, "Brai")
62
+ DEF(Buginese, "Bugi")
63
+ DEF(Buhid, "Buhd")
64
+ DEF(Canadian_Aboriginal, "Cans")
65
+ DEF(Carian, "Cari")
66
+ DEF(Caucasian_Albanian, "Aghb")
67
+ DEF(Chakma, "Cakm")
68
+ DEF(Cham, "Cham")
69
+ DEF(Cherokee, "Cher")
70
+ DEF(Chorasmian, "Chrs")
71
+ DEF(Common, "Zyyy")
72
+ DEF(Coptic, "Copt,Qaac")
73
+ DEF(Cuneiform, "Xsux")
74
+ DEF(Cypriot, "Cprt")
75
+ DEF(Cyrillic, "Cyrl")
76
+ DEF(Cypro_Minoan, "Cpmn")
77
+ DEF(Deseret, "Dsrt")
78
+ DEF(Devanagari, "Deva")
79
+ DEF(Dives_Akuru, "Diak")
80
+ DEF(Dogra, "Dogr")
81
+ DEF(Duployan, "Dupl")
82
+ DEF(Egyptian_Hieroglyphs, "Egyp")
83
+ DEF(Elbasan, "Elba")
84
+ DEF(Elymaic, "Elym")
85
+ DEF(Ethiopic, "Ethi")
86
+ DEF(Georgian, "Geor")
87
+ DEF(Glagolitic, "Glag")
88
+ DEF(Gothic, "Goth")
89
+ DEF(Garay, "Gara")
90
+ DEF(Grantha, "Gran")
91
+ DEF(Greek, "Grek")
92
+ DEF(Gujarati, "Gujr")
93
+ DEF(Gunjala_Gondi, "Gong")
94
+ DEF(Gurmukhi, "Guru")
95
+ DEF(Gurung_Khema, "Gukh")
96
+ DEF(Han, "Hani")
97
+ DEF(Hangul, "Hang")
98
+ DEF(Hanifi_Rohingya, "Rohg")
99
+ DEF(Hanunoo, "Hano")
100
+ DEF(Hatran, "Hatr")
101
+ DEF(Hebrew, "Hebr")
102
+ DEF(Hiragana, "Hira")
103
+ DEF(Imperial_Aramaic, "Armi")
104
+ DEF(Inherited, "Zinh,Qaai")
105
+ DEF(Inscriptional_Pahlavi, "Phli")
106
+ DEF(Inscriptional_Parthian, "Prti")
107
+ DEF(Javanese, "Java")
108
+ DEF(Kaithi, "Kthi")
109
+ DEF(Kannada, "Knda")
110
+ DEF(Katakana, "Kana")
111
+ DEF(Katakana_Or_Hiragana, "Hrkt")
112
+ DEF(Kawi, "Kawi")
113
+ DEF(Kayah_Li, "Kali")
114
+ DEF(Kharoshthi, "Khar")
115
+ DEF(Khmer, "Khmr")
116
+ DEF(Khojki, "Khoj")
117
+ DEF(Khitan_Small_Script, "Kits")
118
+ DEF(Khudawadi, "Sind")
119
+ DEF(Kirat_Rai, "Krai")
120
+ DEF(Lao, "Laoo")
121
+ DEF(Latin, "Latn")
122
+ DEF(Lepcha, "Lepc")
123
+ DEF(Limbu, "Limb")
124
+ DEF(Linear_A, "Lina")
125
+ DEF(Linear_B, "Linb")
126
+ DEF(Lisu, "Lisu")
127
+ DEF(Lycian, "Lyci")
128
+ DEF(Lydian, "Lydi")
129
+ DEF(Makasar, "Maka")
130
+ DEF(Mahajani, "Mahj")
131
+ DEF(Malayalam, "Mlym")
132
+ DEF(Mandaic, "Mand")
133
+ DEF(Manichaean, "Mani")
134
+ DEF(Marchen, "Marc")
135
+ DEF(Masaram_Gondi, "Gonm")
136
+ DEF(Medefaidrin, "Medf")
137
+ DEF(Meetei_Mayek, "Mtei")
138
+ DEF(Mende_Kikakui, "Mend")
139
+ DEF(Meroitic_Cursive, "Merc")
140
+ DEF(Meroitic_Hieroglyphs, "Mero")
141
+ DEF(Miao, "Plrd")
142
+ DEF(Modi, "Modi")
143
+ DEF(Mongolian, "Mong")
144
+ DEF(Mro, "Mroo")
145
+ DEF(Multani, "Mult")
146
+ DEF(Myanmar, "Mymr")
147
+ DEF(Nabataean, "Nbat")
148
+ DEF(Nag_Mundari, "Nagm")
149
+ DEF(Nandinagari, "Nand")
150
+ DEF(New_Tai_Lue, "Talu")
151
+ DEF(Newa, "Newa")
152
+ DEF(Nko, "Nkoo")
153
+ DEF(Nushu, "Nshu")
154
+ DEF(Nyiakeng_Puachue_Hmong, "Hmnp")
155
+ DEF(Ogham, "Ogam")
156
+ DEF(Ol_Chiki, "Olck")
157
+ DEF(Ol_Onal, "Onao")
158
+ DEF(Old_Hungarian, "Hung")
159
+ DEF(Old_Italic, "Ital")
160
+ DEF(Old_North_Arabian, "Narb")
161
+ DEF(Old_Permic, "Perm")
162
+ DEF(Old_Persian, "Xpeo")
163
+ DEF(Old_Sogdian, "Sogo")
164
+ DEF(Old_South_Arabian, "Sarb")
165
+ DEF(Old_Turkic, "Orkh")
166
+ DEF(Old_Uyghur, "Ougr")
167
+ DEF(Oriya, "Orya")
168
+ DEF(Osage, "Osge")
169
+ DEF(Osmanya, "Osma")
170
+ DEF(Pahawh_Hmong, "Hmng")
171
+ DEF(Palmyrene, "Palm")
172
+ DEF(Pau_Cin_Hau, "Pauc")
173
+ DEF(Phags_Pa, "Phag")
174
+ DEF(Phoenician, "Phnx")
175
+ DEF(Psalter_Pahlavi, "Phlp")
176
+ DEF(Rejang, "Rjng")
177
+ DEF(Runic, "Runr")
178
+ DEF(Samaritan, "Samr")
179
+ DEF(Saurashtra, "Saur")
180
+ DEF(Sharada, "Shrd")
181
+ DEF(Shavian, "Shaw")
182
+ DEF(Siddham, "Sidd")
183
+ DEF(Sidetic, "Sidt")
184
+ DEF(SignWriting, "Sgnw")
185
+ DEF(Sinhala, "Sinh")
186
+ DEF(Sogdian, "Sogd")
187
+ DEF(Sora_Sompeng, "Sora")
188
+ DEF(Soyombo, "Soyo")
189
+ DEF(Sundanese, "Sund")
190
+ DEF(Sunuwar, "Sunu")
191
+ DEF(Syloti_Nagri, "Sylo")
192
+ DEF(Syriac, "Syrc")
193
+ DEF(Tagalog, "Tglg")
194
+ DEF(Tagbanwa, "Tagb")
195
+ DEF(Tai_Le, "Tale")
196
+ DEF(Tai_Tham, "Lana")
197
+ DEF(Tai_Viet, "Tavt")
198
+ DEF(Tai_Yo, "Tayo")
199
+ DEF(Takri, "Takr")
200
+ DEF(Tamil, "Taml")
201
+ DEF(Tangut, "Tang")
202
+ DEF(Telugu, "Telu")
203
+ DEF(Thaana, "Thaa")
204
+ DEF(Thai, "Thai")
205
+ DEF(Tibetan, "Tibt")
206
+ DEF(Tifinagh, "Tfng")
207
+ DEF(Tirhuta, "Tirh")
208
+ DEF(Tangsa, "Tnsa")
209
+ DEF(Todhri, "Todr")
210
+ DEF(Tolong_Siki, "Tols")
211
+ DEF(Toto, "Toto")
212
+ DEF(Tulu_Tigalari, "Tutg")
213
+ DEF(Ugaritic, "Ugar")
214
+ DEF(Vai, "Vaii")
215
+ DEF(Vithkuqi, "Vith")
216
+ DEF(Wancho, "Wcho")
217
+ DEF(Warang_Citi, "Wara")
218
+ DEF(Yezidi, "Yezi")
219
+ DEF(Yi, "Yiii")
220
+ DEF(Zanabazar_Square, "Zanb")
221
+ #endif
222
+
223
+ #ifdef UNICODE_PROP_LIST
224
+ /* Prop list not exported to regexp */
225
+ DEF(Hyphen, "")
226
+ DEF(Other_Math, "")
227
+ DEF(Other_Alphabetic, "")
228
+ DEF(Other_Lowercase, "")
229
+ DEF(Other_Uppercase, "")
230
+ DEF(Other_Grapheme_Extend, "")
231
+ DEF(Other_Default_Ignorable_Code_Point, "")
232
+ DEF(Other_ID_Start, "")
233
+ DEF(Other_ID_Continue, "")
234
+ DEF(Prepended_Concatenation_Mark, "")
235
+ /* additional computed properties for smaller tables */
236
+ DEF(ID_Continue1, "")
237
+ DEF(XID_Start1, "")
238
+ DEF(XID_Continue1, "")
239
+ DEF(Changes_When_Titlecased1, "")
240
+ DEF(Changes_When_Casefolded1, "")
241
+ DEF(Changes_When_NFKC_Casefolded1, "")
242
+
243
+ /* Prop list exported to JS */
244
+ DEF(ASCII_Hex_Digit, "AHex")
245
+ DEF(Bidi_Control, "Bidi_C")
246
+ DEF(Dash, "")
247
+ DEF(Deprecated, "Dep")
248
+ DEF(Diacritic, "Dia")
249
+ DEF(Extender, "Ext")
250
+ DEF(Hex_Digit, "Hex")
251
+ DEF(IDS_Unary_Operator, "IDSU")
252
+ DEF(IDS_Binary_Operator, "IDSB")
253
+ DEF(IDS_Trinary_Operator, "IDST")
254
+ DEF(Ideographic, "Ideo")
255
+ DEF(Join_Control, "Join_C")
256
+ DEF(Logical_Order_Exception, "LOE")
257
+ DEF(Modifier_Combining_Mark, "MCM")
258
+ DEF(Noncharacter_Code_Point, "NChar")
259
+ DEF(Pattern_Syntax, "Pat_Syn")
260
+ DEF(Pattern_White_Space, "Pat_WS")
261
+ DEF(Quotation_Mark, "QMark")
262
+ DEF(Radical, "")
263
+ DEF(Regional_Indicator, "RI")
264
+ DEF(Sentence_Terminal, "STerm")
265
+ DEF(Soft_Dotted, "SD")
266
+ DEF(Terminal_Punctuation, "Term")
267
+ DEF(Unified_Ideograph, "UIdeo")
268
+ DEF(Variation_Selector, "VS")
269
+ DEF(White_Space, "space")
270
+ DEF(Bidi_Mirrored, "Bidi_M")
271
+ DEF(Emoji, "")
272
+ DEF(Emoji_Component, "EComp")
273
+ DEF(Emoji_Modifier, "EMod")
274
+ DEF(Emoji_Modifier_Base, "EBase")
275
+ DEF(Emoji_Presentation, "EPres")
276
+ DEF(Extended_Pictographic, "ExtPict")
277
+ DEF(Default_Ignorable_Code_Point, "DI")
278
+ DEF(ID_Start, "IDS")
279
+ DEF(Case_Ignorable, "CI")
280
+
281
+ /* other binary properties */
282
+ DEF(ASCII,"")
283
+ DEF(Alphabetic, "Alpha")
284
+ DEF(Any, "")
285
+ DEF(Assigned,"")
286
+ DEF(Cased, "")
287
+ DEF(Changes_When_Casefolded, "CWCF")
288
+ DEF(Changes_When_Casemapped, "CWCM")
289
+ DEF(Changes_When_Lowercased, "CWL")
290
+ DEF(Changes_When_NFKC_Casefolded, "CWKCF")
291
+ DEF(Changes_When_Titlecased, "CWT")
292
+ DEF(Changes_When_Uppercased, "CWU")
293
+ DEF(Grapheme_Base, "Gr_Base")
294
+ DEF(Grapheme_Extend, "Gr_Ext")
295
+ DEF(ID_Continue, "IDC")
296
+ DEF(ID_Compat_Math_Start, "")
297
+ DEF(ID_Compat_Math_Continue, "")
298
+ DEF(Lowercase, "Lower")
299
+ DEF(Math, "")
300
+ DEF(Uppercase, "Upper")
301
+ DEF(XID_Continue, "XIDC")
302
+ DEF(XID_Start, "XIDS")
303
+
304
+ /* internal tables with index */
305
+ DEF(Cased1, "")
306
+
307
+ /* unused by us */
308
+ DEF(InCB, "")
309
+
310
+ #endif
package/index.js ADDED
@@ -0,0 +1,13 @@
1
+ import {dirname, join} from 'node:path'
2
+ import {fileURLToPath} from 'node:url'
3
+
4
+ const __dirname = dirname(fileURLToPath(import.meta.url))
5
+
6
+ /** Path to quickjs.cmake shared module */
7
+ export const cmakePath = join(__dirname, 'quickjs.cmake')
8
+
9
+ /** Path to QuickJS include directory */
10
+ export const includePath = join(__dirname, 'deps', 'quickjs')
11
+
12
+ /** Path to the qjsc bytecode compiler binary */
13
+ export const qjscPath = join(__dirname, 'bin', process.platform === 'win32' ? 'qjsc.exe' : 'qjsc')
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@mikrojs/quickjs",
3
+ "version": "0.0.7",
4
+ "description": "QuickJS-NG engine source, shared CMake module, and qjsc bytecode compiler",
5
+ "keywords": [
6
+ "bytecode",
7
+ "compiler",
8
+ "mikrojs",
9
+ "quickjs"
10
+ ],
11
+ "homepage": "https://github.com/mikrojs/mikrojs#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/mikrojs/mikrojs/issues"
14
+ },
15
+ "license": "MIT",
16
+ "author": "Bjørge Næss <bjoerge@gmail.com>",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/mikrojs/mikrojs.git"
20
+ },
21
+ "files": [
22
+ "deps/quickjs/*.c",
23
+ "deps/quickjs/*.h",
24
+ "deps/quickjs/LICENSE",
25
+ "index.js",
26
+ "postinstall.js",
27
+ "quickjs.cmake"
28
+ ],
29
+ "type": "module",
30
+ "sideEffects": false,
31
+ "exports": {
32
+ ".": "./index.js",
33
+ "./package.json": "./package.json"
34
+ },
35
+ "engines": {
36
+ "node": ">=24.0.0"
37
+ },
38
+ "scripts": {
39
+ "postinstall": "node postinstall.js"
40
+ }
41
+ }
package/postinstall.js ADDED
@@ -0,0 +1,125 @@
1
+ #!/usr/bin/env node
2
+ /* eslint-disable no-console */
3
+ /**
4
+ * Build the qjsc bytecode compiler from QuickJS source at install time.
5
+ * Produces bin/qjsc in the package directory.
6
+ *
7
+ * Uses cc directly (no cmake dependency) since qjsc is just a few C files.
8
+ * Skips gracefully if cc or the submodule is not available.
9
+ */
10
+ import {execFileSync} from 'node:child_process'
11
+ import {existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync} from 'node:fs'
12
+ import {dirname, join} from 'node:path'
13
+ import {fileURLToPath} from 'node:url'
14
+
15
+ const __dirname = dirname(fileURLToPath(import.meta.url))
16
+ const binDir = join(__dirname, 'bin')
17
+ const qjsDir = join(__dirname, 'deps', 'quickjs')
18
+ const patchesDir = join(__dirname, 'patches')
19
+ const repoRoot = join(__dirname, '..', '..', '..')
20
+
21
+ // Always sync submodule to the pinned commit
22
+ try {
23
+ execFileSync('git', ['submodule', 'update', '--init', 'packages/@mikrojs/quickjs/deps/quickjs'], {
24
+ cwd: repoRoot,
25
+ stdio: 'inherit',
26
+ })
27
+ } catch {
28
+ if (!existsSync(join(qjsDir, 'quickjs.c'))) {
29
+ console.error(
30
+ '@mikrojs/quickjs: Failed to initialize QuickJS submodule.\n' +
31
+ 'Run manually: git submodule update --init packages/@mikrojs/quickjs/deps/quickjs',
32
+ )
33
+ process.exit(1)
34
+ }
35
+ }
36
+
37
+ // Apply mikrojs-local patches to the submodule tree. Patches live in
38
+ // packages/@mikrojs/quickjs/patches/*.patch and are kept minimal.
39
+ // Applied idempotently: if `git apply --reverse --check` succeeds, the
40
+ // patch is already present, skip it.
41
+ applyPatches()
42
+
43
+ function applyPatches() {
44
+ if (!existsSync(patchesDir)) return
45
+ const files = readdirSync(patchesDir)
46
+ .filter((f) => f.endsWith('.patch'))
47
+ .sort()
48
+ for (const f of files) {
49
+ const patch = join(patchesDir, f)
50
+ // Probe: is the patch already applied?
51
+ try {
52
+ execFileSync('git', ['apply', '--reverse', '--check', patch], {
53
+ cwd: qjsDir,
54
+ stdio: 'pipe',
55
+ })
56
+ continue // already applied
57
+ } catch {
58
+ // not applied — fall through
59
+ }
60
+ try {
61
+ execFileSync('git', ['apply', patch], {cwd: qjsDir, stdio: 'inherit'})
62
+ console.log(`@mikrojs/quickjs: applied patch ${f}`)
63
+ } catch (err) {
64
+ console.error(`@mikrojs/quickjs: failed to apply ${f}`, err.message)
65
+ process.exit(1)
66
+ }
67
+ }
68
+ }
69
+
70
+ // Determine the current submodule commit to detect changes
71
+ let currentCommit = ''
72
+ try {
73
+ currentCommit = execFileSync('git', ['-C', qjsDir, 'rev-parse', 'HEAD'], {
74
+ encoding: 'utf8',
75
+ }).trim()
76
+ } catch {
77
+ // Not a git repo (e.g. published package), skip commit tracking
78
+ }
79
+
80
+ // On Windows the C compiler appends .exe automatically.
81
+ const exeSuffix = process.platform === 'win32' ? '.exe' : ''
82
+ const qjscPath = join(binDir, `qjsc${exeSuffix}`)
83
+
84
+ // Skip rebuild if qjsc exists and source hasn't changed
85
+ const stampFile = join(binDir, '.commit')
86
+ if (existsSync(qjscPath)) {
87
+ if (!currentCommit) {
88
+ // No git info (npm install): qjsc exists, sources are static, skip rebuild
89
+ process.exit(0)
90
+ }
91
+ const builtCommit = existsSync(stampFile) ? readFileSync(stampFile, 'utf8').trim() : ''
92
+ if (builtCommit === currentCommit) {
93
+ process.exit(0)
94
+ }
95
+ }
96
+
97
+ // Skip if cc is not available
98
+ try {
99
+ execFileSync('cc', ['--version'], {stdio: 'ignore'})
100
+ } catch {
101
+ console.log('@mikrojs/quickjs: C compiler not found, skipping qjsc build')
102
+ process.exit(0)
103
+ }
104
+
105
+ mkdirSync(binDir, {recursive: true})
106
+
107
+ const output = qjscPath
108
+ const sources = [
109
+ 'quickjs.c',
110
+ 'dtoa.c',
111
+ 'libunicode.c',
112
+ 'libregexp.c',
113
+ 'quickjs-libc.c',
114
+ 'qjsc.c',
115
+ ].map((f) => join(qjsDir, f))
116
+
117
+ console.log('@mikrojs/quickjs: Building qjsc...')
118
+ execFileSync('cc', ['-O2', '-D_GNU_SOURCE', '-I', qjsDir, '-o', output, ...sources, '-lm'], {
119
+ stdio: 'inherit',
120
+ })
121
+
122
+ if (currentCommit) {
123
+ writeFileSync(stampFile, currentCommit)
124
+ }
125
+ console.log('@mikrojs/quickjs: qjsc built successfully')
package/quickjs.cmake ADDED
@@ -0,0 +1,83 @@
1
+ # quickjs.cmake — shared CMake module for QuickJS-NG
2
+ #
3
+ # Provides:
4
+ # Target mode (normal CMake):
5
+ # - `quickjs` static library target
6
+ # Variable mode (ESP-IDF / source inclusion):
7
+ # - QUICKJS_SOURCES — list of source files
8
+ # - QUICKJS_INCLUDE_DIR — include directory
9
+ # - QUICKJS_COMPILE_OPTIONS — compiler flags for QuickJS sources
10
+ # Both modes:
11
+ # - QJSC_EXECUTABLE — path to the qjsc bytecode compiler
12
+ #
13
+ # Usage in normal CMake:
14
+ # include(<path>/quickjs.cmake)
15
+ # target_link_libraries(mylib PUBLIC quickjs)
16
+ #
17
+ # Usage in ESP-IDF component:
18
+ # include(<path>/quickjs.cmake)
19
+ # idf_component_register(SRCS ${QUICKJS_SOURCES} ...)
20
+ # target_include_directories(${COMPONENT_LIB} SYSTEM PUBLIC ${QUICKJS_INCLUDE_DIR})
21
+
22
+ # Include guard — safe for multiple includes
23
+ if(TARGET quickjs)
24
+ return()
25
+ endif()
26
+
27
+ # Resolve paths relative to this file
28
+ get_filename_component(_QUICKJS_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY)
29
+ set(QUICKJS_INCLUDE_DIR "${_QUICKJS_CMAKE_DIR}/deps/quickjs")
30
+
31
+ # Source files
32
+ set(QUICKJS_SOURCES
33
+ "${QUICKJS_INCLUDE_DIR}/quickjs.c"
34
+ "${QUICKJS_INCLUDE_DIR}/dtoa.c"
35
+ "${QUICKJS_INCLUDE_DIR}/libunicode.c"
36
+ "${QUICKJS_INCLUDE_DIR}/libregexp.c"
37
+ )
38
+
39
+ # Compiler flags for QuickJS sources.
40
+ #
41
+ # -fno-strict-aliasing defends against latent aliasing UB in the QuickJS
42
+ # sources miscompiling on 32-bit embedded targets. One real instance of
43
+ # this bit us: a `(int *)&uint32_t_var` cast in js_string_iterator_next
44
+ # was silently optimized away when uint32_t was typedef'd as
45
+ # `unsigned long` (as it is on riscv32-esp-elf), producing a String
46
+ # Iterator that never advanced. With strict aliasing off, GCC can't
47
+ # assume the pointer write through a differently-typed pointer misses
48
+ # the storage, so it reloads from memory and the code behaves as
49
+ # intended. Small codegen cost, predictable correctness — worth it for
50
+ # third-party code we don't audit exhaustively.
51
+ # MSVC understands neither GCC-style -W flags nor -fno-strict-aliasing; its
52
+ # default codegen also doesn't strict-alias (no /Oa equivalent in cl), so
53
+ # leaving the options empty for MSVC is the right call.
54
+ if(MSVC)
55
+ set(QUICKJS_COMPILE_OPTIONS "")
56
+ else()
57
+ set(QUICKJS_COMPILE_OPTIONS -Wno-implicit-fallthrough -Wno-sign-compare -fno-strict-aliasing)
58
+ endif()
59
+
60
+ # qjsc executable path (built by postinstall)
61
+ if(WIN32)
62
+ set(QJSC_EXECUTABLE "${_QUICKJS_CMAKE_DIR}/bin/qjsc.exe")
63
+ else()
64
+ set(QJSC_EXECUTABLE "${_QUICKJS_CMAKE_DIR}/bin/qjsc")
65
+ endif()
66
+
67
+ # ── Target mode: create a static library ────────────────────────────
68
+ # Only create the target if not in ESP-IDF component context
69
+ # (ESP-IDF uses idf_component_register with SRCS instead)
70
+ if(NOT ESP_PLATFORM)
71
+ add_library(quickjs STATIC ${QUICKJS_SOURCES})
72
+ set_target_properties(quickjs PROPERTIES POSITION_INDEPENDENT_CODE ON)
73
+ target_include_directories(quickjs SYSTEM PUBLIC "${QUICKJS_INCLUDE_DIR}")
74
+ target_compile_options(quickjs PRIVATE ${QUICKJS_COMPILE_OPTIONS})
75
+
76
+ # cutils.h has inline functions with C-style void* implicit conversions that are
77
+ # errors in C++. -fpermissive (GCC) downgrades them to warnings, then SYSTEM suppresses.
78
+ # Clang doesn't need this since QuickJS headers are SYSTEM includes; MSVC doesn't
79
+ # ship the flag and is silent on these anyway.
80
+ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
81
+ target_compile_options(quickjs INTERFACE $<$<COMPILE_LANGUAGE:CXX>:-fpermissive>)
82
+ endif()
83
+ endif()