| /* |
| * Copyright 2018 WebAssembly Community Group participants |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "asmjs/asmangle.h" |
| #include <assert.h> |
| |
| namespace wasm { |
| |
| std::string asmangle(std::string name) { |
| // Wasm allows empty names as exports etc., but JS doesn't allow such |
| // identifiers. |
| if (name.empty()) { |
| name = "$"; |
| } |
| |
| bool mightBeKeyword = true; |
| size_t i = 1; |
| |
| assert(!name.empty()); |
| |
| // Names must start with a character, $ or _ |
| switch (auto ch = name[0]) { |
| case '0': |
| case '1': |
| case '2': |
| case '3': |
| case '4': |
| case '5': |
| case '6': |
| case '7': |
| case '8': |
| case '9': { |
| name = "$" + name; |
| i = 2; |
| goto notKeyword; |
| } |
| notKeyword: |
| case '$': |
| case '_': { |
| mightBeKeyword = false; |
| break; |
| } |
| default: { |
| if (!(ch >= 'a' && ch <= 'z') && !(ch >= 'A' && ch <= 'Z')) { |
| name = "$" + name.substr(1); |
| mightBeKeyword = false; |
| } |
| } |
| } |
| |
| // Names must contain only characters, digits, $ or _ |
| size_t len = name.length(); |
| for (; i < len; ++i) { |
| switch (char ch = name[i]) { |
| case '0': |
| case '1': |
| case '2': |
| case '3': |
| case '4': |
| case '5': |
| case '6': |
| case '7': |
| case '8': |
| case '9': |
| case '$': |
| case '_': { |
| mightBeKeyword = false; |
| break; |
| } |
| default: { |
| if (!(ch >= 'a' && ch <= 'z') && !(ch >= 'A' && ch <= 'Z')) { |
| name = name.substr(0, i) + "_" + name.substr(i + 1); |
| mightBeKeyword = false; |
| } |
| } |
| } |
| } |
| |
| // Names must not collide with keywords |
| if (mightBeKeyword && len >= 2 && len <= 10) { |
| switch (name[0]) { |
| case 'a': { |
| if (name == "arguments") { |
| goto mangleKeyword; |
| } |
| break; |
| } |
| case 'b': { |
| if (name == "break") { |
| goto mangleKeyword; |
| } |
| break; |
| } |
| case 'c': { |
| if (name == "case" || name == "continue" || name == "catch" || |
| name == "const" || name == "class") { |
| goto mangleKeyword; |
| } |
| break; |
| } |
| case 'd': { |
| if (name == "do" || name == "default" || name == "debugger") { |
| goto mangleKeyword; |
| } |
| break; |
| } |
| case 'e': { |
| if (name == "else" || name == "enum" || name == "eval" || // to be sure |
| name == "export" || name == "extends") { |
| goto mangleKeyword; |
| } |
| break; |
| } |
| case 'f': { |
| if (name == "for" || name == "false" || name == "finally" || |
| name == "function") { |
| goto mangleKeyword; |
| } |
| break; |
| } |
| case 'i': { |
| if (name == "if" || name == "in" || name == "import" || |
| name == "interface" || name == "implements" || |
| name == "instanceof") { |
| goto mangleKeyword; |
| } |
| break; |
| } |
| case 'l': { |
| if (name == "let") { |
| goto mangleKeyword; |
| } |
| break; |
| } |
| case 'n': { |
| if (name == "new" || name == "null") { |
| goto mangleKeyword; |
| } |
| break; |
| } |
| case 'p': { |
| if (name == "public" || name == "package" || name == "private" || |
| name == "protected") { |
| goto mangleKeyword; |
| } |
| break; |
| } |
| case 'r': { |
| if (name == "return") { |
| goto mangleKeyword; |
| } |
| break; |
| } |
| case 's': { |
| if (name == "super" || name == "static" || name == "switch") { |
| goto mangleKeyword; |
| } |
| break; |
| } |
| case 't': { |
| if (name == "try" || name == "this" || name == "true" || |
| name == "throw" || name == "typeof") { |
| goto mangleKeyword; |
| } |
| break; |
| } |
| case 'v': { |
| if (name == "var" || name == "void") { |
| goto mangleKeyword; |
| } |
| break; |
| } |
| case 'w': { |
| if (name == "with" || name == "while") { |
| goto mangleKeyword; |
| } |
| break; |
| } |
| case 'y': { |
| if (name == "yield") { |
| goto mangleKeyword; |
| } |
| break; |
| } |
| mangleKeyword : { name = name + "_"; } |
| } |
| } |
| return name; |
| } |
| |
| } // namespace wasm |