UNPKG

libxml2-wasm

Version:

WebAssembly-based libxml2 javascript wrapper

315 lines 13.1 kB
import moduleLoader from './libxml2raw.cjs'; import { ContextStorage } from './utils.mjs'; const libxml2 = await moduleLoader(); libxml2._xmlInitParser(); /** * The base class for exceptions in this library. * * All exceptions thrown in this library will be instances of this class or its subclasses. */ export class XmlError extends Error { } /** * An exception class represents the error in libxml2. */ export class XmlLibError extends XmlError { constructor(message, details) { super(message); this.details = details; } } function allocUTF8Buffer(str) { if (!str) { return [0, 0]; } const len = libxml2.lengthBytesUTF8(str); const buf = libxml2._malloc(len + 1); libxml2.stringToUTF8(str, buf, len + 1); return [buf, len]; } function withStrings(process, ...strings) { const args = strings.map((str) => { const [buf] = allocUTF8Buffer(str); return buf; }); const ret = process(...args); args.forEach((buf) => { if (buf) { libxml2._free(buf); } }); return ret; } function withStringUTF8(str, process) { const [buf, len] = allocUTF8Buffer(str); const ret = process(buf, len); if (buf) { libxml2._free(buf); } return ret; } function moveUtf8ToString(cstr) { const str = libxml2.UTF8ToString(cstr); libxml2._free(cstr); return str; } function withCString(str, process) { if (!str) { return process(0, 0); } const buf = libxml2._malloc(str.length + 1); libxml2.HEAPU8.set(str, buf); libxml2.HEAPU8[buf + str.length] = 0; const ret = process(buf, str.length); libxml2._free(buf); return ret; } export function xmlReadString(ctxt, xmlString, url, encoding, options) { return withStringUTF8(xmlString, (xmlBuf, len) => withStrings((urlBuf) => libxml2._xmlCtxtReadMemory(ctxt, xmlBuf, len, urlBuf, 0, options), url)); } export function xmlReadMemory(ctxt, xmlBuffer, url, encoding, options) { return withCString(xmlBuffer, (xmlBuf, len) => withStrings((urlBuf) => libxml2._xmlCtxtReadMemory(ctxt, xmlBuf, len, urlBuf, 0, options), url)); } export function xmlXPathRegisterNs(ctx, prefix, uri) { return withStrings((bufPrefix, bufUri) => libxml2._xmlXPathRegisterNs(ctx, bufPrefix, bufUri), prefix, uri); } export function xmlHasNsProp(node, name, namespace) { return withStrings((bufName, bufNamespace) => libxml2._xmlHasNsProp(node, bufName, bufNamespace), name, namespace); } export function xmlSetNsProp(node, namespace, name, value) { return withStrings((bufName, bufValue) => libxml2._xmlSetNsProp(node, namespace, bufName, bufValue), name, value); } export function xmlNodeGetContent(node) { return moveUtf8ToString(libxml2._xmlNodeGetContent(node)); } export function xmlNodeSetContent(node, content) { return withStringUTF8(content, (buf, len) => libxml2._xmlNodeSetContentLen(node, buf, len)); } function getValueFunc(offset, type) { return (ptr) => { if (ptr === 0) { throw new XmlError('Access with null pointer'); } return libxml2.getValue(ptr + offset, type); }; } function nullableUTF8ToString(str) { if (str === 0) { return null; } return libxml2.UTF8ToString(str); } function getNullableStringValueFunc(offset) { return (ptr) => nullableUTF8ToString(libxml2.getValue(ptr + offset, 'i8*')); } function getStringValueFunc(offset) { return (ptr) => { if (ptr === 0) { throw new XmlError('Access with null pointer'); } return libxml2.UTF8ToString(libxml2.getValue(ptr + offset, 'i8*')); }; } export function xmlGetNsList(doc, node) { const nsList = libxml2._xmlGetNsList(doc, node); if (nsList === 0) { return []; } const arr = []; for (let offset = nsList / libxml2.HEAP32.BYTES_PER_ELEMENT; libxml2.HEAP32[offset]; offset += 1) { arr.push(libxml2.HEAP32[offset]); } libxml2._free(nsList); return arr; } export function xmlSearchNs(doc, node, prefix) { return withStrings((buf) => libxml2._xmlSearchNs(doc, node, buf), prefix); } export function xmlXPathCtxtCompile(ctxt, str) { return withStrings((buf) => libxml2._xmlXPathCtxtCompile(ctxt, buf), str); } export var error; (function (error) { error.storage = new ContextStorage(); error.errorCollector = libxml2.addFunction((index, err) => { const file = XmlErrorStruct.file(err); const detail = { message: XmlErrorStruct.message(err), line: XmlErrorStruct.line(err), col: XmlErrorStruct.col(err), }; if (file != null) { detail.file = file; } error.storage.get(index).push(detail); }, 'vii'); })(error || (error = {})); export class XmlXPathObjectStruct { } XmlXPathObjectStruct.type = getValueFunc(0, 'i32'); XmlXPathObjectStruct.nodesetval = getValueFunc(4, '*'); XmlXPathObjectStruct.boolval = getValueFunc(8, 'i32'); XmlXPathObjectStruct.floatval = getValueFunc(12, 'double'); XmlXPathObjectStruct.stringval = getStringValueFunc(20); (function (XmlXPathObjectStruct) { let Type; (function (Type) { Type[Type["XPATH_NODESET"] = 1] = "XPATH_NODESET"; Type[Type["XPATH_BOOLEAN"] = 2] = "XPATH_BOOLEAN"; Type[Type["XPATH_NUMBER"] = 3] = "XPATH_NUMBER"; Type[Type["XPATH_STRING"] = 4] = "XPATH_STRING"; })(Type = XmlXPathObjectStruct.Type || (XmlXPathObjectStruct.Type = {})); })(XmlXPathObjectStruct || (XmlXPathObjectStruct = {})); export class XmlNodeSetStruct { static nodeTable(nodeSetPtr, size) { // pointer to a pointer array, return the pointer array const tablePtr = libxml2.getValue(nodeSetPtr + 8, '*') / libxml2.HEAP32.BYTES_PER_ELEMENT; return libxml2.HEAP32.subarray(tablePtr, tablePtr + size); } } XmlNodeSetStruct.nodeCount = getValueFunc(0, 'i32'); export class XmlTreeCommonStruct { } XmlTreeCommonStruct.type = getValueFunc(4, 'i32'); XmlTreeCommonStruct.name_ = getStringValueFunc(8); XmlTreeCommonStruct.children = getValueFunc(12, '*'); XmlTreeCommonStruct.last = getValueFunc(16, '*'); XmlTreeCommonStruct.parent = getValueFunc(20, '*'); XmlTreeCommonStruct.next = getValueFunc(24, '*'); XmlTreeCommonStruct.prev = getValueFunc(28, '*'); XmlTreeCommonStruct.doc = getValueFunc(32, '*'); export class XmlNamedNodeStruct extends XmlTreeCommonStruct { } XmlNamedNodeStruct.namespace = getValueFunc(36, '*'); export class XmlNodeStruct extends XmlNamedNodeStruct { } XmlNodeStruct.properties = getValueFunc(44, '*'); XmlNodeStruct.nsDef = getValueFunc(48, '*'); XmlNodeStruct.line = getValueFunc(56, 'i32'); (function (XmlNodeStruct) { let Type; (function (Type) { Type[Type["XML_ELEMENT_NODE"] = 1] = "XML_ELEMENT_NODE"; Type[Type["XML_ATTRIBUTE_NODE"] = 2] = "XML_ATTRIBUTE_NODE"; Type[Type["XML_TEXT_NODE"] = 3] = "XML_TEXT_NODE"; Type[Type["XML_CDATA_SECTION_NODE"] = 4] = "XML_CDATA_SECTION_NODE"; Type[Type["XML_COMMENT_NODE"] = 8] = "XML_COMMENT_NODE"; })(Type = XmlNodeStruct.Type || (XmlNodeStruct.Type = {})); })(XmlNodeStruct || (XmlNodeStruct = {})); export class XmlNsStruct { } XmlNsStruct.next = getValueFunc(0, '*'); XmlNsStruct.href = getStringValueFunc(8); XmlNsStruct.prefix = getStringValueFunc(12); export class XmlAttrStruct extends XmlTreeCommonStruct { } export class XmlErrorStruct { } XmlErrorStruct.message = getStringValueFunc(8); XmlErrorStruct.file = getNullableStringValueFunc(16); XmlErrorStruct.line = getValueFunc(20, 'i32'); XmlErrorStruct.col = getValueFunc(40, 'i32'); export function xmlNewCDataBlock(doc, content) { return withStringUTF8(content, (buf, len) => libxml2._xmlNewCDataBlock(doc, buf, len)); } export function xmlNewDocComment(doc, content) { return withStringUTF8(content, (buf) => libxml2._xmlNewDocComment(doc, buf)); } export function xmlNewDocNode(doc, ns, name) { return withStrings((buf) => libxml2._xmlNewDocNode(doc, ns, buf, 0), name); } export function xmlNewDocText(doc, content) { return withStringUTF8(content, (buf, len) => libxml2._xmlNewDocTextLen(doc, buf, len)); } export function xmlNewNs(node, href, prefix) { return withStrings((bufHref, bufPrefix) => libxml2._xmlNewNs(node, bufHref, bufPrefix), href, prefix ?? null); } /** * Register the callbacks from the provider to the system. * * @param provider Provider of callbacks to be registered. * @alpha */ export function xmlRegisterInputProvider(provider) { const matchFunc = libxml2.addFunction((cfilename) => { const filename = libxml2.UTF8ToString(cfilename); return provider.match(filename) ? 1 : 0; }, 'ii'); const openFunc = libxml2.addFunction((cfilename) => { const filename = libxml2.UTF8ToString(cfilename); const res = provider.open(filename); return res === undefined ? 0 : res; }, 'ii'); const readFunc = libxml2.addFunction((fd, cbuf, len) => provider.read(fd, libxml2.HEAPU8.subarray(cbuf, cbuf + len)), 'iiii'); const closeFunc = libxml2.addFunction((fd) => (provider.close(fd) ? 0 : -1), 'ii'); const res = libxml2._xmlRegisterInputCallbacks(matchFunc, openFunc, readFunc, closeFunc); return res >= 0; } /** * Remove and cleanup all registered input providers. * @alpha */ export function xmlCleanupInputProvider() { libxml2._xmlCleanupInputCallbacks(); } const saveHandlerStorage = new ContextStorage(); const iowrite = libxml2.addFunction((index, buf, len) => saveHandlerStorage.get(index) .write(libxml2.HEAPU8.subarray(buf, buf + len)), 'iiii'); const ioclose = libxml2.addFunction((index) => { const ret = saveHandlerStorage.get(index).close(); saveHandlerStorage.free(index); return ret; }, 'ii'); export function xmlOutputBufferCreate(handler) { const index = saveHandlerStorage.allocate(handler); return libxml2._xmlOutputBufferCreateIO(iowrite, ioclose, index, 0); } export function xmlSaveFormatFileTo(buf, doc, encoding, format) { // Support only UTF-8 as of now return libxml2._xmlSaveFormatFileTo(buf, doc, 0, format); } export const xmlAddChild = libxml2._xmlAddChild; export const xmlAddNextSibling = libxml2._xmlAddNextSibling; export const xmlAddPrevSibling = libxml2._xmlAddPrevSibling; export const xmlCtxtSetErrorHandler = libxml2._xmlCtxtSetErrorHandler; export const xmlDocGetRootElement = libxml2._xmlDocGetRootElement; export const xmlDocSetRootElement = libxml2._xmlDocSetRootElement; export const xmlFreeDoc = libxml2._xmlFreeDoc; export const xmlFreeNode = libxml2._xmlFreeNode; export const xmlFreeParserCtxt = libxml2._xmlFreeParserCtxt; export const xmlGetLastError = libxml2._xmlGetLastError; export const xmlNewDoc = libxml2._xmlNewDoc; export const xmlNewParserCtxt = libxml2._xmlNewParserCtxt; export const xmlRelaxNGFree = libxml2._xmlRelaxNGFree; export const xmlRelaxNGFreeParserCtxt = libxml2._xmlRelaxNGFreeParserCtxt; export const xmlRelaxNGFreeValidCtxt = libxml2._xmlRelaxNGFreeValidCtxt; export const xmlRelaxNGNewDocParserCtxt = libxml2._xmlRelaxNGNewDocParserCtxt; export const xmlRelaxNGNewValidCtxt = libxml2._xmlRelaxNGNewValidCtxt; export const xmlRelaxNGParse = libxml2._xmlRelaxNGParse; export const xmlRelaxNGSetParserStructuredErrors = libxml2._xmlRelaxNGSetParserStructuredErrors; export const xmlRelaxNGSetValidStructuredErrors = libxml2._xmlRelaxNGSetValidStructuredErrors; export const xmlRelaxNGValidateDoc = libxml2._xmlRelaxNGValidateDoc; export const xmlRemoveProp = libxml2._xmlRemoveProp; export const xmlResetLastError = libxml2._xmlResetLastError; export const xmlSchemaFree = libxml2._xmlSchemaFree; export const xmlSchemaFreeParserCtxt = libxml2._xmlSchemaFreeParserCtxt; export const xmlSchemaFreeValidCtxt = libxml2._xmlSchemaFreeValidCtxt; export const xmlSchemaNewDocParserCtxt = libxml2._xmlSchemaNewDocParserCtxt; export const xmlSchemaNewValidCtxt = libxml2._xmlSchemaNewValidCtxt; export const xmlSchemaParse = libxml2._xmlSchemaParse; export const xmlSchemaSetParserStructuredErrors = libxml2._xmlSchemaSetParserStructuredErrors; export const xmlSchemaSetValidStructuredErrors = libxml2._xmlSchemaSetValidStructuredErrors; export const xmlSchemaValidateDoc = libxml2._xmlSchemaValidateDoc; export const xmlSetNs = libxml2._xmlSetNs; export const xmlUnlinkNode = libxml2._xmlUnlinkNode; export const xmlXIncludeFreeContext = libxml2._xmlXIncludeFreeContext; export const xmlXIncludeNewContext = libxml2._xmlXIncludeNewContext; export const xmlXIncludeProcessNode = libxml2._xmlXIncludeProcessNode; export const xmlXIncludeSetErrorHandler = libxml2._xmlXIncludeSetErrorHandler; export const xmlXPathCompiledEval = libxml2._xmlXPathCompiledEval; export const xmlXPathFreeCompExpr = libxml2._xmlXPathFreeCompExpr; export const xmlXPathFreeContext = libxml2._xmlXPathFreeContext; export const xmlXPathFreeObject = libxml2._xmlXPathFreeObject; export const xmlXPathNewContext = libxml2._xmlXPathNewContext; export const xmlXPathSetContextNode = libxml2._xmlXPathSetContextNode; //# sourceMappingURL=libxml2.mjs.map