Skip to content

loader-returned sources always-cached when imported with assert { type: 'json' } #49724

Closed
@iambumblehead

Description

@iambumblehead

Version

v20.6.1

Platform

Linux duck 6.5.2-arch1-1 #1 SMP PREEMPT_DYNAMIC Wed, 06 Sep 2023 21:01:01 +0000 x86_64 GNU/Linux

Subsystem

No response

What steps will reproduce the bug?

  1. clone this reproduction repo https://github.com/iambumblehead/nodejs-import-attributes-repro
  2. cd into the cloned directory and use npm test

How often does it reproduce? Is there a required condition?

the issue is reproduced every time

What is the expected behavior? Why is that the expected behavior?

when json is imported with "assert" this way,

import JSONobj from './example.json' assert { type: 'json' }

it should be possible for the loader to return dynamic, un-cached values to the importing file, following current behaviour around normally imported modules eg import JSobj from './example.js'

What do you see instead?

Instead, when "assert" is used to import a json file, cached results are returned to the importing file, irregardless of what source value is returned by the loader. The example test attached below fails, but should pass.


import test from 'node:test'
import assert from 'node:assert'
import module from 'node:module'

module.register('./loader.js', {
  parentURL: import.meta.url
})

// _importing.js_
// ```
// import JSobj from './example.js'
// import JSONobj from './example.json' assert { type: 'json' }
// 
// export { JSobj, JSONobj }
// ```

// for "module" type modules, the loader can return different versions
// of that "module" source to multiple import contexts (desired behaviour),
test('loader can return fresh source, js', async () => {
  const importOne = await import('./importing.js?t=1')
  const importTwo = await import('./importing.js?t=2')

  assert.deepEqual(importOne.JSobj, { example: 'js-1' })
  assert.deepEqual(importTwo.JSobj, { example: 'js-2' })
})

// for "json" type modules, the loader cannot return different versions
// of that "json" source to different import contexts and, instead, the
// first version is seemingly cache-returned to any subsequently-importing 
// context (not-desired behaviour)
test('loader cannot return fresh source, json', async () => {
  const importThree = await import('./importing.js?t=3')
  const importFour = await import('./importing.js?t=4')

  assert.deepEqual(importThree.JSONobj, { example: 'json-3' })
  assert.deepEqual(importFour.JSONobj, { example: 'json-4' })
  // ^^ fails: importFour.JSONobj == `{ example: 'json-3' }`
})

Additional information

related link about import attributes https://github.com/tc39/proposal-import-attributes#history

2023-03: The proposal is renamed to Import attributes and moves back to Stage 3 (TODO: notes, slides). The restriction on the cache key is completely removed, and the keyword changes back from assert to with: import { x } from "./mod" with { type: "json" };. For compatibility with existing implementations, the assert keyword will still be supported until it's safe to remove it, if it will ever be.

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmed-bugIssues with confirmed bugs.loadersIssues and PRs related to ES module loaders

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions