You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					108 lines
				
				3.5 KiB
			
		
		
			
		
	
	
					108 lines
				
				3.5 KiB
			| 
											3 years ago
										 | const Stream = require('./'); const { DEFAULT_ENCODING, getEncoding } = Stream; | ||
|  | const { end_of_stream, finished, stringToCodePoints } = require('../utils'); | ||
|  | const { encoders } = require('../table'); | ||
|  | 
 | ||
|  | // 8.2 Interface TextEncoder
 | ||
|  | 
 | ||
|  | class TextEncoder { | ||
|  |   /** | ||
|  |    * @param {string=} label The label of the encoding. NONSTANDARD. | ||
|  |    * @param {Object=} [options] NONSTANDARD. | ||
|  |    */ | ||
|  |   constructor(label, options = {}) { | ||
|  |     // A TextEncoder object has an associated encoding and encoder.
 | ||
|  | 
 | ||
|  |     /** @private */ | ||
|  |     this._encoding = null | ||
|  |     /** @private @type {?Encoder} */ | ||
|  |     this._encoder = null | ||
|  | 
 | ||
|  |     // Non-standard
 | ||
|  |     /** @private @type {boolean} */ | ||
|  |     this._do_not_flush = false | ||
|  |     /** @private @type {string} */ | ||
|  |     this._fatal = options['fatal'] ? 'fatal' : 'replacement' | ||
|  | 
 | ||
|  |     // 2. Set enc's encoding to UTF-8's encoder.
 | ||
|  |     if (options['NONSTANDARD_allowLegacyEncoding']) { | ||
|  |       // NONSTANDARD behavior.
 | ||
|  |       label = label !== undefined ? String(label) : DEFAULT_ENCODING | ||
|  |       var encoding = getEncoding(label) | ||
|  |       if (encoding === null || encoding.name === 'replacement') | ||
|  |         throw RangeError('Unknown encoding: ' + label) | ||
|  |       if (!encoders[encoding.name]) { | ||
|  |         throw Error('Encoder not present.' + | ||
|  |                     ' Did you forget to include encoding-indexes.js first?') | ||
|  |       } | ||
|  |       this._encoding = encoding | ||
|  |     } else { | ||
|  |       // Standard behavior.
 | ||
|  |       this._encoding = getEncoding('utf-8') | ||
|  | 
 | ||
|  |       if (label !== undefined && 'console' in global) { | ||
|  |         console.warn('TextEncoder constructor called with encoding label, ' | ||
|  |                       + 'which is ignored.') | ||
|  |       } | ||
|  |     } | ||
|  |   } | ||
|  |   get encoding() { | ||
|  |     return this._encoding.name.toLowerCase() | ||
|  |   } | ||
|  |   /** | ||
|  |    * @param {string=} opt_string The string to encode. | ||
|  |    * @param {Object=} options | ||
|  |    */ | ||
|  |   encode(opt_string = '', options = {}) { | ||
|  |     // NOTE: This option is nonstandard. None of the encodings
 | ||
|  |     // permitted for encoding (i.e. UTF-8, UTF-16) are stateful when
 | ||
|  |     // the input is a USVString so streaming is not necessary.
 | ||
|  |     if (!this._do_not_flush) | ||
|  |       this._encoder = encoders[this._encoding.name]({ | ||
|  |         fatal: this._fatal === 'fatal' }) | ||
|  |     this._do_not_flush = Boolean(options['stream']) | ||
|  | 
 | ||
|  |     // 1. Convert input to a stream.
 | ||
|  |     const input = new Stream(stringToCodePoints(opt_string)) | ||
|  | 
 | ||
|  |     // 2. Let output be a new stream
 | ||
|  |     const output = [] | ||
|  | 
 | ||
|  |     /** @type {?(number|!Array.<number>)} */ | ||
|  |     var result | ||
|  |     // 3. While true, run these substeps:
 | ||
|  |     while (true) { | ||
|  |       // 1. Let token be the result of reading from input.
 | ||
|  |       var token = input.read() | ||
|  |       if (token === end_of_stream) | ||
|  |         break | ||
|  |       // 2. Let result be the result of processing token for encoder,
 | ||
|  |       // input, output.
 | ||
|  |       result = this._encoder.handler(input, token) | ||
|  |       if (result === finished) | ||
|  |         break | ||
|  |       if (Array.isArray(result)) | ||
|  |         output.push.apply(output, /**@type {!Array.<number>}*/(result)) | ||
|  |       else | ||
|  |         output.push(result) | ||
|  |     } | ||
|  |     // TODO: Align with spec algorithm.
 | ||
|  |     if (!this._do_not_flush) { | ||
|  |       while (true) { | ||
|  |         result = this._encoder.handler(input, input.read()) | ||
|  |         if (result === finished) | ||
|  |           break | ||
|  |         if (Array.isArray(result)) | ||
|  |           output.push.apply(output, /**@type {!Array.<number>}*/(result)) | ||
|  |         else | ||
|  |           output.push(result) | ||
|  |       } | ||
|  |       this._encoder = null | ||
|  |     } | ||
|  |     // 3. If result is finished, convert output into a byte sequence,
 | ||
|  |     // and then return a Uint8Array object wrapping an ArrayBuffer
 | ||
|  |     // containing output.
 | ||
|  |     return new Uint8Array(output) | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | module.exports = TextEncoder |