Commit b20d1540 authored by Benjamin Franzke's avatar Benjamin Franzke
Browse files

[WIP][TASK] Support JavaScript invoke instruction on exported functions

Allow for empty invoke() JavaScriptModule instructions which
causes the module export to be invoked as plain function.
The method must not be called with the ES6 module passed
as this-value.

Resolves: #
Releases: main
Change-Id: I5e2f8c5b7c0f617f5ea7f1cf8ae1a6843187515f
parent fc95fe87
Pipeline #22353 passed with stages
in 9 minutes and 19 seconds
......@@ -118,7 +118,11 @@ function executeJavaScriptModuleInstruction(json: JavaScriptItemPayload) {
} else if (item.type === 'invoke') {
return (__esModule: any) => {
const subjectRef = resolveSubjectRef(__esModule);
subjectRef[item.method].apply(subjectRef, item.args);
if ('method' in item && item.method) {
subjectRef[item.method].apply(subjectRef, item.args);
} else {
subjectRef(...item.args);
}
};
} else if (item.type === 'instance') {
return (__esModule: any) => {
......
......@@ -133,11 +133,11 @@ class JavaScriptModuleInstruction implements \JsonSerializable
}
/**
* @param string $method method of JavaScript module to be invoked
* @param string|null $method method of JavaScript module to be invoked
* @param mixed ...$args corresponding method arguments
* @return static
*/
public function invoke(string $method, ...$args): self
public function invoke(?string $method = null, ...$args): self
{
$this->items[] = [
'type' => static::ITEM_INVOKE,
......
......@@ -10,4 +10,4 @@
*
* The TYPO3 project - inspiring people to share!
*/
const FLAG_USE_REQUIRE_JS=1,FLAG_USE_IMPORTMAP=2,FLAG_USE_TOP_WINDOW=16,deniedProperties=["__proto__","prototype","constructor"],allowedJavaScriptItemTypes=["assign","invoke","instance"];let useShim=!1;const moduleImporter=e=>useShim?window.importShim(e):import(e).catch(()=>(useShim=!0,moduleImporter(e)));function loadModule(e){if(!e.name)throw new Error("JavaScript module name is required");if(2==(2&e.flags)){if(16&e.flags)throw new Error("FLAG_USE_TOP_WINDOW is not yet supported for JavaScript modules");return moduleImporter(e.name)}if(1==(1&e.flags))return new Promise((t,o)=>{(16==(16&e.flags)?top.window:window).require([e.name],e=>t(e),e=>o(e))});throw new Error("Unknown JavaScript module type")}function executeJavaScriptModuleInstruction(e){if(!e.name)throw new Error("JavaScript module name is required");if(!e.items)return void loadModule(e);const t=e.exportName,o=o=>"string"==typeof t?o[t]:1==(1&e.flags)?o:o.default,r=e.items.filter(e=>allowedJavaScriptItemTypes.includes(e.type)).map(e=>"assign"===e.type?t=>{mergeRecursive(o(t),e.assignments)}:"invoke"===e.type?t=>{const r=o(t);r[e.method].apply(r,e.args)}:"instance"===e.type?t=>{const r=[null].concat(e.args),n=o(t);new(n.bind.apply(n,r))}:e=>{});loadModule(e).then(e=>r.forEach(t=>t.call(null,e)))}function isObjectInstance(e){return e instanceof Object&&!(e instanceof Array)}function mergeRecursive(e,t){Object.keys(t).forEach(o=>{if(-1!==deniedProperties.indexOf(o))throw new Error("Property "+o+" is not allowed");isObjectInstance(t[o])&&void 0!==e[o]?mergeRecursive(e[o],t[o]):Object.assign(e,{[o]:t[o]})})}export class JavaScriptItemProcessor{constructor(){this.invokableNames=["globalAssignment","javaScriptModuleInstruction"]}processItems(e){e.forEach(e=>this.invoke(e.type,e.payload))}invoke(e,t){if(!this.invokableNames.includes(e)||"function"!=typeof this[e])throw new Error('Unknown handler name "'+e+'"');this[e].call(this,t)}globalAssignment(e){mergeRecursive(window,e)}javaScriptModuleInstruction(e){executeJavaScriptModuleInstruction(e)}}
\ No newline at end of file
const FLAG_USE_REQUIRE_JS=1,FLAG_USE_IMPORTMAP=2,FLAG_USE_TOP_WINDOW=16,deniedProperties=["__proto__","prototype","constructor"],allowedJavaScriptItemTypes=["assign","invoke","instance"];let useShim=!1;const moduleImporter=e=>useShim?window.importShim(e):import(e).catch(()=>(useShim=!0,moduleImporter(e)));function loadModule(e){if(!e.name)throw new Error("JavaScript module name is required");if(2==(2&e.flags)){if(16&e.flags)throw new Error("FLAG_USE_TOP_WINDOW is not yet supported for JavaScript modules");return moduleImporter(e.name)}if(1==(1&e.flags))return new Promise((t,o)=>{(16==(16&e.flags)?top.window:window).require([e.name],e=>t(e),e=>o(e))});throw new Error("Unknown JavaScript module type")}function executeJavaScriptModuleInstruction(e){if(!e.name)throw new Error("JavaScript module name is required");if(!e.items)return void loadModule(e);const t=e.exportName,o=o=>"string"==typeof t?o[t]:1==(1&e.flags)?o:o.default,r=e.items.filter(e=>allowedJavaScriptItemTypes.includes(e.type)).map(e=>"assign"===e.type?t=>{mergeRecursive(o(t),e.assignments)}:"invoke"===e.type?t=>{const r=o(t);"method"in e&&e.method?r[e.method].apply(r,e.args):r(...e.args)}:"instance"===e.type?t=>{const r=[null].concat(e.args),n=o(t);new(n.bind.apply(n,r))}:e=>{});loadModule(e).then(e=>r.forEach(t=>t.call(null,e)))}function isObjectInstance(e){return e instanceof Object&&!(e instanceof Array)}function mergeRecursive(e,t){Object.keys(t).forEach(o=>{if(-1!==deniedProperties.indexOf(o))throw new Error("Property "+o+" is not allowed");isObjectInstance(t[o])&&void 0!==e[o]?mergeRecursive(e[o],t[o]):Object.assign(e,{[o]:t[o]})})}export class JavaScriptItemProcessor{constructor(){this.invokableNames=["globalAssignment","javaScriptModuleInstruction"]}processItems(e){e.forEach(e=>this.invoke(e.type,e.payload))}invoke(e,t){if(!this.invokableNames.includes(e)||"function"!=typeof this[e])throw new Error('Unknown handler name "'+e+'"');this[e].call(this,t)}globalAssignment(e){mergeRecursive(window,e)}javaScriptModuleInstruction(e){executeJavaScriptModuleInstruction(e)}}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment