@adpt/core
Version:
AdaptJS core library
115 lines • 4.73 kB
JavaScript
;
/*
* Copyright 2018-2019 Unbounded Systems, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const dom_parser_1 = require("@adpt/dom-parser");
const utils_1 = require("@adpt/utils");
const ld = tslib_1.__importStar(require("lodash"));
const util = tslib_1.__importStar(require("util"));
const error_1 = require("../error");
const handle_1 = require("../handle");
const jsx_1 = require("../jsx");
const reanimate_1 = require("./reanimate");
async function reanimateDom(xmlString, deployID, deployOpID) {
const domNodesRoot = await dom_parser_1.domFromString(xmlString);
if (domNodesRoot === null)
return null;
const handleReg = {
handles: [],
nodes: new Map(),
};
const dom = await reanimateNode(domNodesRoot, [], handleReg, deployID, deployOpID);
resolveHandles(handleReg);
return dom;
}
exports.reanimateDom = reanimateDom;
function updateLifecycle(domNode, elem, deployID, deployOpID) {
if (!domNode.lifecycleInfo)
return;
if (!jsx_1.isElementImpl(elem))
throw new error_1.InternalError("Element is not ElementImpl");
const info = domNode.lifecycleInfo;
if (elem.props.key !== ld.last(info.stateNamespace)) {
throw new Error(`Invalid DOM XML. Element key does not match stateNamespace: ${util.inspect(domNode)}`);
}
elem.mount(domNode.lifecycleInfo.stateNamespace.slice(0, -1), domNode.lifecycleInfo.path, domNode.lifecycleInfo.keyPath, deployID, deployOpID);
elem.reanimated = true;
}
async function makeHandle(val, handleReg) {
const ctor = await reanimate_1.reanimateUrn(val.urn);
const handle = new ctor(val);
if (handle_1.isHandleInternal(handle) && handle.unresolvedTarget !== null) {
handleReg.handles.push(handle);
}
return handle;
}
//val must be a pod, prototpyes are not preserved
async function convertHandles(val, handleReg) {
if (!(utils_1.isObject(val) || ld.isArray(val)))
return val;
if (utils_1.isObject(val) && handle_1.isHandleObj(val))
return makeHandle(val, handleReg);
if (ld.isArray(val)) {
const retP = val.map(async (v) => convertHandles(v, handleReg));
const ret = Promise.all(retP);
return ret;
}
if (utils_1.isObject(val)) {
const ret = {};
for (const key of Object.keys(val)) {
ret[key] = await convertHandles(val[key], handleReg);
}
return ret;
}
throw new error_1.InternalError(`should be unreachable: ${util.inspect(val)}`);
}
async function reanimateNode(domNode, parentPath, handleReg, deployID, deployOpID) {
const nodeKey = domNode.props.key;
if (typeof nodeKey !== "string")
throw new Error(`Invalid DOM XML. Element with no key: ${util.inspect(domNode)}`);
const keyPath = parentPath.concat([nodeKey]);
const component = await reanimate_1.reanimateUrn(domNode.uri);
const pChildren = jsx_1.childrenToArray(domNode.props.children).map(async (c) => {
if (!dom_parser_1.isDOMNode(c))
return convertHandles(c, handleReg);
return reanimateNode(c, keyPath, handleReg, deployID, deployOpID);
});
const children = await Promise.all(pChildren);
// Reanimate any DOMObjects
const props = {};
for (const k of Object.keys(domNode.props)) {
if (k === "children")
continue;
props[k] = await convertHandles(domNode.props[k], handleReg);
}
const node = jsx_1.createElement(component, props, ...children);
updateLifecycle(domNode, node, deployID, deployOpID);
handleReg.nodes.set(JSON.stringify(keyPath), node);
return node;
}
function resolveHandles(handleReg) {
for (const hand of handleReg.handles) {
const target = hand.unresolvedTarget;
if (target == null)
throw new error_1.InternalError(`target is null`);
const node = handleReg.nodes.get(JSON.stringify(target));
if (node == null)
throw new Error(`DOM reanimation error: cannot find DOM node path '${target}'`);
hand.associate(node);
}
}
//# sourceMappingURL=reanimate_dom.js.map