/* * Copyright (C) 2008, 2016 Apple Inc. All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef RegExpMatchesArray_h #define RegExpMatchesArray_h #include "ButterflyInlines.h" #include "JSArray.h" #include "JSCInlines.h" #include "JSGlobalObject.h" #include "RegExpInlines.h" #include "RegExpObject.h" namespace JSC { static const PropertyOffset RegExpMatchesArrayIndexPropertyOffset = 100; static const PropertyOffset RegExpMatchesArrayInputPropertyOffset = 101; ALWAYS_INLINE JSArray* tryCreateUninitializedRegExpMatchesArray(VM& vm, Structure* structure, unsigned initialLength) { unsigned vectorLength = std::max(BASE_VECTOR_LEN, initialLength); if (vectorLength > MAX_STORAGE_VECTOR_LENGTH) return 0; void* temp; if (!vm.heap.tryAllocateStorage(0, Butterfly::totalSize(0, structure->outOfLineCapacity(), true, vectorLength * sizeof(EncodedJSValue)), &temp)) return 0; Butterfly* butterfly = Butterfly::fromBase(temp, 0, structure->outOfLineCapacity()); butterfly->setVectorLength(vectorLength); butterfly->setPublicLength(initialLength); return JSArray::createWithButterfly(vm, structure, butterfly); } ALWAYS_INLINE JSArray* createRegExpMatchesArray( VM& vm, JSGlobalObject* globalObject, JSString* input, const String& inputValue, RegExp* regExp, unsigned startOffset, MatchResult& result) { Vector subpatternResults; int position = regExp->matchInline(vm, inputValue, startOffset, subpatternResults); if (position == -1) { result = MatchResult::failed(); return nullptr; } result.start = position; result.end = subpatternResults[1]; JSArray* array; // FIXME: This should handle array allocation errors gracefully. // https://bugs.webkit.org/show_bug.cgi?id=155144 if (UNLIKELY(globalObject->isHavingABadTime())) { array = JSArray::tryCreateUninitialized(vm, globalObject->regExpMatchesArrayStructure(), regExp->numSubpatterns() + 1); array->initializeIndex(vm, 0, jsSubstringOfResolved(vm, input, result.start, result.end - result.start)); if (unsigned numSubpatterns = regExp->numSubpatterns()) { for (unsigned i = 1; i <= numSubpatterns; ++i) { int start = subpatternResults[2 * i]; if (start >= 0) array->initializeIndex(vm, i, JSRopeString::createSubstringOfResolved(vm, input, start, subpatternResults[2 * i + 1] - start)); else array->initializeIndex(vm, i, jsUndefined()); } } } else { array = tryCreateUninitializedRegExpMatchesArray(vm, globalObject->regExpMatchesArrayStructure(), regExp->numSubpatterns() + 1); RELEASE_ASSERT(array); array->initializeIndex(vm, 0, jsSubstringOfResolved(vm, input, result.start, result.end - result.start), ArrayWithContiguous); if (unsigned numSubpatterns = regExp->numSubpatterns()) { for (unsigned i = 1; i <= numSubpatterns; ++i) { int start = subpatternResults[2 * i]; if (start >= 0) array->initializeIndex(vm, i, JSRopeString::createSubstringOfResolved(vm, input, start, subpatternResults[2 * i + 1] - start), ArrayWithContiguous); else array->initializeIndex(vm, i, jsUndefined(), ArrayWithContiguous); } } } array->putDirect(vm, RegExpMatchesArrayIndexPropertyOffset, jsNumber(result.start)); array->putDirect(vm, RegExpMatchesArrayInputPropertyOffset, input); return array; } inline JSArray* createRegExpMatchesArray(ExecState* exec, JSGlobalObject* globalObject, JSString* string, RegExp* regExp, unsigned startOffset) { MatchResult ignoredResult; return createRegExpMatchesArray(globalObject->vm(), globalObject, string, string->value(exec), regExp, startOffset, ignoredResult); } JSArray* createEmptyRegExpMatchesArray(JSGlobalObject*, JSString*, RegExp*); Structure* createRegExpMatchesArrayStructure(VM&, JSGlobalObject*); Structure* createRegExpMatchesArraySlowPutStructure(VM&, JSGlobalObject*); } #endif // RegExpMatchesArray_h