@@ -39,55 +39,7 @@ if (!Module['noFSInit'] && !FS.init.initialized)
3939FS.ignorePermissions = false;
4040` )
4141 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.
4542 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;
9143FS.createPreloadedFile = FS_createPreloadedFile;
9244FS.staticInit();` +
9345 // Get module methods from settings
@@ -145,6 +97,79 @@ FS.staticInit();` +
14597 }
14698 } ,
14799
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+
148173 //
149174 // paths
150175 //
@@ -421,44 +446,7 @@ FS.staticInit();` +
421446 // object isn't directly passed in. not possible until
422447 // SOCKFS is completed.
423448 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+
462450 // clone it, so we can return an instance of FSStream
463451 stream = Object . assign ( new FS . FSStream ( ) , stream ) ;
464452 if ( fd == - 1 ) {
@@ -1657,111 +1645,112 @@ FS.staticInit();` +
16571645 // XHR, which is not possible in browsers except in a web worker! Use preloading,
16581646 // either --preload-file in emcc or FS.createPreloadedFile
16591647 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 ;
16921658#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
17021673 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+ }
17051705
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" ) ;
17101731 }
17111732
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 ( ) ;
17161740 }
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 ( ) ;
17261746 }
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 ;
17371748 }
1749+ }
17381750
1739- this . _length = datalength ;
1740- this . _chunkSize = chunkSize ;
1741- this . lengthKnown = true ;
1742- } ;
17431751 if ( typeof XMLHttpRequest != 'undefined' ) {
17441752 if ( ! ENVIRONMENT_IS_WORKER ) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc' ;
17451753 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-
17651754 var properties = { isDevice : false , contents : lazyArray } ;
17661755 } else {
17671756 var properties = { isDevice : false , url : url } ;
@@ -1780,7 +1769,7 @@ FS.staticInit();` +
17801769 // Add a function that defers querying the file size until it is asked the first time.
17811770 Object . defineProperties ( node , {
17821771 usedBytes : {
1783- get : /** @this {FSNode} */ function ( ) { return this . contents . length ; }
1772+ get : function ( ) { return this . contents . length ; }
17841773 }
17851774 } ) ;
17861775 // override each stream op with one that tries to force load the lazy file first
0 commit comments