The WebKit Open Source Project

Published on December 2016 | Categories: Documents | Downloads: 42 | Comments: 0 | Views: 863
of 174
Download PDF   Embed   Report

Comments

Content

The WebKit Open Source Project
                              

Home Surfin’ Safari Blog Planet WebKit Project Goals Keeping in Touch Trac Contributors Meeting Working with the Code Installing Developer Tools Getting the Code Building WebKit Running WebKit Debugging WebKit Contributing Code Commit and Review Policy Security Policy Documentation Wiki Projects Code Style Guidelines Technical Articles Web Inspector Web Developer Resources Demos Testing Regression Testing Leak Hunting Writing New Tests Getting a Crash Log Bugs Reporting Bugs

Reporting Bugs
You have found a bug? Here are 5 steps to getting it fixed! 1. Check your WebKit version

To make sure you're not wasting your (and our) time, you should be using the latest version of WebKit before you file your bug. First of all, you should download the latest nightly build to be sure you have the latest version. If you've done this and you still experience the bug, go ahead to the next step.

2. Search Bugzilla Now that you have the latest WebKit version and still think you've found a WebKit bug, search through Bugzilla first to see if anyone else has already filed it. This step is very important! If you find that someone has filed your bug already, please go to the next step anyway, but instead of filing a new bug, comment on the one you've found. If you can't find your bug in Bugzilla, go to the next step. 3. Create a Bugzilla account You will need to create a Bugzilla account to be able to report bugs (and to comment on them). If you have registered, proceed to the next step. 4. File the bug! Now you are ready to file a bug on the WebKit product. The Writing a Good Bug Report document (also linked in the sidebar) gives some tips about the most useful information to include in bug reports. The better your bug report, the higher the chance that your bug will be addressed (and possibly fixed) quickly! 5. What happens next? Once your bug is filed, you will receive email when it is updated at each stage in the bug life cycle. After the bug is considered fixed, you may be asked to download the latest nightly and confirm that the fix works for you.



Bug Report Guidelines

Bug Reporting Guidelines
This document describes how to write a good WebKit bug report. Good bug reports help developers and quality assurance (QA) people decide an appropriate priority and severity for a bug, and increase the chance that a bug will be fixed quickly. The more specific information you can provide, the better.
1. Version

Please select the WebKit version you were using when the bug occurred, or the closest matching version. Versions of WebKit that are not part of a Safari release have a + after the version number, and their version number is generally higher then the latest released version of WebKit. So, for example, 528+ is an unofficial build of WebKit that is newer than the 525.x version that shipped as part of Safari 3.1.2.
2. Component

If you know the precise cause of a bug (i.e., you've reduced it to a failing test case and know the reason), then you can assign a bug to a specific component such as CSS or HTML Editing.

If, however, there is any doubt in your mind as to the cause of the bug, then file it under New Bugs. This component is the place for any bugs whose cause has not yet been determined. Once someone has reduced the bug and knows the cause, then it will be moved from the New Bugs component to the appropriate place.
3. Platform and OS

Please select the platform and the OS version that your bug occurred on. If you're running on Mac OS X this would often be platform Macintosh and OS Mac OS X 10.5 (Leopard). If you're running on Windows or Linux, please select PC for platform and the appropriate entry from the OS field. If your exact system is not listed, please select the closest entry and provide further details in the description of the bug report.
4. Priority

Normally a QA person or developer will set this, so the bug submitter can leave this at the default value. A number of guidelines and some individual judgment are involved in setting the priority. If you know the bug is a regression, ie. something is wrong which wasn't wrong in previous versions of WebKit, you can set this to P1.
5. Severity

In most cases you should leave this at normal, but if you are confident that your bug is trivial or an enhancement, it's helpful to specify that value. A QA person or developer will set this to some other value if appropriate.
6. URL

Fill in this field with the URL of a page that shows the bug, when possible. If you have created a test case reduction for the bug, please add it to the bug report as an attachment rather than putting it on a web server and listing its URL here. Doing so makes it easier to work on the bug, and can be a first step towards checking in the test case along with the bug fix.
7. Summary

A good summary explains the problem in clear and specific terms, but is often concise enough to fit within the default summary space in Bugzilla. One should be able to tell exactly what a bug is about just by reading the summary.
Tips for a good summary:
o o o

Include the domain of the page that shows the bug (especially if it's an important site) If the bug is a crash, note this and note whether or not the crash is reproducible If you have tested and verified that this is a regression from a previous version of WebKit, prepend "REGRESSION: " to the summary

o

If you know the range of revisions in which the regression occurred, add this to the summary after REGRESSION (i.e., "REGRESSION(r31201-r31211):")

8. Description

In this field, write a more detailed explanation of the problem.
Tips for Descriptions:
o o o

o o o

o

Do not include more than one bug in one bug report. If you built WebKit yourself or used a nightly build, include the SVN revision number as well as information about if you are using WebKit with Qt, GTK+, wxWidgets, etc. If loading a single URL is not enough to show the bug (for instance, you have to click through multiple pages for the bug to occur), then describe the exact navigation required to reach the page where the bug occurs. Don't just say "go to the forums"; use detailed steps. Look at the system console and include any messages that might be relevant in the bug. Include the backtrace if you get a crash, if possible. File the bug first and then add the backtrace as an attachment. Include a screenshot for visual bugs. If the problem isn't very obvious, include a single screenshot which shows both correct and incorrect renderings, for example Safari and another browser such as Firefox or Internet Explorer. On the Mac you can use Grab.app or Cmd-Shift-4 and capture a snap that demonstrates the problem. You can then attach the screenshot to the bug. Be as specific as possible. For instance, if you're describing a problem that occurs while scrolling, note in the bug whether you're scrolling with arrow keys, arrow buttons, scroll thumb, clicking above or below the thumb, scroll-wheel mouse, etc.

9. Keywords

If the bug is specific to one or more of the ports of WebKit (Qt, GTK, Wx, etc), please use any of the valid keywords to tag the bug report accordingly.
10. Depends on

If the fix for this bug depends on another bug fix, put the other bug's number here. Otherwise, leave it empty.
11. Blocks

If this bug blocks another bug from being fixed, put the other bug's number here. Otherwise, leave it empty.

WebKit Bugzilla Bugzilla Keyword Descriptions
   

Home | New | Search |
Find

   

| Reports | Requests | New Account | Log In Description Cairo Curl DeveloperToolsHitList Bugs related to the use of the Cairo library within WebCore Bugs related to the use of the curl library within WebCore This bug is in the Developer Tools Hitlist Open Bugs Search Search Search Total Bugs 74 36 23 1 17 171 346 996 103 1868 13 15

Name

DeveloperToolsHitListCandidate ES5 EasyFix GoogleBug Gtk HTML5 HasReduction HitList HitListCandidate

This bug should be considered for inclusion Search in the Developer Tools Hitlist ECMAScript 5 features and compliance issues. This bug has been identified as a bug that should be easy to fix Keyword to allow tracking of bugs which concern Google products. Bugs related to the Gtk port of WebKit HTML 5 features and compliance issues. This bug has a reduced failing test case attached. This bug is in the Top 10 Safari Compatibility Bugs Hitlist. This bug should be considered for the Top 10 List. Search Search Search Search Search Search Search Search

InChromiumBugs InRadar

The bug is also being tracked in Chromium's bug database at . This bug also has a copy in Apple's Radar bug tracker.

Search Search

420 6176

InTSW LayoutTestFailure

For use of the Nokia WebKit guys, to track if a bug is in their internal bugtracker, Search TSW. Bugs which are causing layout test failures Bugs that are currently causing the bots to be red (even intermittently). Once the bug is no longer making bots red (even if the underlying bug hasn't been fixed yet), this keyword should be removed. NativeListBox bugs bug that affect the new popup menu implementation Regressions from the new text are implementation. A keyword to track bugs against the new native form controls in our engine. Bug that needs a Radar, to help out the Apple WebKit hackers. This bug needs a reduced test case. Tracks bugs that need UI work before they can be completed. This bug relates to a performance issue. This bug occurs only on the platform it has been reported on. Bugs related to the Qt port of WebKit Search

1 571

MakingBotsRed

Search

55

NativeListBox NativePopUp NativeTextArea NativeTextField NeedsRadar NeedsReduction NeedsUI Performance PlatformOnly Qt QtTriaged

Search Search Search Search Search Search Search Search Search Search

35 49 70 132 498 892 7 110 1196 2912 1405

Indicates that the Qt bug was triaged according to the Bug Reporting Guidelines, Search and passed This bug is a regression from a previous version of WebKit. Search

Regression

2501

ReviewedForRadar

This bug has been reviewed to determine whether it needs to be imported into Radar. Search If it does a NeedsRadar keyword will be

1132

set. When it is later migrated to Radar, the NeedsRadar keyword will be replaced by InRadar. Clear the ReviewedForRadar if you feel a bug should be reconsidered. SVGHitList Worst SVG Bugs. Any of these could block SVG from ever being included in an Search official WebKit release. Bugs about the new implementation of the search field Search 55

SearchField Soup SquirrelFish Wx XSSAuditor YahooBug


11 33 33 45 32 18

Bugs related to the use of the Soup network Search library in WebCore Bugs related to the SquirrelFish branch of JavaScriptCore Bugs related to the wx port of WebKit. Tasks related to the XSS Auditor. This bug affects Yahoo products. Search Search Search Search

Actions: o Home o | New o | Search o |
Find

o o o o

| Reports | Requests | New Account | Log In

Getting a Useful Crash Log
Crash logs are incredibly useful when trying to track down a bug, especially if it's not immediately reproducible.
Mac OS X

Obtaining a crash log on Mac OS X is incredibly easy since it automatically creates easily accessible crash logs for you.

1. If WebKit has just crashed or you can easily reproduce the crash, press the Report button on the CrashReporter dialog box to view the crash information.

2. Copy and paste the entire contents of the top portion of the CrashReporter window into your favorite text editor and upload it as an attachment in Bugzilla.

3. If the crash report dialog does not appear or the crash is hard to reproduce, crash logs can be retrieved from the ~/Library/Logs/CrashReporter folder. On Leopard (Mac OS X 10.5), crash logs are stored as individually dated and time stamped files. Despite having a “.crash” extension, they are plain text files and can be attached directly to a bug report. On Tiger (Mac OS X 10.4), all crashes are logged to Safari.crash.log. This is a plain text file and can be viewed in the default Console.app or your favorite text editor. All of Safari's crashes are logged to this file so please only attach the last crash in it. Crashes are separated by a series of asterisks (∗∗∗∗∗∗∗∗∗∗) for easy identification.
Windows XP

Windows XP does not automatically log crashes like OS X, but it does include Dr. Watson, an easy to set up tool that can be configured to log them. 1. In the Start menu's Run box or from a DOS or Cygwin prompt, enter the command drwtsn32 -i.

2. A dialog box will appear informing you that Dr. Watson has been installed as the default debugger. Press OK.

3. Crash information will now be logged to the user.dmp file in C:\Documents and Settings\All Users\Application Data\Microsoft\Dr Watson\.

Dr. Watson will create a user.dmp file that records what WebKit was doing when it crashed. Be careful as it is overwritten with every crash. When reporting a WebKit bug, please upload the user.dmp file if possible. 4. Running drwtsn32 without any options or switches will bring up a window that allows you to change various setting such as moving the log folder to a more easily accessible location or throwing a visual alert letting you know it caught the crash.

Windows Vista

Windows Vista does not include Dr. Watson. Instead, Windows Error Reporting (WER) has been integrated into the operating system. By default, Vista uploads the crash logs to Microsoft, but does not save a local copy. This is configurable via the registry. 1. Save the following text to a file named wer.reg:
2. Windows Registry Editor Version 5.00 3. 4. [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting]

5. "ForceQueue"=dword:00000001

6. Double-click the file from Windows Explorer and respond affirmatively to any prompts. 7. Reboot The next time Safari (or any other application) crashes, the crash information will be written into a folder located inside %LOCALAPPDATA%\Microsoft\Windows\WER\ReportQueue. Check the modification date to make sure you are using the correct file. Be sure to include the following files in your bug report:
WERxxxx.tmp.mdmp

This is the most important file. It contains the crash dump that can be opened inside Visual Studio or other Windows debuggers.
WERxxxx.tmp.version.txt

Contains the operating system version and other hardware information.
WERxxxx.tmp.appcompat.txt

Lists all of the DLLs loaded at the time of the crash with their version information.

Bugzilla
Creating a Bugzilla account

All you have to do to create a Bugzilla account is enter your email-address and optionally your real name. You will then receive an email with your password, with which you can login and do anything you want. Just follow this link: get a Bugzilla account.
Bugzilla "bits"

A "bit" in Bugzilla terms is a setting that allows you to do something. The ones most people doing a lot with Bugzilla should have are the "canconfirm"-bit and the "editbugs"-bit. You probably figured out what they do yourself just by their names but i'll explain them anyway. canconfirm-bit This bit, when switched on, allows you to confirm bugs of other people when you have confirmed that the bug they describe is real, moving a bug from UNCONFIRMED to NEW. It also allows you to file your own bugs as NEW, instead of UNCONFIRMED, which saves you time when you know for certain that a bug is real. editbugs-bit The editbugs bit allows you to edit any part of a bugreport even if you haven't filed the bug

yourself. You can change the title, keywords, component etc. to what you think is best. Having this bit means you can automatically also confirm bugs.
How to get these "bits"?

When you think you have earned the right to have either of these bits switched on for you, contact us. Do not hesitate to mail the mailing-list or ask on our IRC channel. If you mail the mailing-list, give us the numbers of a few bugs you filed or bugs you commented on, so we can check if we think you've earned it too.

Bugzilla
Creating a Bugzilla account

All you have to do to create a Bugzilla account is enter your email-address and optionally your real name. You will then receive an email with your password, with which you can login and do anything you want. Just follow this link: get a Bugzilla account.
Bugzilla "bits"

A "bit" in Bugzilla terms is a setting that allows you to do something. The ones most people doing a lot with Bugzilla should have are the "canconfirm"-bit and the "editbugs"-bit. You probably figured out what they do yourself just by their names but i'll explain them anyway. canconfirm-bit This bit, when switched on, allows you to confirm bugs of other people when you have confirmed that the bug they describe is real, moving a bug from UNCONFIRMED to NEW. It also allows you to file your own bugs as NEW, instead of UNCONFIRMED, which saves you time when you know for certain that a bug is real. editbugs-bit The editbugs bit allows you to edit any part of a bugreport even if you haven't filed the bug yourself. You can change the title, keywords, component etc. to what you think is best. Having this bit means you can automatically also confirm bugs.
How to get these "bits"?

When you think you have earned the right to have either of these bits switched on for you, contact us. Do not hesitate to mail the mailing-list or ask on our IRC cha



Bug Prioritization

Prioritizing Web Kit Bugs in Bugzilla
This document describes the current guidelines for assigning priorities to Web Kit bugs in Bugzilla. The relevant bugs are all of those whose product is "WebKit".
Standard priority rules

Each bug is assigned the first appropriate priority listed below from top to bottom.
P1
   

Any reproducible crash or hang. Any regression from a previous publicly released version of WebKit. Serious problem on important site due to site change or newly-important site. Serious security issue.

P2
   

Site that does not function in some non-trivial way. Serious performance complaints. Site that has really bad cosmetic problems (e.g., content overlapping such that it's very hard to read). Unreproducible crash or hang that has been reported many times.

P3
   

Site that works but has some cosmetic problems. Minor performance complaints, such as trivial memory leaks. Architecture issues that could help with correctness or performance but are not a clear win in advance. Unreproducible crash or hang.

P4


All enhancement requests and feature requests not covered the criteria for p1, p2, or p3.

P5


P5 is not used for WebKit bugs. WebKit shares its Bugzilla with other projects who might use it, that's why it's still there.

Common adjustments to priority
  

If there is a workaround, the priority may be moved down. If a bug gets a lot of duplicates, the priority may be moved up. If a bug is getting a lot of public attention, the priority may be moved up.



If a bug is on a very important site, the priority may be moved up.



Test Case Reduction

Test Case Reduction
A general guide to test case reduction

The basic idea behind bug reduction is to take a page that demonstrates a problem and remove as much content as possible while still reproducing the original problem.
Why is this needed?

A reduced test case can help identify the central problem on the page by eliminating irrelevant information, i.e., portions of the HTML page’s structure that have nothing to do with the problem. With a reduced test case, the development team will spend less time identifying the problem and more time determining the solution. Also, since a site can change its content or design, the problem may no longer occur on the real-world site. By constructing a test case you can capture the initial problem.
The first steps

Really the first step in reducing a page is to identify that main problem of the page. For example:
  

Does the page have text overlapping an image? Is there a form button that fails to work? Is there a portion of the page missing or misaligned?

After you have made this determination, you need to create a local copy of the page created from the page source window. After saving this source, it’s a good idea to put a <BASE> element in the HEAD so that any images/external style sheet or scripts that use a relative path will get loaded. After the BASE element has been added, load the local copy into the browser and verify that problem is still occurring. In this case, let’s assume the problem is still present.
Work from top to bottom

In general, it’s best to start from the top of the <DOCTYPE> and work down through the HEAD to the BODY element. Take a look at the HTML file in a text editor and view what types of elements are present in the <head>. Typically, the HEAD will include the <title> element, which is required, and elements such as <link>, <style> and <script>. The reduction process is to remove one element at a time, save, and reload the test case. If you have removed the element and the page is still displaying the problem, continue with the next element. If removing an element in the HEAD causes the problem to not occur, you may have

found one piece of the problem. Re-add this element back into the HEAD, reload the page and confirm the problem is still occurring and move on to the next element in the HEAD.
Finished the HEAD? Continue with the BODY!

Once the HEAD element has been reduced, you need to start reducing the number of required elements in the BODY. This will tend to be the most time consuming since hundreds (thousands) of elements will be present. The general practice is start removing elements by both their <start> and </end> elements. This is especially true for tables, which are frequently nested. You can speed up this process by selecting groups of elements and removing them but ideally you need to save and reload the test case each time to verify the problem is happening.
Another method

Another way to help you identify unnecessary elements is to temporarily deselect the option “Enable Javascript” in Safari preferences. If you turn this option off and loading your test case still reproduces the problem, then any script elements that are present can be removed since they are not a factor in this issue. Let’s say that you have reduced the page down to a nested table with an ordered list with an <link> element that need to be present. It’s good practice to identify that CSS rule that is being in the external file and add it directly to the test case. Create a <style> </style> in the head and copy/paste the contents of the .css file into this style element. Remove the <link> and save the changes. Load the test case and verify the problem is still occurring. Now manually delete or comment out each CSS rule until you have just the required set of rules to reproduce.
Adding to the bug

When you’ve finished your reduction, you should add it to the bug. It’s quite likely that in the process of reducing, you have found the root cause of the problem, so you are able to set the right component. Don’t forget to add the HasReduction keyword to the bug (and remove the NeedsReduction keyword, if present). If you do not have the rights to change the component or the keywords, read about how to get them in this document about Bugzilla.
Ready to begin?

In addition to providing reductions for bugs that you’ve found, you can help by reducing any of the bugs in Bugzilla tagged with the NeedsReduction keyword.

Bugzilla
Creating a Bugzilla account

All you have to do to create a Bugzilla account is enter your email-address and optionally your real name. You will then receive an email with your password, with which you can login and do anything you want. Just follow this link: get a Bugzilla account.

Bugzilla "bits"

A "bit" in Bugzilla terms is a setting that allows you to do something. The ones most people doing a lot with Bugzilla should have are the "canconfirm"-bit and the "editbugs"-bit. You probably figured out what they do yourself just by their names but i'll explain them anyway. canconfirm-bit This bit, when switched on, allows you to confirm bugs of other people when you have confirmed that the bug they describe is real, moving a bug from UNCONFIRMED to NEW. It also allows you to file your own bugs as NEW, instead of UNCONFIRMED, which saves you time when you know for certain that a bug is real. editbugs-bit The editbugs bit allows you to edit any part of a bugreport even if you haven't filed the bug yourself. You can change the title, keywords, component etc. to what you think is best. Having this bit means you can automatically also confirm bugs.
How to get these "bits"?

When you think you have earned the right to have either of these bits switched on for you, contact us. Do not hesitate to mail the mailing-list or ask on our IRC channel. If you mail the mailing-list, give us the numbers of a few bugs you filed or bugs you commented on, so we can check if we think you've earned it too. WebKit Bugzilla Bug List
   

Home | New | Search |
Find

    

| Reports | Requests | New Account | Help | Log In Sun Apr 17 2011 11:46:26 PST The self-criticism of a tired mind is suicide. - Charles Horton Cooley

200 bugs found. ID Se P OS

Assignee

Sta Resolu

Summary

v ri

tus

tion REGRESSION: ASSERTION FAILED: m_webFrame->_private->currentItem (WebFrameLoaderClient::restoreScrollPosit ionAndViewState()) REGRESSION: Upload progress does not display at DriveHQ.com REGRESSION: Tabbing doesn't return focus to address bar when expected REGRESSION: [Tiger only] Select pop-up menus are drawn split on bugzilla.mozilla.org REGRESSION: svg/custom/foreign-objectskew.svg is broken on TOT in Leopard REGRESSION: <canvas> transparent gradient rendering in 10.5 Valgrind: Invalid read of size 4 REGRESSION (3.0 - 3.1): Dojo layout test page hangs Webkit window REGRESSION: MetaFilter content shown below sidebar until refresh REGRESSION: WebKit double-draws selections in some cases REGRESSION: MLB Gameday doesn't load Crash in RenderObject::containingBlock() opening chess.com live chess WebKit crashes when visiting brokencertificate sites

webkit117 M P Ma NE [email protected] 31 aj 1 c W eb... webkit134 N P Ma NE [email protected] 81 or 1 c W eb... webkit151 N P Ma NE [email protected] 66 or 1 c W eb... webkit151 N P Ma NE [email protected] 68 or 1 c W eb... webkit157 N P Ma NE [email protected] 24 or 1 c W eb... webkit160 M P Ma NE [email protected] 45 aj 1 c W eb... webkit165 N P Ma NE [email protected] 12 or 1 c W eb... webkit188 N P Ma NE [email protected] 96 or 1 c W eb... webkit197 N P Ma NE [email protected] 07 or 1 c W eb... webkit202 N P Ma NE [email protected] 29 or 1 c W eb... webkit204 N P Ma NE [email protected] 94 or 1 c W eb... webkit212 N P Ma NE [email protected] 65 or 1 c W eb... 234 N P Wi webkitNE 04 or 1 nd [email protected] W

eb... webkit234 N P Ma NE [email protected] 24 or 1 c W eb... webkit245 N P Ma NE [email protected] 55 or 1 c W eb... webkit303 N P Lin NE [email protected] 12 or 1 u W eb... webkit421 N P Ma NE [email protected] 28 or 1 c W eb... webkit429 M P Ma NE [email protected] 54 aj 1 c W eb... webkit452 N P Wi NE [email protected] 02 or 1 nd W eb... webkit572 N P Ma NE [email protected] 14 or 1 c W eb... 396 N P Ma [email protected] 20 or 2 c NE W REGRESSION: Recording at screentoaster.com stalls while loading REGRESSION (r40142): FCK editor initially has incorrect size [Gtk] REGRESSION: WebKit fails part 2 of PeaceKeeper benchmark Safari hangs on siano-ms.com REGRESSION: Reproducible crash when pausing in JS debugger Intermittent crashes in EventSource::close() REGRESSION: Navigating to a named anchor causes content to shift off page Clicks inside button elements are sometimes discarded when the mouse moves Pasteboard sometimes receives hidden content. SVG Filters do not support source images besides "sourceGraphic" and "sourceAlpha" Apycom DHTML Menu used on http://www.melges24.com does not work. Table is not dynamically updated when scrolling HTML editing API's not fully rendered and/or not working parent != iframes[i].contentWindow

webkit566 N P Ma NE [email protected] 9 or 2 c W eb... webkit602 N P Ma NE [email protected] 2 or 2 c W eb... webkit764 N P Ma NE [email protected] 2 or 2 c W eb... webkit768 N P Ma NE [email protected] 4 or 2 c W eb... webkit793 M P Ma NE [email protected] 2 aj 2 c W eb... 803 N P Wi webkitNE

6

or 2 nd [email protected] W eb... Flash/JavaScript "LiveConnect" does not work at game site REGRESSION (r14032): Incorrect and nonuniform text zoom applied after going forward and backward Quirksmode: Safari ignores window.close() after form submission Text Input Element: Detection of focus or setting of focus broken Stylesheets fail to reload after b/f navigation @ fandango.com Dropdown menus on the front page don't work Page does not layout right High CPU usage during layout after mouse movement Layout problem.

webkit869 N P Ma NE [email protected] 7 or 2 c W eb... webkit875 N P Ma NE [email protected] 3 or 2 c W eb... webkit925 N P Ma NE [email protected] 4 or 2 c W eb... webkit946 N P Ma NE [email protected] 0 or 2 c W eb... webkit970 N P Ma NE [email protected] 1 or 2 c W eb... webkit971 N P Ma NE [email protected] 9 or 2 c W eb... webkit972 N P Ma NE [email protected] 9 or 2 c W eb... webkit975 M P Ma NE [email protected] 1 aj 2 c W eb... webkit998 N P Ma NE [email protected] 1 or 2 c W eb... webkit101 M P Ma NE [email protected] 65 aj 2 c W eb... webkit101 N P Ma NE [email protected] 72 or 2 c W eb... webkit103 N P Ma NE [email protected] 41 or 2 c W eb... 104 M P Ma webkitNE 76 aj 2 c [email protected] W

Vox: Master Bug

Splunk web application compatibility SVGs fail to render intermittently (on reload) Alert pops up complaining about TypeError (Safari)/ReferenceError (WebKit)

eb... webkit105 N P Ma NE [email protected] 78 or 2 c W eb... webkit113 N P Ma NE [email protected] 75 or 2 c W eb... webkit115 N P Ma NE [email protected] 16 or 2 c W eb... webkit118 M P Ma NE [email protected] 35 aj 2 c W eb... webkit118 N P Ma NE [email protected] 38 or 2 c W eb... webkit120 N P Ma NE [email protected] 10 or 2 c W eb... webkit121 N P Ma NE [email protected] 38 or 2 c W eb... webkit121 N P Ma NE [email protected] 76 or 2 c W eb... webkit123 N P Ma NE [email protected] 24 or 2 c W eb... webkit124 N P Ma NE [email protected] 14 or 2 c W eb... webkit125 N P Ma NE [email protected] 29 or 2 c W eb... webkit125 N P Ma NE [email protected] 40 or 2 c W eb... webkit127 N P Ma NE [email protected] 09 or 2 c W eb... Framesets keeps loading recursively, resulting in massively nested frames Content missing Dragging a text selection on an RSS page can select all text above the intended selection www.thestar.com sites very slow to load, but instant in Camino Reopening SVG world map makes it blank Page does not load in Safari (downloads instead) likely due to mime type Menus on peachtree.com don't display correctly Hotel 'View/Cancel a reservation' option missing User needs to be able to set Lucida Grande "italic" Layout weirdness on Kotaku.com in Safari and Nightlies (r19136) Drop down menus do not work on this site Crash using Kimpton Hotel's internet access when second timer window opened CSS3: The :first-of-type:first-letter pseudo selector combination fails

webkit128 M P Ma NE [email protected] 35 aj 2 c W eb... webkit130 N P Ma NE [email protected] 66 or 2 c W eb... webkit131 N P Ma NE [email protected] 14 or 2 c W eb... webkit131 N P Ma NE [email protected] 33 or 2 c W eb... webkit132 N P Ma NE [email protected] 30 or 2 c W eb... webkit134 N P Ma NE [email protected] 75 or 2 c W eb... webkit135 N P Ma NE [email protected] 04 or 2 c W eb... webkit135 N P Ma NE [email protected] 26 or 2 c W eb... webkit136 N P Ma NE [email protected] 39 or 2 c W eb... webkit136 N P Ma NE [email protected] 98 or 2 c W eb... webkit137 N P Ma NE [email protected] 45 or 2 c W eb... webkit138 N P Ma NE [email protected] 86 or 2 c W eb... webkit142 N P Ma NE [email protected] 46 or 2 c W eb... 144 M P Ma webkitNE

WebKit fails to even load the W3C/NIST DOM Conformance Test Suite Slacker Web Player Error

http://www.itwire.com.au/ misrenders badly The awesome Zune blog's date header overlaps the description Assertion failure in [WebBaseNetscapePluginStream dealloc] (isTerminated) when leaving page 272 leaks for 12304 total leaked bytes at pcadvisor.co.uk Flash deep linking causes page to reload Overlapping site image on The awesome Giveaway of the Day site REGRESSION: Menus at register.com broken in Safari 2.0, works in v1.2 Text overlaps picture when page widened

realeditor.com does not support WebKit Partially obscured vertical scroll bar on DIV does not draw properly on page load Text tearing in colloquy when using "Blak" style Selection highlight in the caption not

67

in 2 c

[email protected] W eb...

completely cleared when advancing to the next photo on Picasa Web Albums ASSERTION FAILED: !containsImage || MimeTypeRegistry::isSupportedImageReso urceMIMEType([resource MIMEType]) getComputedStyle() returns an empty style declaration for detached elements Comments not visible due to wide table in blog entry "Bad field count" message when running Cookie Test on Philiweb.com Repaint issues related to removing or resizing nodes in documents that rely heavily on CSS styling of nodes. Bug in columns support (relpositioned inlines) padding left & right ignored when using percentage values. Quick Reply feature misplaces iframe on KFAN fourms Left navigation renders over main body

webkit144 N P Ma NE [email protected] 93 or 2 c W eb... webkit145 N P Ma NE [email protected] 63 or 2 c W eb... webkit145 N P Ma NE [email protected] 97 or 2 c W eb... webkit146 N P Ma NE [email protected] 57 or 2 c W eb... webkit146 N P Ma NE [email protected] 75 or 2 c W eb... webkit146 N P Ma NE [email protected] 91 or 2 c W eb... webkit146 N P Ma NE [email protected] 94 or 2 c W eb... webkit149 N P Ma NE [email protected] 33 or 2 c W eb... webkit149 N P Ma NE [email protected] 40 or 2 c W eb... webkit149 N P Ma NE [email protected] 56 or 2 c W eb... webkit151 N P Ma NE [email protected] 20 or 2 c W eb... webkit151 N P Ma NE [email protected] 84 or 2 c W eb... 151 N P Ma webkitNE 86 or 2 c [email protected] W

1 pixel background-image shift Offender Locator page does not load (Windows Live Maps mashup) EA Website broken in Safari and WebKit r25484; fine in Firefox Error reloading www.quomodo.com after a file upload

eb... webkit152 N P Ma NE [email protected] 46 or 2 c W eb... webkit153 N P Ma NE [email protected] 90 or 2 c W eb... webkit154 N P Ma NE [email protected] 73 or 2 c W eb... webkit154 N P Ma NE [email protected] 84 or 2 c W eb... webkit155 N P Ma NE [email protected] 03 or 2 c W eb... webkit155 N P Ma NE [email protected] 16 or 2 c W eb... webkit155 N P Ma NE [email protected] 87 or 2 c W eb... webkit155 N P Ma NE [email protected] 93 or 2 c W eb... webkit156 N P Ma NE [email protected] 25 or 2 c W eb... webkit158 N P Ma NE [email protected] 36 or 2 c W eb... webkit160 M P Ma NE [email protected] 38 in 2 c W eb... webkit161 N P Ma NE [email protected] 51 or 2 c W eb... webkit162 N P Ma NE [email protected] 55 or 2 c W eb... Scroll bar removed during page load is not repainted properly Uncaught Exception hit in cookie code while quitting? safari from Lively Kernel SVG fails all 3 of Hixie's CSS intrinsic sizing tests Safari (and opera) fire two onload events while FireFox fires only one DumpRenderTree crashes in loader callbacks Inspector hangs in Position::isRenderedText() inspecting this file Unable to type a left parenthesis when suggest is enabled on google. "CMSCreateDataProviderOrGetInfo : Invalid colorspace type" on www.whatwg.org Page rendered incorrectly after submitting feedback form (www.msnbc.msn.com) WebKit fails some WICD 1.0 core test cases No scroll bars or incorrect scroll height on PayPal bank account help page Report Bill button does not work in BillMonk New GMail interface: unrecognised email address error does not appear

webkit162 N P Ma NE [email protected] 57 or 2 c W eb... webkit162 N P Ma NE [email protected] 68 or 2 c W eb... webkit162 M P Ma NE [email protected] 77 in 2 c W eb... webkit164 N P Ma NE [email protected] 84 or 2 c W eb... webkit164 N P Ma NE [email protected] 91 or 2 c W eb... webkit167 N P Ma NE [email protected] 21 or 2 c W eb... webkit167 N P Ma NE [email protected] 37 or 2 c W eb... ID Se P OS v ri Assignee Sta Resol tus ution NE W NE W NE W NE W NE W NE W

Gmail Long e-mail "To" list makes Safari widen messages target="_top" in embedded SVG fails to replace parent content Problem increasing the size of pictures on this site WebKit fails WICD onunload test WebKit fails to display SVG in WICD test case problem with 'New views' at www.nabble.com Weird selection issues (hit detection?) on site Summary ASSERTION FAILED: maxWidth >= 0

webkit167 N P Wi unassigned@lists. 57 or 2 nd web... webkit168 N P Ma unassigned@lists. 64 or 2 c web... webkit169 N P Ma unassigned@lists. 18 or 2 c web... webkit169 N P Ma unassigned@lists. 29 or 2 c web... webkit169 N P Ma unassigned@lists. 53 or 2 c web... 169 N P Ma webkit62 or 2 c unassigned@lists.

gear popups offset if window is scrolled ASSERTION FAILED: !HashTranslator::equal(KeyTraits::emptyVal ue(), key) div on this page has JS code rendered in it, and ad is offset REGRESSION(Safari3-TOT): SVG renders improperly WebKit fails linking-url-01 and 02 (<view> support)

web... webkit170 N P Ma unassigned@lists. 38 or 2 c web... webkit170 N P Ma unassigned@lists. 40 or 2 c web... webkit170 N P Ma unassigned@lists. 44 or 2 c web... webkit171 N P Ma unassigned@lists. 59 or 2 c web... webkit171 N P Ma unassigned@lists. 66 or 2 c web... webkit174 N P Ma unassigned@lists. 59 or 2 c web... webkit174 N P Ma unassigned@lists. 74 or 2 c web... webkit174 N P Ma unassigned@lists. 99 or 2 c web... webkit175 N P Wi unassigned@lists. 16 or 2 nd web... webkit175 N P Ma unassigned@lists. 42 or 2 c web... webkit175 N P Ma unassigned@lists. 61 or 2 c web... webkit176 N P Ma unassigned@lists. 35 or 2 c web... webkit178 N P Ma unassigned@lists. 69 or 2 c web... NE W NE W NE W NE W NE W NE W NE W NE W NE W NE W NE W NE W NE W Font size does not work correct when using the HTML GUI Editing on GuildPortal SWSoft (parent of Parallels Inc.) website menu issues FOUC when (re)loading page at nuernberg.de Navigation menu works incorrectly Test (and fix) complex resource invalidations (symbol nesting, CDF symbols) .big-issue style text overlaps on HTML5 spec Foafnaut doesn't work Display issue--extended calendar on delta.com at onclick in a select box no change the article picture Sports Menu on Texags.com not rendering on initial load Content border cap renders incorrectly

Page content shifted too high REGRESSION: menu bar renders incorrectly

webkit180 N P Ma unassigned@lists. 00 or 2 c web... webkit187 N P Ma unassigned@lists. 54 or 2 c web... webkit191 N P Ma unassigned@lists. 76 or 2 c web... webkit193 N P Ma unassigned@lists. 79 or 2 c web... webkit194 N P Ma unassigned@lists. 22 or 2 c web... webkit201 N P Ma unassigned@lists. 74 or 2 c web... webkit204 N P Ma unassigned@lists. 88 or 2 c web... webkit205 N P Ma unassigned@lists. 02 or 2 c web... webkit205 N P Ma unassigned@lists. 10 or 2 c web... webkit205 N P Ma unassigned@lists. 17 or 2 c web... webkit205 N P Ma unassigned@lists. 83 or 2 c web... webkit205 N P Ma unassigned@lists. 87 or 2 c web... webkit206 M P Wi unassigned@lists. 50 aj 2 nd web... 209 N P Wi webkit-

NE W NE W NE W NE W NE W NE W NE W NE W NE W NE W NE W NE W NE W NE

ASSERTs in FrameView::scheduleRelayout() Right click on story link causes hang VMware virtual appliance download page broken in Safari WebEx Plugin can't launch application Distinct redirects from the same link do not create distinct history items weird faint lines on canvas when drawing lines div displays in wrong location after being hidden and shown twice The back/forward cache breaks Acid 2 eyes fallback content text content not displayed WebKit fails two elements of the "Web Compatibility Test for Mobile Browsers" Form field values aren't submitted when hitting ENTER WebKit eats CPU on http://uk.sun.com/tryandbuy/products.jsp Robohelp Web Help: Table of Contents does not render on Windows Huge memory usage on Dromaeo test

64

or 2 nd unassigned@lists. web...

W NE W NE W NE W NE W NE W NE W NE W NE W NE W NE W NE W NE W NE W "New" corner out of place at Apple iTunes overview page Video in wrong position @ blizzard.com worldofwarcraft.com Problem Rendering

webkit209 N P Ma unassigned@lists. 66 or 2 c web... webkit209 N P Ma unassigned@lists. 71 or 2 c web... webkit225 N P Ma unassigned@lists. 47 or 2 c web... webkit230 N P Ma unassigned@lists. 61 or 2 c web... webkit233 N P Wi unassigned@lists. 30 or 2 nd web... webkit233 N P Ma unassigned@lists. 44 or 2 c web... webkit236 N P Ma unassigned@lists. 46 or 2 c web... webkit239 N P Wi unassigned@lists. 64 or 2 nd web... webkit241 N P Ma unassigned@lists. 69 or 2 c web... webkit242 N P Ma unassigned@lists. 20 or 2 c web... webkit243 N P Wi unassigned@lists. 18 or 2 nd web... webkit252 N P Ma unassigned@lists. 96 or 2 c web... 256 N P Ma webkit20 or 2 c unassigned@lists.

Layout problems at http://www.cfi.net.cn

Plug-in originated popup not blocked HTMLFormElement magic differs from HTML5 ASSERTION FAILED: docLoader>requestCount() == 0 Repaint errors when collapsing text REGRESSION: gap.com (and affiliates) "QuickLinks" aren't linkfied GCGetGlyphIdealMetrics fails and causes random text Regression: Can't click on navigation links on WebKit nightlies. Image caption overlaps article text when zoomed out a single level REGRESSION (r43007): In MobileMe Calendar, New Event text is displayed offset

web... webkit258 N P Ma unassigned@lists. 13 or 2 c web... webkit258 N P Ma unassigned@lists. 33 or 2 c web... webkit259 N P Wi unassigned@lists. 48 or 2 nd web... webkit264 N P Ma unassigned@lists. 51 or 2 c web... webkit264 N P Ma unassigned@lists. 73 or 2 c web... webkit265 N P Wi unassigned@lists. 06 or 2 nd web... webkit268 M P Wi unassigned@lists. 26 aj 2 nd web... webkit269 M P Ma unassigned@lists. 86 aj 2 c web... webkit280 N P Ma unassigned@lists. 52 or 2 c web... webkit288 N P All unassigned@lists. 17 or 2 web... webkit292 N P Ma unassigned@lists. 32 or 2 c web... webkit305 N P Ma unassigned@lists. 07 or 2 c web... webkit313 N P Wi unassigned@lists. 04 or 2 nd web... NE W NE W NE W NE W NE W NE W NE W NE W NE W NE W NE W NE W NE W

when it's first created First highlighted search is missing, searching for "webkit" on http://developer.apple.com/wwdc/sessions/ Page that performs syntax highlighting on <code> elements in JS looks wrong when loaded from web archive Unexpected Space after 20 characters in column Overlapping content at openbossa.org Incorrectly positioned content at marrow.org (Be The Match registry website) ASSERTION FAILED: stack.size() == depthCrossingShadowBoundaries(node) Hang when clicking on link from kuwo.cn Crash on focussing non rendered input via javascript Photo browser doesn't display enlarged versions of photos Selection is vertically offset when selecting second line of chapter title text of Dive Into HTML 5 Page scrolls to original position on link hover Text repainting incorrect for a combination of padding, columns and ajax Clicking Comment Links on CodeProject Jumps to Middle of Page

webkit325 N P Ma unassigned@lists. 25 or 2 c web... webkit352 N P Ma unassigned@lists. 86 or 2 c web... webkit353 N P Ma unassigned@lists. 90 or 2 c web... webkit360 N P Ma unassigned@lists. 94 or 2 c web... webkit364 N P Ma unassigned@lists. 18 or 2 c web... webkit371 M P Ma unassigned@lists. 89 in 2 c web... webkit372 N P Ma unassigned@lists. 45 or 2 c web... webkit394 N P Ma unassigned@lists. 38 or 2 c web... webkit405 N P Ma unassigned@lists. 42 or 2 c web... webkit417 N P Ma unassigned@lists. 86 or 2 c web... webkit446 M P Ma unassigned@lists. 40 aj 2 c web... webkit474 N P Ma unassigned@lists. 84 or 2 c web... webkit480 N P Ma unassigned@lists. 57 or 2 c web...

NE W NE W NE W NE W NE W NE W NE W NE W NE W NE W NE W NE W NE W

Assertion failure in addStyleMarkup copying link text (from maps.google.com at least) YUI: Button title copied to other buttons when going back to a page behavior with http auth and xmlhttprequest Assertion failure (!layer>m_zOrderListsDirty) in RenderLayerCompositor::rebuildCompositin gLayerTree() Incorrect painting when switching tabs in github account settings Scroll lags on www.ligatureloopandstem.com 'Sign In' button missing from studentloans.gov 'X' buttons are drawn twice on Facebook ads Maps on ebparks.org (East Bay regional park district) are scaled incorrectly iFrame scrolling causes paint errors on boy.co.tt REGRESSION (r53420): Parts of aktrailhead.com invisible until page resize Assertion failure in JSEventListener::jsFunction() (m_wrapper || !m_jsFunction) ASSERT while loading reddit.com

webkit490 N P Ma unassigned@lists. 93 or 2 c web... webkit502 N P Ma unassigned@lists. 10 or 2 c web... webkit508 M P Ma unassigned@lists. 32 aj 2 c web... webkit520 N P Ma unassigned@lists. 60 or 2 c web... webkit547 N P Ma unassigned@lists. 11 or 2 c web... webkit585 N P Ma unassigned@lists. 00 or 2 c web...

NE W NE W NE W NE W NE W NE W

SMIL animation works forward only Positioning error in dynamically inserted content iFrame window gets clipped when Google map pans Layout glitches at noflash.pl login page Assertion failure in HTMLFrameElementBase::insertedIntoDocu ment() when opening comcast.net main page REGRESSION (r81992): Facebook photo tags can get cut off when moving the mouse. CGAffineTransformInvert: singular matrix. spewed to console http://htmlplayground.com/ doesn't work Scroll bars not removed after incremental layout Search button wrongly positioned at amnesty.se history is wrong after loading google.com/ig with digg or wikipedia Page content doesn't show Positioned UL+LIs menu shifts when LI id attribute is referenced (link to it clicked) WebMail button at virginbroadband.com.au does not submit

140 N P Ma zimmermann@kde. NE 65 or 2 c org W 242 N P Ma [email protected] 67 or 2 c m webkit102 N P Ma unassigned@lists. 55 or 3 c web... webkit113 M P Ma unassigned@lists. 02 in 3 c web... webkit129 M P Ma unassigned@lists. 93 in 3 c web... webkit146 N P Ma unassigned@lists. 86 or 3 c web... webkit182 M P Ma unassigned@lists. 55 in 3 c web... webkit205 N P Wi unassigned@lists. 95 or 3 nd web... NE W NE W NE W NE W NE W NE W NE W

webkit366 Tr P Ma unassigned@lists. 83 i 3 c web... webkit541 N P Ma unassigned@lists. 1 or 4 c web... webkit708 N P Ma unassigned@lists. 7 or 4 c web... webkit708 N P Ma unassigned@lists. 8 or 4 c web... webkit104 N P Ma unassigned@lists. 03 or 4 c web... webkit111 N P Ma unassigned@lists. 05 or 4 c web... webkit153 N P Ma unassigned@lists. 74 or 2 c web... webkit176 N P Ma unassigned@lists. 72 or 1 c web... webkit215 N P Ma unassigned@lists. 10 or 1 c web... webkit993 N P Ma unassigned@lists. 5 or 2 c web... webkit134 M P Ma unassigned@lists. 92 aj 2 c web... webkit135 N P Ma unassigned@lists. 91 or 2 c web... webkit141 N P Ma unassigned@lists. 80 or 2 c web...

NE W NE W NE W NE W NE W NE W AS SI RE OP RE OP RE OP RE OP RE OP RE OP

For compatibility, execCommand should support deprecated 'useCSS' alias for 'styleWithCSS' Sarissa test cases fail in Safari

zoozio doesn't work correctly in Safari zoho writer becomes "solid brown" after choosing several pop-up buttons SVG example fails to find resources Flash of white while dragging window during image load RenderBox::availableHeightUsing() contains left/right to top/bottom typo Reproducible SVG Crash when acid3-test77.html timing dependency is fixed REGRESSION: Patterns are recreated every time they paint Scroll bars not redrawn when using back/forward cache Weird behaviour; cursor turns into watch and links don't work. +[WebScriptObject _convertValueToObjcValue:originExecution Context:executionContext:] returns a wrong object for plug-in nodes Detached vertical scrollbar on usps.com (repaint issue)

webkit176 N P Ma unassigned@lists. 27 or 2 c web... 200 bugs found.
Long Format XML

RE OP

Endless reloads on http://space.cweb.nl

Remember search

CSV | RSS | iCalendar | Change Columns | Change Several Bugs at Once |

Edit Search

as



Actions: o Home o | New o | Search o |
Find

o o o o o

| Reports | Requests | New Account | Help | Log In

WebKit Bugzilla Bug 11731: REGRESSION: ASSERTION FAILED: m_webFrame->_private->currentItem (WebFrameLoaderClient::restoreScrollPositionAndViewState())
   

Home | New | Search |
Find

    

| Reports | Requests | New Account | Help | Log In

Bug List: (1 of 200) |« First Last »| « Prev Next » Show last search results

Bug 11731 - REGRESSION: ASSERTION FAILED: m_webFrame->_private->currentItem (WebFrameLoaderClient::restoreScrollPositionAndViewState()) Summary: Status: NEW REGRESSION: ASSERTION FAILED: m_webFrame->_private->currentItem (WebFrameLoad...

Product: WebKit Component: Page Loading Version: 420+ Macintosh Mac OS X Platform: 10.4 Importance: P1 Major Assigned Nobody To: URL: Keywords: Depends on: Blocks: Show dependency tree / graph InRadar, NeedsReduction, Regression, ... Reported: 2006-11-30 22:09 PST by David Kilzer (ddkilzer)

Modified: 2009-05-22 17:57 PST (History)

Attachments Test webarchive (will crash debug builds) (137.54 KB, application/xwebarchive) 2006-11-30 22:11 PST, David Kilzer (ddkilzer) Test App (48.52 KB, application/octet-stream) 2007-01-18 09:51 PST, David Smith View All Add an attachment (proposed patch, testcase, etc.) no flags no flags Details

Details

Note You need to log in before you can comment on or make changes to this bug.

Description From David Kilzer (ddkilzer) 2006-11-30 22:09:33 PST
Loading the attached webarchive on a locally-built debug build of WebKit r17937 on Mac OS X 10.4.8 with Safari 2.0.4 (419.3) causes an assertion

failure: ASSERTION FAILED: m_webFrame->_private->currentItem (/.../WebKit/WebKit/WebCoreSupport/WebFrameLoaderClient.mm:939 restoreScrollPositionAndViewState) This failure does not occur on the nightly build of r17937 (which is a release build). Crash reporter stack: Date/Time: 2006-11-30 22:45:05.509 -0600 OS Version: 10.4.8 (Build 8L127) Report Version: 4 Command: Safari Path: /Applications/Safari.app/Contents/MacOS/Safari Parent: bash [442] Version: Build Version: Project Name: Source Version: PID: 1990 Thread: 0 Exception: Codes: EXC_BAD_ACCESS (0x0001) KERN_INVALID_ADDRESS (0x0001) at 0xbbadbeef 2.0.4 (419.3) 1 WebBrowser 4190300

Thread 0 Crashed: 0 com.apple.WebKit 0x003d6724 WebFrameLoaderClient::restoreScrollPositionAndViewState() + 124 (WebFrameLoaderClient.mm:939) 1 com.apple.WebCore 0x014698a4 WebCore::FrameLoader::checkLoadCompleteForThisFrame() + 1352 (FrameLoaderMac.mm:1020) 2 com.apple.WebCore 0x01493e70 WebCore::FrameLoader::checkLoadComplete() + 204 (FrameLoader.cpp:2150) 3 com.apple.WebCore 0x01496dd0 WebCore::FrameLoader::removeSubresourceLoader(WebCore::ResourceLoader*) + 96 (FrameLoader.cpp:1749) 4 com.apple.WebCore 0x0147502c WebCore::SubresourceLoader::didFinishLoading() + 384 (SubresourceLoaderMac.mm:174) 5 com.apple.WebCore 0x0146f45c [WebCoreResourceLoaderAsDelegate connectionDidFinishLoading:] + 124 (ResourceLoaderMac.mm:571) 6 com.apple.Foundation 0x9299384c [NSURLConnection(NSURLConnectionInternal) _sendDidFinishLoadingCallback] + 188 7 com.apple.Foundation 0x92991ab8 [NSURLConnection(NSURLConnectionInternal) _sendCallbacks] + 556 8 com.apple.Foundation 0x92991810 _sendCallbacks + 156 9 com.apple.CoreFoundation 0x907dd4cc __CFRunLoopDoSources0 + 384 10 com.apple.CoreFoundation 0x907dc9fc __CFRunLoopRun + 452

11 com.apple.CoreFoundation 0x907dc47c CFRunLoopRunSpecific + 268 12 com.apple.HIToolbox 0x93208740 RunCurrentEventLoopInMode + 264 13 com.apple.HIToolbox 0x93207dd4 ReceiveNextEventCommon + 380 14 com.apple.HIToolbox 0x93207c40 BlockUntilNextEventMatchingListInMode + 96 15 com.apple.AppKit 0x9370bae4 _DPSNextEvent + 384 16 com.apple.AppKit 0x9370b7a8 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 116 17 com.apple.Safari 0x00006740 0x1000 + 22336 18 com.apple.AppKit 0x93707cec -[NSApplication run] + 472 19 com.apple.AppKit 0x937f887c NSApplicationMain + 452 20 com.apple.Safari 0x0005c77c 0x1000 + 374652 21 com.apple.Safari 0x0005c624 0x1000 + 374308

------- Comment #1 From David Kilzer (ddkilzer) 2006-11-30 22:11:02 PST ------Created an attachment (id=11702) [details] Test webarchive (will crash debug builds) Webarchive file used to reproduce the assertion failure.

------- Comment #2 From David Smith 2007-01-18 09:51:43 PST ------Created an attachment (id=12537) [details] Test App This attachment is a tiny app that demonstrates the crash. It just loads an empty html file, and then when you click reload (attached to -reload:) it will crash. The executable is set to use the webkit from a nightly in /Applications.

------- Comment #3 From [email protected] 2007-01-18 14:05:31 PST ------According to David Smith, this crashes in release builds.

------- Comment #4 From Brady Eidson 2007-01-18 15:15:57 PST ------I can totally repro this using the test app. I don't have alot of time to look at it at the moment, but this is high on my priority list. It's quite easy to see from the assertion that it'll crash a release build, as well ;) Every single time!

------- Comment #5 From Mark Rowe (bdash) 2007-01-18 16:38:18 PST ------<rdar://problem/4940408>

------- Comment #6 From Joost de Valk (AlthA) 2007-01-19 06:45:08 PST ------If this crashes release builds as well, this isn't a regression now is it? :)

------- Comment #7 From [email protected] 2007-01-19 06:49:12 PST ------(In reply to comment #6) > If this crashes release builds as well, this isn't a regression now is it? :) > "release builds" in this context means "TOT builds using the release build style", not "shipping builds".

------- Comment #8 From [email protected] 2007-02-14 13:09:49 PST ------I could not reproduce the bug with the test app, although it's still reproducible with the webarchive.

------- Comment #9 From Anders Carlsson 2007-03-12 11:59:56 PST -------

This regressed in http://trac.webkit.org/projects/webkit/changeset/14920

------- Comment #10 From Alexey Proskuryakov 2007-04-29 00:07:31 PST ------The attached webarchive doesn't crash nightly r21059 for me. A comment after the failing assertion casts some doubt over its validity: // FIXME: As the ASSERT attests, it seems we should always have a currentItem here. // One counterexample is <rdar://problem/4917290> // For now, to cover this issue in release builds, there is no technical harm to returning // early and from a user standpoint - as in the above radar - the previous page load failed // so there *is* no scroll or view state to restore!

   

Format For Printing - XML - Clone This Bug - Top of page

Bug List: (1 of 200) |« First Last »| « Prev Next » Show last search results



Actions: o Home o | New o | Search o |
Find

o o o o o

| Reports | Requests | New Account | Help | Log In



Bug Life Cycle

WebKit Bug Life Cycle
Introduction

This document describes the life cycle of a bug in the WebKit open-source project. In most ways this is the same as the life cycle of a bug in any Bugzilla project. The Bugzilla site also includes more details about the life cycle of Bugzilla bugs.

Fresh, Unconfirmed Bugs

A freshly-created bug starts out in state UNCONFIRMED. Often it is in component New Bugs, but some bugs will be given an initial component in the initial bug-reporting step.
Confirming Bugs

The next step is for someone with Bugzilla canConfirm privileges to review the unconfirmed bug and decide whether it has enough useful information to move forward. The possible changes to the bug at this step include the following:
   

 

Resolution changed to DUPLICATE if the bug is determined to have the same cause as a bug reported earlier. Resolution changed to WORKSFORME if the bug seems to not be present in the latest sources. Resolution changed to INVALID if the bug does not describe a problem with WebKit. Resolution changed to WONTFIX in the rare case that the bug seems valid but there's a specific reason why it should not be fixed in WebKit (usually this would be a cross-browser compatibility issue). Comments/questions added if the bug does not have enough information to move forward. Status changed to NEW if the bug is reproducible with the latest sources on Mac OS X or otherwise has enough information to move forward. If the bug is not reproducible with the latest sources, but appears to occur only on the platform stated in the platform field, the PlatformOnly keyword is added as well as setting the status to NEW. Along with changing the status, the component should also be set to an appropriate one more specific than New Bugs if necessary.

Analyzing Bugs

Each bug is initially assigned to the person designated as owner of the component. The assignee should move the bug from status NEW to status ASSIGNED after they have read the bug and are satisfied that it represents a real problem in WebKit. If they are not satisfied about this, they should perform one of the actions mentioned in the Confirming Bugs section above. The same procedure is followed for bugs with status REOPENED (see Verifying Fixes below). The assignee represents the person who is expected to take the next step in investigating or fixing a bug. If someone other than the assignee is investigating or fixing a bug, the assignee should be changed to the person doing the work. This helps prevent duplicated work. It's always helpful to add a comment explaining why an assignee has been changed.
Proposing Fixes

A proposed patch should be added as a new attachment. The attachment should have the patch checkbox checked, and the review flag set to ?. This marks the patch as awaiting review. If the patch requires the specialized knowledge of a particular reviewer, the submitter or another reviewer should put the requested reviewer's email address in the Requestee field. Otherwise

this field should be left empty. The state is left at ASSIGNED at this point; it isn't changed to FIXED until a fix has been checked into the source tree. When the review flag's state is changed, or when a comment is made in the Edit form for an attachment, email is automatically sent to the webkit-reviews mailing list. The reviewers all subscribe to this list, and anyone else is free to do so as well. If the submitter of a patch changes their mind about wanting a review, they should clear the review flag by choosing the blank choice in the review pop-menu. More details about how to prepare code changes can be found elsewhere on this site.
Reviewing Proposed Fixes

A reviewer will read through each proposed patch. If the patch is ready to commit, the reviewer will change the review flag to +. For clarity, it's helpful for the reviewer to add a comment when approving a patch. Often this comment is just "r=me", which is simply shorthand for "I have reviewed this patch and it's ready to commit". A patch might not be ready to commit for various reasons. The bug fix might be incorrect. The test cases included in the patch might be insufficient. The bug fix and test cases might be fine but the coding style might be incorrect. The reviewer should always explain in detail why a patch is not ready to commit, so the submitter or someone else can revise the patch. When a submitter proposes an updated patch, they should check the obsolete checkbox on the previous version of the patch. This causes it to appear crossed-out in the list of attachments on the bug's main page. At the same time as marking the old patch obsolete, the submitter should also clear the review flag. This would happen automatically in a perfect world, but doesn't currently in this one.
Committing Patches

After a patch has been approved, someone with commit privileges in the WebKit source repository will commit the patch into the source code repository. The committer should change the state of the bug to FIXED; generally the assignee is left unchanged at this point. All of the people with commit privileges should be subscribed to the webkit-reviews mailing list, and so they will receive email when a patch is approved and thus ready to be committed. If an approved patch has not been committed for what seems to be an inordinately long time, the patch submitter could send email requesting status to this mailing list. As a last resort, the patch submitter could contact the reviewer directly. Due to everyone's busy schedules, some delays in getting patches reviewed, and then in getting them committed, are inevitable. If the bug report mentions that the same bug is represented in another internal system, such as Apple's internal Radar system, and the person who commits the bug has access to that system, then the person who commits the bug should also change the state of the bug appropriately in the

internal system. For a Radar bug the new appropriate state would be Software Changed/Integrate.
Verifying Fixes

After the patch for a bug has been committed, the fix still needs to be verified. Typically this step is done by the person who originally submitted the bug report. If the submitter is not available or does not feel that they can verify the fix, the verification step can be done by anyone with bug editing privileges who is familiar enough with the originally reported problem to be confident about testing it. Note that once a bug is in the FIXED state, the assignee can no longer be changed. This means that a bug that needs to be verified will not usually be assigned to the person expected to verify the bug. To verify a bug fix, build and run the sources that include the fix, and check whether the originally reported problem still occurs. If the problem no longer occurs, change the resolution to VERIFIED. If the problem does still occur, change the resolution to REOPENED and assign it to the person who submitted the patch.
Closing Bugs

Fixed bugs have the VERIFIED resolution until a version of WebKit that includes the fix has been publicly released. At this point, the resolution is changed to CLOSED.

Writing New Tests
A layout test is simply a web page. The layout test machinery renders the web page, and then dumps the internal representation, the render tree, with details of the layout. This lets engineers working on the project know if they do anything that changes the layout. Once we get a test rendering properly, we check it in as part of the layout test suite. The following are some guidelines to follow when writing new layout tests:
1. 2. 3. 4. The test should be the smallest possible code fragment that tests the feature. The test should fit on one page (unless of course it’s testing scrolling). The test should clearly describe what feature it is testing. The test should clearly describe the expected result. It should be possible through visual inspection alone to determine that the test has failed.

An example of a layout test that follows these guidelines is fast/events/eventcreation.html. A layout test should work both in the browser itself, and in the layout test tool. The layout test tool provides an additional object on the window object called the layout test controller with some methods that control test output. One you should know about is the layoutTestController.dumpAsText method. Calling this from JavaScript within a test arranges for the output to be written out as plain text rather than as a render tree dump. This is

useful for tests that are testing something other than layout. The event creation test mentioned above is a good example of how to do this and when it makes sense. Some tests require pixel-level comparisons. For these tests, you must generate expected output for a specific machine type, operating system, and color profile. When you add such a test, you can generate new expected output automatically using the run-webkit-tests --pixel command. This will automatically configure the color profile, and place the resulting rendered image (and checksum) in the appropriate platform directory for checkin. The Ahem font is useful in testing text layout, since its glyphs’ metrics are well known, and it is always available to tests running in the layout test tool. However, if you want to view tests that use Ahem in Safari, you should download Ahem, open it in the Font Book application, and click on the Install Font button to install it. The CSS working group has an excellent document on test writing guidelines for CSS tests. This wiki article has more information on writing good tests and the DumpRenderTree tool.

CSS2.1 Test Case Authoring Guidelines
Editors: Tantek Çelı̇k, Microsoft Corporation Ian Hickson, [email protected] Elika J. Etemad

Copyright © 2003 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C liability, trademark, document use and software licensing rules apply.

Abstract
This is a supporting document for authors of tests in the CSS2.1 test suite. It describes the key aspects of CSS tests, and gives various techniques authors should use when writing tests.

Status of this document
These guidelines were produced by members of the CSS working group which is part of the style activity (see summary).

Comments on, and discussions of this document can be sent on the (archived) public mailing list [email protected] (see instructions). W3C Members can also send comments directly to the CSS working group. These guidelines represent the current thinking of the working group and as such may be updated, replaced or rendered obsolete by other W3C documents at any time. Its publication does not imply endorsement by the W3C membership or the CSS Working Group (members only). Patent disclosures relevant to CSS may be found on the Working Group's public patent disclosure page.

Table of contents
 





1. Introduction 2. Key aspects of tests o 2.1. Easy to determine the result o 2.2. Quick to determine the result o 2.3. Self explanatory o 2.4. Short o 2.5. Valid o 2.6. Cross-platform 3. Format o 3.1. Kinds of test o 3.2. Links to the specification o 3.3. Recommended content o 3.4. Content-Style-Type and Content-Script-Type o 3.5. Encoding o 3.6. Special cases o 3.7. Filenames 4. Writing ideal tests o 4.1. Indicating success  4.1.1. The green paragraph  4.1.2. The green page  4.1.3. The green block  4.1.4. The green paragraph and the blank page  4.1.5. The two identical renderings  4.1.6. The positioned text o 4.2. Indicating failure  4.2.1. Red  4.2.2. Overlapped text  4.2.3. The word "FAIL"  4.2.4. Scrambled text o 4.3. Techniques  4.3.1. Overlapping  4.3.2. Special fonts  4.3.3. The self explanatory sentence followed by pages of identical text  4.3.4. Color

 



 4.3.5. Methodical testing 4.4. Tests to avoid  4.4.1. The long test  4.4.2. The counterintuitive "this should be red" test  4.4.3. Unobvious tests Acknowledgments References o Normative references o Other references Index o

1. Introduction
This document explains how to write test cases for the CSS2.1 test suite.

2. Key aspects of tests
A badly written test can lead to the tester not noticing a failure, as well as breaking the tester's concentration. Therefore it is important that the tests all be of a high standard.
2.1. Easy to determine the result

Tests are viewed one after the other in quick succession, usually in groups of several hundred to a thousand. As such, it is important that the results be easy to interpret.
2.2. Quick to determine the result

The tests should need no more than a few seconds to convey their results to the tester.
2.3. Self explanatory

The tests should not need an understanding of the specification to be used.
2.4. Short

Tests should be very short (a paragraph or so) and certainly not require scrolling on even the most modest of screens, unless the test is specifically for scrolling or paginating behaviour.
2.5. Valid

Unless specifically testing error-recovery features, the tests should all be valid.
2.6. Cross-platform

Test should be as cross-platform as reasonably possible, working across different devices, screen resolutions, paper sizes, etc. Exceptions should document their assumptions.

3. Format
Tests should follow the following template (see details):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>CSS Test: Description of test</title> <link rel="author" title="Name of Author" href="Contact URI for Author (mailto or http)"/> <link rel="help" href="http://www.w3.org/TR/CSS21/...#..."/> <meta name="flags" content="Requirement flags" /> <meta name="assert" content="Assertion the test is trying to prove (optional)" /> <style type="text/css"> CSS for test </style> </head> <body> Content of test </body> </html>

3.1. Kinds of test

The test suite will consist of the following kinds of tests:
basic cases tests that check the simple (but realistic) aspects of a feature, for example the various named color values, or inheritance of a property composite cases tests that check combinations of features, for example 'border-top-color' with 'color'. edge cases tests that check boundary conditions failure cases tests that check failure conditions and error-handling. (These tests are likely to involve invalid CSS2.1 stylesheets.) scenario cases tests that combine multiple features into one complex scenario (Acid 2 is an example of a scenario case, albeit one also that tests features outside the scope of the CSS specs)

3.2. Links to the specification

Each test will contain one or more links to the relevant part of the specification:
<link rel="help" href="link to part of specification">

The first of these links will decide the position of the test in the test suite. The links will be ordered from rare to common such that the link to the rarest feature will be first. The URIs will point to the /TR/CSS21/ spec (i.e. the "latest version"), not to the version existing at the time of publication.
3.3. Recommended content

Basic and failure tests should limit themselves to <p>, <div>, <img>, and <span> elements. Other tests checking for the interaction of CSS with other XHTML elements, or elements from other namespaces, may include those other elements too. If possible without compromising the test itself, block-level markup should be indented to show the structure of the document, as in the template given above.
3.4. Content-Style-Type and Content-Script-Type

When the document contains inline style attributes, then the following line should be added immediately after the title element in the markup:
<meta http-equiv="Content-Style-Type" content="text/css"/>

When the document contains inline script (event handler) attributes, then the following line should be added immediately after the title element in the markup:
<meta http-equiv="Content-Script-Type" content="text/javascript"/>

If both are present, the Content-Style-Type header should be given first.
3.5. Encoding

Tests should use UTF-8 unless the test is specifically checking encoding handling. If the XHTML 1.1 source files need to define a character set other than UTF-8 or UTF-16, then they will define their character set using an XML declaration, as in:
<?xml encoding="iso-8859-1"?/>

3.6. Special cases

It is expected that there will be special cases, e.g. tests that check for the cascading order of multiple stylesheets. Those tests will be handled on a case-by-case basis. Support files will all be kept in one support directory, if possible.
3.7. Filenames

Tests will be given a filename in a special format.
test-topic-###.ext test-topic

A short identifier that describes the test. The test-topic should avoid conjunctions, articles, and prepositions. It is a filename, not an English phrase: it should be as concise as possible.
###

This is a zero-filled number used to keep the filenames unique when files have the same testtopic name. For example in the case of margin-collapsing there are multiple cases so each case could have the same test-topic but different numbers.
ext

The file extension or format of the file, usually xht (for XHTML).

4. Writing ideal tests
Well designed CSS tests typically fall into several categories, named after the features that the test will have when correctly rendered by a user agent. Note: The terms "the test has passed" and "the test has failed" refer to whether the user agent has passed or failed a particular test — a test can pass in one web browser and fail in another. In general, the language "the test has passed" is used when it is clear from context that a particular user agent is being tested, and the term "this-or-that-user-agent has passed the test" is used when multiple user agents are being compared.
4.1. Indicating success 4.1.1. The green paragraph

This is the simplest form of test, and is most often used when testing the parts of CSS that are independent of the rendering, like the cascade or selectors. Such tests consist of a single line of text describing the pass condition, which will be one of the following:
This line should be green. This line should have a green border.

This line should have a green background.

Examples:
 

http://www.hixie.ch/tests/adhoc/css/box/inline/002.html http://www.hixie.ch/tests/adhoc/css/background/20.xml

4.1.2. The green page

This is a variant on the green paragraph test. There are certain parts of CSS that will affect the entire page, when testing these this category of test may be used. Care has to be taken when writing tests like this that the test will not result in a single green paragraph if it fails. This is usually done by forcing the short descriptive paragraph to have a neutral color (e.g. white). Example:


http://www.hixie.ch/tests/adhoc/css/background/18.xml

(This example is poorly designed, because it does not look red when it has failed.)
4.1.3. The green block

This is the best type of test for cases where a particular rendering rule is being tested. The test usually consists of two boxes of some kind that are (through the use of positioning, negative margins, zero line height, or other mechanisms) carefully placed over each other. The bottom box is colored red, and the top box is colored green. Should the top box be misplaced by a faulty user agent, it will cause the red to be shown. (These tests sometimes come in pairs, one checking that the first box is no bigger than the second, and the other checking the reverse.) Examples:
 

http://www.hixie.ch/tests/adhoc/css/box/absolute/001.xml http://www.hixie.ch/tests/adhoc/css/box/table/010.xml

4.1.4. The green paragraph and the blank page

These tests appear to be identical to the green paragraph tests mentioned above. In reality, however, they actually have more in common with the green block tests, but with the green block colored white instead. This type of test is used when the displacement that could be expected in the case of failure is likely to be very small, and so any red must be made as obvious as possible. Because of this, test would appear totally blank when the test has passed. This is a problem because a blank page is the symptom of a badly handled network error. For this reason, a single line of green text is added to the top of the test, reading something like:
This line should be green and there should be no red on this page.

Example:



http://www.hixie.ch/tests/adhoc/css/fonts/size/002.xml

4.1.5. The two identical renderings

It is often hard to make a test that is purely green when the test passes and visibly red when the test fails. For these cases, it may be easier to make a particular pattern using the feature that is being tested, and then have a reference rendering next to the test showing exactly what the test should look like. The reference rendering could be either an image, in the case where the rendering should be identical, to the pixel, on any machine, or the same pattern made using totally different parts of the CSS specification. (Doing the second has the advantage of making the test a test of both the feature under test and the features used to make the reference rendering.) Examples:
  

http://www.hixie.ch/tests/adhoc/css/box/block/003.html http://www.hixie.ch/tests/adhoc/css/box/table/003.html http://www.hixie.ch/tests/adhoc/css/box/ib/002.xml

4.1.6. The positioned text

There are some cases where the easiest test to write is one where the four letters of the word 'PASS' are individually positioned on the page. This type of test is then said to have passed when all that can be seen is the word with all its letters aligned. Should the test fail, the letters are likely to go out of alignment, for instance:
PA SS

...or:
SSPA

The problem with this test is that when there is a failure it is sometimes not immediately clear that the rendering is wrong. (e.g. the first example above could be thought to be intentional.) Example:


http://www.hixie.ch/tests/adhoc/css/box/block/text-indent/001.html

4.2. Indicating failure

Ideal tests, as well as having well defined characteristics when they pass, should have some clear signs when they fail. It can sometimes be hard to make a test do something only when the test fails, because it is very hard to predict how user agents will fail! Furthermore, in a rather ironic twist, the best tests are those that catch the most unpredictable failures!

Having said that, here are the best ways to indicate failures:
4.2.1. Red

This is probably the best way of highlighting bugs. Tests should be designed so that if the rendering is a few pixels off some red is uncovered. Examples:


http://www.hixie.ch/tests/adhoc/css/box/block/first-line/001.html

4.2.2. Overlapped text

Tests of the 'line-height', 'font-size' and similar properties can sometimes be devised in such a way that a failure will result in the text overlapping.
4.2.3. The word "FAIL"

Some properties lend themselves well to this kind of test, for example 'quotes' and 'content'. The idea is that if the word "FAIL" appears anywhere, something must have gone wrong. Examples:
 

http://www.hixie.ch/tests/adhoc/css/box/table/004.html http://www.hixie.ch/tests/adhoc/css/box/absolute/002.xml

4.2.4. Scrambled text

This is similar to using the word "FAIL", except that instead of (or in addition to) having the word "FAIL" appear when an error is made, the rest of the text in the test is generated using the property being tested. That way, if anything goes wrong, it is immediately obvious. Examples:


http://www.hixie.ch/tests/adhoc/css/quotes/001.xml

These are in addition to those inherent to the various test types, e.g., differences in the two halves of a two identical renderings test obviously also shows a bug.
4.3. Techniques

In addition to the techniques mentioned in the previous sections, there are some techniques that are important to consider or to underscore.

4.3.1. Overlapping

This technique should not be cast aside as a curiosity -- it is in fact one of the most useful techniques for testing CSS, especially for areas like positioning and the table model. The basic idea is that a red box is first placed using one set of properties, e.g. the block box model's margin, height and width properties, and then a second box, green, is placed on top of the red one using a different set of properties, e.g. using absolute positioning. This idea can be extended to any kind of overlapping, for example overlapping to lines of identical text of different colors.
4.3.2. Special fonts

Todd Fahrner has developed a font called Ahem, which consists of some very well defined glyphs of precise sizes and shapes. This font is especially useful for testing font and text properties. Without this font it would be very hard to use the overlapping technique with text. Examples:
 

http://www.hixie.ch/tests/adhoc/css/fonts/ahem/001.xml http://www.hixie.ch/tests/adhoc/css/fonts/ahem/002.xml

The font's em-square is exactly square. It's ascent and descent is exactly the size of the em square. This means that the font's extent is exactly the same as its line-height, meaning that it can be exactly aligned with padding, borders, margins, and so forth. The font's alphabetic baseline is 0.2em above its bottom, and 0.8em below its top. The font has four glyphs:
X U+0058 A square exactly 1em in height and width. p U+0070 A rectangle exactly 0.2em high, 1em wide, and aligned so that its top is flush with the baseline. A rectangle exactly 0.8em high, 1em wide, and aligned so that its bottom is flush with the baseline.

É U+00C9

U+0020 A transparent space exactly 1em high and wide.

Most other US-ASCII characters in the font have the same glyph as X.

4.3.3. The self explanatory sentence followed by pages of identical text

For tests that must be long (e.g. scrolling tests), it is important to make it clear that the filler text is not relevant, otherwise the tester may think he is missing something and therefore waste time reading the filler text. Good text for use in these situations is, quite simply, "This is filler text. This is filler text. This is filler text.". If it looks boring, it's working!
4.3.4. Color

In general, using colors in a consistent manner is recommend. Specifically, the following convention has been developed:
Red Any red indicates failure. Green In the absence of any red, green indicates success. Blue Tests that do not use red or green to indicate success or failure should use blue to indicate that the tester should read the text carefully to determine the pass conditions. Black Descriptive text is usually black. Fuchsia, Yellow, Teal, Orange These are useful colors when making complicated patterns for tests of the two identical renderings type. Gray Descriptive lines, such as borders around nested boxes, are usually dark gray. These lines come in useful when trying to reduce the test for engineers. Silver Light gray is sometimes used for filler text to indicate that it is irrelevant.

Here is an example of blue being used:


http://www.hixie.ch/tests/adhoc/css/fonts/size/004.xml

4.3.5. Methodical testing

There are particular parts of CSS that can be tested quite thoroughly with a very methodical approach. For example, testing that all the length units work for each property taking lengths is relatively easy, and can be done methodically simply by creating a test for each property/unit combination. In practice, the important thing to decide is when to be methodical and when to simply test, in an ad hoc fashion, a cross section of the possibilities. This example is a methodical test of the :not() pseudo-class with each attribute selector in turn, first for long values and then for short values:


http://www.hixie.ch/tests/adhoc/css/selectors/not/010.xml

4.4. Tests to avoid 4.4.1. The long test

Any manual test that is so long that is needs to be scrolled to be completed is too long. The reason for this becomes obvious when you consider how manual tests will be run. Typically, the tester will be running a program (such as "Loaderman") which cycles through a list of several hundred tests. Whenever a failure is detected, the tester will do something (such as hit a key) that takes a note of the test case name. Each test will be on the screen for about two or three seconds. If the tester has to scroll the page, that means he has to stop the test to do so. Of course, there are exceptions -- the most obvious one being any tests that examine the scrolling mechanism! However, these tests are considered tests of user interaction and are not run with the majority of the tests. In general, any test that is so long that it needs scrolling can be split into several smaller tests, so in practice this isn't much of a problem. This is an example of a test that is too long:


http://www.bath.ac.uk/~py8ieh/internet/eviltests/lineheight3.html

4.4.2. The counterintuitive "this should be red" test

As mentioned many times in this document, red indicates a bug, so nothing should ever be red in a test. There is one important exception to this rule... the test for the 'red' value for the color properties! The first subtest on this page shows this problem:



http://www.people.fas.harvard.edu/~dbaron/css/test/childsel

4.4.3. Unobvious tests

A test that has half a sentence of normal text with the second half bold if the test has passed is not very obvious, even if the sentence in question explains what should happen. There are various ways to avoid this kind of test, but no general rule can be given since the affected tests are so varied. The last subtest on this page shows this problem:


http://www.w3.org/Style/CSS/Test/current/sec525.htm

Acknowledgments
[acknowledgments]

References
Normative references Other references

Index Contributing Code
This page describes how to contribute changes to the WebKit source control repository. The WebKit project maintains several scripts to assist you. This page assumes you already know how to check out and build the code.
Overview

Below are the recommended steps. Later sections of this page explain each step in more detail.
1. Choose or create a bug report to work on. 2. Develop your changes. 3. Make sure your changes meet the code style guidelines. The check-webkit-style script may be of help. 4. Run the layout tests using the run-webkit-tests script and make sure they all pass. See the testing page for more information, as well as what you need to do if you've modified JavaScriptCore. 5. Add any new files to your working directory.

6. Prepare a change log entry. You may have to add entries to multiple ChangeLogs. The prepare-ChangeLog script will create stub entries for you. See the paragraph about ChangeLogs below. 7. Create the patch using the svn-create-patch script. 8. Submit your patch for review to bugs.webkit.org. 9. Make any changes recommended by the reviewer. 10. Once reviewed, ask someone to land your patch or mark it for automated commit. 11. Please watch for any regressions it may have caused (hopefully none)!

More detail about these steps is below.
Choose a bug report

The bugs.webkit.org database is the central point of communication for contributions to WebKit. Nearly every contribution corresponds to a bug report there. Note that WebKit uses bug reports to track all types of code changes and not just bug fixes. Choose a bug report to work on. You can also create a new report. Be sure to search the database before creating new reports to avoid duplication. After choosing a bug report, follow the WebKit bug life cycle guidelines for the report. For example, it is often good practice to comment in a report if you are working on that issue. If your change may be controversial, you may want to check in advance with the webkit-dev mailing list.
Develop your changes

If you make substantive changes to a file, you may wish to add a copyright line for yourself or for the company on whose behalf you work. Below are sample copyright lines for an individual contributor and a company:
Copyright (C) 2010 John Smith ([email protected]) Copyright (C) 2010 Company Inc. All rights reserved.

In addition, make sure that any new source code and script files you introduce contain license text at the beginning of the file. If you are the author of a new file, preferred license text to include can be found here: WebKit/LICENSE. (The "Original Format" link at the bottom of the page contains text that can be cut and pasted more easily.) Simply replace the copyright line with your own information, for example as suggested above.
Code Style Guidelines

Patches must comply with the code style guidelines. Some older parts of the codebase do not follow these guidelines. If you are modifying such code, it is generally best to clean it up to comply with the current guidelines. An exception is legacy components, which should not be cleaned up.

Regression tests

Once you have made your changes, you need to run the regression tests, which is done via the run-webkit-tests script. All tests must pass. Patches will not be landed in the tree if they break existing layout tests. For any feature that affects the layout engine, a new regression test must be constructed. If you provide a patch that fixes a bug, that patch should also include the addition of a regression test that would fail without the patch and succeed with the patch. If no regression test is provided, the reviewer will ask you to revise the patch, so you can save time by constructing the test up front and making sure it's attached to the bug. If no layout test can be (or needs to be) constructed for the fix, you must explain why a new test isn't necessary to the reviewer. Information on writing a layout test as well as what needs to be done if you've made changes to JavaScriptCore can be found on the testing page.
Add new files to your working directory

If your changes include adding new files (like new layout tests), use the svn add command to mark these files for addition to the repository. If you do not do this, the new files will be missing from the patch file you generate below. You can learn more about Subversion commands like svn add from the online book Version Control with Subversion and by using the svn help command.
ChangeLog files

ChangeLogs are simple text files which provide historical documentation for all changes to the WebKit project. All patches require an entry to the ChangeLog. The prepare-ChangeLog script will create a basic entry containing a list of all files that have been changed. The first line contains the date, your full name, and your email address. Use this to write up a brief summary of the changes you've made. Don't worry about the "Reviewed by NOBODY (OOPS!)" line, the person landing your patch will fill this in. There is one ChangeLog per top-level directory, if you changed code and tests you will need to edit at least two ChangeLogs. The prepare-ChangeLog script will create a stub entries for you. You should edit these stubs to describe your change, including the full url to the bug (example entry, note that you can use --bug flag). (You should set EMAIL_ADDRESS and CHANGE_LOG_NAME in your environment if you will be running this script frequently.) The "No new tests. (OOPS!)" line appears if prepare-ChangeLog did not detect the addition of test cases. If your patch does not require test cases (or test cases are not possible), you should include a line stating such. Otherwise all changes require test cases which should be mentioned in the ChangeLog.

Create the patch

WebKit uses svn-create-patch to create patches. The svn-create-patch script is a small wrapper around Subversion's diff command that better handles moved, added, and deleted files. This command is best run from the top level of your checkout to make sure no changes are left out of your patch. It is not necessary to break a patch into multiple files. The svn-create-patch script does not create a file automatically. You need to redirect the output yourself using something like: svn-create-patch > MyExcellentPatch.txt
Submit your patch

Submit your patch by clicking the "Add an attachment" link in the bug report you chose for your contribution.

Complete the attachment form by doing at least the following:
1. 2. 3. 4. 5. Browse to your patch file in the File field. Type a brief description in the Description field, for example "Proposed patch." Check the "patch" checkbox (see picture below). Select the question mark "?" in the "review" pull-down (see picture below). Click Submit at the bottom.

The patch checkbox and the review:? flag signal to WebKit reviewers that your patch is ready for review. Setting the review flag also sends an automatic e-mail to the webkit-reviews mailing list which some reviewers subscribe to.

Respond to reviewers

A WebKit reviewer must approve your patch before WebKit can accept it into the source control repository. A reviewer will typically either approve your patch (by responding with an r=me in the bug report and marking the patch review:+) or request revisions to your patch (and mark the patch review:-). In rare cases a patch may be permanently rejected, meaning that the reviewer believes the feature should never be committed to the tree. The review process can consist of multiple iterations between you and the reviewer as you submit revised patches.
Landing in the tree

Once a patch is approved, you should ask someone with commit access to land your patch. Alternatively you can request that your patch be committed by our commit bot.
Keeping the tree green

In either case, your responsibility for the patch does not end with the patch landing in the tree. There may be regressions from your change or additional feedback from reviewers after the patch has landed. You can watch the tree at build.webkit.org to make sure your patch builds and passes tests on all platforms. It is your responsibility to be available should regressions arise and to respond to additional feedback that happens after a check-in. Changes should succeed on all platforms, but it can be difficult to test on every platform WebKit supports. Be certain that your change does not introduce new test failures on the high-traffic Mac or Windows ports by comparing the list of failing tests before and after your change. Your change must at least compile on all platforms.
Optional: Use of the WebKit Commit Bot

WebKit provides an automated system (commit-queue) for landing patches for any who would like to use it. To use the commit-queue, set the commit-queue:? flag on your patch. A committer will set commit-queue:+ and an automated process will download, build, run the layout tests, and submit your patch on your behalf. If the WebKit buildbots are passing, your patch should be landed within 15 minutes after commit-queue:+ is set. See the commit-queue documentation for more information.

Obtaining Commit and Review Privileges
Our Committer and Reviewer policy provides details on obtaining commit and review privileges.

WebKit Scripts
The WebKit project maintains several scripts to assist with things like building and testing code, checking style, and preparing patches.

The Tools/Scripts folder of the WebKit source tree contains these scripts. In fact, unless otherwise mentioned, all of the scripts mentioned on this site are located in this folder.
Running a script

To run the build-webkit script, for example, type the following from the command line: WebKit/Tools/Scripts/build-webkit Similarly, to run the build-webkit script with the --help option, type the following: WebKit/Tools/Scripts/build-webkit --help
Adding to your path

It is convenient to add WebKit/Tools/Scripts to your shell path so you can run WebKit scripts without typing the full path. For example, this will allow you to type the following for the two examples above: build-webkit build-webkit --help The instructions throughout this site assume you have added WebKit/Tools/Scripts to your shell path. If you do not add this directory to your shell path, simply always include the full path as in the first examples above.

Getting WebKit
To download a pre-built bundle containing the latest WebKit, visit WebKit Nightly Builds.

Browsing the Code
To browse the source code online, visit WebKit Trac.

Checking Out
To work with the WebKit source tree, you will need a Subversion client installed. See Installing Developer Tools for information on how to install Subversion.
Mac OS X

1. Install a Subversion Client

Subversion (svn) is the source code management tool used by the WebKit Open Source Project. A Subversion 1.4 client for Mac OS X 10.4 is available. 2. Open Terminal Terminal resides in /Applications/Utilities. The Finder Go menu provides a quick way to navigate there.
Windows

1. Open a Cygwin Shell Double-click the Cygwin icon on your Desktop to launch a new shell. 1. Type this command to check out the WebKit source tree: svn checkout http://svn.webkit.org/repository/webkit/trunk WebKit Alternatively you can download a snapshot of the WebKit source tree from http://nightly.webkit.org/files/WebKit-SVN-source.tar.bz2. It is updated every six hours.
Windows

1. Install the WebKit Support Libraries Download the WebKit Support Libraries to the root of your source tree (C:\cygwin\home\<username>\WebKit). If the file is incorrectly named, rename it to WebKitSupportLibrary.zip. Do not extract its contents. 1. Run the update-webkit script to update your source tree. If you downloaded the tarball, this will bring it up to date. Windows users must always execute this command after first obtaining the code, since it will download additional libraries that are needed to build. Once you have a current tree, the next step is building WebKit.

Keeping up to Date
At any time, you can rerun the update-webkit script to update your source tree.

Building WebKit
Building WebKit requires that you have the proper developer tools installed and that you have a copy of the WebKit source tree. Windows

1. Open a Cygwin Shell (if not already open from checking out sources) Double-click the Cygwin icon on your Desktop to launch a new shell. 1. Run the build-webkit script to build WebKit. Use the --debug option for a debug build, which includes debugging symbols and assertions: build-webkit --debug By default, build-webkit places build products in WebKit/WebKitBuild. You can specify a different build location on Mac in your Xcode preferences. On Windows, the WEBKITOUTPUTDIR environment variable can be used to set a different build products location. If you have set up a custom build location, then build-webkit will place the build products there.
Windows

A common source of build errors on Windows is Visual C++ Express forgetting the Platform SDK paths. If you have trouble building WebKit, double check that the paths you set during step 2 of the Platform SDK Installation are still there and add them again if necessary. Don't forget that if you have any questions or problems building WebKit, feel free to get in touch! Once your build has finished, you can run it inside Safari.

Setting a Default Configuration
1. To set a default build configuration for build-webkit and other scripts, use the setwebkit-configuration script: set-webkit-configuration --debug set-webkit-configuration --release

Contributing Code
This page describes how to contribute changes to the WebKit source control repository. The WebKit project maintains several scripts to assist you. This page assumes you already know how to check out and build the code.
Overview

Below are the recommended steps. Later sections of this page explain each step in more detail.
1. Choose or create a bug report to work on. 2. Develop your changes. 3. Make sure your changes meet the code style guidelines. The check-webkit-style script may be of help. 4. Run the layout tests using the run-webkit-tests script and make sure they all pass. See the testing page for more information, as well as what you need to do if you've modified JavaScriptCore. 5. Add any new files to your working directory. 6. Prepare a change log entry. You may have to add entries to multiple ChangeLogs. The prepare-ChangeLog script will create stub entries for you. See the paragraph about ChangeLogs below. 7. Create the patch using the svn-create-patch script. 8. Submit your patch for review to bugs.webkit.org. 9. Make any changes recommended by the reviewer. 10. Once reviewed, ask someone to land your patch or mark it for automated commit. 11. Please watch for any regressions it may have caused (hopefully none)!

More detail about these steps is below.
Choose a bug report

The bugs.webkit.org database is the central point of communication for contributions to WebKit. Nearly every contribution corresponds to a bug report there. Note that WebKit uses bug reports to track all types of code changes and not just bug fixes. Choose a bug report to work on. You can also create a new report. Be sure to search the database before creating new reports to avoid duplication. After choosing a bug report, follow the WebKit bug life cycle guidelines for the report. For example, it is often good practice to comment in a report if you are working on that issue. If your change may be controversial, you may want to check in advance with the webkit-dev mailing list.

Develop your changes

If you make substantive changes to a file, you may wish to add a copyright line for yourself or for the company on whose behalf you work. Below are sample copyright lines for an individual contributor and a company:
Copyright (C) 2010 John Smith ([email protected]) Copyright (C) 2010 Company Inc. All rights reserved.

In addition, make sure that any new source code and script files you introduce contain license text at the beginning of the file. If you are the author of a new file, preferred license text to include can be found here: WebKit/LICENSE. (The "Original Format" link at the bottom of the page contains text that can be cut and pasted more easily.) Simply replace the copyright line with your own information, for example as suggested above.
Code Style Guidelines

Patches must comply with the code style guidelines. Some older parts of the codebase do not follow these guidelines. If you are modifying such code, it is generally best to clean it up to comply with the current guidelines. An exception is legacy components, which should not be cleaned up.
Regression tests

Once you have made your changes, you need to run the regression tests, which is done via the run-webkit-tests script. All tests must pass. Patches will not be landed in the tree if they break existing layout tests. For any feature that affects the layout engine, a new regression test must be constructed. If you provide a patch that fixes a bug, that patch should also include the addition of a regression test that would fail without the patch and succeed with the patch. If no regression test is provided, the reviewer will ask you to revise the patch, so you can save time by constructing the test up front and making sure it's attached to the bug. If no layout test can be (or needs to be) constructed for the fix, you must explain why a new test isn't necessary to the reviewer. Information on writing a layout test as well as what needs to be done if you've made changes to JavaScriptCore can be found on the testing page.
Add new files to your working directory

If your changes include adding new files (like new layout tests), use the svn add command to mark these files for addition to the repository. If you do not do this, the new files will be missing from the patch file you generate below.

You can learn more about Subversion commands like svn add from the online book Version Control with Subversion and by using the svn help command.
ChangeLog files

ChangeLogs are simple text files which provide historical documentation for all changes to the WebKit project. All patches require an entry to the ChangeLog. The prepare-ChangeLog script will create a basic entry containing a list of all files that have been changed. The first line contains the date, your full name, and your email address. Use this to write up a brief summary of the changes you've made. Don't worry about the "Reviewed by NOBODY (OOPS!)" line, the person landing your patch will fill this in. There is one ChangeLog per top-level directory, if you changed code and tests you will need to edit at least two ChangeLogs. The prepare-ChangeLog script will create a stub entries for you. You should edit these stubs to describe your change, including the full url to the bug (example entry, note that you can use --bug flag). (You should set EMAIL_ADDRESS and CHANGE_LOG_NAME in your environment if you will be running this script frequently.) The "No new tests. (OOPS!)" line appears if prepare-ChangeLog did not detect the addition of test cases. If your patch does not require test cases (or test cases are not possible), you should include a line stating such. Otherwise all changes require test cases which should be mentioned in the ChangeLog.
Create the patch

WebKit uses svn-create-patch to create patches. The svn-create-patch script is a small wrapper around Subversion's diff command that better handles moved, added, and deleted files. This command is best run from the top level of your checkout to make sure no changes are left out of your patch. It is not necessary to break a patch into multiple files. The svn-create-patch script does not create a file automatically. You need to redirect the output yourself using something like: svn-create-patch > MyExcellentPatch.txt
Submit your patch

Submit your patch by clicking the "Add an attachment" link in the bug report you chose for your contribution.

Complete the attachment form by doing at least the following:

1. 2. 3. 4. 5.

Browse to your patch file in the File field. Type a brief description in the Description field, for example "Proposed patch." Check the "patch" checkbox (see picture below). Select the question mark "?" in the "review" pull-down (see picture below). Click Submit at the bottom.

The patch checkbox and the review:? flag signal to WebKit reviewers that your patch is ready for review. Setting the review flag also sends an automatic e-mail to the webkit-reviews mailing list which some reviewers subscribe to.
Respond to reviewers

A WebKit reviewer must approve your patch before WebKit can accept it into the source control repository. A reviewer will typically either approve your patch (by responding with an r=me in the bug report and marking the patch review:+) or request revisions to your patch (and mark the patch review:-). In rare cases a patch may be permanently rejected, meaning that the reviewer believes the feature should never be committed to the tree. The review process can consist of multiple iterations between you and the reviewer as you submit revised patches.
Landing in the tree

Once a patch is approved, you should ask someone with commit access to land your patch. Alternatively you can request that your patch be committed by our commit bot.
Keeping the tree green

In either case, your responsibility for the patch does not end with the patch landing in the tree. There may be regressions from your change or additional feedback from reviewers after the patch has landed. You can watch the tree at build.webkit.org to make sure your patch builds and passes tests on all platforms. It is your responsibility to be available should regressions arise and to respond to additional feedback that happens after a check-in.

Changes should succeed on all platforms, but it can be difficult to test on every platform WebKit supports. Be certain that your change does not introduce new test failures on the high-traffic Mac or Windows ports by comparing the list of failing tests before and after your change. Your change must at least compile on all platforms.
Optional: Use of the WebKit Commit Bot

WebKit provides an automated system (commit-queue) for landing patches for any who would like to use it. To use the commit-queue, set the commit-queue:? flag on your patch. A committer will set commit-queue:+ and an automated process will download, build, run the layout tests, and submit your patch on your behalf. If the WebKit buildbots are passing, your patch should be landed within 15 minutes after commit-queue:+ is set. See the commit-queue documentation for more information.

Obtaining Commit and Review Privileges
Our Committer and Reviewer policy provides details on obtaining commit and review privileges.

WebKit Coding Style Guidelines
Indentation 1. Use spaces, not tabs. Tabs should only appear in files that require them for semantic meaning, like Makefiles. 2. The indent size is 4 spaces. Right:
int main() { return 0; }

Wrong:
int main() { return 0; }

3. The contents of an outermost namespace block (and any nested namespaces with the same scope) should not be indented. The contents of other nested namespaces should be indented. Right:
// Document.h namespace WebCore { class Document { Document(); ... };

namespace NestedNamespace { ... } } // namespace WebCore // Document.cpp namespace WebCore { Document::Document() { ... } } // namespace WebCore

Wrong:
// Document.h namespace WebCore { class Document { Document(); ... }; namespace NestedNamespace { ... } } // namespace WebCore // Document.cpp namespace WebCore { Document::Document() { ... } } // namespace WebCore

4. A case label should line up with its switch statement. The case statement is indented. Right:
switch (condition) { case fooCondition: case barCondition: i++; break; default: i--; }

Wrong:
switch (condition) { case fooCondition: case barCondition: i++; break; default: i--; }

5. Boolean expressions at the same nesting level that span multiple lines should have their operators on the left side of the line instead of the right side. Right:
if (attr->name() == srcAttr || attr->name() == lowsrcAttr || (attr->name() == usemapAttr && attr->value().domString()[0] != '#')) return;

Wrong:
if (attr->name() == srcAttr || attr->name() == lowsrcAttr || (attr->name() == usemapAttr && attr->value().domString()[0] != '#')) return;

Spacing 1. Do not place spaces around unary operators. Right:
i++;

Wrong:
i ++;

2. Do place spaces around binary and ternary operators. Right:
y = m * x + b; f(a, b); c = a | b; return condition ? 1 : 0;

Wrong:
y=m*x+b; f(a,b); c = a|b; return condition ? 1:0;

3. Do not place spaces before comma and semicolon.

Right:
for (int i = 0; i < 10; i++) doSomething(); f(a, b);

Wrong:
for (int i = 0 ; i < 10 ; i++) doSomething(); f(a , b) ;

4. Place spaces between control statements and their parentheses. Right:
if (condition) doIt();

Wrong:
if(condition) doIt();

5. Do not place spaces between a function and its parentheses, or between a parenthesis and its content. Right:
f(a, b);

Wrong:
f (a, b); f( a, b );

Line breaking 1. Each statement should get its own line. Right:
x++; y++; if (condition) doIt();

Wrong:
x++; y++; if (condition) doIt();

2. An else statement should go on the same line as a preceding close brace if one is present, else it should line up with the if statement. Right:
if (condition) {

... } else { ... } if (condition) doSomething(); else doSomethingElse(); if (condition) doSomething(); else { ... }

Wrong:
if (condition) { ... } else { ... } if (condition) doSomething(); else doSomethingElse(); if (condition) doSomething(); else { ... }

3. An else if statement should be written as an if statement when the prior if concludes with a return statement. Right:
if (condition) { ... return someValue; } if (condition) { ... }

Wrong:
if (condition) { ... return someValue; } else if (condition) { ... }

Braces 1. Function definitions: place each brace on its own line.

Right:
int main() { ... }

Wrong:
int main() { ... }

2. Other braces: place the open brace on the line preceding the code block; place the close brace on its own line. Right:
class MyClass { ... }; namespace WebCore { ... } for (int i = 0; i < 10; i++) { ... }

Wrong:
class MyClass { ... };

3. One-line control clauses should not use braces unless comments are included or a single statement spans multiple lines. Right:
if (condition) doIt(); if (condition) { // Some comment doIt(); } if (condition) { myFunction(reallyLongParam1, reallyLongParam2, ... reallyLongParam5); }

Wrong:
if (condition) { doIt(); }

if (condition) // Some comment doIt(); if (condition) myFunction(reallyLongParam1, reallyLongParam2, ... reallyLongParam5);

4. Control clauses without a body should use empty braces: Right:
for ( ; current; current = current->next) { }

Wrong:
for ( ; current; current = current->next);

Null, false and 0 1. In C++, the null pointer value should be written as 0. In C, it should be written as NULL. In Objective-C and Objective-C++, follow the guideline for C or C++, respectively, but use nil to represent a null Objective-C object. 2. C++ and C bool values should be written as true and false. Objective-C BOOL values should be written as YES and NO. 3. Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons. Right:
if (condition) doIt(); if (!ptr) return; if (!count) return;

Wrong:
if (condition == true) doIt(); if (ptr == NULL) return; if (count == 0) return;

4. In Objective-C, instance variables are initialized to zero automatically. Don't add explicit initializations to nil or NO in an init method.

Floating point literals 1. Unless required in order to force floating point math, do not append .0, .f and .0f to floating point literals. Right:
const double duration = 60; void setDiameter(float diameter) { radius = diameter / 2; } setDiameter(10); const int framesPerSecond = 12; double frameDuration = 1.0 / framesPerSecond;

Wrong:
const double duration = 60.0; void setDiameter(float diameter) { radius = diameter / 2.f; } setDiameter(10.f); const int framesPerSecond = 12; double frameDuration = 1 / framesPerSecond; // integer division

Names 1. Use CamelCase. Capitalize the first letter, including all letters in an acronym, in a class, struct, protocol, or namespace name. Lower-case the first letter, including all letters in an acronym, in a variable or function name. Right:
struct Data; size_t bufferSize; class HTMLDocument; String mimeType();

Wrong:
struct data; size_t buffer_size; class HtmlDocument; String MIMEType();

2. Use full words, except in the rare case where an abbreviation would be more canonical and easier to understand.

Right:
size_t characterSize; size_t length; short tabIndex; // more canonical

Wrong:
size_t charSize; size_t len; short tabulationIndex; // bizarre

3. Data members in C++ classes should be private. Static data members should be prefixed by "s_". Other data members should be prefixed by "m_". Right:
class String { public: ... private: short m_length; };

Wrong:
class String { public: ... short length; };

4. Prefix Objective-C instance variables with "_". Right:
@class String ... short _length; @end

Wrong:
@class String ... short length; @end

5. Precede boolean values with words like "is" and "did". Right:
bool isValid; bool didSendData;

Wrong:
bool valid; bool sentData;

6. Precede setters with the word "set". Use bare words for getters. Setter and getter names should match the names of the variables being set/gotten. Right:
void setCount(size_t); // sets m_count size_t count(); // returns m_count

Wrong:
void setCount(size_t); // sets m_theCount size_t getCount();

7. Use descriptive verbs in function names. Right:
bool convertToASCII(short*, size_t);

Wrong:
bool toASCII(short*, size_t);

8. Leave meaningless variable names out of function declarations. A good rule of thumb is if the parameter type name contains the parameter name (without trailing numbers or pluralization), then the parameter name isn't needed. Usually, there should be a parameter name for bools, strings, and numerical types. Right:
void setCount(size_t); void doSomething(ScriptExecutionContext*);

Wrong:
void setCount(size_t count); void doSomething(ScriptExecutionContext* context);

9. Objective-C method names should follow the Cocoa naming guidelines — they should read like a phrase and each piece of the selector should start with a lowercase letter and use intercaps. 10. Enum members should user InterCaps with an initial capital letter. 11. Prefer const to #define. Prefer inline functions to macros. 12. #defined constants should use all uppercase names with words separated by underscores. 13. Macros that expand to function calls or other non-constant computation: these should be named like functions, and should have parentheses at the end, even if they take no arguments (with the exception of some special macros like ASSERT). Note that usually it is preferable to use an inline function in such cases instead of a macro. Right:
#define WBStopButtonTitle() \ NSLocalizedString(@"Stop", @"Stop button title")

Wrong:
#define WB_STOP_BUTTON_TITLE \

NSLocalizedString(@"Stop", @"Stop button title") #define WBStopButtontitle \ NSLocalizedString(@"Stop", @"Stop button title")

14. #define, #ifdef "header guards" should be named exactly the same as the file (including case), replacing the '.' with a '_'. Right:
// HTMLDocument.h #ifndef HTMLDocument_h #define HTMLDocument_h

Wrong:
// HTMLDocument.h #ifndef _HTML_DOCUMENT_H_ #define _HTML_DOCUMENT_H_

Other Punctuation 1. Constructors for C++ classes should initialize all of their members using C++ initializer syntax. Each member (and superclass) should be indented on a separate line, with the colon or comma preceding the member on that line. Right:
MyClass::MyClass(Document* doc) : MySuperClass() , m_myMember(0) , m_doc(doc) { } MyOtherClass::MyOtherClass() : MySuperClass() { }

Wrong:
MyClass::MyClass(Document* doc) : MySuperClass() { m_myMember = 0; m_doc = doc; } MyOtherClass::MyOtherClass() : MySuperClass() {}

2. Pointer types in non-C++ code — Pointer types should be written with a space between the type and the * (so the * is adjacent to the following identifier if any). 3. Pointer and reference types in C++ code — Both pointer types and reference types should be written with no space between the type name and the * or &.

Right:
Image* SVGStyledElement::doSomething(PaintInfo& paintInfo) { SVGStyledElement* element = static_cast<SVGStyledElement*>(node()); const KCDashArray& dashes = dashArray();

Wrong:
Image *SVGStyledElement::doSomething(PaintInfo &paintInfo) { SVGStyledElement *element = static_cast<SVGStyledElement *>(node()); const KCDashArray &dashes = dashArray();

#include Statements 1. All implementation files must #include "config.h" first. Header files should never include "config.h". Right:
// RenderLayer.h #include "Node.h" #include "RenderObject.h" #include "RenderView.h"

Wrong:
// RenderLayer.h #include "config.h" #include "RenderObject.h" #include "RenderView.h" #include "Node.h"

2. All implementation files must #include the primary header second, just after "config.h". So for example, Node.cpp should include Node.h first, before other files. This guarantees that each header's completeness is tested. This also assures that each header can be compiled without requiring any other header files be included first. 3. Other #include statements should be in sorted order (case sensitive, as done by the commandline sort tool or the Xcode sort selection command). Don't bother to organize them in a logical order. Right:
// HTMLDivElement.cpp #include "config.h" #include "HTMLDivElement.h" #include "Attribute.h" #include "HTMLElement.h" #include "QualifiedName.h"

Wrong:
// HTMLDivElement.cpp

#include #include #include #include

"HTMLElement.h" "HTMLDivElement.h" "QualifiedName.h" "Attribute.h"

4. Includes of system headers must come after includes of other headers. Right:
// ConnectionQt.cpp #include "ArgumentEncoder.h" #include "ProcessLauncher.h" #include "WebPageProxyMessageKinds.h" #include "WorkItem.h" #include <QApplication> #include <QLocalServer> #include <QLocalSocket>

Wrong:
// ConnectionQt.cpp #include "ArgumentEncoder.h" #include "ProcessLauncher.h" #include <QApplication> #include <QLocalServer> #include <QLocalSocket> #include "WebPageProxyMessageKinds.h" #include "WorkItem.h"

"using" Statements 1. In header files, do not use "using" statements in namespace (or global) scope. Right:
// wtf/Vector.h namespace WTF { class VectorBuffer { using std::min; ... }; } // namespace WTF

Wrong:
// wtf/Vector.h namespace WTF { using std::min; class VectorBuffer { ... };

} // namespace WTF

2. In header files in the WTF sub-library, however, it is acceptable to use "using" declarations at the end of the file to import one or more names in the WTF namespace into the global scope. Right:
// wtf/Vector.h namespace WTF { } // namespace WTF using WTF::Vector;

Wrong:
// wtf/Vector.h namespace WTF { } // namespace WTF using namespace WTF;

Wrong:
// runtime/UString.h namespace WTF { } // namespace WTF using WTF::PlacementNewAdopt;

3. In C++ implementation files, do not use statements of the form "using std::foo" to import names in the standard template library. Use "using namespace std" instead. Right:
// HTMLBaseElement.cpp using namespace std; namespace WebCore { } // namespace WebCore

Wrong:
// HTMLBaseElement.cpp using std::swap; namespace WebCore { } // namespace WebCore

4. In implementation files, if a "using namespace" statement is for a nested namespace whose parent namespace is defined in the file, put the statement inside that namespace definition. Right:
// HTMLBaseElement.cpp namespace WebCore { using namespace HTMLNames; } // namespace WebCore

Wrong:
// HTMLBaseElement.cpp using namespace WebCore::HTMLNames; namespace WebCore { } // namespace WebCore

5. In implementation files, put all other "using" statements at the beginning of the file, before any namespace definitions and after any "include" statements. Right:
// HTMLSelectElement.cpp using namespace std; namespace WebCore { } // namespace WebCore

Wrong:
// HTMLSelectElement.cpp namespace WebCore { using namespace std; } // namespace WebCore

Classes 1. Use a constructor to do an implicit conversion when the argument is reasonably thought of as a type conversion and the type conversion is fast. Otherwise, use the explicit keyword or a function returning the type. This only applies to single argument constructors. Right:
class LargeInt { public: LargeInt(int); ...

class Vector { public: explicit Vector(int size); // Not a type conversion. PassOwnPtr<Vector> create(Array); // Costly conversion. ...

Wrong:
class Task { public: Task(ScriptExecutionContext*); // Not a type conversion. explicit Task(); // No arguments. explicit Task(ScriptExecutionContext*, Other); // More than one argument. ...

Comments 1. Use only one space before end of line comments and in between sentences in comments. Right:
f(a, b); // This explains why the function call was done. This is another sentence.

Wrong:
int i; // This is a comment with several spaces before it, which is a non-conforming style. double f; // This is another comment. There are two spaces before this sentence which is a non-conforming style.

2. Make comments look like sentences by starting with a capital letter and ending with a period (punctation). One exception may be end of line comments like this "if (x == y) // false for NaN". 3. Use FIXME: (without attribution) to denote items that need to be addressed in the future. Right:
drawJpg(); // FIXME: Make this code handle jpg in addition to the png support.

Wrong:
drawJpg(); // FIXME(joe): Make this code handle jpg in addition to the png support. drawJpg(); // TODO: Make this code handle jpg in addition to the png support.

WebKit Bugzilla
A Bug's Life Cycle
   

Home | New | Search |

Find

   

| Reports | Requests | New Account | Log In

The status and resolution fields define and track the life cycle of a bug.

STATUS
The status field indicates the general health of a bug. Only certain status transitions are allowed. UNCONFIRMED This bug has recently been added to the database. Nobody has validated that this bug is true. Users who have the "canconfirm" permission set may confirm this bug, changing its state to NEW. Or, it may be directly resolved and marked RESOLVED. NEW This bug has recently been added to the assignee's list of bugs and must be processed. Bugs in this state may be accepted, and become ASSIGNED, passed on to someone else, and remain NEW, or resolved and marked RESOLVED. ASSIGNED This bug is not yet resolved, but is assigned to the proper person. From here bugs can be given to another person and become NEW, or resolved and become RESOLVED. REOPENED This bug was once resolved, but the

RESOLUTION
The resolution field indicates what happened to this bug. No resolution yet. All bugs which are in one of these "open" states have the resolution set to blank. All other bugs will be marked with one of the following resolutions.

resolution was deemed incorrect. For example, a WORKSFORME bug is REOPENED when more information shows up and the bug is now reproducible. From here bugs are either marked ASSIGNED or RESOLVED. RESOLVED A resolution has been taken, and it is awaiting verification by QA. From here bugs are either re-opened and become REOPENED, are marked VERIFIED, or are closed for good and marked CLOSED. VERIFIED QA has looked at the bug and the resolution and agrees that the appropriate resolution has been taken. Bugs remain in this state until the product they were reported against actually ships, at which point they become CLOSED. CLOSED The bug is considered dead, the resolution is correct. Any zombie bugs who choose to walk the earth again must do so by becoming REOPENED. FIXED A fix for this bug is checked into the tree and tested. INVALID The problem described is not a bug. WONTFIX The problem described is a bug which will never be fixed. DUPLICATE The problem is a duplicate of an existing bug. Marking a bug duplicate requires the bug# of the duplicating bug and will at least put that bug number in the description field. WORKSFORME All attempts at reproducing this bug were futile, and reading the code produces no clues as to why the described behavior would occur. If more information appears later, the bug can be reopened. MOVED The problem was specific to a related product whose bugs are tracked in another bug database. The bug has been moved to that database.

Importance
The importance of a bug is described as the combination of its priority and severity, as described below.

Priority
This field describes the importance and order in which a bug should be fixed. This field is utilized by the programmers/engineers to prioritize their work to be done. The available priorities range from P1 (most important) to P5 (least important).

Severity
This field describes the impact of a bug. Blocker Critical Major Normal Minor Trivial Blocks development and/or testing work crashes, loss of data, severe memory leak major loss of function regular issue, some loss of functionality under specific circumstances minor loss of function, or other problem where easy workaround is present cosmetic problem like misspelled words or misaligned text

Enhancement Request for enhancement

Platform
This is the hardware platform against which the bug was reported. Legal platforms include:
  

All (happens on all platforms; cross-platform bug) Macintosh PC

Note: When searching, selecting the option "All" does not select bugs assigned against any platform. It merely selects bugs that are marked as occurring on all platforms, i.e. are designated "All".

Operating System
This is the operating system against which the bug was reported. Legal operating systems include:
   

All (happens on all operating systems; cross-platformbug) Windows Mac OS Linux

Sometimes the operating system implies the platform, but not always. For example, Linux can run on PC and Macintosh and others.

Assigned To
This is the person in charge of resolving the bug. Every time this field changes, the status changes to NEW to make it easy to see which new bugs have appeared on a person's list. The default status for queries is set to NEW, ASSIGNED and REOPENED. When searching for bugs that have been resolved or verified, remember to set the status field appropriately.


Actions: o Home o | New o | Search o |
Find

o o o o

| Reports | Requests | New Account | Log In

Installing the Developer Tools
Mac OS X

1. Install the Xcode Tools package Install the Xcode Tools package from http://connect.apple.com. Xcode 2.3 or later is required to build. 2. Install a Subversion Client (Tiger only) Subversion (svn) is the source code management tool used by the WebKit Open Source Project. A Subversion client for Mac OS X 10.4 and later is available. Leopard (10.5) and later already include a subversion client. 3. Install Python 2.5 or later (Tiger only) Python is a scripting language used by the WebKit Open Source Project. WebKit scripts require Python 2.5 or later to run. Tiger includes Python 2.3 which is too old to support WebKit's Python scripts.

4. Install Java for Mac OS X Developer Package Download and install the latest OS-appropriate "Java for Mac OS X Developer Package" from http://connect.apple.com/ (located under Downloads > Java).
Windows

1. If you own Visual Studio 2005 (newer versions of Visual Studio are currently unsupported): Install Microsoft Visual Studio 2005 Team Suite Service Pack 1. If you are building from Vista, install Service Pack 1 Update for Windows Vista. Install Visual Studio 2005 Service Pack 1 ATL Security Update. Install the following hotfixes to improve Visual Studio's performance and responsiveness:
1. 2. 3. 4. KB918559 KB935225 KB943969 KB947315

Use the default options for these installations. 2. If not, you can use Visual C++ Express 2005 (newer versions of Visual C++ Express Edition are currently unsupported): Install Visual C++ 2005 Express. Install Microsoft Visual C++ Express 2005 Service Pack 1. If you are building from Vista, install Service Pack 1 Update for Windows Vista. Install Visual Studio 2005 Service Pack 1 ATL Security Update. Install the Windows Server 2003 R2 Platform SDK, then follow steps 2 and 3 of “How to: Use Visual C++ Express Edition with the Microsoft Platform SDK.” Use the default options for all installations. In addition to the paths specified in step 3 of the Platform SDK installation instructions, you must also add the following include path. Update the Visual C++ directories in the Projects and Solutions section in the Options dialog box:
C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include\mfc

3. Install Cygwin Cygwin is a collection of utilities for Windows that includes not only a Subversion client, but also additional tools that are required to build the WebKit source. We have made a downloader available that automatically collects all of the required packages. Download cygwin-downloader.zip. Right-click cygwin-downloader.zip and choose Extract All.... Keep all the default options and click Next until the file is extracted and the cygwin-downloader folder opens. Double-click cygwin-downloader.exe. This will download all the Cygwin packages you need. When all the packages have finished downloading, the Cygwin installer will launch. Choose Install from Local Directory, then click Next until the install is complete. If you are running Vista, the installer won't be able to launch automatically, so you will have to manually launch Cygwin's Setup.exe. Vista may warn you that Cygwin did not install correctly. Ignore this warning and tell Vista that the install was successful. If you are running Vista, click on the Start menu, enter the following command, and press Enter: C:\cygwin\bin\ash -c /bin/rebaseall Remove the following lines from /home/[username]/.bashrc:
unset TMP unset TEMP Those lines would prevent picking up the Windows TMP and TEMP environment variables.

4. Install QuickTime SDK Download QuickTime SDK for Windows from http://developer.apple.com/quicktime/download/ and install it to the default location (\Program Files\QuickTime SDK). This is needed for media support. 5. Install DirectX SDK Download the February 2010 DirectX SDK (newer versions do not support Visual Studio 2005). This is needed for accelerated compositing.

6. Optional: Install the 32-bit version of Debugging Tools for Windows Debugging Tools for Windows includes many useful debugging tools such as WinDbg and NTSD. Some of WebKit’s tests and scripts use these tools. Follow the instructions for installing the 32-bit version of Debugging Tools for Windows. 7. Optional: Hotfix for 64-bit Windows to disable the user-mode callback filter for exceptions Without the 976038 hotfix, exceptions may be thrown in callback routines that do not cause a crash but leave the application in an inconsistent state that might cause a crash later. You will need to click on "View and request hotfix downloads" and fill out the form. A link to download the hotfix and a password will be emailed to you.
GTK Follow the instructions on the BuildingGTK wiki page. QT Follow the instructions on the QtWebKit wiki page.

Once you have installed your developer tools, the next step is getting the code.

Getting WebKit
To download a pre-built bundle containing the latest WebKit, visit WebKit Nightly Builds.

Browsing the Code
To browse the source code online, visit WebKit Trac.

Checking Out
To work with the WebKit source tree, you will need a Subversion client installed. See Installing Developer Tools for information on how to install Subversion.
Mac OS X

1. Install a Subversion Client Subversion (svn) is the source code management tool used by the WebKit Open Source Project. A Subversion 1.4 client for Mac OS X 10.4 is available. 2. Open Terminal

Terminal resides in /Applications/Utilities. The Finder Go menu provides a quick way to navigate there.
Windows

1. Open a Cygwin Shell Double-click the Cygwin icon on your Desktop to launch a new shell. 1. Type this command to check out the WebKit source tree: svn checkout http://svn.webkit.org/repository/webkit/trunk WebKit Alternatively you can download a snapshot of the WebKit source tree from http://nightly.webkit.org/files/WebKit-SVN-source.tar.bz2. It is updated every six hours.
Windows

1. Install the WebKit Support Libraries Download the WebKit Support Libraries to the root of your source tree (C:\cygwin\home\<username>\WebKit). If the file is incorrectly named, rename it to WebKitSupportLibrary.zip. Do not extract its contents. 1. Run the update-webkit script to update your source tree. If you downloaded the tarball, this will bring it up to date. Windows users must always execute this command after first obtaining the code, since it will download additional libraries that are needed to build. Once you have a current tree, the next step is building WebKit.

Keeping up to Date
At any time, you can rerun the update-webkit script to update your source tree.

Building WebKit
Building WebKit requires that you have the proper developer tools installed and that you have a copy of the WebKit source tree. Windows

1. Open a Cygwin Shell (if not already open from checking out sources)

Double-click the Cygwin icon on your Desktop to launch a new shell. 1. Run the build-webkit script to build WebKit. Use the --debug option for a debug build, which includes debugging symbols and assertions: build-webkit --debug By default, build-webkit places build products in WebKit/WebKitBuild. You can specify a different build location on Mac in your Xcode preferences. On Windows, the WEBKITOUTPUTDIR environment variable can be used to set a different build products location. If you have set up a custom build location, then build-webkit will place the build products there.
Windows

A common source of build errors on Windows is Visual C++ Express forgetting the Platform SDK paths. If you have trouble building WebKit, double check that the paths you set during step 2 of the Platform SDK Installation are still there and add them again if necessary. Don't forget that if you have any questions or problems building WebKit, feel free to get in touch! Once your build has finished, you can run it inside Safari.

Setting a Default Configuration
1. To set a default build configuration for build-webkit and other scripts, use the setwebkit-configuration script: set-webkit-configuration --debug set-webkit-configuration --release

Regression Testing
The WebKit Tests

Before patches can land in any of the frameworks in the repository, the layout regression tests must pass. To run these tests, execute the run-webkit-tests script. The script will dump the render trees for all of the pages and diff the results against the expected correct results. If no differences are found, then the patch has passed the tests. If any tests fail, then the patch cannot be committed until the discrepancies in the tests are resolved.

Regression tests must be run on Leopard, since the expected results checked in were generated on Leopard.
The JavaScriptCore Tests

If you are making changes to JavaScriptCore, there is an additional test suite you must run before landing changes. This is the Mozilla JavaScript test suite.
What's covered by the JavaScript tests?

The JavaScript tests cover the functionality of the core JavaScript engine. This includes the following JavaScript objects:
   

Arrays Booleans Dates Functions

   

Global Object Math Numbers Objects

 

Regular Expressions Strings

In addition, the JavaScript tests cover parsing, lexical conventions, expressions, statements, type conversion, and exception handling. How to run the tests

Execute the run-javascriptcore-tests script. The script will run all the tests and summarize how the results differ from what is currently expected.
What just happened

After all the test runs have finished the results of tests are saved to actual.html. The script the compares these results from your local tree against what is expected to pass/fail from the tip of tree. If there are any regressions caused by your changes you'll be made aware of them. If you fixed a bug that caused an existing failure, you'll also be made aware of what specific test your fix affected.
What to do next

So you fixed a bug that fixed a test. This means you've now set a new baseline for the tree as a result. cp actual.html expected.html When you land your changes, the baseline (expected.html) will be updated in the tree.

What happens if I caused a regression?

It's not the end of the world. Go back and fix your bug and rerun run-javascriptcore-tests as many times as necessary.

Leak Hunting
Finding Leaks

Memory leaks are one of our main areas of interest. Since the average user will only notice them by growing memory usage, we don't see as many bug reports on them as we'd like. This is some information about how to hunt down those leaks. The Mac OS X Developer Tools include a very useful program for leak detection. Here's how you can use it:
1. Get a fresh WebKit build, ideally a Debug build as this turns off the various custom allocators in WebKit. 2. Set the MallocStackLogging environment variable to YES (in bash, export MallocStackLogging=YES, in tcsh, setenv MallocStackLogging YES). 3. Run Safari using run-safari. 4. Browse around a little. 5. From the command line, run leaks Safari.

At this point, if you've found memory leaks, the leaks program will tell you how many, and give stack traces for each. You can file a report, along with a description of what steps you took to get the leak, at Bugzilla. Put “LEAK:” at the start of the title so that it's easy to find. If you want to write an even better bug report, see if you can reproduce the leak by following some specific set of steps, and include them in the bug. You can also look at the backtraces in the leak report and see if you can eliminate duplicates. It’s useful to file a separate bug report for each unique leak, and to consolidate duplicate leaks on different sites. Also, check out our general document about filing bugs.
Leaks in Standard Tests

We have two ways to automatically record stack traces for leaks encountered in our standard webkit tests. This is extremely useful since the webkit tests cover many unusual cases that one might not run into during a short browsing session. As we continue to add webkit tests this will continue to test for leaks in more and more corners of the code.
1. (Fast) To get a single leaks report covering all webkit tests, use run-webkit-tests --leaks. You can also pass a specific directory or a specific test to get a leaks report covering just part of the test hierarchy. For example run-webkit-tests --leaks dom/html/level1. 2. (Slow) To get a separate leaks report for each test, use run-webkit-tests --leaks --singly. Again, you can pass a specific directory to run this on only part of the test hierarchy. This option is much slower, but can be very helpful in pinning down a leak.

Fixing Leaks

Fixing memory leaks is a bit of a black art. The leak checker will tell you where the leaked memory was allocated, but not why it was never freed. Sometimes it will be obvious from code inspection that there is no free call to match a particular allocation. Other times, things get trickier - especially when refcounting is involved. In that case, you know that some code has taken a ref without releasing it, but it can be very hard to tell what code. Here’s a trick often found useful for these situations. Fire up the application in gdb. Set breakpoints on the appropriate ref and deref methods. Then, use the gdb “commands” feature to set commands of “bt 10; cont” for these breakpoints. You’ll get a 10-frame backtrace for every ref and deref, and that’s often enough to find the one that doesn’t pair up.
Destroy All Leaks

If you want to help with finding and fixing leaks, and you need more advice, contact us. Happy hunting.

Writing New Tests
A layout test is simply a web page. The layout test machinery renders the web page, and then dumps the internal representation, the render tree, with details of the layout. This lets engineers working on the project know if they do anything that changes the layout. Once we get a test rendering properly, we check it in as part of the layout test suite. The following are some guidelines to follow when writing new layout tests:
1. 2. 3. 4. The test should be the smallest possible code fragment that tests the feature. The test should fit on one page (unless of course it’s testing scrolling). The test should clearly describe what feature it is testing. The test should clearly describe the expected result. It should be possible through visual inspection alone to determine that the test has failed.

An example of a layout test that follows these guidelines is fast/events/eventcreation.html. A layout test should work both in the browser itself, and in the layout test tool. The layout test tool provides an additional object on the window object called the layout test controller with some methods that control test output. One you should know about is the layoutTestController.dumpAsText method. Calling this from JavaScript within a test arranges for the output to be written out as plain text rather than as a render tree dump. This is useful for tests that are testing something other than layout. The event creation test mentioned above is a good example of how to do this and when it makes sense. Some tests require pixel-level comparisons. For these tests, you must generate expected output for a specific machine type, operating system, and color profile. When you add such a test, you

can generate new expected output automatically using the run-webkit-tests --pixel command. This will automatically configure the color profile, and place the resulting rendered image (and checksum) in the appropriate platform directory for checkin. The Ahem font is useful in testing text layout, since its glyphs’ metrics are well known, and it is always available to tests running in the layout test tool. However, if you want to view tests that use Ahem in Safari, you should download Ahem, open it in the Font Book application, and click on the Install Font button to install it. The CSS working group has an excellent document on test writing guidelines for CSS tests. This wiki article has more information on writing good tests and the DumpRenderTree tool.

Getting a Useful Crash Log
Crash logs are incredibly useful when trying to track down a bug, especially if it's not immediately reproducible.
Mac OS X

Obtaining a crash log on Mac OS X is incredibly easy since it automatically creates easily accessible crash logs for you. 1. If WebKit has just crashed or you can easily reproduce the crash, press the Report button on the CrashReporter dialog box to view the crash information.

2. Copy and paste the entire contents of the top portion of the CrashReporter window into your favorite text editor and upload it as an attachment in Bugzilla.

3. If the crash report dialog does not appear or the crash is hard to reproduce, crash logs can be retrieved from the ~/Library/Logs/CrashReporter folder. On Leopard (Mac OS X 10.5), crash logs are stored as individually dated and time stamped files. Despite having a “.crash” extension, they are plain text files and can be attached directly to a bug report. On Tiger (Mac OS X 10.4), all crashes are logged to Safari.crash.log. This is a plain text file and can be viewed in the default Console.app or your favorite text editor. All of Safari's crashes are logged to this file so please only attach the last crash in it. Crashes are separated by a series of asterisks (∗∗∗∗∗∗∗∗∗∗) for easy identification.
Windows XP

Windows XP does not automatically log crashes like OS X, but it does include Dr. Watson, an easy to set up tool that can be configured to log them. 1. In the Start menu's Run box or from a DOS or Cygwin prompt, enter the command drwtsn32 -i.

2. A dialog box will appear informing you that Dr. Watson has been installed as the default debugger. Press OK.

3. Crash information will now be logged to the user.dmp file in C:\Documents and Settings\All Users\Application Data\Microsoft\Dr Watson\. Dr. Watson will create a user.dmp file that records what WebKit was doing when it crashed. Be careful as it is overwritten with every crash. When reporting a WebKit bug, please upload the user.dmp file if possible. 4. Running drwtsn32 without any options or switches will bring up a window that allows you to change various setting such as moving the log folder to a more easily accessible location or throwing a visual alert letting you know it caught the crash.

Windows Vista

Windows Vista does not include Dr. Watson. Instead, Windows Error Reporting (WER) has been integrated into the operating system. By default, Vista uploads the crash logs to Microsoft, but does not save a local copy. This is configurable via the registry. 1. Save the following text to a file named wer.reg:
2. Windows Registry Editor Version 5.00 3. 4. [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting] 5. "ForceQueue"=dword:00000001

6. Double-click the file from Windows Explorer and respond affirmatively to any prompts. 7. Reboot

The next time Safari (or any other application) crashes, the crash information will be written into a folder located inside %LOCALAPPDATA%\Microsoft\Windows\WER\ReportQueue. Check the modification date to make sure you are using the correct file. Be sure to include the following files in your bug report:
WERxxxx.tmp.mdmp

This is the most important file. It contains the crash dump that can be opened inside Visual Studio or other Windows debuggers.
WERxxxx.tmp.version.txt

Contains the operating system version and other hardware information.
WERxxxx.tmp.appcompat.txt

Lists all of the DLLs loaded at the time of the crash with their version information.

WebKit Projects
There are many exciting projects that we are actively working on in the WebKit source tree. To find out more about each project you can visit that project's home page. If you are interested in starting a new project in the WebKit tree, contact us!
General Projects Web Site Compatibility The most important project that we are working on (and the one that receives the most attention) is web site compatibility. Our top priority is ensuring that WebKit works with as many web sites as possible. This is a cross-functional project that touches many areas of the code. Performance Our second highest priority after compatibility is performance. Find out about our performance measurement tools and policies here. Code Cleanup We have a number of tasks in mind for code cleanup. In addition to reformatting existing code to match our coding style guidelines, we also have plenty of work to do moving WebKit code into WebCore now that both frameworks are open source. Portability Making the WebKit code more portable to other platforms is also a priority. We would like to begin integration of ports to other platforms, such as the GTK+ port of WebCore. Find out about our plans here.

Documentation Want to add documents to the WebKit web site? We're interested in architecture documents, support charts and any other documents you think will help people trying to use WebKit. Specific Projects CSS (Cascading Style Sheets) Cascading Style Sheets (CSS) is a simple mechanism for adding style to Web documents. It is a W3C standard. DOM (Document Object Model) The Document Object Model is a platform and language neutral interface that allows code to dynamically access and update the content, structure and style of documents. It is a W3C standard. HTML/XHTML (HyperText Markup Language) The HTML project is concerned with the implementation of the HTML and XHTML specifications from the W3C. In addition to the W3C work on HTML and XHTML, we are also interested in the extensions to HTML proposed by the WhatWG in the Web Apps specification. HTML Editing The HTML editing project provides rich text editing capabilities both as WebKit API for applications and through support of contentEditable and designMode for use in Web pages. HTML Forms The HTML form controls project is about the code to support the form controls that are available in HTML and XHTML. We would like to extend forms to support the work of the WhatWG (in particular the Web Forms specification). We also plan to change how the forms are implemented in order to improve performance and portability of the controls. JavaScript JavaScript is the primary scripting language of the Web, and WebKit's JS engine is one of the fastest out there. Find out about some of the interesting improvements planned for the JavaScript interpreter. Layout and Rendering For work on the layout and rendering of XML/HTML+CSS. This includes block and line layout, table layout and extensions like the XUL box layout. This also includes work on rendering and display issues.

MathML MathML is a specification for the inclusion of mathematical expressions in Web documents. Although this is not yet implemented in WebKit, we are keenly interested in developing a fully integrated implementation. Plug-ins WebKit supports two types of plug-ins, cross-browser plug-ins using an enhanced form of the Netscape plug-in API and WebKit plug-ins that are designed for use by embedded applications that need to display native OS X content integrated with the Web document. Printing Find out about WebKit's printing architecture here and about planned improvements to make page breaks work more cleanly when splitting up objects like HTML tables. SVG (Scalable Vector Graphics) SVG is a standard from the W3C for describing two-dimensional graphics for Web documents. This is not yet implemented in WebKit, but we are very interested in merging KSVG and the KDOM work into our code base to achieve a fully integrated SVG solution. If you want to see Dashboard widgets that use SVG, come on in and help make it happen! WebKit API The WebKit embedding API provides clients with a public API for loading, displaying and manipulating Web content. WebKit clients can find out about plans for the API and get involved in the design process. Web Page Accessibility WebKit has accessibility features designed to work with the VoiceOver technology of OS X. Get involved and make suggestions for how this support can be improved in future releases. We are also interested in how to generalize our current accessibility support to make it portable to other platforms. XML (Extensible Markup Language) XML is the foundation of WebKit's document object model and in the future will be the preferred format for compound documents that use HTML, SVG and MathML together. This project covers the implementation of XML in WebKit and also other XML-related technologies like XPath. XSLT

XSL Transformations provide the ability to take source XML and transform it into text, HTML or XML. This capability is a recent inclusion in WebKit, and there is still lots of interesting work to do in this area.

Web Site Compatibility
Overview

The most important task that we are working on in WebKit is improving web site compatibility. Web site compatibility is actually a generic term that covers bugs that may occur in many different functional areas of the code, from CSS to rendering to plug-ins. Any time you encounter a web site that works in another browser but fails in a WebKit browser you have hit a web site compatibility bug. These bugs can range from minor rendering defects to showstoppers that make an entire site inaccessible. The causes of these bugs are also wide-ranging, from bugs in the way the web page is coded to bugs in the engine itself. For this reason reduction of web site compatibility bugs is a top priority. Only if the bug is reduced to a minimal failing test case is it easy for a developer to determine the root cause of the problem. Web site compatibility bugs fall into several categories:
1. The bug is in the Web site itself. You can test this assumption by checking the site in other browsers like Firefox and Internet Explorer for Windows. If both of these browsers also fail on the site, it's a safe bet that the site is to blame. 2. The HTML on the site is buggy, but WebKit's error recovery does not match other browsers. This is a very common scenario for WebKit as our error handling is still a bit more strict than other browsers. In this case the bug is still our responsibility, since whenever possible we want to match other browsers' error recovery behavior. 3. WebKit has a legitimate compliance bug. This is the most important class of compatibility bug, since we especially want valid HTML to render and behave properly. Get Involved!

How can you help us improve web site compatibility in Safari?
Test Test Test! Build the latest WebKit and use it day to day. Visit all of your favorite Web sites and scrutinize them all closely. Make sure they all work as expected, and if they don't then report problems to us. File Bugs Report bugs to us for any problems you find. Get bugs into our database so that we can track the issue and screen the bug.

Reduce Bugs Scan the bugs in the New Bugs component and help attach reductions and minimal failing test cases. Only when bugs are screened properly will a developer be able to determine the root cause of the problem and move it into the appropriate component. This is one of the most important ways you can help improve WebKit. Create New Tests To help avoid regressions you can make new tests, even for features that WebKit already handles correctly. The more regression tests we have covering a specific feature, the less likely it is that the feature will break when we make changes.

Performance
Overview

Performance is a top priority for WebKit. We adhere to a simple directive for all work we do on WebKit. The way to make a program faster is to never let it get slower. We have a zero-tolerance policy for performance regressions. If a patch lands that regresses performance according to our benchmarks, then the person responsible must either back the patch out of the tree or drop everything immediately and fix the regression. Common excuses people give when they regress performance are, "But the new way is cleaner!" or "The new way is more correct." We don't care. No performance regressions are allowed, regardless of the reason. There is no justification for regressing performance. None. We have a number of benchmarks that we use to measure performance.
1. The i-Bench test suite is the most well-known cross-browser benchmark. The HTML Load Speed and JavaScript tests are the most important sub-tests in the suite. No check-in can regress the benchmark scores for these tests. As of this writing, you can get the i-Bench test suite from this page on the Lionbridge website. After accepting the license agreement you'll be able to download the suite from an FTP site at pcmag.com. 2. Our internal page load test suite (called the PLT for short) must also not regress. The PLT contains pages that are representative of sites that are encountered in the real world. The harness itself is built into Safari and is accessible from the Debug menu. You can actually make Safari run the PLT on any set of test pages. Unfortunately, the pages we use internally at Apple contain copyrighted material and therefore cannot be open source at this time. We hope that in the future sites will be willing to donate snapshots of their front pages so that an open source cross-browser test suite can be developed with content that is not as homogenous as the iBench pages.

Get Involved!

How can you help improve WebKit's performance?
Test for Regressions If you have your own performance tests, run WebKit through them daily. Make sure that the performance of the sites you care about does not regress. Test the above benchmarks on your hardware to help double-check that there have not been any regressions. Remember, the best way to stay fast is to never let your code become slower. Open Source Benchmark We have discussed with Mozilla and Opera the idea of an open-source cross-browser benchmark. The stumbling block to the construction of such a test suite is that we need to get buy-in from high profile sites like Google, Amazon or Yahoo to use snapshots of their front pages in the benchmark. The benefits of having your site in such a benchmark are obvious, since browser vendors will make your sites faster as they optimize for the content of the benchmark.

If you work for one of these high profile sites we encourage you to contact us if you are interested in having your company contribute content to such a benchmark.
Profile with Shark OS X now has an excellent profiling tool called Shark. If you find operations that are slow in WebKit, we encourage you to use Shark to isolate performance problems and file bugs with that information. Here is a link to get you started using Shark.

Code Cleanup
Overview

We have a number of code cleanup tasks in mind for WebKit, WebCore and JavaScriptCore. We have established coding style guidelines for the frameworks and expect to be cleaning up the code so that it matches these guidelines. In addition there are several cleanup tasks for each framework to better refactor code or to make simplifications that will help make the code easier to understand.
Get Involved! Follow the Coding Style Guidelines We welcome patches that clean up code to follow our coding style guidelines. We especially encourage contributors to clean up code that they are already working on. It is less common for contributors to update style without making substantive changes. If you would like to clean up code without making substantive changes, you are advised to check with project members first.

Eliminate Redundant Code in WebKit and WebCore Now that WebKit and WebCore are both open source, there is less of a need for an artificial barrier between the two frameworks. Much of the Objective-C code that is in WebKit can be moved to WebCore and converted to C++. This will improve portability, performance, and eliminate redundant constructs (like the fact that both WebCore and WebKit know about loading subresources and have their own frame trees). [TODO: ADD MORE TASKS]

Portability
Overview

Welcome to the portability project page. In addition to making our code more portable, we are also interested in hosting ports of WebKit to other platforms. For example, WebCore has already been ported to GTK+ and we are interested in hosting this port in our repository. We are also interested in ports of WebKit to other platforms like Windows. This project is concerned with how to do the code refactoring necessary to improve portability, thus making life easier for those doing ports, as well as with the ports themselves.
Get Involved! Move WebKit code into WebCore Over time the WebKit framework has grown to contain a lot of code written in Objective-C that has no real business being in this framework. Now that both frameworks are open source, we would like to move as much of this code as possible from WebKit into WebCore. This means rewriting the code to be C++ instead of Objective-C to make the code more portable. Ultimately we would like WebKit to be nothing more than the embedding APIs for a given platform and infrastructure/glue code that is needed to tie into a specific platform. All of the remaining logic should move to WebCore. Implement missing components Not all platforms have code for handling cookies, authentication, SSL, caching, network loading, or image decoding. We would be interested in implementations of these capabilities that could optionally be used on platforms that do not have this support. On platforms that do, the implementation of the cross-platform abstraction could call into the system. One possibility for obtaining this missing functionality is to port Mozilla's image rendering and networking libraries to Qt (eliminating the XPCOM and converting the use of strings, etc. to QString). Integrate the GTK+ port One port of WebCore already exists, the GTK+ port. We are interested in integrating this into our source tree, and believe that doing so will help us to refactor our code to make future ports easier.

Help Porting! Want to help with porting to Windows or some other platform? Contact us and start submitting patches!

Documentation
Overview As you can see we've gotten a good start on documenting the projects that you can get involved with in WebKit. However we have many more documents that we would like to write. The documentation project tracks everything from the current Web site design to ideas for new developer docs and technical docs. Get Involved! Here are some tasks that you can help with. Developer Documentation We would like to build up a web site that describes in detail the DOM methods, CSS properties and APIs that are supported by the different versions of Safari and WebKit, so that people have a place to go to where they can find out what we support. Project Documentation We can always use more technical documentation, from helpful tutorials on using WebKit APIs to technical documents that describe how a particular functional area of the code works. Use Blogs/Wikis We may in the future use blogs or wikis for the project pages. This would enable them to be updated more easily and to allow collaboration to take place within the project pages themselves. Existing Documentation Introduction to WebKit Objective-C Programming Guide [TODO: Add links to other existing Apple docs]

CSS (Cascading Style Sheets)
Overview

This is the project page for WebKit's Cascading Style Sheets (CSS) implementation. CSS is a W3C specification, and WebKit has implemented virtually all of CSS1, most of CSS2.1 and even some CSS3. At this time we are focusing our efforts on completing CSS1 and CSS2.1

support. Some features of CSS3 are far enough along (like selectors) that they can be implemented safely as well.
Get Involved! View bugs in the CSS component in Bugzilla.

Here are some of the tasks that you can get involved with in CSS.
Complete CSS1 Support Only a handful of CSS1 bugs remain, primarily with text-transform capitalize. Look for bugs that have been prefaced with "CSS1:" in the title. Complete support is measured by passing the CSS1 test suite. Finish CSS2.1 Support Most of CSS2.1 has been implemented in WebKit, but a few holes remain. The new white-space values pre-wrap and pre-line are not yet supported. Some of these features have been implemented in the current KHTML tree, and a merge may be possible for some of these features. Finish CSS3 Selectors Many of the CSS3 selectors are already supported by WebKit, but a few remain. Help complete support and test against the CSS selectors test suite to verify compliance. CSS2.1 Test Suite Check out the CSS2.1 test suite and file compliance bugs so that we can track open issues with our CSS2.1 compliance.

DOM (Document Object Model)
Overview

The Document Object Model (DOM) is a standardized software interface that allows code written in JavaScript and other languages to interact with the contents of an HTML document. The Document Object Model consists of a series of classes that represent HTML elements, events, and so on, each of which contains methods that operate on those elements or events.
Get Involved!
  

View bugs in the HTML DOM and XML DOM component in Bugzilla. If you find a DOM bug in the latest nightly build of WebKit, please file a bug report. Development discussions take place on Freenode IRC in #webkit.

HTML and XHTML (HyperText Markup Language)
Overview

This is the home page for work on WebKit's HTML and XHTML implementation. HTML work generally falls into four categories: work on site compatibility and handling of invalid HTML, work on finishing HTML4 support, extensions to HTML like the canvas element used in Dashboard, and XHTML work.
Get Involved! View bugs in the HTML component in Bugzilla. Complete HTML4 Support There are a handful of HTML4 issues remaining, including adding support for a few more attributes for legacy HTML to APPLET and OBJECT, implementing the BDO element, and implementing alignment inheritance in table columns. Improve XHTML We want to improve our XHTML rendering, making it as incremental as HTML and making sure entity support and scripts work properly. Extend HTML We are interested in the WhatWG work to extend HTML to have functionality that has not been covered in any other HTML specifications.

HTML Editing
Overview

Welcome to the HTML editing home page. HTML editing is a new feature that shipped with Safari 1.3 on Panther and Safari 2.0 on Tiger. Most importantly the WebKit editing engine is used to compose mail messages in Mail on Tiger. HTML editing can also be used in Web pages using WinIE-compatible APIs like contentEditable and designMode. Architecturally the editor operates as a series of commands that are executed on a document's object model tree. Each command can be undone and redone just by performing the appropriate set of DOM operations. The implementation of these commands and other editing infrastructure can be found in the WebCore framework in the editing subdirectory. Editing operations are also part of the WebKit API, and so there is some overlap with that project. Up until now our focus has mostly been on editing for applications that embed WebKit, but we plan to focus in the future on improving the in-page editing support via contentEditable.

Get Involved! View bugs in the HTML editing component in Bugzilla.

Below are some of the tasks that need work in HTML editing.
Improve contentEditable divs Right now there are a number of issues with editable divs in a Web page. The selection highlighting is not confined to the div, and extending the selection across editable and noneditable content should not be possible. In addition WebKit always clears the selection on a mouse down, and other browsers actually only do this if you mouse down on text. Add better support for lists and tables Lists and tables are two editing features that could use a richer user interface so that these sorts of features could be made available to mail and to other WebKit applications. Support more of WinIE's APIs We want to support more of WinIE's editing APIs, including more commands and text ranges. We welcome any WinIE-compatible patches that improve editing support to match WinIE.

HTML Forms
Overview

Welcome to the project page for the HTML form controls. Form controls are the various widgets that can be used in an HTML form and that can participate in form submission. The code in the engine that talks to the controls is in the WebCore framework. The DOM elements are under the html directory, and the rendering objects are under the rendering directory.
Get Involved! View bugs in the HTML Forms component in Bugzilla.

Below is a sampling of interesting open issues with our HTML form controls. To get involved contact us!
Stabilize the new form controls Form controls have recently switched from using standard AppKit controls to being rendered within the engine itself. This allows us to support more CSS properties for controls, and makes our code more portable to other platforms. Because this is such a major architectural change, we ask that you scrutinize the new controls closely and report any bugs. Implement Web Forms

The WhatWG has outlined extensions to existing HTML forms. We are interested in supporting these extensions (along with Opera and Mozilla). The specification details all of these enhancements. We welcome bugs, contributions and testers to help us implement these improvements.

JavaScript
Overview

This is the project page for WebKit's JavaScript implementation. JavaScript is the primary programming language used on web pages. Originally named LiveScript and now also known as ECMAScript, it's a safe, dynamic language that's arguably one of the most well-known programming languages in the world. There's a JavaScript standard, created by ECMA. WebKit's JavaScript engine, JavaScriptCore, based on KJS, is a framework separate from WebCore and WebKit, and is used on Mac OS X for applications other than web page JavaScript.
Get Involved! View bugs in the JavaScriptCore component in Bugzilla.

Here are some of the tasks that you can get involved with in JavaScript.
Generational Garbage Collector The garbage collector in JavaScriptCore has been improved quite a bit from the earliest versions. But much greater efficiency can be achieved with a garbage collector that uses a generational algorithm, so we don't have to mark all the objects every time we garbage collect. This should make JavaScript run significantly faster. Mozilla JavaScript Test Suite JavaScriptCore has an implementation of the Mozilla JavaScript Test Suite, and there are currently many failures. Fixing any of those failures would help our JavaScript engine be more compliant with the specification, and more compatible with real-world web sites as well. Language Extensions The Mozilla project has begun adding some extensions to JavaScript. Someone needs to evaluate these and decide which of them we should implement. We should also consider extensions of our own driven by demand in contexts like Dashboard widgets. Objective-C Language Binding JavaScriptCore currently provides a low-level C API, however using JavaScriptCore in an Objective-C application is somewhat involved. We'd like to add a high-level Objective-C API.

Layout and Rendering
Layout and rendering provides the core functionality to display a markup language such as HTML, SVG, or MathML. A render object tree is generated from the markup and those tree object instances are responsible for the layout and subsequent rendering of the content.
Related Blog Entries

WebCore Rendering I – The Basics WebCore Rendering II – Blocks and Inlines WebCore Rendering III – Layout Basics WebCore Rendering IV – Absolute/Fixed and Relative Positioning WebCore Rendering V – Floats

MathML
Overview

Welcome to the project page for MathML. MathML is a specification from the W3C for the inclusion of mathematical expressions in Web documents. At this time, work is underway to implement MathML in WebKit. Like SVG, we would like MathML to be a first-class citizen in WebKit, using our DOM, CSS and JavaScript engines. Just as with SVG, we would like to work on making improvements to our DOM and reconciling with the KDOM work that has been done for KSVG2 so that SVG and MathML can share some of the same compound document infrastructure (and also to ensure that a MathML implementation can be shared between KDE and OS X). More information about this project is provided on the MathML Wiki page.
Get Involved!

Come find us on #webkit to get involved.

Printing
Overview

Welcome to the printing project page. Printing in WebKit is closely tied to the layout and rendering code. When you print in WebKit, the existing render tree is converted into a new render tree with print styles applied. That new render tree then gets a layout. The big flaw in WebKit's printing architecture right now is that page breaks are determined at a simulated "paint"

time rather than during layout itself. This means that at best all you can hope to do is try to find an optimal position for a break without altering the layout of the Web document at all.
Get Involved Rework Printing Printing needs to be reworked so that render objects know how to split themselves across breaks. This allows two separate formatting contexts (like two adjacent table cells) to still have their contents both break cleanly across a page. This work is also important for future technology like CSS3 multi-column support. The code that splits render objects across pages could obviously be leveraged to also split render objects across column breaks as well.

SVG (Scalable Vector Graphics)
Overview

Welcome to the project page for SVG. At this time there is an experimental SVG implementation in WebKit. We imported KDE's excellent KSVG2 implementation and have tweaked it to integrate seamlessly with the rest of WebCore. There is still much work to be done to finish off some advanced SVG features such as animation and SVG fonts. With your help we look forward to many great uses of SVG throughout the web and Mac OS X!
Get Involved!
  

View bugs in the SVG component in Bugzilla. The WebKit SVG Wiki page The official WebKit SVG status page

Get on IRC There is still much work to be done to complete our implementation of SVG 1.1. Development discussions take place on Freenode IRC in #ksvg and #webkit. Come get involved as we flesh out our SVG implementation for WebKit! Test WebKit+SVG SVG support is enabled in the latest nightly builds. Give it a whirl; try to break it! If WebKit doesn't render your favorite SVG perfectly, please file a bug.

XSLT
Overview

Welcome to the project page for WebKit's XSLT implementation. XSLT is a W3C standard for defining how to transform source XML into a result document that can be examined using the DOM or displayed as a Web document. Here is a test file that demonstrates client-side XSLT in action.

WebKit uses the excellent libxslt library to do XSL transformations. Bugs in WebKit's XSLT support fall into two categories: either they are bugs in libxslt itself, or they are bugs in WebKit's glue code that interacts with libxslt. The following page at xmlsoft.org has a list of helpful resources and explains the process of bug reporting and getting help for bugs in libxslt. Even if the bug is in libxslt, file a tracking bug in WebKit's XSLT component and paste in a link to the corresponding libxslt bug. That way we can track the issue and know that an update to the version of libxslt on the system may be necessary. WebKit's implementation of XSLT can be found in the WebCore framework in the khtml/xsl subdirectory. There are two classes of interest, XSLStyleSheetImpl and XSLTProcessorImpl. The style sheet class shares a common base with CSS style sheets, and exists as an objectoriented expression of the stylesheets that WebKit encounters when it parses the source XML file. The processor wraps the code that actually performs the transformation. It takes the stylesheets and source XML and produces result text that is then fed back into WebKit for parsing as HTML, XML or plain text.
Get Involved!

View XSLT bugs in Bugzilla. Below is a sampling of interesting open issues with WebKit's XSLT support. If you wish to sign up for any of these tasks, send mail to [email protected] or comment in the appropriate bug.
XSL transformations block the user interface The XSLTProcessor that performs the transformation using libxslt does so on the UI thread. Therefore a transformation that takes a long time to complete will block the UI of a WebKit application. The code should be restructured so that both synchronous and asynchronous transformations are allowed, since until JavaScript can be suspended/resumed a synchronous transformation mode must be possible in order for a JS API for XSL transformations to work.

Technical Articles

   



Major Objects in WebCore RefPtr and PassRefPtr Basics - Reference counting in WebKit A guide to Assertion macros in WebKit WebCore Rendering - a series of blog posts by Dave Hyatt on the mechanics of how WebCore renders Web pages: o Part 1 - The Basics o Part 2 - Blocks and Inlines o Part 3 - Layout Basics o Part 4 - Absolute/Fixed and Relative Positioning o Part 5 - Floats How WebKit loads a Web Page

     

WebKit Page Cache - Part 1 & Part 2 How a DOM Element is Attached

Major Objects in WebCore
Adam Barth first draft, 2009-08-12 WebCore uses a number of objects to represent a web page in memory. This document describes the major objects and the relation between them. In some cases, the connection between these objects can be broken, resulting in null pointers. When traversing these pointers, code must be careful to consider the "detached" case and gracefully handle null pointers.
+---------+ | Chrome | +----+----+ | +---+---+ +----------+ | Page +---->| Settings | +---+---+ +----------+ | +-------------------------- ... other Frame objects | +---+---+ +-------------+ +-------------------+ | Frame +---+ FrameLoader + | JSDOMWindowShell | +---+---+ +-------------+ +---------+---------+ / \ | / \ /\ Re-used after navigation /\ | .../....|...............................................|.......... / | \/ Replaced after navigation \/ | / | | /<------|<-- Ptrs to Frame are null after navigation[1] | | | | | +-----+-----+ +-------------+ | | | DOMWindow |<--impl--+ JSDOMWindow |<------window----+ | +-----+-----+ +-------------+ | | | |<-- Can be null for Documents created by XMLHttpRequest | | | +-----+-----+ +-------------+ +-+ Document |<--impl--+ JSDocument | +-----+-----+ +-------------+ | |<-- Can be null for DocumentType objects | +---+---+ +--------+ | Node |<---impl---| JSNode | +-------+ +--------+

                                   

[1] After navigating to a new page, the old DOMWindow and old Document point to a null Frame, and the Frame points to a new DOMWindow and a new Document.



If you have any comments on the above or other ideas about improving the clarity, scope, or presentation, please send mail to the WebKit mailing list.

RefPtr and PassRefPtr Basics
Darin Adler Version 4, 2010-08-27

History
Many objects in WebKit are reference counted. The pattern used is that classes have member functions ref and deref that increment and decrement the reference count. Each call to ref has to be matched by a call to deref. When the function is called on an object with a reference count of 1, the object is deleted. Many classes in WebKit implement this pattern by deriving from the RefCounted class template. Back in 2005, we discovered that there were many memory leaks, especially in HTML editing code, caused by misuse of ref and deref calls. We wanted to use smart pointers to mitigate the problem. However, some early experiments showed that smart pointers led to additional manipulation of reference counts that hurt performance. For example, for a function that took a smart pointer as a parameter and returned that same smart pointer as a return value, just passing the parameter and returning the value would increment and then decrement the reference count two to four times as the object moved from one smart pointer to another. So we looked for an idiom that would let us use smart pointers and avoid this reference count churn. The inspiration for a solution came from the C++ standard class template auto_ptr. These objects implement a model where assignment is transfer of ownership. When you assign from one auto_ptr to another, the donor becomes 0. Maciej Stachowiak devised a pair of class templates, RefPtr and PassRefPtr, that implement this scheme for WebCore’s intrusive reference counting.

Raw pointers
When discussing smart pointers such as the RefPtr class template we use the term raw pointer to refer to the C++ language’s built in pointer type. Here’s the canonical setter function, written with raw pointers:
// example, not preferred style class Document { ... Title* m_title;

} Document::Document() : m_title(0) { } Document::~Document() { if (m_title) m_title->deref(); } void Document::setTitle(Title* title) { if (title) title->ref(); if (m_title) m_title->deref(); m_title = title; }

RefPtr
RefPtr is a simple smart pointer class that calls ref on incoming values and deref on outgoing values. RefPtr works on any object with both a ref and a deref member function. Here’s the setter function example, written with RefPtr:
// example, not preferred style class Document { ... RefPtr<Title> m_title; } void Document::setTitle(Title* title) { m_title = title; }

Use of RefPtr alone can lead to reference count churn.
// example, not preferred style; should use RefCounted and adoptRef (see below) RefPtr<Node> createSpecialNode() { RefPtr<Node> a = new Node; a->setSpecial(true); return a; } RefPtr<Node> b = createSpecialNode();

For purposes of this discussion, lets assume that the node object starts with a reference count of 0 (more on this later). When it’s assigned to a, the reference count is incremented to 1. The reference count is incremented to 2 to create the return value, then decremented back to 1 when a is destroyed. Then the reference count is incremented to 2 to create b, and then decremented back to 1 when the return value of createSpecialNode is destroyed. (If the compiler implements the return value optimization, there may be one less increment and decrement of the reference count.) The overhead of reference count churn is even greater when both function arguments and return values are involved. The solution is PassRefPtr.

PassRefPtr
PassRefPtr is like RefPtr with a difference. When you copy a PassRefPtr or assign the value of a PassRefPtr to a RefPtr or another PassRefPtr, the original pointer value is set to 0; the operation is done without any change to the reference count. Let’s take a look at a new version of our example:
// example, not preferred style; should use RefCounted and adoptRef (see below) PassRefPtr<Node> createSpecialNode() { PassRefPtr<Node> a = new Node; a->setSpecial(true); return a; } RefPtr<Node> b = createSpecialNode();

The node object starts with a reference count of 0. When it’s assigned to a, the reference count is incremented to 1. Then a gets set to 0 when the return value PassRefPtr is created. Then the return value is set to 0 when b is created. However, as the Safari team learned when we started programming with PassRefPtr, the rule that a pointer becomes 0 when it’s assigned to another variable can easily lead to mistakes.
// warning, will dereference a null pointer and will not work static RefPtr<Ring> g_oneRingToRuleThemAll; void finish(PassRefPtr<Ring> ring) { g_oneRingToRuleThemAll = ring; ... ring->wear(); }

By the time wear is called, ring is already 0. To avoid this, we recommend PassRefPtr only for function argument and result types, copying arguments into RefPtr local variables.
static RefPtr<Ring> g_oneRingToRuleThemAll; void finish(PassRefPtr<Ring> prpRing) { RefPtr<Ring> ring = prpRing; g_oneRingToRuleThemAll = ring; ... ring->wear(); }

Mixing RefPtr and PassRefPtr
Since we recommend use of RefPtr in all cases except when passing arguments to or returning values from a function, there will be times when you have a RefPtr and wish to transfer ownership as PassRefPtr does. RefPtr has a member function named release that does the trick. It sets the value of the original RefPtr to 0 and constructs a PassRefPtr, without changing reference counts.
// example, not preferred style; should use RefCounted and adoptRef (see below) PassRefPtr<Node> createSpecialNode() { RefPtr<Node> a = new Node; a->setCreated(true); return a.release(); } RefPtr<Node> b = createSpecialNode();

This keeps the efficiency of PassRefPtr while reducing the chance that its relatively tricky semantics will cause problems.

Mixing with raw pointers
When using a RefPtr to call a function that takes a raw pointer, use the get function.
printNode(stderr, a.get());

However, many operations can be done on a RefPtr or PassRefPtr directly, without resorting to an explicit get call.
RefPtr<Node> a = createSpecialNode(); Node* b = getOrdinaryNode(); // the * operator *a = value;

// the -> operator a->clear(); // null check in an if statement if (a) log("not empty"); // the ! operator if (!a) log("empty"); // the == and != operators, mixing with raw pointers if (a == b) log("equal"); if (a != b) log("not equal"); // some type casts RefPtr<DerivedNode> d = static_pointer_cast<DerivedNode>(a);

Normally, RefPtr and PassRefPtr enforce a simple rule; they always balance ref and deref calls, guaranteeing a programmer can’t miss a deref. But in the case where we have a raw pointer, already have a reference count, and want to transfer ownership the adoptRef function should be used.
// warning, requires a pointer that already has a ref RefPtr<Node> node = adoptRef(rawNodePointer);

To transfer from a RefPtr to a raw pointer without changing the reference count, PassRefPtr provides the leakRef function.
// warning, results in a pointer that must get an explicit deref RefPtr<Node> node = createSpecialNode(); Node* rawNodePointer = node.release().leakRef();

Since leakRef is rarely used, it’s provided only in the PassRefPtr class, hence the need to call release, then leakRef.

RefPtr and new objects
In the examples in this discussion, we talked about objects with a reference count of 0. However, for efficiency and simplicity, the RefCounted class doesn't use a reference count of 0 at all. Objects are created with a reference count of 1. The best programming idiom to use is to put such objects right into a RefPtr to make it impossible to forget to deref the object when done with it. This means that anyone calling new on such an object should immediately call adoptRef. In WebCore we use functions named create instead of direct calls to new.
// preferred style PassRefPtr<Node> Node::create() {

return adoptRef(new Node); } RefPtr<Node> e = Node::create();

Because of the way adoptRef and PassRefPtr are implemented, this is an efficient idiom. The object starts with a reference count of 1 and no manipulation of the reference count happens at all.
// preferred style PassRefPtr<Node> createSpecialNode() { RefPtr<Node> a = Node::create(); a->setCreated(true); return a.release(); } RefPtr<Node> b = createSpecialNode();

The node object is put into a PassRefPtr by a call to adoptRef inside Node::create, then passes into a and is released and passes into b, all without touching the reference count. The RefCounted class implements a runtime check so we get an assertion failure if we create an object and call ref or deref without first calling adoptRef.

Guidelines
We’ve developed these guidelines for use of RefPtr and PassRefPtr in WebKit code.
Local variables
  

If ownership and lifetime are guaranteed, a local variable can be a raw pointer. If the code needs to hold ownership or guarantee lifetime, a local variable should be a RefPtr. Local variables should never be PassRefPtr.

Data members
  

If ownership and lifetime are guaranteed, a data member can be a raw pointer. If the class needs to hold ownership or guarantee lifetime, the data member should be a RefPtr. Data members should never be PassRefPtr.

Function arguments
 

If a function does not take ownership of an object, the argument should be a raw pointer. If a function does take ownership of an object, the argument should be a PassRefPtr. This includes most setter functions. Unless the use of the argument is very simple, the argument should be transferred to a RefPtr at the start of the function; the argument can be named with a “prp” prefix in such cases.

Function results
 

If a function’s result is an object, but ownership is not being transferred, the result should be a raw pointer. This includes most getter functions. If a function’s result is a new object or ownership is being transferred for any other reason, the result should be a PassRefPtr. Since local variables are typically RefPtr, it’s common to call release in the return statement to transfer the RefPtr to the PassRefPtr.

New objects
  

New objects should be put into a RefPtr as soon as possible after creation to allow the smart pointers to do all reference counting automatically. For RefCounted objects, the above should be done with the adoptRef function. Best idiom is to use a private constructor and a public create function that returns a PassRefPtr.

Improving this document
We should add answers to any frequently asked questions are not covered by this document. One or more of the following topics could also be covered by this document.
        

The “protector” idiom, where a local RefPtr variable is used to keep an object alive. Perils of programming with TreeShared. Our desire to eliminate TreeShared and instead have m_firstChild and m_next be ListRefPtr or the equivalent. How we we mix reference counting with garbage collection to implement the DOM and the JavaScript and Objective-C DOM bindings. Comparison of our intrusive reference counting with other schemes such as the external reference counting in Boost shared_ptr. The OwnPtr class template, and how it can be used with PassOwnPtr and adoptPtr. The OwnArrayPtr class template, and PassOwnArrayPtr. The RetainPtr class template, and the lack of a PassRetainPtr. The ListRefPtr class template.

If you have any comments on the above or other ideas about improving the clarity, scope, or presentation, please send mail to the WebKit mailing list.

A guide to Assertion macros in WebKit
Version 1, 2010-5-24

Background
WebKit provides a number of macros to assert that conditions in the code are met. They are defined in Source/JavaScriptCore/wtf/Assertions.h. This document provides an overview of the various macros, including guidelines and best practices for their use.

Types of ASSERT macros
The ASSERT() macro and its variants are compiled out of release builds. They are meant for use during the development process to catch programming mistakes. For those macros that accept an expression as an argument, the expression is also compiled out of release builds and thus incurs no overhead in shipping code.
        

ASSERT(expression) - for use during development to ensure that unexpected conditions do not occur. If the expression evaluates to false then abort execution and break into the debugger. ASSERT_UNREACHED() - for use when a certain branch of code should never be executed.
if (condition) { ... } else { // This should never happen. ASSERT_UNREACHED(); }

ASSERT_UNUSED(variable, expression) - for assertions that check the value of otherwise unused variable. The need for this becomes apparent if you consider the case where you want to assert an expression that uses a variable that wouldn't otherwise be used in the enclosing function. ASSERT() can't be used in this case because in a release build the compiler would warn about the unused variable. ASSERT_UNUSED() avoids this warning. Example from Source/JavaScriptCore/jit/ExecutableAllocatorPosix.cpp :
void ExecutablePool::systemRelease(const ExecutablePool::Allocation& alloc) { int result = munmap(alloc.pages, alloc.size); // result not used outside the ASSERT(). ASSERT_UNUSED(result, !result); }

     

The CRASH() macro
CRASH() raises a fatal error resulting in program termination and triggering either the debugger or the crash reporter. It is active in both debug & release mode. CRASH() directly affects users in that it will disrupt or end their browsing session. If a browser vendor traces crashes, it can be extremely helpful in diagnosing hard to find issues that may only occur on users' machines.

Considerations when using ASSERT() and CRASH() macros.
Hazards of using the ASSERT() family of macros

The expression inside the ASSERT and ASSERT_UNUSED macro is compiled out of release builds together with the macro itself. If the expression that's used has side effects, its omission in release build can lead to programming errors that don't manifest in debug builds.

The benefits of using CRASH:
 

If a browser vendor traces crashes in their software, CRASH() can provide vital information from end users to allow an issue to be resolved. Code after CRASH() is guaranteed unreachable, which can help prevent some bugs from being security liabilities.

The cost of using CRASH:
 

Use of the CRASH macro turns a programming error into a crash, blowing away a webpage or an entire web browser in cases that otherwise might be harmless. Checking for the error condition in release builds may slow the program down.

Guidelines for using ASSERT() and CRASH() macros.
 



Use ASSERT() for things that should never happen, but if they do will cause incorrect results rather than a crash or memory corruption. Assertions are claims that a programmer knows to be true, and they fire only when that programmer turns out to be wrong because there is some kind of programming mistake. There should be no "wishful thinking" involved. For example, ASSERT() should not be used to verify that a file system call has succeeded, because there is no way for a programmer to guarantee that. Use CRASH() for cases that shouldn't happen, but if they do would be unrecoverable. e.g. out of memory errors.

Examples of using CRASH() vs ASSERT()
// Not having any children indicates a programming error. ASSERT(object->numChildren() > 0); Allocation bitmapStorage = systemAlloc(allocSize); if (!bitmapStorage.pages) CRASH(); // Not possible to recover from an out of memory error.

If you have any comments on the above or other ideas about improving the clarity, scope, or presentation, please send mail to the WebKit mailing list.

WebCore Rendering I – The Basics
Posted by Dave Hyatt on Wednesday, August 8th, 2007 at 5:34 pm

This is the first of a series of posts designed to help people interested in hacking on WebCore’s rendering system. I’ll be posting these articles as I finish them on this blog, and they will also be available in the documentation section of the Web site.
The DOM Tree

A Web page is parsed into a tree of nodes called the Document Object Model (DOM for short). The base class for all nodes in the tree is Node.

Node.h

Nodes break down into several categories. The node types that are relevant to the rendering code are:


Document – The root of the tree is always the document. There are three document classes, Document, HTMLDocument and SVGDocument. The first is used for all XML documents other than SVG documents. The second applies only to HTML documents and inherits from Document. The third applies to SVG documents and also inherits from Document.
Document.h HTMLDocument.h



Elements – All of the tags that occur in HTML or XML source turn into elements. From a rendering perspective, an element is a node with a tag name that can be used to cast to a specific subclass that can be queried for data that the renderer needs.
Element.h



Text – Raw text that occurs in between elements gets turned into text nodes. Text nodes store this raw text, and the render tree can query the node for its character data.
Text.h

The Render Tree

At the heart of rendering is the render tree. The render tree is very similar to the DOM in that it is a tree of objects, where each object can correspond to the document, elements or text nodes. The render tree can also contain additional objects that have no corresponding DOM node. The base class of all render tree nodes is RenderObject.
RenderObject.h

The RenderObject for a DOM node can be obtained using the renderer() method on Node.
RenderObject* renderer() const

The following methods are most commonly used to walk the render tree.
RenderObject* RenderObject* RenderObject* RenderObject* firstChild() const; lastChild() const; previousSibling() const; nextSibling() const;

Here is an example of a loop that walks a renderer’s immediate children. This is the most common walk that occurs in the render tree code.
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) { ... }

Creating the Render Tree

Renderers are created through a process on the DOM called attachment. As a document is parsed and DOM nodes are added, a method called attach gets called on the DOM nodes to create the renderers.
void attach()

The attach method computes style information for the DOM node. If the display CSS property for the element is set to none or if the node is a descendant of an element with display: none set, then no renderer will be created. The subclass of the node and the CSS display property value are used together to determine what kind of renderer to make for the node. Attach is a top down recursive operation. A parent node will always have its renderer created before any of its descendants will have their renderers created.
Destroying the Render Tree

Renderers are destroyed when DOM nodes are removed from the document or when the document gets torn down (e.g., because the tab/window it was in got closed). A method called detach gets called on the DOM nodes to disconnect and destroy the renderers.
void detach()

Detachment is a bottom up recursive operation. Descendant nodes will always have their renderers destroyed before a parent destroys its renderer.
Accessing Style Information

During attachment the DOM queries CSS to obtain style information for an element. The resultant information is stored in an object called a RenderStyle.
RenderStyle.h

Every single CSS property that WebKit supports can be queried via this object. RenderStyles are reference counted objects. If a DOM node creates a renderer, then it connects the style information to that renderer using the setStyle method on the renderer.
void setStyle(RenderStyle*)

The renderer adds a reference to the style that it will maintain until it either gets a new style or gets destroyed. The RenderStyle can be accessed from a RenderObject using the style() method.
RenderStyle* style() const

The CSS Box Model

One of the principal workhorse subclasses of RenderObject is RenderBox. This subclass represents objects that obey the CSS box model. These include any objects that have borders, padding, margins, width and height. Right now some objects that do not follow the CSS box model (e.g., SVG objects) still subclass from RenderBox. This is actually a mistake that will be fixed in the future through refactoring of the render tree. This diagram from the CSS2.1 spec illustrates the parts of a CSS box. The following methods can be used to obtain the border/margin/padding widths. The RenderStyle should not be used unless the intent is to look at the original raw style information, since what is actually computed for the RenderObject could be very different (especially for tables, which can override cell padding and have collapsed borders between cells).
int int int int int int int int int int int int marginTop() const; marginBottom() const; marginLeft() const; marginRight() const; paddingTop() const; paddingBottom() const; paddingLeft() const; paddingRight() const; borderTop() const; borderBottom() const; borderLeft() const; borderRight() const;

The width() and height() methods give the width and height of the box including its borders.
int width() const; int height() const;

The client box is the area of the box excluding borders and scrollbars. Padding is included.
int int int int clientLeft() const { return borderLeft(); } clientTop() const { return borderTop(); } clientWidth() const; clientHeight() const;

The term content box is used to describe the area of the CSS box that excludes the borders and padding.

IntRect contentBox() const; int contentWidth() const { return clientWidth() - paddingLeft() paddingRight(); } int contentHeight() const { return clientHeight() - paddingTop() paddingBottom(); }

When a box has a horizontal or vertical scrollbar, it is placed in between the border and the padding. A scrollbar’s size is included in the client width and client height. Scrollbars are not part of the content box. The size of the scrollable area and the current scroll position can both be obtained from the RenderObject. I will cover this in more detail in a separate section on scrolling.
int int int int scrollLeft() const; scrollTop() const; scrollWidth() const; scrollHeight() const;

Boxes also have x and y positions. These positions are relative to the ancestor that is responsible for deciding where this box should be placed. There are numerous exceptions to this rule, however, and this is one of the most confusing areas of the render tree.
int xPos() const; int yPos() const;

You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.
4 Responses to “WebCore Rendering I – The Basics” 1. Sam Weinig Says:
August 8th, 2007 at 6:16 pm

Awesome post Princess. You’re the bees knees.
2. bartocc Says:
August 9th, 2007 at 10:54 am

This kind of documentation is very important and very helpful! Thx for the post, I am looking forward for the coming ones.
3. Pingback from Around the Browsersphere #2:
September 5th, 2007 at 2:08 am

[...] Hyatt has posted five detailed articles on WebCore [...]
4. Pingback from Surfin’ Safari - Blog Archive » Welcome to Planet WebKit:
December 3rd, 2007 at 11:19 pm

[...] WebKit, from descriptions of the many new features being added to technical discussions of engine internals to announcements of WebKit being used in entirely new places. But the web is a big place, and we [...]
                                           

Home Surfin’ Safari Blog Planet WebKit Project Goals Keeping in Touch Trac Contributors Meeting Working with the Code Installing Developer Tools Getting the Code Building WebKit Running WebKit Debugging WebKit Contributing Code Commit and Review Policy Security Policy Documentation Wiki Projects Code Style Guidelines Technical Articles Web Inspector Web Developer Resources Demos Testing Regression Testing Leak Hunting Writing New Tests Getting a Crash Log Bugs Reporting Bugs Bug Report Guidelines Bug Prioritization Test Case Reduction Bug Life Cycle Archives March 2011 February 2011 January 2011 December 2010 September 2010 August 2010 July 2010 June 2010

                                               

May 2010 April 2010 March 2010 February 2010 January 2010 December 2009 November 2009 October 2009 September 2009 July 2009 June 2009 May 2009 April 2009 March 2009 February 2009 December 2008 October 2008 September 2008 June 2008 May 2008 April 2008 March 2008 February 2008 January 2008 December 2007 November 2007 October 2007 September 2007 August 2007 July 2007 June 2007 May 2007 April 2007 March 2007 February 2007 January 2007 December 2006 November 2006 October 2006 September 2006 August 2006 June 2006 May 2006 April 2006 March 2006 February 2006 January 2006 December 2005

     

November 2005 October 2005 September 2005 August 2005 July 2005 June 2005

WebKit is open source software with portions licensed under the LGPL and BSD licenses. Complete license and copyright information can be found within the code. Hosting provided by Mac OS Forge. Use of this site is subject to the Mac OS Forge Terms of Use. Surfin' Safari site is powered by WordPress Entries (RSS) and Comments (RSS). Register | Log in

WebCore Rendering II – Blocks and Inlines
Posted by Dave Hyatt on Thursday, August 9th, 2007 at 2:59 pm

In the previous entry I talked about the basic structure of a CSS box. In this article I’m going to talk about subclasses of RenderBox and about the concepts of block and inline. A block flow is a box designed either to contain lines (e.g., a paragraph) or to contain other blocks that it stacks vertically. Example block flow elements in HTML are p and div. An inline flow is an object that is designed to be part of a line. Example inline flow elements in HTML are a, b, i and span. In WebCore, there are three renderer classes that cover block and inline flows. RenderBlock, RenderInline and their common superclass RenderFlow.
RenderFlow.h RenderBlock.h RenderInline.h

An inline flow can be changed to a block flow (and vice versa) using the CSS display property.
div { display: inline } span { display: block }

In addition to block and inline flows, there is another kind of element that can act as a block or inline: the replaced element. A replaced element is an element whose rendering is unspecified by CSS. How the contents of the object render is left up to the element itself. Examples of replaced elements are images, form controls, iframes, plugins and applets. A replaced element can also be either block-level or inline-level. When a replaced element acts as a block, it will get stacked vertically as though it represents its own paragraph. When a

replaced element acts as an inline, it will be part of a line inside a paragraph. Replaced elements are inline by default. Form controls are actually a strange special case. They are still replaced elements, but because they are implemented by the engine, controls actually ultimately subclass from RenderBlock. As a result, the concept of being replaced can’t really be confined to a single common subclass, and is therefore represented as a bit on RenderObject instead. The isReplaced method can be used to ask if an object is a replaced element.
bool isReplaced() const

Images, plugins, frames and applets all inherit from a common subclass that implements replaced element behavior. This class is RenderReplaced.
RenderReplaced.h

The Inline Block

One of the most confusingly named objects in CSS is the inline-block. Inline blocks are block flows that are designed to sit on a line. In effect they are like inline replaced elements on the outside, but on the inside they are block flows. The display property in CSS can be used to create inline blocks. Inline blocks will report true if asked if they are replaced.
div { display: inline-block }

Tables

Tables in HTML are block-level by default. However they can also be made into inlines using the CSS display property with a value of inline-table.
table { display: inline-table }

Again, from the outside an inline-table is like an inline replaced element (and will return true from isReplaced), but on the inside the object is still just a table. In WebCore the RenderTable class represents a table. It inherits from RenderBlock for reasons that will be covered in the positioning section later.
RenderTable.h

Text

Raw text is represented using the RenderText class. Text is always considered inline by WebCore, since it is always placed on lines.
RenderText.h

Getting Block and Inline Information

The most basic method for obtaining block vs. inline status is the isInline function. This method asks if an object is designed to be part of a line. It does not care what the interior of the element is (e.g., text, image, an inline flow, an inline-block or an inline-table).
bool isInline() const

One of the common mistakes people make when working with the render tree is assuming that isInline means an object is always an inline flow, text or an inline replaced element. However because of inline-blocks and inline-tables, this method can return true even for these objects. To ask if an object is actually a block or inline flow, the following methods should be used.
bool isInlineFlow() const bool isBlockFlow() const

These methods are essentially asking questions about the interior of the object. An inline-block for example is still a block flow and not an inline flow. It is inline on the outside, but on the inside it is a block flow. The exact class type can be queried for blocks and inlines using the following methods.
bool isRenderBlock() const bool isRenderInline() const

The isRenderBlock method is useful in the context of positioning, since both block flows and tables act as positioned object containers. To ask if an object is specifically an inline block or inline table, the isInlineBlockOrInlineTable method can be used.
bool isInlineBlockOrInlineTable() const

Children of Block Flows

Block flows have a simple invariant regarding their children that the render tree always obeys. That rule can be summarized as follows: All in-flow children of a block flow must be blocks, or all in-flow children of a block flow must be inlines. In other words, once you exclude floating and positioned elements, all of the children of a block flow in the render tree must return true from isInline or they must all return false from isInline. The render tree will change its structure as needed to preserve this invariant.

The childrenInline method is used to ask whether the children of a block flow are inlines or blocks.
bool childrenInline() const

Children of Inline Flows

Children of inline flows have an even simpler invariant that must be maintained. All in-flow children of an inline flow must be inlines.
Anonymous Blocks

In order to preserve the block flow child invariant (only inline children or only block children), the render tree will construct objects called anonymous blocks. Consider the following example:
<div> Some text <div> Some more text </div> </div>

In the above example, the outer div has two children: some text and another div. The first child is an inline, but the second child is a block. Because this combination of children violates the allinline or all-block child rule, the render tree will construct an anonymous block flow to wrap the text. The render tree therefore becomes:
<div> <anonymous block> Some text </anonymous block> <div> Some more text </div> </div>

The isAnonymousBlock method can be used to ask if a renderer is an anonymous block flow.
bool isAnonymousBlock() const

Whenever a block flow has inline children and a block object suddenly tries to insert itself as a child, anonymous blocks will be created as needed to wrap all of the inlines. Contiguous inlines will share a single common anonymous block, so the number of anonymous blocks can be kept to a minimum. The makeChildrenNonInline method in RenderBlock is the function that performs this adjustment.
void makeChildrenNonInline(RenderObject *insertionPoint)

Blocks inside Inline Flows

One of the nastiest constructs you will see in HTML is when a block is placed inside an inline flow. Here is an example:
<i>Italic only <b>italic and bold <div> Wow, a block! </div> <div> Wow, another block! </div> More italic and bold text</b> More italic text</i>

The two divs violate the invariant that all of the children of the bold element must be inlines. The render tree has to perform a rather complicated series of steps in order to fix up the tree. Three anonymous blocks are constructed. The first block holds all of the inlines that come before the divs. The second anonymous block holds the divs. The third anonymous block holds all of the inlines that come after the divs.
<anonymous pre block> <i>Italic only <b>italic and bold</b></i> </anonymous pre block> <anonymous middle block> <div> Wow, a block! </div> <div> Wow, another block! </div> </anonymous middle block> <anonymous post block> <i><b>More italic and bold text</b> More italic text</i> </anonymous post block>

Notice that the bold and italic renderers had to split into two render objects, since they are in both the anonymous pre block and the anonymous post block. In the case of the bold DOM element, its children are in the pre block, but then continue into the middle block and then finally continue into the post block. The render tree connects these objects via a continuation chain.
RenderFlow* continuation() const bool isInlineContinuation() const

The first bold renderer in the pre block is the one that can be obtained from the b DOM element using the element’s renderer() method. This renderer has as its continuation() the middle anonymous block. The middle anonymous block has as its continuation() the second bold renderer. In this way code that needs to examine the renderers that represent the children of the DOM element can still do so relatively easily.

In the above example the i DOM element also split. Its children are all in the pre and post blocks, and therefore only one connection is needed. The italic renderer in the pre block sets its continuation() to the italic renderer in the post block. The function that performs the recursive splitting of inline flows and that creates the continuation chain connections is called splitFlow and is in RenderInline.cpp. You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.
3 Responses to “WebCore Rendering II – Blocks and Inlines” 1. Chris Griego Says:
August 9th, 2007 at 4:26 pm

If the problem is having a block-level element within an inline element, then why is the anonymous middle block necessary?
2. hyatt Says:
August 9th, 2007 at 4:48 pm

Strictly speaking it isn’t necessary, although it simplifies a lot of the code that deals with continuations. It’s basically there for convenience.
3. hyatt Says:
August 9th, 2007 at 4:50 pm

Longer term, I’d like to explore eliminating continuations completely and wrapping the offending blocks in an anonymous inline-block instead. The difficult problem with using an anonymous inline-block, however, is that when the pre and post sections end up having no content, you have to margin collapse the offending blocks with surrounding content. This would necessitate having a sort of hybrid line/block layout that could easily slide into and out of both layout modes.
            

Home Surfin’ Safari Blog Planet WebKit Project Goals Keeping in Touch Trac Contributors Meeting Working with the Code Installing Developer Tools Getting the Code Building WebKit Running WebKit Debugging WebKit

                                               

Contributing Code Commit and Review Policy Security Policy Documentation Wiki Projects Code Style Guidelines Technical Articles Web Inspector Web Developer Resources Demos Testing Regression Testing Leak Hunting Writing New Tests Getting a Crash Log Bugs Reporting Bugs Bug Report Guidelines Bug Prioritization Test Case Reduction Bug Life Cycle Archives March 2011 February 2011 January 2011 December 2010 September 2010 August 2010 July 2010 June 2010 May 2010 April 2010 March 2010 February 2010 January 2010 December 2009 November 2009 October 2009 September 2009 July 2009 June 2009 May 2009 April 2009 March 2009 February 2009 December 2008 October 2008

                                    

September 2008 June 2008 May 2008 April 2008 March 2008 February 2008 January 2008 December 2007 November 2007 October 2007 September 2007 August 2007 July 2007 June 2007 May 2007 April 2007 March 2007 February 2007 January 2007 December 2006 November 2006 October 2006 September 2006 August 2006 June 2006 May 2006 April 2006 March 2006 February 2006 January 2006 December 2005 November 2005 October 2005 September 2005 August 2005 July 2005 June 2005

WebKit is open source software with portions licensed under the LGPL and BSD licenses. Complete license and copyright information can be found within the code. Hosting provided by Mac OS Forge. Use of this site is subject to the Mac OS Forge Terms of Use. Surfin' Safari site is powered by WordPress Entries (RSS) and Comments (RSS). Register | Log in

WebCore Rendering III – Layout Basics
Posted by Dave Hyatt on Friday, August 10th, 2007 at 2:01 pm

When renderers are first created and added to the tree, they have no position or size yet. The process by which all of the boxes have their positions and sizes determined is called layout. All renderers have a layout method.
void layout()

Layout is a recursive operation. A class called FrameView represents the containing view for the document, and it also has a layout method. The frame view is responsible for managing the layout of the render tree. There are two types of layout that the FrameView can perform. The first (and by far the most common) is a layout of the entire render tree. In this case the root of the render tree has its layout method called and then the entire render tree gets updated. The second type of layout is constrained to a specific subtree of the render tree. It is used in situations where the layout of some small subtree can’t possibly affect its surroundings. Right now the subtree layout is only used by text fields (but may be used by overflow:auto blocks and other similar constructs in the future).
The Dirty Bits

Layout uses a dirty bit system to determine whether an object actually needs a layout. Whenever new renderers are inserted into the tree, they dirty themselves and the relevant links in their ancestor chain. There are three unique bits that are used by the render tree.
bool needsLayout() const { return m_needsLayout || m_normalChildNeedsLayout || m_posChildNeedsLayout; } bool selfNeedsLayout() const { return m_needsLayout; } bool posChildNeedsLayout() const { return m_posChildNeedsLayout; } bool normalChildNeedsLayout() const { return m_normalChildNeedsLayout; }

The first bit is used when the renderer itself is dirty, and it can be queried using the method selfNeedsLayout. Whenever this bit is set to true, relevant ancestor renderers have bits set indicating that they have a dirty child. The type of bit set depends on the positioned status of the previous link in the chain being dirtied. posChildNeedsLayout is used to indicate that a positioned child got dirtied. normalChildNeedsLayout is used to indicate that an in-flow child got dirtied. By distinguishing between these two types of children, layout can be optimized for the case where only positioned elements moved.
The Containing Block

What exactly did I mean by “the relevant ancestor chain”? When an object is marked as needing layout, the ancestor chain that is dirtied is based on a CSS concept called the containing block. The containing block is also used to establish the coordinate space of children. Renderers have

xPos and yPos coordinates, and these are relative to their containing blocks. So what exactly is a

containing block? Here is the CSS 2.1 spec’s introduction to the concept. My own way of introducing the concept in terms of the WebCore render tree would be as follows: A renderer’s containing block is an ancestor block of the renderer that is responsible for determining that renderer’s position. In other words when layout recurs down the render tree, it is a block’s responsibility to position all of the renderers that have it as their containing block. The root of the render tree is called the RenderView, and this class corresponds to the initial containing block according to CSS2.1. It is also the renderer that will be returned if the renderer() method is called on the Document.
RenderView.h

The initial containing block is always sized to the viewport. In desktop browsers, this is the visible area in the browser window. It is also always at position (0,0) relative to the entire document. Here’s a picture illustrating where the initial containing block is positioned for a document. The black bordered box represents the RenderView, and the grey box represents the entire document. If the document is scrolled, then the initial containing block will be moved offscreen. It is always at the top of the document and sized to the viewport. One area of confusion that people often have with the initial containing block is that they expect it to somehow be outside the document and part of the viewport. Here is the detailed containing block specification in CSS2.1. The rules can be summarized as follows:
  



The root element’s renderer (i.e., the <html> element) will always have the RenderView as its containing block. If a renderer has a CSS position of relative or static, then the containing block will be the nearest block-level ancestor in the render tree. If a renderer has a CSS position of fixed, then the containing block will be the RenderView. Technically the RenderView does not act as a viewport, so the RenderView has to adjust the coordinates of fixed positioned objects to account for the document scroll position. It is simpler to just let the RenderView act like a viewport containing block for this one case rather than having a separate renderer just for the viewport. If a renderer has a CSS position of absolute, then the containing block is the nearest block-level ancestor with a position other than static. If no such ancestor exists, then the containing block will be the RenderView.

The render tree has two convenience methods for asking if an object has a position of absolute, fixed or relative. They are:
bool isPositioned() const; // absolute or fixed positioning bool isRelPositioned() const; // relative positioning

Throughout most of the code the term positioned refers to both absolute and fixed positioned objects in CSS. The term relPositioned refers to relative positioned objects in CSS. The render tree has a method for obtaining the containing block of a renderer.
RenderBlock* containingBlock() const

When an object is marked as needing layout, it walks up a container chain setting either the normalChildNeedsLayout bit or the posChildNeedsLayout bit. The isPositioned status of the previous link in the chain determines what bit gets set. The container chain roughly corresponds to the containing block chain, although intermediate inlines are still dirtied as well. A different method called container is used instead of containingBlock to determine the chain for dirtying because of this distinction.
RenderObject* container() const

layoutIfNeeded and setNeedsLayout(false)

The layoutIfNeeded method (similar in terminology to AppKit’s displayIfNeeded method) is a convenient shorthand for telling a renderer to only do a layout if it has a dirty bit set.
void layoutIfNeeded()

All layout methods typically end with setNeedsLayout(false). It is important to clear dirty bits on the renderer before leaving the layout method, so that future layout calls won’t mistakenly think that the object is still dirty.
Anatomy of a Layout Method

At a high level layout methods usually look something like this:
void layout() { ASSERT(needsLayout()); // Determine the width and horizontal margins of this object. ... for (RenderObject* child = firstChild(); child; child = child>nextSibling()) { // Determine if the child needs to get a relayout despite the dirty bit not being set. ...

// Place the child. ... // Lay out the child child->layoutIfNeeded(); ... } // Now the intrinsic height of the object is known because the children are placed // Determine the final height ... setNeedsLayout(false); }

We will drill into specific layout methods in future articles. You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed. Comments are closed.
                        

Home Surfin’ Safari Blog Planet WebKit Project Goals Keeping in Touch Trac Contributors Meeting Working with the Code Installing Developer Tools Getting the Code Building WebKit Running WebKit Debugging WebKit Contributing Code Commit and Review Policy Security Policy Documentation Wiki Projects Code Style Guidelines Technical Articles Web Inspector Web Developer Resources Demos Testing

                                               

Regression Testing Leak Hunting Writing New Tests Getting a Crash Log Bugs Reporting Bugs Bug Report Guidelines Bug Prioritization Test Case Reduction Bug Life Cycle Archives March 2011 February 2011 January 2011 December 2010 September 2010 August 2010 July 2010 June 2010 May 2010 April 2010 March 2010 February 2010 January 2010 December 2009 November 2009 October 2009 September 2009 July 2009 June 2009 May 2009 April 2009 March 2009 February 2009 December 2008 October 2008 September 2008 June 2008 May 2008 April 2008 March 2008 February 2008 January 2008 December 2007 November 2007 October 2007 September 2007 August 2007

                        

July 2007 June 2007 May 2007 April 2007 March 2007 February 2007 January 2007 December 2006 November 2006 October 2006 September 2006 August 2006 June 2006 May 2006 April 2006 March 2006 February 2006 January 2006 December 2005 November 2005 October 2005 September 2005 August 2005 July 2005 June 2005

WebKit is open source software with portions licensed under the LGPL and BSD licenses. Complete license and copyright information can be found within the code. Hosting provided by Mac OS Forge. Use of this site is subject to the Mac OS Forge Terms of Use. Surfin' Safari site is powered by WordPress Entries (RSS) and Comments (RSS). Register | Log in

WebCore Rendering IV – Absolute/Fixed and Relative Positioning
Posted by Dave Hyatt on Tuesday, August 14th, 2007 at 1:32 pm

The position property in CSS can be used to position an object relative to a specific containing block. It has four values: ’static’, ‘absolute’, ‘fixed’ and ‘relative’. Static positioning is the default and means that the object is just positioned using the normal rules of block and line layout.
Relative Positioning

Relative positioning is exactly like static positioning except that the CSS left, top, right and bottom properties can be used to apply a translation to the object. The isRelPositioned method can be used to ask if a renderer is using relative positioning.

bool isRelPositioned() const

The translation offset that will be applied can be obtained using the following methods:
int relativePositionOffsetX() const; int relativePositionOffsetY() const;

Relative positioning is literally nothing more than a paint-time translation. As far as layout is concerned, the object is at its original position. Below is an example that uses relative positioning to shift part of a line up by a few pixels. As you can see, the line lays out as though the object was at the original position.
<div style="border:5px solid black; padding:20px; width:300px"> Here is a line of text. <span style="position:relative;top:-10px; background-color: #eeeeee"> This part is shifted<br> up a bit, </span> but the rest of the line is in its original position. </div>

Here is a line of text. This part is shifted up a bit, but the rest of the line is in its original position. Absolute and Fixed Positioning

Fixed positioned objects are positioned relative to the viewport, i.e., the visible page area of your browser window. Absolute positioned objects are positioned relative to the containing block, which is the nearest enclosing ancestor block with a position other than ’static’. If no such block exists, then the initial containing block (the RenderView) is used. For more details on containing blocks, see the previous article. The isPositioned method can be used to find out if a renderer is absolute or fixed positioned.
bool isPositioned() const

When an object is absolute/fixed positioned, it becomes block-level. Even if the CSS display type is set to inline (or inline-block/table), the effective display type becomes block-level once an object is positioned. The isInline method will return false for positioned elements. The RenderStyle can give both display values. There are times where the original display type is relevant and needed by layout, and the following methods can be used to obtain both display types.
EDisplay display() const; EDisplay originalDisplay() const;

The Positioned Objects List

Every block has a positioned objects list that contains all of the absolute/fixed positioned renderers for which it is the containing block. It is the block’s responsibility to place these positioned children. The following methods can be used to manipulate the positioned objects list:
void insertPositionedObject(RenderObject*); void removePositionedObject(RenderObject*);

The layoutOnlyPositionedObjects method is used to lay out only the positioned objects for a block. If only positioned objects changed, then this method returns true. This indicates that the layout method doesn’t have to lay out any of its normal children and can just return early.
bool layoutOnlyPositionedObjects

The layoutPositionedObjects method takes care of the placement of positioned objects. It takes a boolean argument that indicates whether relayout should be forced on all of the objects. Relayout can be necessary under a variety of circumstances that will be covered in future articles.
bool layoutPositionedObjects(bool relayoutChildren)

Coordinates of Positioned Objects

The coordinates of positioned objects in CSS are relative to the padding edge of the containing block. For example specifying a left and top position of (0, 0) for an absolute positioned object will result in the object being placed just inside the containing block’s top left border. Here is an example:
<div style="position:relative;border:5px solid black;width:300px;height:300px;"> <div style="position:absolute;width:200px;height:200px;backgroundcolor:purple"></div> </div>

In WebCore, coordinate positions are always relative to the border edge, so in the above example, the object is actually at (5, 5). When the desired coordinates are omitted from CSS, WebCore has to determine an appropriate place for the positioned object. CSS has a set of extremely complex rules for this, which we will delve into in more detail in future articles.
Inline Relative Positioned Containers

It is possible for a relative positioned inline to act as a “containing block” for an absolutely positioned descendant. This is another extremely complex edge case that warrants its own article. For now it is enough to know that such a construct is possible, and that the code does have to deal with it.

You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed. Comments are closed.
                                          

Home Surfin’ Safari Blog Planet WebKit Project Goals Keeping in Touch Trac Contributors Meeting Working with the Code Installing Developer Tools Getting the Code Building WebKit Running WebKit Debugging WebKit Contributing Code Commit and Review Policy Security Policy Documentation Wiki Projects Code Style Guidelines Technical Articles Web Inspector Web Developer Resources Demos Testing Regression Testing Leak Hunting Writing New Tests Getting a Crash Log Bugs Reporting Bugs Bug Report Guidelines Bug Prioritization Test Case Reduction Bug Life Cycle Archives March 2011 February 2011 January 2011 December 2010 September 2010 August 2010 July 2010

                                               

June 2010 May 2010 April 2010 March 2010 February 2010 January 2010 December 2009 November 2009 October 2009 September 2009 July 2009 June 2009 May 2009 April 2009 March 2009 February 2009 December 2008 October 2008 September 2008 June 2008 May 2008 April 2008 March 2008 February 2008 January 2008 December 2007 November 2007 October 2007 September 2007 August 2007 July 2007 June 2007 May 2007 April 2007 March 2007 February 2007 January 2007 December 2006 November 2006 October 2006 September 2006 August 2006 June 2006 May 2006 April 2006 March 2006 February 2006 January 2006

      

December 2005 November 2005 October 2005 September 2005 August 2005 July 2005 June 2005

WebKit is open source software with portions licensed under the LGPL and BSD licenses. Complete license and copyright information can be found within the code. Hosting provided by Mac OS Forge. Use of this site is subject to the Mac OS Forge Terms of Use. Surfin' Safari site is powered by WordPress Entries (RSS) and Comments (RSS). Register | Log in

WebCore Rendering V – Floats
Posted by Dave Hyatt on Wednesday, August 15th, 2007 at 4:33 pm

A float is a renderer that is designed to shift all the way to the left side or all the way to the right side of a paragraph. The lines of the paragraph then flow around the floating object avoiding it. You can see an example of a float in this very paragraph. There is a purple box in the upper right hand corner. Note how all of the text in this paragraph is avoiding the float. Here is how the purple float above was declared:
<div style="float:right; width:50px; height:50px; background-color:purple; margin-left: 5px"></div>

There are also HTML constructs that imply CSS floating behavior. For example, the align attribute on the img element can be used to float an image.
<img align=left src="...">

A float can span multiple paragraphs. In this example, even though the float was declared inside this paragraph, it is tall enough that it will protrude out of this paragraph and into the next one. Because floats can effectively intersect multiple blocks, WebCore uses a floating objects list on block flows to track all of the floating renderers that intrude into the bounds of that block. A single float can therefore be in the floating objects lists of multiple block flows. Line layout has to be aware of the positions of floats so that it can make sure to shrink lines as necessary to avoid these floats. By having all of the relevant floats for a given block immediately accessible in this floating objects list, it becomes easy for that block to know where the floats are that it needs to avoid. A floating objects list contains the following data structure:

struct FloatingObject { enum Type { FloatLeft, FloatRight }; FloatingObject(Type type) : node(0) , startY(0) , endY(0) , left(0) , width(0) , m_type(type) , noPaint(false) { } Type type() { return static_cast<type>(m_type); } RenderObject* node; int startY; int endY; int left; int width; unsigned m_type : 1; // Type (left or right aligned) bool noPaint : 1; };

As you can see, this structure effectively contains a rectangle (a top, bottom, left and width). The reason each list entry has its own position and size that is independent of the floating object’s position and size is that these coordinates are in the space of the block that owns the floating objects list. This way each block can easily query for the float’s position in its own coordinate space without having to do a bunch of conversions. In addition the margins of the float are included in the list entry rectangles, since lines don’t just avoid the border box of the float. They avoid the margin box of the float. This is important so that floats can be padded with extra space to avoid having lines run right up to their edges. The following methods operate on the floating objects list:
void void void void insertFloatingObject(RenderObject*); removeFloatingObject(RenderObject*); clearFloats(); positionNewFloats();

The first two functions are pretty self-explanatory. They are used to add and remove specific floats from a block’s floating objects list. clearFloats will delete all of the objects in a block’s floating objects list. When an object gets inserted into the list it is unpositioned initially. Its vertical position is set to -1. The positionNewFloats method is called by layout to place all of the floats. CSS has a

bunch of rules for where floats are allowed to go. It is this method that ensures that all of those rules are obeyed. There are many more helper methods for working with floats. I will cover these when I talk about block and line layout in more detail in future articles.
Clearance

CSS provides a way for objects to specify that they should be below either all left floats, all right floats, or all floats. The clear property specifies this behavior and has values of none, left, right or both.
This paragraph is below the blue float from the previous paragraph because it specified clear: left. Clearance is computed and applied during block and line layout. The clear property can also be applied to floats to make sure that a float ends up below all previous floats (again, either left, right or both types of floats).

You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.
4 Responses to “WebCore Rendering V – Floats” 1. RichB Says:
August 16th, 2007 at 1:28 am

I’m surprised the concept of the Block Formatting Context wasn’t mentioned during the Clearance discussion. This is one of the least known about concepts in CSS and yet it is vitally important when writing stylesheets in order to isolate one visual style from another. Hint: Clearance isn’t just about a clear:left CSS property. It can also be achieved by leaving a block formatting context.
2. hyatt Says:
August 16th, 2007 at 2:32 am

These initial articles are merely overviews, and are not intended to delve deeply into any one topic yet.
3. Pingback from Around the Browsersphere #2:
September 5th, 2007 at 2:08 am

[...] Dave Hyatt has posted five detailed articles on WebCore rendering. [...]
4. Pingback from Another Caffeinated Day:
September 9th, 2007 at 10:46 am

[...] posted some excellent articles on how a web browser actually works behind the scenes on things like floats, positioning and more, at webkit.org. The code gymnastics that a properly rendering browser has to [...]
                                           

Home Surfin’ Safari Blog Planet WebKit Project Goals Keeping in Touch Trac Contributors Meeting Working with the Code Installing Developer Tools Getting the Code Building WebKit Running WebKit Debugging WebKit Contributing Code Commit and Review Policy Security Policy Documentation Wiki Projects Code Style Guidelines Technical Articles Web Inspector Web Developer Resources Demos Testing Regression Testing Leak Hunting Writing New Tests Getting a Crash Log Bugs Reporting Bugs Bug Report Guidelines Bug Prioritization Test Case Reduction Bug Life Cycle Archives March 2011 February 2011 January 2011 December 2010 September 2010 August 2010 July 2010 June 2010

                                               

May 2010 April 2010 March 2010 February 2010 January 2010 December 2009 November 2009 October 2009 September 2009 July 2009 June 2009 May 2009 April 2009 March 2009 February 2009 December 2008 October 2008 September 2008 June 2008 May 2008 April 2008 March 2008 February 2008 January 2008 December 2007 November 2007 October 2007 September 2007 August 2007 July 2007 June 2007 May 2007 April 2007 March 2007 February 2007 January 2007 December 2006 November 2006 October 2006 September 2006 August 2006 June 2006 May 2006 April 2006 March 2006 February 2006 January 2006 December 2005

     

November 2005 October 2005 September 2005 August 2005 July 2005 June 2005

WebKit is open source software with portions licensed under the LGPL and BSD licenses. Complete license and copyright information can be found within the code. Hosting provided by Mac OS Forge. Use of this site is subject to the Mac OS Forge Terms of Use. Surfin' Safari site is powered by WordPress Entries (RSS) and Comments (RSS). Register | Log in

How WebKit Loads a Web Page
Posted by abarth on Sunday, April 18th, 2010 at 1:57 pm

Before WebKit can render a web page, it needs to load the page and all of its subresources from the network. There are many layers involved in loading resources from the web. In this post, I’ll focus on explaining how WebCore, the main rendering component of WebKit, is involved in the loading process. WebKit contains two loading pipelines, one for loading documents into frames and another for loading the subresources (such as images and scripts). The diagram below summarizes the major objects involved in the two pipelines:

Loading Frames
The FrameLoader is in charge of loading documents into Frames. Whenever you click a link, the FrameLoader begins by creating a new DocumentLoader object in the “policy” state, where it awaits a decision by the WebKit client about how it should handle this load. Typically, the client will instruct the FrameLoader to treat the load as a navigation (instead of blocking the load, for example).

Once the client instructs the FrameLoader to treat the load as a navigation, the FrameLoader advances the DocumentLoader to the “provisional” state, which kicks off a network request and waits to determine whether the network request will result in a download or a new document. The DocumentLoader, in turn, creates a MainResourceLoader, whose job is to interact with the platform’s network library via the ResourceHandle interface. Separating the MainResourceLoader from DocumentLoader serves two purposes: (1) the MainResourceLoader insulates the DocumentLoader from details of handling the callbacks from the ResourceHandle and (2) the lifetime of the MainResourceLoader is decoupled from the lifetime of the DocumentLoader (which is tied to the Document). Once the loading system has received sufficient information from the network to determine that the resource actually represents a document, the FrameLoader advances the DocumentLoader to the “committed” state, which transitions the Frame to displaying the new document.

Loading Subresources
Of course, displaying a web page requires more than just the HTML that comprises the document. We also need to load the images, scripts, and other subresources referenced by the document. The DocLoader is in charge of loading these subresources. (Note that although DocumentLoader and DocLoader have similar names, their roles are quite different.) Let’s take loading an image as a typical example. To load an image, the DocLoader first asks the Cache whether it already has a copy of the image in memory (as a CachedImage object). If the image is already in the Cache, the DocLoader can respond immediately with the image. For even greater efficiency, the Cache often keeps the decoded image in video memory so that WebKit does not have to uncompress the same image twice. If the image is not in the Cache, the Cache creates a new CachedImage object to represent the image. The CachedImage object asks the “Loader” object to kick off a network request, which the Loader does by creating a SubresourceLoader. The SubresourceLoader plays a similar role in the subresource loading pipeline as the MainResourceLoader does in the main resource loading pipeline in that it interacts most directly with the ResourceHandle interface to the platform.

Areas for Improvement
There are many areas in which we can improve WebKit’s loading pipelines. The FrameLoader is significantly more complex than necessary and encompasses more tasks than simply loading a frame. For example, FrameLoader has a several subtly different methods named “load,” which can be confusing, and is responsible for creating new windows, which seems only tangentially related to loading a frame. Also, the various stages of the loading pipeline are more tightly coupled than necessary and there are a number of “layering” violations in which a lower-level object interacts directly with a higher-level object. For example, the MainResourceLoader delivers bytes received from the network directly to FrameLoader instead of delivering them to DocumentLoader.

If you study the diagram above, you will notice that the Cache is used only for subresources. In particular, main resource loads do not get the benefits of WebKit’s memory cache. If we can unify these two loading pipelines, we might be able to improve the performance of main resource loads. Over time, we hope to improve the performance of the loader to make loading web pages as fast as possible. You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.
3 Responses to “How WebKit Loads a Web Page” 1. tomwang Says:
April 22nd, 2010 at 1:33 am

Can you please provide some overall code pieces about this process?
2. smkolins Says:
April 22nd, 2010 at 5:57 am

Hi. While I use Webkit I’m not so much a programmer. I found that at least with the current Webkit I cannot comment on blogspot.com websites. It works in Safari 4.0.5 and Firefox but not in the current nightly build. I know it should be a bug report but the qualificiations for such reporting seem to be beyond me as I’m not so much a programmer.
3. smkolins Says:
April 22nd, 2010 at 6:04 am

I checked with r58082 and it still doesn’t work. See for example
                

Home Surfin’ Safari Blog Planet WebKit Project Goals Keeping in Touch Trac Contributors Meeting Working with the Code Installing Developer Tools Getting the Code Building WebKit Running WebKit Debugging WebKit Contributing Code Commit and Review Policy Security Policy Documentation

                                               

Wiki Projects Code Style Guidelines Technical Articles Web Inspector Web Developer Resources Demos Testing Regression Testing Leak Hunting Writing New Tests Getting a Crash Log Bugs Reporting Bugs Bug Report Guidelines Bug Prioritization Test Case Reduction Bug Life Cycle Archives March 2011 February 2011 January 2011 December 2010 September 2010 August 2010 July 2010 June 2010 May 2010 April 2010 March 2010 February 2010 January 2010 December 2009 November 2009 October 2009 September 2009 July 2009 June 2009 May 2009 April 2009 March 2009 February 2009 December 2008 October 2008 September 2008 June 2008 May 2008 April 2008

                                

March 2008 February 2008 January 2008 December 2007 November 2007 October 2007 September 2007 August 2007 July 2007 June 2007 May 2007 April 2007 March 2007 February 2007 January 2007 December 2006 November 2006 October 2006 September 2006 August 2006 June 2006 May 2006 April 2006 March 2006 February 2006 January 2006 December 2005 November 2005 October 2005 September 2005 August 2005 July 2005 June 2005

WebKit is open source software with portions licensed under the LGPL and BSD licenses. Complete license and copyright information can be found within the code. Hosting provided by Mac OS Forge. Use of this site is subject to the Mac OS Forge Terms of Use. Surfin' Safari site is powered by WordPress Entries (RSS) and Comments (RSS). Register | Log in

WebKit Page Cache I – The Basics
Posted by Brady Eidson on Wednesday, September 16th, 2009 at 4:47 pm

This is the first of two posts that will center around a modern browser engine feature that doesn’t usually get a lot of press: The Page Cache.

Today I’ll talk a bit about what this feature is, why it often doesn’t work, and what plans we have to improve it.
Page Cache Overview

Some of you might be more familiar with what other browsers call their Page Cache. Firefox calls theirs the “Back-Forward Cache” or “bfcache.” Opera refers to theirs as “Fast History Navigation.” We’ve recently started to refer to WebKit’s implementation as the “Page Cache” to reduce confusion with our “Back/Forward List.” Note that the Page Cache is an end user feature that makes navigating the web much smoother. It is not a “cache” in the “HTTP sense“. It is not a “cache” in the “disk cache” sense where raw resources are stored on the local disk. And it’s not a “cache” in the traditional “memory cache” sense where WebKit keeps decoded resources around in memory to be shared between multiple web pages. So… what *exactly* is it? Quite simply, the Page Cache makes it so when you leave a page we “pause” it and when you come back we press “play.” When a user clicks a link to navigate to a new page the previous page is often thrown out completely. The DOM is destroyed, Javascript objects are garbage collected, plug-ins are torn down, decoded image data is thrown out, and all sorts of other cleanup occurs. When this happens and the user later clicks the back button it can be painful for them. WebKit may have to re-download the resources over the network, re-parse the main HTML file, re-run the scripts that dynamically setup the page, re-decode image data, re-layout the page, re-scroll to the right position, and re-paint the screen. All of this work requires time, CPU usage, and battery power. Ideally the previous page can instead be placed in the Page Cache. The entire live page is kept in memory even though it is not on screen. This means that all the different bits and pieces that represent what you see on the screen and how you interact with it are suspended instead of destroyed. They can then be revived later in case you click the back button.
Why is This Important?

When the Page Cache works it makes clicking the back button almost instantaneous. You can do a search, click a search result, then go back and immediately be looking at the exact same results page. You might be browsing an aggregator site like Reddit or Digg and want to rapidly view a lot of different links in the same tab. You might be navigating an image gallery and decide to compare two images by alternately clicking “back” and “forward” rapidly. Or you might have simply clicked on the wrong link and want to go back to correct your mistake.

Anytime you might click the back button or the forward button you unknowingly hope the Page Cache is on your side. When the Page Cache is used, users are happy even though they’re not aware of the magic behind the scenes. Conversely, when the Page Cache is bypassed, users often get frustrated with both the browser and the Web in general.
Why Wouldn’t it Work?

So if the Page Cache is so amazing, why doesn’t WebKit always use it when you navigate to a new page? There’s a few main answers to that question.
Some Pages aren’t Interesting

First off, sometimes it doesn’t make sense to cache a page because it’s not interesting to return to in the exact same state. For example, the page might not even be finished loading yet. Or the page might’ve had an error loading. Or maybe the page was a redirection page that exists solely to automatically move the user to some new URL. These are cases where we’re happy with the current Page Cache behavior in WebKit.
Some Pages are Complicated

Secondly, a page might not be considered for the Page Cache because it’s difficult to figure out how to “pause” it. This happens with more complex pages that do interesting things. For example, plug-ins contain native code that can do just about anything it wants so WebKit can’t “hit the pause button” on them. Another example is pages with multiple frames which WebKit has historically not cached. Distressingly, navigating around these more advanced pages would benefit the most from the Page Cache.
Some Pages are Secure

Server administrators for HTTPS sites often have particular security concerns and are very sensitive with regards to how browsers behave. For example, Financial institutions are often very thorough in verifying each particular browser’s behavior before allowing it to be used by their customers. One area often focused on is back/forward behavior. Such institutions are – understandably – very picky about the types of data left behind in the browser as a user navigates. As a result, in an effort to err on the side of extreme caution, WebKit has disallowed all HTTPS sites from its Page Cache since the very beginning.

A more fine grained approach might go a long way towards improving the user experience.
Planned Improvements

Clearly there’s some important cases we don’t handle and therefore plenty of room for improvement. WebKit’s Page Cache was originally written in 2002 before the very first Safari beta release. Its capabilities reflected both the architecture of WebKit at the time and the landscape of the Web in 2002. The Web of 2009 is a much different place and we need to bring the Page Cache up to par. Fortunately this work is well underway. For example, as of revision 48036 a major limitation was resolved and pages with frames are now placed in the Page Cache. Browsing with the latest WebKit nightly always seems to “feel faster” in ways you can’t quite put your finger on, and recently some of you might have been experiencing this enhancement. But there’s plenty more work to do. Plug-ins are the next huge one on our hit list. As I mentioned earlier, plug-ins can run whatever native code they like so we can’t reliably hit the “pause” button on them. Earlier versions of WebKit handled single-frame pages with some types of plug-ins. WebKit would tear down the plug-in when leaving the page and restoring it when the user returned. But as work continued on WebCore to make it faster and easier to port, this ability was lost. Bug #13634 tracks getting this working again for all plug-ins on all pages. Then there are HTTPS pages. We completely ban them now, but a more selective approach should be able to benefit users as well as keep security-minded institutions happy. Bug #26777 tracks allowing HTTPS pages to be cached unless their response headers include “cache-control: no-store” or “cache-control: no-cache” which has become the canonical way for a selective organization to secure your content. If you have any other ideas for what else might be improved, please feel free to comment in the appropriate bug or file a new bug of your own!
Unload Handlers

One thing I haven’t mentioned is pages with unload event handlers. The unload event was designed to let a page do some cleanup work when the user closes the page.

The browser can’t fire the unload event before it puts the page in the Page Cache, because the page then assumes it is in a terminal state and might destroy critical parts of itself. This completely defeats the purpose of the Page Cache. But if the browser puts the page in the Page Cache without running the unload handler, then the page might be destroyed by the browser while it is “paused” and hidden, and that cleanup work – which might be very important – will never happen. Since the unload event’s purpose is to allow “important work when a page is closed,” all major browsers refuse to put such pages in their Page Cache, causing a direct negative impact on the user experience. In a future post I’ll be talking more about unload event handlers and there will actually be homework for many of you web developers out there! Stay tuned… You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.
8 Responses to “WebKit Page Cache I – The Basics” 1. Miles Says:
September 16th, 2009 at 9:44 pm

Spoilers: https://bugs.webkit.org/show_bug.cgi?id=29021
2. CyberSkull Says:
September 17th, 2009 at 1:51 am

Hmm, perhaps what we need is something like a cache handler for JS and plugins; Ideally to do whatever cleanup or state changes for going into cache and coming out of it…
3. Brady Eidson Says:
September 17th, 2009 at 1:03 pm

CyberSkull, you’re exactly right and I strongly recommend you keep your eyes out for part 2.
4. jomohke Says:
September 18th, 2009 at 4:55 am

It’s fantastic to see the return of technical articles detailing the innards of webkit. They stopped appearing when this blog moved from just David Hyatt to an official team blog. Please give us more!
5. Adrian Russell-Falla Says:
September 18th, 2009 at 9:47 am

Brady, I fervently second jomohke’s request! looking fwd to Part 2.
6. kangax Says:
September 18th, 2009 at 7:48 pm

Unfortunately, in Prototype.js we always attach an “unload” handler in WebKit. This is due to a bug in some of the earlier versions of WebKit, where returning to a page via “page cache” would wipe-off all of the expandos on host objects (e.g. from the `document`). Since Prototype.js extends these host objects with custom methods, there was chaos all over the place : ) See this ticket for more info – What’s even more disappointing is that we use browser sniffing as it seems impossible to feature test this quirk. I suppose disabling unload in newer WebKit wouldn’t affect Prototype, as long as document state persists properly (and it does in newer versions). I would also love to hear if there’s a saner work around for this issue (i.e. any kind of inference we can perform, to replace fragile `userAgent` parsing).
7. kangax Says:
September 18th, 2009 at 7:48 pm

Link got stripped, here it is again – http://dev.rubyonrails.org/ticket/11430
8. nhoel Says:
September 20th, 2009 at 4:50 am

@kangax THANKS FOR THAT LINK @adrian I THIRD DEMOTION thanks, -Nhoel of http://keywordspeak.com/?p=1234
          

Home Surfin’ Safari Blog Planet WebKit Project Goals Keeping in Touch Trac Contributors Meeting Working with the Code Installing Developer Tools Getting the Code Building WebKit

                                               

Running WebKit Debugging WebKit Contributing Code Commit and Review Policy Security Policy Documentation Wiki Projects Code Style Guidelines Technical Articles Web Inspector Web Developer Resources Demos Testing Regression Testing Leak Hunting Writing New Tests Getting a Crash Log Bugs Reporting Bugs Bug Report Guidelines Bug Prioritization Test Case Reduction Bug Life Cycle Archives March 2011 February 2011 January 2011 December 2010 September 2010 August 2010 July 2010 June 2010 May 2010 April 2010 March 2010 February 2010 January 2010 December 2009 November 2009 October 2009 September 2009 July 2009 June 2009 May 2009 April 2009 March 2009 February 2009

                                      

December 2008 October 2008 September 2008 June 2008 May 2008 April 2008 March 2008 February 2008 January 2008 December 2007 November 2007 October 2007 September 2007 August 2007 July 2007 June 2007 May 2007 April 2007 March 2007 February 2007 January 2007 December 2006 November 2006 October 2006 September 2006 August 2006 June 2006 May 2006 April 2006 March 2006 February 2006 January 2006 December 2005 November 2005 October 2005 September 2005 August 2005 July 2005 June 2005

WebKit is open source software with portions licensed under the LGPL and BSD licenses. Complete license and copyright information can be found within the code. Hosting provided by Mac OS Forge. Use of this site is subject to the Mac OS Forge Terms of Use. Surfin' Safari site is powered by WordPress Entries (RSS) and Comments (RSS). Register | Log in

WebKit Page Cache II – The unload Event
Posted by Brady Eidson on Monday, September 21st, 2009 at 4:29 pm

Previously I touched on what exactly the Page Cache does and outlined some of the improvements we’re working on. This post is geared towards web developers and is therefore even more technical than the last. In this article I’d like to talk more about unload event handlers, why they prevent pages from going into the Page Cache, and what can be done to make things better.
Load/Unload Event Handlers

Web developers can make use of the load and unload events to do work at certain points in the lifetime of a web page. The purpose of the load event is quite straightforward: To perform initial setup of a new page once it has loaded. The unload event is comparatively mysterious. Whenever the user leaves a page it is “unloaded” and scripts can do some final cleanup. The mysterious part is that “leaving the page” can mean one of a few things:
1. The user closes the browser tab or window, resulting in the destruction of the visible page. 2. The browser navigates from the old page to a new page, resulting in the destruction of the old visible page.

The Page Cache makes this even more interesting by adding a new navigation possibility:
3. The browser navigates from the old page to a new page, but the old visible page is suspended, hidden, and placed in the Page Cache. The Status Quo

Unload event handlers are meant to do some final cleanup when the visible page is about to be destroyed. But if the page goes into the Page Cache it becomes suspended, is hidden, and is not immediately torn down. This brings up interesting complications. If we fire the unload event when going into the Page Cache, then the handler might be destructive and render the page useless when the user returns. If we fire the unload event every time a page is left, including each time it goes into the Page Cache and when it is eventually destroyed, then the handler might do important work multiple times that it was critical to only do once.

If we don’t fire the unload event when going into the Page Cache, then we face the possibility that the page will be destroyed while it is suspended and hidden, and the unload handler might never be run. If we don’t fire the unload event when going into the Page Cache but consider firing it whenever the suspended page is eventually destroyed, then we’re considering the possibility of doing something that’s never been done before: Executing scripts that belong to an invisible web page that has had its “pause” button pressed. There’s all sorts of obstacles in making this work well including technological hurdles, security concerns, and user-experience considerations. Since there is no clear solution for handling such pages the major browsers vendors have all come to the same conclusion: Don’t cache these pages.
How You Can Help

Web developers have a few things they can do to help their pages be cacheable. One is to only install the unload event handler if the code is relevant to the current browser. For example, we’ve seen unload handlers similar to the following:
function unloadHandler() { if (_scriptSettings.browser.isIE) { // Run some unload code for Internet Explorer ... } }

In all browsers other than Internet Explorer this code does nothing, but its mere existence potentially slows down their user experience. This developer should’ve done the browser check *before* installing the unload handler. Another way developers can improve things is to only install the unload event handler when the page has a need to listen for it, then remove it once that reason has passed. For example the user might be working on a draft of a document so the developer installs an unload handler to make sure the draft gets saved before the page is left. But they also start a timer to automatically save it every minute or so. If the timer fires, the document draft is saved, and the user doesn’t make any further changes, the unload handler should be removed. Particularly savvy developers might consider a third option.

A Replacement For Unload

Some time ago Mozilla approached this problem differently by inventing a replacement for load/unload events. The load and unload events are meant to be fired exactly once, and this is the underlying cause of the problem. The pageshow/pagehide events – which we’ve implemented in WebKit as of revision 47824 – address this. Despite their name the pageshow/pagehide events don’t have anything to do with whether or not the page is actually visible on the screen. They won’t fire when you minimize the window or switch tabs, for example. What they do is augment load/unload to work in more situations involving navigation. Consider this example of how load/unload event handlers might be used:
<html> <head> <script> function pageLoaded() { alert("load event handler called."); } function pageUnloaded() { alert("unload event handler called."); } window.addEventListener("load", pageLoaded, false); window.addEventListener("unload", pageUnloaded, false); </script> <body> <a href="http://www.webkit.org/">Click for WebKit</a> </body> </html>

Click here to view this example in a new window, in case you can’t guess what it does. Try clicking the link to leave the page then press the back button. Pretty straightforward. The pageshow/pagehide fire when load/unload do, but also have one more trick up their sleeve. Instead of firing only at the single discrete moment when a page is “loaded” the pageshow event is also fired when pages are restored from the Page Cache. Similarly the pagehide event fires when the unload event fires but also when a page is suspended into the Page Cache.

By including an additional property on the event called “persisted” the events tell the page whether they represent the load/unload events or saving/restoring from the Page Cache. Here’s the same example using pageshow/pagehide:
<html> <head> <script> function pageShown(evt) { if (evt.persisted) alert("pageshow event handler called. The page was just restored from the Page Cache."); else alert("pageshow event handler called for the initial load. This is the same as the load event."); } function pageHidden(evt) { if (evt.persisted) alert("pagehide event handler called. The page was suspended and placed into the Page Cache."); else alert("pagehide event handler called for page destruction. This is the same as the unload event."); } window.addEventListener("pageshow", pageShown, false); window.addEventListener("pagehide", pageHidden, false); </script> <body> <a href="http://www.webkit.org/">Click for WebKit</a> </body> </html>

Click here to view this example in a new window, but make sure you’re using a recent WebKit nightly. Remember to try clicking the link to leave the page then press the back button. Pretty cool, right?
What These New Events Accomplish

The pagehide event is important for two reasons:
1. It enables web developers to distinguish between a page being suspended and one that is being destroyed. 2. When used instead of the unload event, it enables browsers to use their page cache.

It’s also straightforward to change existing code to use pagehide instead of unload. Here is an example of testing for the onpageshow attribute to choose pageshow/pagehide when supported, falling back to load/unload when they’re not:
<html> <head> <script> function myLoadHandler(evt) { if (evt.persisted) { // This is actually a pageshow event and the page is coming out of the Page Cache. // Make sure to not perform the "one-time work" that we'd normally do in the onload handler. ... return; } // This is either a load event for older browsers, // or a pageshow event for the initial load in supported browsers. // It's safe to do everything my old load event handler did here. ... } function myUnloadHandler(evt) { if (evt.persisted) { // This is actually a pagehide event and the page is going into the Page Cache. // Make sure that we don't do any destructive work, or work that shouldn't be duplicated. ... return; } // This is either an unload event for older browsers, // or a pagehide event for page tear-down in supported browsers. // It's safe to do everything my old unload event handler did here. ... } if ("onpagehide" in window) { window.addEventListener("pageshow", myLoadHandler, false); window.addEventListener("pagehide", myUnloadHandler, false); } else { window.addEventListener("load", myLoadHandler, false); window.addEventListener("unload", myUnloadHandler, false); } </script> <body> Your content goes here! </body>

</html>

Piece of cake!
How You Can Help: Revisited

To reiterate, we’ve now identified three great ways web developers can help the Page Cache work better:
1. Only install the event handler if the code is relevant to the current browser. 2. Only install the event handler once your page actually needs it. 3. If supported by the browser, use pagehide instead.

Web developers that willfully ignore any or all these options are primarily accomplishing one thing: Forcing their users into “slow navigation mode.” I say this both as a browser engineer and a browser user: That stinks!
The Plot Thickens

But now that we’ve covered what savvy and polite web developers can do to help in the future, we need to further scrutinize the current state of the web. Browsers treat the unload handler as sacred because it is designed to do “important work.” Unfortunately many popular sites have unload event handlers that decidedly do not “do important work.” I commonly see handlers that:
   

Always update some cookie for tracking, even though it’s already been updated. Always send an XHR update of draft data to a server, even though it’s already been sent. Do nothing that could possible persist to any future browsing session. That are empty. They literally do nothing.

Since these misbehaved pages are very common and will render improvements to WebKit’s Page Cache ineffective a few of us started to ask the question: What *would* actually happen if we simply started admitting these pages to the Page Cache without running the unload event handler first? What would break? Can we detect any patterns to determine whether an unload event handler is “important” or not?
Our Experiment

You never know for sure until you try.

Starting in revision 48388 we’ve allowed pages with unload handlers into the Page Cache. If a user closes the window while the page is visible, the unload event will fire as usual. But the unload event will not be fired as normal when the user navigates away from the page. If the user closes the window while the page is suspended and in the Page Cache, the unload event handler will never be run. What this means for users is that their navigation experience could be noticeably smoother and quicker in the common case. What this means for developers is that we’re consciously deciding not to run some of their code and their web application might break. For users and developers alike – Please leave your feedback, observations, or suggestions in the bug tracking this experiment. And remember this is just an experiment. No one is planning to ship this drastic change in behavior in a production product. But the Page Cache is such an important part of browser performance that we’re willing to push the envelope a little to improve it a lot. We want to learn what breaks. We want to know if we can heuristically determine if an unload handler is truly critical or not. We want to know if we can detect certain patterns in some types of unload handlers and treat them differently. And, perhaps most importantly, we want to evangelize. At least one popular Javascript library has already adopted some of the advice we’ve given to help improve the landscape on the web. If just a few more developers for popular sites or libraries take notice of this experiment and change their code then the web will be a much friendlier place for all of us. You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.
6 Responses to “WebKit Page Cache II – The unload Event” 1. doekman Says:
September 22nd, 2009 at 2:22 am

I would call it the “Page Flip Cache”…
2. Jake Archibald Says:
September 22nd, 2009 at 4:50 am

BBC Glow has avoided adding an unload listener since 1.6 to avoid breaking this cache. As for my thoughts on the issue, here’s a partial reposting from https://bugs.webkit.org/show_bug.cgi?id=29021

You could save the page to the page cache, then fire the unload event and navigate away. If back is clicked, the page will be returned in the state it was BEFORE unload was fired. This gives you the best of both worlds. (this was suggested in Chrome’s bug tracker) Also, (and webkit may do this already) you need to make sure the element that the mouse is currently over has its mouseout event fired, else you might get sticky hover effects. Jake.
3. Yuan Song Says:
September 22nd, 2009 at 10:11 am

To fire the unload event whenever the suspended page is eventually destroyed could be a good idea. I don’t think executing scripts in an invisible page is a problem, since the ability of executing scripts in the background can bring other potential benefits in the future.
4. randallfarmer Says:
September 25th, 2009 at 12:28 am

As a user, I like more aggressive page caching. One approach might be to look for a small class of onunload handlers that are generally safe to ignore, like Prototype’s and empty handlers. As a Web developer, I’ve sometimes specifically wanted to turn off the back/forward cache. For example, I sometimes have an onsubmit handler — not an onunload! — that leaves the page in an unusable state, e.g., by disabling the submit button. (That means my form is broken if the user starts to submit then immediately hits Esc.) When the user hits Back, I’d rather they see the page as it was at load time (but with form data filled in), not as it was after submit. In an ideal world, I’d want them to see the page as it was just before they hit Submit, but that’s not feasible to do. Right now, I avoid the page cache by adding an empty onunload handler to disable the page cache, but that will break. As alternatives, I could add a cache-control header, or call window.location.reload() in onpageshow if evt.persisted. Both approaches have the downside of forcing the page’s HTML to be redownloaded as well as skipping the page cache. What do you all think is the best thing to do if I want to opt out of the page cache but am OK with the browser using the cached HTML? I know there are more elegant options than opting out of the page cache, like just not messing with the form in my onsubmit handler or “fixing” the form in onpageshow. Still, it seems interesting to ponder what to do if you want to opt out of the page cache; surely someone out there will.
5. Brady Eidson Says:
September 25th, 2009 at 9:02 am

@randalfarmer It would stink if you had to take some action to disable the page cache full-time when you only really want it disabled in this one edge case. As mentioned in the post, developers should only install unload handlers when they actually need them to be installed. Do you install an unload handler full-time, or do you install it only in onsubmit? If there were some other programatic way to disable the PageCache, that would still be desirable to the unload handler. Semantically, the “unload handler” and “I want to disable the PageCache!” are two completely different things. Opera invented “history.navigationMode” for this reason. We might consider implementing that (https://webkit.org/b/29739) but I would shudder if developers just started flipping the switch at page load and left it on the whole time! Of course, maybe that wouldn’t be much different than the situation today…
6. randallfarmer Says:
September 25th, 2009 at 2:31 pm

@Brady: In my defense, the pages I’m thinking of are essentially one big form, and if you leave the page, you’re usually either submitting or never coming back (e.g., closing the window). The onunload is there full-time for these pages right now (I might fix!), but navigating away without submitting and then coming back is rare enough that slowing down that case is bearable, if sloppy. Thanks much for considering history.navigationMode and for wading through my longwinded comment. I think you distilled it right: some folks could use an “explicit, semantically precise” way to tell the browser they’ve destroyed the DOM. You’re also right that we’ll inevitably sometimes use it in ways that make the page slower than is strictly necessary — sorry. Browser developers put up with a lot of nonsense from Web developers — we owe you one. Or rather, we owe you many many.

         

Home Surfin’ Safari Blog Planet WebKit Project Goals Keeping in Touch Trac Contributors Meeting Working with the Code Installing Developer Tools Getting the Code

                                               

Building WebKit Running WebKit Debugging WebKit Contributing Code Commit and Review Policy Security Policy Documentation Wiki Projects Code Style Guidelines Technical Articles Web Inspector Web Developer Resources Demos Testing Regression Testing Leak Hunting Writing New Tests Getting a Crash Log Bugs Reporting Bugs Bug Report Guidelines Bug Prioritization Test Case Reduction Bug Life Cycle Archives March 2011 February 2011 January 2011 December 2010 September 2010 August 2010 July 2010 June 2010 May 2010 April 2010 March 2010 February 2010 January 2010 December 2009 November 2009 October 2009 September 2009 July 2009 June 2009 May 2009 April 2009 March 2009

                                       

February 2009 December 2008 October 2008 September 2008 June 2008 May 2008 April 2008 March 2008 February 2008 January 2008 December 2007 November 2007 October 2007 September 2007 August 2007 July 2007 June 2007 May 2007 April 2007 March 2007 February 2007 January 2007 December 2006 November 2006 October 2006 September 2006 August 2006 June 2006 May 2006 April 2006 March 2006 February 2006 January 2006 December 2005 November 2005 October 2005 September 2005 August 2005 July 2005 June 2005

WebKit is open source software with portions licensed under the LGPL and BSD licenses. Complete license and copyright information can be found within the code. Hosting provided by Mac OS Forge. Use of this site is subject to the Mac OS Forge Terms of Use.

Surfin' Safari site is powered by WordPress Entries (RSS) and Comments (RSS). Register | Log in

How a DOM Element is Attached

The implementation of Node::attach() is just a recursive depth-first traversal. However, Element::attach() does a bit more, also creating a renderer (if necessary) and resolving style for the element. This diagram illustrates how it happens, showing relationships between the objects involved.

Sponsor Documents

Or use your account on DocShare.tips

Hide

Forgot your password?

Or register your new account on DocShare.tips

Hide

Lost your password? Please enter your email address. You will receive a link to create a new password.

Back to log-in

Close