mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2024-12-25 07:22:33 -05:00
Cache Block Inputs & Procedure Definitions
* Cache Block Inputs & Procedure Definitions * @mzgoddard requested changes on this pull request * Move all caching into a single reusable field _cache. * Invalidate 'all' caches on any change. * Use 'typeof' instead of hasOwnProperty. * Take caching out of Block and use lookup instead.
This commit is contained in:
parent
8ce20fd308
commit
6ed2ca6caa
1 changed files with 68 additions and 5 deletions
|
@ -25,6 +25,30 @@ class Blocks {
|
||||||
* @type {Array.<String>}
|
* @type {Array.<String>}
|
||||||
*/
|
*/
|
||||||
this._scripts = [];
|
this._scripts = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime Cache
|
||||||
|
* @type {{inputs: {}, procedureParamNames: {}, procedureDefinitions: {}}}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this._cache = {
|
||||||
|
/**
|
||||||
|
* Cache block inputs by block id
|
||||||
|
* @type {object.<string, !Array.<object>>}
|
||||||
|
*/
|
||||||
|
inputs: {},
|
||||||
|
/**
|
||||||
|
* Cache procedure Param Names by block id
|
||||||
|
* @type {object.<string, ?Array.<string>>}
|
||||||
|
*/
|
||||||
|
procedureParamNames: {},
|
||||||
|
/**
|
||||||
|
* Cache procedure definitions by block id
|
||||||
|
* @type {object.<string, ?string>}
|
||||||
|
*/
|
||||||
|
procedureDefinitions: {}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -105,11 +129,16 @@ class Blocks {
|
||||||
/**
|
/**
|
||||||
* Get all non-branch inputs for a block.
|
* Get all non-branch inputs for a block.
|
||||||
* @param {?object} block the block to query.
|
* @param {?object} block the block to query.
|
||||||
* @return {!object} All non-branch inputs and their associated blocks.
|
* @return {?Array.<object>} All non-branch inputs and their associated blocks.
|
||||||
*/
|
*/
|
||||||
getInputs (block) {
|
getInputs (block) {
|
||||||
if (typeof block === 'undefined') return null;
|
if (typeof block === 'undefined') return null;
|
||||||
const inputs = {};
|
let inputs = this._cache.inputs[block.id];
|
||||||
|
if (typeof inputs !== 'undefined') {
|
||||||
|
return inputs;
|
||||||
|
}
|
||||||
|
|
||||||
|
inputs = {};
|
||||||
for (const input in block.inputs) {
|
for (const input in block.inputs) {
|
||||||
// Ignore blocks prefixed with branch prefix.
|
// Ignore blocks prefixed with branch prefix.
|
||||||
if (input.substring(0, Blocks.BRANCH_INPUT_PREFIX.length) !==
|
if (input.substring(0, Blocks.BRANCH_INPUT_PREFIX.length) !==
|
||||||
|
@ -117,6 +146,8 @@ class Blocks {
|
||||||
inputs[input] = block.inputs[input];
|
inputs[input] = block.inputs[input];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._cache.inputs[block.id] = inputs;
|
||||||
return inputs;
|
return inputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,16 +180,24 @@ class Blocks {
|
||||||
* @return {?string} ID of procedure definition.
|
* @return {?string} ID of procedure definition.
|
||||||
*/
|
*/
|
||||||
getProcedureDefinition (name) {
|
getProcedureDefinition (name) {
|
||||||
|
const blockID = this._cache.procedureDefinitions[name];
|
||||||
|
if (typeof blockID !== 'undefined') {
|
||||||
|
return blockID;
|
||||||
|
}
|
||||||
|
|
||||||
for (const id in this._blocks) {
|
for (const id in this._blocks) {
|
||||||
if (!this._blocks.hasOwnProperty(id)) continue;
|
if (!this._blocks.hasOwnProperty(id)) continue;
|
||||||
const block = this._blocks[id];
|
const block = this._blocks[id];
|
||||||
if (block.opcode === 'procedures_definition') {
|
if (block.opcode === 'procedures_definition') {
|
||||||
const internal = this._getCustomBlockInternal(block);
|
const internal = this._getCustomBlockInternal(block);
|
||||||
if (internal && internal.mutation.proccode === name) {
|
if (internal && internal.mutation.proccode === name) {
|
||||||
return id; // The outer define block id
|
this._cache.procedureDefinitions[name] = id; // The outer define block id
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._cache.procedureDefinitions[name] = null;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,14 +207,23 @@ class Blocks {
|
||||||
* @return {?Array.<string>} List of param names for a procedure.
|
* @return {?Array.<string>} List of param names for a procedure.
|
||||||
*/
|
*/
|
||||||
getProcedureParamNames (name) {
|
getProcedureParamNames (name) {
|
||||||
|
const cachedNames = this._cache.procedureParamNames[name];
|
||||||
|
if (typeof cachedNames !== 'undefined') {
|
||||||
|
return cachedNames;
|
||||||
|
}
|
||||||
|
|
||||||
for (const id in this._blocks) {
|
for (const id in this._blocks) {
|
||||||
if (!this._blocks.hasOwnProperty(id)) continue;
|
if (!this._blocks.hasOwnProperty(id)) continue;
|
||||||
const block = this._blocks[id];
|
const block = this._blocks[id];
|
||||||
if (block.opcode === 'procedures_prototype' &&
|
if (block.opcode === 'procedures_prototype' &&
|
||||||
block.mutation.proccode === name) {
|
block.mutation.proccode === name) {
|
||||||
return JSON.parse(block.mutation.argumentnames);
|
const paramNames = JSON.parse(block.mutation.argumentnames);
|
||||||
|
this._cache.procedureParamNames[name] = paramNames;
|
||||||
|
return paramNames;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._cache.procedureParamNames[name] = null;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,6 +319,15 @@ class Blocks {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset all runtime caches.
|
||||||
|
*/
|
||||||
|
resetCache () {
|
||||||
|
this._cache.inputs = {};
|
||||||
|
this._cache.procedureParamNames = {};
|
||||||
|
this._cache.procedureDefinitions = {};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Block management: create blocks and scripts from a `create` event
|
* Block management: create blocks and scripts from a `create` event
|
||||||
* @param {!object} block Blockly create event to be processed
|
* @param {!object} block Blockly create event to be processed
|
||||||
|
@ -289,6 +346,8 @@ class Blocks {
|
||||||
if (block.topLevel) {
|
if (block.topLevel) {
|
||||||
this._addScript(block.id);
|
this._addScript(block.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.resetCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -301,7 +360,6 @@ class Blocks {
|
||||||
if (['field', 'mutation', 'checkbox'].indexOf(args.element) === -1) return;
|
if (['field', 'mutation', 'checkbox'].indexOf(args.element) === -1) return;
|
||||||
const block = this._blocks[args.id];
|
const block = this._blocks[args.id];
|
||||||
if (typeof block === 'undefined') return;
|
if (typeof block === 'undefined') return;
|
||||||
|
|
||||||
const wasMonitored = block.isMonitored;
|
const wasMonitored = block.isMonitored;
|
||||||
switch (args.element) {
|
switch (args.element) {
|
||||||
case 'field':
|
case 'field':
|
||||||
|
@ -337,6 +395,8 @@ class Blocks {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.resetCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -393,6 +453,7 @@ class Blocks {
|
||||||
}
|
}
|
||||||
this._blocks[e.id].parent = e.newParent;
|
this._blocks[e.id].parent = e.newParent;
|
||||||
}
|
}
|
||||||
|
this.resetCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -447,6 +508,8 @@ class Blocks {
|
||||||
|
|
||||||
// Delete block itself.
|
// Delete block itself.
|
||||||
delete this._blocks[blockId];
|
delete this._blocks[blockId];
|
||||||
|
|
||||||
|
this.resetCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in a new issue