@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
127 lines (99 loc) • 2.76 kB
JavaScript
import { assert } from "../../../core/assert.js";
export class DataScope {
constructor() {
/**
* @private
* @type {Object[]}
*/
this.stack = [];
this.proxy = new Proxy(this, {
/**
*
* @param target
* @param {string} p
* @param receiver
* @returns {*}
*/
get(target, p, receiver) {
return target.read(p);
},
ownKeys(target) {
const size = target.size();
/**
*
* @type {string[]}
*/
const result = [];
for (let i = 0; i < size; i++) {
const frame = target.stack[i];
const keys = Reflect.ownKeys(frame);
const n = keys.length;
for (let j = 0; j < n; j++) {
const key = keys[j];
if (!result.includes(key)) {
result.push(key);
}
}
}
return result;
}
});
}
/**
*
* @return {number}
*/
size() {
return this.stack.length;
}
/**
*
* @param {string} variable_name
* @returns {*|undefined}
*/
read(variable_name) {
assert.isString(variable_name, 'variable_name');
const stack = this.stack;
const last = stack.length - 1;
for (let i = last; i >= 0; i--) {
const scope = stack[i];
const value = scope[variable_name];
if (value !== undefined) {
return value;
}
}
//not found
return undefined;
}
/**
*
* @param {Object} scope
*/
push(scope) {
assert.defined(scope, 'scope');
assert.notNull(scope, 'scope');
assert.isObject(scope, 'scope');
this.stack.push(scope);
}
/**
*
* @returns {Object}
*/
pop() {
assert.ok(this.stack.length > 0, 'Stack is empty');
return this.stack.pop();
}
/**
* Drop multiple frames from the top of the stack until stack size matches given value
* @param {number} size
* @returns {number} how many frames were dropped
*/
unwind(size) {
const top = this.size();
const count = top - size;
for (let i = 0; i < count; i++) {
this.pop();
}
return count;
}
}