Skip to content

Commit

Permalink
⚡️ Only clone certain variables once, when they are initially set
Browse files Browse the repository at this point in the history
  • Loading branch information
skerit committed Apr 28, 2024
1 parent 4f49d6d commit 4dfd010
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 108 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -7,6 +7,7 @@
* Don't let `Hawkejs.doNextSync(promise)` swallow errors
* Use methods for getting (and proxy traps for setting) variables on the `Variables` class
* Refactor variable access in compiled template code
* Only clone certain variables once, when they are initially set

## 2.3.19 (2024-04-13)

Expand Down
1 change: 0 additions & 1 deletion lib/core/base.js
Expand Up @@ -474,7 +474,6 @@ Hawkejs.CONSTRUCTED = Symbol('constructed');
Hawkejs.SERIALIZING = Symbol('serializing');
Hawkejs.VARIABLES = Symbol('variables');
Hawkejs.PRE_TASKS = Symbol('pre_tasks');
Hawkejs.PRE_CLONE = Symbol('pre_clone');
Hawkejs.RC_CACHE = Symbol('rc_cache');
Hawkejs.RESULT = Symbol('result');
Hawkejs.BLOCK = Symbol('block');
Expand Down
92 changes: 26 additions & 66 deletions lib/core/renderer.js
Expand Up @@ -8,7 +8,7 @@ const TASK_GROUP = Symbol('task_group'),
*
* @author Jelle De Loecker <jelle@elevenways.be>
* @since 1.0.0
* @version 2.2.12
* @version 2.4.0
*
* @param {Hawkejs} hawkejs
*/
Expand Down Expand Up @@ -44,9 +44,6 @@ const Renderer = Fn.inherits('Hawkejs.Base', function Renderer(hawkejs) {
// Templates to render
this.queued_templates = [];

// The clone symbol
this.clone_symbol = Symbol('clone');

// Created dialogs
this.dialogs = [];

Expand Down Expand Up @@ -205,6 +202,19 @@ Renderer.enforceRootProperty(function expose_to_scene(value) {
return Hawkejs.Variables.cast(value, this);
});

/**
* The weakmap used for cloning variables
*
* @author Jelle De Loecker <jelle@elevenways.be>
* @since 2.4.0
* @version 2.4.0
*
* @type {WeakMap}
*/
Renderer.enforceRootProperty(function weakmap_for_cloning(value) {
return value || new WeakMap();
});

/**
* Items to preload
*
Expand Down Expand Up @@ -821,7 +831,7 @@ Renderer.setMethod(function toJSON() {
*
* @author Jelle De Loecker <jelle@elevenways.be>
* @since 2.2.11
* @version 2.3.16
* @version 2.4.0
*/
Renderer.setMethod(function _prepareClone(wm, custom_method) {

Expand All @@ -832,8 +842,8 @@ Renderer.setMethod(function _prepareClone(wm, custom_method) {
let blocks = this.blocks._prepareClone(this, wm, custom_method);

const result = {
variables : this._prepareVariables(this.variables, wm, custom_method),
expose_to_scene : this._prepareVariables(this.expose_to_scene, wm, custom_method),
variables : this.variables,
expose_to_scene : this.expose_to_scene,
request : this.request,
blocks : blocks,
page_title : this.page_title,
Expand Down Expand Up @@ -945,58 +955,14 @@ Renderer.setMethod(function createSubRenderer() {
*
* @author Jelle De Loecker <jelle@develry.be>
* @since 2.0.0
* @version 2.2.11
* @version 2.4.0
*
* @param {Object} variables
*
* @return {Object}
* @return {Hawkejs.Variables}
*/
Renderer.setMethod(function prepareVariables(variables) {
return this._prepareVariables(variables);
});

/**
* Prepare variables
*
* @author Jelle De Loecker <jelle@elevenways.be>
* @since 2.2.11
* @version 2.2.14
*
* @param {Object} variables
* @param {WeakMap} wm
*
* @return {Object}
*/
Renderer.setMethod(function _prepareVariables(variables, wm, custom_method) {

if (!variables) {
return null;
}

variables = Hawkejs.Variables.cast(variables, this);

let clone = variables.getExistingCloneIfValid(Hawkejs.PRE_CLONE);

if (clone) {
return clone;
}

clone = variables.getExistingCloneIfValid(this.clone_symbol);

if (clone) {
return clone;
}

if (!custom_method) {
custom_method = 'toHawkejs';
}

clone = Bound.JSON.clone(variables, custom_method, [this], wm);

variables[this.clone_symbol] = clone;
clone[this.clone_symbol] = clone;

return clone;
return Hawkejs.Variables.cast(variables, this);
});

/**
Expand Down Expand Up @@ -1242,7 +1208,7 @@ Renderer.setMethod(function serializeForClientSideRender() {
*
* @author Jelle De Loecker <jelle@develry.be>
* @since 2.0.0
* @version 2.3.15
* @version 2.4.0
*
* @param {Hawkejs.Templates} templates
* @param {Object} variables
Expand All @@ -1266,7 +1232,7 @@ Renderer.setMethod(function renderTemplate(templates, variables, main_name_modif
}

if (variables) {
templates.variables = variables;
templates.variables = Hawkejs.Variables.cast(variables, this);
}

// This still has to remain async for now
Expand All @@ -1277,12 +1243,6 @@ Renderer.setMethod(function renderTemplate(templates, variables, main_name_modif
return next();
}

that.variables = that.prepareVariables(that.variables);

if (templates.variables) {
that.prepareVariables(templates.variables);
}

// Clone the variables, use the toHawkejs method if available
let variables = templates.variables || that.variables;

Expand Down Expand Up @@ -2242,7 +2202,7 @@ Renderer.setMethod(function applyElementOptions(element, options, for_sync_rende
if (options.variables) {

if (!element[Hawkejs.VARIABLES]) {
element[Hawkejs.VARIABLES] = this.prepareVariables({});
element[Hawkejs.VARIABLES] = this.prepareVariables();
}

for (i = 0; i < options.variables.length; i++) {
Expand Down Expand Up @@ -4017,7 +3977,7 @@ Renderer.setCommand(function set(name, value) {
return this.variables.get(name);
}

this.variables.set(name, value);
this.variables.setShouldTransform(name, value);
});

/**
Expand Down Expand Up @@ -4112,7 +4072,7 @@ Renderer.setCommand(function expose(name, value) {
return;
}

this.expose_to_scene.set(name, value);
this.expose_to_scene.setShouldTransform(name, value);
});

/**
Expand All @@ -4137,7 +4097,7 @@ Renderer.setCommand(function serverVar(name, value) {
return this.server_variables.get(name);
}

this.server_variables.set(name, value);
this.server_variables.setShouldTransform(name, value);
});

/**
Expand Down
80 changes: 46 additions & 34 deletions lib/core/variables.js
Expand Up @@ -54,41 +54,27 @@ const TRAPS = {
* @version 2.0.0
*/
const Variables = Fn.inherits('Hawkejs.Base', function Variables(renderer, variables) {
this[Hawkejs.PRE_CLONE] = null;
this[renderer.clone_symbol] = null;
this[PARENT] = null;
this[RENDERER] = renderer;
this[TRAPLESS] = this;
this[VALUES] = mapify(variables);
});

/**
* Turn the given input into a map
*
* @author Jelle De Loecker <jelle@elevenways.be>
* @since 2.4.0
* @version 2.4.0
*
* @param {Object|Map|Variables} input
*
* @return {Map}
*/
function mapify(input) {

if (!input) {
return new Map();
}

if (input instanceof Map) {
return new Map(input);
}
if (variables && typeof variables == 'object') {
if (variables instanceof Map) {
this[VALUES] = new Map(variables);
} else if (variables instanceof Variables) {
this[VALUES] = new Map(variables[TRAPLESS][VALUES]);
this[PARENT] = variables;
} else {
this[VALUES] = new Map();

if (input instanceof Variables) {
return mapify(input[TRAPLESS][VALUES]);
for (let key in variables) {
this.setShouldTransform(key, variables[key]);
}
}
} else {
this[VALUES] = new Map();
}

return new Map(Object.entries(input));
}
});

/**
* Make sure the result is a valid Variables instance
Expand Down Expand Up @@ -221,7 +207,8 @@ Variables.setMethod(function setEphemeralGetter(key, getter) {
});

/**
* Set a specific variable from a template
* Set a variable by name.
* The variable will be stored as is.
*
* @author Jelle De Loecker <jelle@elevenways.be>
* @since 2.4.0
Expand All @@ -231,6 +218,31 @@ Variables.setMethod(function set(key, value) {
return this[VALUES].set(key, value);
});

/**
* Set a variable by name.
* The variable will be converted to the proper hawkejs representation
*
* @author Jelle De Loecker <jelle@elevenways.be>
* @since 2.4.0
* @version 2.4.0
*
* @param {string} key
* @param {*} value
*/
Variables.setMethod(function setShouldTransform(key, value) {

if (!value || typeof value != 'object') {
return this.set(key, value);
}

const renderer = this[RENDERER],
weakmap = renderer.weakmap_for_cloning;

let cloned = Bound.JSON.clone(value, 'toHawkejs', [renderer], weakmap);

return this.set(key, cloned);
});

/**
* Set a specific variable from a template
*
Expand Down Expand Up @@ -287,7 +299,7 @@ Variables.setMethod(function getExistingCloneIfValid(clone_name) {
*
* @author Jelle De Loecker <jelle@develry.be>
* @since 2.0.0
* @version 2.0.0
* @version 2.4.0
*
* @param {WeakMap} wm
*
Expand All @@ -312,7 +324,7 @@ Variables.setMethod(function toHawkejs(wm) {
dict = Bound.JSON.clone(dict, 'toHawkejs', wm);

// Put the cloned values back into the result
result[VALUES] = mapify(dict);
result[VALUES] = new Map(Object.entries(dict))

return result;
});
Expand All @@ -323,10 +335,10 @@ Variables.setMethod(function toHawkejs(wm) {
*
* @author Jelle De Loecker <jelle@elevenways.be>
* @since 2.3.7
* @version 2.3.7
* @version 2.4.0
*/
Variables.setMethod(function getShallowClone() {
let result = new Variables(this[RENDERER], this.toJSON());
let result = new Variables(this[RENDERER], new Map(Object.entries(this.toJSON())));
return result;
});

Expand Down
6 changes: 2 additions & 4 deletions lib/element/custom_element.js
Expand Up @@ -1055,8 +1055,6 @@ function renderCustomTemplate(re_render) {
render_vars.setFromTemplate('child_nodes', slot_data.child_nodes);
render_vars.setFromTemplate('$ancestor_element', that);

render_vars[renderer.clone_symbol] = render_vars;

renderer.renderTemplate(template, render_vars, String(render_counter++)).done(next);
}, function assembleBlock(next, template) {

Expand Down Expand Up @@ -1926,7 +1924,7 @@ Element.setMethod(function setVariable(name, value) {
let variables = this[Hawkejs.VARIABLES];

if (!variables) {
variables = this[Hawkejs.VARIABLES] = this.hawkejs_renderer.prepareVariables({});
variables = this[Hawkejs.VARIABLES] = this.hawkejs_renderer.prepareVariables();
}

variables.set(name, value);
Expand Down Expand Up @@ -2531,7 +2529,7 @@ Element.setMethod(function applyCompiledTemplate(fnc) {
if (this[Hawkejs.VARIABLES]) {
render_vars = this[Hawkejs.VARIABLES].overlay();
} else {
render_vars = renderer.prepareVariables({});
render_vars = renderer.prepareVariables();
}

render_vars.setEphemeralGetter('self', () => {
Expand Down
14 changes: 11 additions & 3 deletions test/10-expressions.js
Expand Up @@ -939,6 +939,10 @@ function createTests(tests) {
}
};

CustomList.prototype.toHawkejs = function toHawkejs() {
return this;
};

let my_deck = new __Protoblast.Classes.Deck();
my_deck.set('x', 'X');
my_deck.set('y', 'Y');
Expand Down Expand Up @@ -990,7 +994,7 @@ function createTests(tests) {
empty_obj : {},
falsy : false,
success : true,
error : new Error('Some error'),
error : 'some error',//,new Error('Some error'),
stuff : 'stuff',
opt_str : new Blast.Classes.Develry.Optional('truthy'),
opt_empty : new Blast.Classes.Develry.Optional(),
Expand Down Expand Up @@ -1106,10 +1110,14 @@ function createTests(tests) {
}
};

vars.iterable = iterable;
let renderer = hawkejs.createRenderer();
let variables = renderer.prepareVariables(vars);

// Set this later, so it won't get cloned
// (and lose the iterator property)
variables.set('iterable', iterable);

hawkejs.render(compiled, vars, function done(err, res) {
renderer.renderHTML(compiled, variables).done(function done(err, res) {

if (err) {
return next(err);
Expand Down

0 comments on commit 4dfd010

Please sign in to comment.