Merge branch 'issue-603' into 'milestone/6.1.0'

Resolve issue #603

See merge request nightlycommit/twing!604
This commit is contained in:
Eric MORAND 2024-03-18 09:12:08 +00:00
commit 960ba91a95
10 changed files with 79 additions and 8 deletions

View File

@ -28,7 +28,9 @@ import {TwingParsingError} from "./error/parsing";
import {createLexer, TwingLexer} from "./lexer";
import {TwingCache} from "./cache";
import {createCoreExtension} from "./extension/core";
import {createAutoEscapeNode} from "../lib";
import {createAutoEscapeNode, type TwingContext} from "../lib";
import {iteratorToMap} from "./helpers/iterator-to-map";
import {createContext} from "./context";
export type TwingNumberFormat = {
numberOfDecimals: number;
@ -60,6 +62,7 @@ export type TwingEnvironmentOptions = {
charset?: string;
dateFormat?: string;
dateIntervalFormat?: string;
globals?: Record<string, any>;
numberFormat?: TwingNumberFormat;
parserOptions?: TwingParserOptions;
sandboxed?: boolean;
@ -84,6 +87,7 @@ export interface TwingEnvironment {
readonly numberFormat: TwingNumberFormat;
readonly filters: Map<string, TwingFilter>;
readonly functions: Map<string, TwingFunction>;
readonly globals: TwingContext<string, any>;
readonly isStrictVariables: boolean;
readonly loader: TwingLoader;
readonly sandboxPolicy: TwingSandboxSecurityPolicy;
@ -202,6 +206,7 @@ export const createEnvironment = (
};
const eventEmitter = new EventEmitter();
const sandboxPolicy = options?.sandboxPolicy || createSandboxSecurityPolicy();
const globals = createContext(iteratorToMap(options?.globals || {}));
let isSandboxed = options?.sandboxed ? true : false;
let lexer: TwingLexer;
@ -228,6 +233,9 @@ export const createEnvironment = (
get functions() {
return extensionSet.functions;
},
get globals() {
return globals;
},
get isStrictVariables() {
return options?.strictVariables ? true : false;
},

View File

@ -11,6 +11,7 @@ export type TwingExecutionContext = {
context: TwingContext<any, any>;
dateFormat: string;
dateIntervalFormat: string;
globals: TwingContext<string, any>;
isStrictVariables: boolean;
numberFormat: TwingNumberFormat;
outputBuffer: TwingOutputBuffer;

View File

@ -2,6 +2,8 @@ import type {TwingBaseExpressionNodeAttributes} from "../expression";
import {createBaseNode, TwingBaseNode} from "../../node";
import {getContextValue} from "../../helpers/get-context-value";
import {getTraceableMethod} from "../../helpers/traceable-method";
import {mergeIterables} from "../../helpers/merge-iterables";
import {createContext} from "../../context";
export type TwingNameNodeAttributes = TwingBaseExpressionNodeAttributes & {
name: string;
@ -29,7 +31,7 @@ export const createNameNode = (
const nameNode: TwingNameNode = {
...baseNode,
execute: async ({template, context, charset, isStrictVariables}) => {
execute: async ({template, context, charset, isStrictVariables, globals}) => {
const {name, isAlwaysDefined, shouldIgnoreStrictCheck, shouldTestExistence} = nameNode.attributes;
const traceableGetContextValue = getTraceableMethod(
@ -43,7 +45,7 @@ export const createNameNode = (
charset,
template.name,
isStrictVariables,
context,
createContext(mergeIterables(globals, context)),
name,
isAlwaysDefined,
shouldIgnoreStrictCheck,

View File

@ -87,11 +87,7 @@ export const createForNode = (
let sequence = ensureTraversable(executedSequence);
if (sequence === context) {
context.set('_seq', context.clone());
} else {
context.set('_seq', sequence);
}
context.set('_seq', sequence);
if (elseNode) {
context.set('_iterated', false);

View File

@ -201,6 +201,7 @@ export const createTemplate = (
context,
dateFormat,
dateIntervalFormat,
globals: environment.globals,
isStrictVariables,
numberFormat,
outputBuffer,
@ -237,6 +238,7 @@ export const createTemplate = (
context: createContext(),
dateFormat,
dateIntervalFormat,
globals: environment.globals,
isStrictVariables,
numberFormat,
outputBuffer,
@ -269,6 +271,7 @@ export const createTemplate = (
context,
dateFormat,
dateIntervalFormat,
globals: environment.globals,
isStrictVariables,
numberFormat,
outputBuffer,
@ -490,6 +493,7 @@ export const createTemplate = (
context,
dateFormat,
dateIntervalFormat,
globals: environment.globals,
isStrictVariables,
numberFormat,
outputBuffer,
@ -555,6 +559,7 @@ export const createTemplate = (
context,
dateFormat,
dateIntervalFormat,
globals: environment.globals,
isStrictVariables,
numberFormat,
outputBuffer,

View File

@ -0,0 +1 @@
import "./with-include";

View File

@ -0,0 +1,43 @@
import {runTest} from "../TestBase";
runTest({
description: 'globals with include',
templates: {
"index.twig": `{{ include("foo") }}`,
'foo': `{{ title }}`
},
environmentOptions: {
globals: {
title: 'foo'
}
},
expectation: `foo`
});
runTest({
description: 'globals with include, when shadowed',
templates: {
"index.twig": `{{ include("foo", {title: "bar"}) }}`,
'foo': `{{ title }}`
},
environmentOptions: {
globals: {
title: 'foo'
}
},
expectation: `bar`
});
runTest({
description: 'globals with include and only',
templates: {
"index.twig": `{{ include("foo", {}, true) }}`,
'foo': `{{ title }}`
},
environmentOptions: {
globals: {
title: 'foo'
}
},
expectation: `foo`
});

View File

@ -8,6 +8,7 @@ import "./expressions";
import "./extensions";
import "./filters";
import "./functions";
import "./globals";
import "./implicit-auto-escaping";
import "./macros";
import "./operators";

View File

@ -0,0 +1,13 @@
import {runTest} from "../../TestBase";
runTest({
description: '"for" tag with context as sequence',
templates: {
"index.twig": `{% for key, value in _context %}{{ key }}{{ value }}{% endfor %}`
},
expectation: `foofoo valuebarbar value_parent[object Object]`,
context: Promise.resolve({
foo: 'foo value',
bar: 'bar value'
})
});

View File

@ -3,6 +3,7 @@ import "./condition.legacy";
import "./condition_and_nested_for_loop_access";
import "./containing_with";
import "./context";
import "./context-as-sequence";
import "./hashes";
import "./inner_variables";
import "./inside_with";