62 lines
2.0 KiB
JavaScript
62 lines
2.0 KiB
JavaScript
// SPDX-License-Identifier: MIT
|
|
// Copyright © 2021 fvtt-lib-wrapper Rui Pinheiro
|
|
|
|
'use strict';
|
|
|
|
// A shim for the libWrapper library
|
|
export let libWrapper = undefined;
|
|
|
|
Hooks.once('init', () => {
|
|
// Check if the real module is already loaded - if so, use it
|
|
if(globalThis.libWrapper && !(globalThis.libWrapper.is_fallback ?? true)) {
|
|
libWrapper = globalThis.libWrapper;
|
|
return;
|
|
}
|
|
|
|
// Fallback implementation
|
|
libWrapper = class {
|
|
static get is_fallback() { return true };
|
|
|
|
static register(module, target, fn, type="MIXED", {chain=undefined}={}) {
|
|
const is_setter = target.endsWith('#set');
|
|
target = !is_setter ? target : target.slice(0, -4);
|
|
const split = target.split('.');
|
|
const fn_name = split.pop();
|
|
const root_nm = split.splice(0,1)[0];
|
|
const _eval = eval; // The browser doesn't expose all global variables (e.g. 'Game') inside globalThis, but it does to an eval. We copy it to a variable to have it run in global scope.
|
|
const obj = split.reduce((x,y)=>x[y], globalThis[root_nm] ?? _eval(root_nm));
|
|
|
|
let iObj = obj;
|
|
let descriptor = null;
|
|
while(iObj) {
|
|
descriptor = Object.getOwnPropertyDescriptor(iObj, fn_name);
|
|
if(descriptor) break;
|
|
iObj = Object.getPrototypeOf(iObj);
|
|
}
|
|
if(!descriptor || descriptor?.configurable === false) throw `libWrapper Shim: '${target}' does not exist, could not be found, or has a non-configurable descriptor.`;
|
|
|
|
let original = null;
|
|
const wrapper = (chain ?? type != 'OVERRIDE') ? function() { return fn.call(this, original.bind(this), ...arguments); } : function() { return fn.apply(this, arguments); };
|
|
|
|
if(!is_setter) {
|
|
if(descriptor.value) {
|
|
original = descriptor.value;
|
|
descriptor.value = wrapper;
|
|
}
|
|
else {
|
|
original = descriptor.get;
|
|
descriptor.get = wrapper;
|
|
}
|
|
}
|
|
else {
|
|
if(!descriptor.set) throw `libWrapper Shim: '${target}' does not have a setter`;
|
|
original = descriptor.set;
|
|
descriptor.set = wrapper;
|
|
}
|
|
|
|
descriptor.configurable = true;
|
|
Object.defineProperty(obj, fn_name, descriptor);
|
|
}
|
|
}
|
|
});
|