void SelectPopupClient::generateHTML(bool multiple, int size, const ScopeArray<BlackBerry::WebKit::WebString>& labels, bool* enableds, const int* itemType, bool* selecteds) { StringBuilder source; source.append("<style>\n"); // Include CSS file. source.append(popupControlBlackBerryCss, sizeof(popupControlBlackBerryCss)); source.append("</style>\n<style>"); source.append(selectControlBlackBerryCss, sizeof(selectControlBlackBerryCss)); source.append("</style></head><body>\n"); source.append("<script>\n"); source.append("window.addEventListener('load', function () {"); if (m_multiple) source.append("window.select.show(true, "); else source.append("window.select.show(false, "); // Add labels. source.append("["); for (int i = 0; i < size; i++) { source.append("'" + String(labels[i].impl()).replace('\\', "\\\\").replace('\'', "\\'") + "'"); // Don't append ',' to last element. if (i != size - 1) source.append(", "); } source.append("], "); // Add enables. source.append("["); for (int i = 0; i < size; i++) { source.append(enableds[i]? "true" : "false"); // Don't append ',' to last element. if (i != size - 1) source.append(", "); } source.append("], "); // Add itemType. source.append("["); for (int i = 0; i < size; i++) { source.append(String::number(itemType[i])); // Don't append ',' to last element. if (i != size - 1) source.append(", "); } source.append("], "); // Add selecteds source.append("["); for (int i = 0; i < size; i++) { source.append(selecteds[i]? "true" : "false"); // Don't append ',' to last element. if (i != size - 1) source.append(", "); } source.append("] "); source.append(", 'Cancel'"); // If multi-select, add OK button for confirm. if (m_multiple) source.append(", 'OK'"); source.append("); \n }); \n"); source.append(selectControlBlackBerryJs, sizeof(selectControlBlackBerryJs)); source.append("</script>\n"); source.append("</body> </html>\n"); m_source = source.toString(); }
void InjectedScriptHost::monitorFunction(const String& scriptId, int lineNumber, int columnNumber, const String& functionName) { StringBuilder builder; builder.appendLiteral("console.log(\"function "); if (functionName.isEmpty()) builder.appendLiteral("(anonymous function)"); else builder.append(functionName); builder.appendLiteral(" called\" + (arguments.length > 0 ? \" with arguments: \" + Array.prototype.join.call(arguments, \", \") : \"\")) && false"); if (m_debuggerAgent) m_debuggerAgent->setBreakpoint(scriptId, lineNumber, columnNumber, V8DebuggerAgent::MonitorCommandBreakpointSource, builder.toString()); }
void EventSource::didReceiveResponse(unsigned long, const ResourceResponse& response) { ASSERT(m_state == CONNECTING); ASSERT(m_requestInFlight); m_eventStreamOrigin = SecurityOrigin::create(response.url())->toString(); int statusCode = response.httpStatusCode(); bool mimeTypeIsValid = response.mimeType() == "text/event-stream"; bool responseIsValid = statusCode == 200 && mimeTypeIsValid; if (responseIsValid) { const String& charset = response.textEncodingName(); // If we have a charset, the only allowed value is UTF-8 (case-insensitive). responseIsValid = charset.isEmpty() || equalIgnoringCase(charset, "UTF-8"); if (!responseIsValid) { StringBuilder message; message.appendLiteral("EventSource's response has a charset (\""); message.append(charset); message.appendLiteral("\") that is not UTF-8. Aborting the connection."); // FIXME: We are missing the source line. scriptExecutionContext()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, message.toString()); } } else { // To keep the signal-to-noise ratio low, we only log 200-response with an invalid MIME type. if (statusCode == 200 && !mimeTypeIsValid) { StringBuilder message; message.appendLiteral("EventSource's response has a MIME type (\""); message.append(response.mimeType()); message.appendLiteral("\") that is not \"text/event-stream\". Aborting the connection."); // FIXME: We are missing the source line. scriptExecutionContext()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, message.toString()); } } if (responseIsValid) { m_state = OPEN; dispatchEvent(Event::create(eventNames().openEvent)); } else { m_loader->cancel(); dispatchEvent(Event::create(eventNames().errorEvent)); } }
// // The MathML specification says: // (http://www.w3.org/TR/MathML/chapter2.html#fund.units) // // "Most presentation elements have attributes that accept values representing // lengths to be used for size, spacing or similar properties. The syntax of a // length is specified as // // number | number unit | namedspace // // There should be no space between the number and the unit of a length." // // "A trailing '%' represents a percent of the default value. The default // value, or how it is obtained, is listed in the table of attributes for each // element. [...] A number without a unit is intepreted as a multiple of the // default value." // // "The possible units in MathML are: // // Unit Description // em an em (font-relative unit traditionally used for horizontal lengths) // ex an ex (font-relative unit traditionally used for vertical lengths) // px pixels, or size of a pixel in the current display // in inches (1 inch = 2.54 centimeters) // cm centimeters // mm millimeters // pt points (1 point = 1/72 inch) // pc picas (1 pica = 12 points) // % percentage of default value" // // The numbers are defined that way: // - unsigned-number: "a string of decimal digits with up to one decimal point // (U+002E), representing a non-negative terminating decimal number (a type of // rational number)" // - number: "an optional prefix of '-' (U+002D), followed by an unsigned // number, representing a terminating decimal number (a type of rational // number)" // bool parseMathMLLength(const String& string, LayoutUnit& lengthValue, const RenderStyle* style, bool allowNegative) { String s = string.simplifyWhiteSpace(); int stringLength = s.length(); if (!stringLength) return false; if (parseMathMLNamedSpace(s, lengthValue, style, allowNegative)) return true; StringBuilder number; String unit; // This verifies whether the negative sign is there. int i = 0; UChar c = s[0]; if (c == '-') { number.append(c); i++; } // This gathers up characters that make up the number. bool gotDot = false; for ( ; i < stringLength; i++) { c = s[i]; // The string is invalid if it contains two dots. if (gotDot && c == '.') return false; if (c == '.') gotDot = true; else if (!isASCIIDigit(c)) { unit = s.substring(i, stringLength - i); // Some authors leave blanks before the unit, but that shouldn't // be allowed, so don't simplifyWhitespace on 'unit'. break; } number.append(c); } // Convert number to floating point bool ok; float floatValue = number.toString().toFloat(&ok); if (!ok) return false; if (floatValue < 0 && !allowNegative) return false; if (unit.isEmpty()) { // no explicit unit, this is a number that will act as a multiplier lengthValue *= floatValue; return true; } if (unit == "%") { lengthValue *= floatValue / 100; return true; } if (unit == "em") { lengthValue = floatValue * style->fontCascade().size(); return true; } if (unit == "ex") { lengthValue = floatValue * style->fontMetrics().xHeight(); return true; } if (unit == "px") { lengthValue = floatValue; return true; } if (unit == "pt") { lengthValue = 4 * (floatValue / 3); return true; } if (unit == "pc") { lengthValue = 16 * floatValue; return true; } if (unit == "in") { lengthValue = 96 * floatValue; return true; } if (unit == "cm") { lengthValue = 96 * (floatValue / 2.54); return true; } if (unit == "mm") { lengthValue = 96 * (floatValue / 25.4); return true; } // unexpected unit return false; }
ResourceRequest createAccessControlPreflightRequest(const ResourceRequest& request, SecurityOrigin* securityOrigin) { ResourceRequest preflightRequest(request.url()); updateRequestForAccessControl(preflightRequest, securityOrigin, DoNotAllowStoredCredentials); preflightRequest.setHTTPMethod("OPTIONS"); preflightRequest.setHTTPHeaderField("Access-Control-Request-Method", request.httpMethod()); preflightRequest.setPriority(request.priority()); preflightRequest.setRequestContext(request.requestContext()); preflightRequest.setSkipServiceWorker(true); const HTTPHeaderMap& requestHeaderFields = request.httpHeaderFields(); if (requestHeaderFields.size() > 0) { // Sort header names lexicographically: https://crbug.com/452391 // Fetch API Spec: // https://fetch.spec.whatwg.org/#cors-preflight-fetch-0 Vector<String> headers; for (const auto& header : requestHeaderFields) { if (equalIgnoringCase(header.key, "referer")) { // When the request is from a Worker, referrer header was added // by WorkerThreadableLoader. But it should not be added to // Access-Control-Request-Headers header. continue; } headers.append(header.key.lower()); } std::sort(headers.begin(), headers.end(), WTF::codePointCompareLessThan); StringBuilder headerBuffer; for (const String& header : headers) { if (!headerBuffer.isEmpty()) headerBuffer.appendLiteral(", "); headerBuffer.append(header); } preflightRequest.setHTTPHeaderField("Access-Control-Request-Headers", AtomicString(headerBuffer.toString())); } return preflightRequest; }
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. if (element->hasTagName(HTMLNames::metaTag)) { const HTMLMetaElement* meta = static_cast<const HTMLMetaElement*>(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 (element->hasTagName(HTMLNames::htmlTag)) { // 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 (element->hasTagName(HTMLNames::baseTag)) { // 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->loader()->writer()->encoding(); 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(); }
void ListMarkerPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (paintInfo.phase != PaintPhaseForeground) return; if (m_layoutListMarker.style()->visibility() != VISIBLE) return; if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(paintInfo.context, m_layoutListMarker, paintInfo.phase, paintOffset)) return; LayoutPoint boxOrigin(paintOffset + m_layoutListMarker.location()); LayoutRect overflowRect(m_layoutListMarker.visualOverflowRect()); overflowRect.moveBy(boxOrigin); IntRect pixelSnappedOverflowRect = pixelSnappedIntRect(overflowRect); if (!paintInfo.cullRect().intersectsCullRect(overflowRect)) return; LayoutObjectDrawingRecorder recorder(paintInfo.context, m_layoutListMarker, paintInfo.phase, pixelSnappedOverflowRect, paintOffset); LayoutRect box(boxOrigin, m_layoutListMarker.size()); IntRect marker = m_layoutListMarker.getRelativeMarkerRect(); marker.moveBy(roundedIntPoint(boxOrigin)); GraphicsContext& context = paintInfo.context; if (m_layoutListMarker.isImage()) { context.drawImage(m_layoutListMarker.image()->image( &m_layoutListMarker, marker.size(), m_layoutListMarker.styleRef().effectiveZoom()).get(), marker); if (m_layoutListMarker.getSelectionState() != SelectionNone) { LayoutRect selRect = m_layoutListMarker.localSelectionRect(); selRect.moveBy(boxOrigin); context.fillRect(pixelSnappedIntRect(selRect), m_layoutListMarker.listItem()->selectionBackgroundColor()); } return; } LayoutListMarker::ListStyleCategory styleCategory = m_layoutListMarker.listStyleCategory(); if (styleCategory == LayoutListMarker::ListStyleCategory::None) return; const Color color(m_layoutListMarker.resolveColor(CSSPropertyColor)); // Apply the color to the list marker text. context.setFillColor(color); const EListStyleType listStyle = m_layoutListMarker.style()->listStyleType(); if (styleCategory == LayoutListMarker::ListStyleCategory::Symbol) { paintSymbol(context, color, marker, listStyle); return; } if (m_layoutListMarker.text().isEmpty()) return; const Font& font = m_layoutListMarker.style()->font(); TextRun textRun = constructTextRun(font, m_layoutListMarker.text(), m_layoutListMarker.styleRef()); GraphicsContextStateSaver stateSaver(context, false); if (!m_layoutListMarker.style()->isHorizontalWritingMode()) { marker.moveBy(roundedIntPoint(-boxOrigin)); marker = marker.transposedRect(); marker.moveBy(IntPoint(roundToInt(box.x()), roundToInt(box.y() - m_layoutListMarker.logicalHeight()))); stateSaver.save(); context.translate(marker.x(), marker.maxY()); context.rotate(static_cast<float>(deg2rad(90.))); context.translate(-marker.x(), -marker.maxY()); } TextRunPaintInfo textRunPaintInfo(textRun); textRunPaintInfo.bounds = marker; IntPoint textOrigin = IntPoint(marker.x(), marker.y() + m_layoutListMarker.style()->fontMetrics().ascent()); // Text is not arbitrary. We can judge whether it's RTL from the first character, // and we only need to handle the direction RightToLeft for now. bool textNeedsReversing = WTF::Unicode::direction(m_layoutListMarker.text()[0]) == WTF::Unicode::RightToLeft; StringBuilder reversedText; if (textNeedsReversing) { unsigned length = m_layoutListMarker.text().length(); reversedText.reserveCapacity(length); for (int i = length - 1; i >= 0; --i) reversedText.append(m_layoutListMarker.text()[i]); ASSERT(reversedText.length() == length); textRun.setText(reversedText.toString()); } const UChar suffix = ListMarkerText::suffix(listStyle, m_layoutListMarker.listItem()->value()); UChar suffixStr[2] = { suffix, static_cast<UChar>(' ') }; TextRun suffixRun = constructTextRun(font, suffixStr, 2, m_layoutListMarker.styleRef(), m_layoutListMarker.style()->direction()); TextRunPaintInfo suffixRunInfo(suffixRun); suffixRunInfo.bounds = marker; if (m_layoutListMarker.style()->isLeftToRightDirection()) { context.drawText(font, textRunPaintInfo, textOrigin); context.drawText(font, suffixRunInfo, textOrigin + IntSize(font.width(textRun), 0)); } else { context.drawText(font, suffixRunInfo, textOrigin); context.drawText(font, textRunPaintInfo, textOrigin + IntSize(font.width(suffixRun), 0)); } }
void CookieDatabaseBackingStore::upgradeTableIfNeeded(const String& databaseFields, const String& primaryKeyFields) { ASSERT(isCurrentThread()); bool creationTimeExists = false; bool protocolExists = false; if (!m_db.tableExists(m_tableName)) return; // Check if the existing table has the required database fields { String query = "PRAGMA table_info(" + m_tableName + ");"; SQLiteStatement statement(m_db, query); if (statement.prepare()) { LOG_ERROR("Cannot prepare statement to query cookie table info. sql:%s", query.utf8().data()); LOG_ERROR("SQLite Error Message: %s", m_db.lastErrorMsg()); return; } while (statement.step() == SQLResultRow) { DEFINE_STATIC_LOCAL(String, creationTime, (ASCIILiteral("creationTime"))); DEFINE_STATIC_LOCAL(String, protocol, (ASCIILiteral("protocol"))); String name = statement.getColumnText(1); if (name == creationTime) creationTimeExists = true; if (name == protocol) protocolExists = true; if (creationTimeExists && protocolExists) return; } LOG(Network, "Need to update cookie table schema."); } // Drop and recreate the cookie table to update to the latest database fields. // We do not use alter table - add column because that method cannot add primary keys. Vector<String> commands; // Backup existing table String renameQuery = "ALTER TABLE " + m_tableName + " RENAME TO Backup_" + m_tableName + ";"; commands.append(renameQuery); // Recreate the cookie table using the new database and primary key fields StringBuilder createTableQuery; createTableQuery.append("CREATE TABLE "); createTableQuery.append(m_tableName); createTableQuery.append(" (" + databaseFields + ", " + primaryKeyFields + ");"); commands.append(createTableQuery.toString()); // Copy the old data into the new table. If a column does not exists, // we have to put a '' in the select statement to make the number of columns // equal in the insert statement. StringBuilder migrationQuery; migrationQuery.append("INSERT OR REPLACE INTO "); migrationQuery.append(m_tableName); migrationQuery.append(" SELECT *"); if (!creationTimeExists) migrationQuery.append(",''"); if (!protocolExists) migrationQuery.append(",''"); migrationQuery.append(" FROM Backup_" + m_tableName); commands.append(migrationQuery.toString()); // The new columns will be blank, set the new values. if (!creationTimeExists) { String setCreationTimeQuery = "UPDATE " + m_tableName + " SET creationTime = lastAccessed;"; commands.append(setCreationTimeQuery); } if (!protocolExists) { String setProtocolQuery = "UPDATE " + m_tableName + " SET protocol = 'http' WHERE isSecure = '0';"; String setProtocolQuery2 = "UPDATE " + m_tableName + " SET protocol = 'https' WHERE isSecure = '1';"; commands.append(setProtocolQuery); commands.append(setProtocolQuery2); } // Drop the backup table String dropBackupQuery = "DROP TABLE IF EXISTS Backup_" + m_tableName + ";"; commands.append(dropBackupQuery); SQLiteTransaction transaction(m_db, false); transaction.begin(); size_t commandSize = commands.size(); for (size_t i = 0; i < commandSize; ++i) { if (!m_db.executeCommand(commands[i])) { LOG_ERROR("Failed to alter cookie table when executing sql:%s", commands[i].utf8().data()); LOG_ERROR("SQLite Error Message: %s", m_db.lastErrorMsg()); transaction.rollback(); // We should never get here, but if we do, rename the current cookie table for future restoration. This has the side effect of // clearing the current cookie table, but that's better than continually hitting this case and hence never being able to use the // cookie table. ASSERT_NOT_REACHED(); String renameQuery = "ALTER TABLE " + m_tableName + " RENAME TO Backup2_" + m_tableName + ";"; if (!m_db.executeCommand(renameQuery)) { LOG_ERROR("Failed to backup existing cookie table."); LOG_ERROR("SQLite Error Message: %s", m_db.lastErrorMsg()); } return; } } transaction.commit(); LOG(Network, "Successfully updated cookie table schema."); }
void CookieDatabaseBackingStore::invokeOpen(const String& cookieJar) { ASSERT(isCurrentThread()); if (m_db.isOpen()) close(); if (!m_db.open(cookieJar)) { LOG_ERROR("Could not open the cookie database. No cookie will be stored!"); LOG_ERROR("SQLite Error Message: %s", m_db.lastErrorMsg()); return; } m_db.executeCommand("PRAGMA locking_mode=EXCLUSIVE;"); m_db.executeCommand("PRAGMA journal_mode=TRUNCATE;"); const String primaryKeyFields("PRIMARY KEY (protocol, host, path, name)"); const String databaseFields("name TEXT, value TEXT, host TEXT, path TEXT, expiry DOUBLE, lastAccessed DOUBLE, isSecure INTEGER, isHttpOnly INTEGER, creationTime DOUBLE, protocol TEXT"); // Update table to add the new column creationTime and protocol for backwards compatability. upgradeTableIfNeeded(databaseFields, primaryKeyFields); // Create table if not exsist in case that the upgradeTableIfNeeded() failed accidentally. StringBuilder createTableQuery; createTableQuery.append("CREATE TABLE IF NOT EXISTS "); createTableQuery.append(m_tableName); // This table schema is compliant with Mozilla's. createTableQuery.append(" (" + databaseFields + ", " + primaryKeyFields+");"); m_db.setBusyTimeout(1000); if (!m_db.executeCommand(createTableQuery.toString())) { LOG_ERROR("Could not create the table to store the cookies into. No cookie will be stored!"); LOG_ERROR("SQLite Error Message: %s", m_db.lastErrorMsg()); close(); return; } StringBuilder insertQuery; insertQuery.append("INSERT OR REPLACE INTO "); insertQuery.append(m_tableName); insertQuery.append(" (name, value, host, path, expiry, lastAccessed, isSecure, isHttpOnly, creationTime, protocol) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10);"); m_insertStatement = new SQLiteStatement(m_db, insertQuery.toString()); if (m_insertStatement->prepare()) { LOG_ERROR("Cannot save cookies"); LOG_ERROR("SQLite Error Message: %s", m_db.lastErrorMsg()); } StringBuilder updateQuery; updateQuery.append("UPDATE "); updateQuery.append(m_tableName); // The where statement is chosen to match CookieMap key. updateQuery.append(" SET name = ?1, value = ?2, host = ?3, path = ?4, expiry = ?5, lastAccessed = ?6, isSecure = ?7, isHttpOnly = ?8, creationTime = ?9, protocol = ?10 where name = ?1 and host = ?3 and path = ?4;"); m_updateStatement = new SQLiteStatement(m_db, updateQuery.toString()); if (m_updateStatement->prepare()) { LOG_ERROR("Cannot update cookies"); LOG_ERROR("SQLite Error Message: %s", m_db.lastErrorMsg()); } StringBuilder deleteQuery; deleteQuery.append("DELETE FROM "); deleteQuery.append(m_tableName); // The where statement is chosen to match CookieMap key. deleteQuery.append(" WHERE name=?1 and host=?2 and path=?3 and protocol=?4;"); m_deleteStatement = new SQLiteStatement(m_db, deleteQuery.toString()); if (m_deleteStatement->prepare()) { LOG_ERROR("Cannot delete cookies"); LOG_ERROR("SQLite Error Message: %s", m_db.lastErrorMsg()); } }
JSObject* constructFunctionSkippingEvalEnabledCheck( ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, const Identifier& functionName, const String& sourceURL, const TextPosition& position, int overrideLineNumber, FunctionConstructionMode functionConstructionMode, JSValue newTarget) { VM& vm = exec->vm(); auto scope = DECLARE_THROW_SCOPE(vm); const char* prefix = nullptr; Structure* structure = nullptr; switch (functionConstructionMode) { case FunctionConstructionMode::Function: structure = globalObject->functionStructure(); prefix = "{function "; break; case FunctionConstructionMode::Generator: structure = globalObject->generatorFunctionStructure(); prefix = "{function *"; break; case FunctionConstructionMode::Async: structure = globalObject->asyncFunctionStructure(); prefix = "{async function "; break; } // How we stringify functions is sometimes important for web compatibility. // See https://bugs.webkit.org/show_bug.cgi?id=24350. String program; if (args.isEmpty()) program = makeString(prefix, functionName.string(), "() {\n\n}}"); else if (args.size() == 1) program = makeString(prefix, functionName.string(), "() {\n", args.at(0).toString(exec)->value(exec), "\n}}"); else { StringBuilder builder; builder.append(prefix); builder.append(functionName.string()); builder.append('('); auto viewWithString = args.at(0).toString(exec)->viewWithUnderlyingString(*exec); RETURN_IF_EXCEPTION(scope, nullptr); builder.append(viewWithString.view); for (size_t i = 1; i < args.size() - 1; i++) { builder.appendLiteral(", "); auto viewWithString = args.at(i).toString(exec)->viewWithUnderlyingString(*exec); RETURN_IF_EXCEPTION(scope, nullptr); builder.append(viewWithString.view); } builder.appendLiteral(") {\n"); viewWithString = args.at(args.size() - 1).toString(exec)->viewWithUnderlyingString(*exec); RETURN_IF_EXCEPTION(scope, nullptr); builder.append(viewWithString.view); builder.appendLiteral("\n}}"); program = builder.toString(); } SourceCode source = makeSource(program, sourceURL, position); JSObject* exception = nullptr; FunctionExecutable* function = FunctionExecutable::fromGlobalCode(functionName, *exec, source, exception, overrideLineNumber); if (!function) { ASSERT(exception); return throwException(exec, scope, exception); } Structure* subclassStructure = InternalFunction::createSubclassStructure(exec, newTarget, structure); RETURN_IF_EXCEPTION(scope, nullptr); switch (functionConstructionMode) { case FunctionConstructionMode::Function: return JSFunction::create(vm, function, globalObject->globalScope(), subclassStructure); case FunctionConstructionMode::Generator: return JSGeneratorFunction::create(vm, function, globalObject->globalScope(), subclassStructure); case FunctionConstructionMode::Async: return JSAsyncFunction::create(vm, function, globalObject->globalScope(), subclassStructure); } ASSERT_NOT_REACHED(); return nullptr; }