static void appendProxyServerString(StringBuilder& builder, const ProxyServer& proxyServer) { switch (proxyServer.type()) { case ProxyServer::Direct: builder.append("DIRECT"); return; case ProxyServer::HTTP: case ProxyServer::HTTPS: builder.append("PROXY"); break; case ProxyServer::SOCKS: builder.append("SOCKS"); break; } builder.append(' '); ASSERT(!proxyServer.hostName().isNull()); builder.append(proxyServer.hostName()); builder.append(':'); ASSERT(proxyServer.port() != -1); builder.appendNumber(proxyServer.port()); }
void MarkupAccumulator::appendNamespace(StringBuilder& result, const AtomicString& prefix, const AtomicString& namespaceURI, Namespaces& namespaces) { namespaces.checkConsistency(); if (namespaceURI.isEmpty()) return; // Use emptyAtoms's impl() for both null and empty strings since the HashMap can't handle 0 as a key AtomicStringImpl* pre = prefix.isEmpty() ? emptyAtom.impl() : prefix.impl(); AtomicStringImpl* foundNS = namespaces.get(pre); if (foundNS != namespaceURI.impl()) { namespaces.set(pre, namespaceURI.impl()); result.append(' '); result.append(xmlnsAtom.string()); if (!prefix.isEmpty()) { result.append(':'); result.append(prefix); } result.append('='); result.append('"'); appendAttributeValue(result, namespaceURI, false); result.append('"'); } }
void MarkupAccumulator::appendAttribute(StringBuilder& result, Element* element, const Attribute& attribute, Namespaces* namespaces) { bool documentIsHTML = element->document()->isHTMLDocument(); result.append(' '); if (documentIsHTML) result.append(attribute.name().localName()); else result.append(attribute.name().toString()); result.append('='); if (element->isURLAttribute(const_cast<Attribute*>(&attribute))) appendQuotedURLAttributeValue(result, element, attribute); else { result.append('\"'); appendAttributeValue(result, attribute.value(), documentIsHTML); result.append('\"'); } if (!documentIsHTML && namespaces && shouldAddNamespaceAttribute(attribute, *namespaces)) appendNamespace(result, attribute.prefix(), attribute.namespaceURI(), *namespaces); }
void MarkupAccumulator::appendAttribute(StringBuilder& result, const Element& element, const Attribute& attribute, Namespaces* namespaces) { bool documentIsHTML = serializeAsHTMLDocument(element); result.append(' '); QualifiedName prefixedName = attribute.name(); if (documentIsHTML && !attributeIsInSerializedNamespace(attribute)) { result.append(attribute.name().localName()); } else { if (attribute.namespaceURI() == XLinkNames::xlinkNamespaceURI) { if (!attribute.prefix()) prefixedName.setPrefix(xlinkAtom); } else if (attribute.namespaceURI() == XMLNames::xmlNamespaceURI) { if (!attribute.prefix()) prefixedName.setPrefix(xmlAtom); } else if (attribute.namespaceURI() == XMLNSNames::xmlnsNamespaceURI) { if (attribute.name() != XMLNSNames::xmlnsAttr && !attribute.prefix()) prefixedName.setPrefix(xmlnsAtom); } result.append(prefixedName.toString()); } result.append('='); if (element.isURLAttribute(attribute)) { appendQuotedURLAttributeValue(result, element, attribute); } else { result.append('"'); appendAttributeValue(result, attribute.value(), documentIsHTML); result.append('"'); } if (!documentIsHTML && namespaces && shouldAddNamespaceAttribute(attribute, *namespaces)) appendNamespace(result, prefixedName.prefix(), prefixedName.namespaceURI(), *namespaces); }
String ViewGestureController::SnapshotRemovalTracker::eventsDescription(Events event) { StringBuilder description; if (event & ViewGestureController::SnapshotRemovalTracker::VisuallyNonEmptyLayout) description.append("VisuallyNonEmptyLayout "); if (event & ViewGestureController::SnapshotRemovalTracker::RenderTreeSizeThreshold) description.append("RenderTreeSizeThreshold "); if (event & ViewGestureController::SnapshotRemovalTracker::RepaintAfterNavigation) description.append("RepaintAfterNavigation "); if (event & ViewGestureController::SnapshotRemovalTracker::MainFrameLoad) description.append("MainFrameLoad "); if (event & ViewGestureController::SnapshotRemovalTracker::SubresourceLoads) description.append("SubresourceLoads "); if (event & ViewGestureController::SnapshotRemovalTracker::ScrollPositionRestoration) description.append("ScrollPositionRestoration "); return description.toString(); }
// Specification of the input: // http://icu-project.org/apiref/icu4c/classSimpleDateFormat.html#details static String localizeFormat(const String& buffer) { StringBuilder builder; UChar lastChar = 0; bool inQuote = false; for (unsigned i = 0; i < buffer.length(); ++i) { if (inQuote) { if (buffer[i] == '\'') { inQuote = false; lastChar = 0; ASSERT(i); if (buffer[i - 1] == '\'') builder.append('\''); } else builder.append(buffer[i]); } else { if (isASCIIAlpha(lastChar) && lastChar == buffer[i]) continue; lastChar = buffer[i]; if (isICUYearSymbol(lastChar)) { String text = dateFormatYearText(); builder.append(text.isEmpty() ? "Year" : text); } else if (isICUMonthSymbol(lastChar)) { String text = dateFormatMonthText(); builder.append(text.isEmpty() ? "Month" : text); } else if (isICUDayInMonthSymbol(lastChar)) { String text = dateFormatDayInMonthText(); builder.append(text.isEmpty() ? "Day" : text); } else if (lastChar == '\'') inQuote = true; else builder.append(lastChar); } } return builder.toString(); }
KURL DOMFileSystemBase::createFileSystemURL(const String& fullPath) const { ASSERT(DOMFilePath::isAbsolute(fullPath)); if (type() == FileSystemTypeExternal) { // For external filesystem originString could be different from what we have in m_filesystemRootURL. StringBuilder result; result.append("filesystem:"); result.append(securityOrigin()->toString()); result.append("/"); result.append(externalPathPrefix); result.append(m_filesystemRootURL.path()); // Remove the extra leading slash. result.append(encodeWithURLEscapeSequences(fullPath.substring(1))); return KURL(ParsedURLString, result.toString()); } // For regular types we can just append the entry's fullPath to the m_filesystemRootURL that should look like 'filesystem:<origin>/<typePrefix>'. ASSERT(!m_filesystemRootURL.isEmpty()); KURL url = m_filesystemRootURL; // Remove the extra leading slash. url.setPath(url.path() + encodeWithURLEscapeSequences(fullPath.substring(1))); return url; }
String fromUChar32(UChar32 c) { StringBuilder input; input.append(c); return input.toString(); }
void MarkupAccumulator::appendDocumentType(StringBuilder& result, const DocumentType* n) { if (n->name().isEmpty()) return; result.append("<!DOCTYPE "); result.append(n->name()); if (!n->publicId().isEmpty()) { result.append(" PUBLIC \""); result.append(n->publicId()); result.append("\""); if (!n->systemId().isEmpty()) { result.append(" \""); result.append(n->systemId()); result.append("\""); } } else if (!n->systemId().isEmpty()) { result.append(" SYSTEM \""); result.append(n->systemId()); result.append("\""); } if (!n->internalSubset().isEmpty()) { result.append(" ["); result.append(n->internalSubset()); result.append("]"); } result.append(">"); }
String StylePropertySet::asText() const { StringBuilder result; int positionXPropertyIndex = -1; int positionYPropertyIndex = -1; int repeatXPropertyIndex = -1; int repeatYPropertyIndex = -1; BitArray<numCSSProperties> shorthandPropertyUsed; BitArray<numCSSProperties> shorthandPropertyAppeared; unsigned size = propertyCount(); unsigned numDecls = 0; for (unsigned n = 0; n < size; ++n) { PropertyReference property = propertyAt(n); CSSPropertyID propertyID = property.id(); CSSPropertyID shorthandPropertyID = CSSPropertyInvalid; CSSPropertyID borderFallbackShorthandProperty = CSSPropertyInvalid; String value; switch (propertyID) { #if ENABLE(CSS_VARIABLES) case CSSPropertyVariable: if (numDecls++) result.append(' '); result.append(property.cssText()); continue; #endif case CSSPropertyBackgroundPositionX: positionXPropertyIndex = n; continue; case CSSPropertyBackgroundPositionY: positionYPropertyIndex = n; continue; case CSSPropertyBackgroundRepeatX: repeatXPropertyIndex = n; continue; case CSSPropertyBackgroundRepeatY: repeatYPropertyIndex = n; continue; case CSSPropertyBorderTopWidth: case CSSPropertyBorderRightWidth: case CSSPropertyBorderBottomWidth: case CSSPropertyBorderLeftWidth: if (!borderFallbackShorthandProperty) borderFallbackShorthandProperty = CSSPropertyBorderWidth; case CSSPropertyBorderTopStyle: case CSSPropertyBorderRightStyle: case CSSPropertyBorderBottomStyle: case CSSPropertyBorderLeftStyle: if (!borderFallbackShorthandProperty) borderFallbackShorthandProperty = CSSPropertyBorderStyle; case CSSPropertyBorderTopColor: case CSSPropertyBorderRightColor: case CSSPropertyBorderBottomColor: case CSSPropertyBorderLeftColor: if (!borderFallbackShorthandProperty) borderFallbackShorthandProperty = CSSPropertyBorderColor; // FIXME: Deal with cases where only some of border-(top|right|bottom|left) are specified. if (!shorthandPropertyAppeared.get(CSSPropertyBorder - firstCSSProperty)) { value = borderPropertyValue(ReturnNullOnUncommonValues); if (value.isNull()) shorthandPropertyAppeared.set(CSSPropertyBorder - firstCSSProperty); else shorthandPropertyID = CSSPropertyBorder; } else if (shorthandPropertyUsed.get(CSSPropertyBorder - firstCSSProperty)) shorthandPropertyID = CSSPropertyBorder; if (!shorthandPropertyID) shorthandPropertyID = borderFallbackShorthandProperty; break; case CSSPropertyWebkitBorderHorizontalSpacing: case CSSPropertyWebkitBorderVerticalSpacing: shorthandPropertyID = CSSPropertyBorderSpacing; break; case CSSPropertyFontFamily: case CSSPropertyLineHeight: case CSSPropertyFontSize: case CSSPropertyFontStyle: case CSSPropertyFontVariant: case CSSPropertyFontWeight: // Don't use CSSPropertyFont because old UAs can't recognize them but are important for editing. break; case CSSPropertyListStyleType: case CSSPropertyListStylePosition: case CSSPropertyListStyleImage: shorthandPropertyID = CSSPropertyListStyle; break; case CSSPropertyMarginTop: case CSSPropertyMarginRight: case CSSPropertyMarginBottom: case CSSPropertyMarginLeft: shorthandPropertyID = CSSPropertyMargin; break; case CSSPropertyOutlineWidth: case CSSPropertyOutlineStyle: case CSSPropertyOutlineColor: shorthandPropertyID = CSSPropertyOutline; break; case CSSPropertyOverflowX: case CSSPropertyOverflowY: shorthandPropertyID = CSSPropertyOverflow; break; case CSSPropertyPaddingTop: case CSSPropertyPaddingRight: case CSSPropertyPaddingBottom: case CSSPropertyPaddingLeft: shorthandPropertyID = CSSPropertyPadding; break; case CSSPropertyWebkitAnimationName: case CSSPropertyWebkitAnimationDuration: case CSSPropertyWebkitAnimationTimingFunction: case CSSPropertyWebkitAnimationDelay: case CSSPropertyWebkitAnimationIterationCount: case CSSPropertyWebkitAnimationDirection: case CSSPropertyWebkitAnimationFillMode: shorthandPropertyID = CSSPropertyWebkitAnimation; break; case CSSPropertyWebkitFlexDirection: case CSSPropertyWebkitFlexWrap: shorthandPropertyID = CSSPropertyWebkitFlexFlow; break; case CSSPropertyWebkitFlexBasis: case CSSPropertyWebkitFlexGrow: case CSSPropertyWebkitFlexShrink: shorthandPropertyID = CSSPropertyWebkitFlex; break; case CSSPropertyWebkitMaskPositionX: case CSSPropertyWebkitMaskPositionY: case CSSPropertyWebkitMaskRepeatX: case CSSPropertyWebkitMaskRepeatY: case CSSPropertyWebkitMaskImage: case CSSPropertyWebkitMaskRepeat: case CSSPropertyWebkitMaskPosition: case CSSPropertyWebkitMaskClip: case CSSPropertyWebkitMaskOrigin: shorthandPropertyID = CSSPropertyWebkitMask; break; case CSSPropertyWebkitTransformOriginX: case CSSPropertyWebkitTransformOriginY: case CSSPropertyWebkitTransformOriginZ: shorthandPropertyID = CSSPropertyWebkitTransformOrigin; break; case CSSPropertyWebkitTransitionProperty: case CSSPropertyWebkitTransitionDuration: case CSSPropertyWebkitTransitionTimingFunction: case CSSPropertyWebkitTransitionDelay: shorthandPropertyID = CSSPropertyWebkitTransition; break; #if ENABLE(CSS_EXCLUSIONS) case CSSPropertyWebkitWrapFlow: case CSSPropertyWebkitShapeMargin: case CSSPropertyWebkitShapePadding: shorthandPropertyID = CSSPropertyWebkitWrap; break; #endif default: break; } unsigned shortPropertyIndex = shorthandPropertyID - firstCSSProperty; if (shorthandPropertyID) { if (shorthandPropertyUsed.get(shortPropertyIndex)) continue; if (!shorthandPropertyAppeared.get(shortPropertyIndex) && value.isNull()) value = getPropertyValue(shorthandPropertyID); shorthandPropertyAppeared.set(shortPropertyIndex); } if (!value.isNull()) { propertyID = shorthandPropertyID; shorthandPropertyUsed.set(shortPropertyIndex); } else value = property.value()->cssText(); if (value == "initial" && !CSSProperty::isInheritedProperty(propertyID)) continue; if (numDecls++) result.append(' '); result.append(getPropertyName(propertyID)); result.appendLiteral(": "); result.append(value); if (property.isImportant()) result.appendLiteral(" !important"); result.append(';'); } // FIXME: This is a not-so-nice way to turn x/y positions into single background-position in output. // It is required because background-position-x/y are non-standard properties and WebKit generated output // would not work in Firefox (<rdar://problem/5143183>) // It would be a better solution if background-position was CSS_PAIR. if (positionXPropertyIndex != -1 && positionYPropertyIndex != -1 && propertyAt(positionXPropertyIndex).isImportant() == propertyAt(positionYPropertyIndex).isImportant()) { PropertyReference positionXProperty = propertyAt(positionXPropertyIndex); PropertyReference positionYProperty = propertyAt(positionYPropertyIndex); if (numDecls++) result.append(' '); result.appendLiteral("background-position: "); if (positionXProperty.value()->isValueList() || positionYProperty.value()->isValueList()) result.append(getLayeredShorthandValue(backgroundPositionShorthand())); else { result.append(positionXProperty.value()->cssText()); result.append(' '); result.append(positionYProperty.value()->cssText()); } if (positionXProperty.isImportant()) result.appendLiteral(" !important"); result.append(';'); } else { if (positionXPropertyIndex != -1) { if (numDecls++) result.append(' '); result.append(propertyAt(positionXPropertyIndex).cssText()); } if (positionYPropertyIndex != -1) { if (numDecls++) result.append(' '); result.append(propertyAt(positionYPropertyIndex).cssText()); } } // FIXME: We need to do the same for background-repeat. if (repeatXPropertyIndex != -1 && repeatYPropertyIndex != -1 && propertyAt(repeatXPropertyIndex).isImportant() == propertyAt(repeatYPropertyIndex).isImportant()) { PropertyReference repeatXProperty = propertyAt(repeatXPropertyIndex); PropertyReference repeatYProperty = propertyAt(repeatYPropertyIndex); if (numDecls++) result.append(' '); result.appendLiteral("background-repeat: "); if (repeatXProperty.value()->isValueList() || repeatYProperty.value()->isValueList()) result.append(getLayeredShorthandValue(backgroundRepeatShorthand())); else { result.append(repeatXProperty.value()->cssText()); result.append(' '); result.append(repeatYProperty.value()->cssText()); } if (repeatXProperty.isImportant()) result.appendLiteral(" !important"); result.append(';'); } else { if (repeatXPropertyIndex != -1) { if (numDecls++) result.append(' '); result.append(propertyAt(repeatXPropertyIndex).cssText()); } if (repeatYPropertyIndex != -1) { if (numDecls++) result.append(' '); result.append(propertyAt(repeatYPropertyIndex).cssText()); } } ASSERT(!numDecls ^ !result.isEmpty()); return result.toString(); }
String FontValue::customCssText() const { // font variant weight size / line-height family StringBuilder result; if (style) result.append(style->cssText()); if (variant) { if (!result.isEmpty()) result.append(' '); result.append(variant->cssText()); } if (weight) { if (!result.isEmpty()) result.append(' '); result.append(weight->cssText()); } if (size) { if (!result.isEmpty()) result.append(' '); result.append(size->cssText()); } if (lineHeight) { if (!size) result.append(' '); result.append('/'); result.append(lineHeight->cssText()); } if (family) { if (!result.isEmpty()) result.append(' '); result.append(family->cssText()); } return result.toString(); }
String WebPageSerializerImpl::preActionBeforeSerializeOpenTag( const Element* element, SerializeDomParam* param, bool* needSkip) { StringBuilder result; *needSkip = false; if (param->isHTMLDocument) { // Skip the open tag of original META tag which declare charset since we // have overrided the META which have correct charset declaration after // serializing open tag of HEAD element. ASSERT(element); if (isHTMLMetaElement(*element)) { const HTMLMetaElement& meta = toHTMLMetaElement(*element); // Check whether the META tag has declared charset or not. String equiv = meta.httpEquiv(); if (equalIgnoringCase(equiv, "content-type")) { String content = meta.content(); if (content.length() && content.contains("charset", false)) { // Find META tag declared charset, we need to skip it when // serializing DOM. param->skipMetaElement = element; *needSkip = true; } } } else if (isHTMLHtmlElement(*element)) { // Check something before processing the open tag of HEAD element. // First we add doc type declaration if original document has it. if (!param->haveSeenDocType) { param->haveSeenDocType = true; result.append(createMarkup(param->document->doctype())); } // Add MOTW declaration before html tag. // See http://msdn2.microsoft.com/en-us/library/ms537628(VS.85).aspx. result.append(WebPageSerializer::generateMarkOfTheWebDeclaration(param->url)); } else if (isHTMLBaseElement(*element)) { // Comment the BASE tag when serializing dom. result.append("<!--"); } } else { // Write XML declaration. if (!param->haveAddedXMLProcessingDirective) { param->haveAddedXMLProcessingDirective = true; // Get encoding info. String xmlEncoding = param->document->xmlEncoding(); if (xmlEncoding.isEmpty()) xmlEncoding = param->document->encodingName(); if (xmlEncoding.isEmpty()) xmlEncoding = UTF8Encoding().name(); result.append("<?xml version=\""); result.append(param->document->xmlVersion()); result.append("\" encoding=\""); result.append(xmlEncoding); if (param->document->xmlStandalone()) result.append("\" standalone=\"yes"); result.append("\"?>\n"); } // Add doc type declaration if original document has it. if (!param->haveSeenDocType) { param->haveSeenDocType = true; result.append(createMarkup(param->document->doctype())); } } return result.toString(); }
int testExecutionTimeLimit() { static const TierOptions tierOptionsList[] = { { "LLINT", 0, "--useConcurrentJIT=false --useLLInt=true --useJIT=false" }, { "Baseline", 0, "--useConcurrentJIT=false --useLLInt=true --useJIT=true --useDFGJIT=false" }, { "DFG", 0, "--useConcurrentJIT=false --useLLInt=true --useJIT=true --useDFGJIT=true --useFTLJIT=false" }, { "FTL", 200, "--useConcurrentJIT=false --useLLInt=true --useJIT=true --useDFGJIT=true --useFTLJIT=true" }, }; bool failed = false; JSC::initializeThreading(); Options::initialize(); // Ensure options is initialized first. for (auto tierOptions : tierOptionsList) { StringBuilder savedOptionsBuilder; Options::dumpAllOptionsInALine(savedOptionsBuilder); Options::setOptions(tierOptions.optionsStr); unsigned tierAdjustmentMillis = tierOptions.timeLimitAdjustmentMillis; double timeLimit; context = JSGlobalContextCreateInGroup(nullptr, nullptr); JSContextGroupRef contextGroup = JSContextGetGroup(context); JSObjectRef globalObject = JSContextGetGlobalObject(context); ASSERT(JSValueIsObject(context, globalObject)); JSValueRef exception = nullptr; JSStringRef currentCPUTimeStr = JSStringCreateWithUTF8CString("currentCPUTime"); JSObjectRef currentCPUTimeFunction = JSObjectMakeFunctionWithCallback(context, currentCPUTimeStr, currentCPUTimeAsJSFunctionCallback); JSObjectSetProperty(context, globalObject, currentCPUTimeStr, currentCPUTimeFunction, kJSPropertyAttributeNone, nullptr); JSStringRelease(currentCPUTimeStr); /* Test script timeout: */ timeLimit = (100 + tierAdjustmentMillis) / 1000.0; JSContextGroupSetExecutionTimeLimit(contextGroup, timeLimit, shouldTerminateCallback, 0); { unsigned timeAfterWatchdogShouldHaveFired = 300 + tierAdjustmentMillis; StringBuilder scriptBuilder; scriptBuilder.append("function foo() { var startTime = currentCPUTime(); while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > "); scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0); scriptBuilder.append(") break; } } foo();"); JSStringRef script = JSStringCreateWithUTF8CString(scriptBuilder.toString().utf8().data()); exception = nullptr; shouldTerminateCallbackWasCalled = false; auto startTime = currentCPUTime(); JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception); auto endTime = currentCPUTime(); if (((endTime - startTime) < milliseconds(timeAfterWatchdogShouldHaveFired)) && shouldTerminateCallbackWasCalled) printf("PASS: %s script timed out as expected.\n", tierOptions.tier); else { if ((endTime - startTime) >= milliseconds(timeAfterWatchdogShouldHaveFired)) printf("FAIL: %s script did not time out as expected.\n", tierOptions.tier); if (!shouldTerminateCallbackWasCalled) printf("FAIL: %s script timeout callback was not called.\n", tierOptions.tier); failed = true; } if (!exception) { printf("FAIL: %s TerminatedExecutionException was not thrown.\n", tierOptions.tier); failed = true; } testResetAfterTimeout(failed); } /* Test script timeout with tail calls: */ timeLimit = (100 + tierAdjustmentMillis) / 1000.0; JSContextGroupSetExecutionTimeLimit(contextGroup, timeLimit, shouldTerminateCallback, 0); { unsigned timeAfterWatchdogShouldHaveFired = 300 + tierAdjustmentMillis; StringBuilder scriptBuilder; scriptBuilder.append("var startTime = currentCPUTime();" "function recurse(i) {" "'use strict';" "if (i % 1000 === 0) {" "if (currentCPUTime() - startTime >"); scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0); scriptBuilder.append(" ) { return; }"); scriptBuilder.append(" }"); scriptBuilder.append(" return recurse(i + 1); }"); scriptBuilder.append("recurse(0);"); JSStringRef script = JSStringCreateWithUTF8CString(scriptBuilder.toString().utf8().data()); exception = nullptr; shouldTerminateCallbackWasCalled = false; auto startTime = currentCPUTime(); JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception); auto endTime = currentCPUTime(); if (((endTime - startTime) < milliseconds(timeAfterWatchdogShouldHaveFired)) && shouldTerminateCallbackWasCalled) printf("PASS: %s script with infinite tail calls timed out as expected .\n", tierOptions.tier); else { if ((endTime - startTime) >= milliseconds(timeAfterWatchdogShouldHaveFired)) printf("FAIL: %s script with infinite tail calls did not time out as expected.\n", tierOptions.tier); if (!shouldTerminateCallbackWasCalled) printf("FAIL: %s script with infinite tail calls' timeout callback was not called.\n", tierOptions.tier); failed = true; } if (!exception) { printf("FAIL: %s TerminatedExecutionException was not thrown.\n", tierOptions.tier); failed = true; } testResetAfterTimeout(failed); } /* Test the script timeout's TerminatedExecutionException should NOT be catchable: */ timeLimit = (100 + tierAdjustmentMillis) / 1000.0; JSContextGroupSetExecutionTimeLimit(contextGroup, timeLimit, shouldTerminateCallback, 0); { unsigned timeAfterWatchdogShouldHaveFired = 300 + tierAdjustmentMillis; StringBuilder scriptBuilder; scriptBuilder.append("function foo() { var startTime = currentCPUTime(); try { while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > "); scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0); scriptBuilder.append(") break; } } catch(e) { } } foo();"); JSStringRef script = JSStringCreateWithUTF8CString(scriptBuilder.toString().utf8().data()); exception = nullptr; shouldTerminateCallbackWasCalled = false; auto startTime = currentCPUTime(); JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception); auto endTime = currentCPUTime(); if (((endTime - startTime) >= milliseconds(timeAfterWatchdogShouldHaveFired)) || !shouldTerminateCallbackWasCalled) { if (!((endTime - startTime) < milliseconds(timeAfterWatchdogShouldHaveFired))) printf("FAIL: %s script did not time out as expected.\n", tierOptions.tier); if (!shouldTerminateCallbackWasCalled) printf("FAIL: %s script timeout callback was not called.\n", tierOptions.tier); failed = true; } if (exception) printf("PASS: %s TerminatedExecutionException was not catchable as expected.\n", tierOptions.tier); else { printf("FAIL: %s TerminatedExecutionException was caught.\n", tierOptions.tier); failed = true; } testResetAfterTimeout(failed); } /* Test script timeout with no callback: */ timeLimit = (100 + tierAdjustmentMillis) / 1000.0; JSContextGroupSetExecutionTimeLimit(contextGroup, timeLimit, 0, 0); { unsigned timeAfterWatchdogShouldHaveFired = 300 + tierAdjustmentMillis; StringBuilder scriptBuilder; scriptBuilder.append("function foo() { var startTime = currentCPUTime(); while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > "); scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0); scriptBuilder.append(") break; } } foo();"); JSStringRef script = JSStringCreateWithUTF8CString(scriptBuilder.toString().utf8().data()); exception = nullptr; shouldTerminateCallbackWasCalled = false; auto startTime = currentCPUTime(); JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception); auto endTime = currentCPUTime(); if (((endTime - startTime) < milliseconds(timeAfterWatchdogShouldHaveFired)) && !shouldTerminateCallbackWasCalled) printf("PASS: %s script timed out as expected when no callback is specified.\n", tierOptions.tier); else { if ((endTime - startTime) >= milliseconds(timeAfterWatchdogShouldHaveFired)) printf("FAIL: %s script did not time out as expected when no callback is specified.\n", tierOptions.tier); else printf("FAIL: %s script called stale callback function.\n", tierOptions.tier); failed = true; } if (!exception) { printf("FAIL: %s TerminatedExecutionException was not thrown.\n", tierOptions.tier); failed = true; } testResetAfterTimeout(failed); } /* Test script timeout cancellation: */ timeLimit = (100 + tierAdjustmentMillis) / 1000.0; JSContextGroupSetExecutionTimeLimit(contextGroup, timeLimit, cancelTerminateCallback, 0); { unsigned timeAfterWatchdogShouldHaveFired = 300 + tierAdjustmentMillis; StringBuilder scriptBuilder; scriptBuilder.append("function foo() { var startTime = currentCPUTime(); while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > "); scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0); scriptBuilder.append(") break; } } foo();"); JSStringRef script = JSStringCreateWithUTF8CString(scriptBuilder.toString().utf8().data()); exception = nullptr; cancelTerminateCallbackWasCalled = false; auto startTime = currentCPUTime(); JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception); auto endTime = currentCPUTime(); if (((endTime - startTime) >= milliseconds(timeAfterWatchdogShouldHaveFired)) && cancelTerminateCallbackWasCalled && !exception) printf("PASS: %s script timeout was cancelled as expected.\n", tierOptions.tier); else { if (((endTime - startTime) < milliseconds(timeAfterWatchdogShouldHaveFired)) || exception) printf("FAIL: %s script timeout was not cancelled.\n", tierOptions.tier); if (!cancelTerminateCallbackWasCalled) printf("FAIL: %s script timeout callback was not called.\n", tierOptions.tier); failed = true; } if (exception) { printf("FAIL: %s Unexpected TerminatedExecutionException thrown.\n", tierOptions.tier); failed = true; } } /* Test script timeout extension: */ timeLimit = (100 + tierAdjustmentMillis) / 1000.0; JSContextGroupSetExecutionTimeLimit(contextGroup, timeLimit, extendTerminateCallback, 0); { unsigned timeBeforeExtendedDeadline = 250 + tierAdjustmentMillis; unsigned timeAfterExtendedDeadline = 600 + tierAdjustmentMillis; unsigned maxBusyLoopTime = 750 + tierAdjustmentMillis; StringBuilder scriptBuilder; scriptBuilder.append("function foo() { var startTime = currentCPUTime(); while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > "); scriptBuilder.appendNumber(maxBusyLoopTime / 1000.0); // in seconds. scriptBuilder.append(") break; } } foo();"); JSStringRef script = JSStringCreateWithUTF8CString(scriptBuilder.toString().utf8().data()); exception = nullptr; extendTerminateCallbackCalled = 0; auto startTime = currentCPUTime(); JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception); auto endTime = currentCPUTime(); auto deltaTime = endTime - startTime; if ((deltaTime >= milliseconds(timeBeforeExtendedDeadline)) && (deltaTime < milliseconds(timeAfterExtendedDeadline)) && (extendTerminateCallbackCalled == 2) && exception) printf("PASS: %s script timeout was extended as expected.\n", tierOptions.tier); else { if (deltaTime < milliseconds(timeBeforeExtendedDeadline)) printf("FAIL: %s script timeout was not extended as expected.\n", tierOptions.tier); else if (deltaTime >= milliseconds(timeAfterExtendedDeadline)) printf("FAIL: %s script did not timeout.\n", tierOptions.tier); if (extendTerminateCallbackCalled < 1) printf("FAIL: %s script timeout callback was not called.\n", tierOptions.tier); if (extendTerminateCallbackCalled < 2) printf("FAIL: %s script timeout callback was not called after timeout extension.\n", tierOptions.tier); if (!exception) printf("FAIL: %s TerminatedExecutionException was not thrown during timeout extension test.\n", tierOptions.tier); failed = true; } } JSGlobalContextRelease(context); Options::setOptions(savedOptionsBuilder.toString().ascii().data()); } return failed; }
static WTF::String specialDrawingTypeAsDebugString(DisplayItem::Type type) { if (type >= DisplayItem::TableCollapsedBorderUnalignedBase) { if (type <= DisplayItem::TableCollapsedBorderBase) return "TableCollapsedBorderAlignment"; if (type <= DisplayItem::TableCollapsedBorderLast) { StringBuilder sb; sb.append("TableCollapsedBorder"); if (type & DisplayItem::TableCollapsedBorderTop) sb.append("Top"); if (type & DisplayItem::TableCollapsedBorderRight) sb.append("Right"); if (type & DisplayItem::TableCollapsedBorderBottom) sb.append("Bottom"); if (type & DisplayItem::TableCollapsedBorderLeft) sb.append("Left"); return sb.toString(); } } switch (type) { DEBUG_STRING_CASE(BoxDecorationBackground); DEBUG_STRING_CASE(Caret); DEBUG_STRING_CASE(ColumnRules); DEBUG_STRING_CASE(DebugRedFill); DEBUG_STRING_CASE(DragImage); DEBUG_STRING_CASE(SVGImage); DEBUG_STRING_CASE(LinkHighlight); DEBUG_STRING_CASE(PageOverlay); DEBUG_STRING_CASE(PageWidgetDelegateBackgroundFallback); DEBUG_STRING_CASE(PopupContainerBorder); DEBUG_STRING_CASE(PopupListBoxBackground); DEBUG_STRING_CASE(PopupListBoxRow); DEBUG_STRING_CASE(PrintedContentBackground); DEBUG_STRING_CASE(PrintedContentDestinationLocations); DEBUG_STRING_CASE(PrintedContentLineBoundary); DEBUG_STRING_CASE(PrintedContentPDFURLRect); DEBUG_STRING_CASE(Resizer); DEBUG_STRING_CASE(SVGClip); DEBUG_STRING_CASE(SVGFilter); DEBUG_STRING_CASE(SVGMask); DEBUG_STRING_CASE(ScrollbarBackButtonEnd); DEBUG_STRING_CASE(ScrollbarBackButtonStart); DEBUG_STRING_CASE(ScrollbarBackground); DEBUG_STRING_CASE(ScrollbarBackTrack); DEBUG_STRING_CASE(ScrollbarCorner); DEBUG_STRING_CASE(ScrollbarForwardButtonEnd); DEBUG_STRING_CASE(ScrollbarForwardButtonStart); DEBUG_STRING_CASE(ScrollbarForwardTrack); DEBUG_STRING_CASE(ScrollbarHorizontal); DEBUG_STRING_CASE(ScrollbarThumb); DEBUG_STRING_CASE(ScrollbarTickmarks); DEBUG_STRING_CASE(ScrollbarTrackBackground); DEBUG_STRING_CASE(ScrollbarVertical); DEBUG_STRING_CASE(SelectionGap); DEBUG_STRING_CASE(SelectionTint); DEBUG_STRING_CASE(TableCellBackgroundFromColumnGroup); DEBUG_STRING_CASE(TableCellBackgroundFromColumn); DEBUG_STRING_CASE(TableCellBackgroundFromSection); DEBUG_STRING_CASE(TableCellBackgroundFromRow); DEBUG_STRING_CASE(VideoBitmap); DEBUG_STRING_CASE(WebPlugin); DEBUG_STRING_CASE(WebFont); DEFAULT_CASE; } }
void StylePropertySerializer::appendBackgroundPropertyAsText(StringBuilder& result, unsigned& numDecls) const { if (isPropertyShorthandAvailable(backgroundShorthand())) { String backgroundValue = getPropertyValue(CSSPropertyBackground); bool isImportant = m_propertySet.propertyIsImportant(CSSPropertyBackgroundImage); result.append(getPropertyText(CSSPropertyBackground, backgroundValue, isImportant, numDecls++)); return; } if (shorthandHasOnlyInitialOrInheritedValue(backgroundShorthand())) { RefPtrWillBeRawPtr<CSSValue> value = m_propertySet.getPropertyCSSValue(CSSPropertyBackgroundImage); bool isImportant = m_propertySet.propertyIsImportant(CSSPropertyBackgroundImage); result.append(getPropertyText(CSSPropertyBackground, value->cssText(), isImportant, numDecls++)); return; } // backgroundShorthandProperty without layered shorhand properties const CSSPropertyID backgroundPropertyIds[] = { CSSPropertyBackgroundImage, CSSPropertyBackgroundAttachment, CSSPropertyBackgroundColor, CSSPropertyBackgroundSize, CSSPropertyBackgroundOrigin, CSSPropertyBackgroundClip }; for (unsigned i = 0; i < WTF_ARRAY_LENGTH(backgroundPropertyIds); ++i) { CSSPropertyID propertyID = backgroundPropertyIds[i]; RefPtrWillBeRawPtr<CSSValue> value = m_propertySet.getPropertyCSSValue(propertyID); if (!value) continue; result.append(getPropertyText(propertyID, value->cssText(), m_propertySet.propertyIsImportant(propertyID), numDecls++)); } // FIXME: This is a not-so-nice way to turn x/y positions into single background-position in output. // It is required because background-position-x/y are non-standard properties and WebKit generated output // would not work in Firefox (<rdar://problem/5143183>) // It would be a better solution if background-position was CSS_PAIR. if (shorthandHasOnlyInitialOrInheritedValue(backgroundPositionShorthand())) { RefPtrWillBeRawPtr<CSSValue> value = m_propertySet.getPropertyCSSValue(CSSPropertyBackgroundPositionX); bool isImportant = m_propertySet.propertyIsImportant(CSSPropertyBackgroundPositionX); result.append(getPropertyText(CSSPropertyBackgroundPosition, value->cssText(), isImportant, numDecls++)); } else if (isPropertyShorthandAvailable(backgroundPositionShorthand())) { String positionValue = m_propertySet.getPropertyValue(CSSPropertyBackgroundPosition); bool isImportant = m_propertySet.propertyIsImportant(CSSPropertyBackgroundPositionX); if (!positionValue.isNull()) result.append(getPropertyText(CSSPropertyBackgroundPosition, positionValue, isImportant, numDecls++)); } else { // should check background-position-x or background-position-y. if (RefPtrWillBeRawPtr<CSSValue> value = m_propertySet.getPropertyCSSValue(CSSPropertyBackgroundPositionX)) { if (!value->isImplicitInitialValue()) { bool isImportant = m_propertySet.propertyIsImportant(CSSPropertyBackgroundPositionX); result.append(getPropertyText(CSSPropertyBackgroundPositionX, value->cssText(), isImportant, numDecls++)); } } if (RefPtrWillBeRawPtr<CSSValue> value = m_propertySet.getPropertyCSSValue(CSSPropertyBackgroundPositionY)) { if (!value->isImplicitInitialValue()) { bool isImportant = m_propertySet.propertyIsImportant(CSSPropertyBackgroundPositionY); result.append(getPropertyText(CSSPropertyBackgroundPositionY, value->cssText(), isImportant, numDecls++)); } } } String repeatValue = m_propertySet.getPropertyValue(CSSPropertyBackgroundRepeat); if (!repeatValue.isNull()) result.append(getPropertyText(CSSPropertyBackgroundRepeat, repeatValue, m_propertySet.propertyIsImportant(CSSPropertyBackgroundRepeatX), numDecls++)); }
// "inline" is required here to help WINSCW compiler resolve specialized argument in templated functions. template <LiteralParser::ParserMode mode> inline LiteralParser::TokenType LiteralParser::Lexer::lexString(LiteralParserToken& token) { ++m_ptr; const UChar* runStart; StringBuilder builder; do { runStart = m_ptr; while (m_ptr < m_end && isSafeStringCharacter<mode>(*m_ptr)) ++m_ptr; if (runStart < m_ptr) builder.append(runStart, m_ptr - runStart); if ((mode == StrictJSON) && m_ptr < m_end && *m_ptr == '\\') { ++m_ptr; if (m_ptr >= m_end) return TokError; switch (*m_ptr) { case '"': builder.append('"'); m_ptr++; break; case '\\': builder.append('\\'); m_ptr++; break; case '/': builder.append('/'); m_ptr++; break; case 'b': builder.append('\b'); m_ptr++; break; case 'f': builder.append('\f'); m_ptr++; break; case 'n': builder.append('\n'); m_ptr++; break; case 'r': builder.append('\r'); m_ptr++; break; case 't': builder.append('\t'); m_ptr++; break; case 'u': if ((m_end - m_ptr) < 5) // uNNNN == 5 characters return TokError; for (int i = 1; i < 5; i++) { if (!isASCIIHexDigit(m_ptr[i])) return TokError; } builder.append(AJ::Lexer::convertUnicode(m_ptr[1], m_ptr[2], m_ptr[3], m_ptr[4])); m_ptr += 5; break; default: return TokError; } } } while ((mode == StrictJSON) && m_ptr != runStart && (m_ptr < m_end) && *m_ptr != '"'); if (m_ptr >= m_end || *m_ptr != '"') return TokError; token.stringToken = builder.build(); token.type = TokString; token.end = ++m_ptr; return TokString; }
static PassRefPtr<InspectorObject> buildObjectForElementInfo(Node* node) { if (!node->isElementNode() || !node->document().frame()) return nullptr; RefPtr<InspectorObject> elementInfo = InspectorObject::create(); Element* element = toElement(node); bool isXHTML = element->document().isXHTMLDocument(); elementInfo->setString("tagName", isXHTML ? element->nodeName() : element->nodeName().lower()); elementInfo->setString("idValue", element->getIdAttribute()); HashSet<AtomicString> usedClassNames; if (element->hasClass() && element->isStyledElement()) { StringBuilder classNames; const SpaceSplitString& classNamesString = toStyledElement(element)->classNames(); size_t classNameCount = classNamesString.size(); for (size_t i = 0; i < classNameCount; ++i) { const AtomicString& className = classNamesString[i]; if (usedClassNames.contains(className)) continue; usedClassNames.add(className); classNames.append('.'); classNames.append(className); } elementInfo->setString("className", classNames.toString()); } RenderElement* renderer = element->renderer(); Frame* containingFrame = node->document().frame(); FrameView* containingView = containingFrame->view(); IntRect boundingBox = pixelSnappedIntRect(containingView->contentsToRootView(renderer->absoluteBoundingBoxRect())); RenderBoxModelObject* modelObject = renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : nullptr; elementInfo->setString("nodeWidth", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetWidth(), *modelObject) : boundingBox.width())); elementInfo->setString("nodeHeight", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetHeight(), *modelObject) : boundingBox.height())); if (renderer->isRenderNamedFlowFragmentContainer()) { RenderNamedFlowFragment* region = toRenderBlockFlow(renderer)->renderNamedFlowFragment(); if (region->isValid()) { RenderFlowThread* flowThread = region->flowThread(); ASSERT(flowThread && flowThread->isRenderNamedFlowThread()); RefPtr<InspectorObject> regionFlowInfo = InspectorObject::create(); regionFlowInfo->setString("name", toRenderNamedFlowThread(flowThread)->flowThreadName()); regionFlowInfo->setArray("regions", buildObjectForCSSRegionsHighlight(region, flowThread)); elementInfo->setObject("regionFlowInfo", regionFlowInfo.release()); } } RenderFlowThread* containingFlowThread = renderer->flowThreadContainingBlock(); if (containingFlowThread && containingFlowThread->isRenderNamedFlowThread()) { RefPtr<InspectorObject> contentFlowInfo = InspectorObject::create(); contentFlowInfo->setString("name", toRenderNamedFlowThread(containingFlowThread)->flowThreadName()); elementInfo->setObject("contentFlowInfo", contentFlowInfo.release()); } #if ENABLE(CSS_SHAPES) if (renderer->isBox()) { RenderBox* renderBox = toRenderBox(renderer); if (RefPtr<InspectorObject> shapeObject = buildObjectForShapeOutside(containingFrame, renderBox)) elementInfo->setObject("shapeOutsideInfo", shapeObject.release()); } #endif // Need to enable AX to get the computed role. if (!WebCore::AXObjectCache::accessibilityEnabled()) WebCore::AXObjectCache::enableAccessibility(); if (AXObjectCache* axObjectCache = node->document().axObjectCache()) { if (AccessibilityObject* axObject = axObjectCache->getOrCreate(node)) elementInfo->setString("role", axObject->computedRoleString()); } return elementInfo.release(); }
String convertHTMLTextToInterchangeFormat(const String& in, const Text& node) { // Assume all the text comes from node. if (node.layoutObject() && node.layoutObject()->style()->preserveNewline()) return in; const char convertedSpaceString[] = "<span class=\"" AppleConvertedSpace "\">\xA0</span>"; static_assert((static_cast<unsigned char>('\xA0') == noBreakSpaceCharacter), "\\xA0 should be non-breaking space"); StringBuilder s; unsigned i = 0; unsigned consumed = 0; while (i < in.length()) { consumed = 1; if (isCollapsibleWhitespace(in[i])) { // count number of adjoining spaces unsigned j = i + 1; while (j < in.length() && isCollapsibleWhitespace(in[j])) j++; unsigned count = j - i; consumed = count; while (count) { unsigned add = count % 3; switch (add) { case 0: s.append(convertedSpaceString); s.append(' '); s.append(convertedSpaceString); add = 3; break; case 1: if (i == 0 || i + 1 == in.length()) // at start or end of string s.append(convertedSpaceString); else s.append(' '); break; case 2: if (i == 0) { // at start of string s.append(convertedSpaceString); s.append(' '); } else if (i + 2 == in.length()) { // at end of string s.append(convertedSpaceString); s.append(convertedSpaceString); } else { s.append(convertedSpaceString); s.append(' '); } break; } count -= add; } } else { s.append(in[i]); } i += consumed; } return s.toString(); }
static void appendMessagePrefix(StringBuilder& builder, MessageSource source, MessageType type, MessageLevel level) { const char* sourceString; switch (source) { case MessageSource::XML: sourceString = "XML"; break; case MessageSource::JS: sourceString = "JS"; break; case MessageSource::Network: sourceString = "NETWORK"; break; case MessageSource::ConsoleAPI: sourceString = "CONSOLE"; break; case MessageSource::Storage: sourceString = "STORAGE"; break; case MessageSource::AppCache: sourceString = "APPCACHE"; break; case MessageSource::Rendering: sourceString = "RENDERING"; break; case MessageSource::CSS: sourceString = "CSS"; break; case MessageSource::Security: sourceString = "SECURITY"; break; case MessageSource::Other: sourceString = "OTHER"; break; default: ASSERT_NOT_REACHED(); sourceString = "UNKNOWN"; break; } const char* levelString; switch (level) { case MessageLevel::Debug: levelString = "DEBUG"; break; case MessageLevel::Log: levelString = "LOG"; break; case MessageLevel::Info: levelString = "INFO"; break; case MessageLevel::Warning: levelString = "WARN"; break; case MessageLevel::Error: levelString = "ERROR"; break; default: ASSERT_NOT_REACHED(); levelString = "UNKNOWN"; break; } if (type == MessageType::Trace) levelString = "TRACE"; else if (type == MessageType::Table) levelString = "TABLE"; builder.append(sourceString); builder.append(' '); builder.append(levelString); }
// See http://tools.ietf.org/html/rfc2822#section-3.3 for more information. String makeRFC2822DateString(unsigned dayOfWeek, unsigned day, unsigned month, unsigned year, unsigned hours, unsigned minutes, unsigned seconds, int utcOffset) { StringBuilder stringBuilder; stringBuilder.append(weekdayName[dayOfWeek]); stringBuilder.appendLiteral(", "); stringBuilder.appendNumber(day); stringBuilder.append(' '); stringBuilder.append(monthName[month]); stringBuilder.append(' '); stringBuilder.appendNumber(year); stringBuilder.append(' '); stringBuilder.append(twoDigitStringFromNumber(hours)); stringBuilder.append(':'); stringBuilder.append(twoDigitStringFromNumber(minutes)); stringBuilder.append(':'); stringBuilder.append(twoDigitStringFromNumber(seconds)); stringBuilder.append(' '); stringBuilder.append(utcOffset > 0 ? '+' : '-'); int absoluteUTCOffset = abs(utcOffset); stringBuilder.append(twoDigitStringFromNumber(absoluteUTCOffset / 60)); stringBuilder.append(twoDigitStringFromNumber(absoluteUTCOffset % 60)); return stringBuilder.toString(); }
void WebPageSerializerImpl::openTagToString(Element* element, SerializeDomParam* param) { bool needSkip; StringBuilder result; // Do pre action for open tag. result.append(preActionBeforeSerializeOpenTag(element, param, &needSkip)); if (needSkip) return; // Add open tag result.append('<'); result.append(element->nodeName().lower()); // Go through all attributes and serialize them. if (element->hasAttributes()) { unsigned numAttrs = element->attributeCount(); for (unsigned i = 0; i < numAttrs; i++) { result.append(' '); // Add attribute pair const Attribute& attribute = element->attributeItem(i); result.append(attribute.name().toString()); result.appendLiteral("=\""); if (!attribute.value().isEmpty()) { const String& attrValue = attribute.value(); // Check whether we need to replace some resource links // with local resource paths. const QualifiedName& attrName = attribute.name(); if (element->hasLegalLinkAttribute(attrName)) { // For links start with "javascript:", we do not change it. if (attrValue.startsWith("javascript:", false)) result.append(attrValue); else { // Get the absolute link WebLocalFrameImpl* subFrame = WebLocalFrameImpl::fromFrameOwnerElement(element); String completeURL = subFrame ? subFrame->frame()->document()->url() : param->document->completeURL(attrValue); // Check whether we have local files for those link. if (m_localLinks.contains(completeURL)) { if (!param->directoryName.isEmpty()) { result.appendLiteral("./"); result.append(param->directoryName); result.append('/'); } result.append(m_localLinks.get(completeURL)); } else result.append(completeURL); } } else { if (param->isHTMLDocument) result.append(m_htmlEntities.convertEntitiesInString(attrValue)); else result.append(m_xmlEntities.convertEntitiesInString(attrValue)); } } result.append('\"'); } } // Do post action for open tag. String addedContents = postActionAfterSerializeOpenTag(element, param); // Complete the open tag for element when it has child/children. if (element->hasChildren() || param->haveAddedContentsBeforeEnd) result.append('>'); // Append the added contents generate in post action of open tag. result.append(addedContents); // Save the result to data buffer. saveHTMLContentToBuffer(result.toString(), param); }
String CSSPrimitiveValue::customCssText() const { // FIXME: return the original value instead of a generated one (e.g. color // name if it was specified) - check what spec says about this if (m_hasCachedCSSText) { ASSERT(cssTextCache().contains(this)); return cssTextCache().get(this); } String text; switch (m_primitiveUnitType) { case CSS_UNKNOWN: // FIXME break; case CSS_NUMBER: case CSS_PARSER_INTEGER: text = formatNumber(m_value.num); break; case CSS_PERCENTAGE: text = formatNumber(m_value.num) + "%"; break; case CSS_EMS: text = formatNumber(m_value.num) + "em"; break; case CSS_EXS: text = formatNumber(m_value.num) + "ex"; break; case CSS_REMS: text = formatNumber(m_value.num) + "rem"; break; case CSS_PX: text = formatNumber(m_value.num) + "px"; break; case CSS_CM: text = formatNumber(m_value.num) + "cm"; break; #if ENABLE(CSS_IMAGE_RESOLUTION) case CSS_DPPX: text = formatNumber(m_value.num) + "dppx"; break; case CSS_DPI: text = formatNumber(m_value.num) + "dpi"; break; case CSS_DPCM: text = formatNumber(m_value.num) + "dpcm"; break; #endif case CSS_MM: text = formatNumber(m_value.num) + "mm"; break; case CSS_IN: text = formatNumber(m_value.num) + "in"; break; case CSS_PT: text = formatNumber(m_value.num) + "pt"; break; case CSS_PC: text = formatNumber(m_value.num) + "pc"; break; case CSS_DEG: text = formatNumber(m_value.num) + "deg"; break; case CSS_RAD: text = formatNumber(m_value.num) + "rad"; break; case CSS_GRAD: text = formatNumber(m_value.num) + "grad"; break; case CSS_MS: text = formatNumber(m_value.num) + "ms"; break; case CSS_S: text = formatNumber(m_value.num) + "s"; break; case CSS_HZ: text = formatNumber(m_value.num) + "hz"; break; case CSS_KHZ: text = formatNumber(m_value.num) + "khz"; break; case CSS_TURN: text = formatNumber(m_value.num) + "turn"; break; case CSS_DIMENSION: // FIXME break; case CSS_STRING: text = quoteCSSStringIfNeeded(m_value.string); break; case CSS_URI: text = "url(" + quoteCSSURLIfNeeded(m_value.string) + ")"; break; case CSS_IDENT: text = valueOrPropertyName(m_value.ident); break; case CSS_ATTR: { DEFINE_STATIC_LOCAL(const String, attrParen, ("attr(")); StringBuilder result; result.reserveCapacity(6 + m_value.string->length()); result.append(attrParen); result.append(m_value.string); result.append(')'); text = result.toString(); break; } case CSS_COUNTER_NAME: text = "counter("; text += m_value.string; text += ")"; break; case CSS_COUNTER: { DEFINE_STATIC_LOCAL(const String, counterParen, ("counter(")); DEFINE_STATIC_LOCAL(const String, countersParen, ("counters(")); DEFINE_STATIC_LOCAL(const String, commaSpace, (", ")); StringBuilder result; String separator = m_value.counter->separator(); result.append(separator.isEmpty() ? counterParen : countersParen); result.append(m_value.counter->identifier()); if (!separator.isEmpty()) { result.append(commaSpace); result.append(quoteCSSStringIfNeeded(separator)); } String listStyle = m_value.counter->listStyle(); if (!listStyle.isEmpty()) { result.append(commaSpace); result.append(listStyle); } result.append(')'); text = result.toString(); break; } case CSS_RECT: { DEFINE_STATIC_LOCAL(const String, rectParen, ("rect(")); Rect* rectVal = getRectValue(); StringBuilder result; result.reserveCapacity(32); result.append(rectParen); result.append(rectVal->top()->cssText()); result.append(' '); result.append(rectVal->right()->cssText()); result.append(' '); result.append(rectVal->bottom()->cssText()); result.append(' '); result.append(rectVal->left()->cssText()); result.append(')'); text = result.toString(); break; } case CSS_QUAD: { Quad* quadVal = getQuadValue(); Vector<UChar> result; result.reserveInitialCapacity(32); append(result, quadVal->top()->cssText()); if (quadVal->right() != quadVal->top() || quadVal->bottom() != quadVal->top() || quadVal->left() != quadVal->top()) { result.append(' '); append(result, quadVal->right()->cssText()); if (quadVal->bottom() != quadVal->top() || quadVal->right() != quadVal->left()) { result.append(' '); append(result, quadVal->bottom()->cssText()); if (quadVal->left() != quadVal->right()) { result.append(' '); append(result, quadVal->left()->cssText()); } } } text = String::adopt(result); break; } case CSS_RGBCOLOR: case CSS_PARSER_HEXCOLOR: { DEFINE_STATIC_LOCAL(const String, commaSpace, (", ")); DEFINE_STATIC_LOCAL(const String, rgbParen, ("rgb(")); DEFINE_STATIC_LOCAL(const String, rgbaParen, ("rgba(")); RGBA32 rgbColor = m_value.rgbcolor; if (m_primitiveUnitType == CSS_PARSER_HEXCOLOR) Color::parseHexColor(m_value.string, rgbColor); Color color(rgbColor); Vector<UChar> result; result.reserveInitialCapacity(32); if (color.hasAlpha()) append(result, rgbaParen); else append(result, rgbParen); appendNumber(result, static_cast<unsigned char>(color.red())); append(result, commaSpace); appendNumber(result, static_cast<unsigned char>(color.green())); append(result, commaSpace); appendNumber(result, static_cast<unsigned char>(color.blue())); if (color.hasAlpha()) { append(result, commaSpace); append(result, String::number(color.alpha() / 255.0f)); } result.append(')'); text = String::adopt(result); break; } case CSS_PAIR: text = m_value.pair->first()->cssText(); if (m_value.pair->second() != m_value.pair->first()) { text += " "; text += m_value.pair->second()->cssText(); } break; #if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION) case CSS_DASHBOARD_REGION: for (DashboardRegion* region = getDashboardRegionValue(); region; region = region->m_next.get()) { if (!text.isEmpty()) text.append(' '); #if ENABLE(DASHBOARD_SUPPORT) && ENABLE(WIDGET_REGION) text += region->m_cssFunctionName; #elif ENABLE(DASHBOARD_SUPPORT) text += "dashboard-region("; #else text += "region("; #endif text += region->m_label; if (region->m_isCircle) text += " circle"; else if (region->m_isRectangle) text += " rectangle"; else break; if (region->top()->m_primitiveUnitType == CSS_IDENT && region->top()->getIdent() == CSSValueInvalid) { ASSERT(region->right()->m_primitiveUnitType == CSS_IDENT); ASSERT(region->bottom()->m_primitiveUnitType == CSS_IDENT); ASSERT(region->left()->m_primitiveUnitType == CSS_IDENT); ASSERT(region->right()->getIdent() == CSSValueInvalid); ASSERT(region->bottom()->getIdent() == CSSValueInvalid); ASSERT(region->left()->getIdent() == CSSValueInvalid); } else { text.append(' '); text += region->top()->cssText() + " "; text += region->right()->cssText() + " "; text += region->bottom()->cssText() + " "; text += region->left()->cssText(); } text += ")"; } break; #endif case CSS_PARSER_OPERATOR: { char c = static_cast<char>(m_value.ident); text = String(&c, 1U); break; } case CSS_PARSER_IDENTIFIER: text = quoteCSSStringIfNeeded(m_value.string); break; case CSS_CALC: text = m_value.calc->cssText(); break; case CSS_SHAPE: text = m_value.shape->cssText(); break; case CSS_VW: text = formatNumber(m_value.num) + "vw"; break; case CSS_VH: text = formatNumber(m_value.num) + "vh"; break; case CSS_VMIN: text = formatNumber(m_value.num) + "vmin"; break; #if ENABLE(CSS_VARIABLES) case CSS_VARIABLE_NAME: text = "-webkit-var("; text += m_value.string; text += ")"; break; #endif } ASSERT(!cssTextCache().contains(this)); cssTextCache().set(this, text); m_hasCachedCSSText = true; return text; }
String StylePropertySet::getLayeredShorthandValue(const StylePropertyShorthand& shorthand) const { StringBuilder result; const unsigned size = shorthand.length(); // Begin by collecting the properties into an array. Vector< RefPtr<CSSValue> > values(size); size_t numLayers = 0; for (unsigned i = 0; i < size; ++i) { values[i] = getPropertyCSSValue(shorthand.properties()[i]); if (values[i]) { if (values[i]->isBaseValueList()) { CSSValueList* valueList = static_cast<CSSValueList*>(values[i].get()); numLayers = max(valueList->length(), numLayers); } else numLayers = max<size_t>(1U, numLayers); } } String commonValue; bool commonValueInitialized = false; // Now stitch the properties together. Implicit initial values are flagged as such and // can safely be omitted. for (size_t i = 0; i < numLayers; i++) { StringBuilder layerResult; bool useRepeatXShorthand = false; bool useRepeatYShorthand = false; bool useSingleWordShorthand = false; bool foundPositionYCSSProperty = false; for (unsigned j = 0; j < size; j++) { RefPtr<CSSValue> value; if (values[j]) { if (values[j]->isBaseValueList()) value = static_cast<CSSValueList*>(values[j].get())->item(i); else { value = values[j]; // Color only belongs in the last layer. if (shorthand.properties()[j] == CSSPropertyBackgroundColor) { if (i != numLayers - 1) value = 0; } else if (i != 0) // Other singletons only belong in the first layer. value = 0; } } // We need to report background-repeat as it was written in the CSS. If the property is implicit, // then it was written with only one value. Here we figure out which value that was so we can // report back correctly. if ((shorthand.properties()[j] == CSSPropertyBackgroundRepeatX && isPropertyImplicit(shorthand.properties()[j])) || (shorthand.properties()[j] == CSSPropertyWebkitMaskRepeatX && isPropertyImplicit(shorthand.properties()[j]))) { // BUG 49055: make sure the value was not reset in the layer check just above. if ((j < size - 1 && shorthand.properties()[j + 1] == CSSPropertyBackgroundRepeatY && value) || (j < size - 1 && shorthand.properties()[j + 1] == CSSPropertyWebkitMaskRepeatY && value)) { RefPtr<CSSValue> yValue; RefPtr<CSSValue> nextValue = values[j + 1]; if (nextValue->isValueList()) yValue = static_cast<CSSValueList*>(nextValue.get())->itemWithoutBoundsCheck(i); else yValue = nextValue; int xId = static_cast<CSSPrimitiveValue*>(value.get())->getIdent(); int yId = static_cast<CSSPrimitiveValue*>(yValue.get())->getIdent(); if (xId != yId) { if (xId == CSSValueRepeat && yId == CSSValueNoRepeat) { useRepeatXShorthand = true; ++j; } else if (xId == CSSValueNoRepeat && yId == CSSValueRepeat) { useRepeatYShorthand = true; continue; } } else { useSingleWordShorthand = true; ++j; } } } String valueText; if (value && !value->isImplicitInitialValue()) { if (!layerResult.isEmpty()) layerResult.append(' '); if (foundPositionYCSSProperty && (shorthand.properties()[j] == CSSPropertyBackgroundSize || shorthand.properties()[j] == CSSPropertyWebkitMaskSize)) layerResult.appendLiteral("/ "); if (!foundPositionYCSSProperty && (shorthand.properties()[j] == CSSPropertyBackgroundSize || shorthand.properties()[j] == CSSPropertyWebkitMaskSize)) continue; if (useRepeatXShorthand) { useRepeatXShorthand = false; layerResult.append(getValueName(CSSValueRepeatX)); } else if (useRepeatYShorthand) { useRepeatYShorthand = false; layerResult.append(getValueName(CSSValueRepeatY)); } else { if (useSingleWordShorthand) useSingleWordShorthand = false; valueText = value->cssText(); layerResult.append(valueText); } if (shorthand.properties()[j] == CSSPropertyBackgroundPositionY || shorthand.properties()[j] == CSSPropertyWebkitMaskPositionY) { foundPositionYCSSProperty = true; // background-position is a special case: if only the first offset is specified, // the second one defaults to "center", not the same value. if (commonValueInitialized && commonValue != "initial" && commonValue != "inherit") commonValue = String(); } } if (!commonValueInitialized) { commonValue = valueText; commonValueInitialized = true; } else if (!commonValue.isNull() && commonValue != valueText) commonValue = String(); } if (!layerResult.isEmpty()) { if (!result.isEmpty()) result.appendLiteral(", "); result.append(layerResult); } } if (isInitialOrInherit(commonValue)) return commonValue; if (result.isEmpty()) return String(); return result.toString(); }
void CSSParserToken::serialize(StringBuilder& builder) const { // This is currently only used for @supports CSSOM. To keep our implementation // simple we handle some of the edge cases incorrectly (see comments below). switch (type()) { case IdentToken: serializeIdentifier(value(), builder); break; case FunctionToken: serializeIdentifier(value(), builder); return builder.append('('); case AtKeywordToken: builder.append('@'); serializeIdentifier(value(), builder); break; case HashToken: // This will always serialize as a hash-token with 'id' type instead of // preserving the type of the input. builder.append('#'); serializeIdentifier(value(), builder); break; case UrlToken: builder.append("url("); serializeIdentifier(value(), builder); return builder.append(")"); case DelimiterToken: if (delimiter() == '\\') return builder.append("\\\n"); return builder.append(delimiter()); case NumberToken: // These won't properly preserve the NumericValueType flag return builder.appendNumber(numericValue()); case PercentageToken: builder.appendNumber(numericValue()); return builder.append('%'); case DimensionToken: // This will incorrectly serialize e.g. 4e3e2 as 4000e2 builder.appendNumber(numericValue()); serializeIdentifier(value(), builder); break; case UnicodeRangeToken: return builder.append(String::format("U+%X-%X", unicodeRangeStart(), unicodeRangeEnd())); case StringToken: return serializeString(value(), builder); case IncludeMatchToken: return builder.append("~="); case DashMatchToken: return builder.append("|="); case PrefixMatchToken: return builder.append("^="); case SuffixMatchToken: return builder.append("$="); case SubstringMatchToken: return builder.append("*="); case ColumnToken: return builder.append("||"); case CDOToken: return builder.append("<!--"); case CDCToken: return builder.append("-->"); case BadStringToken: return builder.append("'\n"); case BadUrlToken: return builder.append("url(()"); case WhitespaceToken: return builder.append(' '); case ColonToken: return builder.append(':'); case SemicolonToken: return builder.append(';'); case CommaToken: return builder.append(','); case LeftParenthesisToken: return builder.append('('); case RightParenthesisToken: return builder.append(')'); case LeftBracketToken: return builder.append('['); case RightBracketToken: return builder.append(']'); case LeftBraceToken: return builder.append('{'); case RightBraceToken: return builder.append('}'); case EOFToken: case CommentToken: ASSERT_NOT_REACHED(); return; } }
// FIXME: This is a very inefficient way of accumulating the markup. // We're converting results of appendStartMarkup and appendEndMarkup from StringBuilder to String // and then back to StringBuilder and again to String here. void MarkupAccumulator::concatenateMarkup(StringBuilder& out) { for (size_t i = 0; i < m_succeedingMarkup.size(); ++i) out.append(m_succeedingMarkup[i]); }
String Resource::reasonNotDeletable() const { StringBuilder builder; if (hasClients()) { builder.append("hasClients("); builder.appendNumber(m_clients.size()); if (!m_clientsAwaitingCallback.isEmpty()) { builder.append(", AwaitingCallback="); builder.appendNumber(m_clientsAwaitingCallback.size()); } if (!m_finishedClients.isEmpty()) { builder.append(", Finished="); builder.appendNumber(m_finishedClients.size()); } builder.append(")"); } if (m_loader) { if (!builder.isEmpty()) builder.append(' '); builder.append("m_loader"); } if (m_preloadCount) { if (!builder.isEmpty()) builder.append(' '); builder.append("m_preloadCount("); builder.appendNumber(m_preloadCount); builder.append(")"); } if (!hasRightHandleCountApartFromCache(0)) { if (!builder.isEmpty()) builder.append(' '); builder.append("m_handleCount("); builder.appendNumber(m_handleCount); builder.append(")"); } if (m_protectorCount) { if (!builder.isEmpty()) builder.append(' '); builder.append("m_protectorCount("); builder.appendNumber(m_protectorCount); builder.append(")"); } if (memoryCache()->contains(this)) { if (!builder.isEmpty()) builder.append(' '); builder.append("in_memory_cache"); } return builder.toString(); }
// http://www.whatwg.org/specs/web-apps/current-work/multipage/rendering.html#fonts-and-colors static bool parseFontSize(const String& input, int& size) { // Step 1 // Step 2 const UChar* position = input.characters(); const UChar* end = position + input.length(); // Step 3 while (position < end) { if (!isHTMLSpace(*position)) break; ++position; } // Step 4 if (position == end) return false; ASSERT(position < end); // Step 5 enum { RelativePlus, RelativeMinus, Absolute } mode; switch (*position) { case '+': mode = RelativePlus; ++position; break; case '-': mode = RelativeMinus; ++position; break; default: mode = Absolute; break; } // Step 6 StringBuilder digits; digits.reserveCapacity(16); while (position < end) { if (!isASCIIDigit(*position)) break; digits.append(*position++); } // Step 7 if (digits.isEmpty()) return false; // Step 8 int value = charactersToIntStrict(digits.characters(), digits.length()); // Step 9 if (mode == RelativePlus) value += 3; else if (mode == RelativeMinus) value = 3 - value; // Step 10 if (value > 7) value = 7; // Step 11 if (value < 1) value = 1; size = value; return true; }
String TypeProfiler::typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptor descriptor, unsigned offset, intptr_t sourceID, VM& vm) { // This returns a JSON string representing an Object with the following properties: // globalTypeSet: 'JSON<TypeSet> | null' // instructionTypeSet: 'JSON<TypeSet>' TypeLocation* location = findLocation(offset, sourceID, descriptor, vm); ASSERT(location); StringBuilder json; json.append("{"); json.append("\"globalTypeSet\":"); if (location->m_globalTypeSet && location->m_globalVariableID != TypeProfilerNoGlobalIDExists) json.append(location->m_globalTypeSet->toJSONString()); else json.append("null"); json.append(","); json.append("\"instructionTypeSet\":"); json.append(location->m_instructionTypeSet->toJSONString()); json.append(","); json.append("\"isOverflown\":"); if (location->m_instructionTypeSet->isOverflown() || (location->m_globalTypeSet && location->m_globalTypeSet->isOverflown())) json.append("true"); else json.append("false"); json.append("}"); return json.toString(); }
static inline JSValue regExpObjectSourceInternal(ExecState* exec, String pattern, const CharacterType* characters, unsigned length) { bool previousCharacterWasBackslash = false; bool inBrackets = false; bool shouldEscape = false; // 15.10.6.4 specifies that RegExp.prototype.toString must return '/' + source + '/', // and also states that the result must be a valid RegularExpressionLiteral. '//' is // not a valid RegularExpressionLiteral (since it is a single line comment), and hence // source cannot ever validly be "". If the source is empty, return a different Pattern // that would match the same thing. if (!length) return jsNontrivialString(exec, ASCIILiteral("(?:)")); // early return for strings that don't contain a forwards slash and LineTerminator for (unsigned i = 0; i < length; ++i) { CharacterType ch = characters[i]; if (!previousCharacterWasBackslash) { if (inBrackets) { if (ch == ']') inBrackets = false; } else { if (ch == '/') { shouldEscape = true; break; } if (ch == '[') inBrackets = true; } } if (Lexer<CharacterType>::isLineTerminator(ch)) { shouldEscape = true; break; } if (previousCharacterWasBackslash) previousCharacterWasBackslash = false; else previousCharacterWasBackslash = ch == '\\'; } if (!shouldEscape) return jsString(exec, pattern); previousCharacterWasBackslash = false; inBrackets = false; StringBuilder result; for (unsigned i = 0; i < length; ++i) { CharacterType ch = characters[i]; if (!previousCharacterWasBackslash) { if (inBrackets) { if (ch == ']') inBrackets = false; } else { if (ch == '/') result.append('\\'); else if (ch == '[') inBrackets = true; } } // escape LineTerminator if (Lexer<CharacterType>::isLineTerminator(ch)) { if (!previousCharacterWasBackslash) result.append('\\'); appendLineTerminatorEscape<CharacterType>(result, ch); } else result.append(ch); if (previousCharacterWasBackslash) previousCharacterWasBackslash = false; else previousCharacterWasBackslash = ch == '\\'; } return jsString(exec, result.toString()); }
static bool parseFontSize(const CharacterType* characters, unsigned length, int& size) { // Step 1 // Step 2 const CharacterType* position = characters; const CharacterType* end = characters + length; // Step 3 while (position < end) { if (!isHTMLSpace(*position)) break; ++position; } // Step 4 if (position == end) return false; ASSERT_WITH_SECURITY_IMPLICATION(position < end); // Step 5 enum { RelativePlus, RelativeMinus, Absolute } mode; switch (*position) { case '+': mode = RelativePlus; ++position; break; case '-': mode = RelativeMinus; ++position; break; default: mode = Absolute; break; } // Step 6 StringBuilder digits; digits.reserveCapacity(16); while (position < end) { if (!isASCIIDigit(*position)) break; digits.append(*position++); } // Step 7 if (digits.isEmpty()) return false; // Step 8 int value; if (digits.is8Bit()) value = charactersToIntStrict(digits.characters8(), digits.length()); else value = charactersToIntStrict(digits.characters16(), digits.length()); // Step 9 if (mode == RelativePlus) value += 3; else if (mode == RelativeMinus) value = 3 - value; // Step 10 if (value > 7) value = 7; // Step 11 if (value < 1) value = 1; size = value; return true; }