Skip to content

Commit

Permalink
Make wrapper instanciation lazy
Browse files Browse the repository at this point in the history
  • Loading branch information
pmdartus committed Jan 22, 2020
1 parent fda810e commit 5506762
Show file tree
Hide file tree
Showing 3 changed files with 1,060 additions and 664 deletions.
67 changes: 39 additions & 28 deletions lib/constructs/interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,9 @@ class Interface {
generateRequires() {
this.requires.addRaw("impl", "utils.implSymbol");
this.requires.addRaw("ctorRegistry", "utils.ctorRegistrySymbol");
this.requires.addRaw("wrapperSymbol", "utils.wrapperSymbol");
this.requires.addRaw("globalObjectSymbol", "utils.globalObjectSymbol");
this.requires.addRaw("createWrapperSymbol", "utils.createWrapperSymbol");

if (this.idl.inheritance !== null) {
this.requires.add(this.idl.inheritance);
Expand Down Expand Up @@ -1126,7 +1129,9 @@ class Interface {

generateIface() {
this.str += `
exports.create = function create(globalObject, constructorArgs, privateData) {
function createWrapper(implObject) {
const globalObject = implObject[globalObjectSymbol];
if (globalObject[ctorRegistry] === undefined) {
throw new Error('Internal error: invalid global object');
}
Expand All @@ -1136,49 +1141,55 @@ class Interface {
throw new Error('Internal error: constructor ${this.name} is not installed on the passed global object');
}
let obj = Object.create(ctor.prototype);
obj = exports.setup(obj, globalObject, constructorArgs, privateData);
return obj;
};
exports.createImpl = function createImpl(globalObject, constructorArgs, privateData) {
const obj = exports.create(globalObject, constructorArgs, privateData);
return utils.implForWrapper(obj);
};
exports._internalSetup = function _internalSetup(obj) {
let wrapperObject = Object.create(ctor.prototype);
exports._internalSetup(wrapperObject);
`;

if (this.idl.inheritance) {
if (this.isLegacyPlatformObj) {
this.str += `
${this.idl.inheritance}._internalSetup(obj);
wrapperObject = new Proxy(wrapperObject, proxyHandler);
`;
}

this.generateOnInstance();

this.str += `
implObject[wrapperSymbol] = wrapperObject;
wrapperObject[impl] = implObject;
return wrapperObject;
};
exports.setup = function setup(obj, globalObject, constructorArgs = [], privateData = {}) {
privateData.wrapper = obj;
exports.create = function create(globalObject, constructorArgs, privateData) {
const implObject = exports.createImpl(globalObject, constructorArgs, privateData);
return utils.wrapperForImpl(implObject);
};
exports.createImpl = function createImpl(globalObject, constructorArgs = [], privateData = {}) {
const implObject = new Impl.implementation(globalObject, constructorArgs, privateData);
exports._internalSetup(obj);
Object.defineProperty(obj, impl, {
value: new Impl.implementation(globalObject, constructorArgs, privateData),
configurable: true
});
implObject[wrapperSymbol] = null;
implObject[globalObjectSymbol] = globalObject;
implObject[createWrapperSymbol] = createWrapper;
return implObject;
};
exports.setup = function setup(wrapperObject, globalObject, constructorArgs = [], privateData = {}) {
const implObject = exports.createImpl(globalObject, constructorArgs, privateData);
implObject[wrapperSymbol] = wrapperObject;
wrapperObject[impl] = implObject;
exports._internalSetup(wrapperObject);
return wrapperObject;
};
exports._internalSetup = function _internalSetup(obj) {
`;

if (this.isLegacyPlatformObj) {
if (this.idl.inheritance) {
this.str += `
obj = new Proxy(obj, proxyHandler);
${this.idl.inheritance}._internalSetup(obj);
`;
}
this.generateOnInstance();

this.str += `
obj[impl][utils.wrapperSymbol] = obj;
if (Impl.init) {
Impl.init(obj[impl], privateData);
}
return obj;
};
`;
}
Expand Down
15 changes: 14 additions & 1 deletion lib/output/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ function hasOwn(obj, prop) {

const wrapperSymbol = Symbol("wrapper");
const implSymbol = Symbol("impl");
const globalObjectSymbol = Symbol("global object");
const createWrapperSymbol = Symbol("create wrapper");
const sameObjectCaches = Symbol("SameObject caches");
const ctorRegistrySymbol = Symbol.for("[webidl2js] constructor registry");

Expand All @@ -28,7 +30,16 @@ function getSameObject(wrapper, prop, creator) {
}

function wrapperForImpl(impl) {
return impl ? impl[wrapperSymbol] : null;
if (!impl) {
return null;
}

const wrapper = impl[wrapperSymbol];
if (wrapper === undefined || wrapper !== null) {
return wrapper;
}

return impl[createWrapperSymbol](impl);
}

function implForWrapper(wrapper) {
Expand Down Expand Up @@ -91,6 +102,8 @@ module.exports = exports = {
hasOwn,
wrapperSymbol,
implSymbol,
globalObjectSymbol,
createWrapperSymbol,
getSameObject,
ctorRegistrySymbol,
wrapperForImpl,
Expand Down
Loading

0 comments on commit 5506762

Please sign in to comment.