@@ -39,55 +39,7 @@ if (!Module['noFSInit'] && !FS.init.initialized)
39
39
FS.ignorePermissions = false;
40
40
` )
41
41
addAtExit ( 'FS.quit();' ) ;
42
- // We must statically create FS.FSNode here so that it is created in a manner
43
- // that is visible to Closure compiler. That lets us use type annotations for
44
- // Closure to the "this" pointer in various node creation functions.
45
42
return `
46
- var FSNode = /** @constructor */ function(parent, name, mode, rdev) {
47
- if (!parent) {
48
- parent = this; // root node sets parent to itself
49
- }
50
- this.parent = parent;
51
- this.mount = parent.mount;
52
- this.mounted = null;
53
- this.id = FS.nextInode++;
54
- this.name = name;
55
- this.mode = mode;
56
- this.node_ops = {};
57
- this.stream_ops = {};
58
- this.rdev = rdev;
59
- };
60
- var readMode = 292/*{{{ cDefs.S_IRUGO }}}*/ | 73/*{{{ cDefs.S_IXUGO }}}*/;
61
- var writeMode = 146/*{{{ cDefs.S_IWUGO }}}*/;
62
- Object.defineProperties(FSNode.prototype, {
63
- read: {
64
- get: /** @this{FSNode} */function() {
65
- return (this.mode & readMode) === readMode;
66
- },
67
- set: /** @this{FSNode} */function(val) {
68
- val ? this.mode |= readMode : this.mode &= ~readMode;
69
- }
70
- },
71
- write: {
72
- get: /** @this{FSNode} */function() {
73
- return (this.mode & writeMode) === writeMode;
74
- },
75
- set: /** @this{FSNode} */function(val) {
76
- val ? this.mode |= writeMode : this.mode &= ~writeMode;
77
- }
78
- },
79
- isFolder: {
80
- get: /** @this{FSNode} */function() {
81
- return FS.isDir(this.mode);
82
- }
83
- },
84
- isDevice: {
85
- get: /** @this{FSNode} */function() {
86
- return FS.isChrdev(this.mode);
87
- }
88
- }
89
- });
90
- FS.FSNode = FSNode;
91
43
FS.createPreloadedFile = FS_createPreloadedFile;
92
44
FS.staticInit();` +
93
45
// Get module methods from settings
@@ -145,6 +97,79 @@ FS.staticInit();` +
145
97
}
146
98
} ,
147
99
100
+ FSStream : class {
101
+ constructor ( ) {
102
+ this . shared = { } ;
103
+ #if USE_CLOSURE_COMPILER
104
+ this . node = null ;
105
+ this . flags = 0 ;
106
+ #endif
107
+ }
108
+ get object ( ) {
109
+ return this . node ;
110
+ }
111
+ set object ( val ) {
112
+ this . node = val ;
113
+ }
114
+ get isRead ( ) {
115
+ return ( this . flags & { { { cDefs . O_ACCMODE } } } ) !== { { { cDefs . O_WRONLY } } } ;
116
+ }
117
+ get isWrite ( ) {
118
+ return ( this . flags & { { { cDefs . O_ACCMODE } } } ) !== { { { cDefs . O_RDONLY } } } ;
119
+ }
120
+ get isAppend ( ) {
121
+ return ( this . flags & { { { cDefs . O_APPEND } } } ) ;
122
+ }
123
+ get flags ( ) {
124
+ return this . shared . flags ;
125
+ }
126
+ set flags ( val ) {
127
+ this . shared . flags = val ;
128
+ }
129
+ get position ( ) {
130
+ return this . shared . position;
131
+ }
132
+ set position ( val ) {
133
+ this . shared . position = val ;
134
+ }
135
+ } ,
136
+ FSNode : class {
137
+ constructor ( parent , name , mode , rdev ) {
138
+ if ( ! parent ) {
139
+ parent = this ; // root node sets parent to itself
140
+ }
141
+ this . parent = parent ;
142
+ this . mount = parent . mount ;
143
+ this . mounted = null ;
144
+ this . id = FS . nextInode ++ ;
145
+ this . name = name ;
146
+ this . mode = mode ;
147
+ this . node_ops = { } ;
148
+ this . stream_ops = { } ;
149
+ this . rdev = rdev ;
150
+ this . readMode = 292 /*{{{ cDefs.S_IRUGO }}}*/ | 73 /*{{{ cDefs.S_IXUGO }}}*/ ;
151
+ this . writeMode = 146 /*{{{ cDefs.S_IWUGO }}}*/ ;
152
+ }
153
+ get read ( ) {
154
+ return ( this . mode & this . readMode ) === this . readMode ;
155
+ }
156
+ set read ( val ) {
157
+ val ? this . mode |= this . readMode : this . mode &= ~ this . readMode ;
158
+ }
159
+ get write ( ) {
160
+ return ( this . mode & this . writeMode ) === this . writeMode ;
161
+ }
162
+ set write ( val ) {
163
+ val ? this . mode |= this . writeMode : this . mode &= ~ this . writeMode ;
164
+ }
165
+ get isFolder ( ) {
166
+ return FS . isDir ( this . mode ) ;
167
+ }
168
+ get isDevice ( ) {
169
+ return FS . isChrdev ( this . mode ) ;
170
+ }
171
+ } ,
172
+
148
173
//
149
174
// paths
150
175
//
@@ -421,44 +446,7 @@ FS.staticInit();` +
421
446
// object isn't directly passed in. not possible until
422
447
// SOCKFS is completed.
423
448
createStream ( stream , fd = - 1 ) {
424
- if ( ! FS . FSStream ) {
425
- FS . FSStream = /** @constructor */ function ( ) {
426
- this . shared = { } ;
427
- } ;
428
- FS . FSStream . prototype = { } ;
429
- Object . defineProperties ( FS . FSStream . prototype , {
430
- object : {
431
- /** @this {FS.FSStream} */
432
- get ( ) { return this . node ; } ,
433
- /** @this {FS.FSStream} */
434
- set ( val ) { this . node = val ; }
435
- } ,
436
- isRead : {
437
- /** @this {FS.FSStream} */
438
- get ( ) { return ( this . flags & { { { cDefs . O_ACCMODE } } } ) !== { { { cDefs . O_WRONLY } } } ; }
439
- } ,
440
- isWrite : {
441
- /** @this {FS.FSStream} */
442
- get ( ) { return ( this . flags & { { { cDefs . O_ACCMODE } } } ) !== { { { cDefs . O_RDONLY } } } ; }
443
- } ,
444
- isAppend : {
445
- /** @this {FS.FSStream} */
446
- get ( ) { return ( this . flags & { { { cDefs . O_APPEND } } } ) ; }
447
- } ,
448
- flags : {
449
- /** @this {FS.FSStream} */
450
- get ( ) { return this . shared . flags ; } ,
451
- /** @this {FS.FSStream} */
452
- set ( val ) { this . shared . flags = val ; } ,
453
- } ,
454
- position : {
455
- /** @this {FS.FSStream} */
456
- get ( ) { return this . shared . position ; } ,
457
- /** @this {FS.FSStream} */
458
- set ( val ) { this . shared . position = val ; } ,
459
- } ,
460
- } ) ;
461
- }
449
+
462
450
// clone it, so we can return an instance of FSStream
463
451
stream = Object . assign ( new FS . FSStream ( ) , stream ) ;
464
452
if ( fd == - 1 ) {
@@ -1657,111 +1645,112 @@ FS.staticInit();` +
1657
1645
// XHR, which is not possible in browsers except in a web worker! Use preloading,
1658
1646
// either --preload-file in emcc or FS.createPreloadedFile
1659
1647
createLazyFile ( parent , name , url , canRead , canWrite ) {
1660
- // Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse.
1661
- /** @constructor */
1662
- function LazyUint8Array ( ) {
1663
- this . lengthKnown = false ;
1664
- this . chunks = [ ] ; // Loaded chunks. Index is the chunk number
1665
- }
1666
- LazyUint8Array . prototype . get = /** @this {Object} */ function LazyUint8Array_get ( idx ) {
1667
- if ( idx > this . length - 1 || idx < 0 ) {
1668
- return undefined ;
1669
- }
1670
- var chunkOffset = idx % this . chunkSize ;
1671
- var chunkNum = ( idx / this . chunkSize ) | 0 ;
1672
- return this . getter ( chunkNum ) [ chunkOffset ] ;
1673
- } ;
1674
- LazyUint8Array . prototype . setDataGetter = function LazyUint8Array_setDataGetter ( getter ) {
1675
- this . getter = getter ;
1676
- } ;
1677
- LazyUint8Array . prototype . cacheLength = function LazyUint8Array_cacheLength ( ) {
1678
- // Find length
1679
- var xhr = new XMLHttpRequest ( ) ;
1680
- xhr . open ( 'HEAD' , url , false ) ;
1681
- xhr . send ( null ) ;
1682
- if ( ! ( xhr . status >= 200 && xhr . status < 300 || xhr . status === 304 ) ) throw new Error ( "Couldn't load " + url + ". Status: " + xhr . status ) ;
1683
- var datalength = Number ( xhr . getResponseHeader ( "Content-length" ) ) ;
1684
- var header ;
1685
- var hasByteServing = ( header = xhr . getResponseHeader ( "Accept-Ranges" ) ) && header === "bytes" ;
1686
- var usesGzip = ( header = xhr . getResponseHeader ( "Content-Encoding" ) ) && header === "gzip" ;
1687
-
1688
- #if SMALL_XHR_CHUNKS
1689
- var chunkSize = 1024 ; // Chunk size in bytes
1690
- #else
1691
- var chunkSize = 1024 * 1024 ; // Chunk size in bytes
1648
+ // Lazy chunked Uint8Array (implements get and length from Uint8Array).
1649
+ // Actual getting is abstracted away for eventual reuse.
1650
+ class LazyUint8Array {
1651
+ constructor ( ) {
1652
+ this . lengthKnown = false ;
1653
+ this . chunks = [ ] ; // Loaded chunks. Index is the chunk number
1654
+ #if USE_CLOSURE_COMPILER
1655
+ this . getter = undefined ;
1656
+ this . _length = 0 ;
1657
+ this . _chunkSize = 0 ;
1692
1658
#endif
1693
-
1694
- if ( ! hasByteServing ) chunkSize = datalength ;
1695
-
1696
- // Function to get a range from the remote URL.
1697
- var doXHR = ( from , to ) => {
1698
- if ( from > to ) throw new Error ( "invalid range (" + from + ", " + to + ") or no bytes requested!" ) ;
1699
- if ( to > datalength - 1 ) throw new Error ( "only " + datalength + " bytes available! programmer error!" ) ;
1700
-
1701
- // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available.
1659
+ }
1660
+ get ( idx ) {
1661
+ if ( idx > this . length - 1 || idx < 0 ) {
1662
+ return undefined ;
1663
+ }
1664
+ var chunkOffset = idx % this . chunkSize ;
1665
+ var chunkNum = ( idx / this . chunkSize ) | 0 ;
1666
+ return this . getter ( chunkNum ) [ chunkOffset ] ;
1667
+ }
1668
+ setDataGetter ( getter ) {
1669
+ this . getter = getter ;
1670
+ }
1671
+ cacheLength ( ) {
1672
+ // Find length
1702
1673
var xhr = new XMLHttpRequest ( ) ;
1703
- xhr . open ( 'GET' , url , false ) ;
1704
- if ( datalength !== chunkSize ) xhr . setRequestHeader ( "Range" , "bytes=" + from + "-" + to ) ;
1674
+ xhr . open ( 'HEAD' , url , false ) ;
1675
+ xhr . send ( null ) ;
1676
+ if ( ! ( xhr . status >= 200 && xhr . status < 300 || xhr . status === 304 ) ) throw new Error ( "Couldn't load " + url + ". Status: " + xhr . status ) ;
1677
+ var datalength = Number ( xhr . getResponseHeader ( "Content-length" ) ) ;
1678
+ var header ;
1679
+ var hasByteServing = ( header = xhr . getResponseHeader ( "Accept-Ranges" ) ) && header === "bytes" ;
1680
+ var usesGzip = ( header = xhr . getResponseHeader ( "Content-Encoding" ) ) && header === "gzip" ;
1681
+
1682
+ #if SMALL_XHR_CHUNKS
1683
+ var chunkSize = 1024 ; // Chunk size in bytes
1684
+ #else
1685
+ var chunkSize = 1024 * 1024 ; // Chunk size in bytes
1686
+ #endif
1687
+
1688
+ if ( ! hasByteServing ) chunkSize = datalength ;
1689
+
1690
+ // Function to get a range from the remote URL.
1691
+ var doXHR = ( from , to ) => {
1692
+ if ( from > to ) throw new Error ( "invalid range (" + from + ", " + to + ") or no bytes requested!" ) ;
1693
+ if ( to > datalength - 1 ) throw new Error ( "only " + datalength + " bytes available! programmer error!" ) ;
1694
+
1695
+ // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available.
1696
+ var xhr = new XMLHttpRequest ( ) ;
1697
+ xhr . open ( 'GET' , url , false ) ;
1698
+ if ( datalength !== chunkSize ) xhr . setRequestHeader ( "Range" , "bytes=" + from + "-" + to ) ;
1699
+
1700
+ // Some hints to the browser that we want binary data.
1701
+ xhr . responseType = 'arraybuffer' ;
1702
+ if ( xhr . overrideMimeType ) {
1703
+ xhr . overrideMimeType ( 'text/plain; charset=x-user-defined' ) ;
1704
+ }
1705
1705
1706
- // Some hints to the browser that we want binary data.
1707
- xhr . responseType = 'arraybuffer' ;
1708
- if ( xhr . overrideMimeType ) {
1709
- xhr . overrideMimeType ( 'text/plain; charset=x-user-defined' ) ;
1706
+ xhr . send ( null ) ;
1707
+ if ( ! ( xhr . status >= 200 && xhr . status < 300 || xhr . status === 304 ) ) throw new Error ( "Couldn't load " + url + ". Status: " + xhr . status ) ;
1708
+ if ( xhr . response !== undefined ) {
1709
+ return new Uint8Array ( /** @type {Array<number> } */ ( xhr . response || [ ] ) ) ;
1710
+ }
1711
+ return intArrayFromString ( xhr . responseText || '' , true ) ;
1712
+ } ;
1713
+ var lazyArray = this ;
1714
+ lazyArray . setDataGetter ( ( chunkNum ) => {
1715
+ var start = chunkNum * chunkSize ;
1716
+ var end = ( chunkNum + 1 ) * chunkSize - 1 ; // including this byte
1717
+ end = Math . min ( end , datalength - 1 ) ; // if datalength-1 is selected, this is the last block
1718
+ if ( typeof lazyArray . chunks [ chunkNum ] == 'undefined' ) {
1719
+ lazyArray . chunks [ chunkNum ] = doXHR ( start , end ) ;
1720
+ }
1721
+ if ( typeof lazyArray . chunks [ chunkNum ] == 'undefined' ) throw new Error ( 'doXHR failed!' ) ;
1722
+ return lazyArray . chunks [ chunkNum ] ;
1723
+ } ) ;
1724
+
1725
+ if ( usesGzip || ! datalength ) {
1726
+ // if the server uses gzip or doesn't supply the length, we have to download the whole file to get the (uncompressed) length
1727
+ chunkSize = datalength = 1 ; // this will force getter(0)/doXHR do download the whole file
1728
+ datalength = this . getter ( 0 ) . length ;
1729
+ chunkSize = datalength ;
1730
+ out ( "LazyFiles on gzip forces download of the whole file when length is accessed" ) ;
1710
1731
}
1711
1732
1712
- xhr . send ( null ) ;
1713
- if ( ! ( xhr . status >= 200 && xhr . status < 300 || xhr . status === 304 ) ) throw new Error ( "Couldn't load " + url + ". Status: " + xhr . status ) ;
1714
- if ( xhr . response !== undefined ) {
1715
- return new Uint8Array ( /** @type {Array<number> } */ ( xhr . response || [ ] ) ) ;
1733
+ this . _length = datalength ;
1734
+ this . _chunkSize = chunkSize ;
1735
+ this . lengthKnown = true ;
1736
+ }
1737
+ get length ( ) {
1738
+ if ( ! this . lengthKnown ) {
1739
+ this . cacheLength ( ) ;
1716
1740
}
1717
- return intArrayFromString ( xhr . responseText || '' , true ) ;
1718
- } ;
1719
- var lazyArray = this ;
1720
- lazyArray . setDataGetter ( ( chunkNum ) => {
1721
- var start = chunkNum * chunkSize ;
1722
- var end = ( chunkNum + 1 ) * chunkSize - 1 ; // including this byte
1723
- end = Math . min ( end , datalength - 1 ) ; // if datalength-1 is selected, this is the last block
1724
- if ( typeof lazyArray . chunks [ chunkNum ] == 'undefined' ) {
1725
- lazyArray . chunks [ chunkNum ] = doXHR ( start , end ) ;
1741
+ return this . _length ;
1742
+ }
1743
+ get chunkSize ( ) {
1744
+ if ( ! this . lengthKnown ) {
1745
+ this . cacheLength ( ) ;
1726
1746
}
1727
- if ( typeof lazyArray . chunks [ chunkNum ] == 'undefined' ) throw new Error ( 'doXHR failed!' ) ;
1728
- return lazyArray . chunks [ chunkNum ] ;
1729
- } ) ;
1730
-
1731
- if ( usesGzip || ! datalength ) {
1732
- // if the server uses gzip or doesn't supply the length, we have to download the whole file to get the (uncompressed) length
1733
- chunkSize = datalength = 1 ; // this will force getter(0)/doXHR do download the whole file
1734
- datalength = this . getter ( 0 ) . length ;
1735
- chunkSize = datalength ;
1736
- out ( "LazyFiles on gzip forces download of the whole file when length is accessed" ) ;
1747
+ return this . _chunkSize ;
1737
1748
}
1749
+ }
1738
1750
1739
- this . _length = datalength ;
1740
- this . _chunkSize = chunkSize ;
1741
- this . lengthKnown = true ;
1742
- } ;
1743
1751
if ( typeof XMLHttpRequest != 'undefined' ) {
1744
1752
if ( ! ENVIRONMENT_IS_WORKER ) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc' ;
1745
1753
var lazyArray = new LazyUint8Array ( ) ;
1746
- Object . defineProperties ( lazyArray , {
1747
- length : {
1748
- get : /** @this {Object} */ function ( ) {
1749
- if ( ! this . lengthKnown ) {
1750
- this . cacheLength ( ) ;
1751
- }
1752
- return this . _length ;
1753
- }
1754
- } ,
1755
- chunkSize : {
1756
- get : /** @this {Object} */ function ( ) {
1757
- if ( ! this . lengthKnown ) {
1758
- this . cacheLength ( ) ;
1759
- }
1760
- return this . _chunkSize ;
1761
- }
1762
- }
1763
- } ) ;
1764
-
1765
1754
var properties = { isDevice : false , contents : lazyArray } ;
1766
1755
} else {
1767
1756
var properties = { isDevice : false , url : url } ;
@@ -1780,7 +1769,7 @@ FS.staticInit();` +
1780
1769
// Add a function that defers querying the file size until it is asked the first time.
1781
1770
Object . defineProperties ( node , {
1782
1771
usedBytes : {
1783
- get : /** @this {FSNode} */ function ( ) { return this . contents . length ; }
1772
+ get : function ( ) { return this . contents . length ; }
1784
1773
}
1785
1774
} ) ;
1786
1775
// override each stream op with one that tries to force load the lazy file first
0 commit comments