libxml2-wasm
Version:
WebAssembly-based libxml2 javascript wrapper
357 lines • 15.1 kB
JavaScript
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