Handlebars with Assemble build returning "not an own property of its parent"

162 Views Asked by At

I am experiencing the dreaded not an "own property" of its parent issue when attempting to build my Handlebars project.

I have been down the rabbit hole and seen the many explanations of using @handlebars/allow-prototype-access to allow the issue to be bypassed, however it seems the project does not use a standard implementation of Handlebars...

It seems I am using something called engine-handlebars

Where I would expect to implement that allow-prototype-access change, I see the following:

app.pages('./source/pages/**/*.hbs');
app.engine('hbi', require('engine-handlebars'));

I can't fathom how I am supposed to implement the prototype access with this setup...

It seems, after a bit of trial and error, commenting lines out as I go, that the line app.pages('./source/pages/**/*.hbs'); is actually causing the issue...

When I run the project with this line in, I get the error:

Handlebars: Access has been denied to resolve the property "path" because it is not an "own property" of its parent.
You can add a runtime option to disable the check or this warning:
See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details
[10:54:49] ERROR - undefined: Cannot read property 'substring' of undefined
1

There are 1 best solutions below

0
romellem On

The plugin @handlebars/allow-prototype-access works by modifying the Handlebars instance.

const _Handlebars = require('handlebars');
const { allowInsecurePrototypeAccess } = require('@handlebars/allow-prototype-access');

const Handlebars = allowInsecurePrototypeAccess(_Handlebars);

Note that allowInsecurePrototypeAccess does not modify the instance in place, but creates an isolated instance via Handlebars.create() so you must use its return value.

In your case, engine-handlebars exposes the Handlebars instance in different ways depending on what version you are using.

Based on your code you provided, my guess is you are using <1.0.0, but I'll provide methods for adjusting this for all its versions.

engine-handlebars@<0.6.0

Unfortunately these versions don't expose Handlebars in any way, so if you are using this version I recommend upgrading engine-handlebars to a later version.

engine-handlebars@>=0.6.0 <1.0.0

Version 0.6.0 exposed Handlebars as a property on the exported engine function. This is then referenced throughout the library via this.Handlebars.

You can then change this before setting the app.engine() and it should work.

const _Handlebars = require('handlebars');
const { allowInsecurePrototypeAccess } = require('@handlebars/allow-prototype-access');
const engine = require('engine-handlebars');

// elsewhere...
// const app = ...

// Do this *before* setting app.engine
const insecureHandlebars = allowInsecurePrototypeAccess(_Handlebars);
engine.Handlebars = insecureHandlebars;

app.engine('hbi', engine);

engine-handlebars@>=1.0.0

For version 1.0.0 and beyond, you must pass the Handlebars instance yourself.

const Handlebars = require('handlebars');
const engine = require('engine-handlebars')(Handlebars);

Thus you don't need to set anything on engine, you just pass in the modified instance when you need it.

const _Handlebars = require('handlebars');
const { allowInsecurePrototypeAccess } = require('@handlebars/allow-prototype-access');

// elsewhere...
// const app = ...

// Do this *before* setting app.engine
const insecureHandlebars = allowInsecurePrototypeAccess(_Handlebars);
const engine = require('engine-handlebars')(insecureHandlebars);

app.engine('hbi', engine);