Skip to content

Commit

Permalink
Reformat templating code
Browse files Browse the repository at this point in the history
Also add a bunch of tests.

On the road to fixing jsdom#35.
  • Loading branch information
TimothyGu committed Aug 2, 2017
1 parent f89ec53 commit 2c772f6
Show file tree
Hide file tree
Showing 12 changed files with 689 additions and 451 deletions.
56 changes: 32 additions & 24 deletions lib/constructs/attribute.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function Attribute(ctx, obj, I, idl) {

Attribute.prototype.generate = function () {
let str = "";
let requires = {};
const requires = {};

const configurable = !utils.getExtAttr(this.idl.extAttrs, "Unforgeable");
const shouldReflect = utils.getExtAttr(this.idl.extAttrs, "Reflect");
Expand Down Expand Up @@ -49,38 +49,46 @@ Attribute.prototype.generate = function () {
getterBody = `return utils.getSameObject(this, "${this.idl.name}", () => { ${getterBody} });`;
}

str += `Object.defineProperty(${definedOn}, "${this.idl.name}", {
get() {
${getterBody}
},`;
str += `
Object.defineProperty(${definedOn}, "${this.idl.name}", {
get() {
${getterBody}
},
`;
if (!this.idl.readonly) {
const conv = Types.generateTypeConversion(this.ctx, "V", this.idl.idlType, this.idl.extAttrs, this.interface.name, `"Failed to set the '${this.idl.name}' property on '${this.interface.name}': The provided value"`);
const conv = Types.generateTypeConversion(
this.ctx, "V", this.idl.idlType, this.idl.extAttrs, this.interface.name,
`"Failed to set the '${this.idl.name}' property on '${this.interface.name}': The provided value"`);
Object.assign(requires, conv.requires);
let conversion = conv.body.replace(/\n/g, "\n ");
str += `
set(V) {${conversion}
${setterBody}
},`;
set(V) {
${conv.body}
${setterBody}
},
`;
} else if (utils.getExtAttr(this.idl.extAttrs, "PutForwards")) {
str += `
set(V) {
this.${this.idl.name}.${utils.getExtAttr(this.idl.extAttrs, "PutForwards").rhs.value} = V;
},`;
set(V) {
this.${this.idl.name}.${utils.getExtAttr(this.idl.extAttrs, "PutForwards").rhs.value} = V;
},
`;
} else if (utils.getExtAttr(this.idl.extAttrs, "Replaceable")) {
str += `
set(V) {
Object.defineProperty(this, "${this.idl.name}", {
configurable: true,
enumerable: true,
value: V,
writable: true
});
},`;
set(V) {
Object.defineProperty(this, "${this.idl.name}", {
configurable: true,
enumerable: true,
value: V,
writable: true
});
},
`;
}
str += `
enumerable: true,
configurable: ${JSON.stringify(configurable)}
});\n\n`;
enumerable: true,
configurable: ${JSON.stringify(configurable)}
});
`;

if (this.idl.stringifier) {
const functionExpression = `
Expand Down
18 changes: 10 additions & 8 deletions lib/constructs/constant.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@ function Constant(ctx, obj, I, idl) {
}

Constant.prototype.generate = function () {
const body = `Object.defineProperty(${this.obj.name}, "${this.idl.name}", {
value: ${JSON.stringify(this.idl.value.value)},
enumerable: true
});
Object.defineProperty(${this.obj.name}.prototype, "${this.idl.name}", {
value: ${JSON.stringify(this.idl.value.value)},
enumerable: true
});\n\n`;
const body = `
Object.defineProperty(${this.obj.name}, "${this.idl.name}", {
value: ${JSON.stringify(this.idl.value.value)},
enumerable: true
});
Object.defineProperty(${this.obj.name}.prototype, "${this.idl.name}", {
value: ${JSON.stringify(this.idl.value.value)},
enumerable: true
});
`;
return {
requires: {},
body
Expand Down
110 changes: 65 additions & 45 deletions lib/constructs/dictionary.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ class Dictionary {
this.ctx = ctx;
this.idl = idl;
this.name = idl.name;

this.requires = {};
}

_generateConversions() {
_prepareFields() {
const fields = [];
const members = this.idl.members;
members.forEach(member => {
Expand All @@ -21,74 +23,92 @@ class Dictionary {
});

fields.sort((a, b) => a.name < b.name ? -1 : 1);
return fields;
}

this.str += `
let key, value;`;
fields.forEach(field => {
this.str += `\n
key = "${field.name}";
value = obj === undefined || obj === null ? undefined : obj[key];`;
_generateConversions() {
let str = "";

for (const field of this._prepareFields()) {
const typeConversion = field.idlType;
this.str += `
if (value !== undefined) {`;
const argAttrs = field.extAttrs;

const conv = Types.generateTypeConversion(this.ctx, "value", typeConversion, argAttrs, this.name, `\`\${context} has member ${field.name} that\``);
for (let key in conv.requires) {
this.str = `const ${key} = ${conv.requires[key]};\n` + this.str;
}
this.str += conv.body;
this.str += `
ret[key] = value;`
Object.assign(this.requires, conv.requires);

str += `
{
const key = "${field.name}";
let value = obj === undefined || obj === null ? undefined : obj[key];
if (value !== undefined) {
${conv.body}
ret[key] = value;
}
`;

if (field.required) {
this.str += `
} else {
throw new TypeError("${field.name} is required in '${this.name}'");`;
str += `
else {
throw new TypeError("${field.name} is required in '${this.name}'");
}
`;
} else if (field.default) {
this.str += `
} else {
ret[key] = `;
if (field.default.type === "null") {
this.str += `null;`;
} else {
this.str += JSON.stringify(field.default.value) + ';';
}
str += `
else {
ret[key] = ${utils.getDefault(field.default)};
}
`;
}
this.str += `
}`;
});

str += `
}
`;
}

return str;
}

generate() {
this.str += `
module.exports = {
convertInherit(obj, ret, { context = "The provided value" } = {}) {`;
module.exports = {
convertInherit(obj, ret, { context = "The provided value" } = {}) {
`;

if (this.idl.inheritance) {
this.str = `const ${this.idl.inheritance} = require("./${this.idl.inheritance}");\n` + this.str;
this.str += `
${this.idl.inheritance}.convertInherit(obj, ret, { context });`;
${this.idl.inheritance}.convertInherit(obj, ret, { context });
`;
}
this._generateConversions();

this.str += `
},
${this._generateConversions()}
},
convert(obj, { context = "The provided value" } = {}) {
if (obj !== undefined && typeof obj !== "object" && typeof obj !== "function") {
throw new TypeError(\`\${context} is not an object.\`);
}
const ret = Object.create(null);
module.exports.convertInherit(obj, ret, { context });
return ret;
}
};
`;

convert(obj, { context = "The provided value" } = {}) {
if (obj !== undefined && typeof obj !== "object" && typeof obj !== "function") {
throw new TypeError(\`\${context} is not an object.\`);
if (this.idl.inheritance) {
this.requires[this.idl.inheritance] = `require("./${this.idl.inheritance}")`;
}
this.str = `
${Object.keys(this.requires).map(key => `const ${key} = ${this.requires[key]};`).join("\n")}
const ret = Object.create(null);
module.exports.convertInherit(obj, ret, { context });
return ret;
}
};`;
${this.str}
`;

return this.str;
}

toString() {
this.str = ``;
this.str = "";
this.generate();
return this.str;
}
Expand Down
Loading

0 comments on commit 2c772f6

Please sign in to comment.