<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>JavaScript</title>
        <link>https://onp4.com/@vadim/~js</link>
        <description>JavaScript</description>
        <lastBuildDate>Thu, 14 May 2026 08:23:59 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>P4 - P for posting</generator>
        <language>en</language>
        <copyright>Copyright, P4</copyright>
        <item>
            <link>https://onp4.com/@vadim/p/ut31o77l9x</link>
            <guid>https://onp4.com/@vadim/p/ut31o77l9x</guid>
            <pubDate>Sun, 19 Oct 2025 22:38:04 GMT</pubDate>
            <content:encoded><![CDATA[Modern eval

```js
const js = `console.log('Hello everyone!');`;
const encodedJs = encodeURIComponent(js);
const dataUri = 'data:text/javascript,'+ encodedJs;
import(dataUri);
```]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/0ic41fxln8</link>
            <guid>https://onp4.com/@vadim/p/0ic41fxln8</guid>
            <pubDate>Fri, 29 Aug 2025 09:39:27 GMT</pubDate>
            <content:encoded><![CDATA[Claude Sonnet 4.0]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/tqziv1amkg</link>
            <guid>https://onp4.com/@vadim/p/tqziv1amkg</guid>
            <pubDate>Wed, 30 Jul 2025 08:41:44 GMT</pubDate>
            <content:encoded><![CDATA[How to add code block in constructor before `super()` call? Wrap it in IIFE:

```ts
class A extends B {
  constructor () {
    super((() => {
       // Code block ...
    })());
  }
}
```]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/97awamfsgw</link>
            <guid>https://onp4.com/@vadim/p/97awamfsgw</guid>
            <pubDate>Fri, 11 Jul 2025 18:36:25 GMT</pubDate>
            <content:encoded><![CDATA[On TypeScript object types:

- `{}` is a type which specifies that the value supports property access dot `.` operator. Like `(123 as {}).toString()`.
- `object` (with lower case) specifies any non primitive value, such as object, array, function, etc.
- `Object` (with upper case) specifies the type of the JavaScript built-in `Object` value.]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/01h774oe2i</link>
            <guid>https://onp4.com/@vadim/p/01h774oe2i</guid>
            <pubDate>Mon, 16 Jun 2025 09:53:36 GMT</pubDate>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/swwz2wfdj3</link>
            <guid>https://onp4.com/@vadim/p/swwz2wfdj3</guid>
            <pubDate>Wed, 19 Mar 2025 18:32:08 GMT</pubDate>
            <content:encoded><![CDATA[There has not been that many exciting new features in JavaScript last few years, but most recently it has changed. The FileSystem API in browser now allows website to access user's native file system. The Observable API will finally bring `Observable` natively into JavaScript, which is by far the best state management solution for UI's and handy for many other things. And most importantly, the *struct* API will be a huge game changer, the struct API will allow to create C-like structs in JavaScript, which will also be sharable across threads. This will enable effecting shared-memory parallel programming in JavaScript, which was not possible so far and has forced so many projects and developers pick Go or Rust, instead.]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/lly1bbudbd</link>
            <guid>https://onp4.com/@vadim/p/lly1bbudbd</guid>
            <pubDate>Sat, 16 Nov 2024 21:52:29 GMT</pubDate>
            <content:encoded><![CDATA[Debugging HTML/CSS of 3rd party website:

```javascript
setInterval(() =>
  [...document.querySelectorAll('*')]
    .forEach(e => e.style.outline = '1px dotted red')
  , 1000)
```
]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/20266uv7pf</link>
            <guid>https://onp4.com/@vadim/p/20266uv7pf</guid>
            <pubDate>Wed, 23 Oct 2024 13:25:57 GMT</pubDate>
            <content:encoded><![CDATA[Scopes in classes:

```js
class A {
  {
    let cnt = 0;
    
    getCnt() {
      return cnt;
    }
    
    setCnt(val) {
      cnt = val;
    }
  }
}
```

Would be equivalent to scopes in prototype-based inheritance:

```js
function A() {}

{
  let cnt = 0;

  A.prototype.getCnt = function() {
    return cnt;
  };
  
  A.prototype.setCnt = function(val) {
    cnt = val;
  };
}
```
]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/kl0ses006y</link>
            <guid>https://onp4.com/@vadim/p/kl0ses006y</guid>
            <pubDate>Tue, 08 Oct 2024 18:07:26 GMT</pubDate>
            <content:encoded><![CDATA[Publish to NPM any PR:

https://github.com/stackblitz-labs/pkg.pr.new
]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/rnp76a72lm</link>
            <guid>https://onp4.com/@vadim/p/rnp76a72lm</guid>
            <pubDate>Fri, 23 Aug 2024 13:20:23 GMT</pubDate>
            <content:encoded><![CDATA[# Zero-overhead Async/Await

[Callbacks are significantly faster](https://hackernoon.com/nodejs-48x-faster-if-you-go-back-to-callbacks) than `Promise`s in Node.js. How can we get the performance of callbacks while benefiting from the `Promise` and async/await syntax?

JavaScript could introduce *CallbackAwaitExpression*, which syntactically would look very much like the existing *AwaitExpression* but it would operate on top of callbacks instead of promises.

The callbacks would have the following form:

```ts
type Callback<V, E = unknown> =
  | (error: E) => void;
  | (error: void, value: V) => void;
```

The new *CallbackAwaitExpression* would have an extra **identifier** parameter of type `Callback`, syntactically in between the `await` keyword and the expression being awaited, for example, note the `cb` identifier:

```js
await cb fs.readFile('myfile.txt', 'utf-8', cb);
```

Likewise, the async function syntax would also be extended to allow *AsyncCallbackFunction* type. There as well, the syntax would allow a single callback identifier:

```js
async cb function(args, cb) {
  // ...
}
```

Putting this all together, this would allow to write async/await syntax-powered code, while benefiting from the performance of callbacks. It would allow to write code like this:

```js
async _ function getFileData(filename, _) {
  try {
    const data = await _ fs.readFile('myfile.txt', 'utf-8', _);
    return 'mydata: ' + data;
  } catch (error) {
    if (!!error && typeof error === 'object' && error.code === 'ENOENT') {
      throw new Error('not found');
    }
    throw error;
  }
}
```

The code would be equivalent to the existing JavaScript:

```js
function getFileData(filename, callback) {
  const onCatch = (error) => {
    if (!!error && typeof error === 'object' && error.code === 'ENOENT') {
      callback(new Error('not found'));
    } else {
      callback(error);
    }
  };
  try {
    fs.readFile('myfile.txt', 'utf-8', (err, data) => {
      if (err) {
        onCatch(err);
      } else {
        try {
          callback(null, 'mydata: ' + data);
        } catch (error) {
          onCatch(error);
        }
      }
    });
  } catch (error) {
    onCatch(error);
  }
}
```

Here is how the above code can look like using the existing async/await syntax. The code is almost equivalent to the *async/await callback* proposal, but less performant due to `Promise` usage.

```js
async function getFileDataAsync(filename) {
    try {
    const data = await promisify(fs.readFile)('myfile.txt', 'utf-8');
    return 'mydata: ' + data;
  } catch (error) {
    if (!!error && typeof error === 'object' && error.code === 'ENOENT') {
      throw new Error('not found');
    }
    throw error;
  }
}
```

Or, equivalently, the good old `promisify` utility could convert our callback powered function to this `Promise` powered one:

```js
const getFileDataAsync = promisify(getFileData);
```

## Sugar Syntax

When awaiting one can explicitly specify the callback identifier and explicitly use it as an argument:

```js
await myCallback fs.readFile('a.txt', myCallback)
```

If the await identifier `myCallback` is not used, it is automatically inserted in the function call as the last argument:

```js
await _ fs.readFile('a.txt')
```

When defining an async callback function, the above text proposed to explicitly specify the callback identifier, like so:

```js
async myCallback function getData(filename, myCallback) {}
```

Instead it can be reduced by simply using the `async` keyword once, in place of some argument:

```js
function getData(filename, async) {}
```

The above syntax modifications reduce the example `getFileData` function to the following:

```js
function getFileData(filename, async) {
  try {
    const data = await _ fs.readFile('myfile.txt', 'utf-8');
    return 'mydata: ' + data;
  } catch (error) {
    // ...
  }
}
```

## Using with TypeScript

From the point of view of TypeScript, to define a new async callback function, one can simply use the `CallbackType`:

```ts
type GetFileData = (filename: string, callback: Callback<string>) => void;
```

Alternatively, the `async` type shorthand could be introduced, to make it more explicit:

```ts
type GetFileData = (filename: string, async<string>) => void;
```

Maybe it could be called `callback`:

```ts
type GetFileData = (filename: string, callback<string>) => void;
```
]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/gqrahqqvms</link>
            <guid>https://onp4.com/@vadim/p/gqrahqqvms</guid>
            <pubDate>Sun, 18 Aug 2024 08:51:39 GMT</pubDate>
            <content:encoded><![CDATA[[Callbacks are significantly faster](https://hackernoon.com/nodejs-48x-faster-if-you-go-back-to-callbacks) than `Promise`s in Node.js. How can we get the performance of callbacks while benefiting from the `Promise` and async/await syntax?

JavaScript could introduce *CallbackAwaitExpression*, which syntactically would look very much like the existing *AwaitExpression* but it would operate on top of callbacks instead of promises.

The callbacks would have the following form:

```ts
type Callback<V, E = unknown> = ErrorCallback<E> | ValueCallback<V>;
type ErrorCallback<E = unknown> = (error: E) => void;
type ValueCallback<V> = (error: void, value: V) => void;
```

The new *CallbackAwaitExpression* would have an extra **identifier** parameter of type `Callback`, syntactically in between the `await` keyword and the expression being awaited, for example, note the `cb` identifier:

```js
await cb fs.readFile('myfile.txt', 'utf-8', cb);
```

Likewise, the async function syntax would also be extended allow *AsyncCallbackFunction* type. There as well, the syntax would allow a single callback identifier:

```js
async cb function(args, cb) {
  // ...
}
```

Putting this all together, this would allow to write async/await syntax-powered code, while benefiting from the performance of callbacks. It would allow to write functions like:

```js
async _ function getFileData(filename, _) {
  try {
    const data = await _ fs.readFile('myfile.txt', 'utf-8', _);
    return 'mydata: ' + data;
  } catch (error) {
    if (!!error && typeof error === 'object' && error.code === 'ENOENT') {
      throw new Error('not found');
    }
    throw error;
  }
}
```

The code would be equivalent to the existing JavaScript:

```js
function getFileData(filename, callback) {
  const onCatch = (error) => {
    if (!!error && typeof error === 'object' && error.code === 'ENOENT') {
      callback(new Error('not found'));
    }
    callback(error);
  };
  try {
    fs.readFile('myfile.txt', 'utf-8', (err, data) => {
      if (err) return onCatch(err);
      callback(null, 'mydata: ' + data);
    });
  } catch (error) {
    onCatch(error);
  }
}
```

Here is how the above code can look like using the existing async/await syntax. The code is almost equivalent to the *async/await callback* proposal, but less performant due to `Promise` usage.

```js
async function getFileData(filename) {
    try {
    const data = await promisify(fs.readFile('myfile.txt', 'utf-8'));
    return 'mydata: ' + data;
  } catch (error) {
    if (!!error && typeof error === 'object' && error.code === 'ENOENT') {
      throw new Error('not found');
    }
    throw error;
  }
}
```]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/857h4ap4ls</link>
            <guid>https://onp4.com/@vadim/p/857h4ap4ls</guid>
            <pubDate>Thu, 08 Aug 2024 19:07:09 GMT</pubDate>
            <content:encoded><![CDATA[https://blog.isquaredsoftware.com/2021/01/context-redux-differences/]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/ehvyvq5g6w</link>
            <guid>https://onp4.com/@vadim/p/ehvyvq5g6w</guid>
            <pubDate>Sun, 16 Jun 2024 22:14:34 GMT</pubDate>
            <content:encoded><![CDATA[Parser CST-to-AST node transformation using JSON Expressions:

```js
['set', 'type', 'Number', {}]

['apply', {
  type: 'Number',
  pos: ['$', '/csr/pos'],
  end: ['$', '/csr/end'],
  value: ['num', '/csr/text'],
}, {}]

['apply', {
  value: ['num', '/csr/text'],
}, ['$', '/ast']]

['assign', ['$', '/ast'], {
  value: ['num', '/csr/text'],
}]

['extend', ['$', '/ast'], {
  '/value': ['num', ['$', '/csr/text']],
}]


['apply', ['$', '/ast'],
  '/value', ['num', ['$', '/csr/text']],
  '/isFloat', false,
]

['add', ['$', '/ast'],
  '/value', ['num', ['$', '/csr/text']],
  '/isFloat', false,
]

['$', '/ast/children/0']

['o.set', {},
  'value', ['num', ['$', '/csr/text']],
  'location', ['o.set', {},
    'start', ['$', '/csr/pos'],
    'length', ['-', ['$', '/csr/end'], ['$', '/csr/pos']]
  ],
]
```]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/0pshojgkpq</link>
            <guid>https://onp4.com/@vadim/p/0pshojgkpq</guid>
            <pubDate>Fri, 14 Jun 2024 12:02:16 GMT</pubDate>
            <content:encoded><![CDATA[*Internalized* strings in V8 runtime are an immutable string collection in a common shared pool. Normally those are the strings known at the build time.]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/eaw42510se</link>
            <guid>https://onp4.com/@vadim/p/eaw42510se</guid>
            <pubDate>Fri, 14 Jun 2024 12:01:27 GMT</pubDate>
            <content:encoded><![CDATA[You can internalize stings in V8 using `eval`:

```js
s = eval(JSON.stringify(s));
```]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/vxuibqku5g</link>
            <guid>https://onp4.com/@vadim/p/vxuibqku5g</guid>
            <pubDate>Mon, 13 May 2024 22:18:54 GMT</pubDate>
            <content:encoded><![CDATA[https://www.youtube.com/watch?v=U6s2pdxebSo]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/dqnx8upmvk</link>
            <guid>https://onp4.com/@vadim/p/dqnx8upmvk</guid>
            <pubDate>Mon, 13 May 2024 22:18:43 GMT</pubDate>
            <content:encoded><![CDATA[https://www.youtube.com/watch?v=5AqbCQuK0gM]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/7ie0x9pzmm</link>
            <guid>https://onp4.com/@vadim/p/7ie0x9pzmm</guid>
            <pubDate>Sat, 11 May 2024 10:48:57 GMT</pubDate>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/t9gm6knczt</link>
            <guid>https://onp4.com/@vadim/p/t9gm6knczt</guid>
            <pubDate>Wed, 03 Apr 2024 11:41:41 GMT</pubDate>
            <content:encoded><![CDATA[To download audio `.mp3` from a page:

```js
[...document.getElementsByTagName('AUDIO')].map(a => a.src)
```]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/af3n8t9yk6</link>
            <guid>https://onp4.com/@vadim/p/af3n8t9yk6</guid>
            <pubDate>Mon, 04 Mar 2024 14:44:12 GMT</pubDate>
            <content:encoded><![CDATA[jQuery is still in development:

https://blog.jquery.com/2024/02/06/jquery-4-0-0-beta/]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/gi6f3adu0v</link>
            <guid>https://onp4.com/@vadim/p/gi6f3adu0v</guid>
            <pubDate>Sun, 03 Mar 2024 19:51:28 GMT</pubDate>
            <content:encoded><![CDATA[Browser on-disk storage APIs:

- `document.cookie` --- a "cookie" is the oldest persistence mechanism, by simply updating the [`document.cookie`](https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie) property the browser will synchronously update the value.
- `localStorage` --- synchronously stores a key-value pair on the disk, historically every write to disk used to be blocking, now browsers seem to optimize this.
- [WebSQL](https://en.wikipedia.org/wiki/Web_SQL_Database) --- a deprecated SQL standard for the browser.
- [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) --- the current "database API" of the browsers. It used to have asynchronous and synchronous variants, now the synchronous variant is deprecated and works only in worker threads.
- [`CacheStorage`](https://developer.mozilla.org/en-US/docs/Web/API/CacheStorage) --- key/value storage of service workers.
- [OPFS](https://developer.mozilla.org/en-US/docs/Web/API/File_System_API/Origin_private_file_system) --- a virtual file system implemented as [FSA](https://developer.mozilla.org/en-US/docs/Web/API/File_System_API). It exposes only asynchronous API from the main threads, but synchronous reads and writes are available from the worker threads. Using the `Atomic.wait` trick, it is possible to achieve synchronous reads and writes from the main thread, too.
- [FSA (File System Access)](https://wicg.github.io/file-system-access/) --- File System Access, it is implemented using the FSA (File System API), just like, OPFS, but it gives access to real user files on their device. Requires user permission to access a file or a folder, however, the permission object can be stored in IndexDB, which is accessible after browser reload. ]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/fmuxmxaysp</link>
            <guid>https://onp4.com/@vadim/p/fmuxmxaysp</guid>
            <pubDate>Wed, 16 Aug 2023 21:59:56 GMT</pubDate>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/elnqp3roc7</link>
            <guid>https://onp4.com/@vadim/p/elnqp3roc7</guid>
            <pubDate>Sat, 08 Jul 2023 22:22:29 GMT</pubDate>
            <content:encoded><![CDATA[Have Node's implementation of ES modules split the JavaScript ecosystem in two? Similar to how Python ecosystem was split into Python 2 vs Python 3.]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/axuothg11o</link>
            <guid>https://onp4.com/@vadim/p/axuothg11o</guid>
            <pubDate>Fri, 07 Jul 2023 07:32:57 GMT</pubDate>
            <content:encoded><![CDATA[https://www.aleksandrhovhannisyan.com/blog/interactive-guide-to-javascript-events/]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/nl9jcosg43</link>
            <guid>https://onp4.com/@vadim/p/nl9jcosg43</guid>
            <pubDate>Tue, 13 Jun 2023 11:45:15 GMT</pubDate>
            <content:encoded><![CDATA["The default programming language."]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/tjto7dj6jc</link>
            <guid>https://onp4.com/@vadim/p/tjto7dj6jc</guid>
            <pubDate>Mon, 24 Apr 2023 20:07:29 GMT</pubDate>
            <content:encoded><![CDATA[Fast empty object

```js
const NullObject = function NullObject() {};
NullObject.prototype = Object.create(null);
```
]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/dlpkxvvt3h</link>
            <guid>https://onp4.com/@vadim/p/dlpkxvvt3h</guid>
            <pubDate>Wed, 19 Apr 2023 21:48:11 GMT</pubDate>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/6hhelfqdaw</link>
            <guid>https://onp4.com/@vadim/p/6hhelfqdaw</guid>
            <pubDate>Wed, 19 Apr 2023 19:20:44 GMT</pubDate>
            <content:encoded><![CDATA[Computed property `"constructor"` is not picked up as constructor:

```js
class A {
    get ['constructor'] () {
        return 'foo';
    }
}
```]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/nvppvgm38b</link>
            <guid>https://onp4.com/@vadim/p/nvppvgm38b</guid>
            <pubDate>Fri, 14 Apr 2023 15:57:29 GMT</pubDate>
            <content:encoded><![CDATA[https://blog.logrocket.com/snapshot-flags-node-js-v18-8/]]></content:encoded>
        </item>
        <item>
            <link>https://onp4.com/@vadim/p/6hr87w1xdr</link>
            <guid>https://onp4.com/@vadim/p/6hr87w1xdr</guid>
            <pubDate>Sun, 09 Apr 2023 21:34:44 GMT</pubDate>
            <content:encoded><![CDATA[Create an array of given size:

```js
Array.from({length: 5}, () => 0);
```]]></content:encoded>
        </item>
    </channel>
</rss>