Sunteți pe pagina 1din 174

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 Include the domain of the page that shows the bug (especially if it's an important site)
o If the bug is a crash, note this and note whether or not the crash is reproducible
o 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 Do not include more than one bug in one bug report.


o 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.
o 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.
o Look at the system console and include any messages that might be relevant in the bug.
o Include the backtrace if you get a crash, if possible. File the bug first and then add the
backtrace as an attachment.
o 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.
o 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

Open Total
Name Description
Bugs Bugs
Bugs related to the use of the Cairo library
Cairo Search 74
within WebCore
Bugs related to the use of the curl library
Curl Search 36
within WebCore
DeveloperToolsHitList This bug is in the Developer Tools Hitlist Search 23
This bug should be considered for inclusion
DeveloperToolsHitListCandidate Search 1
in the Developer Tools Hitlist
ECMAScript 5 features and compliance
ES5 Search 17
issues.
This bug has been identified as a bug that
EasyFix Search 171
should be easy to fix
Keyword to allow tracking of bugs which
GoogleBug Search 346
concern Google products.
Gtk Bugs related to the Gtk port of WebKit Search 996
HTML5 HTML 5 features and compliance issues. Search 103
This bug has a reduced failing test case
HasReduction Search 1868
attached.
This bug is in the Top 10 Safari
HitList Search 13
Compatibility Bugs Hitlist.
This bug should be considered for the Top
HitListCandidate Search 15
10 List.
The bug is also being tracked in
InChromiumBugs Search 420
Chromium's bug database at .
This bug also has a copy in Apple's Radar
InRadar Search 6176
bug tracker.
For use of the Nokia WebKit guys, to track
InTSW if a bug is in their internal bugtracker, Search 1
TSW.
LayoutTestFailure Bugs which are causing layout test failures Search 571
Bugs that are currently causing the bots to
be red (even intermittently). Once the bug
MakingBotsRed is no longer making bots red (even if the Search 55
underlying bug hasn't been fixed yet), this
keyword should be removed.
NativeListBox NativeListBox bugs Search 35
bug that affect the new popup menu
NativePopUp Search 49
implementation
Regressions from the new text are
NativeTextArea Search 70
implementation.
A keyword to track bugs against the new
NativeTextField Search 132
native form controls in our engine.
Bug that needs a Radar, to help out the
NeedsRadar Search 498
Apple WebKit hackers.
NeedsReduction This bug needs a reduced test case. Search 892
Tracks bugs that need UI work before they
NeedsUI Search 7
can be completed.
Performance This bug relates to a performance issue. Search 110
This bug occurs only on the platform it has
PlatformOnly Search 1196
been reported on.
Qt Bugs related to the Qt port of WebKit Search 2912
Indicates that the Qt bug was triaged
QtTriaged according to the Bug Reporting Guidelines, Search 1405
and passed
This bug is a regression from a previous
Regression Search 2501
version of WebKit.
This bug has been reviewed to determine
ReviewedForRadar whether it needs to be imported into Radar. Search 1132
If it does a NeedsRadar keyword will be
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.
Worst SVG Bugs. Any of these could block
SVGHitList SVG from ever being included in an Search 55
official WebKit release.
Bugs about the new implementation of the
SearchField Search 11
search field
Bugs related to the use of the Soup network
Soup Search 33
library in WebCore
Bugs related to the SquirrelFish branch of
SquirrelFish Search 33
JavaScriptCore
Wx Bugs related to the wx port of WebKit. Search 45
XSSAuditor Tasks related to the XSS Auditor. Search 32
YahooBug This bug affects Yahoo products. Search 18

 Actions:
o Home
o | New
o | Search
o |

Find

o | Reports
o | Requests
o | New Account
o | 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:
webkit-
117 M P Ma NE m_webFrame->_private->currentItem
unassigned@lists.w
31 aj 1 c W (WebFrameLoaderClient::restoreScrollPosit
eb...
ionAndViewState())
webkit-
134 N P Ma NE REGRESSION: Upload progress does not
unassigned@lists.w
81 or 1 c W display at DriveHQ.com
eb...
webkit-
151 N P Ma NE REGRESSION: Tabbing doesn't return
unassigned@lists.w
66 or 1 c W focus to address bar when expected
eb...
webkit- REGRESSION: [Tiger only] Select pop-up
151 N P Ma NE
unassigned@lists.w menus are drawn split on
68 or 1 c W
eb... bugzilla.mozilla.org
webkit-
157 N P Ma NE REGRESSION: svg/custom/foreign-object-
unassigned@lists.w
24 or 1 c W skew.svg is broken on TOT in Leopard
eb...
webkit-
160 M P Ma NE REGRESSION: <canvas> transparent
unassigned@lists.w
45 aj 1 c W gradient rendering in 10.5
eb...
webkit-
165 N P Ma NE
unassigned@lists.w Valgrind: Invalid read of size 4
12 or 1 c W
eb...
webkit-
188 N P Ma NE REGRESSION (3.0 - 3.1): Dojo layout test
unassigned@lists.w
96 or 1 c W page hangs Webkit window
eb...
webkit-
197 N P Ma NE REGRESSION: MetaFilter content shown
unassigned@lists.w
07 or 1 c W below sidebar until refresh
eb...
webkit-
202 N P Ma NE REGRESSION: WebKit double-draws
unassigned@lists.w
29 or 1 c W selections in some cases
eb...
webkit-
204 N P Ma NE REGRESSION: MLB Gameday doesn't
unassigned@lists.w
94 or 1 c W load
eb...
webkit-
212 N P Ma NE Crash in RenderObject::containingBlock()
unassigned@lists.w
65 or 1 c W opening chess.com live chess
eb...
234 N P Wi webkit- NE WebKit crashes when visiting broken-
04 or 1 nd unassigned@lists.w W certificate sites
eb...
webkit-
234 N P Ma NE REGRESSION: Recording at
unassigned@lists.w
24 or 1 c W screentoaster.com stalls while loading
eb...
webkit-
245 N P Ma NE REGRESSION (r40142): FCK editor
unassigned@lists.w
55 or 1 c W initially has incorrect size
eb...
webkit-
303 N P Lin NE [Gtk] REGRESSION: WebKit fails part 2 of
unassigned@lists.w
12 or 1 u W PeaceKeeper benchmark
eb...
webkit-
421 N P Ma NE
unassigned@lists.w Safari hangs on siano-ms.com
28 or 1 c W
eb...
webkit-
429 M P Ma NE REGRESSION: Reproducible crash when
unassigned@lists.w
54 aj 1 c W pausing in JS debugger
eb...
webkit-
452 N P Wi NE
unassigned@lists.w Intermittent crashes in EventSource::close()
02 or 1 nd W
eb...
webkit-
572 N P Ma NE REGRESSION: Navigating to a named
unassigned@lists.w
14 or 1 c W anchor causes content to shift off page
eb...
396 N P Ma NE Clicks inside button elements are sometimes
rniwa@webkit.org
20 or 2 c W discarded when the mouse moves
webkit-
566 N P Ma NE Pasteboard sometimes receives hidden
unassigned@lists.w
9 or 2 c W content.
eb...
webkit-
602 N P Ma NE SVG Filters do not support source images
unassigned@lists.w
2 or 2 c W besides "sourceGraphic" and "sourceAlpha"
eb...
webkit-
764 N P Ma NE Apycom DHTML Menu used on
unassigned@lists.w
2 or 2 c W http://www.melges24.com does not work.
eb...
webkit-
768 N P Ma NE Table is not dynamically updated when
unassigned@lists.w
4 or 2 c W scrolling
eb...
webkit-
793 M P Ma NE HTML editing API's not fully rendered
unassigned@lists.w
2 aj 2 c W and/or not working
eb...
803 N P Wi webkit- NE parent != iframes[i].contentWindow
6 or 2 nd unassigned@lists.w W
eb...
webkit-
869 N P Ma NE Flash/JavaScript "LiveConnect" does not
unassigned@lists.w
7 or 2 c W work at game site
eb...
webkit- REGRESSION (r14032): Incorrect and non-
875 N P Ma NE
unassigned@lists.w uniform text zoom applied after going
3 or 2 c W
eb... forward and backward
webkit-
925 N P Ma NE Quirksmode: Safari ignores window.close()
unassigned@lists.w
4 or 2 c W after form submission
eb...
webkit-
946 N P Ma NE Text Input Element: Detection of focus or
unassigned@lists.w
0 or 2 c W setting of focus broken
eb...
webkit-
970 N P Ma NE Stylesheets fail to reload after b/f navigation
unassigned@lists.w
1 or 2 c W @ fandango.com
eb...
webkit-
971 N P Ma NE Dropdown menus on the front page don't
unassigned@lists.w
9 or 2 c W work
eb...
webkit-
972 N P Ma NE
unassigned@lists.w Page does not layout right
9 or 2 c W
eb...
webkit-
975 M P Ma NE High CPU usage during layout after mouse
unassigned@lists.w
1 aj 2 c W movement
eb...
webkit-
998 N P Ma NE
unassigned@lists.w Layout problem.
1 or 2 c W
eb...
webkit-
101 M P Ma NE
unassigned@lists.w Vox: Master Bug
65 aj 2 c W
eb...
webkit-
101 N P Ma NE
unassigned@lists.w Splunk web application compatibility
72 or 2 c W
eb...
webkit-
103 N P Ma NE SVGs fail to render intermittently (on
unassigned@lists.w
41 or 2 c W reload)
eb...
104 M P Ma webkit- NE Alert pops up complaining about TypeError
76 aj 2 c unassigned@lists.w W (Safari)/ReferenceError (WebKit)
eb...
webkit-
105 N P Ma NE Framesets keeps loading recursively,
unassigned@lists.w
78 or 2 c W resulting in massively nested frames
eb...
webkit-
113 N P Ma NE
unassigned@lists.w Content missing
75 or 2 c W
eb...
webkit- Dragging a text selection on an RSS page
115 N P Ma NE
unassigned@lists.w can select all text above the intended
16 or 2 c W
eb... selection
webkit-
118 M P Ma NE www.thestar.com sites very slow to load,
unassigned@lists.w
35 aj 2 c W but instant in Camino
eb...
webkit-
118 N P Ma NE
unassigned@lists.w Reopening SVG world map makes it blank
38 or 2 c W
eb...
webkit-
120 N P Ma NE Page does not load in Safari (downloads
unassigned@lists.w
10 or 2 c W instead) likely due to mime type
eb...
webkit-
121 N P Ma NE Menus on peachtree.com don't display
unassigned@lists.w
38 or 2 c W correctly
eb...
webkit-
121 N P Ma NE Hotel 'View/Cancel a reservation' option
unassigned@lists.w
76 or 2 c W missing
eb...
webkit-
123 N P Ma NE User needs to be able to set Lucida Grande
unassigned@lists.w
24 or 2 c W "italic"
eb...
webkit-
124 N P Ma NE Layout weirdness on Kotaku.com in Safari
unassigned@lists.w
14 or 2 c W and Nightlies (r19136)
eb...
webkit-
125 N P Ma NE
unassigned@lists.w Drop down menus do not work on this site
29 or 2 c W
eb...
webkit-
125 N P Ma NE Crash using Kimpton Hotel's internet access
unassigned@lists.w
40 or 2 c W when second timer window opened
eb...
webkit-
127 N P Ma NE CSS3: The :first-of-type:first-letter pseudo
unassigned@lists.w
09 or 2 c W selector combination fails
eb...
webkit-
128 M P Ma NE WebKit fails to even load the W3C/NIST
unassigned@lists.w
35 aj 2 c W DOM Conformance Test Suite
eb...
webkit-
130 N P Ma NE
unassigned@lists.w Slacker Web Player Error
66 or 2 c W
eb...
webkit-
131 N P Ma NE
unassigned@lists.w http://www.itwire.com.au/ misrenders badly
14 or 2 c W
eb...
webkit-
131 N P Ma NE The awesome Zune blog's date header
unassigned@lists.w
33 or 2 c W overlaps the description
eb...
webkit- Assertion failure in -
132 N P Ma NE
unassigned@lists.w [WebBaseNetscapePluginStream dealloc]
30 or 2 c W
eb... (isTerminated) when leaving page
webkit-
134 N P Ma NE 272 leaks for 12304 total leaked bytes at
unassigned@lists.w
75 or 2 c W pcadvisor.co.uk
eb...
webkit-
135 N P Ma NE
unassigned@lists.w Flash deep linking causes page to reload
04 or 2 c W
eb...
webkit-
135 N P Ma NE Overlapping site image on The awesome
unassigned@lists.w
26 or 2 c W Giveaway of the Day site
eb...
webkit-
136 N P Ma NE REGRESSION: Menus at register.com
unassigned@lists.w
39 or 2 c W broken in Safari 2.0, works in v1.2
eb...
webkit-
136 N P Ma NE
unassigned@lists.w Text overlaps picture when page widened
98 or 2 c W
eb...
webkit-
137 N P Ma NE
unassigned@lists.w realeditor.com does not support WebKit
45 or 2 c W
eb...
webkit-
138 N P Ma NE Partially obscured vertical scroll bar on DIV
unassigned@lists.w
86 or 2 c W does not draw properly on page load
eb...
webkit-
142 N P Ma NE Text tearing in colloquy when using "Blak"
unassigned@lists.w
46 or 2 c W style
eb...
144 M P Ma webkit- NE Selection highlight in the caption not
67 in 2 c unassigned@lists.w W completely cleared when advancing to the
eb... next photo on Picasa Web Albums
webkit- ASSERTION FAILED: !containsImage ||
144 N P Ma NE
unassigned@lists.w MimeTypeRegistry::isSupportedImageReso
93 or 2 c W
eb... urceMIMEType([resource MIMEType])
webkit-
145 N P Ma NE getComputedStyle() returns an empty style
unassigned@lists.w
63 or 2 c W declaration for detached elements
eb...
webkit-
145 N P Ma NE Comments not visible due to wide table in
unassigned@lists.w
97 or 2 c W blog entry
eb...
webkit-
146 N P Ma NE "Bad field count" message when running
unassigned@lists.w
57 or 2 c W Cookie Test on Philiweb.com
eb...
webkit- Repaint issues related to removing or
146 N P Ma NE
unassigned@lists.w resizing nodes in documents that rely
75 or 2 c W
eb... heavily on CSS styling of nodes.
webkit-
146 N P Ma NE Bug in columns support (relpositioned
unassigned@lists.w
91 or 2 c W inlines)
eb...
webkit-
146 N P Ma NE padding left & right ignored when using
unassigned@lists.w
94 or 2 c W percentage values.
eb...
webkit-
149 N P Ma NE Quick Reply feature misplaces iframe on
unassigned@lists.w
33 or 2 c W KFAN fourms
eb...
webkit-
149 N P Ma NE
unassigned@lists.w Left navigation renders over main body
40 or 2 c W
eb...
webkit-
149 N P Ma NE
unassigned@lists.w 1 pixel background-image shift
56 or 2 c W
eb...
webkit-
151 N P Ma NE Offender Locator page does not load
unassigned@lists.w
20 or 2 c W (Windows Live Maps mashup)
eb...
webkit-
151 N P Ma NE EA Website broken in Safari and WebKit
unassigned@lists.w
84 or 2 c W r25484; fine in Firefox
eb...
151 N P Ma webkit- NE Error reloading www.quomodo.com after a
86 or 2 c unassigned@lists.w W file upload
eb...
webkit-
152 N P Ma NE Scroll bar removed during page load is not
unassigned@lists.w
46 or 2 c W repainted properly
eb...
webkit-
153 N P Ma NE Uncaught Exception hit in cookie code
unassigned@lists.w
90 or 2 c W while quitting? safari from Lively Kernel
eb...
webkit-
154 N P Ma NE SVG fails all 3 of Hixie's CSS intrinsic
unassigned@lists.w
73 or 2 c W sizing tests
eb...
webkit-
154 N P Ma NE Safari (and opera) fire two onload events
unassigned@lists.w
84 or 2 c W while FireFox fires only one
eb...
webkit-
155 N P Ma NE DumpRenderTree crashes in loader
unassigned@lists.w
03 or 2 c W callbacks
eb...
webkit- Inspector hangs in
155 N P Ma NE
unassigned@lists.w Position::isRenderedText() inspecting this
16 or 2 c W
eb... file
webkit-
155 N P Ma NE Unable to type a left parenthesis when
unassigned@lists.w
87 or 2 c W suggest is enabled on google.
eb...
webkit- "CMSCreateDataProviderOrGetInfo :
155 N P Ma NE
unassigned@lists.w Invalid colorspace type" on
93 or 2 c W
eb... www.whatwg.org
webkit-
156 N P Ma NE Page rendered incorrectly after submitting
unassigned@lists.w
25 or 2 c W feedback form (www.msnbc.msn.com)
eb...
webkit-
158 N P Ma NE
unassigned@lists.w WebKit fails some WICD 1.0 core test cases
36 or 2 c W
eb...
webkit-
160 M P Ma NE No scroll bars or incorrect scroll height on
unassigned@lists.w
38 in 2 c W PayPal bank account help page
eb...
webkit-
161 N P Ma NE Report Bill button does not work in
unassigned@lists.w
51 or 2 c W BillMonk
eb...
webkit-
162 N P Ma NE New GMail interface: unrecognised email
unassigned@lists.w
55 or 2 c W address error does not appear
eb...
webkit-
162 N P Ma NE Gmail Long e-mail "To" list makes Safari
unassigned@lists.w
57 or 2 c W widen messages
eb...
webkit-
162 N P Ma NE target="_top" in embedded SVG fails to
unassigned@lists.w
68 or 2 c W replace parent content
eb...
webkit-
162 M P Ma NE Problem increasing the size of pictures on
unassigned@lists.w
77 in 2 c W this site
eb...
webkit-
164 N P Ma NE
unassigned@lists.w WebKit fails WICD onunload test
84 or 2 c W
eb...
webkit-
164 N P Ma NE WebKit fails to display SVG in WICD test
unassigned@lists.w
91 or 2 c W case
eb...
webkit-
167 N P Ma NE problem with 'New views' at
unassigned@lists.w
21 or 2 c W www.nabble.com
eb...
webkit-
167 N P Ma NE Weird selection issues (hit detection?) on
unassigned@lists.w
37 or 2 c W site
eb...
Se P Sta Resol
ID OS Assignee Summary
v ri tus ution
webkit-
167 N P Wi NE
unassigned@lists. ASSERTION FAILED: maxWidth >= 0
57 or 2 nd W
web...
webkit-
168 N P Ma NE
unassigned@lists. gear popups offset if window is scrolled
64 or 2 c W
web...
webkit- ASSERTION FAILED:
169 N P Ma NE
unassigned@lists. !HashTranslator::equal(KeyTraits::emptyVal
18 or 2 c W
web... ue(), key)
webkit-
169 N P Ma NE div on this page has JS code rendered in it,
unassigned@lists.
29 or 2 c W and ad is offset
web...
webkit-
169 N P Ma NE REGRESSION(Safari3-TOT): SVG renders
unassigned@lists.
53 or 2 c W improperly
web...
169 N P Ma webkit- NE WebKit fails linking-url-01 and 02 (<view>
62 or 2 c unassigned@lists. W support)
web...
webkit-
170 N P Ma NE Font size does not work correct when using
unassigned@lists.
38 or 2 c W the HTML GUI Editing on GuildPortal
web...
webkit-
170 N P Ma NE SWSoft (parent of Parallels Inc.) website
unassigned@lists.
40 or 2 c W menu issues
web...
webkit-
170 N P Ma NE FOUC when (re)loading page at
unassigned@lists.
44 or 2 c W nuernberg.de
web...
webkit-
171 N P Ma NE
unassigned@lists. Navigation menu works incorrectly
59 or 2 c W
web...
webkit-
171 N P Ma NE Test (and fix) complex resource invalidations
unassigned@lists.
66 or 2 c W (symbol nesting, CDF symbols)
web...
webkit-
174 N P Ma NE .big-issue style text overlaps on HTML5
unassigned@lists.
59 or 2 c W spec
web...
webkit-
174 N P Ma NE
unassigned@lists. Foafnaut doesn't work
74 or 2 c W
web...
webkit-
174 N P Ma NE Display issue--extended calendar on
unassigned@lists.
99 or 2 c W delta.com
web...
webkit-
175 N P Wi NE at onclick in a select box no change the
unassigned@lists.
16 or 2 nd W article picture
web...
webkit-
175 N P Ma NE Sports Menu on Texags.com not rendering
unassigned@lists.
42 or 2 c W on initial load
web...
webkit-
175 N P Ma NE
unassigned@lists. Content border cap renders incorrectly
61 or 2 c W
web...
webkit-
176 N P Ma NE
unassigned@lists. Page content shifted too high
35 or 2 c W
web...
webkit-
178 N P Ma NE REGRESSION: menu bar renders
unassigned@lists.
69 or 2 c W incorrectly
web...
webkit-
180 N P Ma NE ASSERTs in
unassigned@lists.
00 or 2 c W FrameView::scheduleRelayout()
web...
webkit-
187 N P Ma NE
unassigned@lists. Right click on story link causes hang
54 or 2 c W
web...
webkit-
191 N P Ma NE VMware virtual appliance download page
unassigned@lists.
76 or 2 c W broken in Safari
web...
webkit-
193 N P Ma NE
unassigned@lists. WebEx Plugin can't launch application
79 or 2 c W
web...
webkit-
194 N P Ma NE Distinct redirects from the same link do not
unassigned@lists.
22 or 2 c W create distinct history items
web...
webkit-
201 N P Ma NE weird faint lines on canvas when drawing
unassigned@lists.
74 or 2 c W lines
web...
webkit-
204 N P Ma NE div displays in wrong location after being
unassigned@lists.
88 or 2 c W hidden and shown twice
web...
webkit-
205 N P Ma NE The back/forward cache breaks Acid 2 eyes
unassigned@lists.
02 or 2 c W fallback content
web...
webkit-
205 N P Ma NE
unassigned@lists. text content not displayed
10 or 2 c W
web...
webkit-
205 N P Ma NE WebKit fails two elements of the "Web
unassigned@lists.
17 or 2 c W Compatibility Test for Mobile Browsers"
web...
webkit-
205 N P Ma NE Form field values aren't submitted when
unassigned@lists.
83 or 2 c W hitting ENTER
web...
webkit-
205 N P Ma NE WebKit eats CPU on
unassigned@lists.
87 or 2 c W http://uk.sun.com/tryandbuy/products.jsp
web...
webkit-
206 M P Wi NE Robohelp Web Help: Table of Contents does
unassigned@lists.
50 aj 2 nd W not render on Windows
web...
209 N P Wi webkit- NE Huge memory usage on Dromaeo test
64 or 2 nd unassigned@lists. W
web...
webkit-
209 N P Ma NE "New" corner out of place at Apple iTunes
unassigned@lists.
66 or 2 c W overview page
web...
webkit-
209 N P Ma NE Video in wrong position @ blizzard.com
unassigned@lists.
71 or 2 c W worldofwarcraft.com
web...
webkit-
225 N P Ma NE
unassigned@lists. Problem Rendering
47 or 2 c W
web...
webkit-
230 N P Ma NE
unassigned@lists. Layout problems at http://www.cfi.net.cn
61 or 2 c W
web...
webkit-
233 N P Wi NE
unassigned@lists. Plug-in originated popup not blocked
30 or 2 nd W
web...
webkit-
233 N P Ma NE HTMLFormElement magic differs from
unassigned@lists.
44 or 2 c W HTML5
web...
webkit-
236 N P Ma NE ASSERTION FAILED: docLoader-
unassigned@lists.
46 or 2 c W >requestCount() == 0
web...
webkit-
239 N P Wi NE
unassigned@lists. Repaint errors when collapsing text
64 or 2 nd W
web...
webkit-
241 N P Ma NE REGRESSION: gap.com (and affiliates)
unassigned@lists.
69 or 2 c W "QuickLinks" aren't linkfied
web...
webkit-
242 N P Ma NE GCGetGlyphIdealMetrics fails and causes
unassigned@lists.
20 or 2 c W random text
web...
webkit-
243 N P Wi NE Regression: Can't click on navigation links
unassigned@lists.
18 or 2 nd W on WebKit nightlies.
web...
webkit-
252 N P Ma NE Image caption overlaps article text when
unassigned@lists.
96 or 2 c W zoomed out a single level
web...
256 N P Ma webkit- NE REGRESSION (r43007): In MobileMe
20 or 2 c unassigned@lists. W Calendar, New Event text is displayed offset
web... when it's first created
webkit- First highlighted search is missing, searching
258 N P Ma NE
unassigned@lists. for "webkit" on
13 or 2 c W
web... http://developer.apple.com/wwdc/sessions/
webkit- Page that performs syntax highlighting on
258 N P Ma NE
unassigned@lists. <code> elements in JS looks wrong when
33 or 2 c W
web... loaded from web archive
webkit-
259 N P Wi NE Unexpected Space after 20 characters in
unassigned@lists.
48 or 2 nd W column
web...
webkit-
264 N P Ma NE
unassigned@lists. Overlapping content at openbossa.org
51 or 2 c W
web...
webkit-
264 N P Ma NE Incorrectly positioned content at marrow.org
unassigned@lists.
73 or 2 c W (Be The Match registry website)
web...
webkit-
265 N P Wi NE ASSERTION FAILED: stack.size() ==
unassigned@lists.
06 or 2 nd W depthCrossingShadowBoundaries(node)
web...
webkit-
268 M P Wi NE
unassigned@lists. Hang when clicking on link from kuwo.cn
26 aj 2 nd W
web...
webkit-
269 M P Ma NE Crash on focussing non rendered input via
unassigned@lists.
86 aj 2 c W javascript
web...
webkit-
280 N P Ma NE Photo browser doesn't display enlarged
unassigned@lists.
52 or 2 c W versions of photos
web...
webkit- Selection is vertically offset when selecting
288 N P NE
All unassigned@lists. second line of chapter title text of Dive Into
17 or 2 W
web... HTML 5
webkit-
292 N P Ma NE Page scrolls to original position on link
unassigned@lists.
32 or 2 c W hover
web...
webkit-
305 N P Ma NE Text repainting incorrect for a combination
unassigned@lists.
07 or 2 c W of padding, columns and ajax
web...
webkit-
313 N P Wi NE Clicking Comment Links on CodeProject
unassigned@lists.
04 or 2 nd W Jumps to Middle of Page
web...
webkit-
325 N P Ma NE Assertion failure in addStyleMarkup copying
unassigned@lists.
25 or 2 c W link text (from maps.google.com at least)
web...
webkit-
352 N P Ma NE YUI: Button title copied to other buttons
unassigned@lists.
86 or 2 c W when going back to a page
web...
webkit-
353 N P Ma NE
unassigned@lists. behavior with http auth and xmlhttprequest
90 or 2 c W
web...
Assertion failure (!layer-
webkit-
360 N P Ma NE >m_zOrderListsDirty) in
unassigned@lists.
94 or 2 c W RenderLayerCompositor::rebuildCompositin
web...
gLayerTree()
webkit-
364 N P Ma NE Incorrect painting when switching tabs in
unassigned@lists.
18 or 2 c W github account settings
web...
webkit-
371 M P Ma NE Scroll lags on
unassigned@lists.
89 in 2 c W www.ligatureloopandstem.com
web...
webkit-
372 N P Ma NE 'Sign In' button missing from
unassigned@lists.
45 or 2 c W studentloans.gov
web...
webkit-
394 N P Ma NE
unassigned@lists. 'X' buttons are drawn twice on Facebook ads
38 or 2 c W
web...
webkit-
405 N P Ma NE Maps on ebparks.org (East Bay regional park
unassigned@lists.
42 or 2 c W district) are scaled incorrectly
web...
webkit-
417 N P Ma NE iFrame scrolling causes paint errors on
unassigned@lists.
86 or 2 c W boy.co.tt
web...
webkit-
446 M P Ma NE REGRESSION (r53420): Parts of
unassigned@lists.
40 aj 2 c W aktrailhead.com invisible until page resize
web...
webkit- Assertion failure in
474 N P Ma NE
unassigned@lists. JSEventListener::jsFunction() (m_wrapper ||
84 or 2 c W
web... !m_jsFunction)
webkit-
480 N P Ma NE
unassigned@lists. ASSERT while loading reddit.com
57 or 2 c W
web...
webkit-
490 N P Ma NE
unassigned@lists. SMIL animation works forward only
93 or 2 c W
web...
webkit-
502 N P Ma NE Positioning error in dynamically inserted
unassigned@lists.
10 or 2 c W content
web...
webkit-
508 M P Ma NE iFrame window gets clipped when Google
unassigned@lists.
32 aj 2 c W map pans
web...
webkit-
520 N P Ma NE
unassigned@lists. Layout glitches at noflash.pl login page
60 or 2 c W
web...
webkit- Assertion failure in
547 N P Ma NE
unassigned@lists. HTMLFrameElementBase::insertedIntoDocu
11 or 2 c W
web... ment() when opening comcast.net main page
webkit-
585 N P Ma NE REGRESSION (r81992): Facebook photo
unassigned@lists.
00 or 2 c W tags can get cut off when moving the mouse.
web...
140 N P Ma zimmermann@kde. NE CGAffineTransformInvert: singular matrix.
65 or 2 c org W spewed to console
242 N P Ma zwarich@apple.co NE
http://htmlplayground.com/ doesn't work
67 or 2 c m W
webkit-
102 N P Ma NE Scroll bars not removed after incremental
unassigned@lists.
55 or 3 c W layout
web...
webkit-
113 M P Ma NE Search button wrongly positioned at
unassigned@lists.
02 in 3 c W amnesty.se
web...
webkit-
129 M P Ma NE history is wrong after loading google.com/ig
unassigned@lists.
93 in 3 c W with digg or wikipedia
web...
webkit-
146 N P Ma NE
unassigned@lists. Page content doesn't show
86 or 3 c W
web...
webkit-
182 M P Ma NE Positioned UL+LIs menu shifts when LI id
unassigned@lists.
55 in 3 c W attribute is referenced (link to it clicked)
web...
webkit-
205 N P Wi NE WebMail button at virginbroadband.com.au
unassigned@lists.
95 or 3 nd W does not submit
web...
webkit- For compatibility, execCommand should
366 Tr P Ma NE
unassigned@lists. support deprecated 'useCSS' alias for
83 i 3 c W
web... 'styleWithCSS'
webkit-
541 N P Ma NE
unassigned@lists. Sarissa test cases fail in Safari
1 or 4 c W
web...
webkit-
708 N P Ma NE
unassigned@lists. zoozio doesn't work correctly in Safari
7 or 4 c W
web...
webkit-
708 N P Ma NE zoho writer becomes "solid brown" after
unassigned@lists.
8 or 4 c W choosing several pop-up buttons
web...
webkit-
104 N P Ma NE
unassigned@lists. SVG example fails to find resources
03 or 4 c W
web...
webkit-
111 N P Ma NE Flash of white while dragging window
unassigned@lists.
05 or 4 c W during image load
web...
webkit-
153 N P Ma AS RenderBox::availableHeightUsing() contains
unassigned@lists.
74 or 2 c SI left/right to top/bottom typo
web...
webkit-
176 N P Ma RE Reproducible SVG Crash when acid3-test-
unassigned@lists.
72 or 1 c OP 77.html timing dependency is fixed
web...
webkit-
215 N P Ma RE REGRESSION: Patterns are recreated every
unassigned@lists.
10 or 1 c OP time they paint
web...
webkit-
993 N P Ma RE Scroll bars not redrawn when using
unassigned@lists.
5 or 2 c OP back/forward cache
web...
webkit-
134 M P Ma RE Weird behaviour; cursor turns into watch and
unassigned@lists.
92 aj 2 c OP links don't work.
web...
+[WebScriptObject
webkit-
135 N P Ma RE _convertValueToObjcValue:originExecution
unassigned@lists.
91 or 2 c OP Context:executionContext:] returns a wrong
web...
object for plug-in nodes
webkit-
141 N P Ma RE Detached vertical scrollbar on usps.com
unassigned@lists.
80 or 2 c OP (repaint issue)
web...
webkit-
176 N P Ma RE
unassigned@lists. Endless reloads on http://space.cweb.nl
27 or 2 c OP
web...
200 bugs found.
Long Format Remember search
CSV | RSS | iCalendar | Change Columns | as
XML
Edit Search
Change Several Bugs at Once |

 Actions:
o Home
o | New
o | Search
o |

Find

o | Reports
o | Requests
o | New Account
o | Help
o | 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())
REGRESSION: ASSERTION FAILED:
Summary: m_webFrame->_private->currentItem
(WebFrameLoad...
Status: NEW
Product: WebKit
Component: Page Loading
Version: 420+
Macintosh Mac OS X
Platform:
10.4
Importance: P1 Major 2006-11-30 22:09 PST by David Kilzer
Reported:
Assigned (ddkilzer)
Nobody
To: Modified: 2009-05-22 17:57 PST (History)
URL:
InRadar, NeedsReduction,
Keywords:
Regression, ...
Depends on:
Blocks:
Show dependency tree
/ graph

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

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: 2.0.4 (419.3)


Build Version: 1
Project Name: WebBrowser
Source Version: 4190300

PID: 1990
Thread: 0

Exception: EXC_BAD_ACCESS (0x0001)


Codes: KERN_INVALID_ADDRESS (0x0001) at 0xbbadbeef

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 mitz@webkit.org 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 mitz@webkit.org 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 mitz@webkit.org 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 | Reports
o | Requests
o | New Account
o | Help
o | 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. The test should be the smallest possible code fragment that tests the feature.
2. The test should fit on one page (unless of course it’s testing scrolling).
3. The test should clearly describe what feature it is testing.
4. 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/event-


creation.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, ian@hixie.ch

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
public-css-testsuite@w3.org (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
o4.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

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 test-
topic 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.

A rectangle exactly 0.2em high, 1em wide, and aligned so that its top is flush with the
p U+0070
baseline.

A rectangle exactly 0.8em high, 1em wide, and aligned so that its bottom is flush with the
É U+00C9
baseline.

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 (jsmith@example.com)

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. Browse to your patch file in the File field.


2. Type a brief description in the Description field, for example "Proposed patch."
3. Check the "patch" checkbox (see picture below).
4. Select the question mark "?" in the "review" pull-down (see picture below).
5. 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 set-
webkit-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 (jsmith@example.com)

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. Browse to your patch file in the File field.
2. Type a brief description in the Description field, for example "Proposed patch."
3. Check the "patch" checkbox (see picture below).
4. Select the question mark "?" in the "review" pull-down (see picture below).
5. 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 command-
line 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 "HTMLElement.h"
#include "HTMLDivElement.h"
#include "QualifiedName.h"
#include "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 RESOLUTION
The status field indicates the general health of a The resolution field indicates what happened to
bug. Only certain status transitions are allowed. this bug.

UNCONFIRMED No resolution yet. All bugs which are in


one of these "open" states have the
This bug has recently been added to the resolution set to blank. All other bugs will
database. Nobody has validated that this
be marked with one of the following
bug is true. Users who have the
resolutions.
"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 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 FIXED

A resolution has been taken, and it is A fix for this bug is checked into the tree
awaiting verification by QA. From here and tested.
bugs are either re-opened and become
INVALID
REOPENED, are marked VERIFIED, or are
closed for good and marked CLOSED. The problem described is not a bug.
VERIFIED WONTFIX
QA has looked at the bug and the The problem described is a bug which will
resolution and agrees that the appropriate never be fixed.
resolution has been taken. Bugs remain in
this state until the product they were DUPLICATE
reported against actually ships, at which
The problem is a duplicate of an existing
point they become CLOSED.
bug. Marking a bug duplicate requires the
CLOSED bug# of the duplicating bug and will at
least put that bug number in the
The bug is considered dead, the resolution description field.
is correct. Any zombie bugs who choose to
walk the earth again must do so by WORKSFORME
becoming REOPENED.
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 Blocks development and/or testing work

Critical crashes, loss of data, severe memory leak

Major major loss of function

Normal regular issue, some loss of functionality under specific circumstances

Minor minor loss of function, or other problem where easy workaround is present

Trivial 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 | Reports
o | Requests
o | New Account
o | 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. KB918559
2. KB935225
3. KB943969
4. 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 set-
webkit-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  Global Object  Regular Expressions


 Booleans  Math  Strings
 Dates  Numbers
 Functions  Objects

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. The test should be the smallest possible code fragment that tests the feature.
2. The test should fit on one page (unless of course it’s testing scrolling).
3. The test should clearly describe what feature it is testing.
4. 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/event-


creation.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 i-
Bench 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 non-
editable 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 object-
oriented 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 webkit-dev@lists.webkit.org 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* firstChild() const;


RenderObject* lastChild() const;
RenderObject* previousSibling() const;
RenderObject* 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 marginTop() const;


int marginBottom() const;
int marginLeft() const;
int marginRight() const;

int paddingTop() const;


int paddingBottom() const;
int paddingLeft() const;
int paddingRight() const;

int borderTop() const;


int borderBottom() const;
int borderLeft() const;
int 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 clientLeft() const { return borderLeft(); }


int clientTop() const { return borderTop(); }
int clientWidth() const;
int 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 scrollLeft() const;


int scrollTop() const;
int scrollWidth() const;
int 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 all-
inline 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;background-
color: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 insertFloatingObject(RenderObject*);
void removeFloatingObject(RenderObject*);
void clearFloats();
void 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.

S-ar putea să vă placă și