tizen beta release
[framework/web/webkit-efl.git] / LayoutTests / fast / dom / script-tests / prototype-inheritance-2.js
1 description("Make sure prototypes are set up using the window a property came from, instead of the lexical global object.")
2
3 var subframe = document.createElement("iframe");
4 document.body.appendChild(subframe);
5 var inner = subframe.contentWindow; // Call it "inner" to make shouldBe output shorter
6
7 var skippedProperties = [
8     // These reach outside the frame:
9     "parent", "top", "opener", "frameElement",
10     // These are defined by DumpRenderTree
11     "GCController", "layoutTestController",
12     "objCController", "textInputController", "navigationController",
13     "eventSender", "objCPlugin", "objCPluginFunction",
14     "appleScriptController", "plainText", "accessibilityController",
15     "internals",
16     // Skip our test property
17     "isInner",
18     // Ignore fooConstructor.prototype, fooInstance.__proto__ is more likely to fail.
19     "prototype",
20     // Skip Geolocation until it is supported on most platforms.
21     "geolocation",
22     // Skip webkitURL until it is supported on most platforms.
23     "webkitURL",
24 ];
25
26 var skippedPropertiesSet = {};
27 for (var i = 0; i < skippedProperties.length; i++)
28   skippedPropertiesSet[skippedProperties[i]] = true;
29
30 // Stash a property on the prototypes.
31 window.Object.prototype.isInner = false;
32 inner.Object.prototype.isInner = true;
33
34 function propertiesOnObject(object) {
35     var properties = [];
36     for (property in object) {
37         if (skippedPropertiesSet[property])
38             continue;
39         properties.push(property);
40     }
41     return properties;
42 }
43
44 var resultsByType = {};
45
46 function classNameForObject(object)
47 {
48     // call will use the global object if passed null or undefined, so special case those:
49     if (object == null)
50         return null;
51     var result = Object.prototype.toString.call(object);
52     // remove '[object ' and ']'
53     return result.split(' ')[1].split(']')[0];
54 }
55
56 function constructorNamesForWindow(globalObject)
57 {
58     var namesSet = {};
59     for (var property in globalObject) {
60         var value = inner[property];
61         if (value == null)
62             continue;
63         var type = classNameForObject(value);
64         // Ignore these properties because they do not exist in all implementations. They will be tested separately
65         if (type == "WebGLRenderingContextConstructor" ||
66             type == "WebGLActiveInfoConstructor" ||
67             type == "WebGLBufferConstructor" ||
68             type == "WebGLFramebufferConstructor" ||
69             type == "WebGLProgramConstructor" ||
70             type == "WebGLRenderbufferConstructor" ||
71             type == "WebGLShaderConstructor" ||
72             type == "WebGLTextureConstructor" ||
73             type == "WebGLUniformLocationConstructor" ||
74             type == "ArrayBufferConstructor" ||
75             type == "DataViewConstructor" ||
76             type =="Float32ArrayConstructor" ||
77             type =="Float64ArrayConstructor" ||
78             type =="Int8ArrayConstructor" ||
79             type =="Int16ArrayConstructor" ||
80             type =="Int32ArrayConstructor" ||
81             type =="Uint8ArrayConstructor" ||
82             type =="Uint16ArrayConstructor" ||
83             type =="Uint32ArrayConstructor" ||
84             type == "FileErrorConstructor" ||
85             type == "FileReaderConstructor" ||
86             type == "WebKitBlobBuilderConstructor" ||
87             type == "HTMLProgressElementConstructor")
88             continue; // We ignore WebGLRenderingContext and test it elsewhere, since it is not in all builds
89         if (!type.match('Constructor$'))
90             continue;
91         namesSet[type] = 1;
92     }
93     return propertiesOnObject(namesSet).sort();
94 }
95
96 function makeCrawlObject(value, valuePath)
97 {
98     return {
99         'value' : value,
100         'valuePath' : valuePath
101     };
102 }
103
104 function evalToCrawlObject(path)
105 {
106     // This allows us to add things to the end of the crawl list
107     // without the early-eval changing the test results.
108     function LazyEvalCrawlObject(path){
109         this.valuePath = path;
110         var value;
111
112         this.__defineGetter__("value", function(){
113             if (!value)
114                 value = eval(this.valuePath);
115             return value;
116         });
117     }
118
119     return new LazyEvalCrawlObject(path);
120 }
121
122 function pushPropertyValuesWithUnseenTypes(toCrawl, parentObject, parentPath)
123 {
124     var propertiesToCrawl = propertiesOnObject(parentObject);
125     propertiesToCrawl.push("__proto__");
126     propertiesToCrawl.push("constructor");
127
128     var parentType = classNameForObject(parentObject);
129     
130     for (var x = 0; x < propertiesToCrawl.length; x++) {
131         var property = propertiesToCrawl[x];
132         var value = parentObject[property];
133         var valuePath = parentPath + "." + property;
134         // CSSStyleDeclaration.item() just returns property names, but we want to crawl the actual CSS values
135         if (parentType == "CSSStyleDeclaration" && parseInt(property)) { // This will skip 0, but that should be OK.
136             valuePath = parentPath + ".getPropertyCSSValue(" + value + ")"
137             value = parentObject.getPropertyCSSValue(value);
138         }
139         var type = classNameForObject(value);
140         if (!type)
141             continue;
142          // We already have other tests which cover window.Foo constructor objects, so skip them.
143          // fooInstance.constructor is the case we want to catch here.
144         if (parentType == "DOMWindow" && type.match("Constructor$") && property != "constructor")
145             continue;
146         if (!resultsByType[type])
147             toCrawl.push(makeCrawlObject(value, valuePath));
148     }
149 }
150
151 function crawl(crawlStarts) {
152     while (crawlStarts.length) {
153         var toCrawl = [crawlStarts.shift()];
154         while (toCrawl.length) {
155             var crawlTarget = toCrawl.shift();
156             var object = crawlTarget.value;
157             var type = classNameForObject(object);
158             // If we've already seen an object of this type, and it's not a collection
159             if (resultsByType[type] && !object.item && !object.length) {
160                 // Make sure this isn't a new failure before skipping it.
161                 if (object.isInner || object.isInner === resultsByType[type].value)
162                     continue;
163             }
164             if (typeof(object) == "string")
165                 continue;
166             if (typeof(object) == "boolean")
167                 continue;
168             if (typeof(object) == "number")
169                 continue;
170
171             resultsByType[type] = makeCrawlObject(object.isInner, crawlTarget.valuePath);
172             pushPropertyValuesWithUnseenTypes(toCrawl, object, crawlTarget.valuePath);
173         }
174     }
175 }
176
177 var tagReplacements = {
178     'anchor' : 'a',
179     'dlist' : 'dl',
180     'image' : 'img',
181     'ulist' : 'ul',
182     'olist' : 'ol',
183     'tablerow' : 'tr',
184     'tablecell' : 'td',
185     'tablecol' : 'col',
186     'tablecaption' : 'caption',
187     'paragraph' : 'p',
188     'blockquote' : 'quote',
189 }
190
191 function tagNameFromConstructor(constructorName)
192 {
193     var expectedObjectName = constructorName.split("Constructor")[0];
194     var match = expectedObjectName.match(/HTML(\w+)Element$/);
195     if (!match)
196         return null;
197     var tagName = match[1].toLowerCase();
198     if (tagReplacements[tagName])
199         return tagReplacements[tagName];
200     return tagName;
201 }
202
203
204 /* Give us more stuff to crawl */
205 /* If you're seeing "Never found..." errors from this test, more should be added here. */
206 var htmlToAdd = "";
207 var constructorNames = constructorNamesForWindow(inner);
208 for (var x = 0; x < constructorNames.length; x++) {
209     var constructorName = constructorNames[x];
210     var tagName = tagNameFromConstructor(constructorName);
211     if (!tagName)
212         continue;
213     if (tagName == 'html')
214         continue; // <html> causes a parse error.
215     htmlToAdd += "<" + tagName + "></" + tagName + ">";
216 }
217 htmlToAdd += "<form name='testForm'><input name='testInput'></form><form name='testForm'></form>";
218 htmlToAdd += "<!-- test -->";
219 styleContents = "@charset 'UTF-8';";
220 styleContents += "@import url('dummy.css') print;\n"; // Our parser seems to want this rule first?
221 styleContents += "@variables { Ignored: 2em; }\n"; // For when variables are turned back on
222 styleContents += "@page { margin: 3cm; }\n";
223 styleContents += "@media print { body { margin: 3cm; } }\n"
224 styleContents += "@font-face {font-family:'Times';}\n";
225 styleContents += "ignored {font-family: var(Ignored);}\n"; // a CSSStyleRule
226 styleContents += "@-webkit-keyframes fade { 0% { opacity: 0; } }\n"; // a WebKitCSSKeyframesRule
227
228 htmlToAdd += "<style id='dummyStyle'>" + styleContents + "</style>";
229 htmlToAdd += "<span id='styledSpan' style='clip: rect(0, 0, 1, 1); content: counter(dummy, square);'></span>";
230
231 inner.document.body.style.display = "none";
232 inner.document.body.innerHTML = htmlToAdd;
233
234 var crawlStartPaths = [
235     evalToCrawlObject('inner.document.createElement'),
236     evalToCrawlObject('inner.document.location'), // window.location is tested by other tests, so test document.location in this one.
237     //evalToCrawlObject('inner.testForm'), // Causes many failures
238     evalToCrawlObject('inner.document.forms.testForm'), // NamedNodesCollection has the wrong prototype, test that.
239     evalToCrawlObject('inner'),
240     evalToCrawlObject('inner.document.testForm'),
241     evalToCrawlObject('inner.document.testForm[0].testInput'),
242     evalToCrawlObject('inner.document.getElementsByTagName("canvas")[0].getContext("2d")'), // for CanvasRenderingContext2D
243     evalToCrawlObject('inner.document.getElementsByTagName("canvas")[0].getContext("2d").createPattern(inner.document.getElementsByTagName("img")[0], "")'), // for CanvasRenderingContext2D
244     evalToCrawlObject('inner.document.body.getClientRects()'), // For ClientRectList
245     evalToCrawlObject('inner.document.body.getBoundingClientRect()'), // For ClientRect, getClientRects() returns an empty list for in our test, not sure why.
246     evalToCrawlObject('inner.getComputedStyle(inner.document.body)'),
247     evalToCrawlObject('inner.document.getElementById("dummyStyle").sheet.cssRules'), // For various CSSRule subclasses
248     evalToCrawlObject('inner.document.getElementById("styledSpan").style'),
249     evalToCrawlObject('inner.document.getElementById("styledSpan").style.getPropertyCSSValue("clip").getRectValue()'),
250     evalToCrawlObject('inner.document.getElementById("styledSpan").style.getPropertyCSSValue("content")[0].getCounterValue()'),
251     // Can add more stuff to crawl here.
252 ];
253
254 crawl(crawlStartPaths);
255 var sortedTypes = propertiesOnObject(resultsByType).sort();
256
257 // Run the actual tests
258 for (var x = 0; x < sortedTypes.length; x++) {
259     var type = sortedTypes[x];
260     var result = resultsByType[type];
261     if (result.value)
262         testPassed(type + " from " + result.valuePath);
263     else
264         testFailed(type + " from " + result.valuePath);
265 }
266
267 // Add a bunch of fails at the end for stuff we missed in our crawl.
268 for (var x = 0; x < constructorNames.length; x++) {
269     var constructorName = constructorNames[x];
270     var expectedObjectName = constructorName.split("Constructor")[0];
271     if (expectedObjectName.match("Event$"))
272         continue; // Not going to be able to test events with a crawl.
273     if (expectedObjectName.match("Exception$"))
274         continue; // Not going to be able to test exceptions with a crawl.
275     if (expectedObjectName.match("Error$"))
276         continue; // Not going to be able to test errors with a crawl.
277     if (!resultsByType[expectedObjectName])
278         debug("Never found " + expectedObjectName);
279 }
280
281 //document.body.removeChild(subframe);