Friday, June 21, 2024

ECMAScript module equivalent of CommonJS module usage: const x = require('myModule')(options);

A common, concise idiom of CommonJS modules that export factory functions is:

const instance = import('myModule')(myOptions);

This is concise and minimizes consumption of the name space.

With ECMAScript modules and the import declaration, the same or similar is not possible because the import declaration is not an expression that returns a value and it must be at the top level of the module: they cannot be within a block or function, including an immediately invoked function expression (IIFE).

Assuming the module in question exports a factory function as its default export, then the nearest equivalent would be something like:

import myFactory from 'myModule';

const instance = myFactory(myOptions);

If a named export the something like:

import { exportName as myFactory } from 'myModule';

const instance = myFactory(myOptions);

This is a little less concise: two lines of code instead of one, and an additional name consumed in the module name space. But otherwise gives the same result.

Something more equivalent is possible with the dynamic import keyword. This is function-like and can occur within a function, including an IIFE.

const instance = (await import('myModule')).default(myOptions);

This is only a little less concise than the CommonJS syntax. Similar construct is possible with named exports, by simply replacing 'default' with the name of the named export.

Using dynamic import keyword instead of the import declaration, one gives up the static analysis made possible by the import declaration, and there may be other benefits of the declaration over the keyword.

Sunday, June 16, 2024

JavaScript testing with Tape

 I mostly use tape for testing my JavaScript packages. Today I was updating dependencies and update of tape was among them.

The link from npmjs.com to GitHub was broken, yielding a 404 page. So I logged an issue and within a few minutes the links were fixed.

So, the GitHub repository for tape has moved to https://github.com/tape-testing/tape but all is well. Jordan is still actively maintaining the package.

It remains my favourite test package for JavaScript.

First release from the current repository was Nov 26, 2012. Well over a decade ago. It is good to see that it is still maintained and with attention to backwards compatibility.

Thus far, all my packages are CommonJS.

For linting, I use eslint with configuration @ig3/eslint-config-entrain

For coverage, I use c8.

For test runner I use multi-tape. Pending an update of multi-tape dependencies, I have published @ig3/multi-tape.

Typical test script is: "eslint . && multi-tape test/*.js"

@ig3/eslint-config-entrain is based on neostandard and eslint version 9. Typical eslint.config.js is:

 

'use strict';

const eslintConfigEntrain = require('@ig3/eslint-config-entrain');

module.exports = [
  ...eslintConfigEntrain,
];

Or sometimes something like:

'use strict';

const eslintConfigEntrain = require('@ig3/eslint-config-entrain');

module.exports = [
  ...eslintConfigEntrain,
  {
    ignores: ['public/js/**'],
  },
];

Setup is:

$ npm install -D @ig3/eslint-config-entrain c8 tape multi-tape

 Change the test script to:

"eslint . && c8 multi-tape test/*.js"

 And create eslint.config.js as above.

 

Tuesday, March 26, 2024

Thunar sort order

For many years I have run Debian with xfce4 desktop.

I have always hated the way Thunar sorts files by name. The developers would say it is not a Thunar issue but rather a Gtk issue. But I really don't care. I hate it whatever the root cause. It is made worse by the fact that there is absolutely no configuration possible other than collation options (LC_ALL and LC_COLLATE) but these don't fix the problem.

So, today I dug in to fix it.

I tried several other file browsers, but they all have slight variations of the same nonsense and I didn't find any that sort file names sensibly (e.g. like ls does).

There are many bug reports against Thunar, Nautilus and several others, reporting that available sorting options are not satisfying.

There are so many, it makes me wonder why there isn't a simple plug-in option, to separate sorting from other aspects of the file browser, allowing people to easily develop the sorting algorithm they need. Gtk could provide this but so could the various file browsers. It seems all I investigated in any detail delegate sorting to Gtk and refuse to add any features to work around its limitations and stupidity (i.e. 'natural' sorting).

I read many bug reports and posts, with the conclusion that there is no configuration option to fix it.

I tried building Thunar from source, thinking I would hack on it to fix the sorting or add an interface to an external sort implementation, but there were too many dependencies and I got tired of installing them.

But in reading through all the bug reports, I came across GlibSortFileNameHackLibrary so I gave it a try. I cloned the repo and tried to build it.

On Debian Bookworm, despite having built various other packages, I still had to install libglib2.0-dev:

$ sudo apt install libglib2.0-dev

Then:

$ make all

This terminates with an error compiling test.c, but that's only a test program. The library builds OK.

Then, from a command window:

$ thunar -q; LD_PRELOAD=./glibSortFileNameHack.so thunar

This launched a new Thunar instance and files were sorted sensibly (as opposed to the Gtk idea of 'naturally'). It was wonderful! Finally, I can find files in Thunar without wasting time scrolling up and down to try to figure out where they have been misplaced.

I couldn't find trace of a Thunar background process running after I logged in (i.e. ps -ef showed nothing with 'thunar' in the command line). So I guessed there isn't one and didn't worry about why.

I use Whisker menu but don't really know how to configure it. When I tried prefixing the command for the file browser launcher with LD_PRELOAD=/path/to/glibSortFileNameHack.so, I got an error that LD_PRELOAD isn't executable. 

So, I made a bash script:

#!/bin/bash
LD_PRELOAD=/home/ian/lib/glibSortFileNameHack.so thunar

And I changed the launcher to run the script.

This seems to work fine. At least, I haven't noticed any problems yet.

Now every Thunar instance sorts files sensibly.

Kudos to Alexandre Richonnier for publishing GlibSortFileNameHackLibrary. It hasn't been updated in 9 years, but it still works a treat!

Labels