File tree Expand file tree Collapse file tree 5 files changed +38
-32
lines changed Expand file tree Collapse file tree 5 files changed +38
-32
lines changed Original file line number Diff line number Diff line change 11'use strict' ;
22const {
33 ObjectDefineProperties,
4- Proxy,
54} = primordials ;
65const { getOptionValue } = require ( 'internal/options' ) ;
6+ const { lazyDOMException } = require ( 'internal/util' ) ;
77const { kConstructorKey, Storage } = internalBinding ( 'webstorage' ) ;
88const { getValidatedPath } = require ( 'internal/fs/utils' ) ;
99const kInMemoryPath = ':memory:' ;
@@ -23,32 +23,16 @@ ObjectDefineProperties(module.exports, {
2323 if ( lazyLocalStorage === undefined ) {
2424 const location = getOptionValue ( '--localstorage-file' ) ;
2525
26+ // HTML specification: If [the result of obtaining a local storage map] is failure,
27+ // then throw a "SecurityError" DOMException.
2628 if ( location === '' ) {
27- let warningEmitted = false ;
28- const handler = {
29- __proto__ : null ,
30- get ( target , prop ) {
31- if ( ! warningEmitted ) {
32- process . emitWarning ( '`--localstorage-file` was provided without a valid path' ) ;
33- warningEmitted = true ;
34- }
35-
36- return undefined ;
37- } ,
38- set ( target , prop , value ) {
39- if ( ! warningEmitted ) {
40- process . emitWarning ( '`--localstorage-file` was provided without a valid path' ) ;
41- warningEmitted = true ;
42- }
43-
44- return false ;
45- } ,
46- } ;
47-
48- lazyLocalStorage = new Proxy ( { } , handler ) ;
49- } else {
50- lazyLocalStorage = new Storage ( kConstructorKey , getValidatedPath ( location ) ) ;
29+ throw lazyDOMException (
30+ 'Unable to initialize local storage without a `--localstorage-file` path' ,
31+ 'SecurityError' ,
32+ ) ;
5133 }
34+
35+ lazyLocalStorage = new Storage ( kConstructorKey , getValidatedPath ( location ) ) ;
5236 }
5337
5438 return lazyLocalStorage ;
Original file line number Diff line number Diff line change @@ -59,6 +59,14 @@ const hasSQLite = Boolean(process.versions.sqlite);
5959
6060const hasQuic = hasCrypto && ! ! process . features . quic ;
6161
62+ const hasLocalStorage = ( ( ) => {
63+ try {
64+ return hasSQLite && globalThis . localStorage !== undefined ;
65+ } catch {
66+ return false ;
67+ }
68+ } ) ( ) ;
69+
6270/**
6371 * Parse test metadata from the specified file.
6472 * @param {string } filename - The name of the file to parse.
@@ -350,14 +358,17 @@ const knownGlobals = new Set([
350358 'CompressionStream' ,
351359 'DecompressionStream' ,
352360 'Storage' ,
353- 'localStorage' ,
354361 'sessionStorage' ,
355362] . forEach ( ( i ) => {
356363 if ( globalThis [ i ] !== undefined ) {
357364 knownGlobals . add ( globalThis [ i ] ) ;
358365 }
359366} ) ;
360367
368+ if ( hasLocalStorage ) {
369+ knownGlobals . add ( globalThis . localStorage ) ;
370+ }
371+
361372if ( hasCrypto ) {
362373 knownGlobals . add ( globalThis . crypto ) ;
363374 knownGlobals . add ( globalThis . Crypto ) ;
@@ -389,6 +400,11 @@ if (process.env.NODE_TEST_KNOWN_GLOBALS !== '0') {
389400 if ( val === 'crypto' && ! hasCrypto ) {
390401 continue ;
391402 }
403+ // globalThis.localStorage is a getter that throws if Node.js was
404+ // executed without a --localstorage-file path.
405+ if ( val === 'localStorage' && ! hasLocalStorage ) {
406+ continue ;
407+ }
392408 if ( ! knownGlobals . has ( globalThis [ val ] ) ) {
393409 leaked . push ( val ) ;
394410 }
@@ -933,6 +949,7 @@ const common = {
933949 hasQuic,
934950 hasInspector,
935951 hasSQLite,
952+ hasLocalStorage,
936953 invalidArgTypeHelper,
937954 isAlive,
938955 isASan,
Original file line number Diff line number Diff line change @@ -19,6 +19,7 @@ const {
1919 hasQuic,
2020 hasInspector,
2121 hasSQLite,
22+ hasLocalStorage,
2223 hasIntl,
2324 hasIPv6,
2425 isAIX,
@@ -71,6 +72,7 @@ export {
7172 hasQuic ,
7273 hasInspector ,
7374 hasSQLite ,
75+ hasLocalStorage ,
7476 hasIntl ,
7577 hasIPv6 ,
7678 isAIX ,
Original file line number Diff line number Diff line change 11'use strict' ;
2- const { hasCrypto } = require ( '../common' ) ;
2+ const { hasCrypto, hasLocalStorage } = require ( '../common' ) ;
33const { test } = require ( 'node:test' ) ;
44const assert = require ( 'assert' ) ;
55
@@ -12,7 +12,7 @@ const assert = require('assert');
1212if ( process . stdout . isTTY )
1313 process . env . NODE_DISABLE_COLORS = '1' ;
1414
15- test ( '' , { skip : ! hasCrypto } , ( ) => {
15+ test ( { skip : ! hasCrypto || ! hasLocalStorage } , ( ) => {
1616 // See https://github.com/nodejs/node/issues/10258
1717 {
1818 const date = new Date ( '2016' ) ;
Original file line number Diff line number Diff line change @@ -41,13 +41,16 @@ test('sessionStorage is not persisted', async () => {
4141 assert . strictEqual ( ( await readdir ( tmpdir . path ) ) . length , 0 ) ;
4242} ) ;
4343
44- test ( 'localStorage emits a warning when used without --localstorage-file ' , async ( ) => {
44+ test ( 'localStorage throws without --localstorage-file' , async ( ) => {
4545 const cp = await spawnPromisified ( process . execPath , [
46- '-pe ' , 'localStorage.length ' ,
46+ '-e ' , 'localStorage' ,
4747 ] ) ;
48- assert . strictEqual ( cp . code , 0 ) ;
48+ assert . strictEqual ( cp . code , 1 ) ;
4949 assert . strictEqual ( cp . signal , null ) ;
50- assert . match ( cp . stderr , / W a r n i n g : ` - - l o c a l s t o r a g e - f i l e ` w a s p r o v i d e d w i t h o u t a v a l i d p a t h / ) ;
50+ assert . match (
51+ cp . stderr ,
52+ / S e c u r i t y E r r o r : U n a b l e t o i n i t i a l i z e l o c a l s t o r a g e w i t h o u t a ` - - l o c a l s t o r a g e - f i l e ` p a t h / ,
53+ ) ;
5154} ) ;
5255
5356test ( 'localStorage is not persisted if it is unused' , async ( ) => {
You can’t perform that action at this time.
0 commit comments