diff --git a/compiler/CompileContext.js b/compiler/CompileContext.js index 8d2977e5f..700484a52 100644 --- a/compiler/CompileContext.js +++ b/compiler/CompileContext.js @@ -77,6 +77,7 @@ const helpers = { 'loadTemplate': { module: 'marko/runtime/helper-loadTemplate' }, 'mergeNestedTagsHelper': { module: 'marko/runtime/helper-mergeNestedTags' }, 'merge': { module: 'marko/runtime/helper-merge' }, + 'renderComponent': { module: 'marko/components/taglib/helpers/renderComponent' }, 'str': 's', 'styleAttr': { vdom: { module: 'marko/runtime/vdom/helper-styleAttr'}, diff --git a/compiler/ast/CustomTag.js b/compiler/ast/CustomTag.js index c1336aef3..ba21dacb7 100644 --- a/compiler/ast/CustomTag.js +++ b/compiler/ast/CustomTag.js @@ -432,6 +432,10 @@ class CustomTag extends HtmlElement { return this._nestedTagVar; } + generateRenderTagCode(codegen, tagVar, tagArgs) { + return codegen.builder.functionCall(tagVar, tagArgs); + } + generateCode(codegen) { if (this.type !== 'CustomTag') { throw new Error(this.type); @@ -601,8 +605,7 @@ class CustomTag extends HtmlElement { let loadTag = builder.functionCall(context.helper('loadTag'), [templateVar]); let tagVar = codegen.addStaticVar(tagVarName, loadTag); - let tagFunctionCall = builder.functionCall(tagVar, [ inputProps, 'out' ]); - finalNode = tagFunctionCall; + finalNode = this.generateRenderTagCode(codegen, tagVar, [ inputProps, builder.identifierOut() ]); } else { if (rendererRequirePath) { codegen.pushMeta('tags', builder.literal(rendererRequirePath), true); @@ -631,8 +634,11 @@ class CustomTag extends HtmlElement { let tagVar = codegen.addStaticVar(tagVarName, loadTag); - let tagFunctionCall = builder.functionCall(tagVar, tagArgs); - finalNode = tagFunctionCall; + if (isNestedTag) { + finalNode = builder.functionCall(tagVar, tagArgs); + } else { + finalNode = this.generateRenderTagCode(codegen, tagVar, tagArgs); + } } if (bodyOnlyIf && renderBodyFunctionVar) { diff --git a/components/legacy/renderer-legacy.js b/components/legacy/renderer-legacy.js index 722a06040..437418974 100644 --- a/components/legacy/renderer-legacy.js +++ b/components/legacy/renderer-legacy.js @@ -52,9 +52,10 @@ function createRendererFunc(templateRenderFunc, componentProps) { isExisting = true; outGlobal.$w = null; } else { - var componentArgs = input && input.$w || out.data.$w; + var componentArgs = out.$c; if (componentArgs) { + out.$c = null; scope = componentArgs[0]; if (scope) { diff --git a/components/renderer.js b/components/renderer.js index feade9d4d..9a5afdcb7 100644 --- a/components/renderer.js +++ b/components/renderer.js @@ -60,11 +60,9 @@ function handleBeginAsync(event) { var nestedComponentsContext = new ComponentsContext(asyncOut, componentStack[componentStack.length-1]); asyncOut.data.components = nestedComponentsContext; } - asyncOut.data.$w = parentOut.data.$w; + asyncOut.$c = parentOut.$c; } - - function createRendererFunc(templateRenderFunc, componentProps, renderingLogic) { if (typeof renderingLogic == 'function') { var ctor = renderingLogic; @@ -101,9 +99,11 @@ function createRendererFunc(templateRenderFunc, componentProps, renderingLogic) isExisting = true; outGlobal.$w = null; } else { - var componentArgs = input && input.$w || out.data.$w; + var componentArgs = out.$c; if (componentArgs) { + out.$c = null; + scope = componentArgs[0]; if (scope) { @@ -116,7 +116,6 @@ function createRendererFunc(templateRenderFunc, componentProps, renderingLogic) } id = id || resolveComponentKey(out, key, scope); customEvents = componentArgs[2]; - delete input.$w; } } diff --git a/components/taglib/TransformHelper/ComponentArgs.js b/components/taglib/TransformHelper/ComponentArgs.js index 745cfe9b0..6ed923fa5 100644 --- a/components/taglib/TransformHelper/ComponentArgs.js +++ b/components/taglib/TransformHelper/ComponentArgs.js @@ -1,5 +1,4 @@ 'use strict'; - class ComponentArgs { constructor() { @@ -61,37 +60,34 @@ class ComponentArgs { args.push(builder.literal(customEvents)); } - if (el.tagDef && el.tagDef.template) { - el.setAttributeValue('$w', builder.literal(args)); + if (el.type === 'CustomTag') { + var renderComponentHelper = transformHelper.context.helper('renderComponent'); + + el.generateRenderTagCode = function(codegen, tagVar, tagArgs) { + tagArgs = [tagVar].concat(tagArgs); + + tagArgs.push(builder.literal(args)); + + return codegen.builder.functionCall( + renderComponentHelper, + tagArgs); + }; } else { - let componentArgsVar = transformHelper.context.addStaticVar('marko_componentArgs', - builder.require(builder.literal('marko/components/taglib/helpers/componentArgs'))); - - let componentArgsFunctionCall = builder.functionCall(componentArgsVar, [ - builder.identifierOut(), - builder.literal(args) - ]); - let cleanupComponentArgsFunctionCall = this.buildCleanupComponentArgsFunctionCall(transformHelper); - el.onBeforeGenerateCode((event) => { - event.insertCode(componentArgsFunctionCall); + let lhs = builder.memberExpression(builder.identifierOut(), builder.identifier('$c')); + let rhs = builder.literal(args); + + event.insertCode(builder.assignment(lhs, rhs)); }); el.onAfterGenerateCode((event) => { - event.insertCode(cleanupComponentArgsFunctionCall); + let lhs = builder.memberExpression(builder.identifierOut(), builder.identifier('$c')); + let rhs = builder.literalNull(); + + event.insertCode(builder.assignment(lhs, rhs)); }); } } - - buildCleanupComponentArgsFunctionCall(transformHelper) { - var context = transformHelper.context; - var builder = transformHelper.builder; - - var cleanupComponentArgsVar = context.addStaticVar('marko_cleanupComponentArgs', - 'marko_componentArgs.cleanup'); - - return builder.functionCall(cleanupComponentArgsVar, [builder.identifierOut()]); - } } -module.exports = ComponentArgs; \ No newline at end of file +module.exports = ComponentArgs; diff --git a/components/taglib/helpers/renderComponent.js b/components/taglib/helpers/renderComponent.js new file mode 100644 index 000000000..3e6b1c3a9 --- /dev/null +++ b/components/taglib/helpers/renderComponent.js @@ -0,0 +1,5 @@ +module.exports = function renderCompontent(tagRenderer, input, out, componentArgs) { + out.$c = componentArgs; + tagRenderer(input, out); + out.$c = null; +}; diff --git a/package.json b/package.json index af1af9abb..47e9d0c68 100644 --- a/package.json +++ b/package.json @@ -141,6 +141,7 @@ }, "minprops": { "exclude": [ + "$c", "b", "be", "c", diff --git a/runtime/html/AsyncStream.js b/runtime/html/AsyncStream.js index f6c1cd34f..d7eb369d6 100644 --- a/runtime/html/AsyncStream.js +++ b/runtime/html/AsyncStream.js @@ -60,6 +60,8 @@ function AsyncStream(global, writer, state, shouldBuffer) { this._node = undefined; this._elStack = undefined; // Array + + this.$c = null; // Component args } AsyncStream.DEFAULT_TIMEOUT = 10000; diff --git a/runtime/vdom/AsyncVDOMBuilder.js b/runtime/vdom/AsyncVDOMBuilder.js index 3d93acb60..c316c3bd3 100644 --- a/runtime/vdom/AsyncVDOMBuilder.js +++ b/runtime/vdom/AsyncVDOMBuilder.js @@ -40,6 +40,7 @@ function AsyncVDOMBuilder(globalData, parentNode, state) { this.global = globalData || {}; this.$__stack = [parentNode]; this.$__sync = false; + this.$c = null; // Component args } var proto = AsyncVDOMBuilder.prototype = { diff --git a/test/autotests/components-browser/key-intermediate-template/components/foo/components/real-foo/index.marko b/test/autotests/components-browser/key-intermediate-template/components/foo/components/real-foo/index.marko new file mode 100644 index 000000000..19c8d5fcc --- /dev/null +++ b/test/autotests/components-browser/key-intermediate-template/components/foo/components/real-foo/index.marko @@ -0,0 +1,9 @@ +class { + onMount() { + this.realFoo = true; + } +} + +