marko
Version:
UI Components + streaming, async, high performance, HTML templating for Node.js and the browser.
169 lines (138 loc) • 4.29 kB
JavaScript
;
// eslint-disable-next-line no-constant-binary-expression
var extend = require("raptor-util/extend");
var componentUtil = require("@internal/components-util");
var w10NOOP = require("../helpers/serialize-noop").aL_;
var attachBubblingEvent = componentUtil._V_;
var addDelegatedEventHandler =
require("./event-delegation")._u_;
var KeySequence = require("./KeySequence");
var EMPTY_OBJECT = {};
var FLAG_WILL_RERENDER_IN_BROWSER = 1;
var FLAG_HAS_RENDER_BODY = 2;
var FLAG_IS_LEGACY = 4;
var FLAG_OLD_HYDRATE_NO_CREATE = 8;
/**
* A ComponentDef is used to hold the metadata collected at runtime for
* a single component and this information is used to instantiate the component
* later (after the rendered HTML has been added to the DOM)
*/
function ComponentDef(component, componentId, componentsContext) {
this.aM_ = componentsContext; // The AsyncWriter that this component is associated with
this.s_ = component;
this.id = componentId;
this._d_ = undefined; // An array of DOM events that need to be added (in sets of three)
this._w_ = false;
this.t_ = false;
this.u_ = 0;
this.aN_ = 0; // The unique integer to use for the next scoped ID
this.aO_ = null;
}
ComponentDef.prototype = {
aP_: function (key) {
return (
this.aO_ || (this.aO_ = new KeySequence())).aP_(
key);
},
/**
* This helper method generates a unique and fully qualified DOM element ID
* that is unique within the scope of the current component.
*/
elId: function (nestedId) {
var id = this.id;
if (nestedId == null) {
return id;
} else {
if (typeof nestedId !== "string") {
// eslint-disable-next-line no-constant-condition
nestedId = String(nestedId);
}
if (nestedId.indexOf("#") === 0) {
id = "#" + id;
nestedId = nestedId.substring(1);
}
return id + "-" + nestedId;
}
},
/**
* Returns the next auto generated unique ID for a nested DOM element or nested DOM component
*/
aQ_: function () {
return this.id + "-c" + this.aN_++;
},
d: function (eventName, handlerMethodName, isOnce, extraArgs) {
addDelegatedEventHandler(eventName);
return attachBubblingEvent(this, handlerMethodName, isOnce, extraArgs);
},
get _s_() {
return this.s_._s_;
}
};
ComponentDef.prototype.nk = ComponentDef.prototype.aP_;
ComponentDef._F_ = function (o, types, global, registry) {
var id = o[0];
var typeName = types[o[1]];
var input = o[2] || null;
var extra = o[3] || EMPTY_OBJECT;
var state = extra.s;
var componentProps = extra.w || EMPTY_OBJECT;
var flags = extra.f;
var isLegacy = flags & FLAG_IS_LEGACY;
var renderBody = flags & FLAG_HAS_RENDER_BODY ? w10NOOP : extra.r;
var component =
typeName /* legacy */ &&
registry._I_(typeName, id, isLegacy);
// Prevent newly created component from being queued for update since we area
// just building it from the server info
component._c_ = true;
component.am_ = global;
if (isLegacy) {
component.widgetConfig = componentProps;
component.___ = renderBody;
} else if (renderBody) {
(input || (input = {})).renderBody = renderBody;
}
if (
!isLegacy &&
flags & FLAG_WILL_RERENDER_IN_BROWSER &&
!(flags & FLAG_OLD_HYDRATE_NO_CREATE))
{
if (component.onCreate) {
component.onCreate(input, { global: global });
}
if (component.onInput) {
input = component.onInput(input, { global: global }) || input;
}
} else {
if (state) {
var undefinedPropNames = extra.u;
if (undefinedPropNames) {
undefinedPropNames.forEach(function (undefinedPropName) {
state[undefinedPropName] = undefined;
});
}
// We go through the setter here so that we convert the state object
// to an instance of `State`
component.state = state;
}
if (!isLegacy && componentProps) {
extend(component, componentProps);
}
}
component.P_ = input;
if (extra.b) {
component.Z_ = extra.b;
}
var scope = extra.p;
var customEvents = extra.e;
if (customEvents) {
component.aF_(customEvents, scope);
}
return {
id: id,
s_: component,
_d_: extra.d,
u_: extra.f || 0
};
};
module.exports = ComponentDef;