What globals are available in template expressions? - vue.js

I'm reading the Vue.js guide, and I've come across the statement.
Template expressions are sandboxed and only have access to a whitelist
of globals such as Math and Date. You should not attempt to access
user defined globals in template expressions.
What are all the globals available in templates?
That is, what is the content of the whitelist, exhaustively?

Vue.js defines the whitelist of globals in the core/instance/proxy.js file:
//...
const allowedGlobals = makeMap(
'Infinity,undefined,NaN,isFinite,isNaN,' +
'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' +
'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' +
'require' // for Webpack/Browserify
)
// ...
When Vue compiles the template, the string interpolations are processed, and if you reference a global that is not whitelisted, you will have a warning on Development.
If you are curious about how templates are compiled to render functions, look through the template explorer.

From what I understood from source code globals are declared in a variable and make it available via a proxy between vm instance and template :
const allowedGlobals = makeMap(
'Infinity,undefined,NaN,isFinite,isNaN,' +
'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' +
'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' +
'require' // for Webpack/Browserify
)
So gobals available in template are :
Infinity
undefined
NaN
isFinite
isNaN
parseFloat
parseInt
decodeURI
decodeURIComponent
encodeURI
encodeURIComponent
Math
Number
Date
Array
Object
Boolean
String
RegExp
Map
Set
JSON
Intl
require
If you try to put in your template a reference that is not whitelisted or not in your vm instance then you will have this warning :
Property or method "${key}" is not defined on the instance but
referenced during render. Make sure that this property is reactive
either in the data option, or for class-based components, by
initializing the property.

Related

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

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
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);

In Vue2, how to remove observor functionality from object to save in cookie

I have the following code fragment and would like to strip the observer functionality from the user.accounts object. How would I do that? this.$cookies is a reference to my vue-cookies instance
setUserAccount(user, account){
// var accounts = Object.assign({},user.accounts)
this.$cookies.set('AUTH_TOKEN', user.authHash);
this.$cookies.set('CURRENT_ACCOUNT', user.id);
this.$cookies.set('ACCOUNTS', user.accounts);
console.log(user.accounts);
},
Convert the object to a JSON string. That will remove all the Vue observer mechanisms.
const strAccounts = JSON.stringify(user.accounts)
this.$cookies.set('ACCOUNTS', strAccounts);
And to convert it back (without the observer functionality).
JSON.parse(strAccounts);
The only caveat is you need to watch out for circular references in your object, and functions will not get serialized.

Global variables objects React-Native

I have one class ContentManager on android objects and global variables ContentManager style, the aim is to create this object from one time only, you can get set properties for it anywhere in the app, now declared on React native the declaration is this? the picture below is me java code on android. Help!!!!!!!
code in java
code in java
create global.js
module.exports = {
// your global variable
},
};
Then require it at the top in your file
GLOBAL = require('../global');
for access
GLOBAL.your_variable_name

AMD and Dojo 1.7 questions

Simple question.
Does AMD DOJO implementation support these type of declarations?
text!./plain.html
define(["../Widget","text!./plain.html"],
function(Widget,plain){
return new Widget({name:"mainApp",template:plain});
});
Load non-modules, let's say underscore.js
require(['dir/underscore.js'], function(){
_.reduce ...
});
Yes, but the precise syntax is different to that used in the question.
The Dojo Loader (1.7)
Plugins
dojo/text
The plugin for loading character data is dojo/text.
The extension should not be used when loading a JavaScript library and the location of the file is set via either a relative of the dojotoolkit base or a packages location declaration in dojoConfig:
require(['underscore'], function( _ ){
_.reduce ...
});
Configure the namespace in the Dojo configuration to avoid messy import paths - see dojoConfig in the loader documentation.
Also, consider using the dojo/global module and/or defining a Dojo module as a wrapper for Underscore.js:
//_.js
define(['dojo/global', 'underscore'], function(global){
return global._
});
With the above consideration, you must have loaded the actual .js file manually. If in conjunction with the dojo/text plugin, one would create a wrapper which also loads the required JS and evaluates it, following could do the trick.
/var/www/dojo-release-1.7/ext_lib/_.js - this sample file is hierachially placed in a library namespace, alongside dojo, dijit, dojox
define(['dojo/global', 'dojo/text!./Underscore.js'], function(global, scriptContents){
global.eval(scriptContents);
return global._ // '_' is the evaluated reference from window['_']
/**
* Alternatively, wrap even further to maintain a closure scope thus hiding _ from global
* - so adapt global.eval to simply eval
* - remove above return statement
* - return a dojo declared module with a getInstance simple method
*/
function get_ () { return _ };
var __Underscore = declare('ext_lib._', [/*mixins - none*/], {
getInstance: get_
});
// practical 'static' reference too, callable by 'ext_lib.getInstance' without creating a 'new ext_lib._'
__Underscore.getInstance = get_;
return __Underscore;
});
A sample of defining own modules using declare here
Note: this code is untested; feel free to add corrections.

WHMCS, how to create template variables from my hook

My question maybe is simple, but anfortunatly I don't know how to answer it.
How can I create a variable in a hook function and then pass a PHP variable from within the function to my Template in order to use it in the form of {VARIABLE_COMES_FROM_HOOK}
WHMCS uses Smarty template engine so as an example inside the includes/hooks folder you will have your hook file e.g hook_example.php from which you can assign variables to $smarty global object and access them in your template as {$VARIABLE_COMES_FROM_HOOK}.
Inside hook_example.php:
function example() {
global $smarty;
$variable = "Hello world!";
$smarty->assign('VARIABLE_COMES_FROM_HOOK', $variable);
}
Search in hook categories http://docs.whmcs.com/Hooks
There are hooks that return variables to tpl and other that don't do that