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.
		
		
		
		
		
			
		
			
				
					498 lines
				
				11 KiB
			
		
		
			
		
	
	
					498 lines
				
				11 KiB
			| 
											3 years ago
										 | import { | ||
|  |     AST_Accessor, | ||
|  |     AST_Array, | ||
|  |     AST_Arrow, | ||
|  |     AST_Await, | ||
|  |     AST_BigInt, | ||
|  |     AST_Binary, | ||
|  |     AST_Block, | ||
|  |     AST_Break, | ||
|  |     AST_Call, | ||
|  |     AST_Case, | ||
|  |     AST_Class, | ||
|  |     AST_ClassStaticBlock, | ||
|  |     AST_ClassPrivateProperty, | ||
|  |     AST_ClassProperty, | ||
|  |     AST_ConciseMethod, | ||
|  |     AST_Conditional, | ||
|  |     AST_Const, | ||
|  |     AST_Continue, | ||
|  |     AST_Debugger, | ||
|  |     AST_Default, | ||
|  |     AST_Defun, | ||
|  |     AST_Destructuring, | ||
|  |     AST_Directive, | ||
|  |     AST_Do, | ||
|  |     AST_Dot, | ||
|  |     AST_DotHash, | ||
|  |     AST_EmptyStatement, | ||
|  |     AST_Expansion, | ||
|  |     AST_Export, | ||
|  |     AST_False, | ||
|  |     AST_For, | ||
|  |     AST_ForIn, | ||
|  |     AST_Function, | ||
|  |     AST_Hole, | ||
|  |     AST_If, | ||
|  |     AST_Import, | ||
|  |     AST_ImportMeta, | ||
|  |     AST_Infinity, | ||
|  |     AST_LabeledStatement, | ||
|  |     AST_Let, | ||
|  |     AST_NameMapping, | ||
|  |     AST_NaN, | ||
|  |     AST_New, | ||
|  |     AST_NewTarget, | ||
|  |     AST_Node, | ||
|  |     AST_Null, | ||
|  |     AST_Number, | ||
|  |     AST_Object, | ||
|  |     AST_ObjectKeyVal, | ||
|  |     AST_ObjectGetter, | ||
|  |     AST_ObjectSetter, | ||
|  |     AST_PrivateGetter, | ||
|  |     AST_PrivateMethod, | ||
|  |     AST_PrivateSetter, | ||
|  |     AST_PrivateIn, | ||
|  |     AST_RegExp, | ||
|  |     AST_Return, | ||
|  |     AST_Sequence, | ||
|  |     AST_String, | ||
|  |     AST_Sub, | ||
|  |     AST_Super, | ||
|  |     AST_Switch, | ||
|  |     AST_Symbol, | ||
|  |     AST_SymbolClassProperty, | ||
|  |     AST_SymbolExportForeign, | ||
|  |     AST_SymbolImportForeign, | ||
|  |     AST_SymbolRef, | ||
|  |     AST_SymbolDeclaration, | ||
|  |     AST_TemplateSegment, | ||
|  |     AST_TemplateString, | ||
|  |     AST_This, | ||
|  |     AST_Throw, | ||
|  |     AST_Toplevel, | ||
|  |     AST_True, | ||
|  |     AST_Try, | ||
|  |     AST_Catch, | ||
|  |     AST_Finally, | ||
|  |     AST_Unary, | ||
|  |     AST_Undefined, | ||
|  |     AST_Var, | ||
|  |     AST_VarDef, | ||
|  |     AST_While, | ||
|  |     AST_With, | ||
|  |     AST_Yield, | ||
|  |     walk_parent | ||
|  | } from "./ast.js"; | ||
|  | import { first_in_statement } from "./utils/first_in_statement.js"; | ||
|  | 
 | ||
|  | let mangle_options = undefined; | ||
|  | AST_Node.prototype.size = function (compressor, stack) { | ||
|  |     mangle_options = compressor && compressor.mangle_options; | ||
|  | 
 | ||
|  |     let size = 0; | ||
|  |     walk_parent(this, (node, info) => { | ||
|  |         size += node._size(info); | ||
|  | 
 | ||
|  |         // Braceless arrow functions have fake "return" statements
 | ||
|  |         if (node instanceof AST_Arrow && node.is_braceless()) { | ||
|  |             size += node.body[0].value._size(info); | ||
|  |             return true; | ||
|  |         } | ||
|  |     }, stack || (compressor && compressor.stack)); | ||
|  | 
 | ||
|  |     // just to save a bit of memory
 | ||
|  |     mangle_options = undefined; | ||
|  | 
 | ||
|  |     return size; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Node.prototype._size = () => 0; | ||
|  | 
 | ||
|  | AST_Debugger.prototype._size = () => 8; | ||
|  | 
 | ||
|  | AST_Directive.prototype._size = function () { | ||
|  |     // TODO string encoding stuff
 | ||
|  |     return 2 + this.value.length; | ||
|  | }; | ||
|  | 
 | ||
|  | /** Count commas/semicolons necessary to show a list of expressions/statements */ | ||
|  | const list_overhead = (array) => array.length && array.length - 1; | ||
|  | 
 | ||
|  | AST_Block.prototype._size = function () { | ||
|  |     return 2 + list_overhead(this.body); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Toplevel.prototype._size = function() { | ||
|  |     return list_overhead(this.body); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_EmptyStatement.prototype._size = () => 1; | ||
|  | 
 | ||
|  | AST_LabeledStatement.prototype._size = () => 2;  // x:
 | ||
|  | 
 | ||
|  | AST_Do.prototype._size = () => 9; | ||
|  | 
 | ||
|  | AST_While.prototype._size = () => 7; | ||
|  | 
 | ||
|  | AST_For.prototype._size = () => 8; | ||
|  | 
 | ||
|  | AST_ForIn.prototype._size = () => 8; | ||
|  | // AST_ForOf inherits ^
 | ||
|  | 
 | ||
|  | AST_With.prototype._size = () => 6; | ||
|  | 
 | ||
|  | AST_Expansion.prototype._size = () => 3; | ||
|  | 
 | ||
|  | const lambda_modifiers = func => | ||
|  |     (func.is_generator ? 1 : 0) + (func.async ? 6 : 0); | ||
|  | 
 | ||
|  | AST_Accessor.prototype._size = function () { | ||
|  |     return lambda_modifiers(this) + 4 + list_overhead(this.argnames) + list_overhead(this.body); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Function.prototype._size = function (info) { | ||
|  |     const first = !!first_in_statement(info); | ||
|  |     return (first * 2) + lambda_modifiers(this) + 12 + list_overhead(this.argnames) + list_overhead(this.body); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Defun.prototype._size = function () { | ||
|  |     return lambda_modifiers(this) + 13 + list_overhead(this.argnames) + list_overhead(this.body); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Arrow.prototype._size = function () { | ||
|  |     let args_and_arrow = 2 + list_overhead(this.argnames); | ||
|  | 
 | ||
|  |     if ( | ||
|  |         !( | ||
|  |             this.argnames.length === 1 | ||
|  |             && this.argnames[0] instanceof AST_Symbol | ||
|  |         ) | ||
|  |     ) { | ||
|  |         args_and_arrow += 2; // parens around the args
 | ||
|  |     } | ||
|  | 
 | ||
|  |     const body_overhead = this.is_braceless() ? 0 : list_overhead(this.body) + 2; | ||
|  | 
 | ||
|  |     return lambda_modifiers(this) + args_and_arrow + body_overhead; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Destructuring.prototype._size = () => 2; | ||
|  | 
 | ||
|  | AST_TemplateString.prototype._size = function () { | ||
|  |     return 2 + (Math.floor(this.segments.length / 2) * 3);  /* "${}" */ | ||
|  | }; | ||
|  | 
 | ||
|  | AST_TemplateSegment.prototype._size = function () { | ||
|  |     return this.value.length; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Return.prototype._size = function () { | ||
|  |     return this.value ? 7 : 6; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Throw.prototype._size = () => 6; | ||
|  | 
 | ||
|  | AST_Break.prototype._size = function () { | ||
|  |     return this.label ? 6 : 5; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Continue.prototype._size = function () { | ||
|  |     return this.label ? 9 : 8; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_If.prototype._size = () => 4; | ||
|  | 
 | ||
|  | AST_Switch.prototype._size = function () { | ||
|  |     return 8 + list_overhead(this.body); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Case.prototype._size = function () { | ||
|  |     return 5 + list_overhead(this.body); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Default.prototype._size = function () { | ||
|  |     return 8 + list_overhead(this.body); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Try.prototype._size = function () { | ||
|  |     return 3 + list_overhead(this.body); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Catch.prototype._size = function () { | ||
|  |     let size = 7 + list_overhead(this.body); | ||
|  |     if (this.argname) { | ||
|  |         size += 2; | ||
|  |     } | ||
|  |     return size; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Finally.prototype._size = function () { | ||
|  |     return 7 + list_overhead(this.body); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Var.prototype._size = function () { | ||
|  |     return 4 + list_overhead(this.definitions); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Let.prototype._size = function () { | ||
|  |     return 4 + list_overhead(this.definitions); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Const.prototype._size = function () { | ||
|  |     return 6 + list_overhead(this.definitions); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_VarDef.prototype._size = function () { | ||
|  |     return this.value ? 1 : 0; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_NameMapping.prototype._size = function () { | ||
|  |     // foreign name isn't mangled
 | ||
|  |     return this.name ? 4 : 0; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Import.prototype._size = function () { | ||
|  |     // import
 | ||
|  |     let size = 6; | ||
|  | 
 | ||
|  |     if (this.imported_name) size += 1; | ||
|  | 
 | ||
|  |     // from
 | ||
|  |     if (this.imported_name || this.imported_names) size += 5; | ||
|  | 
 | ||
|  |     // braces, and the commas
 | ||
|  |     if (this.imported_names) { | ||
|  |         size += 2 + list_overhead(this.imported_names); | ||
|  |     } | ||
|  | 
 | ||
|  |     return size; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_ImportMeta.prototype._size = () => 11; | ||
|  | 
 | ||
|  | AST_Export.prototype._size = function () { | ||
|  |     let size = 7 + (this.is_default ? 8 : 0); | ||
|  | 
 | ||
|  |     if (this.exported_value) { | ||
|  |         size += this.exported_value._size(); | ||
|  |     } | ||
|  | 
 | ||
|  |     if (this.exported_names) { | ||
|  |         // Braces and commas
 | ||
|  |         size += 2 + list_overhead(this.exported_names); | ||
|  |     } | ||
|  | 
 | ||
|  |     if (this.module_name) { | ||
|  |         // "from "
 | ||
|  |         size += 5; | ||
|  |     } | ||
|  | 
 | ||
|  |     return size; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Call.prototype._size = function () { | ||
|  |     if (this.optional) { | ||
|  |         return 4 + list_overhead(this.args); | ||
|  |     } | ||
|  |     return 2 + list_overhead(this.args); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_New.prototype._size = function () { | ||
|  |     return 6 + list_overhead(this.args); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Sequence.prototype._size = function () { | ||
|  |     return list_overhead(this.expressions); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Dot.prototype._size = function () { | ||
|  |     if (this.optional) { | ||
|  |         return this.property.length + 2; | ||
|  |     } | ||
|  |     return this.property.length + 1; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_DotHash.prototype._size = function () { | ||
|  |     if (this.optional) { | ||
|  |         return this.property.length + 3; | ||
|  |     } | ||
|  |     return this.property.length + 2; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Sub.prototype._size = function () { | ||
|  |     return this.optional ? 4 : 2; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Unary.prototype._size = function () { | ||
|  |     if (this.operator === "typeof") return 7; | ||
|  |     if (this.operator === "void") return 5; | ||
|  |     return this.operator.length; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Binary.prototype._size = function (info) { | ||
|  |     if (this.operator === "in") return 4; | ||
|  | 
 | ||
|  |     let size = this.operator.length; | ||
|  | 
 | ||
|  |     if ( | ||
|  |         (this.operator === "+" || this.operator === "-") | ||
|  |         && this.right instanceof AST_Unary && this.right.operator === this.operator | ||
|  |     ) { | ||
|  |         // 1+ +a > needs space between the +
 | ||
|  |         size += 1; | ||
|  |     } | ||
|  | 
 | ||
|  |     if (this.needs_parens(info)) { | ||
|  |         size += 2; | ||
|  |     } | ||
|  | 
 | ||
|  |     return size; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Conditional.prototype._size = () => 3; | ||
|  | 
 | ||
|  | AST_Array.prototype._size = function () { | ||
|  |     return 2 + list_overhead(this.elements); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Object.prototype._size = function (info) { | ||
|  |     let base = 2; | ||
|  |     if (first_in_statement(info)) { | ||
|  |         base += 2; // parens
 | ||
|  |     } | ||
|  |     return base + list_overhead(this.properties); | ||
|  | }; | ||
|  | 
 | ||
|  | /*#__INLINE__*/ | ||
|  | const key_size = key => | ||
|  |     typeof key === "string" ? key.length : 0; | ||
|  | 
 | ||
|  | AST_ObjectKeyVal.prototype._size = function () { | ||
|  |     return key_size(this.key) + 1; | ||
|  | }; | ||
|  | 
 | ||
|  | /*#__INLINE__*/ | ||
|  | const static_size = is_static => is_static ? 7 : 0; | ||
|  | 
 | ||
|  | AST_ObjectGetter.prototype._size = function () { | ||
|  |     return 5 + static_size(this.static) + key_size(this.key); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_ObjectSetter.prototype._size = function () { | ||
|  |     return 5 + static_size(this.static) + key_size(this.key); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_ConciseMethod.prototype._size = function () { | ||
|  |     return static_size(this.static) + key_size(this.key) + lambda_modifiers(this); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_PrivateMethod.prototype._size = function () { | ||
|  |     return AST_ConciseMethod.prototype._size.call(this) + 1; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_PrivateGetter.prototype._size = AST_PrivateSetter.prototype._size = function () { | ||
|  |     return AST_ConciseMethod.prototype._size.call(this) + 4; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_PrivateIn.prototype._size = function () { | ||
|  |     return 5; // "#", and " in "
 | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Class.prototype._size = function () { | ||
|  |     return ( | ||
|  |         (this.name ? 8 : 7) | ||
|  |         + (this.extends ? 8 : 0) | ||
|  |     ); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_ClassStaticBlock.prototype._size = function () { | ||
|  |     // "class{}" + semicolons
 | ||
|  |     return 7 + list_overhead(this.body); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_ClassProperty.prototype._size = function () { | ||
|  |     return ( | ||
|  |         static_size(this.static) | ||
|  |         + (typeof this.key === "string" ? this.key.length + 2 : 0) | ||
|  |         + (this.value ? 1 : 0) | ||
|  |     ); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_ClassPrivateProperty.prototype._size = function () { | ||
|  |     return AST_ClassProperty.prototype._size.call(this) + 1; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Symbol.prototype._size = function () { | ||
|  |     if (!(mangle_options && this.thedef && !this.thedef.unmangleable(mangle_options))) { | ||
|  |         return this.name.length; | ||
|  |     } else { | ||
|  |         return 1; | ||
|  |     } | ||
|  | }; | ||
|  | 
 | ||
|  | // TODO take propmangle into account
 | ||
|  | AST_SymbolClassProperty.prototype._size = function () { | ||
|  |     return this.name.length; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_SymbolRef.prototype._size = AST_SymbolDeclaration.prototype._size = function () { | ||
|  |     if (this.name === "arguments") return 9; | ||
|  | 
 | ||
|  |     return AST_Symbol.prototype._size.call(this); | ||
|  | }; | ||
|  | 
 | ||
|  | AST_NewTarget.prototype._size = () => 10; | ||
|  | 
 | ||
|  | AST_SymbolImportForeign.prototype._size = function () { | ||
|  |     return this.name.length; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_SymbolExportForeign.prototype._size = function () { | ||
|  |     return this.name.length; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_This.prototype._size = () => 4; | ||
|  | 
 | ||
|  | AST_Super.prototype._size = () => 5; | ||
|  | 
 | ||
|  | AST_String.prototype._size = function () { | ||
|  |     return this.value.length + 2; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Number.prototype._size = function () { | ||
|  |     const { value } = this; | ||
|  |     if (value === 0) return 1; | ||
|  |     if (value > 0 && Math.floor(value) === value) { | ||
|  |         return Math.floor(Math.log10(value) + 1); | ||
|  |     } | ||
|  |     return value.toString().length; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_BigInt.prototype._size = function () { | ||
|  |     return this.value.length; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_RegExp.prototype._size = function () { | ||
|  |     return this.value.toString().length; | ||
|  | }; | ||
|  | 
 | ||
|  | AST_Null.prototype._size = () => 4; | ||
|  | 
 | ||
|  | AST_NaN.prototype._size = () => 3; | ||
|  | 
 | ||
|  | AST_Undefined.prototype._size = () => 6; // "void 0"
 | ||
|  | 
 | ||
|  | AST_Hole.prototype._size = () => 0;  // comma is taken into account by list_overhead()
 | ||
|  | 
 | ||
|  | AST_Infinity.prototype._size = () => 8; | ||
|  | 
 | ||
|  | AST_True.prototype._size = () => 4; | ||
|  | 
 | ||
|  | AST_False.prototype._size = () => 5; | ||
|  | 
 | ||
|  | AST_Await.prototype._size = () => 6; | ||
|  | 
 | ||
|  | AST_Yield.prototype._size = () => 6; |