Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] I'm seeing some strange behaviors with shared environments, anyone see this behavior before? #565

Open
jrlost opened this issue Feb 9, 2024 · 2 comments
Labels

Comments

@jrlost
Copy link

jrlost commented Feb 9, 2024

I have a model, it looks similar to this:

[
    {
        "url": "//domain.com/4fc914bb-7c8c-4801-a0a0-e2819413f703.jpg",
        "sequence": 1,
        "isPrimary": true,
        "isImage": true,
        "imageType": "Studio"
    },
    ....
]

As part of a larger template, I have this

{{#objectFilter @data.images "isPrimary=true OR isImage=false"}}
	<pre>{{toJson this}}</pre>

	{{#each this}}
		<pre>{{this}}</pre>
		<pre>{{toJson this}}</pre>

		this.isImage => {{this.isImage}},
		isImage => {{isImage}},		
		this.isPrimary => {{this.isPrimary}},
		isPrimary => {{isPrimary}},

		<pre>{{toJson this}}</pre>
	{{/each}}
{{/objectFilter}}

With HandlebarsDotNet.Handlebars.CreateSharedEnvironment(config);, I get a result of

<pre>[{"url":"//domain.com/4fc914bb-7c8c-4801-a0a0-e2819413f703.jpg","sequence":1,"isPrimary":true,"isImage":true,"imageType":"Studio"}]</pre>
<pre>[url, //domain.com/4fc914bb-7c8c-4801-a0a0-e2819413f703.jpg],[sequence, 1],[isPrimary, True],[isImage, True],[imageType, Studio]</pre>
<pre>{"url":"//domain.com/4fc914bb-7c8c-4801-a0a0-e2819413f703.jpg","sequence":1,"isPrimary":true,"isImage":true,"imageType":"Studio"}</pre>

this.isImage => True,
isImage => True,
this.isPrimary => ,
isPrimary => True,

<pre>{"url":"//domain.com/4fc914bb-7c8c-4801-a0a0-e2819413f703.jpg","sequence":1,"isPrimary":true,"isImage":true,"imageType":"Studio"}</pre>

Note the this.isPrimary => ,

Changing only HandlebarsDotNet.Handlebars.CreateSharedEnvironment(config); to HandlebarsDotNet.Handlebars.Create(config); results in an output of

<pre>[{"url":"//domain.com/4fc914bb-7c8c-4801-a0a0-e2819413f703.jpg","sequence":1,"isPrimary":true,"isImage":true,"imageType":"Studio"}]</pre>
<pre>[url, //domain.com/4fc914bb-7c8c-4801-a0a0-e2819413f703.jpg],[sequence, 1],[isPrimary, True],[isImage, True],[imageType, Studio]</pre>
<pre>{"url":"//domain.com/4fc914bb-7c8c-4801-a0a0-e2819413f703.jpg","sequence":1,"isPrimary":true,"isImage":true,"imageType":"Studio"}</pre>

this.isImage => True,
isImage => True,
this.isPrimary => True,
isPrimary => True,

<pre>{"url":"//domain.com/4fc914bb-7c8c-4801-a0a0-e2819413f703.jpg","sequence":1,"isPrimary":true,"isImage":true,"imageType":"Studio"}</pre>

Again, note this.isPrimary => True,

Can anyone think of why this. would evaluate differently when using a shared environment?
To add to the mystery, it's always happening to this one property, notice the isImage property was not impacted. Also, we do use custom helpers, but none change the context, attempt to do any late binding, or interact with the BlockHelperOptions. The objectFilter helper above uses Antlr to filter a collection of objects given an expression, so something like this:

		/// <summary>
		/// Filters a list of objects given some expression.
		/// </summary>
		/// <param name="input">List to apply the filter to.</param>
		/// <param name="expression">Expression to filter by.</param>
		/// <param name="ignoreCase">Whether or not to ignore case.</param>
		/// <returns>The filtered list; null if input is null.</returns>
		public static List<object> Filter(object input, string expression, bool ignoreCase) {
			if (input == null) {
				return null;
			}

			if (input is List<object> list) {
				var context = new FilterParser(
					new CommonTokenStream(
						new FilterLexer(
							CharStreams.fromString(expression)
						)
					)
				) {
					BuildParseTree = true
				}.parse();

				return list.Where(i => (bool) new FilterVisitor(i as Dictionary<string, object>, ignoreCase).Visit(context)).ToList();
			}

			return null;
		}

The toJson simply returns the serialized representation of the object

		/// <summary>
		/// Convert an object to a serialized json string.
		/// </summary>
		/// <param name="input">Object to serialize.</param>
		/// <returns>Serialized response.</returns>
		public static string ToJson(object input) {
			return input == null ? null : JsonConvert.SerializeObject(input);
		}

I added the output of this above and below to show that it does contain the property I'm attempting to access; so I can't imagine it's a case where we're running into some concurrency issue; additionally, I'd expect this to puke randomly if that were the case and not always on this specific property.

One more piece to add to the mystery, I cannot replicate this locally in an isolated environment (even when using the full complete model and template), so there's something more to it (which I'll continue to try to diagnose and identify). I'm just curious

  1. if anyone has seen this before
  2. if anyone has any clues as to why/how there could be a discrepancy between {{property}} and {{this.property}}

Thanks, I appreciate any insight.

@jrlost jrlost added the question label Feb 9, 2024
@oformaniuk
Copy link
Member

It may be easier to help if you provide a test that reproduces the problem.

@jrlost
Copy link
Author

jrlost commented Apr 8, 2024

Right, as I said, I've still been unable to replicate it locally in an isolated environment. I will continue to poke around and figure out what might be causing this to happen.

I created this issue to simply get some feelers out as to whether or not anyone else has seen behavior like this. I'm trying/hoping that I'm simply doing something wrong, making an incorrect assumption, or at the very least hoping I could get some more anecdotal evidence to use in diagnosing the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants