1+ // Reusing all MEMFS functionality
2+ // additionaly read data at mount
3+ // and save data at some operations.
4+ // Intended to use only for small files (like game settings),
5+ // because LocalStorage is very limited
6+ // and data saved as text in JSON format.
7+
8+ function LSFS ( ) {
9+ if ( LSFS . mount ) {
10+ return LSFS ;
11+ }
12+
13+ var wrapCreateNode = wrapNode ( MEMFS . createNode ) ;
14+
15+ var wrap_node_ops = {
16+ setattr : wrapSave ( MEMFS . node_ops . setattr ) ,
17+ mknod : wrapNode ( MEMFS . node_ops . mknod ) ,
18+ rename : wrapSave ( MEMFS . node_ops . rename ) ,
19+ unlink : wrapSave ( MEMFS . node_ops . unlink ) ,
20+ rmdir : wrapSave ( MEMFS . node_ops . rmdir ) ,
21+ symlink : wrapNode ( MEMFS . node_ops . symlink )
22+ } ;
23+
24+ var wrap_stream_ops = {
25+ write : wrapSave ( MEMFS . stream_ops . write ) ,
26+ msync : wrapSave ( MEMFS . stream_ops . msync )
27+ } ;
28+
29+ var props = [ 'name' , 'mode' , 'rdev' , 'link' , 'usedBytes' , 'timestamp' ] ;
30+
31+ LSFS . mount = mount ;
32+
33+ return LSFS ;
34+
35+ function wrapNode ( fn ) {
36+ return function ( ) {
37+ var node = fn . apply ( null , arguments ) ;
38+ setupNode ( node ) ;
39+ return node ;
40+ }
41+ }
42+
43+ function wrapSave ( fn ) {
44+ return function ( node ) {
45+ var res = fn . apply ( null , arguments ) ;
46+ save ( node ) ;
47+ return res ;
48+ }
49+ }
50+
51+ function setupNode ( node ) {
52+ var node_ops = { } ;
53+ for ( var op in node . node_ops ) {
54+ node_ops [ op ] = wrap_node_ops [ op ] || node . node_ops [ op ] ;
55+ }
56+ node . node_ops = node_ops ;
57+
58+ var stream_ops = { } ;
59+ for ( var op in node . stream_ops ) {
60+ stream_ops [ op ] = wrap_stream_ops [ op ] || node . stream_ops [ op ] ;
61+ }
62+ node . stream_ops = stream_ops ;
63+ }
64+
65+ function filter ( node ) {
66+ var result = { } ;
67+ for ( var key in node ) {
68+ if ( props . indexOf ( key ) !== - 1 ) {
69+ result [ key ] = node [ key ] ;
70+ }
71+ }
72+
73+ if ( node . contents ) {
74+ if ( node . contents . length ) {
75+ result . contents = Array . apply ( [ ] , node . contents ) ;
76+ } else {
77+ result . contents = { } ;
78+ for ( var name in node . contents ) {
79+ result . contents [ name ] = filter ( node . contents [ name ] ) ;
80+ }
81+ }
82+ }
83+
84+ return result ;
85+ }
86+
87+ function save ( node ) {
88+ if ( node . node ) {
89+ node = node . node ;
90+ }
91+
92+ var mount = node . mount ;
93+ if ( ! mount || ! mount . opts || ! mount . opts . key ) {
94+ return ;
95+ }
96+
97+ try {
98+ localStorage . setItem ( mount . opts . key , JSON . stringify ( filter ( mount . root ) ) ) ;
99+ } catch ( err ) { }
100+ }
101+
102+ function mount ( mount ) {
103+ if ( ! mount . opts || ! mount . opts . key ) {
104+ return ;
105+ }
106+
107+ var data ;
108+ try {
109+ data = localStorage . getItem ( mount . opts . key ) ;
110+ } catch ( err ) { }
111+ if ( data ) {
112+ try {
113+ data = JSON . parse ( data ) ;
114+ } catch ( err ) { }
115+ }
116+
117+ var node = MEMFS . mount ( mount ) ;
118+ setupNode ( node ) ;
119+ load ( node , mount , data ) ;
120+
121+ return node ;
122+ }
123+
124+ function load ( node , mount , data ) {
125+ node . mount = mount ;
126+ if ( ! data ) {
127+ return ;
128+ }
129+ for ( var key in data ) {
130+ if ( props . indexOf ( key ) !== - 1 ) {
131+ node [ key ] = data [ key ] ;
132+ }
133+ }
134+ if ( data . contents ) {
135+ if ( data . contents . length ) {
136+ node . contents = data . contents ;
137+ } else {
138+ node . contents = { } ;
139+ for ( var name in data . contents ) {
140+ var childData = data . contents [ name ] ;
141+ var childNode = wrapCreateNode ( node , name , childData . mode , childData . rdev ) ;
142+ load ( childNode , mount , childData ) ;
143+ }
144+ }
145+ }
146+ }
147+ }
0 commit comments