feat: bring forward most of the v4 legacy runtime

This commit is contained in:
Dylan Piercey 2023-05-23 10:56:29 -07:00 committed by Dylan Piercey
parent 4286236b0e
commit d4bdc443d2
57 changed files with 1606 additions and 127 deletions

View File

@ -0,0 +1,15 @@
<module-code(function(require, opts) {
var file = `"./${opts.optimize ? "dist" : "src"}/runtime/components/legacy"`;
if (opts.modules === "cjs") {
return `module.exports = require(${file});\n`;
} else {
return `export { default } from ${file};\nexport * from ${file};\n`;
}
})/>
// What's going on here? We are using Marko to do JavaScript code generation
// during the module bundling phase to conditionally export either the
// "src" or the "dist" folder based on whether or not we are doing a
// debug or non-debug build. We are using Marko since we know the Marko compiler
// is enabled already (no extra babel transform required).

View File

@ -0,0 +1,7 @@
var isDebug = require("./env").isDebug;
if (isDebug) {
module.exports = require("./src/runtime/components/legacy");
} else {
module.exports = require("./dist/runtime/components/legacy");
}

View File

@ -35,6 +35,7 @@
"browser": {
"./compiler.js": "./compiler-browser.marko",
"./components.js": "./components-browser.marko",
"./legacy-components.js": "./legacy-components-browser.marko",
"./index.js": "./index-browser.marko"
},
"types": "index.d.ts",
@ -50,6 +51,8 @@
"compiler.js",
"components-browser.marko",
"components.js",
"legacy-components-browser.marko",
"legacy-components.js",
"env.js",
"index.d.ts",
"index-browser.marko",

View File

@ -4,6 +4,7 @@ const ComponentDef = require("../../../runtime/components/ComponentDef");
var FLAG_WILL_RERENDER_IN_BROWSER = 1;
// var FLAG_HAS_RENDER_BODY = 2;
var FLAG_OLD_HYDRATE_NO_CREATE = 8;
module.exports = function beginComponent(
componentsContext,
@ -11,15 +12,20 @@ module.exports = function beginComponent(
key,
ownerComponentDef,
isSplitComponent,
isImplicitComponent
isImplicitComponent,
existingComponentDef
) {
var componentId = component.id;
var componentDef = (componentsContext.___componentDef = new ComponentDef(
component,
componentId,
componentsContext
));
// existingComponentDef is only here to allow binding a conditional
// widget. It should be removed when the legacy compat layer is removed.
var componentDef =
existingComponentDef ||
(componentsContext.___componentDef = new ComponentDef(
component,
componentId,
componentsContext
));
var ownerIsRenderBoundary =
ownerComponentDef && ownerComponentDef.___renderBoundary;
@ -54,6 +60,10 @@ module.exports = function beginComponent(
componentsContext.___isPreserved = false;
}
if (out.global.oldHydrateNoCreate === true) {
componentDef.___flags |= FLAG_OLD_HYDRATE_NO_CREATE;
}
if ((ownerIsRenderBoundary || ownerWillRerender) && key != null) {
out.w(
"<!--" +

View File

@ -0,0 +1,331 @@
"use strict";
/* jshint newcap:false */
var BaseState;
var BaseComponent;
var inherit;
var loader = require("@internal/loader");
var registry = require("@internal/components-registry");
var jQuery = require("../../../runtime/components/legacy/jquery");
var ready = require("../../../runtime/components/legacy/ready");
var complain = "MARKO_DEBUG" && require("complain");
var stateToJSONDef = {
enumerable: false,
value: function returnSelf() {
return this;
}
};
function noop() { }
module.exports = function defineWidget(def, renderer) {
def = def.Widget || def;
if (def.___isComponent) {
return def;
}
var ComponentClass = function () { };
var proto;
var legacyInit;
if (typeof def === "function") {
proto = def.prototype;
legacyInit = def;
} else if (typeof def === "object") {
proto = def;
legacyInit = def.init;
} else {
throw TypeError();
}
ComponentClass.prototype = proto;
// We don't use the constructor provided by the user
// since we don't invoke their constructor until
// we have had a chance to do our own initialization.
// Instead, we store their constructor in the "initComponent"
// property and that method gets called later inside
// init-components-browser.js
function Component(id, doc) {
BaseComponent.call(this, id, doc);
}
if (!proto.___isComponent) {
// Inherit from Component if they didn't already
ComponentClass.prototype = Object.create(BaseComponent.prototype);
for (var propName in proto) {
if (proto.hasOwnProperty(propName)) {
ComponentClass.prototype[propName] = proto[propName];
}
}
}
// The same prototype will be used by our constructor after
// we he have set up the prototype chain using the inherit function
proto = Component.prototype = ComponentClass.prototype;
proto.___isLegacy = true;
proto.constructor = def.constructor = Component;
Object.defineProperty(proto, "state", {
get: function () {
var raw = this.___state && this.___state.___raw;
if (raw && !raw.toJSON) {
Object.defineProperty(this.___state.___raw, "toJSON", stateToJSONDef);
}
return raw;
},
set: function (newState) {
newState = newState || {};
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
if (
Object.keys(newState).sort().join("") !==
Object.keys((this.___state && this.___state.___raw) || {})
.sort()
.join("")
)
complain(
"'widget.state = newState' has changed from merging the newState to replacing the old state."
);
}
this.setState(newState);
}
});
Object.defineProperty(proto, "__document", {
get: function () {
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
complain("__document is deprecated");
}
return this.___host;
}
});
Object.defineProperty(proto, "el", {
get: function () {
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
if (
this.___currentLegacyBindEl !==
(this.___rootNode && this.___rootNode.firstChild)
) {
complain(
"this.el no longer returns the `w-bind` element and instead returns the first node in the template. Assign a key to the w-bind element and use getEl(key) instead."
);
}
}
return this.___currentLegacyBindEl;
}
});
// get legacy methods
proto.___legacyOnRender = proto.onRender;
Object.defineProperty(proto, "onRender", {
get: noop,
set: function (v) {
proto.___legacyOnRender = v;
}
});
proto.___legacyOnUpdate = proto.onUpdate;
Object.defineProperty(proto, "onUpdate", {
get: function () {
return modernMountOrUpdate;
},
set: function (v) {
proto.___legacyOnUpdate = v;
}
});
proto.___legacyOnDestroy = proto.onDestroy;
Object.defineProperty(proto, "onDestroy", {
get: function () {
return modernOnDestory;
},
set: function (v) {
proto.___legacyOnDestroy = v;
}
});
proto.getWidget = proto.getComponent;
proto.getWidgets = proto.getComponents;
proto.onMount = modernMountOrUpdate;
if (legacyInit) {
proto.___legacyInit = legacyInit;
}
// convert legacy to modern
proto.___modernUpdate = proto.update;
proto.update = function () {
if (this.___destroyed) {
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
complain(
"widget was updated after it was destroyed, if this widget is migrated to a modern component this will become a noop.",
{
location: this.___type
}
);
}
this.destroy = modernOnDestory;
this.___destroyed = false;
}
this.___legacyExplicitUpdate = true;
if (this.___currentLegacyBindEl) {
this.onBeforeUpdate && this.onBeforeUpdate();
}
this.___modernUpdate();
this.___legacyExplicitUpdate = false;
};
function modernMountOrUpdate() {
var self = this;
var el = this.___keyedElements["@_wbind"];
var prevEl = this.___currentLegacyBindEl;
if (prevEl !== el) {
this.___currentLegacyBindEl = el;
if (prevEl) {
this.onBeforeDestroy && this.onBeforeDestroy();
this.___legacyOnDestroy && this.___legacyOnDestroy();
this.___legacyRender = undefined;
this.removeAllListeners();
}
if (el) {
this.___legacyInit && this.___legacyInit(this.widgetConfig || {});
this.___legacyOnRender && this.___legacyOnRender({ firstRender: true });
this.___legacyRender = legacyRender;
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
Object.defineProperty(el, "__widget", {
configurable: true,
get: function () {
complain("__widget is deprecated");
return self;
}
});
} else {
el.__widget = this;
}
}
} else if (el) {
if (prevEl) {
this.___legacyOnUpdate && this.___legacyOnUpdate();
}
if (this.___didUpdate) {
this.___legacyOnRender &&
this.___legacyOnRender({ firstRender: false });
}
}
this.___widgetProps = this.___input;
this.___input = null;
this.___didUpdate = false;
}
function legacyRender() {
if (!this.___legacyExplicitUpdate) {
this.onBeforeUpdate && this.onBeforeUpdate();
}
this.___didUpdate = true;
}
function modernOnDestory() {
if (this.___currentLegacyBindEl) {
this.onBeforeDestroy && this.onBeforeDestroy();
this.___legacyOnDestroy && this.___legacyOnDestroy();
this.___currentLegacyBindEl = null;
}
}
// Set a flag on the constructor function to make it clear this is
// a component so that we can short-circuit this work later
Component.___isComponent = true;
function State() {
BaseState.apply(this, arguments);
}
inherit(State, BaseState);
proto.___State = State;
jQuery.patchComponent(
window.$,
proto,
true /* don't throw error until used if `$` is missing*/
);
ready.patchComponent(proto);
if (!renderer) {
renderer = ComponentClass.renderer || ComponentClass.prototype.renderer;
if (renderer) {
// Legacy support
var createOut = renderer.createOut;
if (typeof renderer !== "function") {
var rendererObject = renderer;
renderer = function (input, out) {
var rendererFunc = rendererObject.renderer || rendererObject.render;
rendererFunc(input, out);
};
renderer.createOut = createOut;
}
renderer.render = function (input) {
var out = createOut();
renderer(input, out);
return out.end();
};
}
}
if (renderer) {
// Add the rendering related methods as statics on the
// new component constructor function
Component.renderer = proto.___renderer = renderer;
Component.render = renderer.render;
Component.renderSync = renderer.renderSync;
}
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
Object.defineProperty(Component, "_isWidget", {
get: function () {
complain("_isWidget is deprecated");
return true;
}
});
} else {
Component._isWidget = true;
}
var template = def.template;
if (template) {
if (typeof template === "string") {
template = loader(template);
}
registry.r(template.___typeName, function () { return Component });
}
return Component;
};
BaseState = require("../../../runtime/components/State");
BaseComponent = require("../../../runtime/components/Component");
inherit = require("raptor-util/inherit");

View File

@ -0,0 +1,18 @@
module.exports = function defineWidget(def, renderer) {
if (def.___isComponent) {
return def;
}
if (renderer) {
return {
___isComponent: true,
_isWidget: true,
renderer: renderer,
render: renderer.render,
renderSync: renderer.renderSync,
template: renderer.template
};
} else {
return { ___isComponent: true, _isWidget: true };
}
};

View File

@ -0,0 +1,11 @@
{
"main": "./index.js",
"browser": "./index-browser.js",
"exports": {
".": {
"worker": "./index.js",
"browser": "./index-browser.js",
"default": "./index.js"
}
}
}

View File

@ -0,0 +1,74 @@
var Component = require("../../../runtime/components/Component");
var loader = require("@internal/loader");
var getComponentForEl =
require("@internal/components-util").___getComponentForEl;
var complain = "MARKO_DEBUG" && require("complain");
// expose legacy
require("@internal/components-registry").___legacy = exports;
exports.load = function (typeName) {
return exports.defineWidget(loader(typeName));
};
// legacy api
exports.defineComponent = require("../../../runtime/components/legacy/defineComponent-legacy");
exports.defineWidget = require("@internal/components-define-widget-legacy");
exports.defineRenderer = require("../../../runtime/components/legacy/defineRenderer-legacy");
exports.makeRenderable = exports.renderable = require("../../../runtime/renderable");
// browser only
var Widget = (exports.Widget = Component);
exports.getWidgetForEl = exports.get = function (elOrId) {
var el = elOrId;
if (typeof elOrId === "string") {
el = document.getElementById(elOrId);
}
if (el && el.__widget) {
return el.__widget;
}
return getComponentForEl(el);
};
exports.initWidgets =
require("@internal/components-registry").___initServerRendered;
// monkey patch Widget
if (Widget) {
var WidgetProto = Widget.prototype;
WidgetProto.setProps = function (newInput) {
this.___isReceivingNewInput = true;
this.___setInput(newInput);
};
WidgetProto.rerender = function (newInput) {
if (newInput) {
this.setProps(newInput);
}
this.forceUpdate();
this.update();
};
}
var RenderResult = require("../../../runtime/RenderResult");
RenderResult.prototype.getWidget = function () {
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
complain("getWidget is deprecated. use getComponent instead.");
}
return this.getWidgets()[0];
};
RenderResult.prototype.getWidgets = function () {
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
complain("getWidgets is deprecated. use getComponents instead.");
}
return RenderResult.prototype.getComponents
.apply(this, arguments)
.filter(function (component) {
return component.___isLegacy;
});
};

View File

@ -0,0 +1,15 @@
var modernMarko = require("@internal/components-entry");
// legacy api
exports.defineComponent = require("../../../runtime/components/legacy/defineComponent-legacy");
exports.defineWidget = require("@internal/components-define-widget-legacy");
exports.defineRenderer = require("../../../runtime/components/legacy/defineRenderer-legacy");
exports.makeRenderable = exports.renderable = require("../../../runtime/renderable");
// server only
exports.writeInitWidgetsCode = modernMarko.writeInitComponentsCode;
exports.getRenderedWidgets = exports.getRenderedWidgetIds =
modernMarko.getRenderedComponents;
exports.getInitWidgetsCode = function (out) {
return modernMarko.___getInitComponentsCode(out);
};

View File

@ -0,0 +1,11 @@
{
"main": "./index.js",
"browser": "./index-browser.js",
"exports": {
".": {
"worker": "./index.js",
"browser": "./index-browser.js",
"default": "./index.js"
}
}
}

View File

@ -7,6 +7,8 @@ var DEFAULT_RUNTIME_ID = "M";
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;
function safeJSONReplacer(match) {
if (match === "</") {
@ -65,55 +67,80 @@ function addComponentsFromContext(componentsContext, componentsToHydrate) {
var id = componentDef.id;
var component = componentDef.___component;
var flags = componentDef.___flags;
var isLegacy = componentDef.___isLegacy;
var state = component.state;
var input = component.input || 0;
var typeName = component.typeName;
var customEvents = component.___customEvents;
var scope = component.___scope;
var bubblingDomEvents = component.___bubblingDomEvents;
var state;
var needsState;
var serializedProps;
var undefinedPropNames;
var renderBody;
if (flags & FLAG_WILL_RERENDER_IN_BROWSER) {
if (typeof input.renderBody === "function") {
flags |= FLAG_HAS_RENDER_BODY;
if (isLegacy) {
flags |= FLAG_IS_LEGACY;
renderBody = component.___widgetBody;
if (component.widgetConfig && isNotEmpty(component.widgetConfig)) {
serializedProps = component.widgetConfig;
}
needsState = true;
} else {
if (input && input.renderBody) {
renderBody = input.renderBody;
input.renderBody = undefined;
}
} else {
if (component.state) {
state = component.state;
// Update state properties with an `undefined` value to have a `null`
// value so that the property name will be serialized down to the browser.
// This ensures that we add the proper getter/setter for the state property.
const stateKeys = Object.keys(state);
for (let i = stateKeys.length; i--; ) {
const stateKey = stateKeys[i];
if (state[stateKey] === undefined) {
if (undefinedPropNames) {
undefinedPropNames.push(stateKey);
} else {
undefinedPropNames = [stateKey];
}
if (
!(flags & FLAG_WILL_RERENDER_IN_BROWSER) ||
flags & FLAG_OLD_HYDRATE_NO_CREATE
) {
component.___state = undefined; // We don't use `delete` to avoid V8 deoptimization
component.___input = undefined; // We don't use `delete` to avoid V8 deoptimization
component.typeName = undefined;
component.id = undefined;
component.___customEvents = undefined;
component.___scope = undefined;
component.___bubblingDomEvents = undefined;
component.___bubblingDomEventsExtraArgsCount = undefined;
component.___updatedInput = undefined;
component.___updateQueued = undefined;
needsState = true;
if (isNotEmpty(component)) {
serializedProps = component;
}
}
}
var undefinedPropNames = undefined;
if (needsState && state) {
// Update state properties with an `undefined` value to have a `null`
// value so that the property name will be serialized down to the browser.
// This ensures that we add the proper getter/setter for the state property.
const stateKeys = Object.keys(state);
for (let i = stateKeys.length; i--; ) {
const stateKey = stateKeys[i];
if (state[stateKey] === undefined) {
if (undefinedPropNames) {
undefinedPropNames.push(stateKey);
} else {
undefinedPropNames = [stateKey];
}
}
}
}
component.___state = undefined; // We don't use `delete` to avoid V8 deoptimization
component.___input = undefined; // We don't use `delete` to avoid V8 deoptimization
component.typeName = undefined;
component.id = undefined;
component.___customEvents = undefined;
component.___scope = undefined;
component.___bubblingDomEvents = undefined;
component.___bubblingDomEventsExtraArgsCount = undefined;
component.___updatedInput = undefined;
component.___updateQueued = undefined;
if (isNotEmpty(component)) {
serializedProps = component;
}
if (typeof renderBody === "function") {
flags |= FLAG_HAS_RENDER_BODY;
renderBody = undefined;
}
var extra = {
@ -122,9 +149,10 @@ function addComponentsFromContext(componentsContext, componentsToHydrate) {
e: customEvents,
f: flags || undefined,
p: customEvents && scope, // Only serialize scope if we need to attach custom events
s: state,
s: needsState && state,
u: undefinedPropNames,
w: serializedProps
w: serializedProps,
r: renderBody
};
var parts = [id, typeName];

View File

@ -8,6 +8,7 @@ var createFragmentNode =
var ComponentDef = require("../../../runtime/components/ComponentDef");
var domData = require("../../../runtime/components/dom-data");
var componentsUtil = require("@internal/components-util");
var loader = require("@internal/loader");
var componentLookup = componentsUtil.___componentLookup;
var addComponentRootToKeyedElements =
componentsUtil.___addComponentRootToKeyedElements;
@ -72,13 +73,23 @@ function addPendingDef(def, type, meta, host, runtimeId) {
]);
}
function load(typeName) {
function load(typeName, isLegacy) {
var target = loaded[typeName];
if (!target) {
target = registered[typeName];
if (target) {
target = target();
} else if (isLegacy) {
target = exports.___legacy.load(typeName);
} else {
target = loader(typeName);
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
complain(
"Looks like you used `require:` in your browser.json to load a component. This requires that Marko has knowledge of how lasso generates paths and will be removed in a future version. `marko-dependencies:/path/to/template.marko` should be used instead."
);
}
}
if (!target) {
@ -91,14 +102,14 @@ function load(typeName) {
return target;
}
function getComponentClass(typeName) {
function getComponentClass(typeName, isLegacy) {
var ComponentClass = componentTypes[typeName];
if (ComponentClass) {
return ComponentClass;
}
ComponentClass = load(typeName);
ComponentClass = load(typeName, isLegacy);
ComponentClass = ComponentClass.Component || ComponentClass;
@ -124,6 +135,7 @@ function getComponentClass(typeName) {
.replace(/^[^a-z$_]/i, "_$&")
.replace(/[^0-9a-z$_]+/gi, "_");
className = className[0].toUpperCase() + className.slice(1);
// eslint-disable-next-line no-unused-vars
var OldComponentClass = ComponentClass;
ComponentClass = {
[className]: function (id, doc) {
@ -138,8 +150,8 @@ function getComponentClass(typeName) {
return ComponentClass;
}
function createComponent(typeName, id) {
var ComponentClass = getComponentClass(typeName);
function createComponent(typeName, id, isLegacy) {
var ComponentClass = getComponentClass(typeName, isLegacy);
return new ComponentClass(id);
}
@ -290,6 +302,10 @@ function addDOMEventListeners(
function initComponent(componentDef, host) {
var component = componentDef.___component;
if (!component || !component.___isComponent) {
return; // legacy
}
component.___reset();
component.___host = host;
@ -479,7 +495,18 @@ function initServerRendered(renderedComponents, host) {
.map(function (componentDef) {
var typeName = meta.___types[componentDef[1]];
return registered[typeName]
return (
registered[typeName] ||
document.readyState === "complete" ||
(
// loader.runtime is only going to exist for lasso apps
// this code is used to detect if a module was registered
// via a browser.json but not executed.
loader.runtime &&
loader.runtime.resolve &&
loader.runtime.resolve(typeName)
)
)
? tryHydrateComponent(componentDef, meta, host, runtimeId)
: addPendingDef(componentDef, typeName, meta, host, runtimeId);
})

View File

@ -5,6 +5,16 @@ function nextComponentIdProvider(out) {
var prefix = out.global.componentIdPrefix || out.global.widgetIdPrefix || "s"; // "s" is for server (we use "b" for the browser)
var nextId = 0;
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
if (out.global.widgetIdPrefix) {
require("complain")(
"$global.widgetIdPrefix is deprecated. use $global.componentIdPrefix instead.",
{ location: false }
);
}
}
return function nextComponentId() {
return prefix + nextId++;
};

View File

@ -247,19 +247,17 @@ Component.prototype = componentProto = {
},
getEl: function (key, index) {
if (key) {
var keyedElement =
this.___keyedElements["@" + resolveKeyHelper(key, index)];
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
if (
keyedElement &&
keyedElement.nodeType !== 1 /* Node.ELEMENT_NODE */
) {
throw new Error(
"Using 'getEl(key)' to get a component instance is not supported, did you mean 'getComponent(key)'?"
var resolvedKey = resolveKeyHelper(key, index);
var keyedElement = this.___keyedElements["@" + resolvedKey];
if (keyedElement && keyedElement.nodeType === 12 /** FRAGMENT_NODE */) {
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
complain(
"Accessing the elements of a child component using 'component.getEl' is deprecated."
);
}
return walkFragments(keyedElement);
}
return keyedElement;
@ -281,15 +279,15 @@ Component.prototype = componentProto = {
},
getComponent: function (key, index) {
var rootNode = this.___keyedElements["@" + resolveKeyHelper(key, index)];
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
if (/\[\]$/.test(key)) {
throw new Error(
if (/\[\]$/.test(key)) {
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
complain(
"A repeated key[] was passed to getComponent. Use a non-repeating key if there is only one of these components."
);
}
rootNode = rootNode && rootNode[Object.keys(rootNode)[0]];
}
return rootNode && componentsByDOMNode.get(rootNode);
},
getComponents: function (key) {

View File

@ -11,6 +11,8 @@ 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
@ -93,19 +95,31 @@ ComponentDef.___deserialize = function (o, types, global, registry) {
var extra = o[3] || EMPTY_OBJECT;
var state = extra.s;
var componentProps = extra.w;
var componentProps = extra.w || EMPTY_OBJECT;
var flags = extra.f;
var component = registry.___createComponent(typeName, id);
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;
if (flags & FLAG_HAS_RENDER_BODY) {
(input || (input = {})).renderBody = w10Noop;
if (isLegacy) {
component.widgetConfig = componentProps;
component.___widgetBody = renderBody;
} else if (renderBody) {
(input || (input = {})).renderBody = renderBody;
}
if (flags & FLAG_WILL_RERENDER_IN_BROWSER) {
if (
!isLegacy &&
flags & FLAG_WILL_RERENDER_IN_BROWSER &&
!(flags & FLAG_OLD_HYDRATE_NO_CREATE)
) {
if (component.onCreate) {
component.onCreate(input, { global: global });
}
@ -125,7 +139,7 @@ ComponentDef.___deserialize = function (o, types, global, registry) {
component.state = state;
}
if (componentProps) {
if (!isLegacy && componentProps) {
extend(component, componentProps);
}
}

View File

@ -0,0 +1,9 @@
{
"dependencies": [
{
"type": "require",
"path": "./index",
"run": true
}
]
}

View File

@ -0,0 +1,32 @@
/**
* Define a new UI component that includes component and renderer.
*
* @param {Object} def The definition of the UI component (component methods, component constructor, rendering methods, etc.)
* @return {Component} The resulting Component with renderer
*/
var defineRenderer;
var defineWidget;
module.exports = function defineComponent(def) {
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
require("complain")("defineComponent is deprecated");
}
if (def.___isComponent) {
return def;
}
var renderer;
if (def.template || def.renderer) {
renderer = defineRenderer(def);
} else {
throw new Error('Expected "template" or "renderer"');
}
return defineWidget(def, renderer);
};
defineRenderer = require("./defineRenderer-legacy");
defineWidget = require("./defineWidget-legacy");

View File

@ -0,0 +1,171 @@
var complain = "MARKO_DEBUG" && require("complain");
var makeRenderable = require("../../renderable");
var getComponentsContext =
require("../ComponentsContext").___getComponentsContext;
var componentLookup = require("@internal/components-util").___componentLookup;
var modernRenderer = require("../renderer");
var loader = require("@internal/loader");
var resolveComponentKey = modernRenderer.___resolveComponentKey;
module.exports = function defineRenderer(renderingLogic) {
var renderer = renderingLogic.renderer;
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
require("complain")("defineRenderer is deprecated");
}
if (renderer && renderer.___isRenderer) {
return renderer;
}
var template = renderingLogic.template;
if (typeof template === "string") {
template = loader(template);
}
if (!renderer) {
var getInitialProps;
var getTemplateData;
var getInitialState;
var getWidgetConfig;
var getInitialBody;
if (renderingLogic) {
getInitialProps = renderingLogic.getInitialProps;
getTemplateData = renderingLogic.getTemplateData;
getInitialState = renderingLogic.getInitialState;
getWidgetConfig = renderingLogic.getWidgetConfig;
getInitialBody = renderingLogic.getInitialBody;
}
// Create a renderer function that takes care of translating
// the input properties to a view state. Also, this renderer
// takes care of re-using existing components.
renderer = function renderer(input, out) {
var componentsContext = getComponentsContext(out);
var globalComponentsContext = componentsContext.___globalContext;
var component = globalComponentsContext.___rerenderComponent;
var isReceivingNewInput = !component || component.___isReceivingNewInput;
var parentComponentDef;
if (component) {
component.___isReceivingNewInput = false;
}
// Render the template associated with the component using the final template
// data that we constructed
var newProps = input;
var widgetConfig;
var widgetState;
var widgetBody;
var id;
if (!component && componentLookup) {
var key = out.___assignedKey;
if (
(parentComponentDef = componentsContext.___componentDef) &&
key != null
) {
id = resolveComponentKey(key.toString(), parentComponentDef);
} else if (parentComponentDef) {
id = parentComponentDef.___nextComponentId();
} else {
id = globalComponentsContext.___nextComponentId();
}
component = componentLookup[id];
}
if (isReceivingNewInput) {
// If we do not have state then we need to go through the process
// of converting the input to a widget state, or simply normalizing
// the input using getInitialProps
if (getInitialProps) {
// This optional method is used to normalize input state
newProps = getInitialProps(newProps, out) || {};
}
if (getInitialState) {
// This optional method is used to derive the widget state
// from the input properties
widgetState = getInitialState(newProps, out);
}
if (getInitialBody) {
// If we have widget a widget body then pass it to the template
// so that it is available to the widget tag and can be inserted
// at the w-body marker
widgetBody = getInitialBody(newProps, out);
} else {
// Default to using the nested content as the widget body
// getInitialBody was not implemented
widgetBody = newProps.renderBody;
}
} else if (component) {
newProps = newProps || component.___widgetProps;
widgetBody = component.___widgetBody;
widgetState = component.___rawState;
widgetConfig = component.widgetConfig;
}
// Use getTemplateData(state, props, out) to get the template
// data. If that method is not provided then just use the
// the state (if provided) or the input data.
var templateData = clone(
getTemplateData
? getTemplateData(widgetState, newProps, out)
: widgetState || newProps
);
if (isReceivingNewInput && getWidgetConfig) {
// If getWidgetConfig() was implemented then use that to
// get the widget config. The widget config will be passed
// to the widget constructor. If rendered on the server the
// widget config will be serialized.
widgetConfig = getWidgetConfig(newProps, out);
}
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
if (widgetState && "widgetState" in templateData) {
complain("Passing widgetState as input is deprecated.");
}
if (widgetConfig && "widgetConfig" in templateData) {
complain("Passing widgetConfig as input is deprecated.");
}
}
templateData.widgetProps = newProps;
widgetBody && (templateData.renderBody = widgetBody);
widgetState && (templateData.widgetState = widgetState);
widgetConfig && (templateData.widgetConfig = widgetConfig);
template._(templateData, out, id, renderingLogic);
};
}
renderer.___isRenderer = true;
renderer.createOut = template ? template.createOut : renderingLogic.createOut;
renderer.template = template;
makeRenderable(renderer, renderer);
renderer.render = renderer.render.bind(this);
return renderer;
};
function clone(src) {
var result = {};
if (src) {
for (var key in src) {
result[key] = src[key];
}
}
return result;
}

View File

@ -0,0 +1 @@
module.exports = require("@internal/components-define-widget-legacy");

View File

@ -0,0 +1,3 @@
var patch = require("./").patch;
var Template = require("../../../html").Template;
patch(Template);

View File

@ -0,0 +1,178 @@
var nodePath = require("path");
var defaultResolveFrom = require("resolve-from");
var env = process.env.NODE_ENV;
var production = !env || env !== "development";
function getRootDeps(template, context) {
if (production && template.___depsArray) {
return template.___depsArray;
}
attachDepsAndComponentsToTemplate(template, context);
var deps = (template.___depsArray = Object.keys(template.___deps).map(
(key) => template.___deps[key]
));
var initModule = getInitModule(template.path, template.___components);
if (initModule) deps.push(initModule);
// these dependencies should be last
deps.concat = function () {
var result = [];
result = result.concat.apply(result, arguments);
result.push.apply(result, this);
return result;
};
return deps;
}
function attachDepsAndComponentsToTemplate(target, context) {
var template;
if (!target.meta && target.template) {
template = target.template;
} else {
template = target;
}
if (typeof template.createOut !== "function") return;
if (production && target.___deps) return;
var deps = (target.___deps = {});
var components = (target.___components = {});
if (!template.meta) {
// eslint-disable-next-line no-console
console.warn("Metadata not set for template at ", template.path);
return;
}
var meta = template.meta;
var root = nodePath.dirname(template.path);
if (meta.deps) {
meta.deps.forEach((dep) => {
dep = resolveDep(dep, root, context);
deps[dep.virtualPath || dep.path] = dep;
});
}
if (meta.id && meta.component) {
var resolveFrom = (context && context.resolveFrom) || defaultResolveFrom;
components[meta.id] = {
id: meta.id,
path: resolveFrom(root, meta.component),
};
}
if (meta.tags) {
meta.tags.forEach((tagPath) => {
var resolveFrom = context.resolveFrom || defaultResolveFrom;
var tag = resolveFrom(root, tagPath);
var ext = nodePath.extname(tag);
var req = context.require || require;
try {
tag = req.resolve(tag.slice(0, 0 - ext.length) + ".js");
} catch (e) {
/* ignore error */
}
tag = req(tag);
attachDepsAndComponentsToTemplate(tag, context);
if (tag.___deps) Object.assign(deps, tag.___deps);
if (tag.___components) Object.assign(components, tag.___components);
});
}
}
function getInitModule(path, components) {
var module = null;
if (components) {
components = Object.keys(components).map((key) => components[key]);
if (components.length) {
var root = nodePath.dirname(path);
var virtualPath = path + ".init.js";
var registrations = components.map(
(component) =>
`components.register('${component.id}', require('.${
nodePath.sep
}${nodePath.relative(root, component.path)}'));`
);
var code = `
var components = require('marko/components');
${registrations.join("\n")}
`;
module = {
type: "require",
run: true,
virtualModule: {
path: virtualPath,
read: function (_, callback) {
// TODO: Check if read can just return string in lasso 2
if (callback) {
callback(null, code);
} else {
return code;
}
},
},
};
}
}
return module;
}
function resolveDep(dep, root, context) {
if (typeof dep === "string") {
dep = parseDependencyString(dep);
}
if (dep.path) {
var resolveFrom = (context && context.resolveFrom) || defaultResolveFrom;
dep.path = resolveFrom(root, dep.path);
if (dep.path && !dep.type) {
dep.type = dep.path.slice(dep.path.lastIndexOf(".") + 1);
}
}
if (dep.virtualPath) {
dep.virtualPath = nodePath.resolve(root, dep.virtualPath);
}
if (dep.type === "js") {
dep.type = "require";
dep.run = true;
}
return dep;
}
function parseDependencyString(string) {
var match = /^(?:([\w-]+)(?::\s*|\s+))?(.*?(?:\.(\w+))?)$/.exec(string);
return {
type: match[1] || match[3],
path: match[2],
};
}
function patch(Template) {
Template.prototype.getDependencies = function (context) {
context = context || {};
return getRootDeps(this, context);
};
}
exports.getDeps = getRootDeps;
exports.resolveDep = resolveDep;
exports.patch = patch;

View File

@ -0,0 +1,3 @@
var patch = require("./").patch;
var Template = require("../../../vdom").Template;
patch(Template);

View File

@ -0,0 +1 @@
module.exports = require("@internal/components-entry-legacy");

View File

@ -0,0 +1,51 @@
var ready = require("./ready");
var idRegExp = /^#(\S+)( .*)?/;
exports.patchComponent = function (jQuery, proto, delayThrow) {
if (!(jQuery || (jQuery = window.$)) && !delayThrow) {
throw new Error("jQuery not found");
}
(proto || require("../Component").prototype).$ = function jqueryProxy(arg) {
var args = arguments;
var self = this;
if (!jQuery) {
throw new Error("jQuery not found");
}
if (args.length === 1) {
//Handle an "ondomready" callback function
if (typeof arg === "function") {
return ready(function () {
arg.call(self);
});
} else if (typeof arg === "string") {
var match = idRegExp.exec(arg);
//Reset the search to 0 so the next call to exec will start from the beginning for the new string
if (match != null) {
var key = match[1];
if (match[2] == null) {
return jQuery(self.getEl(key));
} else {
return jQuery(match[2].trim(), self.getEl(key));
}
} else {
var rootEl = self.getEl();
if (!rootEl) {
throw new Error("Root element is not defined for component");
}
if (rootEl) {
return jQuery(arg, rootEl);
}
}
}
} else if (args.length === 2 && typeof args[1] === "string") {
return jQuery(arg, self.getEl(args[1]));
} else if (args.length === 0) {
return jQuery(self.el);
}
return jQuery.apply(window, arguments);
};
};

View File

@ -0,0 +1,152 @@
/*
jQuery's doc.ready/$(function(){}) should
you wish to use a cross-browser domReady solution
without opting for a library.
Demo: http://jsfiddle.net/zKLpb/
usage:
$(function(){
// your code
});
Parts: jQuery project, Diego Perini, Lucent M.
Previous version from Addy Osmani (https://raw.github.com/addyosmani/jquery.parts/master/jquery.documentReady.js)
This version: Patrick Steele-Idem
- Converted to CommonJS module
- Code cleanup
- Fixes for IE <=10
*/
var isReady = false;
var readyBound = false;
var defaultWindow = typeof window != "undefined" && window;
var defaultDocument = typeof document != "undefined" && document;
var listeners = [];
function domReadyCallback() {
for (var i = 0, len = listeners.length; i < len; i++) {
var listener = listeners[i];
listener[0].call(listener[1]);
}
listeners = null;
}
function bindReady(doc) {
var toplevel = false;
var win = doc.defaultView || defaultWindow || doc;
// Handle when the DOM is ready
function domReady() {
// Make sure that the DOM is not already loaded
if (!isReady) {
// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
if (!doc.body) {
return setTimeout(domReady, 1);
}
// Remember that the DOM is ready
isReady = true;
// If there are functions bound, to execute
domReadyCallback();
// Execute all of them
}
} // /ready()
// The ready event handler
function domContentLoaded() {
if (doc.addEventListener) {
doc.removeEventListener("DOMContentLoaded", domContentLoaded, false);
doc.removeEventListener("load", domContentLoaded, false);
} else {
// we're here because readyState !== "loading" in oldIE
// which is good enough for us to call the dom ready!
doc.detachEvent("onreadystatechange", domContentLoaded);
doc.detachEvent("onload", domContentLoaded);
}
domReady();
}
// The DOM ready check for Internet Explorer
function doScrollCheck() {
if (isReady) {
return;
}
try {
// If IE is used, use the trick by Diego Perini
// http://javascript.nwbox.com/IEContentLoaded/
doc.documentElement.doScroll("left");
} catch (error) {
setTimeout(doScrollCheck, 1);
return;
}
// and execute any waiting functions
domReady();
}
// Catch cases where $ is called after the
// browser event has already occurred. IE <= 10 has a bug that results in 'interactive' being assigned
// to the readyState before the DOM is really ready
if (
document.attachEvent
? document.readyState === "complete"
: document.readyState !== "loading"
) {
// We will get here if the browser is IE and the readyState === 'complete' or the browser
// is not IE and the readyState === 'interactive' || 'complete'
domReady(doc);
} else if (doc.addEventListener) {
// Standards-based browsers support DOMContentLoaded
// Use the handy event callback
doc.addEventListener("DOMContentLoaded", domContentLoaded, false);
// A fallback to win.onload, that will always work
win.addEventListener("load", domContentLoaded, false);
// If IE event model is used
} else if (doc.attachEvent) {
// ensure firing before onload,
// maybe late but safe also for iframes
doc.attachEvent("onreadystatechange", domContentLoaded);
// A fallback to win.onload, that will always work
win.attachEvent("onload", domContentLoaded);
// If IE and not a frame
// continually check to see if the document is ready
try {
toplevel = win.frameElement == null;
} catch (e) {
/* ignore error */
}
if (doc.documentElement.doScroll && toplevel) {
doScrollCheck();
}
}
}
function ready(callback, thisObj, doc) {
if (isReady) {
return callback.call(thisObj);
}
listeners.push([callback, thisObj]);
if (!readyBound) {
readyBound = true;
bindReady(doc || defaultDocument);
}
}
module.exports = ready;
module.exports.patchComponent = function (proto) {
if (proto && proto.ready) {
// Don't patch if the component has overwritten the ready method.
return;
}
(proto || require("../Component").prototype).ready = function (callback) {
var document = this.el.ownerDocument;
ready(callback, this, document);
};
};

View File

@ -0,0 +1,230 @@
var getComponentsContext =
require("../ComponentsContext").___getComponentsContext;
var componentsUtil = require("@internal/components-util");
var componentLookup = componentsUtil.___componentLookup;
var registry = require("@internal/components-registry");
var modernRenderer = require("../renderer");
var resolveComponentKey = modernRenderer.___resolveComponentKey;
var trackAsyncComponents = modernRenderer.___trackAsyncComponents;
var beginComponent = require("@internal/components-beginComponent");
var endComponent = require("@internal/components-endComponent");
var complain = "MARKO_DEBUG" && require("complain");
function createRendererFunc(templateRenderFunc, componentProps) {
var typeName = componentProps.t;
//var assignedId = componentProps.id;
var isSplit = componentProps.s === true;
var isImplicit = componentProps.i === true;
return function renderer(input, out, assignedId, renderingLogic) {
trackAsyncComponents(out);
var componentsContext = getComponentsContext(out);
var parentLegacyComponentDef = componentsContext.___legacyComponentDef;
if (isImplicit && parentLegacyComponentDef) {
templateRenderFunc(
input,
out,
parentLegacyComponentDef,
parentLegacyComponentDef.___component,
parentLegacyComponentDef.___component.___rawState,
out.global
);
return;
}
var widgetBody = input.renderBody;
var widgetState = input.widgetState;
var widgetConfig = input.widgetConfig;
var globalComponentsContext = componentsContext.___globalContext;
var component = globalComponentsContext.___rerenderComponent;
var isRerender = component !== undefined;
var id = assignedId;
var isExisting;
var parentComponentDef = componentsContext.___componentDef;
var ownerComponentDef = out.___assignedComponentDef;
var ownerComponentId = ownerComponentDef && ownerComponentDef.id;
var key = out.___assignedKey;
var customEvents = out.___assignedCustomEvents;
out.___assignedComponentDef = null;
if (component) {
id = component.id;
isExisting = true;
globalComponentsContext.___rerenderComponent = null;
} else {
if (key != null) {
id = id || resolveComponentKey(key.toString(), parentComponentDef);
} else if (parentComponentDef) {
id = parentComponentDef.___nextComponentId();
} else {
id = globalComponentsContext.___nextComponentId();
}
}
if (registry.___isServer && typeName) {
if (renderingLogic) delete renderingLogic.onRender;
component = registry.___createComponent(
renderingLogic,
id,
input,
out,
typeName,
customEvents,
ownerComponentId
);
if (isSplit || widgetState) {
component.input = null;
} else if (input.widgetProps) {
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
complain(
"Possible performance impact: this widget does not contain state, but is marked as a stateful widget. This will result in additional hydration data serialized. In order for marko to identify this as a split widget, w-bind should use a widget.js with defineWidget rather than index.js with defineComponent.",
{ location: typeName, level: 1 }
);
}
component.input = input.widgetProps;
}
} else {
if (!component) {
if (isRerender) {
// Look in in the DOM to see if a component with the same ID and type already exists.
component = componentLookup[id];
if (component && component.___type !== typeName) {
component = undefined;
}
}
if (component) {
isExisting = true;
} else {
isExisting = false;
// We need to create a new instance of the component
if (typeName) {
component = registry.___createComponent(typeName, id);
}
}
}
}
var isFakeComponent = false;
if (!component) {
isFakeComponent = true;
component = {
id: id,
___keyedElements: {},
};
} else {
component.___updateQueued = true;
if (widgetState) {
component.state = widgetState;
}
}
component.widgetConfig = widgetConfig;
component.___widgetBody = widgetBody || component.___widgetBody;
var componentDef = beginComponent(
componentsContext,
component,
key,
ownerComponentDef,
isSplit,
isFakeComponent
);
componentsContext.___legacyComponentDef = componentDef;
// This is a hack, but we have to swap out the component instance stored with this node
var vComponentNode = out.___parent;
componentDef.___component = isFakeComponent ? null : component;
componentDef.___isExisting = isExisting;
componentDef.___isLegacy = true;
componentDef.t = function (typeName) {
if (typeName) {
if (registry.___isServer) {
var oldComponent = component;
if (renderingLogic) delete renderingLogic.onRender;
component = registry.___createComponent(
renderingLogic || {},
id,
input,
out,
typeName,
customEvents,
ownerComponentId
);
if (isSplit || widgetState) {
component.input = null;
} else if (input.widgetProps) {
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
complain(
"Possible performance impact: this widget does not contain state, but is marked as a stateful widget. This will result in additional hydration data serialized. In order for marko to identify this as a split widget, w-bind should use a widget.js with defineWidget rather than index.js with defineComponent.",
{ location: typeName, level: 1 }
);
}
component.input = input.widgetProps;
}
Object.assign(component, oldComponent);
beginComponent(
componentsContext,
component,
key,
ownerComponentDef,
isSplit,
false,
this
);
} else {
vComponentNode.___component = component = registry.___createComponent(
typeName,
component.id
);
}
this.___component = component;
}
return component;
};
if (!registry.___isServer) {
component.___legacyRender && component.___legacyRender();
}
// Render the template associated with the component using the final template
// data that we constructed
templateRenderFunc(
input,
out,
componentDef,
component,
component.___rawState,
out.global
);
if (customEvents && componentDef.___component) {
if (registry.___isServer) {
componentDef.___customEvents = customEvents;
componentDef.___scope = ownerComponentId;
} else {
componentDef.___component.___setCustomEvents(
customEvents,
ownerComponentId
);
}
}
endComponent(out, componentDef);
componentsContext.___componentDef = parentComponentDef;
componentsContext.___legacyComponentDef = parentLegacyComponentDef;
};
}
module.exports = createRendererFunc;

View File

@ -230,3 +230,7 @@ function createRendererFunc(
}
module.exports = createRendererFunc;
// exports used by the legacy renderer
createRendererFunc.___resolveComponentKey = resolveComponentKey;
createRendererFunc.___trackAsyncComponents = trackAsyncComponents;

View File

@ -67,13 +67,11 @@ module.exports = function dynamicTag(
var renderer =
tag._ ||
tag.render ||
(tag.renderer && tag.renderer.renderer) ||
tag.renderer;
(tag.renderer ? tag.renderer.renderer || tag.renderer : tag.render);
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
if (tag.renderer && tag.renderer.renderer === renderer) {
if (tag.renderer && tag.renderer.renderer) {
complain(
"An object with a 'renderer' was passed to the dynamic tag, but renderer was another template."
);

View File

@ -3,6 +3,7 @@
var escapeQuoteHelpers = require("./escape-quotes");
var escapeDoubleQuotes = escapeQuoteHelpers.___escapeDoubleQuotes;
var escapeSingleQuotes = escapeQuoteHelpers.___escapeSingleQuotes;
var complain = "MARKO_DEBUG" && require("complain");
module.exports = maybeEmptyAttr;
@ -26,8 +27,20 @@ function notEmptyAttr(name, value) {
case "number":
return " " + name + "=" + value;
case "object":
if (value instanceof RegExp) {
return " " + name + doubleQuote(value.source);
switch (value.toString) {
case Object.prototype.toString:
case Array.prototype.toString:
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
complain(
"Relying on JSON.stringify for attribute values is deprecated, in future versions of Marko these will be cast to strings instead.",
{ locationIndex: 2 }
);
}
return " " + name + singleQuote(JSON.stringify(value), 2);
case RegExp.prototype.toString:
return " " + name + guessQuotes(value.source);
}
}

View File

@ -1,5 +1,6 @@
"use strict";
var complain = "MARKO_DEBUG" && require("complain");
var dynamicAttrHelper = require("./_dynamic-attr");
module.exports = function attrs(arg) {
@ -11,6 +12,12 @@ module.exports = function attrs(arg) {
}
return result;
case "string":
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
complain(
"Passing a string as a dynamic attribute value is deprecated - More details: https://github.com/marko-js/marko/wiki/Deprecation:-String-as-dynamic-attribute-value"
);
}
return arg;
default:
return "";

View File

@ -1,5 +1,6 @@
"use strict";
var complain = "MARKO_DEBUG" && require("complain");
var dynamicAttrHelper = require("./_dynamic-attr");
/**
@ -11,10 +12,25 @@ module.exports = function mergeAttrs() {
for (var i = arguments.length, last = i - 1; i--; ) {
var source = arguments[i];
for (var k in source) {
if (i === last || !seen.has(k)) {
result += dynamicAttrHelper(k, source[k]);
seen.add(k);
if (typeof source === "string") {
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
complain(
"Passing a string as dynamic attributes ('<div ${string}>' or '<div ...string>') is deprecated, use an object instead."
);
}
if (source[0] !== " ") {
result += " " + source;
} else {
result += source;
}
} else {
for (var k in source) {
if (i === last || !seen.has(k)) {
result += dynamicAttrHelper(k, source[k]);
seen.add(k);
}
}
}
}

View File

@ -15,7 +15,7 @@ exports.t = function createTemplate(typeName) {
};
function Template(typeName) {
this.___typeName = typeName;
this.path = this.___typeName = typeName;
}
Template.prototype.stream = require("@internal/create-readable");

View File

@ -1,3 +1,5 @@
"use strict";
var defaultCreateOut = require("./createOut");
var setImmediate = require("@internal/set-immediate").___setImmediate;
var extend = require("raptor-util/extend");
@ -27,6 +29,7 @@ module.exports = function (target, renderer) {
var createOut = target.createOut || renderer.createOut || defaultCreateOut;
return extend(target, {
_: renderFunc,
createOut: createOut,
renderToString: function (data, callback) {
@ -127,7 +130,7 @@ module.exports = function (target, renderer) {
if (callback) {
finalOut
.on("finish", function () {
callback(null, finalOut.___getResult());
callback(null, finalOut.___getResult(), finalOut);
})
.once("error", callback);
}

View File

@ -1,5 +1,6 @@
/* jshint newcap:false */
var complain = "MARKO_DEBUG" && require("complain");
var domData = require("../components/dom-data");
var componentsUtil = require("@internal/components-util");
var vElementByDOMNode = domData.___vElementByDOMNode;
@ -30,8 +31,18 @@ function convertAttrValue(type, value) {
if (value === true) {
return "";
} else if (type == "object") {
if (value instanceof RegExp) {
return value.source;
switch (value.toString) {
case Object.prototype.toString:
case Array.prototype.toString:
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
complain(
"Relying on JSON.stringify for attribute values is deprecated, in future versions of Marko these will be cast to strings instead."
);
}
return JSON.stringify(value);
case RegExp.prototype.toString:
return value.source;
}
}

View File

@ -1,22 +1,25 @@
"use strict";
var complain = "MARKO_DEBUG" && require("complain");
var classHelper = require("../../helpers/class-value");
var styleHelper = require("../../helpers/style-value");
var parseHTML = require("../parse-html");
/**
* Helper for processing dynamic attributes
*/
module.exports = function (attributes) {
if (attributes != null) {
if (typeof attributes === "string") {
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
if (typeof attributes !== "object") {
throw new Error(
"A non object was passed as a dynamic attributes value."
);
}
complain(
"Passing a string as a dynamic attribute value is deprecated - More details: https://github.com/marko-js/marko/wiki/Deprecation:-String-as-dynamic-attribute-value"
);
}
return parseAttrs(attributes);
}
if (attributes) {
var newAttributes = {};
for (var attrName in attributes) {
@ -39,3 +42,20 @@ module.exports = function (attributes) {
return attributes;
};
function parseAttrs(str) {
if (str === "") {
return {};
}
var attrs = parseHTML("<a " + str + ">").attributes;
var result = {};
var attr;
for (var len = attrs.length, i = 0; i < len; i++) {
attr = attrs[i];
result[attr.name] = attr.value;
}
return result;
}

View File

@ -15,7 +15,7 @@ exports.t = function createTemplate(typeName) {
};
function Template(typeName) {
this.___typeName = typeName;
this.path = this.___typeName = typeName;
}
var AsyncVDOMBuilder = require("./AsyncVDOMBuilder");

View File

@ -44,7 +44,11 @@ export function exit(path) {
block
);
} else if (ofAttr) {
let ofAttrValue = ofAttr.value;
let ofAttrValue = t.logicalExpression(
"||",
ofAttr.value,
t.arrayExpression([])
);
allowedAttributes.push("of");
const [valParam, keyParam, loopParam] = params;

View File

@ -17,7 +17,7 @@ const _marko_component = {};
_marko_template._ = (0, _renderer.default)(function (input, out, _componentDef, _component, state, $global) {
const _cols = [];
const _items = [];
for (const color of input.colors) {
for (const color of input.colors || []) {
if (x) {
_items.push({
"style": {
@ -59,9 +59,9 @@ _marko_template._ = (0, _renderer.default)(function (input, out, _componentDef,
[Symbol.iterator]: _selfIterator.default
});
}
for (const col of input.table) {
for (const col of input.table || []) {
const _rows = [];
for (const row of col) {
for (const row of col || []) {
_rows.push({
"row": row,
"renderBody": out => {

View File

@ -11,7 +11,7 @@ const _marko_component = {};
_marko_template._ = _marko_renderer(function (input, out, _componentDef, _component, state, $global) {
const _cols = [];
const _items = [];
for (const color of input.colors) {
for (const color of input.colors || []) {
if (x) {
_items.push({
"style": {
@ -53,9 +53,9 @@ _marko_template._ = _marko_renderer(function (input, out, _componentDef, _compon
[Symbol.iterator]: _marko_self_iterator
});
}
for (const col of input.table) {
for (const col of input.table || []) {
const _rows = [];
for (const row of col) {
for (const row of col || []) {
_rows.push({
"row": row,
"renderBody": out => {

View File

@ -11,7 +11,7 @@ const _marko_component = {};
_marko_template._ = _marko_renderer(function (input, out, _componentDef, _component, state, $global) {
const _cols = [];
const _items = [];
for (const color of input.colors) {
for (const color of input.colors || []) {
if (x) {
_items.push({
"style": {
@ -53,9 +53,9 @@ _marko_template._ = _marko_renderer(function (input, out, _componentDef, _compon
[Symbol.iterator]: _marko_self_iterator
});
}
for (const col of input.table) {
for (const col of input.table || []) {
const _rows = [];
for (const row of col) {
for (const row of col || []) {
_rows.push({
"row": row,
"renderBody": out => {

View File

@ -12,7 +12,7 @@ const _marko_component = {};
_marko_template._ = _marko_renderer(function (input, out, _componentDef, _component, state, $global) {
const _cols = [];
const _items = [];
for (const color of input.colors) {
for (const color of input.colors || []) {
if (x) {
_items.push({
"style": {
@ -54,9 +54,9 @@ _marko_template._ = _marko_renderer(function (input, out, _componentDef, _compon
[Symbol.iterator]: _marko_self_iterator
});
}
for (const col of input.table) {
for (const col of input.table || []) {
const _rows = [];
for (const row of col) {
for (const row of col || []) {
_rows.push({
"row": row,
"renderBody": out => {

View File

@ -12,7 +12,7 @@ const _marko_component = {};
_marko_template._ = _marko_renderer(function (input, out, _componentDef, _component, state, $global) {
const _cols = [];
const _items = [];
for (const color of input.colors) {
for (const color of input.colors || []) {
if (x) {
_items.push({
"style": {
@ -54,9 +54,9 @@ _marko_template._ = _marko_renderer(function (input, out, _componentDef, _compon
[Symbol.iterator]: _marko_self_iterator
});
}
for (const col of input.table) {
for (const col of input.table || []) {
const _rows = [];
for (const row of col) {
for (const row of col || []) {
_rows.push({
"row": row,
"renderBody": out => {

View File

@ -14,7 +14,7 @@ exports.default = _default;
const _marko_component = {};
_marko_template._ = (0, _renderer.default)(function (input, out, _componentDef, _component, state, $global) {
let _i = 0;
for (const val of arr) {
for (const val of arr || []) {
let i = _i++;
const _keyScope = `[${i}]`;
out.w("<div>");
@ -46,7 +46,7 @@ _marko_template._ = (0, _renderer.default)(function (input, out, _componentDef,
out.w("<div></div>");
}
let _i2 = 0;
for (const val of arr) {
for (const val of arr || []) {
let i = _i2++;
const _keyValue = `@${i}`,
_keyScope4 = `[${_keyValue}]`;

View File

@ -8,7 +8,7 @@ import _marko_renderer from "marko/src/runtime/components/renderer.js";
const _marko_component = {};
_marko_template._ = _marko_renderer(function (input, out, _componentDef, _component, state, $global) {
let _i = 0;
for (const val of arr) {
for (const val of arr || []) {
let i = _i++;
const _keyScope = `[${i}]`;
out.w("<div>");
@ -40,7 +40,7 @@ _marko_template._ = _marko_renderer(function (input, out, _componentDef, _compon
out.w("<div></div>");
}
let _i2 = 0;
for (const val of arr) {
for (const val of arr || []) {
let i = _i2++;
const _keyValue = `@${i}`,
_keyScope4 = `[${_keyValue}]`;

View File

@ -8,7 +8,7 @@ import _marko_renderer from "marko/dist/runtime/components/renderer.js";
const _marko_component = {};
_marko_template._ = _marko_renderer(function (input, out, _componentDef, _component, state, $global) {
let _i = 0;
for (const val of arr) {
for (const val of arr || []) {
let i = _i++;
const _keyScope = `[${i}]`;
out.w(`<div>${_marko_escapeXml(i)}: ${_marko_escapeXml(val)}</div><div></div><div></div>`);
@ -24,7 +24,7 @@ _marko_template._ = _marko_renderer(function (input, out, _componentDef, _compon
out.w(`<div>${_marko_escapeXml(i)}</div><div></div><div></div>`);
}
let _i2 = 0;
for (const val of arr) {
for (const val of arr || []) {
let i = _i2++;
const _keyValue = `@${i}`,
_keyScope4 = `[${_keyValue}]`;

View File

@ -8,7 +8,7 @@ _marko_registerComponent(_marko_componentType, () => _marko_template);
const _marko_component = {};
_marko_template._ = _marko_renderer(function (input, out, _componentDef, _component, state, $global) {
let _i = 0;
for (const val of arr) {
for (const val of arr || []) {
let i = _i++;
const _keyScope = `[${i}]`;
out.be("div", null, "0" + _keyScope, _component, null, 0);
@ -40,7 +40,7 @@ _marko_template._ = _marko_renderer(function (input, out, _componentDef, _compon
out.e("div", null, "8" + _keyScope3, _component, 0, 0);
}
let _i2 = 0;
for (const val of arr) {
for (const val of arr || []) {
let i = _i2++;
const _keyValue = `@${i}`,
_keyScope4 = `[${_keyValue}]`;

View File

@ -8,7 +8,7 @@ _marko_registerComponent(_marko_componentType, () => _marko_template);
const _marko_component = {};
_marko_template._ = _marko_renderer(function (input, out, _componentDef, _component, state, $global) {
let _i = 0;
for (const val of arr) {
for (const val of arr || []) {
let i = _i++;
const _keyScope = `[${i}]`;
out.be("div", null, "0" + _keyScope, _component, null, 0);
@ -40,7 +40,7 @@ _marko_template._ = _marko_renderer(function (input, out, _componentDef, _compon
out.e("div", null, "8" + _keyScope3, _component, 0, 0);
}
let _i2 = 0;
for (const val of arr) {
for (const val of arr || []) {
let i = _i2++;
const _keyValue = `@${i}`,
_keyScope4 = `[${_keyValue}]`;

View File

@ -21,7 +21,7 @@ _marko_template._ = (0, _renderer.default)(function (input, out, _componentDef,
out.w("<ul>");
{
let _keyValue = 0;
for (const child of node.children) {
for (const child of node.children || []) {
const _keyScope = `[${_keyValue++}]`;
out.w("<li>");
(0, _dynamicTag.default)(out, _renderTree, () => child, null, null, null, _componentDef, "3" + _keyScope);

View File

@ -15,7 +15,7 @@ _marko_template._ = _marko_renderer(function (input, out, _componentDef, _compon
out.w("<ul>");
{
let _keyValue = 0;
for (const child of node.children) {
for (const child of node.children || []) {
const _keyScope = `[${_keyValue++}]`;
out.w("<li>");
_marko_dynamic_tag(out, _renderTree, () => child, null, null, null, _componentDef, "3" + _keyScope);

View File

@ -13,7 +13,7 @@ _marko_template._ = _marko_renderer(function (input, out, _componentDef, _compon
out.w("<ul>");
{
let _keyValue = 0;
for (const child of node.children) {
for (const child of node.children || []) {
const _keyScope = `[${_keyValue++}]`;
out.w("<li>");
_marko_dynamic_tag(out, _renderTree, () => child, null, null, null, _componentDef, "3" + _keyScope);

View File

@ -16,7 +16,7 @@ _marko_template._ = _marko_renderer(function (input, out, _componentDef, _compon
out.be("ul", null, "1", _component, null, 0);
{
let _keyValue = 0;
for (const child of node.children) {
for (const child of node.children || []) {
const _keyScope = `[${_keyValue++}]`;
out.be("li", null, "2" + _keyScope, _component, null, 0);
_marko_dynamic_tag(out, _renderTree, () => child, null, null, null, _componentDef, "3" + _keyScope);

View File

@ -16,7 +16,7 @@ _marko_template._ = _marko_renderer(function (input, out, _componentDef, _compon
out.be("ul", null, "1", _component, null, 0);
{
let _keyValue = 0;
for (const child of node.children) {
for (const child of node.children || []) {
const _keyScope = `[${_keyValue++}]`;
out.be("li", null, "2" + _keyScope, _component, null, 0);
_marko_dynamic_tag(out, _renderTree, () => child, null, null, null, _componentDef, "3" + _keyScope);

View File

@ -19,7 +19,7 @@ _marko_template._ = (0, _renderer.default)(function (input, out, _componentDef,
out.w("<ul>");
{
let _keyValue = 0;
for (const color of input.colors) {
for (const color of input.colors || []) {
const _keyScope = `[${_keyValue++}]`;
out.w("<li>");
out.w((0, _escapeXml.x)(color));

View File

@ -13,7 +13,7 @@ _marko_template._ = _marko_renderer(function (input, out, _componentDef, _compon
out.w("<ul>");
{
let _keyValue = 0;
for (const color of input.colors) {
for (const color of input.colors || []) {
const _keyScope = `[${_keyValue++}]`;
out.w("<li>");
out.w(_marko_escapeXml(color));

View File

@ -11,7 +11,7 @@ _marko_template._ = _marko_renderer(function (input, out, _componentDef, _compon
out.w("<ul>");
{
let _keyValue = 0;
for (const color of input.colors) {
for (const color of input.colors || []) {
const _keyScope = `[${_keyValue++}]`;
out.w(`<li>${_marko_escapeXml(color)}</li>`);
}

View File

@ -14,7 +14,7 @@ _marko_template._ = _marko_renderer(function (input, out, _componentDef, _compon
out.be("ul", null, "0", _component, null, 0);
{
let _keyValue = 0;
for (const color of input.colors) {
for (const color of input.colors || []) {
const _keyScope = `[${_keyValue++}]`;
out.be("li", null, "1" + _keyScope, _component, null, 0);
out.t(color, _component);

View File

@ -16,7 +16,7 @@ _marko_template._ = _marko_renderer(function (input, out, _componentDef, _compon
out.be("ul", null, "0", _component, null, 0);
{
let _keyValue = 0;
for (const color of input.colors) {
for (const color of input.colors || []) {
const _keyScope = `[${_keyValue++}]`;
out.be("li", null, "1" + _keyScope, _component, null, 0);
out.t(color, _component);