This commit is contained in:
Ilya Kantor 2019-08-04 17:36:26 +03:00
parent f96872425d
commit 6d1fa5de73
8 changed files with 84 additions and 79 deletions

View file

@ -224,6 +224,6 @@ MyClass.property = ...
MyClass.method = ... MyClass.method = ...
``` ```
Static properties are inherited. Static properties and methods are inherited.
For `class B extends A` the prototype of the class `B` itself points to `A`: `B.[[Prototype]] = A`. So if a field is not found in `B`, the search continues in `A`. For `class B extends A` the prototype of the class `B` itself points to `A`: `B.[[Prototype]] = A`. So if a field is not found in `B`, the search continues in `A`.

View file

@ -53,7 +53,7 @@ In JavaScript, there are two types of object fields (properties and methods):
- Public: accessible from anywhere. They comprise the external interface. Till now we were only using public properties and methods. - Public: accessible from anywhere. They comprise the external interface. Till now we were only using public properties and methods.
- Private: accessible only from inside the class. These are for the internal interface. - Private: accessible only from inside the class. These are for the internal interface.
In many other languages there also exist "protected" fields: accessible only from inside the class and those extending it. They are also useful for the internal interface. They are in a sense more widespread than private ones, because we usually want inheriting classes to gain access to them. In many other languages there also exist "protected" fields: accessible only from inside the class and those extending it (like private, but plus access from inheriting classes). They are also useful for the internal interface. They are in a sense more widespread than private ones, because we usually want inheriting classes to gain access to them.
Protected fields are not implemented in JavaScript on the language level, but in practice they are very convenient, so they are emulated. Protected fields are not implemented in JavaScript on the language level, but in practice they are very convenient, so they are emulated.
@ -297,7 +297,7 @@ Supportable
**If we strictly delimit the internal interface, then the developer of the class can freely change its internal properties and methods, even without informing the users.** **If we strictly delimit the internal interface, then the developer of the class can freely change its internal properties and methods, even without informing the users.**
If you're a developer of such class, it's great to know that private methods can be safely renamed, their parameters can be changed, and even removed, because no external code depends on them. If you're a developer of such class, it's great to know that private methods can be safely renamed, their parameters can be changed, and even removed, because no external code depends on them.
For users, when a new version comes out, it may be a total overhaul internally, but still simple to upgrade if the external interface is the same. For users, when a new version comes out, it may be a total overhaul internally, but still simple to upgrade if the external interface is the same.

View file

@ -21,14 +21,14 @@ alert(filteredArr); // 10, 50
alert(filteredArr.isEmpty()); // false alert(filteredArr.isEmpty()); // false
``` ```
Please note a very interesting thing. Built-in methods like `filter`, `map` and others -- return new objects of exactly the inherited type. They rely on the `constructor` property to do so. Please note a very interesting thing. Built-in methods like `filter`, `map` and others -- return new objects of exactly the inherited type `PowerArray`. Their internal implementation uses object `constructor` property for that.
In the example above, In the example above,
```js ```js
arr.constructor === PowerArray arr.constructor === PowerArray
``` ```
So when `arr.filter()` is called, it internally creates the new array of results using exactly `new PowerArray`, not basic `Array`. That's actually very cool, because we can keep using `PowerArray` methods further on the result. When `arr.filter()` is called, it internally creates the new array of results using exactly `arr.constructor`, not basic `Array`. That's actually very cool, because we can keep using `PowerArray` methods further on the result.
Even more, we can customize that behavior. Even more, we can customize that behavior.
@ -64,6 +64,10 @@ alert(filteredArr.isEmpty()); // Error: filteredArr.isEmpty is not a function
As you can see, now `.filter` returns `Array`. So the extended functionality is not passed any further. As you can see, now `.filter` returns `Array`. So the extended functionality is not passed any further.
```smart header="Other collections work similarly"
Other collections, such as `Map` and `Set`, work alike. They also use `Symbol.species`.
```
## No static inheritance in built-ins ## No static inheritance in built-ins
Built-in objects have their own static methods, for instance `Object.keys`, `Array.isArray` etc. Built-in objects have their own static methods, for instance `Object.keys`, `Array.isArray` etc.
@ -81,3 +85,5 @@ Here's the picture structure for `Date` and `Object`:
![](object-date-inheritance.svg) ![](object-date-inheritance.svg)
As you can see, there's no link between `Date` and `Object`. They are independent, only `Date.prototype` inherits from `Object.prototype`. As you can see, there's no link between `Date` and `Object`. They are independent, only `Date.prototype` inherits from `Object.prototype`.
That's an important difference of inheritance between built-in objects compared to what we get with `extends`.

View file

@ -11,7 +11,7 @@ The syntax is:
obj instanceof Class obj instanceof Class
``` ```
It returns `true` if `obj` belongs to the `Class` (or a class inheriting from it). It returns `true` if `obj` belongs to the `Class` or a class inheriting from it.
For instance: For instance:
@ -46,15 +46,17 @@ alert( arr instanceof Object ); // true
Please note that `arr` also belongs to the `Object` class. That's because `Array` prototypally inherits from `Object`. Please note that `arr` also belongs to the `Object` class. That's because `Array` prototypally inherits from `Object`.
The `instanceof` operator examines the prototype chain for the check, but we can set a custom logic in the static method `Symbol.hasInstance`. Normally, `instanceof` operator examines the prototype chain for the check. We can also set a custom logic in the static method `Symbol.hasInstance`.
The algorithm of `obj instanceof Class` works roughly as follows: The algorithm of `obj instanceof Class` works roughly as follows:
1. If there's a static method `Symbol.hasInstance`, then just call it: `Class[Symbol.hasInstance](obj)`. It should return either `true` or `false`. We're done. 1. If there's a static method `Symbol.hasInstance`, then just call it: `Class[Symbol.hasInstance](obj)`. It should return either `true` or `false`, and we're done. That's how we can customize the behavior of `instanceof`.
For example:
For example:
```js run ```js run
// setup instanceOf check that assumes that anything that canEat is an animal // setup instanceOf check that assumes that
// anything with canEat property is an animal
class Animal { class Animal {
static [Symbol.hasInstance](obj) { static [Symbol.hasInstance](obj) {
if (obj.canEat) return true; if (obj.canEat) return true;
@ -68,17 +70,19 @@ The algorithm of `obj instanceof Class` works roughly as follows:
2. Most classes do not have `Symbol.hasInstance`. In that case, the standard logic is used: `obj instanceOf Class` checks whether `Class.prototype` equals to one of prototypes in the `obj` prototype chain. 2. Most classes do not have `Symbol.hasInstance`. In that case, the standard logic is used: `obj instanceOf Class` checks whether `Class.prototype` equals to one of prototypes in the `obj` prototype chain.
In other words, compare: In other words, compare one after another:
```js ```js
obj.__proto__ === Class.prototype obj.__proto__ === Class.prototype?
obj.__proto__.__proto__ === Class.prototype obj.__proto__.__proto__ === Class.prototype?
obj.__proto__.__proto__.__proto__ === Class.prototype obj.__proto__.__proto__.__proto__ === Class.prototype?
... ...
// if any answer is true, return true
// otherwise, if we reached the end of the chain, return false
``` ```
In the example above `Rabbit.prototype === rabbit.__proto__`, so that gives the answer immediately. In the example above `rabbit.__proto__ === Rabbit.prototype`, so that gives the answer immediately.
In the case of an inheritance, `rabbit` is an instance of the parent class as well: In the case of an inheritance, the match will be at the second step:
```js run ```js run
class Animal {} class Animal {}
@ -88,8 +92,11 @@ The algorithm of `obj instanceof Class` works roughly as follows:
*!* *!*
alert(rabbit instanceof Animal); // true alert(rabbit instanceof Animal); // true
*/!* */!*
// rabbit.__proto__ === Rabbit.prototype // rabbit.__proto__ === Rabbit.prototype
*!*
// rabbit.__proto__.__proto__ === Animal.prototype (match!) // rabbit.__proto__.__proto__ === Animal.prototype (match!)
*/!*
``` ```
Here's the illustration of what `rabbit instanceof Animal` compares with `Animal.prototype`: Here's the illustration of what `rabbit instanceof Animal` compares with `Animal.prototype`:
@ -100,7 +107,7 @@ By the way, there's also a method [objA.isPrototypeOf(objB)](mdn:js/object/isPro
That's funny, but the `Class` constructor itself does not participate in the check! Only the chain of prototypes and `Class.prototype` matters. That's funny, but the `Class` constructor itself does not participate in the check! Only the chain of prototypes and `Class.prototype` matters.
That can lead to interesting consequences when `prototype` is changed. That can lead to interesting consequences when `prototype` property is changed after the object is created.
Like here: Like here:
@ -117,8 +124,6 @@ alert( rabbit instanceof Rabbit ); // false
*/!* */!*
``` ```
That's one of the reasons to avoid changing `prototype`. Just to keep safe.
## Bonus: Object.prototype.toString for the type ## Bonus: Object.prototype.toString for the type
We already know that plain objects are converted to string as `[object Object]`: We already know that plain objects are converted to string as `[object Object]`:
@ -152,7 +157,7 @@ let objectToString = Object.prototype.toString;
// what type is this? // what type is this?
let arr = []; let arr = [];
alert( objectToString.call(arr) ); // [object Array] alert( objectToString.call(arr) ); // [object *!*Array*/!*]
``` ```
Here we used [call](mdn:js/function/call) as described in the chapter [](info:call-apply-decorators) to execute the function `objectToString` in the context `this=arr`. Here we used [call](mdn:js/function/call) as described in the chapter [](info:call-apply-decorators) to execute the function `objectToString` in the context `this=arr`.
@ -196,11 +201,11 @@ As you can see, the result is exactly `Symbol.toStringTag` (if exists), wrapped
At the end we have "typeof on steroids" that not only works for primitive data types, but also for built-in objects and even can be customized. At the end we have "typeof on steroids" that not only works for primitive data types, but also for built-in objects and even can be customized.
It can be used instead of `instanceof` for built-in objects when we want to get the type as a string rather than just to check. We can use `{}.toString.call` instead of `instanceof` for built-in objects when we want to get the type as a string rather than just to check.
## Summary ## Summary
Let's recap the type-checking methods that we know: Let's summarize the type-checking methods that we know:
| | works for | returns | | | works for | returns |
|---------------|-------------|---------------| |---------------|-------------|---------------|

View file

@ -2,9 +2,9 @@
In JavaScript we can only inherit from a single object. There can be only one `[[Prototype]]` for an object. And a class may extend only one other class. In JavaScript we can only inherit from a single object. There can be only one `[[Prototype]]` for an object. And a class may extend only one other class.
But sometimes that feels limiting. For instance, I have a class `StreetSweeper` and a class `Bicycle`, and want to make a `StreetSweepingBicycle`. But sometimes that feels limiting. For instance, I have a class `StreetSweeper` and a class `Bicycle`, and want to make their mix: a `StreetSweepingBicycle`.
Or, talking about programming, we have a class `User` and a class `EventEmitter` that implements event generation, and we'd like to add the functionality of `EventEmitter` to `User`, so that our users can emit events. Or we have a class `User` and a class `EventEmitter` that implements event generation, and we'd like to add the functionality of `EventEmitter` to `User`, so that our users can emit events.
There's a concept that can help here, called "mixins". There's a concept that can help here, called "mixins".
@ -14,7 +14,7 @@ In other words, a *mixin* provides methods that implement a certain behavior, bu
## A mixin example ## A mixin example
The simplest way to make a mixin in JavaScript is to make an object with useful methods, so that we can easily merge them into a prototype of any class. The simplest way to implement a mixin in JavaScript is to make an object with useful methods, so that we can easily merge them into a prototype of any class.
For instance here the mixin `sayHiMixin` is used to add some "speech" for `User`: For instance here the mixin `sayHiMixin` is used to add some "speech" for `User`:
@ -75,10 +75,10 @@ let sayHiMixin = {
*!* *!*
// call parent method // call parent method
*/!* */!*
super.say(`Hello ${this.name}`); super.say(`Hello ${this.name}`); // (*)
}, },
sayBye() { sayBye() {
super.say(`Bye ${this.name}`); super.say(`Bye ${this.name}`); // (*)
} }
}; };
@ -95,11 +95,13 @@ Object.assign(User.prototype, sayHiMixin);
new User("Dude").sayHi(); // Hello Dude! new User("Dude").sayHi(); // Hello Dude!
``` ```
Please note that the call to the parent method `super.say()` from `sayHiMixin` looks for the method in the prototype of that mixin, not the class. Please note that the call to the parent method `super.say()` from `sayHiMixin` (at lines labelled with `(*)`) looks for the method in the prototype of that mixin, not the class.
Here's the diagram (see the right part):
![](mixin-inheritance.svg) ![](mixin-inheritance.svg)
That's because methods `sayHi` and `sayBye` were initially created in `sayHiMixin`. So their `[[HomeObject]]` internal property references `sayHiMixin`, as shown on the picture above. That's because methods `sayHi` and `sayBye` were initially created in `sayHiMixin`. So even though they got copied, their `[[HomeObject]]` internal property references `sayHiMixin`, as shown on the picture above.
As `super` looks for parent methods in `[[HomeObject]].[[Prototype]]`, that means it searches `sayHiMixin.[[Prototype]]`, not `User.[[Prototype]]`. As `super` looks for parent methods in `[[HomeObject]].[[Prototype]]`, that means it searches `sayHiMixin.[[Prototype]]`, not `User.[[Prototype]]`.
@ -199,7 +201,7 @@ And `eventMixin` mixin makes it easy to add such behavior to as many classes as
*Mixin* -- is a generic object-oriented programming term: a class that contains methods for other classes. *Mixin* -- is a generic object-oriented programming term: a class that contains methods for other classes.
Some other languages like e.g. Python allow to create mixins using multiple inheritance. JavaScript does not support multiple inheritance, but mixins can be implemented by copying methods into prototype. Some other languages like allow multiple inheritance. JavaScript does not support multiple inheritance, but mixins can be implemented by copying methods into prototype.
We can use mixins as a way to augment a class by multiple behaviors, like event-handling as we have seen above. We can use mixins as a way to augment a class by multiple behaviors, like event-handling as we have seen above.

View file

@ -11,13 +11,15 @@ In this chapter we first cover theoretical details about how things work, and th
The concept of *event loop* is very simple. There's an endless loop, when JavaScript engine waits for tasks, executes them and then sleeps waiting for more tasks. The concept of *event loop* is very simple. There's an endless loop, when JavaScript engine waits for tasks, executes them and then sleeps waiting for more tasks.
The general algorithm of the engine:
1. While there are tasks: 1. While there are tasks:
- execute the oldest task. - execute them, starting with the oldest task.
2. Sleep until a task appears, then go to 1. 2. Sleep until a task appears, then go to 1.
That's a formalized algorithm for what we see when browsing a page. JavaScript engine does nothing most of the time, only runs if a script/handler/event activates. That's a formalization for what we see when browsing a page. JavaScript engine does nothing most of the time, only runs if a script/handler/event activates.
A task can be JS-code triggered by events, but can also be something else, e.g.: Examples of tasks:
- When an external script `<script src="...">` loads, the task is to execute it. - When an external script `<script src="...">` loads, the task is to execute it.
- When a user moves their mouse, the task is to dispatch `mousemove` event and execute handlers. - When a user moves their mouse, the task is to dispatch `mousemove` event and execute handlers.
@ -34,27 +36,25 @@ The tasks form a queue, so-called "macrotask queue" (v8 term):
For instance, while the engine is busy executing a `script`, a user may move their mouse causing `mousemove`, and `setTimeout` may be due and so on, these tasks form a queue, as illustrated on the picture above. For instance, while the engine is busy executing a `script`, a user may move their mouse causing `mousemove`, and `setTimeout` may be due and so on, these tasks form a queue, as illustrated on the picture above.
Tasks from the queue are processed on "first come first served" basis. When the engine browser finishes with `fetch`, it handles `mousemove` event, then `setTimeout` handler, and so on. Tasks from the queue are processed on "first come first served" basis. When the engine browser is done with the `script`, it handles `mousemove` event, then `setTimeout` handler, and so on.
So far, quite simple, right? So far, quite simple, right?
Two more details: Two more details:
1. Rendering never happens while the engine executes a task. 1. Rendering never happens while the engine executes a task. Doesn't matter if the task takes a long time. Changes to DOM are painted only after the task is complete.
2. If a task takes too long, the browser can't do other tasks, process user events, so after a time it raises an alert like "Page Unresponsive" and suggesting to kill the task with the whole page. That happens when there are a lot of complex calculations or a programming error leading to infinite loop.
Doesn't matter if the task takes a long time. Changes to DOM are painted only after the task is complete. That was a theory. Now let's see how we can apply that knowledge.
2. If a task takes too long, the browser can't do other tasks, process user events, so after a time it raises an alert like "Page Unresponsive" and suggesting to kill the task with the whole page.
Now let's see how we can apply that knowledge. ## Use-case 1: splitting CPU-hungry tasks
## Use-case: splitting CPU-hungry tasks
Let's say we have a CPU-hungry task. Let's say we have a CPU-hungry task.
For example, syntax-highlighting (used to colorize code examples on this page) is quite CPU-heavy. To highlight the code, it performs the analysis, creates many colored elements, adds them to the document -- for a big text that takes a lot of time. For example, syntax-highlighting (used to colorize code examples on this page) is quite CPU-heavy. To highlight the code, it performs the analysis, creates many colored elements, adds them to the document -- for a big text that takes a lot of time.
While the engine is busy with syntax highlighting, it can't do other DOM-related stuff, process user events, etc. It may even cause the browser to "hang", which is unacceptable. While the engine is busy with syntax highlighting, it can't do other DOM-related stuff, process user events, etc. It may even cause the browser to "hang" for a bit, which is unacceptable.
So we can split the long text into pieces. Highlight first 100 lines, then schedule another 100 lines using zero-delay `setTimeout`, and so on. We can evade problems by splitting the big task into pieces. Highlight first 100 lines, then schedule `setTimeout` (with zero-delay) another 100 lines, and so on.
To demonstrate the approach, for the sake of simplicity, instead of syntax-highlighting let's take a function that counts from `1` to `1000000000`. To demonstrate the approach, for the sake of simplicity, instead of syntax-highlighting let's take a function that counts from `1` to `1000000000`.
@ -78,7 +78,7 @@ function count() {
count(); count();
``` ```
The browser may even show "the script takes too long" warning (but hopefully it won't, because the number is not very big). The browser may even show "the script takes too long" warning.
Let's split the job using nested `setTimeout`: Let's split the job using nested `setTimeout`:
@ -154,7 +154,9 @@ Why?
That's simple: as you remember, there's the in-browser minimal delay of 4ms for many nested `setTimeout` calls. Even if we set `0`, it's `4ms` (or a bit more). So the earlier we schedule it - the faster it runs. That's simple: as you remember, there's the in-browser minimal delay of 4ms for many nested `setTimeout` calls. Even if we set `0`, it's `4ms` (or a bit more). So the earlier we schedule it - the faster it runs.
## Use case: progress indication Finally, we've split a CPU-hungry task into parts - now it doesn't block the user interface. And its overall execution time isn't much longer.
## Use case 2: progress indication
Another benefit of splitting heavy tasks for browser scripts is that we can show progress indication. Another benefit of splitting heavy tasks for browser scripts is that we can show progress indication.
@ -214,11 +216,11 @@ This looks prettier:
Now the `<div>` shows increasing values of `i`, a kind of a progress bar. Now the `<div>` shows increasing values of `i`, a kind of a progress bar.
## Use case: doing something after the event ## Use case 3: doing something after the event
In an event handler we may decide to postpone some actions until the event bubbled up and was handled on all levels. We can do that by wrapping the code in zero delay `setTimeout`. In an event handler we may decide to postpone some actions until the event bubbled up and was handled on all levels. We can do that by wrapping the code in zero delay `setTimeout`.
In the chapter <info:dispatch-events> we saw an example: a custom event `menu-open` is dispatched after the "click" event is fully handled. In the chapter <info:dispatch-events> we saw an example: custom event `menu-open` is dispatched in `setTimeout`, so that it happens after the "click" event is fully handled.
```js ```js
menu.onclick = function() { menu.onclick = function() {
@ -227,7 +229,6 @@ menu.onclick = function() {
// create a custom event with the clicked menu item data // create a custom event with the clicked menu item data
let customEvent = new CustomEvent("menu-open", { let customEvent = new CustomEvent("menu-open", {
bubbles: true bubbles: true
/* details: can add more details, e.g. clicked item data here */
}); });
// dispatch the custom event asynchronously // dispatch the custom event asynchronously
@ -235,20 +236,15 @@ menu.onclick = function() {
}; };
``` ```
The custom event is totally independent here. It's dispatched asynchronously, after the `click` event bubbled up and was fully handled. That helps to workaround some potential bugs, that may happen when different events are nested in each other. ## Macrotasks and Microtasks
## Microtasks
Along with *macrotasks*, described in this chapter, there exist *microtasks*, mentioned in the chapter <info:microtask-queue>. Along with *macrotasks*, described in this chapter, there exist *microtasks*, mentioned in the chapter <info:microtask-queue>.
There are two main ways to create a microtask: Microtasks come solely from our code. They are usually created by promises: an execution of `.then/catch/finally` handler becomes a microtask. Microtasks are used "under the cover" of `await` as well, as it's another form of promise handling.
1. When a promise is ready, the execution of its `.then/catch/finally` handler becomes a microtask. Microtasks are used "under the cover" of `await` as well, as it's a form of promise handling, similar to `.then`, but syntactically different. There's also a special function `queueMicrotask(func)` that queues `func` for execution in the microtask queue.
2. There's a special function `queueMicrotask(func)` that queues `func` for execution in the microtask queue.
After every *macrotask*, the engine executes all tasks from *microtask* queue, prior to running any other macrotasks. **Immediately after every *macrotask*, the engine executes all tasks from *microtask* queue, prior to running any other macrotasks or rendering or anything else.**
**Microtask queue has a higher priority than the macrotask queue.**
For instance, take a look: For instance, take a look:
@ -261,21 +257,23 @@ Promise.resolve()
alert("code"); alert("code");
``` ```
What's the order? What's going to be the order here?
1. `code` shows first, because it's a regular synchronous call. 1. `code` shows first, because it's a regular synchronous call.
2. `promise` shows second, because `.then` passes through the microtask queue, and runs after the current code. 2. `promise` shows second, because `.then` passes through the microtask queue, and runs after the current code.
3. `timeout` shows last, because it's a macrotask. 3. `timeout` shows last, because it's a macrotask.
**There may be no UI event between microtasks.** The richer event loop picture looks like this:
Most of browser processing is macrotasks, including processing network request results, handling UI events and so on. ![](eventLoop-full.svg)
So if we'd like our code to execute asynchronously, but want the application state be basically the same (no mouse coordinate changes, no new network data, etc), then we can achieve that by creating a microtask with `queueMicrotask`. **All microtasks are completed before any other event handling or rendering or any other macrotask takes place.**
Rendering also waits until the microtask queue is emptied. That's important, as it guarantees that the application environment be basically the same (no mouse coordinate changes, no new network data, etc) between microtasks.
Here's an example with a "counting progress bar", similar to the one shown previously, but `queueMicrotask` is used instead of `setTimeout`. You can see that it renders at the very end, just like the regular code: If we'd like to execute a function asynchronously (after the current code), but before changes are rendered or new events, we can schedule it with `queueMicrotask`.
Here's an example with "counting progress bar", similar to the one shown previously, but `queueMicrotask` is used instead of `setTimeout`. You can see that it renders at the very end. Just like the synchronous code:
```html run ```html run
<div id="progress"></div> <div id="progress"></div>
@ -303,14 +301,8 @@ Here's an example with a "counting progress bar", similar to the one shown previ
</script> </script>
``` ```
So, microtasks are asynchronous from the point of code execution, but they don't allow any browser processes or events to stick in-between them.
## Summary ## Summary
The richer event loop picture may look like this:
![](eventLoop-full.svg)
The more detailed algorithm of the event loop (though still simplified compare to the [specification](https://html.spec.whatwg.org/multipage/webappapis.html#event-loop-processing-model)): The more detailed algorithm of the event loop (though still simplified compare to the [specification](https://html.spec.whatwg.org/multipage/webappapis.html#event-loop-processing-model)):
1. Dequeue and run the oldest task from the *macrotask* queue (e.g. "script"). 1. Dequeue and run the oldest task from the *macrotask* queue (e.g. "script").
@ -318,23 +310,23 @@ The more detailed algorithm of the event loop (though still simplified compare t
- While the microtask queue is not empty: - While the microtask queue is not empty:
- Dequeue and run the oldest microtask. - Dequeue and run the oldest microtask.
3. Render changes if any. 3. Render changes if any.
4. Wait until the macrotask queue is not empty (if needed). 4. If the macrotask queue is empty, wait till a macrotask appears.
5. Go to step 1. 5. Go to step 1.
To schedule a new macrotask: To schedule a new *macrotask*:
- Use zero delayed `setTimeout(f)`. - Use zero delayed `setTimeout(f)`.
That may be used to split a big calculation-heavy task into pieces, for the browser to be able to react on user events and show progress between them. That may be used to split a big calculation-heavy task into pieces, for the browser to be able to react on user events and show progress between them.
Also, used in event handlers to schedule an action after the event is fully handled (bubbling done). Also, used in event handlers to schedule an action after the event is fully handled (bubbling done).
To schedule a new microtask: To schedule a new *microtask*
- Use `queueMicrotask(f)`. - Use `queueMicrotask(f)`.
- Also promise handlers go through the microtask queue. - Also promise handlers go through the microtask queue.
There's no UI or network event handling between microtasks: they run immediately one after another. There's no UI or network event handling between microtasks: they run immediately one after another.
So one may want to `queueMicrotask` to execute a function asynchronously, but also with the same application state. So one may want to `queueMicrotask` to execute a function asynchronously, but within the environment state.
```smart header="Web Workers" ```smart header="Web Workers"
For long heavy calculations that shouldn't block the event loop, we can use [Web Workers](https://html.spec.whatwg.org/multipage/workers.html). For long heavy calculations that shouldn't block the event loop, we can use [Web Workers](https://html.spec.whatwg.org/multipage/workers.html).

View file

@ -24,7 +24,7 @@
<tspan x="45.1621094" y="189">event</tspan> <tspan x="45.1621094" y="189">event</tspan>
<tspan x="51.1152344" y="222">loop</tspan> <tspan x="51.1152344" y="222">loop</tspan>
</text> </text>
<g id="Group-Copy" transform="translate(255.000000, 267.000000)" fill="#EE6B47"> <g id="Group-Copy" transform="translate(256.000000, 267.000000)" fill="#EE6B47">
<path d="M23.1454405,0.978488667 C21.7366033,0.348781349 20.1862777,-0.000633284678 18.5591614,8.61663483e-07 C15.9694405,-0.000633284678 13.5756265,0.885269154 11.6377196,2.37931793 L10.4743707,0.618927691 C10.4060451,0.515561837 10.2863242,0.466732569 10.1690219,0.494000862 C10.0523242,0.521269154 9.96404514,0.618927691 9.94288235,0.742586228 L8.7970684,7.77907403 C8.78195212,7.87229354 8.80734747,7.96678135 8.86781259,8.03717159 C8.92404514,8.10312281 9.0038591,8.13926915 9.08669631,8.13926915 C9.09274282,8.13926915 9.09939398,8.13863501 9.10544049,8.13863501 L12.2169754,7.93253745 L15.7209289,7.70043989 C15.8382312,7.69219598 15.9398126,7.61229354 15.9791149,7.49561062 C16.0184172,7.37892769 15.9887893,7.24956184 15.9011149,7.16648867 L14.4408824,5.75107403 C15.6217661,4.92922037 17.0354405,4.45043989 18.5591614,4.44980574 C19.6281847,4.44980574 20.6421847,4.68761062 21.5618591,5.11185452 C21.6344172,5.14546428 21.7178591,5.14609842 21.7916265,5.11502525 C21.8647893,5.08331793 21.9240451,5.02117159 21.9536731,4.94380574 L23.3032544,1.37609842 C23.3619056,1.22009842 23.2923707,1.04507403 23.1454405,0.978488667" id="Fill-52" transform="translate(16.058418, 4.069635) scale(-1, 1) translate(-16.058418, -4.069635) "></path> <path d="M23.1454405,0.978488667 C21.7366033,0.348781349 20.1862777,-0.000633284678 18.5591614,8.61663483e-07 C15.9694405,-0.000633284678 13.5756265,0.885269154 11.6377196,2.37931793 L10.4743707,0.618927691 C10.4060451,0.515561837 10.2863242,0.466732569 10.1690219,0.494000862 C10.0523242,0.521269154 9.96404514,0.618927691 9.94288235,0.742586228 L8.7970684,7.77907403 C8.78195212,7.87229354 8.80734747,7.96678135 8.86781259,8.03717159 C8.92404514,8.10312281 9.0038591,8.13926915 9.08669631,8.13926915 C9.09274282,8.13926915 9.09939398,8.13863501 9.10544049,8.13863501 L12.2169754,7.93253745 L15.7209289,7.70043989 C15.8382312,7.69219598 15.9398126,7.61229354 15.9791149,7.49561062 C16.0184172,7.37892769 15.9887893,7.24956184 15.9011149,7.16648867 L14.4408824,5.75107403 C15.6217661,4.92922037 17.0354405,4.45043989 18.5591614,4.44980574 C19.6281847,4.44980574 20.6421847,4.68761062 21.5618591,5.11185452 C21.6344172,5.14546428 21.7178591,5.14609842 21.7916265,5.11502525 C21.8647893,5.08331793 21.9240451,5.02117159 21.9536731,4.94380574 L23.3032544,1.37609842 C23.3619056,1.22009842 23.2923707,1.04507403 23.1454405,0.978488667" id="Fill-52" transform="translate(16.058418, 4.069635) scale(-1, 1) translate(-16.058418, -4.069635) "></path>
<path d="M12.7869128,13.3145374 C12.923564,14.9144887 13.36375,16.5119033 14.133471,18.0148301 C15.3584942,20.4080984 17.2341221,22.2014643 19.4066338,23.2858545 L18.4784942,25.1933667 C18.423471,25.3056106 18.4391919,25.4394155 18.5171919,25.5345374 C18.5951919,25.6290253 18.7191454,25.6651716 18.8334244,25.6252204 L25.2868663,23.3562448 C25.3721221,23.3258057 25.4398431,23.2579521 25.4700756,23.1691716 C25.4984942,23.0860984 25.4918431,22.9947813 25.4519361,22.9180496 C25.4489128,22.9123423 25.4464942,22.906635 25.4428663,22.9015618 L23.7982151,20.1233667 L21.945564,16.995757 C21.8826803,16.8911228 21.7677965,16.8353179 21.6510989,16.8537082 C21.5350058,16.8727326 21.4406803,16.9615131 21.411657,17.0820009 L20.9134244,19.1004887 C19.6642151,18.3984887 18.5927733,17.3179033 17.8720291,15.9100984 C17.3665407,14.9227326 17.0859826,13.8732204 17.0073779,12.823074 C17.0019361,12.7400009 16.9626338,12.6620009 16.901564,12.6087326 C16.8404942,12.5560984 16.7600756,12.5313667 16.681471,12.5408789 L13.0457035,12.9809765 C12.8872849,13.000635 12.7724012,13.1483911 12.7869128,13.3145374" id="Fill-54" transform="translate(19.136573, 19.090084) scale(-1, 1) translate(-19.136573, -19.090084) "></path> <path d="M12.7869128,13.3145374 C12.923564,14.9144887 13.36375,16.5119033 14.133471,18.0148301 C15.3584942,20.4080984 17.2341221,22.2014643 19.4066338,23.2858545 L18.4784942,25.1933667 C18.423471,25.3056106 18.4391919,25.4394155 18.5171919,25.5345374 C18.5951919,25.6290253 18.7191454,25.6651716 18.8334244,25.6252204 L25.2868663,23.3562448 C25.3721221,23.3258057 25.4398431,23.2579521 25.4700756,23.1691716 C25.4984942,23.0860984 25.4918431,22.9947813 25.4519361,22.9180496 C25.4489128,22.9123423 25.4464942,22.906635 25.4428663,22.9015618 L23.7982151,20.1233667 L21.945564,16.995757 C21.8826803,16.8911228 21.7677965,16.8353179 21.6510989,16.8537082 C21.5350058,16.8727326 21.4406803,16.9615131 21.411657,17.0820009 L20.9134244,19.1004887 C19.6642151,18.3984887 18.5927733,17.3179033 17.8720291,15.9100984 C17.3665407,14.9227326 17.0859826,13.8732204 17.0073779,12.823074 C17.0019361,12.7400009 16.9626338,12.6620009 16.901564,12.6087326 C16.8404942,12.5560984 16.7600756,12.5313667 16.681471,12.5408789 L13.0457035,12.9809765 C12.8872849,13.000635 12.7724012,13.1483911 12.7869128,13.3145374" id="Fill-54" transform="translate(19.136573, 19.090084) scale(-1, 1) translate(-19.136573, -19.090084) "></path>
<path d="M2.64553278,22.3327326 C3.89716069,21.4081472 4.99581185,20.2089765 5.85139324,18.7574155 C7.21427696,16.4484887 7.75664906,13.8472204 7.56436999,11.3328301 L9.60325371,11.2212204 C9.72357929,11.2148789 9.82697464,11.1337082 9.86567231,11.0144887 C9.90497464,10.8965374 9.87292813,10.7659033 9.78223045,10.682196 L4.68078859,5.95780574 C4.61246301,5.89502525 4.52297464,5.86839111 4.43409092,5.8861472 C4.35125371,5.90073257 4.27990487,5.95273257 4.23576534,6.02692769 C4.23274208,6.03263501 4.22971882,6.03834233 4.22669557,6.04404964 L2.75618394,8.92687891 L1.10185836,12.1743423 C1.04623045,12.2840496 1.05771882,12.4159521 1.13209092,12.5129765 C1.20585836,12.6093667 1.32618394,12.6499521 1.43925371,12.6169765 L3.35539324,12.0589277 C3.40074208,13.5440984 3.0452072,15.0571716 2.24404441,16.4167813 C1.68171882,17.3699033 0.955532778,18.1492692 0.127160685,18.746635 C0.0618583596,18.7935618 0.0171141736,18.8671228 0.00381184799,18.9495618 C-0.00888582643,19.0313667 0.0104630108,19.1169765 0.0570211503,19.1835618 L2.2404165,22.2648789 C2.33595138,22.3993179 2.51492813,22.4284887 2.64553278,22.3327326" id="Fill-56" transform="translate(4.941093, 14.134846) scale(-1, 1) translate(-4.941093, -14.134846) "></path> <path d="M2.64553278,22.3327326 C3.89716069,21.4081472 4.99581185,20.2089765 5.85139324,18.7574155 C7.21427696,16.4484887 7.75664906,13.8472204 7.56436999,11.3328301 L9.60325371,11.2212204 C9.72357929,11.2148789 9.82697464,11.1337082 9.86567231,11.0144887 C9.90497464,10.8965374 9.87292813,10.7659033 9.78223045,10.682196 L4.68078859,5.95780574 C4.61246301,5.89502525 4.52297464,5.86839111 4.43409092,5.8861472 C4.35125371,5.90073257 4.27990487,5.95273257 4.23576534,6.02692769 C4.23274208,6.03263501 4.22971882,6.03834233 4.22669557,6.04404964 L2.75618394,8.92687891 L1.10185836,12.1743423 C1.04623045,12.2840496 1.05771882,12.4159521 1.13209092,12.5129765 C1.20585836,12.6093667 1.32618394,12.6499521 1.43925371,12.6169765 L3.35539324,12.0589277 C3.40074208,13.5440984 3.0452072,15.0571716 2.24404441,16.4167813 C1.68171882,17.3699033 0.955532778,18.1492692 0.127160685,18.746635 C0.0618583596,18.7935618 0.0171141736,18.8671228 0.00381184799,18.9495618 C-0.00888582643,19.0313667 0.0104630108,19.1169765 0.0570211503,19.1835618 L2.2404165,22.2648789 C2.33595138,22.3993179 2.51492813,22.4284887 2.64553278,22.3327326" id="Fill-56" transform="translate(4.941093, 14.134846) scale(-1, 1) translate(-4.941093, -14.134846) "></path>
@ -41,16 +41,16 @@
<text id="render-copy-2" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal" fill="#000000"> <text id="render-copy-2" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal" fill="#000000">
<tspan x="297.3" y="142">render</tspan> <tspan x="297.3" y="142">render</tspan>
</text> </text>
<g id="np_paint_2296353_000000-copy" transform="translate(255.000000, 233.000000)" fill="#EE6B47" fill-rule="nonzero"> <g id="np_paint_2296353_000000-copy" transform="translate(256.000000, 233.000000)" fill="#EE6B47" fill-rule="nonzero">
<path d="M3.07894737,0 C1.39113684,0 0,1.39113684 0,3.07894737 L0,22.9210526 C0,24.6088632 1.39113684,26 3.07894737,26 L22.9210526,26 C24.6088632,26 26,24.6088632 26,22.9210526 L26,3.07894737 C26,1.39113684 24.6088632,0 22.9210526,0 L3.07894737,0 Z M3.07894737,2.05252895 L22.9210526,2.05252895 C23.5076947,2.05252895 23.9473684,2.49230526 23.9473684,3.07894737 L23.9473684,16.1217105 L21.0608553,13.4383053 C20.8590679,13.2485429 20.5891263,13.1483163 20.3125,13.1603447 C20.0492397,13.1710355 19.8006763,13.2819529 19.6176158,13.4703776 L13.8979579,19.4250618 L8.86251053,15.2770355 C8.64735711,15.1006392 8.3694,15.0191189 8.09277368,15.0525289 C7.86158579,15.0805922 7.64642895,15.1848279 7.48341579,15.3518711 L2.05249474,20.7827921 L2.05249474,3.07884474 C2.05249474,2.49220263 2.49216842,2.05252895 3.07881053,2.05252895 L3.07894737,2.05252895 Z M6.15789474,3.42105263 C4.47008421,3.42105263 3.07894737,4.81218947 3.07894737,6.5 C3.07894737,8.18781053 4.47008421,9.57894737 6.15789474,9.57894737 C7.84570526,9.57894737 9.23684211,8.18781053 9.23684211,6.5 C9.23684211,4.81218947 7.84570526,3.42105263 6.15789474,3.42105263 Z M6.15789474,5.47368421 C6.73653158,5.47368421 7.18421053,5.92136316 7.18421053,6.5 C7.18421053,7.07863684 6.73653158,7.52631579 6.15789474,7.52631579 C5.57925789,7.52631579 5.13157895,7.07863684 5.13157895,6.5 C5.13157895,5.92136316 5.57925789,5.47368421 6.15789474,5.47368421 Z M20.3340526,6.04027895 C19.9571895,6.04027895 19.5749895,6.76191579 19.5749895,7.12003158 C19.1152684,7.23228316 18.8266342,7.47818158 18.8266342,7.83633158 C18.8266342,8.19448158 19.1981263,8.55263158 19.5749895,8.55263158 L22.2369789,8.55263158 C22.9666211,8.55263158 23.3461526,7.12006579 22.2155974,7.12006579 C22.1942158,6.44252632 21.7705868,6.2608 21.0823737,6.40376579 C20.8992926,6.12046158 20.7068447,6.01756316 20.3340184,6.04027895 L20.3340526,6.04027895 Z M16.7097895,9.23684211 C16.3957471,9.23684211 16.0790158,9.82081579 16.0790158,10.1134868 C15.6968158,10.2056945 15.4482421,10.4088195 15.4482421,10.7014974 C15.4482421,10.9941753 15.7649563,11.2895079 16.0790158,11.2895079 L18.2920263,11.2895079 C18.90005,11.2895079 19.2234763,10.1135211 18.2813355,10.1135211 C18.2639631,9.55893421 17.9031382,9.40792895 17.3298724,9.52551053 C17.1775295,9.29432263 17.0198395,9.21814947 16.7098066,9.23685921 L16.7097895,9.23684211 Z M20.3980263,15.6191579 L23.9473684,18.9119211 L23.9473684,22.9210526 C23.9473684,23.5076947 23.5076947,23.9473684 22.9210526,23.9473684 L3.07894737,23.9473684 C2.71279211,23.9473684 2.40407632,23.7709721 2.22368421,23.4983553 L8.27484211,17.4581447 L12.4762368,20.9113553 L11.2361053,22.2049237 L12.7114342,23.6267816 L20.3980263,15.6191579 Z" id="Shape"></path> <path d="M3.07894737,0 C1.39113684,0 0,1.39113684 0,3.07894737 L0,22.9210526 C0,24.6088632 1.39113684,26 3.07894737,26 L22.9210526,26 C24.6088632,26 26,24.6088632 26,22.9210526 L26,3.07894737 C26,1.39113684 24.6088632,0 22.9210526,0 L3.07894737,0 Z M3.07894737,2.05252895 L22.9210526,2.05252895 C23.5076947,2.05252895 23.9473684,2.49230526 23.9473684,3.07894737 L23.9473684,16.1217105 L21.0608553,13.4383053 C20.8590679,13.2485429 20.5891263,13.1483163 20.3125,13.1603447 C20.0492397,13.1710355 19.8006763,13.2819529 19.6176158,13.4703776 L13.8979579,19.4250618 L8.86251053,15.2770355 C8.64735711,15.1006392 8.3694,15.0191189 8.09277368,15.0525289 C7.86158579,15.0805922 7.64642895,15.1848279 7.48341579,15.3518711 L2.05249474,20.7827921 L2.05249474,3.07884474 C2.05249474,2.49220263 2.49216842,2.05252895 3.07881053,2.05252895 L3.07894737,2.05252895 Z M6.15789474,3.42105263 C4.47008421,3.42105263 3.07894737,4.81218947 3.07894737,6.5 C3.07894737,8.18781053 4.47008421,9.57894737 6.15789474,9.57894737 C7.84570526,9.57894737 9.23684211,8.18781053 9.23684211,6.5 C9.23684211,4.81218947 7.84570526,3.42105263 6.15789474,3.42105263 Z M6.15789474,5.47368421 C6.73653158,5.47368421 7.18421053,5.92136316 7.18421053,6.5 C7.18421053,7.07863684 6.73653158,7.52631579 6.15789474,7.52631579 C5.57925789,7.52631579 5.13157895,7.07863684 5.13157895,6.5 C5.13157895,5.92136316 5.57925789,5.47368421 6.15789474,5.47368421 Z M20.3340526,6.04027895 C19.9571895,6.04027895 19.5749895,6.76191579 19.5749895,7.12003158 C19.1152684,7.23228316 18.8266342,7.47818158 18.8266342,7.83633158 C18.8266342,8.19448158 19.1981263,8.55263158 19.5749895,8.55263158 L22.2369789,8.55263158 C22.9666211,8.55263158 23.3461526,7.12006579 22.2155974,7.12006579 C22.1942158,6.44252632 21.7705868,6.2608 21.0823737,6.40376579 C20.8992926,6.12046158 20.7068447,6.01756316 20.3340184,6.04027895 L20.3340526,6.04027895 Z M16.7097895,9.23684211 C16.3957471,9.23684211 16.0790158,9.82081579 16.0790158,10.1134868 C15.6968158,10.2056945 15.4482421,10.4088195 15.4482421,10.7014974 C15.4482421,10.9941753 15.7649563,11.2895079 16.0790158,11.2895079 L18.2920263,11.2895079 C18.90005,11.2895079 19.2234763,10.1135211 18.2813355,10.1135211 C18.2639631,9.55893421 17.9031382,9.40792895 17.3298724,9.52551053 C17.1775295,9.29432263 17.0198395,9.21814947 16.7098066,9.23685921 L16.7097895,9.23684211 Z M20.3980263,15.6191579 L23.9473684,18.9119211 L23.9473684,22.9210526 C23.9473684,23.5076947 23.5076947,23.9473684 22.9210526,23.9473684 L3.07894737,23.9473684 C2.71279211,23.9473684 2.40407632,23.7709721 2.22368421,23.4983553 L8.27484211,17.4581447 L12.4762368,20.9113553 L11.2361053,22.2049237 L12.7114342,23.6267816 L20.3980263,15.6191579 Z" id="Shape"></path>
</g> </g>
<g id="np_paint_2296353_000000-copy-2" transform="translate(255.000000, 124.000000)" fill="#EE6B47" fill-rule="nonzero"> <g id="np_paint_2296353_000000-copy-2" transform="translate(256.000000, 124.000000)" fill="#EE6B47" fill-rule="nonzero">
<path d="M3.07894737,0 C1.39113684,0 0,1.39113684 0,3.07894737 L0,22.9210526 C0,24.6088632 1.39113684,26 3.07894737,26 L22.9210526,26 C24.6088632,26 26,24.6088632 26,22.9210526 L26,3.07894737 C26,1.39113684 24.6088632,0 22.9210526,0 L3.07894737,0 Z M3.07894737,2.05252895 L22.9210526,2.05252895 C23.5076947,2.05252895 23.9473684,2.49230526 23.9473684,3.07894737 L23.9473684,16.1217105 L21.0608553,13.4383053 C20.8590679,13.2485429 20.5891263,13.1483163 20.3125,13.1603447 C20.0492397,13.1710355 19.8006763,13.2819529 19.6176158,13.4703776 L13.8979579,19.4250618 L8.86251053,15.2770355 C8.64735711,15.1006392 8.3694,15.0191189 8.09277368,15.0525289 C7.86158579,15.0805922 7.64642895,15.1848279 7.48341579,15.3518711 L2.05249474,20.7827921 L2.05249474,3.07884474 C2.05249474,2.49220263 2.49216842,2.05252895 3.07881053,2.05252895 L3.07894737,2.05252895 Z M6.15789474,3.42105263 C4.47008421,3.42105263 3.07894737,4.81218947 3.07894737,6.5 C3.07894737,8.18781053 4.47008421,9.57894737 6.15789474,9.57894737 C7.84570526,9.57894737 9.23684211,8.18781053 9.23684211,6.5 C9.23684211,4.81218947 7.84570526,3.42105263 6.15789474,3.42105263 Z M6.15789474,5.47368421 C6.73653158,5.47368421 7.18421053,5.92136316 7.18421053,6.5 C7.18421053,7.07863684 6.73653158,7.52631579 6.15789474,7.52631579 C5.57925789,7.52631579 5.13157895,7.07863684 5.13157895,6.5 C5.13157895,5.92136316 5.57925789,5.47368421 6.15789474,5.47368421 Z M20.3340526,6.04027895 C19.9571895,6.04027895 19.5749895,6.76191579 19.5749895,7.12003158 C19.1152684,7.23228316 18.8266342,7.47818158 18.8266342,7.83633158 C18.8266342,8.19448158 19.1981263,8.55263158 19.5749895,8.55263158 L22.2369789,8.55263158 C22.9666211,8.55263158 23.3461526,7.12006579 22.2155974,7.12006579 C22.1942158,6.44252632 21.7705868,6.2608 21.0823737,6.40376579 C20.8992926,6.12046158 20.7068447,6.01756316 20.3340184,6.04027895 L20.3340526,6.04027895 Z M16.7097895,9.23684211 C16.3957471,9.23684211 16.0790158,9.82081579 16.0790158,10.1134868 C15.6968158,10.2056945 15.4482421,10.4088195 15.4482421,10.7014974 C15.4482421,10.9941753 15.7649563,11.2895079 16.0790158,11.2895079 L18.2920263,11.2895079 C18.90005,11.2895079 19.2234763,10.1135211 18.2813355,10.1135211 C18.2639631,9.55893421 17.9031382,9.40792895 17.3298724,9.52551053 C17.1775295,9.29432263 17.0198395,9.21814947 16.7098066,9.23685921 L16.7097895,9.23684211 Z M20.3980263,15.6191579 L23.9473684,18.9119211 L23.9473684,22.9210526 C23.9473684,23.5076947 23.5076947,23.9473684 22.9210526,23.9473684 L3.07894737,23.9473684 C2.71279211,23.9473684 2.40407632,23.7709721 2.22368421,23.4983553 L8.27484211,17.4581447 L12.4762368,20.9113553 L11.2361053,22.2049237 L12.7114342,23.6267816 L20.3980263,15.6191579 Z" id="Shape"></path> <path d="M3.07894737,0 C1.39113684,0 0,1.39113684 0,3.07894737 L0,22.9210526 C0,24.6088632 1.39113684,26 3.07894737,26 L22.9210526,26 C24.6088632,26 26,24.6088632 26,22.9210526 L26,3.07894737 C26,1.39113684 24.6088632,0 22.9210526,0 L3.07894737,0 Z M3.07894737,2.05252895 L22.9210526,2.05252895 C23.5076947,2.05252895 23.9473684,2.49230526 23.9473684,3.07894737 L23.9473684,16.1217105 L21.0608553,13.4383053 C20.8590679,13.2485429 20.5891263,13.1483163 20.3125,13.1603447 C20.0492397,13.1710355 19.8006763,13.2819529 19.6176158,13.4703776 L13.8979579,19.4250618 L8.86251053,15.2770355 C8.64735711,15.1006392 8.3694,15.0191189 8.09277368,15.0525289 C7.86158579,15.0805922 7.64642895,15.1848279 7.48341579,15.3518711 L2.05249474,20.7827921 L2.05249474,3.07884474 C2.05249474,2.49220263 2.49216842,2.05252895 3.07881053,2.05252895 L3.07894737,2.05252895 Z M6.15789474,3.42105263 C4.47008421,3.42105263 3.07894737,4.81218947 3.07894737,6.5 C3.07894737,8.18781053 4.47008421,9.57894737 6.15789474,9.57894737 C7.84570526,9.57894737 9.23684211,8.18781053 9.23684211,6.5 C9.23684211,4.81218947 7.84570526,3.42105263 6.15789474,3.42105263 Z M6.15789474,5.47368421 C6.73653158,5.47368421 7.18421053,5.92136316 7.18421053,6.5 C7.18421053,7.07863684 6.73653158,7.52631579 6.15789474,7.52631579 C5.57925789,7.52631579 5.13157895,7.07863684 5.13157895,6.5 C5.13157895,5.92136316 5.57925789,5.47368421 6.15789474,5.47368421 Z M20.3340526,6.04027895 C19.9571895,6.04027895 19.5749895,6.76191579 19.5749895,7.12003158 C19.1152684,7.23228316 18.8266342,7.47818158 18.8266342,7.83633158 C18.8266342,8.19448158 19.1981263,8.55263158 19.5749895,8.55263158 L22.2369789,8.55263158 C22.9666211,8.55263158 23.3461526,7.12006579 22.2155974,7.12006579 C22.1942158,6.44252632 21.7705868,6.2608 21.0823737,6.40376579 C20.8992926,6.12046158 20.7068447,6.01756316 20.3340184,6.04027895 L20.3340526,6.04027895 Z M16.7097895,9.23684211 C16.3957471,9.23684211 16.0790158,9.82081579 16.0790158,10.1134868 C15.6968158,10.2056945 15.4482421,10.4088195 15.4482421,10.7014974 C15.4482421,10.9941753 15.7649563,11.2895079 16.0790158,11.2895079 L18.2920263,11.2895079 C18.90005,11.2895079 19.2234763,10.1135211 18.2813355,10.1135211 C18.2639631,9.55893421 17.9031382,9.40792895 17.3298724,9.52551053 C17.1775295,9.29432263 17.0198395,9.21814947 16.7098066,9.23685921 L16.7097895,9.23684211 Z M20.3980263,15.6191579 L23.9473684,18.9119211 L23.9473684,22.9210526 C23.9473684,23.5076947 23.5076947,23.9473684 22.9210526,23.9473684 L3.07894737,23.9473684 C2.71279211,23.9473684 2.40407632,23.7709721 2.22368421,23.4983553 L8.27484211,17.4581447 L12.4762368,20.9113553 L11.2361053,22.2049237 L12.7114342,23.6267816 L20.3980263,15.6191579 Z" id="Shape"></path>
</g> </g>
<g id="Group-Copy-2" transform="translate(253.000000, 159.000000)" fill="#EE6B47"> <g id="Group-Copy-2" transform="translate(256.000000, 159.000000)" fill="#EE6B47">
<path d="M26.7062775,1.12902538 C25.0806961,0.402440019 23.2918589,-0.00073071309 21.414417,9.94227133e-07 C18.4262775,-0.00073071309 15.6641845,1.02146441 13.428138,2.74536685 L12.0858124,0.714147336 C12.0069752,0.594879043 11.8688356,0.53853758 11.7334868,0.570000994 C11.5988356,0.601464409 11.4969752,0.714147336 11.4725566,0.856830263 L10.1504635,8.97585465 C10.1330217,9.08341563 10.162324,9.19244002 10.2320914,9.27365953 C10.2969752,9.34975709 10.3890682,9.39146441 10.4846496,9.39146441 C10.4916263,9.39146441 10.4993007,9.3907327 10.5062775,9.3907327 L14.0965101,9.15292782 L18.1395333,8.88512295 C18.2748821,8.87561075 18.3920914,8.78341563 18.4374403,8.64878148 C18.4827891,8.51414734 18.4486031,8.36487904 18.3474403,8.26902538 L16.6625566,6.63585465 C18.0251147,5.68756197 19.6562775,5.13512295 21.414417,5.13439124 C22.6479054,5.13439124 23.8179054,5.40878148 24.8790682,5.89829368 C24.9627891,5.93707416 25.0590682,5.93780587 25.1441845,5.90195221 C25.2286031,5.86536685 25.2969752,5.79365953 25.3311612,5.70439124 L26.8883705,1.58780587 C26.9560449,1.40780587 26.8758124,1.20585465 26.7062775,1.12902538" id="Fill-52" transform="translate(18.528944, 4.695732) scale(-1, 1) translate(-18.528944, -4.695732) "></path> <path d="M23.1454405,0.978488667 C21.7366033,0.348781349 20.1862777,-0.000633284678 18.5591614,8.61663483e-07 C15.9694405,-0.000633284678 13.5756265,0.885269154 11.6377196,2.37931793 L10.4743707,0.618927691 C10.4060451,0.515561837 10.2863242,0.466732569 10.1690219,0.494000862 C10.0523242,0.521269154 9.96404514,0.618927691 9.94288235,0.742586228 L8.7970684,7.77907403 C8.78195212,7.87229354 8.80734747,7.96678135 8.86781259,8.03717159 C8.92404514,8.10312281 9.0038591,8.13926915 9.08669631,8.13926915 C9.09274282,8.13926915 9.09939398,8.13863501 9.10544049,8.13863501 L12.2169754,7.93253745 L15.7209289,7.70043989 C15.8382312,7.69219598 15.9398126,7.61229354 15.9791149,7.49561062 C16.0184172,7.37892769 15.9887893,7.24956184 15.9011149,7.16648867 L14.4408824,5.75107403 C15.6217661,4.92922037 17.0354405,4.45043989 18.5591614,4.44980574 C19.6281847,4.44980574 20.6421847,4.68761062 21.5618591,5.11185452 C21.6344172,5.14546428 21.7178591,5.14609842 21.7916265,5.11502525 C21.8647893,5.08331793 21.9240451,5.02117159 21.9536731,4.94380574 L23.3032544,1.37609842 C23.3619056,1.22009842 23.2923707,1.04507403 23.1454405,0.978488667" id="Fill-52" transform="translate(16.058418, 4.069635) scale(-1, 1) translate(-16.058418, -4.069635) "></path>
<path d="M14.7541302,15.3629278 C14.9118046,17.2090254 15.4197116,19.0521961 16.3078511,20.7863425 C17.7213395,23.5478059 19.8855255,25.6170742 22.3922697,26.8682937 L21.3213395,29.0692693 C21.2578511,29.1987815 21.2759906,29.3531717 21.3659906,29.4629278 C21.4559906,29.5719522 21.5990139,29.6136595 21.7308744,29.567562 L29.1771534,26.9495132 C29.2755255,26.9143912 29.3536651,26.8360986 29.3885488,26.7336595 C29.4213395,26.6378059 29.4136651,26.53244 29.3676186,26.4439034 C29.3641302,26.4373181 29.3613395,26.4307327 29.3571534,26.424879 L27.459479,23.2192693 L25.3218046,19.6104888 C25.2492465,19.4897571 25.1166883,19.4253668 24.9820372,19.4465864 C24.8480837,19.4685376 24.7392465,19.5709766 24.7057581,19.710001 L24.1308744,22.0390254 C22.689479,21.2290254 21.4531999,19.9821961 20.621572,18.3578059 C20.0383162,17.2185376 19.7145953,16.007562 19.6238976,14.7958547 C19.6176186,14.700001 19.5722697,14.610001 19.5018046,14.5485376 C19.4313395,14.4878059 19.3385488,14.4592693 19.2478511,14.4702449 L15.0527348,14.9780498 C14.8699441,15.0007327 14.737386,15.1712205 14.7541302,15.3629278" id="Fill-54" transform="translate(22.080661, 22.027020) scale(-1, 1) translate(-22.080661, -22.027020) "></path> <path d="M12.7869128,13.3145374 C12.923564,14.9144887 13.36375,16.5119033 14.133471,18.0148301 C15.3584942,20.4080984 17.2341221,22.2014643 19.4066338,23.2858545 L18.4784942,25.1933667 C18.423471,25.3056106 18.4391919,25.4394155 18.5171919,25.5345374 C18.5951919,25.6290253 18.7191454,25.6651716 18.8334244,25.6252204 L25.2868663,23.3562448 C25.3721221,23.3258057 25.4398431,23.2579521 25.4700756,23.1691716 C25.4984942,23.0860984 25.4918431,22.9947813 25.4519361,22.9180496 C25.4489128,22.9123423 25.4464942,22.906635 25.4428663,22.9015618 L23.7982151,20.1233667 L21.945564,16.995757 C21.8826803,16.8911228 21.7677965,16.8353179 21.6510989,16.8537082 C21.5350058,16.8727326 21.4406803,16.9615131 21.411657,17.0820009 L20.9134244,19.1004887 C19.6642151,18.3984887 18.5927733,17.3179033 17.8720291,15.9100984 C17.3665407,14.9227326 17.0859826,13.8732204 17.0073779,12.823074 C17.0019361,12.7400009 16.9626338,12.6620009 16.901564,12.6087326 C16.8404942,12.5560984 16.7600756,12.5313667 16.681471,12.5408789 L13.0457035,12.9809765 C12.8872849,13.000635 12.7724012,13.1483911 12.7869128,13.3145374" id="Fill-54" transform="translate(19.136573, 19.090084) scale(-1, 1) translate(-19.136573, -19.090084) "></path>
<path d="M3.05253782,25.7685376 C4.49672387,24.7017083 5.76439829,23.3180498 6.75160759,21.6431717 C8.32416573,18.9790254 8.94997968,15.977562 8.72811922,13.0763425 L11.0806774,12.947562 C11.2195146,12.9402449 11.3388169,12.8465864 11.3834681,12.7090254 C11.4288169,12.5729278 11.3918401,12.4221961 11.287189,12.3256108 L5.40090991,6.87439124 C5.3220727,6.80195221 5.21881689,6.77122051 5.11625875,6.79170831 C5.02067736,6.80853758 4.93835177,6.86853758 4.88742154,6.95414734 C4.88393317,6.9607327 4.8804448,6.96731807 4.87695643,6.97390343 L3.18021224,10.3002449 L1.27137503,14.0473181 C1.20718898,14.1739034 1.2204448,14.3260986 1.30625875,14.4380498 C1.39137503,14.5492693 1.53021224,14.5960986 1.66067736,14.5580498 L3.87160759,13.9141473 C3.92393317,15.6278059 3.51370061,17.3736595 2.58928201,18.94244 C1.9404448,20.0421961 1.10253782,20.9414644 0.146723868,21.6307327 C0.0713750303,21.684879 0.0197471233,21.7697571 0.00439828614,21.864879 C-0.0102528767,21.9592693 0.0120727047,22.0580498 0.065793635,22.134879 L2.58509596,25.6902449 C2.69532852,25.8453668 2.90184015,25.8790254 3.05253782,25.7685376" id="Fill-56" transform="translate(5.701261, 16.309438) scale(-1, 1) translate(-5.701261, -16.309438) "></path> <path d="M2.64553278,22.3327326 C3.89716069,21.4081472 4.99581185,20.2089765 5.85139324,18.7574155 C7.21427696,16.4484887 7.75664906,13.8472204 7.56436999,11.3328301 L9.60325371,11.2212204 C9.72357929,11.2148789 9.82697464,11.1337082 9.86567231,11.0144887 C9.90497464,10.8965374 9.87292813,10.7659033 9.78223045,10.682196 L4.68078859,5.95780574 C4.61246301,5.89502525 4.52297464,5.86839111 4.43409092,5.8861472 C4.35125371,5.90073257 4.27990487,5.95273257 4.23576534,6.02692769 C4.23274208,6.03263501 4.22971882,6.03834233 4.22669557,6.04404964 L2.75618394,8.92687891 L1.10185836,12.1743423 C1.04623045,12.2840496 1.05771882,12.4159521 1.13209092,12.5129765 C1.20585836,12.6093667 1.32618394,12.6499521 1.43925371,12.6169765 L3.35539324,12.0589277 C3.40074208,13.5440984 3.0452072,15.0571716 2.24404441,16.4167813 C1.68171882,17.3699033 0.955532778,18.1492692 0.127160685,18.746635 C0.0618583596,18.7935618 0.0171141736,18.8671228 0.00381184799,18.9495618 C-0.00888582643,19.0313667 0.0104630108,19.1169765 0.0570211503,19.1835618 L2.2404165,22.2648789 C2.33595138,22.3993179 2.51492813,22.4284887 2.64553278,22.3327326" id="Fill-56" transform="translate(4.941093, 14.134846) scale(-1, 1) translate(-4.941093, -14.134846) "></path>
</g> </g>
<path id="Path" d="M271.37688,54.2091068 L277.281818,43.0430224 L279.933822,44.4454762 L270.10532,63.030918 L259.326034,44.9802923 L261.901723,43.4421687 L268.37789,54.2869371 L268.114902,44.1533849 C266.186912,31.2365743 257.43807,26.5 240.535714,26.5 L189.464286,26.5 C170.419705,26.5 161.5,32.5455101 161.5,49.720739 L161.5,344.396487 C161.5,353.579279 164.161121,359.079115 169.381009,362.098821 C173.770528,364.638159 179.668177,365.5 189.464286,365.5 L240.535714,365.5 C250.331823,365.5 256.229472,364.638159 260.618991,362.098821 C265.838879,359.079115 268.5,353.579279 268.5,344.396487 L268.5,337.923831 L271.5,337.923831 L271.5,344.396487 C271.5,354.57926 268.348133,361.093339 262.12123,364.695603 C257.137794,367.578522 250.832047,368.5 240.535714,368.5 L189.464286,368.5 C179.167953,368.5 172.862206,367.578522 167.87877,364.695603 C161.651867,361.093339 158.5,354.57926 158.5,344.396487 L158.5,49.720739 C158.5,30.5855262 168.954172,23.5 189.464286,23.5 L240.535714,23.5 C258.785035,23.5 268.930165,29.0165608 271.096211,43.8064028 L271.111539,43.9848515 L271.37688,54.2091068 Z" fill="#EE6B47" fill-rule="nonzero"></path> <path id="Path" d="M271.37688,54.2091068 L277.281818,43.0430224 L279.933822,44.4454762 L270.10532,63.030918 L259.326034,44.9802923 L261.901723,43.4421687 L268.37789,54.2869371 L268.114902,44.1533849 C266.186912,31.2365743 257.43807,26.5 240.535714,26.5 L189.464286,26.5 C170.419705,26.5 161.5,32.5455101 161.5,49.720739 L161.5,344.396487 C161.5,353.579279 164.161121,359.079115 169.381009,362.098821 C173.770528,364.638159 179.668177,365.5 189.464286,365.5 L240.535714,365.5 C250.331823,365.5 256.229472,364.638159 260.618991,362.098821 C265.838879,359.079115 268.5,353.579279 268.5,344.396487 L268.5,337.923831 L271.5,337.923831 L271.5,344.396487 C271.5,354.57926 268.348133,361.093339 262.12123,364.695603 C257.137794,367.578522 250.832047,368.5 240.535714,368.5 L189.464286,368.5 C179.167953,368.5 172.862206,367.578522 167.87877,364.695603 C161.651867,361.093339 158.5,354.57926 158.5,344.396487 L158.5,49.720739 C158.5,30.5855262 168.954172,23.5 189.464286,23.5 L240.535714,23.5 C258.785035,23.5 268.930165,29.0165608 271.096211,43.8064028 L271.111539,43.9848515 L271.37688,54.2091068 Z" fill="#EE6B47" fill-rule="nonzero"></path>
</g> </g>

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Before After
Before After

Binary file not shown.