/* * Copyright (C) 2012-2015 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. ``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 * 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. */ #include "config.h" #include "RegExpMatchesArray.h" #include "ButterflyInlines.h" #include "JSCInlines.h" namespace JSC { static const PropertyOffset indexPropertyOffset = 100; static const PropertyOffset inputPropertyOffset = 101; static 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); } JSArray* createRegExpMatchesArray(ExecState* exec, JSString* input, RegExp* regExp, MatchResult result) { ASSERT(result); VM& vm = exec->vm(); JSArray* array = tryCreateUninitializedRegExpMatchesArray(vm, exec->lexicalGlobalObject()->regExpMatchesArrayStructure(), regExp->numSubpatterns() + 1); RELEASE_ASSERT(array); SamplingRegion samplingRegion("Reifying substring properties"); array->initializeIndex(vm, 0, jsSubstring(exec, input, result.start, result.end - result.start), ArrayWithContiguous); if (unsigned numSubpatterns = regExp->numSubpatterns()) { Vector subpatternResults; int position = regExp->match(vm, input->value(exec), result.start, subpatternResults); ASSERT_UNUSED(position, position >= 0 && static_cast(position) == result.start); ASSERT(result.start == static_cast(subpatternResults[0])); ASSERT(result.end == static_cast(subpatternResults[1])); for (unsigned i = 1; i <= numSubpatterns; ++i) { int start = subpatternResults[2 * i]; if (start >= 0) array->initializeIndex(vm, i, jsSubstring(exec, input, start, subpatternResults[2 * i + 1] - start), ArrayWithContiguous); else array->initializeIndex(vm, i, jsUndefined(), ArrayWithContiguous); } } array->putDirect(vm, indexPropertyOffset, jsNumber(result.start)); array->putDirect(vm, inputPropertyOffset, input); return array; } Structure* createRegExpMatchesArrayStructure(VM& vm, JSGlobalObject& globalObject) { Structure* structure = globalObject.arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous); PropertyOffset offset; structure = structure->addPropertyTransition(vm, structure, vm.propertyNames->index, 0, offset); ASSERT(offset == indexPropertyOffset); structure = structure->addPropertyTransition(vm, structure, vm.propertyNames->input, 0, offset); ASSERT(offset == inputPropertyOffset); return structure; } } // namespace JSC