Back to Releases

Release notes *2.7.8*

May 8, 2025

Performance Optimizations

The WLJS Interpreter is a silent hero running in the browser, handling all interactivity, UI updates, the core of ManipulatePlot, and much more. It is essentially a tiny Wolfram Language interpreter.

We optimized a subsystem responsible for dynamics to handle better such cases:

ov = 1.0;
{Circle[], Line[{{0,0}, {Sin[ov], Cos[ov]} // Offload}]} // Graphics 
(*VB[*)(Graphics[{Circle[{0, 0}], Line[{{0, 0}, Offload[{Sin[ov], Cos[ov]}]}]}, ImageSize -> Small])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KWlMIB4HkHAvSizIyEwuhoiA5H0yi0sgqtmAhHNmUXJOKqpsJpBmABMIU30y89BU4dfDDiT809Jy8hNTsFnNDCSCM/OKQVL5ZQgx5/ximBhcV1BpTmoxJ5DhmZuYnhqcWZVazArSnpuYkwMAQg4unA=="*)(*]VB*)

Before, each update of ov could cause 2x reevaluation of the Line primitive, which is a waste of resources. Now, our systems have become smarter and disregard the duplicates:

ov = RandomReal[{0,2Pi}];

Symbols compression

We added gzip compression to any dynamic symbols exeeding 2048 bytes, which reduces the filesize of a notebook as well as saving and loading time. If you open now a notebook in the editor one can spot a Base63 encoded compressed data:

%3Cpre%20class%3D%22text-sm%20pt-1%22%3E%3C%7C%22Notebook%22%20-%3E%20%3C%7C%0A%20%20%20%22Objects%22%20-%3E%20%3C%7C%7C%3E%2C%20%0A%20%20%20%22Path%22%20-%3E%20%22%2Fusers%2Fkirill%2FDownloads%2FTest.wln%22%2C%20%0A%20%20%20%22PublicFields%22%20-%3E%20%7B%22Properties%22%7D%2C%20%22Quick%22%20-%3E%20True%2C%0A%20%20%20%22Symbols%22%20-%3E%0A%20%20%20%20%3C%7C%22buffer%24310657%22%20-%3E%20CoffeeLiqueur%60Extensions%60FrontendObject%60Tools%60ExtractCompressed%5B%22eJzszrE%5C%0AJAgEAQ9FdrrYSbgs3EAew1v2xMoGbIMUrQuBV%2F3k83p%2Fvcbv%2B%2FTz%2Fe0EIIYQQQgghhBBCCCGEEEII%5C%0AIYQQQgghhBBCCCGEEEIIIYQQQjiC1b02CCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEE%5C%0A...%0A%3C%2Fpre%3E

It is similar to what we did to big graphs or sound data.

Better support of 2D graphics

Even more supported primitives, modifiers!

RadialAxisPlot[{{9, 7, 9, 5, 5, 7}, {6, 2, 3, 8, 8, 7}, {6, 8, 3, 4, 
   1, 9}}]
(*VB[*)(FrontEndRef["f343e8f9-f77e-43c1-b33b-2fcabc95147a"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKpxmbGKdapFnqppmbp+qaGCcb6iYZGyfpGqUlJyYlW5oampgnAgCK3RYJ"*)(*]VB*)

SVGGroup

We intoroduce a new (with respect to Wolfram Language Library) element:

With[{p = ContourPlot[x y, {x,0,1}, {y,0,1}]//First},
  Graphics[{
    Pink, Disk[], {Opacity[0.5], Translate[SVGGroup[p], {0.05,0.05}]}
  }, PlotRange->{{0,1.05}, {0,1.05}}]
]
(*VB[*)(FrontEndRef["d34d9848-1b18-417a-96ab-95d8c2d25e07"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKpxibpFhamFjoGiYZWuiaGJon6lqaJSbpWpqmWCQbpRiZphqYAwB8ZhVQ"*)(*]VB*)

A standard library lacks tools for grouping primitives in order to apply the properties to the group container. Like transparency for example. The modified properties such as RGBColor, Directive will not affect the content of SVGGroup, which helps to isolate the styles.

Slides styles

We refined the srtandard styles used for heading, titles and other sections on .slide cell type.

.slide

<!-- .slide: class="slide-standard" -->

# Title

Some text
<dummy >
<!-- .slide: class="slide-standard" -->

# Title

Some text
</dummy>

There is a shorthand class for standard PPT-like slides with left-aligned text and 100% height:

.slide

<!-- .slide: class="slide-standard" -->

Or for scrollable slides

.slide

<!-- .slide: class="slide-standard-scroll" -->

## Title

<br/><br/><br/>
...large content goes
<br/><br/><br/>
...large content goes
<br/><br/><br/>
...large content goes
<br/><br/><br/>

<br/><br/><br/>
...large content goes

<br/><br/><br/>
...large content goes
<br/><br/><br/>
...large content goes
<br/><br/><br/>
...large content goes
<br/><br/><br/>
...large content goes
<br/><br/><br/>
...large content goes
<dummy >
<!-- .slide: class="slide-standard-scroll" -->

## Title

<br /><br /><br />
...large content goes
<br /><br /><br />
...large content goes
<br /><br /><br />
...large content goes
<br /><br /><br /><br /><br /><br />
...large content goes

<br /><br /><br />
...large content goes
<br /><br /><br />
...large content goes
<br /><br /><br />
...large content goes
<br /><br /><br />
...large content goes
<br /><br /><br />
...large content goes</dummy>

Async functions

We made a huge step in development of Async and Promise modules. AsyncFunction expression allows to write asynchronous sequential code avoiding callback hell. AsyncFunction and Await expressions and their concepts are built on top of promises:

temperature = "";
TextView[temperature // Offload]
If[Kernels[] == {}, LaunchKernels[1]];

Button["Get Temperature", AsyncFunction[Null, Module[{response},
  temperature = "Loading";
  response = ParallelSubmitAsync[URLRead[(*VB[*)(Uncompress["1:eJwlx7EOgjAUBdD+igsbbVpkMSH8A64mptarkNC+5nHr9zN4tnN5yXJ/GGNWsh4352LdrFSUPoMQmyS7n3cfUaR4cN4jN7Y3pjHYMXS7lO//frBX36WmisKJyBUa2RTPkE+6nCL0"])(*,*)(*"1:eJxTTMoPSmNmYGAo5gUSYZmp5S6pyflFiSX5RcEcQBHP5Py8zKrUlMwKICeNCaSQBUgEleakBrMCGT6JSak5wSAhv/y8VADrohJz"*)(*]VB*)]] // Await;
  temperature = ImportByteArray[response["BodyByteArray"], "RawJSON"]["current", "temperature_2m"];
]][]]
(*VB[*)(FrontEndRef["8adfafe8-3a4d-4c85-8990-de57aa132fcc"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKWySmpCWmpVroGieapOiaJFuY6lpYWhropqSamicmGhobpSUnAwCWuBZt"*)(*]VB*)
(*VB[*)(EventObject[<|"Id" -> "77baa753-1e5f-4593-94e0-2589f8c8d457", "Initial" -> False, "View" -> "b967121d-e458-414e-921a-12930b2dc60c"|>])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKJ1mamRsaGaboppqYWuiaGJqk6loaGSbqGhpZGhskGaUkmxkkAwB19hUH"*)(*]VB*)

Heavy branching

In this example we demonstrate branching, assignments and compound expressions in asynchronous functions:

p1%20%3D%20Promise%5B%5D%3B%0Ap2%20%3D%20Promise%5B%5D%3B%0Ap3%20%3D%20Promise%5B%5D%3B%0A%0Awin%20%3D%20CurrentWindow%5B%5D%3B%0A%0ASpeak%5B%22Let%27s%20see%20how%20it%20works%21%22%5D%3B%0APause%5B2.5%5D%3B%0A%0Af%20%3D%20AsyncFunction%5BNull%2C%20With%5B%7B%7D%2C%0A%20%20Speak%5B%22Press%20p1%22%2C%20%22Window%22-%3Ewin%5D%3B%0A%20%20p1%20%2F%2F%20Await%3B%0A%20%20Speak%5B%22Press%20p2A%20or%20p2B%22%2C%20%22Window%22-%3Ewin%5D%3B%0A%20%20Module%5B%7Bm%20%3D%20-100%7D%2C%0A%20%20%20%20m%20%3D%20Await%5Bp2%5D%3B%0A%20%20%20%20Speak%5B%22Pause%202%20seconds%22%2C%20%22Window%22-%3Ewin%5D%3B%0A%20%20%20%20PauseAsync%5B2%5D%20%2F%2F%20Await%3B%0A%20%20%20%20%0A%20%20%20%20If%5Bm%20%3E%204%2C%0A%20%20%20%20%20%20Speak%5B%22Press%20p3%22%2C%20%22Window%22-%3Ewin%5D%3B%0A%20%20%20%20%20%20m%20%3D%20Await%5Bp3%5D%3B%0A%20%20%20%20%5D%3B%0A%0A%20%20%20%20StringTemplate%5B%22Result%3A%20%60%60%22%5D%5Bm%5D%0A%20%20%5D%0A%5D%5D%3B%0A%0AThen%5Bf%5B%5D%2C%20Speak%5D%3B

To simulate async events here we use buttons

Button["p1", EventFire[p1, Resolve, True]]
Button["p2A", EventFire[p2, Resolve, 1]]
Button["p2B", EventFire[p2, Resolve, 5]]
Button["p3", EventFire[p3, Resolve, 10]]

Writting this in a traditional way would lead straight to the callback hell.

%3Cbr%20%2F%3E %3Cbr%20%2F%3E

Limitations

The following constructions are supported with Await:

  • Set
  • CompoundExpression
  • If
  • Module, With
  • _Symbol or any other singular expressions

What is not supported (by now)

  • Loops: While, For, Do
  • Tables and maps: Map, Table

Please read the documentation for more examples.

Animation Framework 🌈

AF is a build-in library for creating complex event-driven 2D animations in a functional style. You create all necessary primitives by yourself combining well-known expressions of Wolfram Language.

%3Cbr%20%2F%3E %3Cdetails%20%3E%3Csummary%20%3E%0A%20%20%20%20Created%20using%20__AF__%0A%20%20%3C%2Fsummary%3E%3Ciframe%20width%3D%22720%22%20height%3D%22576%22%20src%3D%22https%3A%2F%2Fwww.youtube.com%2Fembed%2FvTrVGam84m8%22%20title%3D%22YouTube%20video%20player%22%20frameborder%3D%220%22%20allow%3D%22accelerometer%3B%20autoplay%3B%20clipboard-write%3B%20encrypted-media%3B%20gyroscope%3B%20picture-in-picture%22%3E%3C%2Fiframe%3E%3C%2Fdetails%3E %3Cbr%20%2F%3E

The framework is entirely based on AsyncFunction and Offload acting as a wrapper. You may also use GUI helper tools such as a timeline if you want:

Or record a voice over right in-place.

See tutorials in the documentation on our website in Advanced section

Basic example

Here is how you can make an animation quickly using WL primitives as building blocks

Needs%5B%22AnimationFramework%60%22%20-%3E%20%22af%60%22%5D%20%2F%2F%20Quiet

Create a scene:

s%20%3D%20af%60Scene%5B%5D%3B%0AFramed%5Bs%5D

Run animation

AsyncFunction%5Bscene%2C%20Module%5B%7Bd%7D%2C%0A%20%20d%20%3D%20af%60AddTo%5Bscene%2C%20Disk%5B%23pos%2C%200.1%5D%2C%20%7B%0A%20%20%20%20%22pos%22%20-%3E%20%7B-1%2C0%7D%0A%20%20%7D%5D%3B%0A%0A%20%20af%60Animate%5Bscene%2C%20d%2C%20%22pos%22-%3E%7B1%2C0%7D%2C%20%22QuadOut%22%2C%201.5%5D%20%2F%2F%20Await%3B%0A%20%20%0A%20%20af%60Remove%5Bd%5D%3B%0A%5D%5D%5Bs%5D%3B

And that's all you need. Here is another example with two objects:

AsyncFunction%5Bscene%2C%20Module%5B%7Bd%2Cr%7D%2C%0A%20%20r%20%3D%20af%60AddTo%5Bscene%2C%20%7BRed%2C%20Translate%5BRotate%5B%0A%20%20%20%20%20%20Rectangle%5B0.2%7B-1%2C-1%7D%2C%200.2%7B1%2C1%7D%5D%0A%20%20%2C%20%23angle%5D%2C%20%23pos%5D%7D%2C%20%7B%0A%20%20%20%20%22pos%22%20-%3E%20%7B1.5%2C1.5%7D%2C%0A%20%20%20%20%22angle%22%20-%3E%200.%0A%20%20%7D%5D%3B%20%20%0A%0A%20%20d%20%3D%20af%60AddTo%5Bscene%2C%20%7BBlue%2C%20Disk%5B%23pos%2C%200.1%5D%7D%2C%20%7B%0A%20%20%20%20%22pos%22%20-%3E%20%7B-1.5%2C0%7D%0A%20%20%7D%5D%3B%0A%0A%20%20%7B%0A%20%20%20%20af%60Animate%5Bscene%2C%20d%2C%20%22pos%22-%3E%7B0%2C0%7D%2C%20%22QuadOut%22%2C%201.5%5D%2C%0A%20%20%20%20af%60Animate%5Bscene%2C%20r%2C%20%7B%0A%20%20%20%20%20%20%22pos%22-%3E%7B0%2C0%7D%2C%20%22angle%22-%3E2Pi%0A%20%20%20%20%7D%2C%20%22QuadOut%22%2C%201.5%5D%0A%20%20%7D%2F%2F%20Await%3B%0A%20%20%0A%20%20af%60Remove%5Bd%5D%3B%0A%20%20af%60Remove%5Br%5D%3B%0A%5D%5D%5Bs%5D%3B

To make more complex animations we also provide:

  • easing functions;
  • workers;
  • loops;

and many more.


%0A%3Cstyle%3E%0A%20%20img%20%7B%0A%20%20%20%20border-radius%3A%200.5rem%3B%0A%20%20%7D%0A%3C%2Fstyle%3E %0A%3Cstyle%3E%0A%20%20%5Btransparency%3D%22false%22%5D%20.bg-g-trans%20%7B%0A%20%20%20%20background%3A%20transparent%20%21important%3B%0A%20%20%7D%0A%0A%20%20%5Btransparency%3D%22true%22%5D%20.bg-g-trans%20%7B%0A%20%20%20%20background%3A%20transparent%20%21important%3B%0A%20%20%7D%0A%3C%2Fstyle%3E