class ShikiError extends Error { constructor(message) { super(message); this.name = 'ShikiError'; } } function getHeapMax() { return 2147483648; } function _emscripten_get_now() { return typeof performance !== 'undefined' ? performance.now() : Date.now(); } const alignUp = (x, multiple) => x + ((multiple - (x % multiple)) % multiple); async function main(init) { let wasmMemory; let buffer; const binding = {}; function updateGlobalBufferAndViews(buf) { buffer = buf; binding.HEAPU8 = new Uint8Array(buf); binding.HEAPU32 = new Uint32Array(buf); } function _emscripten_memcpy_big(dest, src, num) { binding.HEAPU8.copyWithin(dest, src, src + num); } function emscripten_realloc_buffer(size) { try { wasmMemory.grow((size - buffer.byteLength + 65535) >>> 16); updateGlobalBufferAndViews(wasmMemory.buffer); return 1; } catch { } } function _emscripten_resize_heap(requestedSize) { const oldSize = binding.HEAPU8.length; requestedSize = requestedSize >>> 0; const maxHeapSize = getHeapMax(); if (requestedSize > maxHeapSize) return false; for (let cutDown = 1; cutDown <= 4; cutDown *= 2) { let overGrownHeapSize = oldSize * (1 + 0.2 / cutDown); overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296); const newSize = Math.min(maxHeapSize, alignUp(Math.max(requestedSize, overGrownHeapSize), 65536)); const replacement = emscripten_realloc_buffer(newSize); if (replacement) return true; } return false; } const UTF8Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder('utf8') : undefined; function UTF8ArrayToString(heapOrArray, idx, maxBytesToRead = 1024) { const endIdx = idx + maxBytesToRead; let endPtr = idx; while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr; if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) { return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr)); } let str = ''; while (idx < endPtr) { let u0 = heapOrArray[idx++]; if (!(u0 & 128)) { str += String.fromCharCode(u0); continue; } const u1 = heapOrArray[idx++] & 63; if ((u0 & 224) === 192) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; } const u2 = heapOrArray[idx++] & 63; if ((u0 & 240) === 224) { u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; } else { u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63); } if (u0 < 65536) { str += String.fromCharCode(u0); } else { const ch = u0 - 65536; str += String.fromCharCode(55296 | (ch >> 10), 56320 | (ch & 1023)); } } return str; } function UTF8ToString(ptr, maxBytesToRead) { return ptr ? UTF8ArrayToString(binding.HEAPU8, ptr, maxBytesToRead) : ''; } const asmLibraryArg = { emscripten_get_now: _emscripten_get_now, emscripten_memcpy_big: _emscripten_memcpy_big, emscripten_resize_heap: _emscripten_resize_heap, fd_write: () => 0, }; async function createWasm() { const info = { env: asmLibraryArg, wasi_snapshot_preview1: asmLibraryArg, }; const exports = await init(info); wasmMemory = exports.memory; updateGlobalBufferAndViews(wasmMemory.buffer); Object.assign(binding, exports); binding.UTF8ToString = UTF8ToString; } await createWasm(); return binding; } /* --------------------------------------------------------- * Copyright (C) Microsoft Corporation. All rights reserved. *-------------------------------------------------------- */ let onigBinding = null; // let defaultDebugCall = false function throwLastOnigError(onigBinding) { throw new ShikiError(onigBinding.UTF8ToString(onigBinding.getLastOnigError())); } class UtfString { static _utf8ByteLength(str) { let result = 0; for (let i = 0, len = str.length; i < len; i++) { const charCode = str.charCodeAt(i); let codepoint = charCode; let wasSurrogatePair = false; if (charCode >= 0xD800 && charCode <= 0xDBFF) { // Hit a high surrogate, try to look for a matching low surrogate if (i + 1 < len) { const nextCharCode = str.charCodeAt(i + 1); if (nextCharCode >= 0xDC00 && nextCharCode <= 0xDFFF) { // Found the matching low surrogate codepoint = (((charCode - 0xD800) << 10) + 0x10000) | (nextCharCode - 0xDC00); wasSurrogatePair = true; } } } if (codepoint <= 0x7F) result += 1; else if (codepoint <= 0x7FF) result += 2; else if (codepoint <= 0xFFFF) result += 3; else result += 4; if (wasSurrogatePair) i++; } return result; } utf16Length; utf8Length; utf16Value; utf8Value; utf16OffsetToUtf8; utf8OffsetToUtf16; constructor(str) { const utf16Length = str.length; const utf8Length = UtfString._utf8ByteLength(str); const computeIndicesMapping = (utf8Length !== utf16Length); const utf16OffsetToUtf8 = computeIndicesMapping ? new Uint32Array(utf16Length + 1) : null; if (computeIndicesMapping) utf16OffsetToUtf8[utf16Length] = utf8Length; const utf8OffsetToUtf16 = computeIndicesMapping ? new Uint32Array(utf8Length + 1) : null; if (computeIndicesMapping) utf8OffsetToUtf16[utf8Length] = utf16Length; const utf8Value = new Uint8Array(utf8Length); let i8 = 0; for (let i16 = 0; i16 < utf16Length; i16++) { const charCode = str.charCodeAt(i16); let codePoint = charCode; let wasSurrogatePair = false; if (charCode >= 0xD800 && charCode <= 0xDBFF) { // Hit a high surrogate, try to look for a matching low surrogate if (i16 + 1 < utf16Length) { const nextCharCode = str.charCodeAt(i16 + 1); if (nextCharCode >= 0xDC00 && nextCharCode <= 0xDFFF) { // Found the matching low surrogate codePoint = (((charCode - 0xD800) << 10) + 0x10000) | (nextCharCode - 0xDC00); wasSurrogatePair = true; } } } if (computeIndicesMapping) { utf16OffsetToUtf8[i16] = i8; if (wasSurrogatePair) utf16OffsetToUtf8[i16 + 1] = i8; if (codePoint <= 0x7F) { utf8OffsetToUtf16[i8 + 0] = i16; } else if (codePoint <= 0x7FF) { utf8OffsetToUtf16[i8 + 0] = i16; utf8OffsetToUtf16[i8 + 1] = i16; } else if (codePoint <= 0xFFFF) { utf8OffsetToUtf16[i8 + 0] = i16; utf8OffsetToUtf16[i8 + 1] = i16; utf8OffsetToUtf16[i8 + 2] = i16; } else { utf8OffsetToUtf16[i8 + 0] = i16; utf8OffsetToUtf16[i8 + 1] = i16; utf8OffsetToUtf16[i8 + 2] = i16; utf8OffsetToUtf16[i8 + 3] = i16; } } if (codePoint <= 0x7F) { utf8Value[i8++] = codePoint; } else if (codePoint <= 0x7FF) { utf8Value[i8++] = 0b11000000 | ((codePoint & 0b00000000000000000000011111000000) >>> 6); utf8Value[i8++] = 0b10000000 | ((codePoint & 0b00000000000000000000000000111111) >>> 0); } else if (codePoint <= 0xFFFF) { utf8Value[i8++] = 0b11100000 | ((codePoint & 0b00000000000000001111000000000000) >>> 12); utf8Value[i8++] = 0b10000000 | ((codePoint & 0b00000000000000000000111111000000) >>> 6); utf8Value[i8++] = 0b10000000 | ((codePoint & 0b00000000000000000000000000111111) >>> 0); } else { utf8Value[i8++] = 0b11110000 | ((codePoint & 0b00000000000111000000000000000000) >>> 18); utf8Value[i8++] = 0b10000000 | ((codePoint & 0b00000000000000111111000000000000) >>> 12); utf8Value[i8++] = 0b10000000 | ((codePoint & 0b00000000000000000000111111000000) >>> 6); utf8Value[i8++] = 0b10000000 | ((codePoint & 0b00000000000000000000000000111111) >>> 0); } if (wasSurrogatePair) i16++; } this.utf16Length = utf16Length; this.utf8Length = utf8Length; this.utf16Value = str; this.utf8Value = utf8Value; this.utf16OffsetToUtf8 = utf16OffsetToUtf8; this.utf8OffsetToUtf16 = utf8OffsetToUtf16; } createString(onigBinding) { const result = onigBinding.omalloc(this.utf8Length); onigBinding.HEAPU8.set(this.utf8Value, result); return result; } } class OnigString { static LAST_ID = 0; static _sharedPtr = 0; // a pointer to a string of 10000 bytes static _sharedPtrInUse = false; id = (++OnigString.LAST_ID); _onigBinding; content; utf16Length; utf8Length; utf16OffsetToUtf8; utf8OffsetToUtf16; ptr; constructor(str) { if (!onigBinding) throw new ShikiError('Must invoke loadWasm first.'); this._onigBinding = onigBinding; this.content = str; const utfString = new UtfString(str); this.utf16Length = utfString.utf16Length; this.utf8Length = utfString.utf8Length; this.utf16OffsetToUtf8 = utfString.utf16OffsetToUtf8; this.utf8OffsetToUtf16 = utfString.utf8OffsetToUtf16; if (this.utf8Length < 10000 && !OnigString._sharedPtrInUse) { if (!OnigString._sharedPtr) OnigString._sharedPtr = onigBinding.omalloc(10000); OnigString._sharedPtrInUse = true; onigBinding.HEAPU8.set(utfString.utf8Value, OnigString._sharedPtr); this.ptr = OnigString._sharedPtr; } else { this.ptr = utfString.createString(onigBinding); } } convertUtf8OffsetToUtf16(utf8Offset) { if (this.utf8OffsetToUtf16) { if (utf8Offset < 0) return 0; if (utf8Offset > this.utf8Length) return this.utf16Length; return this.utf8OffsetToUtf16[utf8Offset]; } return utf8Offset; } convertUtf16OffsetToUtf8(utf16Offset) { if (this.utf16OffsetToUtf8) { if (utf16Offset < 0) return 0; if (utf16Offset > this.utf16Length) return this.utf8Length; return this.utf16OffsetToUtf8[utf16Offset]; } return utf16Offset; } dispose() { if (this.ptr === OnigString._sharedPtr) OnigString._sharedPtrInUse = false; else this._onigBinding.ofree(this.ptr); } } class OnigScanner { _onigBinding; _ptr; constructor(patterns) { if (!onigBinding) throw new ShikiError('Must invoke loadWasm first.'); const strPtrsArr = []; const strLenArr = []; for (let i = 0, len = patterns.length; i < len; i++) { const utfString = new UtfString(patterns[i]); strPtrsArr[i] = utfString.createString(onigBinding); strLenArr[i] = utfString.utf8Length; } const strPtrsPtr = onigBinding.omalloc(4 * patterns.length); onigBinding.HEAPU32.set(strPtrsArr, strPtrsPtr / 4); const strLenPtr = onigBinding.omalloc(4 * patterns.length); onigBinding.HEAPU32.set(strLenArr, strLenPtr / 4); const scannerPtr = onigBinding.createOnigScanner(strPtrsPtr, strLenPtr, patterns.length); for (let i = 0, len = patterns.length; i < len; i++) onigBinding.ofree(strPtrsArr[i]); onigBinding.ofree(strLenPtr); onigBinding.ofree(strPtrsPtr); if (scannerPtr === 0) throwLastOnigError(onigBinding); this._onigBinding = onigBinding; this._ptr = scannerPtr; } dispose() { this._onigBinding.freeOnigScanner(this._ptr); } findNextMatchSync(string, startPosition, arg) { // let debugCall = defaultDebugCall let options = 0 /* FindOption.None */; if (typeof arg === 'number') { // if (arg & FindOption.DebugCall) // debugCall = true options = arg; } if (typeof string === 'string') { string = new OnigString(string); const result = this._findNextMatchSync(string, startPosition, false, options); string.dispose(); return result; } return this._findNextMatchSync(string, startPosition, false, options); } _findNextMatchSync(string, startPosition, debugCall, options) { const onigBinding = this._onigBinding; // let resultPtr: Pointer // if (debugCall) // resultPtr = onigBinding.findNextOnigScannerMatchDbg(this._ptr, string.id, string.ptr, string.utf8Length, string.convertUtf16OffsetToUtf8(startPosition), options) // else const resultPtr = onigBinding.findNextOnigScannerMatch(this._ptr, string.id, string.ptr, string.utf8Length, string.convertUtf16OffsetToUtf8(startPosition), options); if (resultPtr === 0) { // no match return null; } const HEAPU32 = onigBinding.HEAPU32; let offset = resultPtr / 4; // byte offset -> uint32 offset const index = HEAPU32[offset++]; const count = HEAPU32[offset++]; const captureIndices = []; for (let i = 0; i < count; i++) { const beg = string.convertUtf8OffsetToUtf16(HEAPU32[offset++]); const end = string.convertUtf8OffsetToUtf16(HEAPU32[offset++]); captureIndices[i] = { start: beg, end, length: end - beg, }; } return { index, captureIndices, }; } } function isInstantiatorOptionsObject(dataOrOptions) { return (typeof dataOrOptions.instantiator === 'function'); } function isInstantiatorModule(dataOrOptions) { return (typeof dataOrOptions.default === 'function'); } function isDataOptionsObject(dataOrOptions) { return (typeof dataOrOptions.data !== 'undefined'); } function isResponse(dataOrOptions) { return (typeof Response !== 'undefined' && dataOrOptions instanceof Response); } function isArrayBuffer(data) { return (typeof ArrayBuffer !== 'undefined' && (data instanceof ArrayBuffer || ArrayBuffer.isView(data))) // eslint-disable-next-line node/prefer-global/buffer || (typeof Buffer !== 'undefined' && Buffer.isBuffer?.(data)) || (typeof SharedArrayBuffer !== 'undefined' && data instanceof SharedArrayBuffer) || (typeof Uint32Array !== 'undefined' && data instanceof Uint32Array); } let initPromise; function loadWasm(options) { if (initPromise) return initPromise; async function _load() { onigBinding = await main(async (info) => { let instance = options; instance = await instance; if (typeof instance === 'function') instance = await instance(info); if (typeof instance === 'function') instance = await instance(info); if (isInstantiatorOptionsObject(instance)) { instance = await instance.instantiator(info); } else if (isInstantiatorModule(instance)) { instance = await instance.default(info); } else { if (isDataOptionsObject(instance)) instance = instance.data; if (isResponse(instance)) { if (typeof WebAssembly.instantiateStreaming === 'function') instance = await _makeResponseStreamingLoader(instance)(info); else instance = await _makeResponseNonStreamingLoader(instance)(info); } else if (isArrayBuffer(instance)) { instance = await _makeArrayBufferLoader(instance)(info); } // import("shiki/onig.wasm") returns `{ default: WebAssembly.Module }` on cloudflare workers // https://developers.cloudflare.com/workers/wrangler/bundling/ else if (instance instanceof WebAssembly.Module) { instance = await _makeArrayBufferLoader(instance)(info); } else if ('default' in instance && instance.default instanceof WebAssembly.Module) { instance = await _makeArrayBufferLoader(instance.default)(info); } } if ('instance' in instance) instance = instance.instance; if ('exports' in instance) instance = instance.exports; return instance; }); } initPromise = _load(); return initPromise; } function _makeArrayBufferLoader(data) { return importObject => WebAssembly.instantiate(data, importObject); } function _makeResponseStreamingLoader(data) { return importObject => WebAssembly.instantiateStreaming(data, importObject); } function _makeResponseNonStreamingLoader(data) { return async (importObject) => { const arrayBuffer = await data.arrayBuffer(); return WebAssembly.instantiate(arrayBuffer, importObject); }; } // export function createOnigString(str: string) { // return new OnigString(str) // } // export function createOnigScanner(patterns: string[]) { // return new OnigScanner(patterns) // } // export function setDefaultDebugCall(_defaultDebugCall: boolean): void { // defaultDebugCall = _defaultDebugCall // } let _defaultWasmLoader; /** * Set the default wasm loader for `loadWasm`. * @internal */ function setDefaultWasmLoader(_loader) { _defaultWasmLoader = _loader; } /** * @internal */ function getDefaultWasmLoader() { return _defaultWasmLoader; } async function createOnigurumaEngine(options) { if (options) await loadWasm(options); return { createScanner(patterns) { return new OnigScanner(patterns); }, createString(s) { return new OnigString(s); }, }; } /** * Deprecated. Use `createOnigurumaEngine` instead. */ async function createWasmOnigEngine(options) { return createOnigurumaEngine(options); } export { createOnigurumaEngine, createWasmOnigEngine, getDefaultWasmLoader, loadWasm, setDefaultWasmLoader };