Make AMD parser modules extensible

This commit is contained in:
chuckd 2018-03-05 07:51:12 -05:00
parent 6970103b79
commit 1b37115e4b
2 changed files with 430 additions and 408 deletions

View File

@ -40,26 +40,20 @@ class AMDDefineDependencyParserPlugin {
this.options = options; this.options = options;
} }
newDefineDependency( apply(parser) {
range, this.parser = parser;
arrayRange, parser.hooks.call.for("define").tap(
functionRange, "AMDDefineDependencyParserPlugin",
objectRange, this.processCallDefine.bind(
namedModule Object.create(this, {
) { parser: { value: parser }
return new AMDDefineDependency( })
range, )
arrayRange,
functionRange,
objectRange,
namedModule
); );
} }
apply(parser) { processArray(expr, param, identifiers, namedModule) {
const options = this.options; const parser = this.parser;
const processArray = (expr, param, identifiers, namedModule) => {
if (param.isArray()) { if (param.isArray()) {
param.items.forEach((param, idx) => { param.items.forEach((param, idx) => {
if ( if (
@ -67,9 +61,9 @@ class AMDDefineDependencyParserPlugin {
["require", "module", "exports"].includes(param.string) ["require", "module", "exports"].includes(param.string)
) )
identifiers[idx] = param.string; identifiers[idx] = param.string;
const result = processItem(expr, param, namedModule); const result = this.processItem(expr, param, namedModule);
if (result === undefined) { if (result === undefined) {
processContext(expr, param); this.processContext(expr, param);
} }
}); });
return true; return true;
@ -95,26 +89,27 @@ class AMDDefineDependencyParserPlugin {
dep.loc = expr.loc; dep.loc = expr.loc;
parser.state.current.addDependency(dep); parser.state.current.addDependency(dep);
} else { } else {
dep = new AMDRequireItemDependency(request); dep = this.newRequireItemDependency(request);
dep.loc = expr.loc; dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry; dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep); parser.state.current.addDependency(dep);
} }
deps.push(dep); deps.push(dep);
}); });
const dep = new AMDRequireArrayDependency(deps, param.range); const dep = this.newRequireArrayDependency(deps, param.range);
dep.loc = expr.loc; dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry; dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep); parser.state.current.addDependency(dep);
return true; return true;
} }
}; }
const processItem = (expr, param, namedModule) => { processItem(expr, param, namedModule) {
const parser = this.parser;
if (param.isConditional()) { if (param.isConditional()) {
param.options.forEach(param => { param.options.forEach(param => {
const result = processItem(expr, param); const result = this.processItem(expr, param);
if (result === undefined) { if (result === undefined) {
processContext(expr, param); this.processContext(expr, param);
} }
}); });
return true; return true;
@ -134,32 +129,31 @@ class AMDDefineDependencyParserPlugin {
// eslint-disable-line no-cond-assign // eslint-disable-line no-cond-assign
dep = new LocalModuleDependency(localModule, param.range); dep = new LocalModuleDependency(localModule, param.range);
} else { } else {
dep = new AMDRequireItemDependency(param.string, param.range); dep = this.newRequireItemDependency(param.string, param.range);
} }
dep.loc = expr.loc; dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry; dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep); parser.state.current.addDependency(dep);
return true; return true;
} }
}; }
const processContext = (expr, param) => { processContext(expr, param) {
const dep = ContextDependencyHelpers.create( const dep = ContextDependencyHelpers.create(
AMDRequireContextDependency, AMDRequireContextDependency,
param.range, param.range,
param, param,
expr, expr,
options this.options
); );
if (!dep) return; if (!dep) return;
dep.loc = expr.loc; dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry; dep.optional = !!this.parser.scope.inTry;
parser.state.current.addDependency(dep); this.parser.state.current.addDependency(dep);
return true; return true;
}; }
parser.hooks.call processCallDefine(expr) {
.for("define") const parser = this.parser;
.tap("AMDDefineDependencyParserPlugin", expr => {
let array, fn, obj, namedModule; let array, fn, obj, namedModule;
switch (expr.arguments.length) { switch (expr.arguments.length) {
case 1: case 1:
@ -239,7 +233,7 @@ class AMDDefineDependencyParserPlugin {
if (array) { if (array) {
identifiers = {}; identifiers = {};
const param = parser.evaluateExpression(array); const param = parser.evaluateExpression(array);
const result = processArray(expr, param, identifiers, namedModule); const result = this.processArray(expr, param, identifiers, namedModule);
if (!result) return; if (!result) return;
if (fnParams) if (fnParams)
fnParams = fnParams.slice(fnParamsOffset).filter((param, idx) => { fnParams = fnParams.slice(fnParamsOffset).filter((param, idx) => {
@ -305,7 +299,16 @@ class AMDDefineDependencyParserPlugin {
} }
parser.state.current.addDependency(dep); parser.state.current.addDependency(dep);
return true; return true;
}); }
newDefineDependency(...args) {
return new AMDDefineDependency(...args);
}
newRequireArrayDependency(...args) {
return new AMDRequireArrayDependency(...args);
}
newRequireItemDependency(...args) {
return new AMDRequireItemDependency(...args);
} }
} }
module.exports = AMDDefineDependencyParserPlugin; module.exports = AMDDefineDependencyParserPlugin;

View File

@ -46,36 +46,24 @@ class AMDRequireDependenciesBlockParserPlugin {
} }
apply(parser) { apply(parser) {
const options = this.options; this.parser = parser;
parser.hooks.call.for("require").tap(
const processArrayForRequestString = param => { "AMDRequireDependenciesBlockParserPlugin",
if (param.isArray()) { this.processCallRequire.bind(
const result = param.items.map(item => Object.create(this, {
processItemForRequestString(item) parser: { value: parser }
})
)
); );
if (result.every(Boolean)) return result.join(" ");
} else if (param.isConstArray()) {
return param.array.join(" ");
} }
};
const processItemForRequestString = param => { processArray(expr, param) {
if (param.isConditional()) { const parser = this.parser;
const result = param.options.map(item =>
processItemForRequestString(item)
);
if (result.every(Boolean)) return result.join("|");
} else if (param.isString()) {
return param.string;
}
};
const processArray = (expr, param) => {
if (param.isArray()) { if (param.isArray()) {
for (const p of param.items) { for (const p of param.items) {
const result = processItem(expr, p); const result = this.processItem(expr, p);
if (result === undefined) { if (result === undefined) {
processContext(expr, p); this.processContext(expr, p);
} }
} }
return true; return true;
@ -98,26 +86,27 @@ class AMDRequireDependenciesBlockParserPlugin {
dep.loc = expr.loc; dep.loc = expr.loc;
parser.state.current.addDependency(dep); parser.state.current.addDependency(dep);
} else { } else {
dep = new AMDRequireItemDependency(request); dep = this.newRequireItemDependency(request);
dep.loc = expr.loc; dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry; dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep); parser.state.current.addDependency(dep);
} }
deps.push(dep); deps.push(dep);
} }
const dep = new AMDRequireArrayDependency(deps, param.range); const dep = this.newRequireArrayDependency(deps, param.range);
dep.loc = expr.loc; dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry; dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep); parser.state.current.addDependency(dep);
return true; return true;
} }
}; }
const processItem = (expr, param) => { processItem(expr, param) {
const parser = this.parser;
if (param.isConditional()) { if (param.isConditional()) {
for (const p of param.options) { for (const p of param.options) {
const result = processItem(expr, p); const result = this.processItem(expr, p);
if (result === undefined) { if (result === undefined) {
processContext(expr, p); this.processContext(expr, p);
} }
} }
return true; return true;
@ -144,41 +133,62 @@ class AMDRequireDependenciesBlockParserPlugin {
// eslint-disable-line no-cond-assign // eslint-disable-line no-cond-assign
dep = new LocalModuleDependency(localModule, param.range); dep = new LocalModuleDependency(localModule, param.range);
} else { } else {
dep = new AMDRequireItemDependency(param.string, param.range); dep = this.newRequireItemDependency(param.string, param.range);
} }
dep.loc = expr.loc; dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry; dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep); parser.state.current.addDependency(dep);
return true; return true;
} }
}; }
const processContext = (expr, param) => { processContext(expr, param) {
const dep = ContextDependencyHelpers.create( const dep = ContextDependencyHelpers.create(
AMDRequireContextDependency, AMDRequireContextDependency,
param.range, param.range,
param, param,
expr, expr,
options this.options
); );
if (!dep) return; if (!dep) return;
dep.loc = expr.loc; dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry; dep.optional = !!this.parser.scope.inTry;
parser.state.current.addDependency(dep); this.parser.state.current.addDependency(dep);
return true; return true;
}
processCallRequire(expr) {
const processArrayForRequestString = param => {
if (param.isArray()) {
const result = param.items.map(item =>
processItemForRequestString(item)
);
if (result.every(Boolean)) return result.join(" ");
} else if (param.isConstArray()) {
return param.array.join(" ");
}
};
const processItemForRequestString = param => {
if (param.isConditional()) {
const result = param.options.map(item =>
processItemForRequestString(item)
);
if (result.every(Boolean)) return result.join("|");
} else if (param.isString()) {
return param.string;
}
}; };
parser.hooks.call
.for("require")
.tap("AMDRequireDependenciesBlockParserPlugin", expr => {
let param; let param;
let dep; let dep;
let result; let result;
const parser = this.parser;
const old = parser.state.current; const old = parser.state.current;
if (expr.arguments.length >= 1) { if (expr.arguments.length >= 1) {
param = parser.evaluateExpression(expr.arguments[0]); param = parser.evaluateExpression(expr.arguments[0]);
dep = new AMDRequireDependenciesBlock( dep = this.newRequireDependenciesBlock(
expr, expr,
param.range, param.range,
expr.arguments.length > 1 ? expr.arguments[1].range : null, expr.arguments.length > 1 ? expr.arguments[1].range : null,
@ -192,7 +202,7 @@ class AMDRequireDependenciesBlockParserPlugin {
if (expr.arguments.length === 1) { if (expr.arguments.length === 1) {
parser.inScope([], () => { parser.inScope([], () => {
result = processArray(expr, param); result = this.processArray(expr, param);
}); });
parser.state.current = old; parser.state.current = old;
if (!result) return; if (!result) return;
@ -203,7 +213,7 @@ class AMDRequireDependenciesBlockParserPlugin {
if (expr.arguments.length === 2 || expr.arguments.length === 3) { if (expr.arguments.length === 2 || expr.arguments.length === 3) {
try { try {
parser.inScope([], () => { parser.inScope([], () => {
result = processArray(expr, param); result = this.processArray(expr, param);
}); });
if (!result) { if (!result) {
dep = new UnsupportedDependency("unsupported", expr.range); dep = new UnsupportedDependency("unsupported", expr.range);
@ -235,7 +245,16 @@ class AMDRequireDependenciesBlockParserPlugin {
} }
return true; return true;
} }
}); }
newRequireDependenciesBlock(...args) {
return new AMDRequireDependenciesBlock(...args);
}
newRequireItemDependency(...args) {
return new AMDRequireItemDependency(...args);
}
newRequireArrayDependency(...args) {
return new AMDRequireArrayDependency(...args);
} }
} }
module.exports = AMDRequireDependenciesBlockParserPlugin; module.exports = AMDRequireDependenciesBlockParserPlugin;