Skip to content

Commit

Permalink
♻️ Use methods for getting (and proxy traps for setting) variables on…
Browse files Browse the repository at this point in the history
… the `Variables` class
  • Loading branch information
skerit committed Apr 27, 2024
1 parent 3c93786 commit cdc6d5e
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* Make sure variables are always cast to a `Variables` instance
* Add `Variables#get(key)` & `Variables#setFromTemplate(key, value)` method
* Don't let `Hawkejs.doNextSync(promise)` swallow errors
* Use methods for getting (and proxy traps for setting) variables on the `Variables` class

## 2.3.19 (2024-04-13)

Expand Down
22 changes: 22 additions & 0 deletions benchmark/05-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ const createRawVariables = () => {
return {...RAW_VARIABLES};
};

const PREPARED_VARIABLES = RENDERER.prepareVariables(createRawVariables());
const LAYERED_VARIABLES = PREPARED_VARIABLES.overlay({e_object: {a: 10}});

//RENDERER.renderHTML(VARIABLE_TEST_TEMPLATE, createRawVariables()).done((err, result) => console.log(err, result))
//console.log();

Expand Down Expand Up @@ -74,3 +77,22 @@ suite('Renderer', function() {
});
});

suite('Variables', () => {

bench('get(key)', () => {
let nr = PREPARED_VARIABLES.get('a_number');
nr += PREPARED_VARIABLES.get('e_object').a;

if (nr !== 15) {
throw new Error('Invalid result: ' + nr);
}

let overlayed_nr = LAYERED_VARIABLES.get('a_number');
overlayed_nr += LAYERED_VARIABLES.get('e_object').a;

if (overlayed_nr !== 24) {
throw new Error('Invalid result: ' + overlayed_nr);
}
});

});
19 changes: 16 additions & 3 deletions lib/core/hawkejs.js
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,7 @@ Main.setMethod(function parseTemplateSyntax(source, name, wrap_ejs) {
*
* @author Jelle De Loecker <[email protected]>
* @since 1.0.0
* @version 2.3.18
* @version 2.4.0
*
* @param {string} code
* @param {Hawkejs.Scopes} scopes
Expand Down Expand Up @@ -1018,8 +1018,21 @@ Main.setMethod(function rewriteVariableReferences(code, scopes, level) {
if (Hawkejs.hasGlobal(token.value)) {
token.value = '(Hawkejs.getGlobal(' + JSON.stringify(token.value) + '))';
} else {
// All the rest are variables that should be changed
token.value = 'vars.' + token.value;

let is_assignment = false,
name = next?.name;

if (name) {
if (name == 'increment' || name == 'decrement' || name.indexOf('assign') === 0) {
is_assignment = true;
}
}

if (is_assignment) {
token.value = 'vars.getProxy().' + token.value;
} else {
token.value = 'vars.get(' + JSON.stringify(token.value) + ')';
}
}
}
}
Expand Down
53 changes: 48 additions & 5 deletions lib/core/variables.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
const PARENT = Symbol('parent'),
RENDERER = Symbol('renderer');
RENDERER = Symbol('renderer'),
TRAPLESS = Symbol('trapless'),
PROXY = Symbol('proxy');

/**
* This way we can skip transforming ejs `my_value = 1`
* into complicated calls.
*
* @author Jelle De Loecker <[email protected]>
* @since 2.4.0
* @version 2.4.0
*/
const TRAPS = {
set(target, name, value) {

if (typeof name == 'symbol') {
target[name] = value;
} else {
target.setFromTemplate(name, value);
}

return true;
}
};

/**
* Simple class to use for storing variables
Expand All @@ -13,6 +36,7 @@ const Variables = Fn.inherits('Hawkejs.Base', function Variables(renderer, varia
this[renderer.clone_symbol] = null;
this[PARENT] = null;
this[RENDERER] = renderer;
this[TRAPLESS] = this;

if (variables != null) {
Object.assign(this, variables);
Expand Down Expand Up @@ -60,6 +84,24 @@ Variables.setProperty(function length() {
return Object.keys(this).length;
});

/**
* Get the proxy of this instance.
* This allows us to set variables without having to use the `set` method.
*
* @author Jelle De Loecker <[email protected]>
* @since 2.4.0
* @version 2.4.0
*/
Variables.setMethod(function getProxy() {

if (this[PROXY] == null) {
this[PROXY] = new Proxy(this, TRAPS);
this[PROXY][TRAPLESS] = this;
}

return this[PROXY];
});

/**
* Get a specific variable
*
Expand Down Expand Up @@ -137,11 +179,12 @@ Variables.setMethod(function getExistingCloneIfValid(clone_name) {
*
* @author Jelle De Loecker <[email protected]>
* @since 2.0.0
* @version 2.0.0
* @version 2.4.0
*/
Variables.setMethod(function createShim() {

var result = Object.create(this);
let result = Object.create(this[TRAPLESS]);
result[PROXY] = null;

return result;
});
Expand Down Expand Up @@ -226,7 +269,7 @@ Variables.setMethod(function toJSON() {
*
* @author Jelle De Loecker <[email protected]>
* @since 2.0.0
* @version 2.0.0
* @version 2.4.0
*/
Variables.setMethod(function overlay(new_variables) {

Expand All @@ -242,7 +285,7 @@ Variables.setMethod(function overlay(new_variables) {

// This will set this instance as the new parent of the variables instance
// (This can overwrite the parent in the cloned instance)
result[PARENT] = this;
result[PARENT] = this[TRAPLESS];

return result;
});
4 changes: 2 additions & 2 deletions test/00-init.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ describe('Hawkejs', function() {
fnc = hawkejs.compile('test this js: <% i = 10;\nprint(i);%>');
body = String(fnc);

if (body.indexOf('print(vars.i)') == -1) {
if (body.indexOf('print(vars.get("i"))') == -1) {
throw new Error('The inline JS code was not added to the compiled function');
}

Expand Down Expand Up @@ -209,7 +209,7 @@ print(zever);
assertContains(code, 'let zever = 1; __render.print(zever);');

assertContains(code, '{__render.print(zever);}');
assertContains(code, '__render.print(vars.zever)');
assertContains(code, '__render.print(vars.get("zever"))');

hawkejs.try_template_expressions = true;
hawkejs.skip_set_err = false;
Expand Down

0 comments on commit cdc6d5e

Please sign in to comment.