Frontend Development 15 min read

Why Atom Fell and How Figma’s Plugin Sandbox Redefines Web Editor Architecture

This article examines the decline of traditional web editors like Atom, compares them with VS Code, explores Figma’s JavaScript‑based plugin system and its sandbox mechanisms—including Realm, Duktape, and Web Workers—while discussing broader JavaScript sandboxing techniques and CSS isolation strategies for modern front‑end applications.

Taobao Frontend Technology
Taobao Frontend Technology
Taobao Frontend Technology
Why Atom Fell and How Figma’s Plugin Sandbox Redefines Web Editor Architecture

Modern Text Editor Rise and Fall

Since the maturation of web technologies, large console projects such as Alibaba Cloud and Tencent Cloud have become increasingly complex, making maintenance, release, and cost control difficult. In this context, micro‑frontends emerged, but the article uses them only as a hook to discuss broader web‑application challenges.

Modern Text Editor Decline

After Microsoft acquired GitHub in 2018, Atom became a frequent target of jokes. VS Code has become the default editor for front‑end engineers, outperforming Atom in performance (both are Electron‑based) and plugin ecosystem—VS Code surpassed 10 000 plugins while Atom remains around 8 000. The LSP/DAP protocols further cement VS Code’s dominance.

Discussions on Zhihu highlight Atom’s slowness, largely caused by its overly permissive plugin architecture, which exposes UI components (FileTree, Tab bar, Settings) to third‑party plugins, creating security and performance issues. VS Code’s plugins run in Node.js with a much more closed UI API.

Because VS Code’s UI is relatively closed, developers sometimes resort to forcibly modifying VS Code’s installation files (e.g., the VS Code Background plugin changes CSS, while the VSC Netease Music plugin replaces the missing FFmpeg library in the Electron bundle), which can break the editor and require reinstallations.

Beyond Editors – Figma

Figma is an online collaborative UI design tool that recently launched its plugin system. Plugins are built with JavaScript/TypeScript and Webpack, lowering the development barrier. Over 300 plugins have been created, ranging from graphic resources to 3D model import.

<code>.</code><code>├── README.md</code><code>├── figma.d.ts</code><code>├── manifest.json</code><code>├── package-lock.json</code><code>├── package.json</code><code>├── src</code><code>│   ├── code.ts</code><code>│   ├── logo.svg</code><code>│   ├── ui.css</code><code>│   ├── ui.html</code><code>│   └── ui.tsx</code><code>├── tsconfig.json</code><code>└── webpack.config.js</code>

The

manifest.json

defines the plugin entry points:

<code>{</code><code>  "name": "React Sample",</code><code>  "id": "738168449509241862",</code><code>  "api": "1.0.0",</code><code>  "main": "dist/code.js",</code><code>  "ui": "dist/ui.html"</code><code>}</code>

The

main

part runs the plugin logic, while

ui

is an HTML fragment rendered in an iframe, preventing CSS leakage. When a plugin is installed, its JavaScript runs inside a sandboxed iframe, and the UI iframe isolates styles from the host application.

How Figma’s Plugin System Works

Figma creates a minimal JavaScript execution environment for the

main

entry that runs on the browser’s main thread, restricting access to global browser APIs. The UI part consists of a single HTML snippet rendered in a popup.

Initially Figma tried an iframe‑based sandbox, but communication via

postMessage

required all API calls to be async, which was unfriendly to designers and introduced performance overhead for large documents. To improve security while staying on the main thread, Figma adopted a stage‑2 Realm API draft that creates a separate global object for plugins.

<code>let g = window; // outer global</code><code>let r = new Realm(); // root realm</code><code></code><code>let f = r.evaluate("(function() { return 17 })");</code><code>f() === 17 // true</code><code>Reflect.getPrototypeOf(f) === g.Function.prototype // false</code><code>Reflect.getPrototypeOf(f) === r.globalThis.Function.prototype // true</code>

Realm can also be implemented with

with

and

Proxy

, a pattern popular in the community.

<code>const whitelist = {</code><code>  window: undefined,</code><code>  document: undefined,</code><code>  console: window.console,</code><code>};</code><code></code><code>const scopeProxy = new Proxy(whitelist, {</code><code>  get(target, prop) {</code><code>    if (prop in target) {</code><code>      return target[prop];</code><code>    }</code><code>    return undefined;</code><code>  }</code><code>});</code><code></code><code>with (scopeProxy) {</code><code>  eval("console.log(document.write)"); // Cannot read property 'write' of undefined!</code><code>  eval("console.log('hello')"); // hello</code><code>}</code>

To safely expose whitelisted APIs, each API can be wrapped inside the Realm context, preventing prototype‑chain leaks.

<code>const safeLogFactory = realm.evaluate(`</code><code>(function safeLogFactory(unsafeLog) {</code><code>  return function safeLog(...args) {</code><code>    unsafeLog(...args);</code><code>  }</code><code>})`);</code><code></code><code>const safeLog = safeLogFactory(console.log);</code>

Figma also embeds the Duktape JavaScript engine (a C++‑implemented interpreter) compiled to WebAssembly. Plugin code runs inside Duktape, allowing a controlled set of APIs without exposing the host’s global objects.

Figma retains the original iframe option, letting plugins create their own iframes and communicate with the sandbox via

postMessage

.

Key Requirements for Plugin Sandboxes

JavaScript code sandbox that gives the host application control over third‑party code.

Strong CSS isolation to prevent style leakage.

JavaScript Sandbox

Common approaches include:

Iframe sandbox with the

sandbox

attribute.

Using language features such as

with

,

Realm

, or

Proxy

to mask global objects and enforce a whitelist.

Embedding a separate JavaScript engine (e.g., Duktape) compiled to WebAssembly.

Running code in Web Workers and proxying DOM APIs (e.g., worker‑dom, preact‑worker‑demo).

These solutions each have trade‑offs in performance, security, and developer ergonomics.

CSS Scope

Isolation techniques include:

Rendering plugin UI in an iframe (full style isolation at the cost of performance).

CSS Modules that hash class names during build.

Web Components with Shadow DOM, which prevents external styles from affecting the plugin and vice‑versa.

Conclusion

This article listed the challenges faced by large‑scale web applications such as editors and design tools when introducing plugin architectures, and surveyed community solutions like iframe sandboxing, Realm, Web Workers, Duktape, and Shadow DOM. Each approach has its own strengths and weaknesses, and as web applications grow more complex, standardized plugin mechanisms will become increasingly important.

frontendplugin architecturefigmaweb developmentjavascript sandboxeditor comparison
Taobao Frontend Technology
Written by

Taobao Frontend Technology

The frontend landscape is constantly evolving, with rapid innovations across familiar languages. Like us, your understanding of the frontend is continually refreshed. Join us on Taobao, a vibrant, all‑encompassing platform, to uncover limitless potential.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.