Update web-platform-tests to revision 7f2f85a88f434798e9d643427b34b05fab8278c6

This commit is contained in:
Ms2ger 2016-02-01 09:19:46 +01:00
parent 6b1a08c051
commit 73bc5cf1b8
180 changed files with 5807 additions and 169 deletions

View file

@ -0,0 +1,48 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Request clone</title>
<meta name="help" href="https://fetch.spec.whatwg.org/#request">
<meta name="author" title="Canon Research France" href="https://www.crf.canon.fr">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/utils.js"></script>
</head>
<body>
<script>
var headers = new Headers( {"name":"value"} );
var emptyHeaders = new Headers();
var initValuesDict = {"method" : "POST",
"referrer" : "http://{{host}}:{{ports[http][0]}}/",
"referrerPolicy" : "origin-only",
"mode" : "same-origin",
"credentials" : "include",
"cache" : "no-cache",
"redirect" : "error",
"integrity" : "Request's Integrity",
"headers" : headers,
"body" : "Request's body"
};
var expectedInitialized = {"method" : "POST",
"referrer" : "http://{{host}}:{{ports[http][0]}}/",
"referrerPolicy" : "origin-only",
"mode" : "same-origin",
"credentials" : "include",
"cache" : "no-cache",
"redirect" : "error",
"integrity" : "Request's Integrity",
"headers" : headers,
"body" : "Request's body"
};
test(function() {
var RequestInitialized = new Request("", initValuesDict);
var requestToCheck = RequestInitialized.clone();
checkRequest(requestToCheck, expectedInitialized);
}, "Check cloning a request");
</script>
</body>
</html>

View file

@ -0,0 +1,89 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Request consume</title>
<meta name="help" href="https://fetch.spec.whatwg.org/#request">
<meta name="help" href="https://fetch.spec.whatwg.org/#body-mixin">
<meta name="author" title="Canon Research France" href="https://www.crf.canon.fr">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
function checkBodyText(request, expectedBody) {
return request.text().then( function(bodyAsText) {
assert_equals(bodyAsText, expectedBody, "Retrieve and verify request's body");
assert_true(request.bodyUsed, "body as text: bodyUsed turned true");
});
}
function checkBodyBlob(request, expectedBody) {
return request.blob().then(function(bodyAsBlob) {
var promise = new Promise(function (resolve, reject) {
var reader = new FileReader();
reader.onload = function(evt) {
resolve(reader.result)
};
reader.onerror = function() {
reject("Blob's reader failed");
};
reader.readAsText(bodyAsBlob);
});
return promise.then(function(body) {
assert_equals(body, expectedBody, "Retrieve and verify request's body");
assert_true(request.bodyUsed, "body as blob: bodyUsed turned true");
});
});
}
<!-- Taken from https://developers.google.com -->
function str2ab(str) {
var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
var bufView = new Uint16Array(buf);
for (var i=0, strLen=str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
function checkBodyArrayBuffer(request, expectedBody) {
return request.arrayBuffer().then( function(bodyAsArrayBuffer) {
assert_array_equals(bodyAsArrayBuffer, str2ab(expectedBody), "Retrieve and verify request's body");
assert_true(request.bodyUsed, "body as arrayBuffer: bodyUsed turned true");
});
}
function checkBodyJSON(request, expectedBody) {
return request.json().then(function(bodyAsJSON) {
var strBody = JSON.stringify(bodyAsJSON)
assert_equals(strBody, expectedBody, "Retrieve and verify request's body");
assert_true(request.bodyUsed, "body as json: bodyUsed turned true");
});
}
function checkBodyFormData(request, expectedBody) {
return request.formData().then(function(bodyAsFormData) {
assert_true(bodyAsFormData instanceof FormData, "Should receive a FormData");
assert_true(request.bodyUsed, "body as formData: bodyUsed turned true");
});
}
function checkRequestBody(body, bodyType, checkFunction) {
promise_test(function(test) {
var request = new Request("", {"method": "POST", "body": body });
assert_false(request.bodyUsed, "bodyUsed is false at init");
return checkFunction(request, body);
}, "Consume request's body as " + bodyType);
}
var formData = new FormData();
formData.append("name", "value")
checkRequestBody("This is request's body", "text", checkBodyText);
checkRequestBody("This is request's body", "blob", checkBodyBlob);
checkRequestBody("This is request's body", "arrayBuffer", checkBodyArrayBuffer);
checkRequestBody(JSON.stringify("This is request's body"), "json", checkBodyJSON);
checkRequestBody(formData, "formData", checkBodyFormData);
</script>
</body>
</html>

View file

@ -0,0 +1,55 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Request disturbed</title>
<meta name="help" href="https://fetch.spec.whatwg.org/#request">
<meta name="help" href="https://fetch.spec.whatwg.org/#body-mixin">
<meta name="author" title="Canon Research France" href="https://www.crf.canon.fr">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
var initValuesDict = {"method" : "POST",
"body" : "Request's body"
};
var noBodyConsumed = new Request("");
noBodyConsumed.blob();
var bodyConsumed = new Request("", initValuesDict);
bodyConsumed.blob();
test(function() {
assert_false(noBodyConsumed.bodyUsed , "bodyUsed is false when request is not disturbed");
try {
noBodyConsumed.clone();
} catch (e) {
assert_unreached("Can use request not disturbed for creating or cloning request");
}
}, "Request without body cannot be disturbed");
test(function() {
assert_true(bodyConsumed.bodyUsed , "bodyUsed is true when request is disturbed");
assert_throws(new TypeError(), function() { bodyConsumed.clone(); });
}, "Check cloning a disturbed request");
test(function() {
assert_true(bodyConsumed.bodyUsed , "bodyUsed is true when request is disturbed");
assert_throws(new TypeError(), function() { new Request(bodyConsumed); });
}, "Check creating a new request from a disturbed request");
test(function() {
var bodyRequest = new Request("", initValuesDict);
assert_false(bodyRequest.bodyUsed , "bodyUsed is false when request is not disturbed");
var requestFromRequest = new Request(bodyRequest);
assert_true(bodyRequest.bodyUsed , "bodyUsed is true when request is disturbed");
}, "Input request used for creating new request became disturbed");
promise_test(function(test) {
assert_true(bodyConsumed.bodyUsed , "bodyUsed is true when request is disturbed");
return promise_rejects(test, new TypeError(), bodyConsumed.blob());
}, "Check consuming a disturbed request");
</script>
</body>
</html>

View file

@ -0,0 +1,104 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Request error</title>
<meta name="help" href="https://fetch.spec.whatwg.org/#request">
<meta name="help" href="https://fetch.spec.whatwg.org/#body-mixin">
<meta name="author" title="Canon Research France" href="https://www.crf.canon.fr">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
test(function() {
assert_throws(new TypeError() , function() { new Request("", {"window" : "http://test.url"}); },
"Expect TypeError exception");
},"RequestInit's window is not null");
test(function() {
assert_throws(new TypeError() , function() { new Request("http://:not a valid URL"); },
"Expect TypeError exception");
},"Input URL is not valid")
test(function() {
assert_throws(new TypeError() , function() { new Request("http://user:pass@test.url"); },
"Expect TypeError exception");
},"Input URL has credentials");
test(function() {
assert_throws(new TypeError() , function() { new Request("", {"mode" : "navigate"}); },
"Expect TypeError exception");
},"RequestInit's mode is navigate");
test(function() {
assert_throws(new TypeError() , function() { new Request("", {"referrer" : "http://:not a valid URL"}); },
"Expect TypeError exception");
},"RequestInit's referrer is invalid");
test(function() {
assert_throws(new TypeError() , function() { new Request("", {"referrer" : "http://test.url"}); },
"Expect TypeError exception");
},"RequestInit's referrer has invalid origin")
test(function() {
assert_throws(new TypeError() , function() { new Request("", {"method" : "IN VALID"}); },
"Expect TypeError exception");
}, "RequestInit's method is invalid");
test(function() {
assert_throws(new TypeError() , function() { new Request("", {"method" : "TRACE"}); },
"Expect TypeError exception");
}, "RequestInit's method is forbidden");
test(function() {
assert_throws(new TypeError() , function() { new Request("", {"mode" : "no-cors", "method" : "PUT"}); },
"Expect TypeError exception");
},"RequestInit's mode is no-cors and method is not simple");
test(function() {
assert_throws(new TypeError() ,
function() { new Request("", {"mode" : "no-cors", "integrity" : "not an empty string"}); },
"Expect TypeError exception");
},"RequestInit's mode is no-cors and integrity is not empty");
test(function() {
var initialHeaders = new Headers([["Content-Type", "potato"]]);
var initialRequest = new Request("", {"headers" : initialHeaders});
var request = new Request(initialRequest);
assert_equals(request.headers.get("Content-Type"), "potato");
}, "Request should get its content-type from the init request");
test(function() {
var initialHeaders = new Headers([["Content-Type", "potato"]]);
var initialRequest = new Request("", {"headers" : initialHeaders});
var headers = new Headers([]);
var request = new Request(initialRequest, {"headers" : headers});
assert_false(request.headers.has("Content-Type"));
}, "Request should not get its content-type from the init request if init headers are provided");
test(function() {
var initialHeaders = new Headers([["Content-Type-Extra", "potato"]]);
var initialRequest = new Request("", {"headers" : initialHeaders, "body" : "this is my plate", "method" : "POST"});
var request = new Request(initialRequest);
assert_equals(request.headers.get("Content-Type"), "text/plain;charset=UTF-8");
}, "Request should get its content-type from the body if none is provided");
test(function() {
var initialHeaders = new Headers([["Content-Type", "potato"]]);
var initialRequest = new Request("", {"headers" : initialHeaders, "body" : "this is my plate", "method" : "POST"});
var request = new Request(initialRequest);
assert_equals(request.headers.get("Content-Type"), "potato");
}, "Request should get its content-type from init headers if one is provided");
var parameters = ["referrerPolicy", "mode", "credentials", "cache", "redirect"];
parameters.forEach(function(parameter) {
test(function() {
var options = { };
options[parameter] = "BAD";
assert_throws(new TypeError(), function() { new Request("", options); });
},"Bad " + parameter +" init parameter value");
});
</script>
</body>
</html>

View file

@ -0,0 +1,85 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Request idl interface</title>
<meta name="help" href="https://fetch.spec.whatwg.org/#response">
<meta name="author" title="Canon Research France" href="https://www.crf.canon.fr">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/WebIDLParser.js"></script>
<script src="/resources/idlharness.js"></script>
</head>
<body>
<script id="body-idl" type="text/plain">
typedef any JSON;
typedef (Blob or BufferSource or FormData or URLSearchParams or USVString) BodyInit;
[NoInterfaceObject,
Exposed=(Window,Worker)]
interface Body {
readonly attribute boolean bodyUsed;
[NewObject] Promise<ArrayBuffer> arrayBuffer();
[NewObject] Promise<Blob> blob();
[NewObject] Promise<FormData> formData();
[NewObject] Promise<JSON> json();
[NewObject] Promise<USVString> text();
};
</script>
<script id="request-idl" type="text/plain">
typedef (Request or USVString) RequestInfo;
[Constructor(RequestInfo input, optional RequestInit init),
Exposed=(Window,Worker)]
interface Request {
readonly attribute ByteString method;
readonly attribute USVString url;
[SameObject] readonly attribute Headers headers;
readonly attribute RequestType type;
readonly attribute RequestDestination destination;
readonly attribute USVString referrer;
readonly attribute ReferrerPolicy referrerPolicy;
readonly attribute RequestMode mode;
readonly attribute RequestCredentials credentials;
readonly attribute RequestCache cache;
readonly attribute RequestRedirect redirect;
readonly attribute DOMString integrity;
[NewObject] Request clone();
};
Request implements Body;
dictionary RequestInit {
ByteString method;
HeadersInit headers;
BodyInit? body;
USVString referrer;
ReferrerPolicy referrerPolicy;
RequestMode mode;
RequestCredentials credentials;
RequestCache cache;
RequestRedirect redirect;
DOMString integrity;
any window; // can only be set to null
};
enum RequestType { "", "audio", "font", "image", "script", "style", "track", "video" };
enum RequestDestination { "", "document", "sharedworker", "subresource", "unknown", "worker" };
enum RequestMode { "navigate", "same-origin", "no-cors", "cors" };
enum RequestCredentials { "omit", "same-origin", "include" };
enum RequestCache { "default", "no-store", "reload", "no-cache", "force-cache", "only-if-cached" };
enum RequestRedirect { "follow", "error", "manual" };
</script>
<script>
var idlsArray = new IdlArray();
var idl = document.getElementById("body-idl").innerHTML
idl += document.getElementById("request-idl").innerHTML
idlsArray.add_idls(idl);
idlsArray.add_untested_idls("interface Headers {};");
idlsArray.add_objects({ Request: ['new Request("")'] });
idlsArray.test();
</script>
</body>
</html>

View file

@ -0,0 +1,92 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Request init: simple cases</title>
<meta name="help" href="https://fetch.spec.whatwg.org/#request">
<meta name="author" title="Canon Research France" href="https://www.crf.canon.fr">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
var methods = {"givenValues" : ["GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS", "head"],
"expectedValues" : ["GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS", "HEAD"]
};
var referrers = {"givenValues" : ["/relative/ressource",
"http://{{host}}:{{ports[http][0]}}/relative/ressource?query=true#fragment",
"http://{{host}}:{{ports[http][0]}}/",
"about:client",
""
],
"expectedValues" : ["http://{{host}}:{{ports[http][0]}}/relative/ressource",
"http://{{host}}:{{ports[http][0]}}/relative/ressource?query=true#fragment",
"http://{{host}}:{{ports[http][0]}}/",
"about:client",
""
]
};
var referrerPolicies = {"givenValues" : [ "",
"no-referrer",
"no-referrer-when-downgrade",
"origin-only",
"origin-when-cross-origin",
"unsafe-url"
],
"expectedValues" : ["",
"no-referrer",
"no-referrer-when-downgrade",
"origin-only",
"origin-when-cross-origin",
"unsafe-url"
]
};
var modes = {"givenValues" : ["same-origin", "no-cors", "cors"],
"expectedValues" : ["same-origin", "no-cors", "cors"]
};
var credentials = {"givenValues" : ["omit", "same-origin", "include"],
"expectedValues" : ["omit", "same-origin", "include"]
};
var caches = {"givenValues" : [ "default", "no-store", "reload", "no-cache", "force-cache"],
"expectedValues" : [ "default", "no-store", "reload", "no-cache", "force-cache"]
};
var redirects = {"givenValues" : ["follow", "error", "manual"],
"expectedValues" : ["follow", "error", "manual"]
};
var integrities = {"givenValues" : ["", "AZERTYUIOP1234567890" ],
"expectedValues" : ["", "AZERTYUIOP1234567890"]
};
//there is no getter for window, init's window might be null
var windows = {"givenValues" : [ null ],
"expectedValues" : [undefined]
};
var initValuesDict = { "method" : methods,
"referrer" : referrers,
"referrerPolicy" : referrerPolicies,
"mode" : modes,
"credentials" : credentials,
"cache" : caches,
"redirect" : redirects,
"integrity" : integrities,
"window" : windows
};
for (var attributeName in initValuesDict) {
var valuesToTest = initValuesDict[attributeName];
for (var valueIdx in valuesToTest["givenValues"]) {
var givenValue = valuesToTest["givenValues"][valueIdx];
var expectedValue = valuesToTest["expectedValues"][valueIdx];
test(function() {
var requestInit = {};
requestInit[attributeName] = givenValue
var request = new Request("", requestInit);
assert_equals(request[attributeName], expectedValue,
"Expect request's " + attributeName + " is " + expectedValue + " when initialized with " + givenValue);
}, "Check " + attributeName + " init value of " + givenValue + " and associated getter");
}
}
</script>
</body>
</html>

View file

@ -0,0 +1,62 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Request init: headers and body</title>
<meta name="help" href="https://fetch.spec.whatwg.org/#request">
<meta name="author" title="Canon Research France" href="https://www.crf.canon.fr">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
test(function() {
var headerDict = {"name1": "value1",
"name2": "value2",
"name3": "value3"
};
var headers = new Headers(headerDict);
var request = new Request("", { "headers" : headers })
for (var name in headerDict) {
assert_equals(request.headers.get(name), headerDict[name],
"request's headers has " + name + " : " + headerDict[name]);
}
}, "Initialize Request with headers values");
function checkRequestInit(body, bodyType, expectedTextBody) {
promise_test(function(test) {
var request = new Request("", {"method": "POST", "body": body});
assert_throws(new TypeError(),
function() { new Request("", {"method": "GET", "body": body}); }
);
var reqHeaders = request.headers;
var mime = reqHeaders.get("Content-Type");
assert_true(mime && mime.search(bodyType) > -1, "Content-Type header should be \"" + bodyType + "\", not \"" + mime + "\"");
return request.text().then(function(bodyAsText) {
//not equals: cannot guess formData exact value
assert_true( bodyAsText.search(expectedTextBody) > -1, "Retrieve and verify request body");
});
}, "Initialize Response's body with " + bodyType);
}
var blob = new Blob(["This is a blob"], {type: "application/octet-binary"});
var formaData = new FormData();
formaData.append("name", "value");
var usvString = "This is a USVString"
checkRequestInit(blob, "application/octet-binary", "This is a blob");
checkRequestInit(formaData, "multipart/form-data", "name=\"name\"\r\n\r\nvalue");
checkRequestInit(usvString, "text/plain;charset=UTF-8", "This is a USVString");
// Ensure test does not time out in case of missing URLSearchParams support.
if (window.URLSearchParams) {
var urlSearchParams = new URLSearchParams("name=value");
checkRequestInit(urlSearchParams, "application/x-www-form-urlencoded;charset=UTF-8", "name=value");
} else {
promise_test(function(test) {
return Promise.reject("URLSearchParams not supported");
}, "Initialize Response's body with application/x-www-form-urlencoded;charset=UTF-8");
}
</script>
</body>
</html>

View file

@ -0,0 +1,84 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Request: init with request or url</title>
<meta name="help" href="https://fetch.spec.whatwg.org/#request">
<meta name="help" href="https://url.spec.whatwg.org/#concept-url-serializer">
<meta name="author" title="Canon Research France" href="https://www.crf.canon.fr">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script src="../resources/utils.js"></script>
<script>
var headers = new Headers( {"name":"value"} );
var emptyHeaders = new Headers();
var initValuesDict = {"method" : "POST",
"referrer" : "http://{{host}}:{{ports[http][0]}}/",
"referrerPolicy" : "origin-only",
"mode" : "same-origin",
"credentials" : "include",
"cache" : "no-cache",
"redirect" : "error",
"integrity" : "Request's Integrity",
"headers" : headers,
"body" : "Request's body"
};
var expectedInitialized = {"method" : "POST",
"referrer" : "http://{{host}}:{{ports[http][0]}}/",
"referrerPolicy" : "origin-only",
"mode" : "same-origin",
"credentials" : "include",
"cache" : "no-cache",
"redirect" : "error",
"integrity" : "Request's Integrity",
"headers" : headers,
"body" : "Request's body"
};
var expectedDefault = {"method" : "GET",
"url" : location.href,
"referrer" : "http://{{host}}:{{ports[http][0]}}/",
"referrerPolicy" : "",
"mode" : "cors",
"credentials" : "omit",
"cache" : "default",
"redirect" : "follow",
"integrity" : "",
"headers" : emptyHeaders
};
var requestDefault = new Request("");
var requestInitialized = new Request("", initValuesDict);
test(function() {
var requestToCheck = new Request(requestInitialized);
checkRequest(requestToCheck, expectedInitialized);
}, "Check request values when initialized from Request");
test(function() {
var requestToCheck = new Request(requestDefault, initValuesDict);
checkRequest(requestToCheck, expectedInitialized);
}, "Check request values when initialized from Request and init values");
test(function() {
var url = "http://url.test:1234/path/subpath?query=true";
expectedDefault["url"] = url;
url += "#fragment";
var requestToCheck = new Request(url);
checkRequest(requestToCheck, expectedDefault);
}, "Check request values when initialized from url string");
test(function() {
var url = "http://url.test:1234/path/subpath?query=true";
expectedInitialized["url"] = url;
url += "#fragment";
var requestToCheck = new Request(url , initValuesDict);
checkRequest(requestToCheck, expectedInitialized);
}, "Check request values when initialized from url and init values");
</script>
</body>
</html>

View file

@ -0,0 +1,132 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Request structure</title>
<meta name="help" href="https://fetch.spec.whatwg.org/#request">
<meta name="author" title="Canon Research France" href="https://www.crf.canon.fr">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
var request = new Request("");
var methods = ["clone",
//Request implements Body
"arrayBuffer",
"blob",
"formData",
"json",
"text"
];
var attributes = ["method",
"url",
"headers",
"type",
"destination",
"referrer",
"referrerPolicy",
"mode",
"credentials",
"cache",
"redirect",
"integrity",
//Request implements Body
"bodyUsed"
];
function IsreadOnly(request, attributeToCheck) {
var defaultValue = undefined;
var newValue = undefined;
switch (attributeToCheck) {
case "method":
defaultValue = "GET";
newValue = "POST";
break;
case "url":
//default value is base url
//i.e http://web-platform.test:8000/fetch/api/request-structure.html
newValue = "http://url.test";
break;
case "headers":
request.headers = new Headers ( {"name":"value"} );
assert_false(request.headers.has("name"), "Headers attribute is read only");
return;
break;
case "type":
defaultValue = "";
newValue = "style";
break;
case "destination":
defaultValue = "";
newValue = "worker";
break;
case "referrer":
defaultValue = "about:client";
newValue = "http://url.test";
break;
case "referrerPolicy":
defaultValue = "";
newValue = "unsafe-url";
break;
case "mode":
defaultValue = "cors";
newValue = "navigate";
break;
case "credentials":
defaultValue = "omit";
newValue = "cors";
break;
case "cache":
defaultValue = "default";
newValue = "reload";
break;
case "redirect":
defaultValue = "follow";
newValue = "manual";
break;
case "integrity":
newValue = "CannotWriteIntegrity";
break;
case "bodyUsed":
defaultValue = false;
newValue = true;
break;
default:
return;
}
request[attributeToCheck] = newValue;
if (defaultValue === undefined)
assert_not_equals(request[attributeToCheck], newValue, "Attribute " + attributeToCheck + " is read only");
else
assert_equals(request[attributeToCheck], defaultValue,
"Attribute " + attributeToCheck + " is read only. Default value is " + defaultValue);
}
for (var idx in methods)
test(function() {
assert_true(methods[idx] in request, "request has " + methods[idx] + " method");
}, "Request has " + methods[idx] + " method");
for (var idx in attributes)
test(function() {
assert_true(attributes[idx] in request, "request has " + attributes[idx] + " attribute");
IsreadOnly(request, attributes[idx]);
}, "Check " + attributes[idx] + " attribute");
</script>
</body>
</html>