449 lines
16 KiB
JavaScript
449 lines
16 KiB
JavaScript
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") : void 0;
|
|
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;
|
|
}
|
|
|
|
var __defProp = Object.defineProperty;
|
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
let onigBinding = null;
|
|
function throwLastOnigError(onigBinding2) {
|
|
throw new ShikiError(onigBinding2.UTF8ToString(onigBinding2.getLastOnigError()));
|
|
}
|
|
class UtfString {
|
|
constructor(str) {
|
|
__publicField(this, "utf16Length");
|
|
__publicField(this, "utf8Length");
|
|
__publicField(this, "utf16Value");
|
|
__publicField(this, "utf8Value");
|
|
__publicField(this, "utf16OffsetToUtf8");
|
|
__publicField(this, "utf8OffsetToUtf16");
|
|
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 >= 55296 && charCode <= 56319) {
|
|
if (i16 + 1 < utf16Length) {
|
|
const nextCharCode = str.charCodeAt(i16 + 1);
|
|
if (nextCharCode >= 56320 && nextCharCode <= 57343) {
|
|
codePoint = (charCode - 55296 << 10) + 65536 | nextCharCode - 56320;
|
|
wasSurrogatePair = true;
|
|
}
|
|
}
|
|
}
|
|
if (computeIndicesMapping) {
|
|
utf16OffsetToUtf8[i16] = i8;
|
|
if (wasSurrogatePair)
|
|
utf16OffsetToUtf8[i16 + 1] = i8;
|
|
if (codePoint <= 127) {
|
|
utf8OffsetToUtf16[i8 + 0] = i16;
|
|
} else if (codePoint <= 2047) {
|
|
utf8OffsetToUtf16[i8 + 0] = i16;
|
|
utf8OffsetToUtf16[i8 + 1] = i16;
|
|
} else if (codePoint <= 65535) {
|
|
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 <= 127) {
|
|
utf8Value[i8++] = codePoint;
|
|
} else if (codePoint <= 2047) {
|
|
utf8Value[i8++] = 192 | (codePoint & 1984) >>> 6;
|
|
utf8Value[i8++] = 128 | (codePoint & 63) >>> 0;
|
|
} else if (codePoint <= 65535) {
|
|
utf8Value[i8++] = 224 | (codePoint & 61440) >>> 12;
|
|
utf8Value[i8++] = 128 | (codePoint & 4032) >>> 6;
|
|
utf8Value[i8++] = 128 | (codePoint & 63) >>> 0;
|
|
} else {
|
|
utf8Value[i8++] = 240 | (codePoint & 1835008) >>> 18;
|
|
utf8Value[i8++] = 128 | (codePoint & 258048) >>> 12;
|
|
utf8Value[i8++] = 128 | (codePoint & 4032) >>> 6;
|
|
utf8Value[i8++] = 128 | (codePoint & 63) >>> 0;
|
|
}
|
|
if (wasSurrogatePair)
|
|
i16++;
|
|
}
|
|
this.utf16Length = utf16Length;
|
|
this.utf8Length = utf8Length;
|
|
this.utf16Value = str;
|
|
this.utf8Value = utf8Value;
|
|
this.utf16OffsetToUtf8 = utf16OffsetToUtf8;
|
|
this.utf8OffsetToUtf16 = utf8OffsetToUtf16;
|
|
}
|
|
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 >= 55296 && charCode <= 56319) {
|
|
if (i + 1 < len) {
|
|
const nextCharCode = str.charCodeAt(i + 1);
|
|
if (nextCharCode >= 56320 && nextCharCode <= 57343) {
|
|
codepoint = (charCode - 55296 << 10) + 65536 | nextCharCode - 56320;
|
|
wasSurrogatePair = true;
|
|
}
|
|
}
|
|
}
|
|
if (codepoint <= 127)
|
|
result += 1;
|
|
else if (codepoint <= 2047)
|
|
result += 2;
|
|
else if (codepoint <= 65535)
|
|
result += 3;
|
|
else
|
|
result += 4;
|
|
if (wasSurrogatePair)
|
|
i++;
|
|
}
|
|
return result;
|
|
}
|
|
createString(onigBinding2) {
|
|
const result = onigBinding2.omalloc(this.utf8Length);
|
|
onigBinding2.HEAPU8.set(this.utf8Value, result);
|
|
return result;
|
|
}
|
|
}
|
|
const _OnigString = class _OnigString {
|
|
constructor(str) {
|
|
__publicField(this, "id", ++_OnigString.LAST_ID);
|
|
__publicField(this, "_onigBinding");
|
|
__publicField(this, "content");
|
|
__publicField(this, "utf16Length");
|
|
__publicField(this, "utf8Length");
|
|
__publicField(this, "utf16OffsetToUtf8");
|
|
__publicField(this, "utf8OffsetToUtf16");
|
|
__publicField(this, "ptr");
|
|
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 < 1e4 && !_OnigString._sharedPtrInUse) {
|
|
if (!_OnigString._sharedPtr)
|
|
_OnigString._sharedPtr = onigBinding.omalloc(1e4);
|
|
_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);
|
|
}
|
|
};
|
|
__publicField(_OnigString, "LAST_ID", 0);
|
|
__publicField(_OnigString, "_sharedPtr", 0);
|
|
// a pointer to a string of 10000 bytes
|
|
__publicField(_OnigString, "_sharedPtrInUse", false);
|
|
let OnigString = _OnigString;
|
|
class OnigScanner {
|
|
constructor(patterns) {
|
|
__publicField(this, "_onigBinding");
|
|
__publicField(this, "_ptr");
|
|
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 options = 0 /* None */;
|
|
if (typeof arg === "number") {
|
|
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 onigBinding2 = this._onigBinding;
|
|
const resultPtr = onigBinding2.findNextOnigScannerMatch(this._ptr, string.id, string.ptr, string.utf8Length, string.convertUtf16OffsetToUtf8(startPosition), options);
|
|
if (resultPtr === 0) {
|
|
return null;
|
|
}
|
|
const HEAPU32 = onigBinding2.HEAPU32;
|
|
let offset = resultPtr / 4;
|
|
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)) || 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);
|
|
} 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);
|
|
};
|
|
}
|
|
|
|
let _defaultWasmLoader;
|
|
function setDefaultWasmLoader(_loader) {
|
|
_defaultWasmLoader = _loader;
|
|
}
|
|
function getDefaultWasmLoader() {
|
|
return _defaultWasmLoader;
|
|
}
|
|
async function createOnigurumaEngine(options) {
|
|
if (options)
|
|
await loadWasm(options);
|
|
return {
|
|
createScanner(patterns) {
|
|
return new OnigScanner(patterns.map((p) => typeof p === "string" ? p : p.source));
|
|
},
|
|
createString(s) {
|
|
return new OnigString(s);
|
|
}
|
|
};
|
|
}
|
|
|
|
export { createOnigurumaEngine, getDefaultWasmLoader, loadWasm, setDefaultWasmLoader };
|