Identifier.cpp (3866B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "util/Identifier.h" 8 9 #include "mozilla/Assertions.h" // MOZ_ASSERT 10 11 #include <stddef.h> // size_t 12 13 #include "js/GCAPI.h" // JS::AutoCheckCannotGC 14 #include "js/TypeDecls.h" // JS::Latin1Char 15 #include "util/Unicode.h" // unicode::{IsIdentifierStart, IsIdentifierPart, IsIdentifierStartASCII, IsIdentifierPartASCII, IsLeadSurrogate, IsTrailSurrogate, UTF16Decode} 16 #include "vm/StringType.h" // JSLinearString 17 18 using namespace js; 19 20 bool js::IsIdentifier(const JSLinearString* str) { 21 JS::AutoCheckCannotGC nogc; 22 MOZ_ASSERT(str); 23 if (str->hasLatin1Chars()) { 24 return IsIdentifier(str->latin1Chars(nogc), str->length()); 25 } 26 return IsIdentifier(str->twoByteChars(nogc), str->length()); 27 } 28 29 bool js::IsIdentifierNameOrPrivateName(const JSLinearString* str) { 30 JS::AutoCheckCannotGC nogc; 31 MOZ_ASSERT(str); 32 if (str->hasLatin1Chars()) { 33 return IsIdentifierNameOrPrivateName(str->latin1Chars(nogc), str->length()); 34 } 35 return IsIdentifierNameOrPrivateName(str->twoByteChars(nogc), str->length()); 36 } 37 38 bool js::IsIdentifier(const JS::Latin1Char* chars, size_t length) { 39 if (length == 0) { 40 return false; 41 } 42 43 if (!unicode::IsIdentifierStart(char16_t(*chars))) { 44 return false; 45 } 46 47 const JS::Latin1Char* end = chars + length; 48 while (++chars != end) { 49 if (!unicode::IsIdentifierPart(char16_t(*chars))) { 50 return false; 51 } 52 } 53 54 return true; 55 } 56 57 bool js::IsIdentifierASCII(char c) { 58 return unicode::IsIdentifierStartASCII(c); 59 } 60 61 bool js::IsIdentifierASCII(char c1, char c2) { 62 return unicode::IsIdentifierStartASCII(c1) && 63 unicode::IsIdentifierPartASCII(c2); 64 } 65 66 bool js::IsIdentifierNameOrPrivateName(const JS::Latin1Char* chars, 67 size_t length) { 68 if (length == 0) { 69 return false; 70 } 71 72 // Skip over any private name marker. 73 if (*chars == '#') { 74 ++chars; 75 --length; 76 } 77 78 return IsIdentifier(chars, length); 79 } 80 81 static char32_t GetSingleCodePoint(const char16_t** p, const char16_t* end) { 82 using namespace js; 83 84 if (MOZ_UNLIKELY(unicode::IsLeadSurrogate(**p)) && *p + 1 < end) { 85 char16_t lead = **p; 86 char16_t maybeTrail = *(*p + 1); 87 if (unicode::IsTrailSurrogate(maybeTrail)) { 88 *p += 2; 89 return unicode::UTF16Decode(lead, maybeTrail); 90 } 91 } 92 93 char32_t codePoint = **p; 94 (*p)++; 95 return codePoint; 96 } 97 98 bool js::IsIdentifier(const char16_t* chars, size_t length) { 99 if (length == 0) { 100 return false; 101 } 102 103 const char16_t* p = chars; 104 const char16_t* end = chars + length; 105 char32_t codePoint; 106 107 codePoint = GetSingleCodePoint(&p, end); 108 if (!unicode::IsIdentifierStart(codePoint)) { 109 return false; 110 } 111 112 while (p < end) { 113 codePoint = GetSingleCodePoint(&p, end); 114 if (!unicode::IsIdentifierPart(codePoint)) { 115 return false; 116 } 117 } 118 119 return true; 120 } 121 122 bool js::IsIdentifierNameOrPrivateName(const char16_t* chars, size_t length) { 123 if (length == 0) { 124 return false; 125 } 126 127 const char16_t* p = chars; 128 const char16_t* end = chars + length; 129 char32_t codePoint; 130 131 codePoint = GetSingleCodePoint(&p, end); 132 133 // Skip over any private name marker. 134 if (codePoint == '#') { 135 // The identifier part of a private name mustn't be empty. 136 if (length == 1) { 137 return false; 138 } 139 140 codePoint = GetSingleCodePoint(&p, end); 141 } 142 143 if (!unicode::IsIdentifierStart(codePoint)) { 144 return false; 145 } 146 147 while (p < end) { 148 codePoint = GetSingleCodePoint(&p, end); 149 if (!unicode::IsIdentifierPart(codePoint)) { 150 return false; 151 } 152 } 153 154 return true; 155 }