Skip to content

Commit

Permalink
Fix issue #497
Browse files Browse the repository at this point in the history
  • Loading branch information
Eric MORAND authored and ericmorand committed May 11, 2020
1 parent b7f9c75 commit 1a19bf6
Show file tree
Hide file tree
Showing 57 changed files with 339 additions and 278 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
"@typescript-eslint/eslint-plugin": "^2.3.2",
"@typescript-eslint/parser": "^2.3.2",
"browserify": "^16.2.3",
"coveralls": "^3.0.0",
"coveralls": "3.0.9",
"eslint": "^6.5.1",
"eslint-plugin-import": "^2.18.2",
"fs-finder": "^1.8.1",
Expand Down
2 changes: 1 addition & 1 deletion src/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export {TwingNodeVerbatim} from "./lib/node/verbatim";
export {TwingNodeWith} from "./lib/node/with";
export {TwingNode} from "./lib/node";
export {TwingOperator,TwingOperatorType, TwingOperatorAssociativity} from "./lib/operator";
export {TwingOutputBuffering, TwingOutputHandler} from "./lib/output-buffering";
export {TwingOutputBuffer, TwingOutputHandler} from "./lib/output-buffer";
export {TwingParser} from "./lib/parser";
export {TwingSandboxSecurityError} from "./lib/sandbox/security-error";
export {TwingSandboxSecurityNotAllowedFilterError} from "./lib/sandbox/security-not-allowed-filter-error";
Expand Down
6 changes: 6 additions & 0 deletions src/lib/callable-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export type TwingCallableWrapperOptions = {
needs_environment?: boolean;
needs_context?: boolean;
needs_source?: boolean;
needs_output_buffer?: boolean;
is_variadic?: boolean;
is_safe?: Array<any>;
is_safe_callback?: Function;
Expand All @@ -38,6 +39,7 @@ export abstract class TwingCallableWrapper<T> {
needs_environment: false,
needs_context: false,
needs_source: false,
needs_output_buffer: false,
is_variadic: false,
is_safe: null,
is_safe_callback: null,
Expand Down Expand Up @@ -107,6 +109,10 @@ export abstract class TwingCallableWrapper<T> {
return this.options.needs_source;
}

needsOutputBuffer(): boolean {
return this.options.needs_output_buffer;
}

getSafe(functionArgs: TwingNode): any[] {
if (this.options.is_safe !== null) {
return this.options.is_safe;
Expand Down
4 changes: 2 additions & 2 deletions src/lib/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ export class TwingCompiler {
.raw(', ')
.string(node.getType())
.raw(', ')
.raw('this.getSourceContext());\n')
.raw('this.getSourceContext(), outputBuffer);\n')
}

return this;
Expand All @@ -187,7 +187,7 @@ export class TwingCompiler {
addSourceMapLeave() {
if (this.getEnvironment().isSourceMap()) {
this
.write('this.env.leaveSourceMapBlock();\n')
.write('this.env.leaveSourceMapBlock(outputBuffer);\n')
;
}

Expand Down
14 changes: 9 additions & 5 deletions src/lib/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {TwingNodeModule} from "./node/module";
import {TwingCacheNull} from "./cache/null";
import {TwingErrorRuntime} from "./error/runtime";
import {EventEmitter} from 'events';
import {TwingOutputBuffering} from "./output-buffering";
import {TwingOutputBuffer} from "./output-buffer";
import {TwingSourceMapNode} from "./source-map/node";
import {TwingOperator} from "./operator";
import {TwingSandboxSecurityPolicy} from "./sandbox/security-policy";
Expand Down Expand Up @@ -911,9 +911,10 @@ return module.exports;
* @param {number} column 1-based
* @param {TwingNodeType} nodeType
* @param {TwingSource} source
* @param {TwingOutputBuffer} outputBuffer
*/
enterSourceMapBlock(line: number, column: number, nodeType: TwingNodeType, source: TwingSource) {
TwingOutputBuffering.obStart();
enterSourceMapBlock(line: number, column: number, nodeType: TwingNodeType, source: TwingSource, outputBuffer: TwingOutputBuffer) {
outputBuffer.start();

let sourceName = source.getResolvedName();

Expand All @@ -938,8 +939,11 @@ return module.exports;
this.sourceMapNode = node;
}

leaveSourceMapBlock() {
this.sourceMapNode.content = TwingOutputBuffering.obGetFlush() as string;
/**
* @param {TwingOutputBuffer} outputBuffer
*/
leaveSourceMapBlock(outputBuffer: TwingOutputBuffer) {
this.sourceMapNode.content = outputBuffer.getAndFlush() as string;

let parent = this.sourceMapNode.parent;

Expand Down
1 change: 1 addition & 0 deletions src/lib/extension/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,7 @@ export class TwingExtensionCore extends TwingExtension {
needs_context: true,
needs_environment: true,
needs_source: true,
needs_output_buffer: true,
is_safe: ['all']
}),
new TwingFunction('max', max, []),
Expand Down
6 changes: 4 additions & 2 deletions src/lib/extension/core/functions/include.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ import {isTraversable} from "../../../helpers/is-traversable";
import {TwingErrorRuntime} from "../../../error/runtime";
import {isNullOrUndefined} from "util";
import {isPlainObject} from "../../../helpers/is-plain-object";
import {TwingOutputBuffer} from "../../../output-buffer";

/**
* Renders a template.
*
* @param {TwingEnvironment} env
* @param {any} context
* @param {TwingSource} from
* @param {TwingOutputBuffer} outputBuffer
* @param {string | Map<number, string | TwingTemplate>} templates The template to render or an array of templates to try consecutively
* @param {any} variables The variables to pass to the template
* @param {boolean} withContext
Expand All @@ -23,7 +25,7 @@ import {isPlainObject} from "../../../helpers/is-plain-object";
*
* @returns {Promise<string>} The rendered template
*/
export function include(env: TwingEnvironment, context: any, from: TwingSource, templates: string | Map<number, string | TwingTemplate> | TwingTemplate, variables: any = {}, withContext: boolean = true, ignoreMissing: boolean = false, sandboxed: boolean = false): Promise<string> {
export function include(env: TwingEnvironment, context: any, from: TwingSource, outputBuffer: TwingOutputBuffer, templates: string | Map<number, string | TwingTemplate> | TwingTemplate, variables: any = {}, withContext: boolean = true, ignoreMissing: boolean = false, sandboxed: boolean = false): Promise<string> {
let alreadySandboxed = env.isSandboxed();

if (!isPlainObject(variables) && !isTraversable(variables)) {
Expand Down Expand Up @@ -69,7 +71,7 @@ export function include(env: TwingEnvironment, context: any, from: TwingSource,
};

return resolveTemplate(templates).then((template) => {
let promise = template ? template.render(variables) : Promise.resolve('');
let promise = template ? template.render(variables, outputBuffer) : Promise.resolve('');

return promise.then((result) => {
restoreSandbox();
Expand Down
2 changes: 1 addition & 1 deletion src/lib/node/block-reference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class TwingNodeBlockReference extends TwingNode implements TwingNodeOutpu

compile(compiler: TwingCompiler) {
compiler
.write(`this.echo(await this.traceableRenderBlock(${this.getTemplateLine()}, this.getSourceContext())('${this.getAttribute('name')}', context.clone(), blocks));\n`)
.write(`outputBuffer.echo(await this.traceableRenderBlock(${this.getTemplateLine()}, this.getSourceContext())('${this.getAttribute('name')}', context.clone(), outputBuffer, blocks));\n`)
;
}
}
2 changes: 1 addition & 1 deletion src/lib/node/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class TwingNodeBlock extends TwingNode {

compile(compiler: TwingCompiler) {
compiler
.raw(`async (context, blocks = new Map()) => {\n`)
.raw(`async (context, outputBuffer, blocks = new Map()) => {\n`)
.indent()
.write('let aliases = this.aliases.clone();\n')
;
Expand Down
14 changes: 9 additions & 5 deletions src/lib/node/expression/block-reference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ export class TwingNodeExpressionBlockReference extends TwingNodeExpression {

compile(compiler: TwingCompiler) {
if (this.getAttribute('is_defined_test')) {
this.compileTemplateCall(compiler, 'traceableHasBlock');
this.compileTemplateCall(compiler, 'traceableHasBlock', false);
} else {
this.compileTemplateCall(compiler, 'traceableRenderBlock');
this.compileTemplateCall(compiler, 'traceableRenderBlock', true);
}
}

compileTemplateCall(compiler: TwingCompiler, method: string): TwingCompiler {
compileTemplateCall(compiler: TwingCompiler, method: string, needsOutputBuffer: boolean): TwingCompiler {
compiler.write('await ');

if (!this.hasNode('template')) {
Expand All @@ -47,17 +47,21 @@ export class TwingNodeExpressionBlockReference extends TwingNodeExpression {

compiler.raw(`.${method}(${this.getTemplateLine()}, this.getSourceContext())`);

this.compileBlockArguments(compiler);
this.compileBlockArguments(compiler, needsOutputBuffer);

return compiler;
}

compileBlockArguments(compiler: TwingCompiler) {
compileBlockArguments(compiler: TwingCompiler, needsOutputBuffer: boolean) {
compiler
.raw('(')
.subcompile(this.getNode('name'))
.raw(', context.clone()');

if (needsOutputBuffer) {
compiler.raw(', outputBuffer');
}

if (!this.hasNode('template')) {
compiler.raw(', blocks');
}
Expand Down
10 changes: 10 additions & 0 deletions src/lib/node/expression/call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@ export abstract class TwingNodeExpressionCall extends TwingNodeExpression {
first = false;
}

if (this.hasAttribute('needs_output_buffer') && this.getAttribute('needs_output_buffer')) {
if (!first) {
compiler.raw(', ');
}

compiler.raw('outputBuffer');

first = false;
}

if (this.hasAttribute('arguments')) {
for (let argument_ of this.getAttribute('arguments')) {
if (!first) {
Expand Down
5 changes: 2 additions & 3 deletions src/lib/node/expression/function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,15 @@ export class TwingNodeExpressionFunction extends TwingNodeExpressionCall {
compile(compiler: TwingCompiler) {
let name = this.getAttribute('name');
let function_ = compiler.getEnvironment().getFunction(name);
let callable = function_.getCallable();

this.setAttribute('name', name);
this.setAttribute('type', 'function');
this.setAttribute('needs_environment', function_.needsEnvironment());
this.setAttribute('needs_context', function_.needsContext());
this.setAttribute('needs_source', function_.needsSource());
this.setAttribute('needs_output_buffer', function_.needsOutputBuffer());
this.setAttribute('arguments', function_.getArguments());

let callable = function_.getCallable();

this.setAttribute('callable', callable);
this.setAttribute('is_variadic', function_.isVariadic());
this.setAttribute('accepted_arguments', function_.getAcceptedArgments());
Expand Down
1 change: 1 addition & 0 deletions src/lib/node/expression/method-call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export class TwingNodeExpressionMethodCall extends TwingNodeExpression {
.repr(this.getNode('node').getAttribute('name'))
.raw('], ')
.repr(this.getAttribute('method'))
.raw(', outputBuffer')
.raw(', [')
;
let first = true;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/node/expression/parent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class TwingNodeExpressionParent extends TwingNodeExpression {
compiler
.raw(`await this.traceableRenderParentBlock(${this.getTemplateLine()}, this.getSourceContext())(`)
.string(name)
.raw(', context, blocks)')
.raw(', context, outputBuffer, blocks)')
;
}
}
2 changes: 1 addition & 1 deletion src/lib/node/flush.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class TwingNodeFlush extends TwingNode {

compile(compiler: TwingCompiler) {
compiler
.write("this.flushOutputBuffer();\n")
.write("outputBuffer.flush();\n")
;
}
}
2 changes: 1 addition & 1 deletion src/lib/node/include.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class TwingNodeInclude extends TwingNode {

compile(compiler: TwingCompiler) {
compiler
.write('this.echo(await this.include(context, this.getSourceContext(), ');
.write('outputBuffer.echo(await this.include(context, this.getSourceContext(), outputBuffer, ');

this.addGetTemplate(compiler);

Expand Down
2 changes: 1 addition & 1 deletion src/lib/node/inline-print.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export class TwingNodeInlinePrint extends TwingNode {

compile(compiler: TwingCompiler) {
compiler
.raw('this.echo(')
.raw('outputBuffer.echo(')
.subcompile(this.getNode('node'))
.raw(')')
;
Expand Down
11 changes: 6 additions & 5 deletions src/lib/node/macro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,16 @@ export class TwingNodeMacro extends TwingNode {
compile(compiler: TwingCompiler) {
compiler
.raw(`async (`)
.raw('outputBuffer, ')
;

let count = this.getNode('arguments').getNodes().size;
let pos = 0;

for (let [name, default_] of this.getNode('arguments').getNodes()) {
for (let [name, defaultValue] of this.getNode('arguments').getNodes()) {
compiler
.raw('__' + name + '__ = ')
.subcompile(default_)
.subcompile(defaultValue)
;

if (++pos < count) {
Expand Down Expand Up @@ -93,12 +94,12 @@ export class TwingNodeMacro extends TwingNode {
.write("let blocks = new Map();\n")
.write('let result;\n')
.write('let error;\n\n')
.write("this.startOutputBuffer();\n")
.write("outputBuffer.start();\n")
.write("try {\n")
.indent()
.subcompile(this.getNode('body'))
.raw("\n")
.write('let tmp = this.getOutputBufferContent();\n')
.write('let tmp = outputBuffer.getContents();\n')
.write("result = (tmp === '') ? '' : new this.Markup(tmp, this.env.getCharset());\n")
.outdent()
.write("}\n")
Expand All @@ -107,7 +108,7 @@ export class TwingNodeMacro extends TwingNode {
.write('error = e;\n')
.outdent()
.write('}\n\n')
.write("this.endAndCleanOutputBuffer();\n\n")
.write("outputBuffer.endAndClean();\n\n")
.write('if (error) {\n')
.indent()
.write('throw error;\n')
Expand Down
4 changes: 2 additions & 2 deletions src/lib/node/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ export class TwingNodeModule extends TwingNode {

protected compileDoDisplay(compiler: TwingCompiler) {
compiler
.write("async doDisplay(context, blocks = new Map()) {\n")
.write("async doDisplay(context, outputBuffer, blocks = new Map()) {\n")
.indent()
.write('let aliases = this.aliases.clone();\n\n')
.addSourceMapEnter(this)
Expand All @@ -282,7 +282,7 @@ export class TwingNodeModule extends TwingNode {
;

if (this.hasNode('parent')) {
compiler.write('await (await this.getParent(context)).display(context, this.merge(await this.getBlocks(), blocks));\n');
compiler.write('await (await this.getParent(context)).display(context, this.merge(await this.getBlocks(), blocks), outputBuffer);\n');
}

compiler
Expand Down
2 changes: 1 addition & 1 deletion src/lib/node/print.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export class TwingNodePrint extends TwingNode implements TwingNodeOutputInterfac
compile(compiler: TwingCompiler) {
compiler
.addSourceMapEnter(this)
.write('this.echo(')
.write('outputBuffer.echo(')
.subcompile(this.getNode('expr'))
.raw(');\n')
.addSourceMapLeave()
Expand Down
2 changes: 1 addition & 1 deletion src/lib/node/sandboxed-print.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {TwingCompiler} from "../compiler";
export class TwingNodeSandboxedPrint extends TwingNodePrint {
compile(compiler: TwingCompiler) {
compiler
.write('this.echo(this.env.ensureToStringAllowed(')
.write('outputBuffer.echo(this.env.ensureToStringAllowed(')
.subcompile(this.getNode('expr'))
.raw("));\n")
;
Expand Down
4 changes: 2 additions & 2 deletions src/lib/node/set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export class TwingNodeSet extends TwingNode implements TwingNodeCaptureInterface
} else {
if (this.getAttribute('capture')) {
compiler
.write("this.startOutputBuffer();\n")
.write("outputBuffer.start();\n")
.subcompile(this.getNode('values'))
;
}
Expand All @@ -67,7 +67,7 @@ export class TwingNodeSet extends TwingNode implements TwingNodeCaptureInterface

if (this.getAttribute('capture')) {
compiler
.raw(" = (() => {let tmp = this.getAndCleanOutputBuffer(); return tmp === '' ? '' : new this.Markup(tmp, this.env.getCharset());})()")
.raw(" = (() => {let tmp = outputBuffer.getAndClean(); return tmp === '' ? '' : new this.Markup(tmp, this.env.getCharset());})()")
;
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/lib/node/spaceless.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ export class TwingNodeSpaceless extends TwingNode implements TwingNodeOutputInte
compile(compiler: TwingCompiler) {
compiler
.addSourceMapEnter(this)
.write("this.startOutputBuffer();\n")
.write("outputBuffer.start();\n")
.subcompile(this.getNode('body'))
.write("this.echo(this.getAndCleanOutputBuffer().replace(/>\\s+</g, '><').trim());\n")
.write("outputBuffer.echo(outputBuffer.getAndClean().replace(/>\\s+</g, '><').trim());\n")
.addSourceMapLeave()
;
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/node/text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export class TwingNodeText extends TwingNode implements TwingNodeOutputInterface
compile(compiler: TwingCompiler) {
compiler
.addSourceMapEnter(this)
.write('this.echo(')
.write('outputBuffer.echo(')
.string(this.getAttribute('data'))
.raw(");\n")
.addSourceMapLeave()
Expand Down
Loading

0 comments on commit 1a19bf6

Please sign in to comment.