UNPKG

libxml2-wasm

Version:

WebAssembly-based libxml2 javascript wrapper

357 lines 15.1 kB
import moduleLoader from './libxml2raw.mjs'; 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(16, 'double'); // 8 bytes padding XmlXPathObjectStruct.stringval = getStringValueFunc(24); (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_ENTITY_REF_NODE"] = 5] = "XML_ENTITY_REF_NODE"; Type[Type["XML_COMMENT_NODE"] = 8] = "XML_COMMENT_NODE"; Type[Type["XML_DTD_NODE"] = 14] = "XML_DTD_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); } export function xmlNewReference(doc, name) { return withStringUTF8(name, (buf) => libxml2._xmlNewReference(doc, buf)); } /** * 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(); } export function xmlSaveOption(options) { if (!options) { return 1; // default is to format with default setting } let flags = 0; if (options.format) { flags |= 1 << 0; } if (options.noDeclaration) { flags |= 1 << 1; } if (options.noEmptyTags) { flags |= 1 << 2; } return flags; } const outputHandlerStorage = new ContextStorage(); const outputWrite = libxml2.addFunction((index, buf, len) => outputHandlerStorage.get(index) .write(libxml2.HEAPU8.subarray(buf, buf + len)), 'iiii'); const outputClose = libxml2.addFunction((index) => { const ret = outputHandlerStorage.get(index).close(); outputHandlerStorage.free(index); return ret; }, 'ii'); export function xmlSaveToIO(handler, encoding, format) { const index = outputHandlerStorage.allocate(handler); // will be freed in outputClose // Support only UTF-8 as of now return libxml2._xmlSaveToIO(outputWrite, outputClose, index, 0, format); } var XmlParserInputFlags; (function (XmlParserInputFlags) { XmlParserInputFlags[XmlParserInputFlags["XML_INPUT_BUF_STATIC"] = 2] = "XML_INPUT_BUF_STATIC"; XmlParserInputFlags[XmlParserInputFlags["XML_INPUT_BUF_ZERO_TERMINATED"] = 4] = "XML_INPUT_BUF_ZERO_TERMINATED"; XmlParserInputFlags[XmlParserInputFlags["XML_INPUT_UNZIP"] = 8] = "XML_INPUT_UNZIP"; XmlParserInputFlags[XmlParserInputFlags["XML_INPUT_NETWORK"] = 16] = "XML_INPUT_NETWORK"; })(XmlParserInputFlags || (XmlParserInputFlags = {})); export function xmlCtxtParseDtd(ctxt, mem, publicId, systemId) { return withCString(mem, (buf, len) => { const input = libxml2._xmlNewInputFromMemory(0, buf, len, XmlParserInputFlags.XML_INPUT_BUF_STATIC | XmlParserInputFlags.XML_INPUT_BUF_ZERO_TERMINATED); return withStrings((publicIdBuf, systemIdBuf) => libxml2._xmlCtxtParseDtd(ctxt, input, publicIdBuf, systemIdBuf), publicId, systemId); }); } export function xmlSaveSetIndentString(ctxt, indent) { return withStringUTF8(indent, (buf) => libxml2._xmlSaveSetIndentString(ctxt, buf)); } export const xmlAddChild = libxml2._xmlAddChild; export const xmlAddNextSibling = libxml2._xmlAddNextSibling; export const xmlAddPrevSibling = libxml2._xmlAddPrevSibling; export const xmlCtxtSetErrorHandler = libxml2._xmlCtxtSetErrorHandler; export const xmlCtxtValidateDtd = libxml2._xmlCtxtValidateDtd; export const xmlDocGetRootElement = libxml2._xmlDocGetRootElement; export const xmlDocSetRootElement = libxml2._xmlDocSetRootElement; export const xmlFreeDoc = libxml2._xmlFreeDoc; export const xmlFreeNode = libxml2._xmlFreeNode; export const xmlFreeDtd = libxml2._xmlFreeDtd; export const xmlFreeParserCtxt = libxml2._xmlFreeParserCtxt; export const xmlGetIntSubset = libxml2._xmlGetIntSubset; 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 xmlSaveClose = libxml2._xmlSaveClose; export const xmlSaveDoc = libxml2._xmlSaveDoc; export const xmlSaveTree = libxml2._xmlSaveTree; 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 xmlSchemaValidateOneElement = libxml2._xmlSchemaValidateOneElement; 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