기존 글:

Hello, ewebkit



이번에는 ewk_view에 투명한 배경을 주는 예제를 소개할까 합니다.

기존의 예제(simple.c)를 약간 수정하는 정도의 예제입니다.


먼저 투명한 배경에 대한 설명을 하겠습니다.


일반적으로 웹 페이지는 웹뷰(ewk_view)의 전체 영역에 컨텐츠를 그리게 됩니다.

웹페이지는 body 태그의 배경을 이용하여 컨텐츠의 배경색을 갖게 되는데, 보통 다음과 같이 사용합니다.

### html

<!doctype html>

<!- no background -->

<body>HELLO</body>


### html

<!doctype html>

<body bgcolor="red">Hello, I am red background</body>


### html

<!doctype html>

<head><style>body { background-color: green; } </style></head>

<body>Hello, I am green background</body>


두번째와 세번째는 배경을 갖는 예제인 반면, 첫번째는 배경을 갖지 않는 예제입니다. 그러나 만약 첫번째 예제를 브라우저에서 실행한다면 흰 배경 위에 HELLO라는 글자가 적혀 있는 것을 보게 될 것입니다.


일반적으로 거의 대부분의 브라우저들은 기본 배경을 흰색으로 제공하고 있습니다.

그래서 웹 컨텐츠를 제작하는 대부분의 분들이 배경을 지정하지 않고 있습니다.

(

하지만 만약 흰 배경을 사용하지 않는 브라우저가 나타나면 어쩌실건가요? ㅡ.ㅡ

그리고, 특정 모바일 디스플레이들은 흰색일 때 배터리 소모가 극심합니다.

)


webkit도 기본 배경을 흰색으로 정하고 있지만, 다른 색을 쓰거나, 투명하게 그릴 수 있는 방법을 제공하고 있습니다.

ewebkit에서 관련 API는 ewk_view_bg_color_set 이라는 API가 존재합니다.


### c++

/**
 * Sets the background color and transparency of the view.             
 *
 * @param o view object to change the background color
 * @param r red color component
 * @param g green color component                                          
 * @param b blue color component     
 * @param a transparency             
 */
EAPI void ewk_view_bg_color_set(Evas_Object *o, int r, int g, int b, int a);

각각의 color component들은 0 부터 255 사이의 숫자여야 합니다.


일반적으로 EFL에서는 evas_object_color_set이라는 API를 이용하여 evas object의 색을 지정했지만,

ewebkit에서는 alpha를 제외하곤 evas_object_color_set의 다른 인자들을 사실상 무시합니다.

이유는, evas_object_color_set의 alpha가 전체 컨텐츠의 opacity를 다루는 반면, ewebkit은 배경만의 opacity를 다루어야 하는 요구사항이 있기 때문입니다.

즉, evas_object_color_set은 evas_object 전체의 색을 조절하는 API로 ewebkit에서는 contents의 색은 contents가 지정해야 하기 때문에 RGB값은 무시됩니다. (현재)


ewk_view_bg_color_set 을 사용하는 예제는 아래와 같습니다.

https://github.com/ewebkit/samples/blob/master/devs/ryuan/transparent.c

### c++

// gcc transparent.cpp `pkg-config --cflags --libs elementary ewebkit2
#include <Elementary.h>
#include <EWebKit2.h>

void on_done(void *userData, Evas_Object *webView, void *eventInfo)
{
   elm_exit();
}

EAPI_MAIN int
elm_main(int argc, char *argv[])
{
   ewk_init();

   Evas_Object* win;
   win = elm_win_add(NULL, "sample", ELM_WIN_BASIC);
   elm_win_title_set(win, "sample");
   evas_object_smart_callback_add(win, "delete,request", on_done, NULL);
   elm_win_autodel_set(win, EINA_TRUE);

   Evas_Object* bg = elm_bg_add(win);
   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
   elm_bg_color_set(bg, 0, 0, 255);
   elm_win_resize_object_add(win, bg);
   evas_object_show(bg);

   Evas_Object* ewk = ewk_view_add(evas_object_evas_get(win));
   ewk_view_html_string_load(ewk, "<!doctype html><body>HELLO</body>", NULL, NULL);
   ewk_view_bg_color_set(ewk, 0, 0, 0, 0);

   evas_object_resize(ewk, 400, 400);
   evas_object_move(ewk, 0, 0);
   evas_object_show(ewk);

   evas_object_resize(win, 400, 400);
   evas_object_show(win);

   elm_run();

   ewk_shutdown();
}
ELM_MAIN()

배경 속성이 없는 web contents를 위해 url 대신 ewk_view_html_string_load를 이용했습니다.

그리고 ewk_view_bg_color_set 을 통해 ewk_view의 배경을 투명하게 만든 예제입니다.


위에서 elm_bg의 색을 blue로 했기 때문에 파란색 배경 위에 HELLO라는 글자가 적혀있어야 합니다.

만약 검은색으로 나온다면, ewebkit을 최신으로 빌드해보시기 바랍니다.

(최근 수정 :https://bugs.webkit.org/show_bug.cgi?id=135333)


추신. 현재 ewk_view_bg_color_set과 EFL 관련 버그가 하나 더 있는 것 같습니다.

만약 ewk_view_bg_color_set의 RGB요소에 값을 주고 alpha를 준 경우, elm_bg의 색과 blend되고 있습니다.

만약 투명한 웹뷰가 필요한 경우라면 RGB요소를 모두 0으로 주시기 바랍니다.

저작자 표시
신고

'Open Source > EFL' 카테고리의 다른 글

[EFL] EWebKit Extension  (0) 2014.09.23
transparent ewebkit  (0) 2014.07.30
Hello ewebkit?  (2) 2014.03.14
WebKit/efl 하면서 쓸 ctags 만들기  (0) 2013.12.17
Elementary Dark theme  (0) 2013.10.17
[TIZEN][EFL] 타이젠 상에서 EFL 예제 실행하기  (9) 2013.08.02
Posted by 소혼
2014.03.14 08:44

ewebkit은 WebKit 엔진 기반에 EFL 라이브러리를 사용하여 UI를 표현하는 라이브러리입니다.

(WebKit/EFL 이라고도 부르는데,  저는 so 파일 이름에 따라 ewebkit이라고 부르고 있습니다.)


물론,  Elementary의 elm_web이 ewebkit 에서 사용하는 ewk_view의 간단한 wrapper 클래스이지만 아직 문제가 많은 상태이기 때문에(1.9) ewebkit을 직접 쓰는 방법을 권장하고 있습니다. (또 타이젠(~2.2) 에서는 elm_web을 사용하실 수 없습니다.)

이 글에서는 elm_web이 아닌 ewk_view를 사용해서 간단한 페이지를 만드는 법을 공유하려고 합니다.


ewebkit 라이브러리는 현재 두 종류가 있습니다.

ewebkit : WebKit1/EFL 포트에 기반하는 라이브러리

ewebkit2 : WebKit2/EFL 포트에 기반하는 라이브러리


둘의 가장 큰 차이는 간단히 설명드리면 웹페이지를 렌더링하는 코어영역을 같은 프로세스에서 처리하느냐(ewebkit), 다른 프로세스에서 처리하느냐(ewebkit2) 입니다.

대부분의 인터페이스는 유사하지만, 이런 프로세스 모델의 차이에서 몇몇 인터페이스에는 차이가 있습니다.


참고로 타이젠과 같은 경우 1.0에서는 ewebkit을 사용하였고, 2.0부터는 ewebkit2를 사용하고 있습니다.

(현재 ewebkit은 webkit.org에서 제거되어 ewebkit2만 남았습니다.)


ewebkit을 사용한 코드들은 elm_web (http://git.enlightenment.org/core/elementary.git/tree/src/lib/elm_web.c) 이나 WebKit 프로젝트 내의 http://trac.webkit.org/browser/trunk/Tools/EWebLauncher/main.c 가있습니다.

ewebkit2를 사용한 코드들은 elm_web2(http://git.enlightenment.org/core/elementary.git/tree/src/lib/elm_web2.c),  또는 WebKit 프로젝트 내의 http://trac.webkit.org/browser/trunk/Tools/MiniBrowser/efl/main.c 가 있습니다.


참고삼아 보시면 될 듯 하고, 이 글에서는 ewebkit2 의 코드를 MiniBrowser 기반으로 설명을 드리려고 합니다.

(http://trac.webkit.org/browser/trunk/Tools/MiniBrowser/efl/main.c 정도의 설명입니다.)


혹시 EFL 에 대해서 잘 모르신다면, 이 글을 읽기에 부담스러우실 수 있습니다.

(과감히 뒤로가기를 누르셔도 됩니다.)


(

혹, EFL에 관심이 있으시면 먼저 아래 글을 보시는 것을 추천드립니다.

https://events.linuxfoundation.org/images/stories/pdf/lfcs2012_raster.pdf

)


1. 생성 / 소멸

다른 EFL 라이브러리들처럼 ewebkit/ewebkit2도 전역의  _init 과  _shutdown 을 가지고 있습니다.


### c++

int main ()

{

    ewk_init();

    ...

    ewk_shutdown();

    return 0;

}

반드시 사용하기 전에 호출해주셔야 합니다.

가능하면 main 시작하자마자 ewk_init을 호출하고, loop가 끝난 후 ewk_shutdown을 호출해주시는 것이 좋습니다.


다음으로,ewk_view 객체를 만들어야 합니다.

ewk_view를 만드는 방법은 여러가지가 있습니다. 하나씩 살펴보도록 하겠습니다.


1) ewk_view_add(Evas *e)

ewk_view_add 는 ewk_view를 만드는 가장 쉬운 방법입니다.

간단한 페이지를 로드하는 데는 적합하지만, alert/prompt/confirm이라던가 새창을 열거나 그 밖에 UI의 도움을 받아야 하는 많은 것들을 할 수 없습니다.

또, ewebkit에서는 관계없으나 ewebkit2에서는 매 evas object가 별도의 WebProcess를 생성하여 동작하게 됩니다.


### c++

Evas_Object *o = ewk_view_add(e);

ewk_view_url_set(o, "http://bunhere.tistory.com");


2) ewk_view_add_with_context(Evas *e, Ewk_Context *context)

ewebkit에서는 없는 함수입니다.

ewebkit2에서는 web context 라는 것이 있어서 하나의 web context는 하나의 WebProcess를 생성하게 합니다. 만약 이미 생성한 web context 안에 웹뷰를 만들려고 하면 이 함수를 사용해서 생성하면 됩니다.


### c++

// o 와 같은 context(web process)에서 동작하는 ewk_view를 생성

Evas_Object *o2 = ewk_view_add_with_context(e, ewk_view_context_get(o));


3) ewk_view_smart_add(Evas *e, Evas_Smart *smart, Ewk_Context *context, Ewk_Page_Group *group)

해당 API는 ewebkit에는 없습니다.(유사한 방법이 있으나 별도의 API 로 존재하지 않습니다.)


이 API 를 쓰면 ewk_view가 할 수 있는 일을 모두 할 수 있습니다.

물론 그만큼 사용하기 어렵다는 문제도 있습니다.


먼저, 인자들을 하나씩 살펴보도록 하겠습니다.

Evas *e

현재 생성하는 ewk_view의 기반이 될 canvas입니다.


Evas_Smart *smart

ewk_view는 여러 Evas_Object들 중 smart object로 만들어졌습니다.

Smart Object를 만드는 것에 대한 자세한 내용은 아래 글을 참고하시면 좋을 것 같습니다.

http://docs.enlightenment.org/stable/efl/Example_Evas_Smart_Objects.html


일반적으로 smart object를 만들때는 smart class를 만들어서 evas_object_smart_add를 호출하면 되지만, ewk_view는 추가로 처리해야 하는 인자들이 있어서 ewk_view_smart_add를 대신 사용합니다.

ewk_view_smart_add는 내부적으로 evas_object_smart_add의 일을 수행하게 됩니다.

(ewebkit은 evas_object_smart_add를 사용합니다.)

Evas_Smart를 만드는 법은 복잡하기 때문에 아래에서 다시 설명하겠습니다.


Ewk_Context *context

여러 ewk_view는 하나의 context를 가질 수도 있고, 여러개의 context를 가질 수도 있습니다.

하나의 context에 기반한 ewk_view들은 많은 것을 공유하게 됩니다.

특히 하나의 프로세스에서 수행되게 될 것입니다.

context를 구하려면 기존의 ewk_view 를 이용하여 ewk_view_context_get(o)을 하거나, ewk_context_default_get()을 이용하여 default context를 생성하면 됩니다.


Ewk_Page_Group *group

page group을 이해하는 쉬운 예제는 자바스크립트로 실행한 새창입니다. 자바스크립트로 새창을 열면 해당 페이지와 새로 열린 페이지는 opener / child 관계를 갖게 됩니다. 이 두 페이지는 같은 세팅을 가져야 합니다. 세션도 공유할 것이고요.

이렇게 같은 설정을 가져야 하고 정보들을 공유해야 한다면 같은 page group으로 묶어야 합니다.

page group을 얻는 방법은 기존의 ewk_view를 이용하여 ewk_view_page_group(o)을 호출하거나 ewk_page_group_create(group_name) 을 호출하여 특정 그룹을 생성하면 됩니다. group_name이 null이면 임의의 그룹을 생성하게 됩니다.


Evas_Smart 만들기

Evas_Smart를 만들려면 smart class를 하나 만들어야 합니다.

특히 ewk_view를 위한 smart class는 Evas_Smart_Class 를 확장한 Ewk_View_Smart_Class입니다.

사용자는 Ewk_View_Smart_Class를 확장하거나, Ewk_View_Smart_Class를 고쳐서 쓸 수 있습니다.

확장을 해서 쓸 경우, 기본 구현을 오버라이드하여 이용하기 좋다는 장점이 있습니다만, 대부분의 경우에는 기본 구현이 없습니다.(마우스/터치 이벤트 제외)


이 글에서는 일단 Ewk_View_Smart_Class를 고쳐서 쓰려고 합니다.

###  c++

static Ewk_View_Smart_Class *miniBrowserViewSmartClass()                                                                                                                 
{
    static Ewk_View_Smart_Class ewkViewClass = EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION("MiniBrowser_View");
    return &ewkViewClass;
}

MiniBrowser에서 발췌한 코드로 Ewk_View_Smart_Class 객체를 하나 만들어서 MiniBrowser_View라는 이름으로 초기화했습니다.

이 때, 값들은 모두 NULL로 초기화 될 것입니다.

ewk_view가 제공하는 메소드들로 재정의하기 위해서 ewk_view_smart_class_set을 호출해 주어야 합니다.

사실 ewk_view는 재정의할 메소드들이 별로 없습니다만 이 함수는 반드시 호출되어야 합니다. 가장 중요한 Evas_Smart_Class의 메소드들이 연결될 것입니다.

### c++

    if (!ewk_init())
        return EXIT_FAILURE;

    ewk_view_smart_class_set(miniBrowserViewSmartClass());


이제 어플리케이션에서 필요로 하는 기능들에 대해 추가로 수정을 하시면 됩니다.

### c++

    Ewk_View_Smart_Class *ewkViewClass = miniBrowserViewSmartClass();                                                                                                    
    ewkViewClass->run_javascript_alert = on_javascript_alert;
    ewkViewClass->run_javascript_confirm = on_javascript_confirm;
    ewkViewClass->run_javascript_prompt = on_javascript_prompt;
    ewkViewClass->window_geometry_get = on_window_geometry_get;
    ewkViewClass->window_geometry_set = on_window_geometry_set;
    ewkViewClass->fullscreen_enter = on_fullscreen_enter;
    ewkViewClass->fullscreen_exit = on_fullscreen_exit;
    ewkViewClass->window_create = on_window_create;
    ewkViewClass->window_close = on_window_close;
    ewkViewClass->popup_menu_show = on_popup_menu_show;
    ewkViewClass->popup_menu_hide = on_popup_menu_hide;
    ewkViewClass->context_menu_show = on_context_menu_show;
    ewkViewClass->context_menu_hide = on_context_menu_hide;
    ewkViewClass->input_picker_color_request = on_color_picker_request;
    ewkViewClass->input_picker_color_dismiss = on_color_picker_dismiss;

앞서 말씀 드린 것과 같이 마우스 이벤트와 같은 몇몇 이벤트를 제외하면 ewkViewClass가 추가한 메소드들은 특수한 구현들을 갖고 있지 않습니다.


각각의 메소드들이 어떤 인자들과 반환값을 가져야 하는지는 http://trac.webkit.org/browser/trunk/Source/WebKit2/UIProcess/API/efl/ewk_view.h 를 참고하셔야 합니다.

몇몇 메소드들은 아래에서 좀 더 설명하도록 하겠습니다.


이렇게 smart class가 준비되었다면 Evas_Smart를 만들면 됩니다.

### c++

Evas_Smart *smart = evas_smart_class_new(&ewkViewClass->sc);

sc는 Evas_Smart_Class를 가르키는 주소입니다.


아래는 MiniBrowser에서 ewk_view_smart_add를 호출하는 일부 코드입니다..

### c++

    Evas *evas = evas_object_evas_get(window->elm_window);
    Evas_Smart *smart = evas_smart_class_new(&ewkViewClass->sc);
    Ewk_Context *context = opener ? ewk_view_context_get(opener) : ewk_context_default_get();
    Ewk_Page_Group *pageGroup = opener ? ewk_view_page_group_get(opener) : ewk_page_group_create("");
    window->ewk_view = ewk_view_smart_add(evas, smart, context, pageGroup);


생성과 달리 소멸은 간단히 evas_object_del을 호출해주면 됩니다.


2. Load contents

ewebkit에서 contents를 읽는 방법은 두가지가 있습니다.
가장 기본적인 방법인 url을 읽는 방법과, html string을 읽는 방법입니다.


url을 읽는 API는 다음과 같습니다.

### c++

ewk_view_url_set(view, "http://bunhere.tistory.com");

그 다음은 알아서 로딩이 된 후, 화면에 그려지게 됩니다.


html string을 직접 읽는 방법도 크게 어렵지는 않습니다.

### c++

ewk_view_html_string_load(view, "<!doctype html><body>hello</body>", base_uri, unreachable_uri);

img나 기타 리소스들이 상대 경로로 놓여질 때 읽어올 base_uri, 에러가 났을때 알려줄 unreachable_uri가 추가된 것을 제외하면 특별한 것이 없습니다. 그리고 이 값들은 NULL로 넘겨도 상관없습니다.


간단한 예제


여기까지 이야기한 것들을 바탕으로 가장 간단한 ewebkit 기반의 웹브라우저를 만들어보겠습니다.

https://github.com/ewebkit/samples/blob/master/devs/ryuan/simple.c

### c++

// gcc simplebutton.cpp `pkg-config --cflags --libs elementary ewebkit2`           
#include <Elementary.h>                                                            
#include <EWebKit2.h>                                                              
                                                                                   
void on_done(void *userData, Evas_Object *webView, void *eventInfo)
{
   elm_exit();
}

EAPI_MAIN int
elm_main(int argc, char *argv[])
{
   ewk_init();

   Evas_Object* win;
   win = elm_win_add(NULL, "sample", ELM_WIN_BASIC);
   elm_win_title_set(win, "sample");
   evas_object_smart_callback_add(win, "delete,request", on_done, NULL);
   elm_win_autodel_set(win, EINA_TRUE);

   Evas_Object* bg = elm_bg_add(win);
   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
   elm_bg_color_set(bg, 0, 0, 255);
   elm_win_resize_object_add(win, bg);
   evas_object_show(bg);

   Evas_Object* ewk = ewk_view_add(evas_object_evas_get(win));
   ewk_view_url_set(ewk, "http://bunhere.tistory.com");

   evas_object_resize(ewk, 400, 400);
   evas_object_move(ewk, 0, 0);
   evas_object_show(ewk);

   evas_object_resize(win, 400, 400);
   evas_object_show(win);

   elm_run();

   ewk_shutdown();                                                                                                                                                      
}                                                                                  
ELM_MAIN()


실행 결과입니다.



저작자 표시
신고

'Open Source > EFL' 카테고리의 다른 글

[EFL] EWebKit Extension  (0) 2014.09.23
transparent ewebkit  (0) 2014.07.30
Hello ewebkit?  (2) 2014.03.14
WebKit/efl 하면서 쓸 ctags 만들기  (0) 2013.12.17
Elementary Dark theme  (0) 2013.10.17
[TIZEN][EFL] 타이젠 상에서 EFL 예제 실행하기  (9) 2013.08.02
Posted by 소혼
TAG EFL, Webkit

이전에 작성한 linkElement, style element에 이어 media rule을 사용해 media query를 주었을 때 웹킷이 처리하는 과정을 정리해보고자 합니다.


이전글 1 : Media query in webkit(link Element)

이전글 2 : Media query in webkit(style element)


특히 이전글2는 반드시 읽으셔야 합니다.


사용할 예제는 이전글2에서 잠깐 보여드렸던 것과 동일합니다.

### html

<!doctype html>
<head>
<style>
@media screen and (min-width:300px) {
body { background-color:red; }
}
</style>
<body>
hello
</body>


시작 지점은 이전 예제의 밑에서 두번째 코드인 DocumentRuleSets::appendAuthorStyleSheets 입니다.

### c++ ; highlight : 21

void DocumentRuleSets::appendAuthorStyleSheets(unsigned firstNew, const Vector<RefPtr<CSSStyleSheet> >& styleSheets, MediaQueryEvaluator* medium, InspectorCSSOMWrappers& inspectorCSSOMWrappers, bool isViewSource, StyleResolver* resolver)
{
    // This handles sheets added to the end of the stylesheet list only. In other cases the style resolver
    // needs to be reconstructed. To handle insertions too the rule order numbers would need to be updated.
    unsigned size = styleSheets.size();
    for (unsigned i = firstNew; i < size; ++i) {
        CSSStyleSheet* cssSheet = styleSheets[i].get();
        ASSERT(!cssSheet->disabled());
        if (cssSheet->mediaQueries() && !medium->eval(cssSheet->mediaQueries(), resolver))
            continue;
        StyleSheetContents* sheet = cssSheet->contents();
#if ENABLE(STYLE_SCOPED) || ENABLE(SHADOW_DOM)
        if (const ContainerNode* scope = StyleScopeResolver::scopeFor(cssSheet)) {
            // FIXME: Remove a dependency to calling a StyleResolver's member function.
            // If we can avoid calling resolver->ensureScopeResolver() here, we don't have to include "StyleResolver.h".
            // https://bugs.webkit.org/show_bug.cgi?id=108890
            resolver->ensureScopeResolver()->ensureRuleSetFor(scope)->addRulesFromSheet(sheet, *medium, resolver, scope);
            continue;
        }
#endif
        m_authorStyle->addRulesFromSheet(sheet, *medium, resolver);
        inspectorCSSOMWrappers.collectFromStyleSheetIfNeeded(cssSheet);
    }
    m_authorStyle->shrinkToFit();
    collectFeatures(isViewSource, resolver->scopeResolver());
}


현재 styleSheet에 mediaQuery가 있다면, 2번글에서와 같이 eval과정을 거쳐서 addRulesFromSheet를 수행할지 말지를 결정할 것입니다. [9, 21라인]

하지만, 이번 예제에서 stylesheet에는 mediaQuery가 없습니다. 따라서 addRulesFromSheet가 수행됩니다.


addRulesFromSheet는 다음과 같습니다.


### c++

void RuleSet::addRulesFromSheet(StyleSheetContents* sheet, const MediaQueryEvaluator& medium, StyleResolver* resolver, const ContainerNode* scope)
{  
    ASSERT(sheet);                                                                                          
   
    const Vector<RefPtr<StyleRuleImport> >& importRules = sheet->importRules();                             
    for (unsigned i = 0; i < importRules.size(); ++i) {
        StyleRuleImport* importRule = importRules[i].get();
        if (importRule->styleSheet() && (!importRule->mediaQueries() || medium.eval(importRule->mediaQueries(), resolver)))
            addRulesFromSheet(importRule->styleSheet(), medium, resolver, scope);                           
    }                                                                                                       
                                                                                                            
    bool hasDocumentSecurityOrigin = resolver && resolver->document()->securityOrigin()->canRequest(sheet->baseURL());
    AddRuleFlags addRuleFlags = static_cast<AddRuleFlags>((hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : 0) | (!scope ? RuleCanUseFastCheckSelector : 0));
   
    addChildRules(sheet->childRules(), medium, resolver, scope, hasDocumentSecurityOrigin, addRuleFlags);   
                                                                                                            
    if (m_autoShrinkToFitEnabled)
        shrinkToFit();                                                                                      
}

sheet의 import rule들을 모두 순회하며, import rule의 media query를 확인, 있으면, 해당 import rule의 styleSheet를 위해 addRulesFromSheet를 호출합니다.

여기서는  import rule도 없으므로 지나가면 addChildRules라는 함수에서 실제 childRules들을 반영합니다. 이 함수의 인자에도 medium이 있는 것을 볼 수 있습니다.


### c++ ; highlight : [11, 13]

void RuleSet::addChildRules(const Vector<RefPtr<StyleRuleBase> >& rules, const MediaQueryEvaluator& medium, StyleResolver* resolver, const ContainerNode* scope, bool hasDocumentSecurityOrigin, AddRuleFlags addRuleFlags)
{
    for (unsigned i = 0; i < rules.size(); ++i) {
        StyleRuleBase* rule = rules[i].get();

        if (rule->isStyleRule()) {
            StyleRule* styleRule = static_cast<StyleRule*>(rule);
            addStyleRule(styleRule, addRuleFlags);
        } else if (rule->isPageRule())
            addPageRule(static_cast<StyleRulePage*>(rule));
        else if (rule->isMediaRule()) {
            StyleRuleMedia* mediaRule = static_cast<StyleRuleMedia*>(rule);
            if ((!mediaRule->mediaQueries() || medium.eval(mediaRule->mediaQueries(), resolver)))
                addChildRules(mediaRule->childRules(), medium, resolver, scope, hasDocumentSecurityOrigin, addRuleFlags);
        } else if (rule->isFontFaceRule() && resolver) {
            // Add this font face to our set.
            // FIXME(BUG 72461): We don't add @font-face rules of scoped style sheets for the moment.
            if (scope)
                continue;
            const StyleRuleFontFace* fontFaceRule = static_cast<StyleRuleFontFace*>(rule);
            resolver->fontSelector()->addFontFaceRule(fontFaceRule);
            resolver->invalidateMatchedPropertiesCache();
        } else if (rule->isKeyframesRule() && resolver) {
            // FIXME (BUG 72462): We don't add @keyframe rules of scoped style sheets for the moment.
            if (scope)
                continue;
            resolver->addKeyframeStyle(static_cast<StyleRuleKeyframes*>(rule));
        }
#if ENABLE(CSS_REGIONS)
        else if (rule->isRegionRule() && resolver) {
            // FIXME (BUG 72472): We don't add @-webkit-region rules of scoped style sheets for the moment.
            if (scope)
                continue;
            addRegionRule(static_cast<StyleRuleRegion*>(rule), hasDocumentSecurityOrigin);
        }
#endif
#if ENABLE(SHADOW_DOM)
        else if (rule->isHostRule())
            resolver->addHostRule(static_cast<StyleRuleHost*>(rule), hasDocumentSecurityOrigin, scope);
#endif
#if ENABLE(CSS_DEVICE_ADAPTATION)
        else if (rule->isViewportRule() && resolver) {
            // @viewport should not be scoped.
            if (scope)
                continue;
            resolver->viewportStyleResolver()->addViewportRule(static_cast<StyleRuleViewport*>(rule));
        }
#endif
#if ENABLE(CSS3_CONDITIONAL_RULES)
        else if (rule->isSupportsRule() && static_cast<StyleRuleSupports*>(rule)->conditionIsSupported())
            addChildRules(static_cast<StyleRuleSupports*>(rule)->childRules(), medium, resolver, scope, hasDocumentSecurityOrigin, addRuleFlags);

#endif

    }

}

다양한 CSS rule들을 처리하는 코드 가운데 media rule에 관한 코드를 발견하실 수 있습니다. [11라인]



media query를 발생시키는 코드들은 다 살펴보았지만, 2번글 마지막에서 잠깐 언급했던 것과 같이, viewport와 관련된 media query는 화면의 크기등이 바뀌었을 때 다시 계산할 필요가 있습니다.


예를 들어 webview를 resize하는 경우, FrameView의 size가 변경되어 FrameView::setFrameRect가 호출될 것입니다.


### c++ ; highlight : [33, 34, 35, 36, 37]

void FrameView::setFrameRect(const IntRect& newRect)
{
    IntRect oldRect = frameRect();
    if (newRect == oldRect)              
        return;
       
#if ENABLE(TEXT_AUTOSIZING)
    // Autosized font sizes depend on the width of the viewing area.
    if (newRect.width() != oldRect.width()) {
        Page* page = m_frame ? m_frame->page() : 0;
        if (page && page->mainFrame() == m_frame && page->settings()->textAutosizingEnabled()) {
            for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext())        
                m_frame->document()->textAutosizer()->recalculateMultipliers();
        }                
    }
#endif

    ScrollView::setFrameRect(newRect);

    updateScrollableAreaSet();

    RenderView* renderView = this->renderView();

#if USE(ACCELERATED_COMPOSITING)
    if (renderView) {
        if (renderView->usesCompositing())
            renderView->compositor()->frameViewDidChangeSize();
    }
#endif

    Document* document = m_frame ? m_frame->document() : 0;

    // Viewport-dependent media queries may cause us to need completely different style information.
    if (document && document->styleResolverIfExists() && document->styleResolverIfExists()->affectedByViewportChange()) {
        document->styleResolverChanged(DeferRecalcStyle);
        InspectorInstrumentation::mediaQueryResultChanged(document);
    }

    sendResizeEventIfNeeded();
}

document객체에 있는 styleResolver의 affectedByViewportChange를 통해 media query의 결과가 바뀌었는지 보고[34 라인],

바뀌었다면, styleResolverChanged를 다시 불러줍니다.[35라인]


affectedByViewportChange는 아래와 같습니다.


### c++

bool StyleResolver::affectedByViewportChange() const
{
    unsigned s = m_viewportDependentMediaQueryResults.size();
    for (unsigned i = 0; i < s; i++) {
        if (m_medium->eval(&m_viewportDependentMediaQueryResults[i]->m_expression) != m_viewportDependentMediaQueryResults[i]->m_result)
            return true;
    }
    return false;
}


저작자 표시 비영리 변경 금지
신고
Posted by 소혼

이전에 작성한 linkElement에 이어 style element로 media query를 주었을 때 웹킷이 처리하는 과정을 정리해보고자 합니다.

style element에 대한 처리를 알려면, webkit이 style element을 처리하는 전반적인 플로우를 이해해야 합니다.

하지만, 여기서는 되도록 media query에 집중해서 설명하려고 노력할 생각입니다.


이전글 : Media query in webkit(link Element)

다음글 : Media query in webkit(import/media rule)


이번에 다룰 예제는 아래와 같습니다.


### html

<!doctype html>
<head>
<style media="screen and (min-width:300px)">
body { background-color:red; }
</style>
<body>
hello
</body>

HTML specification에서 style element를 보면 attribute로 media를 지정할 수 있습니다.


먼저 이 코드를 크롬으로 로드하여 inspector를 통해 document.styleSheets를 보도록 하겠습니다.


StyleSheetList에 한 개의 stylesheet가 있고, 0번째 CSSStyleSheet에는 cssRules, disabled, href, media, 등등이 있습니다.

MediaList타입의 media 프로퍼티에는 style element의 attribute로 넘긴 media query 정보가 들어 있음을 알 수 있습니다.

CSSRuleList타입의 cssRules에는 1개의 CSSStyleRule이 있고 이 안에 지정한 스타일 정보가 들어있음을 알 수 있습니다.


여기서 표현되는 CSSStyleSheet, CSSRuleList, CSSStyleRul은 웹킷 내부에 동일한 이름의 클래스와 매칭됩니다.


이번 글에서 다루진 않겠지만 참고 삼아, 예제를 조금 고쳐보겠습니다. 이번에는 @media rule을 사용한 경우입니다.


### html

<!doctype html>
<head>
<style>
@media screen and (min-width:300px) {
body { background-color:red; }
}
</style>
<body>
hello
</body>




이렇게 변경하면 CSSStyleSheet가 가진 media 프로퍼티에는 아무런 값이 존재하지 않습니다.

대신 cssRules 가 직접 CSSStyleRule을 갖는 것이 아니라, CSSMediaRule을 갖는 것을 알 수 있습니다. CSSMediaRule이  CSSStyleRule을 갖습니다.


[WebKit Internal]

WebKit에서 Style tag를 담당하는 클래스는 HTMLStyleElement와 StyleElement입니다.

HTMLStyleElement는 StyleElement를 상속받습니다. (class HTMLStyleElement : public HTMLElement, private StyleElement)

SVGStyleElement와 공용으로 쓸 수 있는 기능들이 StyleElement안에 있는듯 합니다.


먼저 </style>태그를  만나 읽게 되면  HTMLElement들은 finishParsingChildren을 호출합니다.

HTMLStyleElement 도 해당 함수의 구현을 갖고 있습니다.


### c++

void HTMLStyleElement::finishParsingChildren()
{
    StyleElement::finishParsingChildren(this);
    HTMLElement::finishParsingChildren();
}

여기서 관심을 갖는 부분은 StyleElement입니다.


### c++ ; highlight : [29, 34]

void StyleElement::finishParsingChildren(Element* element)
{  
    ASSERT(element);
    process(element);
    m_createdByParser = false;
}

void StyleElement::process(Element* e)
{  
    if (!e || !e->inDocument())
        return;
   
    unsigned resultLength = 0;
    for (Node* c = e->firstChild(); c; c = c->nextSibling()) {
        if (isValidStyleChild(c)) {
            unsigned length = c->nodeValue().length();
            if (length > std::numeric_limits<unsigned>::max() - resultLength) {
                createSheet(e, m_startLineNumber, "");
                return;
            }
            resultLength += length;
        }
    }
    StringBuilder sheetText;
    sheetText.reserveCapacity(resultLength);
   
    for (Node* c = e->firstChild(); c; c = c->nextSibling()) {
        if (isValidStyleChild(c)) {
            sheetText.append(c->nodeValue());
        }
    }
    ASSERT(sheetText.length() == resultLength);
   
    createSheet(e, m_startLineNumber, sheetText.toString());
}

StyleElement::finishParsingChildren가 하는 일도 간단히 process()를 부르는 일이 전부입니다.

process()는

1. parsing이 끝났을때(finishParsingChildren),

2. StyleElement가 document에 insert 되었을 때(insertIntoDocument)

3. 자식 노드들이 바뀌었을 때(childrendChanged)

호출됩니다.


process()안을 보시면, child node 가운데 validStyleChild만 찾아서 해당하는 sheetText에 추가하는 것을 알 수 있습니다.(29 line)

위 예제에서는 하나의 노드(TextNode)만을 가지고

값(nodeValue)은 "

body { background-color:red; }

" 입니다. (<style>부터 </style>까지 이기 때문에 위 예제에서는 앞뒤로 newline이 있습니다.)


### c++

static bool isValidStyleChild(Node* node)
{  
    ASSERT(node);
    Node::NodeType nodeType = node->nodeType();
    return nodeType == Node::TEXT_NODE || nodeType == Node::CDATA_SECTION_NODE;
}

validStyleChild는 단순히 TEXT_NODE와 CDATA_SECTION_NODE 인지 여부만 체크합니다.


사실상 핵심은 sheet를 만드는 것입니다.(StyleElement::process의 34 line)

StyleElement::process는 엘리먼트(e)와 시작라인, sheetText 문자열(valid한 child node들의 문자열)을 createSheet에게 넘겨줍니다.


### c++ ; highlight: [6,7,8,9,10, 17]

void StyleElement::createSheet(Element* e, WTF::OrdinalNumber startLineNumber, const String& text)
{            
    ASSERT(e);             
    ASSERT(e->inDocument());          
    Document* document = e->document();
    if (m_sheet) {              
        if (m_sheet->isLoading())                                 
            document->styleSheetCollection()->removePendingSheet();
        clearSheet();
    }
                                                          
    // If type is empty or CSS, this is a CSS style sheet.
    const AtomicString& type = this->type();                                       
    if (document->contentSecurityPolicy()->allowInlineStyle(e->document()->url(), startLineNumber) && isCSS(e, type)) {
        RefPtr<MediaQuerySet> mediaQueries;
        if (e->isHTMLElement())
            mediaQueries = MediaQuerySet::createAllowingDescriptionSyntax(media());
        else
            mediaQueries = MediaQuerySet::create(media());
           
        MediaQueryEvaluator screenEval("screen", true);
        MediaQueryEvaluator printEval("print", true);
        if (screenEval.eval(mediaQueries.get()) || printEval.eval(mediaQueries.get())) {

            // ... 생략, 아래에서 계속
        }  
    }
               
    if (m_sheet)
        m_sheet->contents()->checkLoaded();
}

먼저 기존에 만든 CSSStyleSheet이 있는지 확인하고, 있다면 제거합니다. (6-10 line). 이 때 CSSStyleSheet이 로딩중이면 제거합니다.(8line)

StyleElement가 가진 CSSStyleSheet이 로딩중인 케이스는 import rule을 생각하시면 됩니다.


현재 StyleElement는 HTMLStyleElement 에서 this를 받아왔기 때문에 MediaQuerySet::createAllowingDescriptionSyntax(media())를 호출합니다.(17 line)


Media query in webkit(linkElement)를 읽으신 분들은 MediaQueryEvaluator을 만들때 추가로 요구하는 값들이 있었다는 것을 기억해주시기 바랍니다.

FrameView의 mediaType, frame, documentStyle입니다. 여기서는 FrameView의 media type대신 "screen"과 "print" 두개의 MediaQueryEvaluator를 만들고 있고 다른 값들은 넘겨주지 않습니다. 

다른 값들이 없으면 media feature를 확인하는 것이 불가능합니다.

이전 글에서 colorMediaFeatureEval의 구현을 보시면, frame을 이용하여 screenDepth를 구하고 있는 것을 알 수 있습니다.


여기서는 대신 두 번째 인자로 true를 넘겨주고 있습니다. 이 값은 MediaQueryEvaluator의 멤버인 m_expResult의 값이 됩니다.

그리고 MediaQueryEvaluator::eval(MediaQueryExp*) const을 다시 보시면,

### c++ ; hilight : [3, 4]

bool MediaQueryEvaluator::eval(const MediaQueryExp* expr) const
{
    if (!m_frame || !m_style)
        return m_expResult;

    if (!expr->isValid())
        return false;

    if (!gFunctionMap)
        createFunctionMap();

    // call the media feature evaluation function. Assume no prefix
    // and let trampoline functions override the prefix if prefix is
    // used
    EvalFunc func = gFunctionMap->get(expr->mediaFeature().impl());
    if (func)
        return func(expr->value(), m_style.get(), m_frame, NoPrefix);

    return false;
}

frame과 style의 값이 없을 때 m_expResult의 값을 반환합니다.(4 line)

즉, StyleElement::createSheet에서는 media type만 확인하고 true를 반환합니다.


### c++ ; highlight : [ 7, 10, 11, 13 ]

void StyleElement::createSheet(Element* e, WTF::OrdinalNumber startLineNumber, const String& text)
{
        // ... 생략, 위에서 계속
        MediaQueryEvaluator screenEval("screen", true);
        MediaQueryEvaluator printEval("print", true);
        if (screenEval.eval(mediaQueries.get()) || printEval.eval(mediaQueries.get())) {
            document->styleSheetCollection()->addPendingSheet();
            m_loading = true;

            m_sheet = CSSStyleSheet::createInline(e, KURL(), document->inputEncoding());
            m_sheet->setMediaQueries(mediaQueries.release());
            m_sheet->setTitle(e->title());
            m_sheet->contents()->parseStringAtLine(text, startLineNumber.zeroBasedInt());

            m_loading = false;
        }
    }

    if (m_sheet)
        m_sheet->contents()->checkLoaded();
}

media type이 screen이나 print를 포함한다면, StyleElement::createSheet의 7-15 line에서 CSSStyleSheet를 만듭니다.
먼저 document에 pending된 스타일 시트가 있음을 알립니다.(7 line). document에 pending된 스타일 시트가 있으면 웹코어는 layout을 주기적으로 스케줄링합니다.


그리고, CSSStyleSheet::createInline을 통해 stylesheet를 만듭니다.(9 line) 이 때, CSSStyleSheet::createInline은 StyleSheetContents를 만드는데 여기가 parsing된 결과물(CSSRule)이 저장되는 곳입니다.,


이 후, media query를 설정후(10 line), 넘겨받은 text data의 파싱을 수행합니다. (11 line)


parsing이 끝나면, checkLoaded를 통해 style을 적용할지를 결정합니다.

### c++ ; highlight : 23

void StyleSheetContents::checkLoaded()
{                                                                                  
    if (isLoading())                                                               
        return;                                                                    
                                                                                   
    RefPtr<StyleSheetContents> protect(this);                                      
                                                                                   
    // Avoid |this| being deleted by scripts that run via                          
    // ScriptableDocumentParser::executeScriptsWaitingForStylesheets().            
    // See <rdar://problem/6622300>.                                               
    RefPtr<StyleSheetContents> protector(this);                                    
    StyleSheetContents* parentSheet = parentStyleSheet();                          
    if (parentSheet) {                                                             
        parentSheet->checkLoaded();                                                
        m_loadCompleted = true;                                                    
        return;                                                                    
    }                                                                              
    RefPtr<Node> ownerNode = singleOwnerNode();                                    
    if (!ownerNode) {                                                              
        m_loadCompleted = true;                                                    
        return;                                                                    
    }                                                                              
    m_loadCompleted = ownerNode->sheetLoaded();                                    
    if (m_loadCompleted)                                                           
        ownerNode->notifyLoadedSheetAndAllCriticalSubresources(m_didLoadErrorOccur);
}

먼저 자신이 로딩중이면, return합니다 (3 line). 예제에서는 로딩할 것이 없으므로 파싱이 끝나면 로딩도 끝납니다. 다음엔 parentSheet가 있으면 parentSheet를 check하는데 여기서는 parentSheet가 없으므로 ownerNode(StyleElement)의 sheetLoaded를 호출합니다. (23 line)


### c++

bool StyleElement::sheetLoaded(Document* document)
{                                                                                  
    ASSERT(document);                                                              
    if (isLoading())
        return false;                                                              
   
    document->styleSheetCollection()->removePendingSheet();                        
    return true;                                                                   
}

pendingSheet를 제거합니다.


### c++ ; highlight : [14, 22]

// This method is called whenever a top-level stylesheet has finished loading.
void DocumentStyleSheetCollection::removePendingSheet(RemovePendingSheetNotificationType notification)
{  
    // Make sure we knew this sheet was pending, and that our count isn't out of sync.
    ASSERT(m_pendingStylesheets > 0);

    m_pendingStylesheets--;
    
#ifdef INSTRUMENT_LAYOUT_SCHEDULING                                                
    if (!ownerElement())                                                           
        printf("Stylesheet loaded at time %d. %d stylesheets still remain.\n", elapsedTime(), m_pendingStylesheets);
#endif 
   
    if (m_pendingStylesheets)
        return;

    if (notification == RemovePendingSheetNotifyLater) {
        m_document->setNeedsNotifyRemoveAllPendingStylesheet();                    
        return;
    }
   
    m_document->didRemoveAllPendingStylesheet();                                   
}

pendingStyleSheets가 더이상 없다면(14 line), didRemoveAllPendingStylesheet를 호출합니다.


### c++ ; highlight : 5

void Document::didRemoveAllPendingStylesheet()                                     
{  
    m_needsNotifyRemoveAllPendingStylesheet = false;

    styleResolverChanged(RecalcStyleIfNeeded);
   
    if (ScriptableDocumentParser* parser = scriptableDocumentParser())
        parser->executeScriptsWaitingForStylesheets();
   
    if (m_gotoAnchorNeededAfterStylesheetsLoad && view())
        view()->scrollToFragment(m_url);
}

StyleResolve가 변경되었음을 알려줍니다.(5 line)


### c++ ; highlight : 19

void Document::styleResolverChanged(StyleResolverUpdateFlag updateFlag)
{
    // Don't bother updating, since we haven't loaded all our style info yet
    // and haven't calculated the style selector for the first time.
    if (!attached() || (!m_didCalculateStyleResolver && !haveStylesheetsLoaded())) {
        m_styleResolver.clear();
        return;
    }
    m_didCalculateStyleResolver = true;

#ifdef INSTRUMENT_LAYOUT_SCHEDULING
    if (!ownerElement())
        printf("Beginning update of style selector at time %d.\n", elapsedTime());
#endif

    DocumentStyleSheetCollection::UpdateFlag styleSheetUpdate = (updateFlag == RecalcStyleIfNeeded)
        ? DocumentStyleSheetCollection::OptimizedUpdate
        : DocumentStyleSheetCollection::FullUpdate;
    bool stylesheetChangeRequiresStyleRecalc = m_styleSheetCollection->updateActiveStyleSheets(styleSheetUpdate);

    if (updateFlag == DeferRecalcStyle) {
        scheduleForcedStyleRecalc();
        return;
    }

    // ...

}

styleResolverChanged는 webkit이 layout을 다시 수행하게 되는 관문격에 해당하는 메소드입니다.

이 메소드에서 updateActiveStyleSheets가 호출되어 스타일 시트들을 업데이트 하게 됩니다. (19 line)


### c++ ; highlight : [16, 22, 35, 38]

bool DocumentStyleSheetCollection::updateActiveStyleSheets(UpdateFlag updateFlag)
{
    if (m_document->inStyleRecalc()) {
        // SVG <use> element may manage to invalidate style selector in the middle of a style recalc.
        // https://bugs.webkit.org/show_bug.cgi?id=54344
        // FIXME: This should be fixed in SVG and the call site replaced by ASSERT(!m_inStyleRecalc).
        m_needsUpdateActiveStylesheetsOnStyleRecalc = true;
        m_document->scheduleForcedStyleRecalc();
        return false;
       
    }
    if (!m_document->renderer() || !m_document->attached())
        return false;
       
    Vector<RefPtr<StyleSheet> > activeStyleSheets;
    collectActiveStyleSheets(activeStyleSheets);
   
    Vector<RefPtr<CSSStyleSheet> > activeCSSStyleSheets;
    activeCSSStyleSheets.append(injectedAuthorStyleSheets());
    activeCSSStyleSheets.append(documentAuthorStyleSheets());
    collectActiveCSSStyleSheetsFromSeamlessParents(activeCSSStyleSheets, m_document);
    filterEnabledCSSStyleSheets(activeCSSStyleSheets, activeStyleSheets);
   
    StyleResolverUpdateType styleResolverUpdateType;
    bool requiresFullStyleRecalc;
    analyzeStyleSheetChange(updateFlag, activeCSSStyleSheets, styleResolverUpdateType, requiresFullStyleRecalc);


    if (styleResolverUpdateType == Reconstruct)
        m_document->clearStyleResolver();
    else {                                                                             
        StyleResolver* styleResolver = m_document->styleResolver();
        if (styleResolverUpdateType == Reset) {
            styleResolver->ruleSets().resetAuthorStyle();
            styleResolver->appendAuthorStyleSheets(0, activeCSSStyleSheets);
        } else {
            ASSERT(styleResolverUpdateType == Additive);                               
            styleResolver->appendAuthorStyleSheets(m_activeAuthorStyleSheets.size(), activeCSSStyleSheets);                                                                    
        }
        resetCSSFeatureFlags();
    }

    m_activeAuthorStyleSheets.swap(activeCSSStyleSheets);
    m_styleSheetsForStyleSheetList.swap(activeStyleSheets);

// ...

updateActiveStyleSheets도 많은 일을 수행하지만 일단, collectActiveStyleSheets를 호출합니다. (16 line)

아래서 코드를 보겠지만, activeStyleSheets를 통해 현재 page의 style sheet를 가져오게 됩니다.

여기에 filterEnabledCSSStyleSheets 함수를 통해 activeStyleSheets중에 사용할 수 있는 것들만 activeCSSStyleSheets로 옮깁니다. ( 22 line)
그리고 styleResolver->appendAuthorStyleSheets를 호출합니다. (35 or 38 line)



### c++ ; highlight : [8, 25, 64, 87]

void DocumentStyleSheetCollection::collectActiveStyleSheets(Vector<RefPtr<StyleSheet> >& sheets)
{
    if (m_document->settings() && !m_document->settings()->authorAndUserStylesEnabled())
        return;

    StyleSheetCandidateListHashSet::iterator begin = m_styleSheetCandidateNodes.begin();
    StyleSheetCandidateListHashSet::iterator end = m_styleSheetCandidateNodes.end();
    for (StyleSheetCandidateListHashSet::iterator it = begin; it != end; ++it) {
        Node* n = *it;
        StyleSheet* sheet = 0;
        if (n->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) {
            // Processing instruction (XML documents only).
            // We don't support linking to embedded CSS stylesheets, see <https://bugs.webkit.org/show_bug.cgi?id=49281> for discussion.
            ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(n);
            sheet = pi->sheet();
#if ENABLE(XSLT)
            // Don't apply XSL transforms to already transformed documents -- <rdar://problem/4132806>
            if (pi->isXSL() && !m_document->transformSourceDocument()) {
                // Don't apply XSL transforms until loading is finished.
                if (!m_document->parsing())
                    m_document->applyXSLTransform(pi);
                return;
            }
#endif
        } else if ((n->isHTMLElement() && (n->hasTagName(linkTag) || n->hasTagName(styleTag)))
#if ENABLE(SVG)
                   ||  (n->isSVGElement() && n->hasTagName(SVGNames::styleTag))
#endif
                   ) {
            Element* e = static_cast<Element*>(n);
            AtomicString title = e->getAttribute(titleAttr);
            bool enabledViaScript = false;
            if (e->hasLocalName(linkTag)) {
                // <LINK> element
                HTMLLinkElement* linkElement = static_cast<HTMLLinkElement*>(n);
                if (linkElement->isDisabled())
                    continue;
                enabledViaScript = linkElement->isEnabledViaScript();
                if (linkElement->styleSheetIsLoading()) {
                    // it is loading but we should still decide which style sheet set to use
                    if (!enabledViaScript && !title.isEmpty() && m_preferredStylesheetSetName.isEmpty()) {
                        const AtomicString& rel = e->getAttribute(relAttr);
                        if (!rel.contains("alternate")) {
                            m_preferredStylesheetSetName = title;
                            m_selectedStylesheetSetName = title;
                        }
                    }
                    continue;
                }
                if (!linkElement->sheet())
                    title = nullAtom;
            }
            // Get the current preferred styleset. This is the
            // set of sheets that will be enabled.
#if ENABLE(SVG)
            if (n->isSVGElement() && n->hasTagName(SVGNames::styleTag))
                sheet = static_cast<SVGStyleElement*>(n)->sheet();
            else
#endif
            if (e->hasLocalName(linkTag))
                sheet = static_cast<HTMLLinkElement*>(n)->sheet();
            else
                // <STYLE> element
                sheet = static_cast<HTMLStyleElement*>(n)->sheet();
            // Check to see if this sheet belongs to a styleset
            // (thus making it PREFERRED or ALTERNATE rather than
            // PERSISTENT).
            AtomicString rel = e->getAttribute(relAttr);
            if (!enabledViaScript && !title.isEmpty()) {
                // Yes, we have a title.
                if (m_preferredStylesheetSetName.isEmpty()) {
                    // No preferred set has been established. If
                    // we are NOT an alternate sheet, then establish
                    // us as the preferred set. Otherwise, just ignore
                    // this sheet.
                    if (e->hasLocalName(styleTag) || !rel.contains("alternate"))
                        m_preferredStylesheetSetName = m_selectedStylesheetSetName = title;
                }
                if (title != m_preferredStylesheetSetName)
                    sheet = 0;
            }

            if (rel.contains("alternate") && title.isEmpty())
                sheet = 0;
        }
        if (sheet)
            sheets.append(sheet);
    }
}

CandidateNode들을 돌면서 style element의 sheet를 append합니다.


styleResolver->appendAuthorStyleSheets는 결국 DocumentRuleSets::appendAuthorStyleSheets를 호출합니다.

### c++ ; highlight : [9, 21]

void DocumentRuleSets::appendAuthorStyleSheets(unsigned firstNew, const Vector<RefPtr<CSSStyleSheet> >& styleSheets, MediaQueryEvaluator* medium, InspectorCSSOMWrappers& inspectorCSSOMWrappers, bool isViewSource, StyleResolver* resolver)
{
    // This handles sheets added to the end of the stylesheet list only. In other cases the style resolver
    // needs to be reconstructed. To handle insertions too the rule order numbers would need to be updated.
    unsigned size = styleSheets.size();
    for (unsigned i = firstNew; i < size; ++i) {
        CSSStyleSheet* cssSheet = styleSheets[i].get();
        ASSERT(!cssSheet->disabled());
        if (cssSheet->mediaQueries() && !medium->eval(cssSheet->mediaQueries(), resolver))
            continue;
        StyleSheetContents* sheet = cssSheet->contents();
#if ENABLE(STYLE_SCOPED) || ENABLE(SHADOW_DOM)
        if (const ContainerNode* scope = StyleScopeResolver::scopeFor(cssSheet)) {
            // FIXME: Remove a dependency to calling a StyleResolver's member function.
            // If we can avoid calling resolver->ensureScopeResolver() here, we don't have to include "StyleResolver.h".
            // https://bugs.webkit.org/show_bug.cgi?id=108890
            resolver->ensureScopeResolver()->ensureRuleSetFor(scope)->addRulesFromSheet(sheet, *medium, resolver, scope);
            continue;
        }
#endif
        m_authorStyle->addRulesFromSheet(sheet, *medium, resolver);
        inspectorCSSOMWrappers.collectFromStyleSheetIfNeeded(cssSheet);
    }
    m_authorStyle->shrinkToFit();
    collectFeatures(isViewSource, resolver->scopeResolver());
}

드디어 찾아헤매던 media query가 나왔습니다.( 9 line)

StyleResolver가 갖고 있던 m_medium을 받아 이 값을 각각의 CSSStyleSheet의 media query와 비교하여 매치 되는 스타일 시트만 rule에 추가됩니다. (21 line)

이 때 resolver의 값도 같이 넘어가는 것을 보실 수 있습니다.


resolver의 값이 있기 때문에 이제 viewport dependent여부를 확인할 수 있습니다.

### c++ ; highlight : [25, 26]

bool MediaQueryEvaluator::eval(const MediaQuerySet* querySet, StyleResolver* styleResolver) const
{
    if (!querySet)
        return true;

    const Vector<OwnPtr<MediaQuery> >& queries = querySet->queryVector();
    if (!queries.size())
        return true; // empty query list evaluates to true

    // iterate over queries, stop if any of them eval to true (OR semantics)
    bool result = false;
    for (size_t i = 0; i < queries.size() && !result; ++i) {
        MediaQuery* query = queries[i].get();

        if (query->ignored())
            continue;

        if (mediaTypeMatch(query->mediaType())) {
            const Vector<OwnPtr<MediaQueryExp> >* exps = query->expressions();
            // iterate through expressions, stop if any of them eval to false
            // (AND semantics)
            size_t j = 0;
            for (; j < exps->size(); ++j) {
                bool exprResult = eval(exps->at(j).get());
                if (styleResolver && exps->at(j)->isViewportDependent())
                    styleResolver->addViewportDependentMediaQueryResult(exps->at(j).get(), exprResult);
                if (!exprResult)
                    break;
            }

            // assume true if we are at the end of the list,
            // otherwise assume false
            result = applyRestrictor(query->restrictor(), exps->size() == j);
        } else
            result = applyRestrictor(query->restrictor(), false);
    }

    return result;
}

Media query expression이 viewport dependent한지 체크합니다. 예제에서 width를 지정했으므로 viewport dependent합니다.

따라서 styleResolver에 해당 mediaQuery를 넘겨주게 따로 저장하고 있게 됩니다. ( 26 line )

이렇게 저장된 정보는 layout과정에서 다시 evaluation의 대상이 될 것입니다.


위에서 스타일 시트를 추가할 때 link element도 고려해서 추가하고 있었던 것을 기억하신다면,

이전글에서 설명한 것 외에 linke element에 대해서도 이 부분에서 한번 더 evaluation과정을 거치게 되고 이 때 viewportDependent도 체크하게 될 것입니다.

저작자 표시 비영리 변경 금지
신고
Posted by 소혼

[media query 간략 소개]

Media query는 media의 종류에 따라 특정 CSS 스타일을 적용하고자 할 때  사용하는 CSS 스펙 가운데 하나입니다.

(http://www.w3.org/TR/css3-mediaqueries/)



media query에 대한 article : http://html.nhncorp.com/blog/42284


다음글 : Media query in webkit (style element)

그 다음글 : Media query in webkit(import/media rule)







예를 들어 아래는 대표적인 media query의 예입니다. (이 글에서 코드리딩할 방법입니다.)

### html
<link rel="stylesheet" type="text/css" media="screen" href="sans-serif.css">
<link rel="stylesheet" type="text/css" media="print" href="serif.css">

screenprint는 가장 많이 알려진 미디어의 종류(type)입니다.


또는 아래처럼 쓸 수도 있습니다.

### css
@media screen {
 * { font-family: sans-serif }
}


또 @import rule을 사용하여 아래와 같은 방법도 있습니다.

### css

@import url(example.css) screen


style element 자체에도 media query를 사용할 수 있습니다.

### html

<style media="screen and (min-width:300px)">
body { background-color:red; }
</style>


media query라는 단어가 말하듯 단순히 media의 종류를 지정하는 것 뿐 아니라 간단한 형태의 조건을 줄 수도 있습니다.

자세한 내용은 위에 링크한 스펙을 참고하시기 바랍니다.


간단히 정리하면 다음과 같습니다.

  • 여러 media type을 지정하고 싶다면 , 를 사용합니다. (screen, print)
  • media에 추가로 특정 media feature만 적용되도록 제한하고 싶다면 media feature와 media value로 이루어지는 수식들을 and로 추가할 수 있습니다.
  • only, not과 같은 제한자를 가질 수 있습니다.


예를 들면, 아래와 같습니다.

### css

<link rel="stylesheet" media="speech and (min-device-width: 800px)" href="example.css" />



[WebKit internal]

일단 위 예제 1의 <link>의 경우부터 시작하겠습니다. (1번라인을 기준으로 설명하겠습니다.)

네트워크로부터 데이터를 가져와서 link 태그를 파싱하면 HTMLLinkElement를 만들게 됩니다.

그 다음 Attribute들을 파싱하기 위해 parseAttribute를 부릅니다.


### c++; highlight: [9, 10]

void HTMLLinkElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
{
    if (name == relAttr) {
        m_relAttribute = LinkRelAttribute(value);
        process();
    } else if (name == hrefAttr) {
         // ...
    } else if (name == mediaAttr) {
        m_media = value.string().lower();
        process();
    } else if (name == disabledAttr)
         // ...
    else {
        if (name == titleAttr && m_sheet)
            m_sheet->setTitle(value);
        HTMLElement::parseAttribute(name, value);
    }
}

만약 현재 처리할 attribute가 media라면(9 line) value(screen)를 소문자로 변경하여 m_media에 넣고 process()를 호출합니다.


### c++; highlight:[10, 11, 12]

void HTMLLinkElement::process()
{
    // ...

    if (m_disabledState != Disabled && (m_relAttribute.m_isStyleSheet || (acceptIfTypeContainsTextCSS && type.contains("text/css")))
        && document()->frame() && m_url.isValid()) {

        // ...

        bool mediaQueryMatches = true;
        if (!m_media.isEmpty()) {
            RefPtr<RenderStyle> documentStyle = StyleResolver::styleForDocument(document());
            RefPtr<MediaQuerySet> media = MediaQuerySet::createAllowingDescriptionSyntax(m_media);
            MediaQueryEvaluator evaluator(document()->frame()->view()->mediaType(), document()->frame(), documentStyle.get());
            mediaQueryMatches = evaluator.eval(media.get());
        }

        // Don't hold up render tree construction and script execution on stylesheets
        // that are not needed for the rendering at the moment.
        bool blocking = mediaQueryMatches && !isAlternate();
        addPendingSheet(blocking ? Blocking : NonBlocking);

        // Load stylesheets that are not needed for the rendering immediately with low priority.
        ResourceLoadPriority priority = blocking ? ResourceLoadPriorityUnresolved : ResourceLoadPriorityVeryLow;
        CachedResourceRequest request(ResourceRequest(document()->completeURL(m_url)), charset, priority);
        request.setInitiator(this);
        m_cachedSheet = document()->cachedResourceLoader()->requestCSSStyleSheet(request);

        if (m_cachedSheet)
            m_cachedSheet->addClient(this);
        else {
            // The request may have been denied if (for example) the stylesheet is local and the document is remote.
            m_loading = false;
            removePendingSheet();
        }

       // ...

}

기본적으로 mediaQueryMatches는 true 입니다.

그러나, m_media가 있다면, FrameView의 mediaType, frame, documentStyle과 비교하여 mediaQuery가 match되는지 확인합니다.(9-12 line)

MediaQueryEvaluator가 이 값들을 가지고 있다가 eval을 통해 비교할 것입니다. (12 line)


만약 match된다면, loader에게 정상적으로 로드요청을 하겠지만, 아니면, blocking되었다가 제거될 것입니다.


m_media는 간단하게는 screen과 같이 media type만 있을 수도 있지만, "screen and (color:1), projection" 과 같이 여러 media type들과 media feature로 이루어진 수식을 포함할지도 모릅니다.


따라서 MediaQueryEvaluator가 쉽게 계산할 수 있도록 MediaQuerySet::createAllowingDescriptionSyntax을 이용하여 media query set으로 변환합니다.(10 line)


### c++ : highlight: [7, 9, 15]

bool MediaQuerySet::parse(const String& mediaString)
{
    CSSParser parser(CSSStrictMode);

    Vector<OwnPtr<MediaQuery> > result;
    Vector<String> list;
    mediaString.split(',', list);
    for (unsigned i = 0; i < list.size(); ++i) {
        String medium = list[i].stripWhiteSpace();
        if (medium.isEmpty()) {
            if (!m_fallbackToDescriptor)
                return false;
            continue;
        }
        OwnPtr<MediaQuery> mediaQuery = parser.parseMediaQuery(medium);
        if (!mediaQuery) {
            if (!m_fallbackToDescriptor)
                return false;
            String mediaDescriptor = parseMediaDescriptor(medium);
            if (mediaDescriptor.isNull())
                continue;
            mediaQuery = adoptPtr(new MediaQuery(MediaQuery::None, mediaDescriptor, nullptr));
        }
        result.append(mediaQuery.release());
    }
    // ",,,," falls straight through, but is not valid unless fallback
    if (!m_fallbackToDescriptor && list.isEmpty()) {
        String strippedMediaString = mediaString.stripWhiteSpace();
        if (!strippedMediaString.isEmpty())
            return false;
    }
    m_queries.swap(result);
    return true;
}

createAllowingDescriptionSyntax는 m_fallbackToDescriptor를 true로 하는 MediaQuerySet을 만들어 parse를 부르는게 전부입니다.

parse는 넘겨받은 mediaString을 ,로 구분해서(7 line) strip하고 (9 line) CSSParser에게 parsing을 요청하는게 전부입니다.(15 line)

MediaQuery는 세가지 주요 인자를 갖는데 Restrictor( Only, Not, None)와 mediaType(String), ExpressionVector입니다.


ExpressionVector 는 MediaQueryExp를 갖는 자료형으로 Exp가 만들어지면서 유효한 expression들이 vector에 들어가게 됩니다.


이제 MediaQuery는 만들어졌으니 이전 소스코드에서 MediaQueryEvaluator::eval을 보도록 하겠습니다.

### c++; highlight: [6, 18, 19, 24]

bool MediaQueryEvaluator::eval(const MediaQuerySet* querySet, StyleResolver* styleResolver) const
{
    if (!querySet)
        return true;

    const Vector<OwnPtr<MediaQuery> >& queries = querySet->queryVector();
    if (!queries.size())
        return true; // empty query list evaluates to true

    // iterate over queries, stop if any of them eval to true (OR semantics)
    bool result = false;
    for (size_t i = 0; i < queries.size() && !result; ++i) {
        MediaQuery* query = queries[i].get();

        if (query->ignored())
            continue;

        if (mediaTypeMatch(query->mediaType())) {
            const Vector<OwnPtr<MediaQueryExp> >* exps = query->expressions();
            // iterate through expressions, stop if any of them eval to false
            // (AND semantics)
            size_t j = 0;
            for (; j < exps->size(); ++j) {
                bool exprResult = eval(exps->at(j).get());
                if (styleResolver && exps->at(j)->isViewportDependent())
                    styleResolver->addViewportDependentMediaQueryResult(exps->at(j).get(), exprResult);
                if (!exprResult)
                    break;
            }

            // assume true if we are at the end of the list,
            // otherwise assume false
            result = applyRestrictor(query->restrictor(), exps->size() == j);
        } else
            result = applyRestrictor(query->restrictor(), false);
    }

    return result;
}

6 line에서 qureySet을 vector로 변환하여 loop를 돌리면서

먼저 type이 같은지 확인합니다.(18 line)


같다면 expression들을 꺼내 (19 line), 수식을 eval()합니다.

전 예제에서 styleResolver를 넘기지 않았기 때문에 addViewportDependentMediaQueryResult는 수행하지 않습니다.

* 현재 사용중인 예제는 media type만 갖고 있습니다. 만약에 max-width:300처럼 media expression이 있다면 어떻게 될까요?

   현재 width가 1024라고 가정하면, 해당 엘리먼트는 로드하지 않을 것입니다.

   그러나, 브라우저 크기를 줄여서 width가 300이하가 되면? 해당 스타일 시트를 로드해야 합니다.

   이러한 처리를 하기 위한 것이 바로 addViewportDependentMediaQueryResult입니다.

   이 부분의 동작은 다음 글과 다다음 글을 통해 따라가 보도록 하겠습니다.


### c++; highlight: [6, 20]

static void createFunctionMap()
{
    // Create the table.
    gFunctionMap = new FunctionMap;
#define ADD_TO_FUNCTIONMAP(name, str)  \
    gFunctionMap->set(name##MediaFeature.impl(), name##MediaFeatureEval);
    CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(ADD_TO_FUNCTIONMAP);
#undef ADD_TO_FUNCTIONMAP
}

bool MediaQueryEvaluator::eval(const MediaQueryExp* expr) const
{
    if (!m_frame || !m_style)
        return m_expResult;

    if (!expr->isValid())
        return false;

    if (!gFunctionMap)
        createFunctionMap();

    // call the media feature evaluation function. Assume no prefix
    // and let trampoline functions override the prefix if prefix is
    // used
    EvalFunc func = gFunctionMap->get(expr->mediaFeature().impl());
    if (func)
        return func(expr->value(), m_style.get(), m_frame, NoPrefix);

    return false;
}

수식의 eval은 mediaFeature마다 정의된 함수를 수행하는 것입니다.

함수의 등록은 createFunctionMap안의 매크로로 이루어집니다.(20 line)


현재 등록된 mediaFeature는이 글 제일 아래를 참고하시기 바랍니다. 웹킷은 현재 CSS 스펙에 없는 media feature도 몇 가지 지원하고 있습니다.(예: device-pixel-ratio)


media feature마다 함수와 구현이 다 다르기 때문에 각각의 구현을 확인하시려면 Source/WebCore/css/MediaQueryEvaluator.cpp 를 참고하시기 바랍니다.


예제로 color를 보도록 하겠습니다. 6 line에서 보듯 'media feature명' + MediaFeatureEval()이라는 함수를 봐야 찾아야 합니다.


### c++; highlight: [3, 6]

static bool colorMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op)
{                                                                                      
    int bitsPerComponent = screenDepthPerComponent(frame->page()->mainFrame()->view());
    float number;                                                                      
    if (value)                                                                         
        return numberValue(value, number) && compareValue(bitsPerComponent, static_cast<int>(number), op);

    return bitsPerComponent != 0;                                                      

color 의 경우 screenDepthPerComponent라는 platform specific function으로부터 값을 꺼내오고 있습니다.해당 함수는 Source/WebCore/platform/xxx/PlatformScreenXXX.cpp에 각 포트별로 구현되어 있습니다.(XXX는 포트명)


value가 있다는 것은 현재 확인하고 있는 expression이 >, < 와 같은 비교문이 있다는 뜻(ex - color:256)입니다.

MediaFeaturePrefix는 비교하는 media feature앞에 min- 또느 max-가 붙어있는지를 전달합니다. 이 값에 따라 compareValue가 ==을 비교할지 <= 나 >=를 비교할지가 결정됩니다.





현재 등록된 media feature의 종류

### c++

#define CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(macro) \
    macro(color, "color") \
    macro(grid, "grid") \
    macro(monochrome, "monochrome") \
    macro(height, "height") \
    macro(hover, "hover") \
    macro(width, "width") \
    macro(orientation, "orientation") \
    macro(aspect_ratio, "aspect-ratio") \
    macro(device_aspect_ratio, "device-aspect-ratio") \
    macro(device_pixel_ratio, "-webkit-device-pixel-ratio") \
    macro(device_height, "device-height") \
    macro(device_width, "device-width") \
    macro(max_color, "max-color") \
    macro(max_aspect_ratio, "max-aspect-ratio") \
    macro(max_device_aspect_ratio, "max-device-aspect-ratio") \
    macro(max_device_pixel_ratio, "-webkit-max-device-pixel-ratio") \
    macro(max_device_height, "max-device-height") \
    macro(max_device_width, "max-device-width") \
    macro(max_height, "max-height") \
    macro(max_monochrome, "max-monochrome") \
    macro(max_width, "max-width") \
    macro(max_resolution, "max-resolution") \
    macro(min_color, "min-color") \
    macro(min_aspect_ratio, "min-aspect-ratio") \
    macro(min_device_aspect_ratio, "min-device-aspect-ratio") \
    macro(min_device_pixel_ratio, "-webkit-min-device-pixel-ratio") \
    macro(min_device_height, "min-device-height") \
    macro(min_device_width, "min-device-width") \
    macro(min_height, "min-height") \
    macro(min_monochrome, "min-monochrome") \
    macro(min_width, "min-width") \
    macro(min_resolution, "min-resolution") \
    macro(pointer, "pointer") \
    macro(resolution, "resolution") \
    macro(transform_2d, "-webkit-transform-2d") \
    macro(transform_3d, "-webkit-transform-3d") \
    macro(transition, "-webkit-transition") \
    macro(animation, "-webkit-animation") \
    macro(view_mode, "-webkit-view-mode")



저작자 표시 비영리 변경 금지
신고
Posted by 소혼
http://www.webkit.org
http://trac.webkit.org
https://bugs.webkit.org
http://build.webkit.org/
http://webkit.org/pending-commit
http://webkit.org/pending-review
http://www.chromium.org/developers/how-tos/webkit-merge-1

http://trac.webkit.org/wiki/UsingGitWithWebKit



https://wiki.mozilla.org/images/c/c0/Larres-thesis.pdf
wkb.ug/82701

webkit-perf.appspot.com

신고
Posted by 소혼
TAG Webkit
jsgamebench에서 webkit/gtk의 callstak

Breakpoint 1, 0x003277b6 in WebKit::ChromeClient::invalidateContentsAndWindow(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
(gdb) bt
#0  0x003277b6 in WebKit::ChromeClient::invalidateContentsAndWindow(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#1  0x008724d6 in WebCore::Chrome::invalidateContentsAndWindow(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#2  0x00938985 in WebCore::ScrollView::repaintContentRectangle(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#3  0x008a99b8 in WebCore::FrameView::repaintContentRectangle(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#4  0x00a4fdad in WebCore::RenderView::repaintViewRectangle(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#5  0x00a0fef1 in WebCore::RenderObject::repaintUsingContainer(WebCore::RenderBoxModelObject*, WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#6  0x00a11964 in WebCore::RenderObject::repaint(bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#7  0x00a0e3e0 in WebCore::RenderObjectChildList::removeChildNode(WebCore::RenderObject*, WebCore::RenderObject*, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#8  0x00a113af in WebCore::RenderObject::removeChild(WebCore::RenderObject*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#9  0x0099b09c in WebCore::RenderBlock::removeChild(WebCore::RenderObject*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#10 0x00a11082 in WebCore::RenderObject::destroy() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#11 0x009c08d1 in WebCore::RenderBoxModelObject::destroy() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#12 0x009b7e20 in WebCore::RenderBox::destroy() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#13 0x009957eb in WebCore::RenderBlock::destroy() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#14 0x005be836 in WebCore::Node::detach() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#15 0x0056dfc1 in WebCore::ContainerNode::detach() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#16 0x005a6f18 in WebCore::Element::detach() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#17 0x0056d459 in WebCore::ContainerNode::removeBetween(WebCore::Node*, WebCore::Node*, WebCore::Node*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#18 0x0056fbff in WebCore::ContainerNode::removeChild(WebCore::Node*, int&) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#19 0x005bedc3 in WebCore::Node::removeChild(WebCore::Node*, int&) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#20 0x004790fd in WebCore::JSNode::removeChild(JSC::ExecState*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#21 0x00e4208e in WebCore::jsNodePrototypeFunctionRemoveChild(JSC::ExecState*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#22 0x02b9d341 in ?? ()
#23 0x010a1d84 in JSC::Interpreter::execute(JSC::ProgramExecutable*, JSC::ExecState*, JSC::ScopeChainNode*, JSC::JSObject*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#24 0x01134d9e in JSC::evaluate(JSC::ExecState*, JSC::ScopeChainNode*, JSC::SourceCode const&, JSC::JSValue) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#25 0x0049c7ab in WebCore::ScriptController::evaluateInWorld(WebCore::ScriptSourceCode const&, WebCore::DOMWrapperWorld*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#26 0x0049cc7b in WebCore::ScriptController::executeScriptInWorld(WebCore::DOMWrapperWorld*, WTF::String const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#27 0x004981db in WebCore::ScheduledAction::execute(WebCore::Document*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#28 0x0049866b in WebCore::ScheduledAction::execute(WebCore::ScriptExecutionContext*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#29 0x008801ba in WebCore::DOMTimer::fired() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#30 0x0094b72d in WebCore::ThreadTimers::sharedTimerFiredInternal() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#31 0x0094b7a5 in WebCore::ThreadTimers::sharedTimerFired() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#32 0x003015de in WebCore::timeout_cb(void*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#33 0x01c0683c in g_timeout_dispatch (source=0xb63f7110, callback=0xb63fefc0, user_data=0x0) at gmain.c:3877
#34 0x01c05e75 in g_main_dispatch (context=0x807a4b0) at gmain.c:2440
#35 g_main_context_dispatch (context=0x807a4b0) at gmain.c:3013
#36 0x01c0a428 in g_main_context_iterate (context=0x807a4b0, block=<value optimized out>, dispatch=1, self=0x8050520) at gmain.c:3091
#37 0x01c0a967 in g_main_loop_run (loop=0x83a1e38) at gmain.c:3299
#38 0x014e81d9 in gtk_main () from /usr/lib/libgtk-x11-2.0.so.0
#39 0x0804a082 in main ()
(gdb) c
Continuing.
 * (457, 265, 32, 32)

Breakpoint 1, 0x003277b6 in WebKit::ChromeClient::invalidateContentsAndWindow(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
(gdb) bt
#0  0x003277b6 in WebKit::ChromeClient::invalidateContentsAndWindow(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#1  0x008724d6 in WebCore::Chrome::invalidateContentsAndWindow(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#2  0x00938985 in WebCore::ScrollView::repaintContentRectangle(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#3  0x008a99b8 in WebCore::FrameView::repaintContentRectangle(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#4  0x00a4fdad in WebCore::RenderView::repaintViewRectangle(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#5  0x00a0fef1 in WebCore::RenderObject::repaintUsingContainer(WebCore::RenderBoxModelObject*, WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#6  0x00a11964 in WebCore::RenderObject::repaint(bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#7  0x00a0e3e0 in WebCore::RenderObjectChildList::removeChildNode(WebCore::RenderObject*, WebCore::RenderObject*, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#8  0x00a113af in WebCore::RenderObject::removeChild(WebCore::RenderObject*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#9  0x0099b09c in WebCore::RenderBlock::removeChild(WebCore::RenderObject*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#10 0x00a11082 in WebCore::RenderObject::destroy() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#11 0x00a4120f in WebCore::RenderText::destroy() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#12 0x005be836 in WebCore::Node::detach() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#13 0x0056dfab in WebCore::ContainerNode::detach() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#14 0x005a6f18 in WebCore::Element::detach() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#15 0x0056d459 in WebCore::ContainerNode::removeBetween(WebCore::Node*, WebCore::Node*, WebCore::Node*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#16 0x0056fbff in WebCore::ContainerNode::removeChild(WebCore::Node*, int&) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#17 0x0057177c in WebCore::ContainerNode::replaceChild(WTF::PassRefPtr<WebCore::Node>, WebCore::Node*, int&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#18 0x006ec22c in WebCore::replaceChildrenWithFragment(WebCore::HTMLElement*, WTF::PassRefPtr<WebCore::DocumentFragment>, int&) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#19 0x006ec33e in WebCore::HTMLElement::setInnerHTML(WTF::String const&, int&) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#20 0x00d71823 in WebCore::setJSHTMLElementInnerHTML(JSC::ExecState*, JSC::JSObject*, JSC::JSValue) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#21 0x00d73efd in WebCore::JSHTMLElement::put(JSC::ExecState*, JSC::Identifier const&, JSC::JSValue, JSC::PutPropertySlot&) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#22 0x00d6ab28 in WebCore::JSHTMLDivElement::put(JSC::ExecState*, JSC::Identifier const&, JSC::JSValue, JSC::PutPropertySlot&) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#23 0x010e0096 in cti_op_put_by_id_generic () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#24 0x02bd5719 in ?? ()
#25 0x010a1d84 in JSC::Interpreter::execute(JSC::ProgramExecutable*, JSC::ExecState*, JSC::ScopeChainNode*, JSC::JSObject*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#26 0x01134d9e in JSC::evaluate(JSC::ExecState*, JSC::ScopeChainNode*, JSC::SourceCode const&, JSC::JSValue) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#27 0x0049c7ab in WebCore::ScriptController::evaluateInWorld(WebCore::ScriptSourceCode const&, WebCore::DOMWrapperWorld*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#28 0x0049cc7b in WebCore::ScriptController::executeScriptInWorld(WebCore::DOMWrapperWorld*, WTF::String const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#29 0x004981db in WebCore::ScheduledAction::execute(WebCore::Document*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#30 0x0049866b in WebCore::ScheduledAction::execute(WebCore::ScriptExecutionContext*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#31 0x008801ba in WebCore::DOMTimer::fired() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#32 0x0094b72d in WebCore::ThreadTimers::sharedTimerFiredInternal() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#33 0x0094b7a5 in WebCore::ThreadTimers::sharedTimerFired() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#34 0x003015de in WebCore::timeout_cb(void*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#35 0x01c0683c in g_timeout_dispatch (source=0xb63f7110, callback=0xb63fefc0, user_data=0x0) at gmain.c:3877
#36 0x01c05e75 in g_main_dispatch (context=0x807a4b0) at gmain.c:2440
#37 g_main_context_dispatch (context=0x807a4b0) at gmain.c:3013
#38 0x01c0a428 in g_main_context_iterate (context=0x807a4b0, block=<value optimized out>, dispatch=1, self=0x8050520) at gmain.c:3091
#39 0x01c0a967 in g_main_loop_run (loop=0x83a1e38) at gmain.c:3299
#40 0x014e81d9 in gtk_main () from /usr/lib/libgtk-x11-2.0.so.0
#41 0x0804a082 in main ()
(gdb) c
Continuing.
 * (5, 55, 752, 72)

Breakpoint 1, 0x003277b6 in WebKit::ChromeClient::invalidateContentsAndWindow(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
(gdb) bt
#0  0x003277b6 in WebKit::ChromeClient::invalidateContentsAndWindow(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#1  0x008724d6 in WebCore::Chrome::invalidateContentsAndWindow(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#2  0x00938985 in WebCore::ScrollView::repaintContentRectangle(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#3  0x008a99b8 in WebCore::FrameView::repaintContentRectangle(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#4  0x00a4fdad in WebCore::RenderView::repaintViewRectangle(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#5  0x00a0fef1 in WebCore::RenderObject::repaintUsingContainer(WebCore::RenderBoxModelObject*, WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#6  0x00a11964 in WebCore::RenderObject::repaint(bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#7  0x00a0e3e0 in WebCore::RenderObjectChildList::removeChildNode(WebCore::RenderObject*, WebCore::RenderObject*, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#8  0x00a113af in WebCore::RenderObject::removeChild(WebCore::RenderObject*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#9  0x0099b09c in WebCore::RenderBlock::removeChild(WebCore::RenderObject*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#10 0x00a11082 in WebCore::RenderObject::destroy() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#11 0x00a4120f in WebCore::RenderText::destroy() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#12 0x005be836 in WebCore::Node::detach() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#13 0x0056dfc1 in WebCore::ContainerNode::detach() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#14 0x005a6f18 in WebCore::Element::detach() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#15 0x0056dfab in WebCore::ContainerNode::detach() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#16 0x005a6f18 in WebCore::Element::detach() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#17 0x0056d459 in WebCore::ContainerNode::removeBetween(WebCore::Node*, WebCore::Node*, WebCore::Node*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#18 0x0056fbff in WebCore::ContainerNode::removeChild(WebCore::Node*, int&) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#19 0x0057177c in WebCore::ContainerNode::replaceChild(WTF::PassRefPtr<WebCore::Node>, WebCore::Node*, int&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#20 0x006ec22c in WebCore::replaceChildrenWithFragment(WebCore::HTMLElement*, WTF::PassRefPtr<WebCore::DocumentFragment>, int&) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#21 0x006ec33e in WebCore::HTMLElement::setInnerHTML(WTF::String const&, int&) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#22 0x00d71823 in WebCore::setJSHTMLElementInnerHTML(JSC::ExecState*, JSC::JSObject*, JSC::JSValue) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#23 0x00d73efd in WebCore::JSHTMLElement::put(JSC::ExecState*, JSC::Identifier const&, JSC::JSValue, JSC::PutPropertySlot&) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#24 0x00d6ab28 in WebCore::JSHTMLDivElement::put(JSC::ExecState*, JSC::Identifier const&, JSC::JSValue, JSC::PutPropertySlot&) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#25 0x010e0096 in cti_op_put_by_id_generic () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#26 0x02bd5719 in ?? ()
#27 0x010a1d84 in JSC::Interpreter::execute(JSC::ProgramExecutable*, JSC::ExecState*, JSC::ScopeChainNode*, JSC::JSObject*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#28 0x01134d9e in JSC::evaluate(JSC::ExecState*, JSC::ScopeChainNode*, JSC::SourceCode const&, JSC::JSValue) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#29 0x0049c7ab in WebCore::ScriptController::evaluateInWorld(WebCore::ScriptSourceCode const&, WebCore::DOMWrapperWorld*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#30 0x0049cc7b in WebCore::ScriptController::executeScriptInWorld(WebCore::DOMWrapperWorld*, WTF::String const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#31 0x004981db in WebCore::ScheduledAction::execute(WebCore::Document*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#32 0x0049866b in WebCore::ScheduledAction::execute(WebCore::ScriptExecutionContext*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#33 0x008801ba in WebCore::DOMTimer::fired() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#34 0x0094b72d in WebCore::ThreadTimers::sharedTimerFiredInternal() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#35 0x0094b7a5 in WebCore::ThreadTimers::sharedTimerFired() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#36 0x003015de in WebCore::timeout_cb(void*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#37 0x01c0683c in g_timeout_dispatch (source=0xb63f7110, callback=0xb63fefc0, user_data=0x0) at gmain.c:3877
#38 0x01c05e75 in g_main_dispatch (context=0x807a4b0) at gmain.c:2440
#39 g_main_context_dispatch (context=0x807a4b0) at gmain.c:3013
#40 0x01c0a428 in g_main_context_iterate (context=0x807a4b0, block=<value optimized out>, dispatch=1, self=0x8050520) at gmain.c:3091
#41 0x01c0a967 in g_main_loop_run (loop=0x83a1e38) at gmain.c:3299
#42 0x014e81d9 in gtk_main () from /usr/lib/libgtk-x11-2.0.so.0
#43 0x0804a082 in main ()
(gdb) c
Continuing.
 * (5, 55, 752, 72)

Breakpoint 1, 0x003277b6 in WebKit::ChromeClient::invalidateContentsAndWindow(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
(gdb) bt
#0  0x003277b6 in WebKit::ChromeClient::invalidateContentsAndWindow(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#1  0x008724d6 in WebCore::Chrome::invalidateContentsAndWindow(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#2  0x00938985 in WebCore::ScrollView::repaintContentRectangle(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#3  0x008a99b8 in WebCore::FrameView::repaintContentRectangle(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#4  0x00a4fdad in WebCore::RenderView::repaintViewRectangle(WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#5  0x00a0fef1 in WebCore::RenderObject::repaintUsingContainer(WebCore::RenderBoxModelObject*, WebCore::IntRect const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#6  0x00a11964 in WebCore::RenderObject::repaint(bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#7  0x00a0e3e0 in WebCore::RenderObjectChildList::removeChildNode(WebCore::RenderObject*, WebCore::RenderObject*, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#8  0x00a113af in WebCore::RenderObject::removeChild(WebCore::RenderObject*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#9  0x0099b09c in WebCore::RenderBlock::removeChild(WebCore::RenderObject*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#10 0x00a11082 in WebCore::RenderObject::destroy() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#11 0x00a4120f in WebCore::RenderText::destroy() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#12 0x005be836 in WebCore::Node::detach() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#13 0x0056dfab in WebCore::ContainerNode::detach() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#14 0x005a6f18 in WebCore::Element::detach() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#15 0x0056d459 in WebCore::ContainerNode::removeBetween(WebCore::Node*, WebCore::Node*, WebCore::Node*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#16 0x0056fbff in WebCore::ContainerNode::removeChild(WebCore::Node*, int&) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#17 0x0057177c in WebCore::ContainerNode::replaceChild(WTF::PassRefPtr<WebCore::Node>, WebCore::Node*, int&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#18 0x006ec22c in WebCore::replaceChildrenWithFragment(WebCore::HTMLElement*, WTF::PassRefPtr<WebCore::DocumentFragment>, int&) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#19 0x006ec33e in WebCore::HTMLElement::setInnerHTML(WTF::String const&, int&) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#20 0x00d71823 in WebCore::setJSHTMLElementInnerHTML(JSC::ExecState*, JSC::JSObject*, JSC::JSValue) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#21 0x00d73efd in WebCore::JSHTMLElement::put(JSC::ExecState*, JSC::Identifier const&, JSC::JSValue, JSC::PutPropertySlot&) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#22 0x00d6ab28 in WebCore::JSHTMLDivElement::put(JSC::ExecState*, JSC::Identifier const&, JSC::JSValue, JSC::PutPropertySlot&) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#23 0x010e0096 in cti_op_put_by_id_generic () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#24 0x02bd5719 in ?? ()
#25 0x010a1d84 in JSC::Interpreter::execute(JSC::ProgramExecutable*, JSC::ExecState*, JSC::ScopeChainNode*, JSC::JSObject*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#26 0x01134d9e in JSC::evaluate(JSC::ExecState*, JSC::ScopeChainNode*, JSC::SourceCode const&, JSC::JSValue) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#27 0x0049c7ab in WebCore::ScriptController::evaluateInWorld(WebCore::ScriptSourceCode const&, WebCore::DOMWrapperWorld*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#28 0x0049cc7b in WebCore::ScriptController::executeScriptInWorld(WebCore::DOMWrapperWorld*, WTF::String const&, bool) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#29 0x004981db in WebCore::ScheduledAction::execute(WebCore::Document*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#30 0x0049866b in WebCore::ScheduledAction::execute(WebCore::ScriptExecutionContext*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#31 0x008801ba in WebCore::DOMTimer::fired() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#32 0x0094b72d in WebCore::ThreadTimers::sharedTimerFiredInternal() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#33 0x0094b7a5 in WebCore::ThreadTimers::sharedTimerFired() () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#34 0x003015de in WebCore::timeout_cb(void*) () from /workspace/webkit/WebKit/WebKitBuild/Release/.libs/libwebkitgtk-1.0.so.0
#35 0x01c0683c in g_timeout_dispatch (source=0xb63f7110, callback=0xb63fefc0, user_data=0x0) at gmain.c:3877
#36 0x01c05e75 in g_main_dispatch (context=0x807a4b0) at gmain.c:2440
#37 g_main_context_dispatch (context=0x807a4b0) at gmain.c:3013
#38 0x01c0a428 in g_main_context_iterate (context=0x807a4b0, block=<value optimized out>, dispatch=1, self=0x8050520) at gmain.c:3091
#39 0x01c0a967 in g_main_loop_run (loop=0x83a1e38) at gmain.c:3299
#40 0x014e81d9 in gtk_main () from /usr/lib/libgtk-x11-2.0.so.0
#41 0x0804a082 in main ()
 
신고
Posted by 소혼
TAG Webkit
이전버튼 1 이전버튼

티스토리 툴바