UNPKG

marko

Version:

UI Components + streaming, async, high performance, HTML templating for Node.js and the browser.

170 lines (142 loc) 4.8 kB
"use strict"; // eslint-disable-next-line no-constant-binary-expression var complain = "MARKO_DEBUG" && require("complain"); var extend = require("raptor-util/extend"); var componentUtil = require("@internal/components-util"); var w10NOOP = require("../helpers/serialize-noop").___noop; var attachBubblingEvent = componentUtil.___attachBubblingEvent; var addDelegatedEventHandler = require("./event-delegation").___addDelegatedEventHandler; 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.___componentsContext = componentsContext; // The AsyncWriter that this component is associated with this.___component = component; this.id = componentId; this.___domEvents = undefined; // An array of DOM events that need to be added (in sets of three) this.___isExisting = false; this.___renderBoundary = false; this.___flags = 0; this.___nextIdIndex = 0; // The unique integer to use for the next scoped ID this.___keySequence = null; } ComponentDef.prototype = { ___nextKey: function (key) { return ( this.___keySequence || (this.___keySequence = new KeySequence()) ).___nextKey(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 if ("MARKO_DEBUG") { complain("Using non strings as keys is deprecated."); } 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 */ ___nextComponentId: function () { return this.id + "-c" + this.___nextIdIndex++; }, d: function (eventName, handlerMethodName, isOnce, extraArgs) { addDelegatedEventHandler(eventName); return attachBubblingEvent(this, handlerMethodName, isOnce, extraArgs); }, get ___type() { return this.___component.___type; }, }; ComponentDef.prototype.nk = ComponentDef.prototype.___nextKey; ComponentDef.___deserialize = 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.___createComponent(typeName, id, isLegacy); // Prevent newly created component from being queued for update since we area // just building it from the server info component.___updateQueued = true; component.___global = global; if (isLegacy) { component.widgetConfig = componentProps; component.___widgetBody = 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.___input = input; if (extra.b) { component.___bubblingDomEvents = extra.b; } var scope = extra.p; var customEvents = extra.e; if (customEvents) { component.___setCustomEvents(customEvents, scope); } return { id: id, ___component: component, ___domEvents: extra.d, ___flags: extra.f || 0, }; }; module.exports = ComponentDef;