One, foreword
Recently I looked at a number of low code development platforms and found that they all have the ability to edit code. So the question is, how does this code perform during app preview/live?
Simplifying, this code (which is just a string) shows how I can implement add or subtract while the app is running.
export function add ( a, b ) {
return a + b;
}
export function subtract ( a, b ) {
return a - b;
}
Copy the code
Second, early thinking
2.1 正则 + eval
The first idea is to extract all the method names and the entire content of that method with the re, and then execute it with eval or new Function.
The problem with this idea, however, is that there is no convenient way to extract the functions associated with this method. So I gave up.
function log () {
console.log('my log');
}
export function add ( a, b ) {
log()
return a + b;
}
Copy the code
2.2 the export + Babel
Then I found that these platforms all use the export method when defining functions, and there is no restriction on the use of ES6 syntax, so I thought to try Babel.
Using Babel online transcoding tool, the conversion effect is:
The whole idea becomes clear when you look at these two lines of code: we can mount all the export methods on the Exports object.
exports.add = add;
exports.subtract = subtract;
Copy the code
Third, the idea of implementation
3.1 introduced the Babel
Use @babel/standalone, which is used on a browser.
3.2 code
// Edit area code
const source = ` export function add ( a, b ) { return a + b; } `
// Exports object created
const exports = {};
// Use the Babel conversion
const output = Babel.transform(source, {
presets: ['env']
}).code;
/ / create the function
const fn = new Function('exports', output);
// Execute fn and pass in the exports object. Once executed, the add method is bound to the Exports object.
fn(exports);
// Call the add method on exports
const result = exports['add'] (1.2);
console.log(result);
Copy the code
3.3 Execution Process
source
Transcoding, namelyoutput
To:
"use strict";
Object.defineProperty(exports."__esModule", {
value: true
});
exports.add = add;
function add(a, b) {
return a + b;
}
Copy the code
const fn = new Function('exports', output);
This line of code is saying
function fn(exports) {
"use strict";
Object.defineProperty(exports."__esModule", {
value: true
});
exports.add = add;
function add(a, b) {
returna + b; }}Copy the code
-
Performing fn(exports) is the same as performing the above function, and add is assigned to exports.
-
Finally, you can execute exports.add.
Four, other
Perform context binding
You can use bind/apply/call when calling.
Get method list
Object.keys(exports)
Asynchronous methods
export async function add ( a, b ) {
return Promise.resolve(a + b);
}
Copy the code
The configuration of Babel needs to be adjusted for compatibility. I didn’t test this locally, just an idea.
Five, the afterword.
This is a basic implementation that needs to be tailored to the business. Of course, the security and performance problems existing in new Function also need to be considered in business.
Six, reference
- babel-standalone
- Function