1/*
2 * Copyright (C) 2009 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1.  Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2.  Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25#import "WebScriptWorld.h"
26
27#import "WebScriptWorldInternal.h"
28#import <WebCore/JSDOMBinding.h>
29#import <WebCore/ScriptController.h>
30#import <JavaScriptCore/APICast.h>
31#import <JavaScriptCore/JSContextInternal.h>
32
33#import <wtf/RefPtr.h>
34
35using namespace WebCore;
36
37@interface WebScriptWorldPrivate : NSObject {
38@public
39    RefPtr<DOMWrapperWorld> world;
40}
41@end
42
43@implementation WebScriptWorldPrivate
44@end
45
46typedef HashMap<DOMWrapperWorld*, WebScriptWorld*> WorldMap;
47static WorldMap& allWorlds()
48{
49    static WorldMap& map = *new WorldMap;
50    return map;
51}
52
53@implementation WebScriptWorld
54
55- (id)initWithWorld:(PassRefPtr<DOMWrapperWorld>)world
56{
57    ASSERT_ARG(world, world);
58    if (!world)
59        return nil;
60
61    self = [super init];
62    if (!self)
63        return nil;
64
65    _private = [[WebScriptWorldPrivate alloc] init];
66    _private->world = world;
67
68    ASSERT_ARG(world, !allWorlds().contains(_private->world.get()));
69    allWorlds().add(_private->world.get(), self);
70
71    return self;
72}
73
74- (id)init
75{
76    return [self initWithWorld:ScriptController::createWorld()];
77}
78
79- (void)unregisterWorld
80{
81    _private->world->clearWrappers();
82}
83
84- (void)dealloc
85{
86    ASSERT(allWorlds().contains(_private->world.get()));
87    allWorlds().remove(_private->world.get());
88
89    [_private release];
90    _private = nil;
91    [super dealloc];
92}
93
94+ (WebScriptWorld *)standardWorld
95{
96    static WebScriptWorld *world = [[WebScriptWorld alloc] initWithWorld:&mainThreadNormalWorld()];
97    return world;
98}
99
100+ (WebScriptWorld *)world
101{
102    return [[[self alloc] init] autorelease];
103}
104
105+ (WebScriptWorld *)scriptWorldForGlobalContext:(JSGlobalContextRef)context
106{
107    return [self findOrCreateWorld:currentWorld(toJS(context))];
108}
109
110#if JSC_OBJC_API_ENABLED
111+ (WebScriptWorld *)scriptWorldForJavaScriptContext:(JSContext *)context
112{
113    return [self scriptWorldForGlobalContext:[context JSGlobalContextRef]];
114}
115#endif
116
117@end
118
119@implementation WebScriptWorld (WebInternal)
120
121DOMWrapperWorld* core(WebScriptWorld *world)
122{
123    return world ? world->_private->world.get() : 0;
124}
125
126+ (WebScriptWorld *)findOrCreateWorld:(DOMWrapperWorld&)world
127{
128    if (&world == &mainThreadNormalWorld())
129        return [self standardWorld];
130
131    if (WebScriptWorld *existingWorld = allWorlds().get(&world))
132        return existingWorld;
133
134    return [[[self alloc] initWithWorld:&world] autorelease];
135}
136
137@end
138