preface
In order to limit the popularity of small programs beyond auditing, wechat restricts the dynamic execution of code in ways such as eval/New Function. In fact, to be honest, it would have been understandable, but your review speed is so slow that iteration and bug fixing are extremely difficult. Especially on the eve of the Spring Festival this year, our small program is 5 days! But a large factory next door told us that their small program audit only took 3 hours, so it is not difficult to guess that our small entrepreneurial factories are always crazy to jump the queue.
Good, goose factory since you are not benevolent, then fuck I don’t blame my injustice. Can’t execute code dynamically without using eval/new Function? It doesn’t exist! This restriction is better than nothing, it’s just a piece of paper, so turn off Ajax if you can.
Start by writing a JavaScript interpreter in JavaScript
The first step in hotfix is to write a JavaScript interpreter in JavaScript. For many of you, writing a JavaScript interpreter may sound like a fantasy, but it’s actually quite simple because the semantics are almost completely reusable because JavaScript is used to implement the JavaScript interpreter.
Let me list the implementation steps:
- Parsing JavaScript code strings to get abstract syntax tree (AST) of JavaScript code. You don’t have to do this yourself. There are many excellent off-the-shelf libraries, such as Acornjs/Acorn. The results are parsed to standard ESTree.
- Because JavaScript syntax trees have standard format estree/ ESTREE, we only need to implement the evaluation of the syntax tree against this standard format, as long as the same semantics as JavaScript, the effect is similar to eval/new Function.
Details to pay attention to:
- Scope. For example, var is a function scope and const/let is a lexical scope.
- | | and && operator. These two operators have the effect of short-circuiting, so we cannot evaluate both sides first like other operators.
- Function closure. As mentioned above, implementing JavaScript interpreters in JavaScript allows for almost complete reuse of JavaScript semantics, which is pretty polished here. Interpreter function closures can then be implemented with the language’s own closures, making it very easy and enjoyable.
- Inject into the standard library. We didn’t make the interpreter for sandbox purposes, so we didn’t isolate the environment, but even so, we needed to inject the JavaScript standard library into it. The standard library can be found in the JavaScript standard library.
- The new operator. I studied this problem for a long time and finally found a solution that worked, as shown in the following sample code.
- Interrupt control flow operations. Operations such as break/return/continue that interrupt the flow of control need to be handled with care.
Example code: bramblex/ JSJS
The effect is as follows:
Then design the complete heat exchanger scheme
Page/Component is something I haven’t explored yet, and I’m not very familiar with applets. Let’s get straight to how to modify program code.
First, since we want to heat up, we must consider several questions:
- Where to update the code? There is no doubt that we need a server to update.
- Where does the updated code go? So far, the update in the small program inside the Storage is very good.
- When do you know your code needs to be updated? To solve this problem, we need to record the code version on the remote server and locally, and compare the version to determine if it needs to be updated.
- When does the code run? My recommendation is to treat the Hotmore code as a separate module that can be executed before the App is created
Next, solve the problem and design a specific heat recovery scheme:
- The code is updated from the server and there are two apis. /update/version returns a version number like v0.0.1, and /update/code returns a code string.
- A local Storage has two keys, version and code, to store the corresponding local code and version.
- When you open the applet, get a comparison between the local version and the remote version, do not care if the version is consistent, and update the local code if the version is inconsistent.
- Exports, or whatever you like, export exposed interfaces in a module.
- Then each page calls the module code of the hot part, embedded in the business code.
I won’t give you sample code for specific scenarios, because I don’t have… After all, you can write this code later if you need a project that needs a smaller program, because it’s already designed.
The last
There are a lot of improvements to be made to this solution, such as implementing IR intermediate codes for transfer and use, improving performance and memory footprint, etc. But that’s for another day. We’ll have time to make improvements.