| /* |
| * Copyright (C) 2016 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| * THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| importScripts(...[ |
| "../../External/Esprima/esprima.js", |
| "CSSFormatter.js", |
| "ESTreeWalker.js", |
| "FormatterContentBuilder.js", |
| "FormatterUtilities.js", |
| "HTMLFormatter.js", |
| "HTMLParser.js", |
| "HTMLTreeBuilderFormatter.js", |
| "JSFormatter.js", |
| ]); |
| |
| FormatterWorker = class FormatterWorker |
| { |
| constructor() |
| { |
| self.addEventListener("message", this._handleMessage.bind(this)); |
| } |
| |
| // Actions |
| |
| formatJavaScript(sourceText, isModule, indentString, includeSourceMapData) |
| { |
| let sourceType = isModule ? JSFormatter.SourceType.Module : JSFormatter.SourceType.Script; |
| |
| // Format a JavaScript program. |
| const builder = null; |
| let formatter = new JSFormatter(sourceText, sourceType, builder, indentString); |
| if (formatter.success) { |
| let result = {formattedText: formatter.formattedText}; |
| if (includeSourceMapData) { |
| result.sourceMapData = formatter.sourceMapData; |
| // NOTE: With the JSFormatter, multi-line tokens, such as comments and strings, |
| // would not have had their newlines counted properly by the builder. Rather then |
| // modify the formatter to check and account for newlines in every token just |
| // compute the list of line endings directly on the result. |
| result.sourceMapData.formattedLineEndings = result.formattedText.lineEndings(); |
| } |
| return result; |
| } |
| |
| // Format valid JSON. |
| // The formatter could fail if this was just a JSON string. So try a JSON.parse and stringify. |
| // This will produce empty source map data, but it is not code, so it is not as important. |
| try { |
| let jsonStringified = JSON.stringify(JSON.parse(sourceText), null, indentString); |
| let result = {formattedText: jsonStringified}; |
| if (includeSourceMapData) |
| result.sourceMapData = {mapping: {original: [], formatted: []}, originalLineEndings: [], formattedLineEndings: []}; |
| return result; |
| } catch { } |
| |
| // Format invalid JSON and anonymous functions. |
| // Some applications do not use JSON.parse but eval on JSON content. That is more permissive |
| // so try to format invalid JSON. Again no source map data since it is not code. |
| // Likewise, an unnamed function's toString() produces a "function() { ... }", which is not |
| // a valid program on its own. Wrap it in parenthesis to make it a function expression, |
| // which is a valid program. |
| let invalidJSONFormatter = new JSFormatter("(" + sourceText + ")", sourceType, builder, indentString); |
| if (invalidJSONFormatter.success) { |
| let formattedTextWithParens = invalidJSONFormatter.formattedText; |
| let result = {formattedText: formattedTextWithParens.substring(1, formattedTextWithParens.length - 2)}; // Remove "(" and ")\n". |
| if (includeSourceMapData) |
| result.sourceMapData = {mapping: {original: [], formatted: []}, originalLineEndings: [], formattedLineEndings: []}; |
| return result; |
| } |
| |
| return {formattedText: null}; |
| } |
| |
| formatCSS(sourceText, indentString, includeSourceMapData) |
| { |
| let result = {formattedText: null}; |
| const builder = null; |
| let formatter = new CSSFormatter(sourceText, builder, indentString); |
| if (formatter.success) { |
| result.formattedText = formatter.formattedText; |
| if (includeSourceMapData) |
| result.sourceMapData = formatter.sourceMapData; |
| } |
| return result; |
| } |
| |
| formatHTML(sourceText, indentString, includeSourceMapData) |
| { |
| let result = {formattedText: null}; |
| const builder = null; |
| const sourceType = HTMLFormatter.SourceType.HTML; |
| let formatter = new HTMLFormatter(sourceText, sourceType, builder, indentString); |
| if (formatter.success) { |
| result.formattedText = formatter.formattedText; |
| if (includeSourceMapData) |
| result.sourceMapData = formatter.sourceMapData; |
| } |
| return result; |
| } |
| |
| formatXML(sourceText, indentString, includeSourceMapData) |
| { |
| let result = {formattedText: null}; |
| const builder = null; |
| const sourceType = HTMLFormatter.SourceType.XML; |
| let formatter = new HTMLFormatter(sourceText, sourceType, builder, indentString); |
| if (formatter.success) { |
| result.formattedText = formatter.formattedText; |
| if (includeSourceMapData) |
| result.sourceMapData = formatter.sourceMapData; |
| } |
| return result; |
| } |
| |
| // Private |
| |
| _handleMessage(event) |
| { |
| let data = event.data; |
| |
| // Action. |
| if (data.actionName) { |
| let result = this[data.actionName](...data.actionArguments); |
| self.postMessage({callId: data.callId, result}); |
| return; |
| } |
| |
| console.error("Unexpected FormatterWorker message", data); |
| } |
| }; |
| |
| self.formatterWorker = new FormatterWorker; |