Commit f30452ba authored by jochen@chromium.org's avatar jochen@chromium.org

Store i18n meta data in hidden symbols instead of js accessible properties

There were some tests that are supposed to protect against js messing
with the meta data, however, they just didn't try hard enough.

BUG=354967
R=dcarney@chromium.org
LOG=y

Committed: https://code.google.com/p/v8/source/detail?r=20375

Review URL: https://codereview.chromium.org/215293005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20388 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 69f8179c
...@@ -376,7 +376,9 @@ namespace internal { ...@@ -376,7 +376,9 @@ namespace internal {
V(next_string, "next") \ V(next_string, "next") \
V(byte_length_string, "byteLength") \ V(byte_length_string, "byteLength") \
V(byte_offset_string, "byteOffset") \ V(byte_offset_string, "byteOffset") \
V(buffer_string, "buffer") V(buffer_string, "buffer") \
V(intl_initialized_marker_string, "v8::intl_initialized_marker") \
V(intl_impl_object_string, "v8::intl_object")
// Forward declarations. // Forward declarations.
class GCTracer; class GCTracer;
......
...@@ -232,8 +232,7 @@ var ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR = ...@@ -232,8 +232,7 @@ var ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR =
*/ */
function addBoundMethod(obj, methodName, implementation, length) { function addBoundMethod(obj, methodName, implementation, length) {
function getter() { function getter() {
if (!this || typeof this !== 'object' || if (!%IsInitializedIntlObject(this)) {
this.__initializedIntlObject === undefined) {
throw new $TypeError('Method ' + methodName + ' called on a ' + throw new $TypeError('Method ' + methodName + ' called on a ' +
'non-object or on a wrong type of object.'); 'non-object or on a wrong type of object.');
} }
...@@ -896,7 +895,7 @@ function BuildLanguageTagREs() { ...@@ -896,7 +895,7 @@ function BuildLanguageTagREs() {
* Useful for subclassing. * Useful for subclassing.
*/ */
function initializeCollator(collator, locales, options) { function initializeCollator(collator, locales, options) {
if (collator.hasOwnProperty('__initializedIntlObject')) { if (%IsInitializedIntlObject(collator)) {
throw new $TypeError('Trying to re-initialize Collator object.'); throw new $TypeError('Trying to re-initialize Collator object.');
} }
...@@ -967,9 +966,7 @@ function initializeCollator(collator, locales, options) { ...@@ -967,9 +966,7 @@ function initializeCollator(collator, locales, options) {
resolved); resolved);
// Writable, configurable and enumerable are set to false by default. // Writable, configurable and enumerable are set to false by default.
$Object.defineProperty(collator, 'collator', {value: internalCollator}); %MarkAsInitializedIntlObjectOfType(collator, 'collator', internalCollator);
$Object.defineProperty(collator, '__initializedIntlObject',
{value: 'collator'});
$Object.defineProperty(collator, 'resolved', {value: resolved}); $Object.defineProperty(collator, 'resolved', {value: resolved});
return collator; return collator;
...@@ -1005,8 +1002,7 @@ function initializeCollator(collator, locales, options) { ...@@ -1005,8 +1002,7 @@ function initializeCollator(collator, locales, options) {
throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR); throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
} }
if (!this || typeof this !== 'object' || if (!%IsInitializedIntlObjectOfType(this, 'collator')) {
this.__initializedIntlObject !== 'collator') {
throw new $TypeError('resolvedOptions method called on a non-object ' + throw new $TypeError('resolvedOptions method called on a non-object ' +
'or on a object that is not Intl.Collator.'); 'or on a object that is not Intl.Collator.');
} }
...@@ -1063,7 +1059,8 @@ function initializeCollator(collator, locales, options) { ...@@ -1063,7 +1059,8 @@ function initializeCollator(collator, locales, options) {
* the sort order, or x comes after y in the sort order, respectively. * the sort order, or x comes after y in the sort order, respectively.
*/ */
function compare(collator, x, y) { function compare(collator, x, y) {
return %InternalCompare(collator.collator, $String(x), $String(y)); return %InternalCompare(%GetImplFromInitializedIntlObject(collator),
$String(x), $String(y));
}; };
...@@ -1104,7 +1101,7 @@ function getNumberOption(options, property, min, max, fallback) { ...@@ -1104,7 +1101,7 @@ function getNumberOption(options, property, min, max, fallback) {
* Useful for subclassing. * Useful for subclassing.
*/ */
function initializeNumberFormat(numberFormat, locales, options) { function initializeNumberFormat(numberFormat, locales, options) {
if (numberFormat.hasOwnProperty('__initializedIntlObject')) { if (%IsInitializedIntlObject(numberFormat)) {
throw new $TypeError('Trying to re-initialize NumberFormat object.'); throw new $TypeError('Trying to re-initialize NumberFormat object.');
} }
...@@ -1196,10 +1193,8 @@ function initializeNumberFormat(numberFormat, locales, options) { ...@@ -1196,10 +1193,8 @@ function initializeNumberFormat(numberFormat, locales, options) {
writable: true}); writable: true});
} }
$Object.defineProperty(numberFormat, 'formatter', {value: formatter}); %MarkAsInitializedIntlObjectOfType(numberFormat, 'numberformat', formatter);
$Object.defineProperty(numberFormat, 'resolved', {value: resolved}); $Object.defineProperty(numberFormat, 'resolved', {value: resolved});
$Object.defineProperty(numberFormat, '__initializedIntlObject',
{value: 'numberformat'});
return numberFormat; return numberFormat;
} }
...@@ -1234,8 +1229,7 @@ function initializeNumberFormat(numberFormat, locales, options) { ...@@ -1234,8 +1229,7 @@ function initializeNumberFormat(numberFormat, locales, options) {
throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR); throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
} }
if (!this || typeof this !== 'object' || if (!%IsInitializedIntlObjectOfType(this, 'numberformat')) {
this.__initializedIntlObject !== 'numberformat') {
throw new $TypeError('resolvedOptions method called on a non-object' + throw new $TypeError('resolvedOptions method called on a non-object' +
' or on a object that is not Intl.NumberFormat.'); ' or on a object that is not Intl.NumberFormat.');
} }
...@@ -1309,7 +1303,8 @@ function formatNumber(formatter, value) { ...@@ -1309,7 +1303,8 @@ function formatNumber(formatter, value) {
// Spec treats -0 and +0 as 0. // Spec treats -0 and +0 as 0.
var number = $Number(value) + 0; var number = $Number(value) + 0;
return %InternalNumberFormat(formatter.formatter, number); return %InternalNumberFormat(%GetImplFromInitializedIntlObject(formatter),
number);
} }
...@@ -1317,7 +1312,8 @@ function formatNumber(formatter, value) { ...@@ -1317,7 +1312,8 @@ function formatNumber(formatter, value) {
* Returns a Number that represents string value that was passed in. * Returns a Number that represents string value that was passed in.
*/ */
function parseNumber(formatter, value) { function parseNumber(formatter, value) {
return %InternalNumberParse(formatter.formatter, $String(value)); return %InternalNumberParse(%GetImplFromInitializedIntlObject(formatter),
$String(value));
} }
...@@ -1530,7 +1526,7 @@ function toDateTimeOptions(options, required, defaults) { ...@@ -1530,7 +1526,7 @@ function toDateTimeOptions(options, required, defaults) {
*/ */
function initializeDateTimeFormat(dateFormat, locales, options) { function initializeDateTimeFormat(dateFormat, locales, options) {
if (dateFormat.hasOwnProperty('__initializedIntlObject')) { if (%IsInitializedIntlObject(dateFormat)) {
throw new $TypeError('Trying to re-initialize DateTimeFormat object.'); throw new $TypeError('Trying to re-initialize DateTimeFormat object.');
} }
...@@ -1592,10 +1588,8 @@ function initializeDateTimeFormat(dateFormat, locales, options) { ...@@ -1592,10 +1588,8 @@ function initializeDateTimeFormat(dateFormat, locales, options) {
throw new $RangeError('Unsupported time zone specified ' + tz); throw new $RangeError('Unsupported time zone specified ' + tz);
} }
$Object.defineProperty(dateFormat, 'formatter', {value: formatter}); %MarkAsInitializedIntlObjectOfType(dateFormat, 'dateformat', formatter);
$Object.defineProperty(dateFormat, 'resolved', {value: resolved}); $Object.defineProperty(dateFormat, 'resolved', {value: resolved});
$Object.defineProperty(dateFormat, '__initializedIntlObject',
{value: 'dateformat'});
return dateFormat; return dateFormat;
} }
...@@ -1630,8 +1624,7 @@ function initializeDateTimeFormat(dateFormat, locales, options) { ...@@ -1630,8 +1624,7 @@ function initializeDateTimeFormat(dateFormat, locales, options) {
throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR); throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
} }
if (!this || typeof this !== 'object' || if (!%IsInitializedIntlObjectOfType(this, 'dateformat')) {
this.__initializedIntlObject !== 'dateformat') {
throw new $TypeError('resolvedOptions method called on a non-object or ' + throw new $TypeError('resolvedOptions method called on a non-object or ' +
'on a object that is not Intl.DateTimeFormat.'); 'on a object that is not Intl.DateTimeFormat.');
} }
...@@ -1713,7 +1706,8 @@ function formatDate(formatter, dateValue) { ...@@ -1713,7 +1706,8 @@ function formatDate(formatter, dateValue) {
throw new $RangeError('Provided date is not in valid range.'); throw new $RangeError('Provided date is not in valid range.');
} }
return %InternalDateFormat(formatter.formatter, new $Date(dateMs)); return %InternalDateFormat(%GetImplFromInitializedIntlObject(formatter),
new $Date(dateMs));
} }
...@@ -1724,7 +1718,8 @@ function formatDate(formatter, dateValue) { ...@@ -1724,7 +1718,8 @@ function formatDate(formatter, dateValue) {
* Returns undefined if date string cannot be parsed. * Returns undefined if date string cannot be parsed.
*/ */
function parseDate(formatter, value) { function parseDate(formatter, value) {
return %InternalDateParse(formatter.formatter, $String(value)); return %InternalDateParse(%GetImplFromInitializedIntlObject(formatter),
$String(value));
} }
...@@ -1772,7 +1767,7 @@ function canonicalizeTimeZoneID(tzID) { ...@@ -1772,7 +1767,7 @@ function canonicalizeTimeZoneID(tzID) {
* Useful for subclassing. * Useful for subclassing.
*/ */
function initializeBreakIterator(iterator, locales, options) { function initializeBreakIterator(iterator, locales, options) {
if (iterator.hasOwnProperty('__initializedIntlObject')) { if (%IsInitializedIntlObject(iterator)) {
throw new $TypeError('Trying to re-initialize v8BreakIterator object.'); throw new $TypeError('Trying to re-initialize v8BreakIterator object.');
} }
...@@ -1798,10 +1793,9 @@ function initializeBreakIterator(iterator, locales, options) { ...@@ -1798,10 +1793,9 @@ function initializeBreakIterator(iterator, locales, options) {
internalOptions, internalOptions,
resolved); resolved);
$Object.defineProperty(iterator, 'iterator', {value: internalIterator}); %MarkAsInitializedIntlObjectOfType(iterator, 'breakiterator',
internalIterator);
$Object.defineProperty(iterator, 'resolved', {value: resolved}); $Object.defineProperty(iterator, 'resolved', {value: resolved});
$Object.defineProperty(iterator, '__initializedIntlObject',
{value: 'breakiterator'});
return iterator; return iterator;
} }
...@@ -1836,8 +1830,7 @@ function initializeBreakIterator(iterator, locales, options) { ...@@ -1836,8 +1830,7 @@ function initializeBreakIterator(iterator, locales, options) {
throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR); throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
} }
if (!this || typeof this !== 'object' || if (!%IsInitializedIntlObjectOfType(this, 'breakiterator')) {
this.__initializedIntlObject !== 'breakiterator') {
throw new $TypeError('resolvedOptions method called on a non-object or ' + throw new $TypeError('resolvedOptions method called on a non-object or ' +
'on a object that is not Intl.v8BreakIterator.'); 'on a object that is not Intl.v8BreakIterator.');
} }
...@@ -1884,7 +1877,8 @@ function initializeBreakIterator(iterator, locales, options) { ...@@ -1884,7 +1877,8 @@ function initializeBreakIterator(iterator, locales, options) {
* gets discarded. * gets discarded.
*/ */
function adoptText(iterator, text) { function adoptText(iterator, text) {
%BreakIteratorAdoptText(iterator.iterator, $String(text)); %BreakIteratorAdoptText(%GetImplFromInitializedIntlObject(iterator),
$String(text));
} }
...@@ -1892,7 +1886,7 @@ function adoptText(iterator, text) { ...@@ -1892,7 +1886,7 @@ function adoptText(iterator, text) {
* Returns index of the first break in the string and moves current pointer. * Returns index of the first break in the string and moves current pointer.
*/ */
function first(iterator) { function first(iterator) {
return %BreakIteratorFirst(iterator.iterator); return %BreakIteratorFirst(%GetImplFromInitializedIntlObject(iterator));
} }
...@@ -1900,7 +1894,7 @@ function first(iterator) { ...@@ -1900,7 +1894,7 @@ function first(iterator) {
* Returns the index of the next break and moves the pointer. * Returns the index of the next break and moves the pointer.
*/ */
function next(iterator) { function next(iterator) {
return %BreakIteratorNext(iterator.iterator); return %BreakIteratorNext(%GetImplFromInitializedIntlObject(iterator));
} }
...@@ -1908,7 +1902,7 @@ function next(iterator) { ...@@ -1908,7 +1902,7 @@ function next(iterator) {
* Returns index of the current break. * Returns index of the current break.
*/ */
function current(iterator) { function current(iterator) {
return %BreakIteratorCurrent(iterator.iterator); return %BreakIteratorCurrent(%GetImplFromInitializedIntlObject(iterator));
} }
...@@ -1916,7 +1910,7 @@ function current(iterator) { ...@@ -1916,7 +1910,7 @@ function current(iterator) {
* Returns type of the current break. * Returns type of the current break.
*/ */
function breakType(iterator) { function breakType(iterator) {
return %BreakIteratorBreakType(iterator.iterator); return %BreakIteratorBreakType(%GetImplFromInitializedIntlObject(iterator));
} }
......
...@@ -13899,6 +13899,87 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLanguageTagVariants) { ...@@ -13899,6 +13899,87 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLanguageTagVariants) {
} }
RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInitializedIntlObject) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
if (!input->IsJSObject()) return isolate->heap()->ToBoolean(false);
Handle<JSObject> obj = Handle<JSObject>::cast(input);
Handle<String> marker = isolate->factory()->intl_initialized_marker_string();
Handle<Object> tag(obj->GetHiddenProperty(*marker), isolate);
return isolate->heap()->ToBoolean(!tag->IsTheHole());
}
RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInitializedIntlObjectOfType) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
CONVERT_ARG_HANDLE_CHECKED(String, expected_type, 1);
if (!input->IsJSObject()) return isolate->heap()->ToBoolean(false);
Handle<JSObject> obj = Handle<JSObject>::cast(input);
Handle<String> marker = isolate->factory()->intl_initialized_marker_string();
Handle<Object> tag(obj->GetHiddenProperty(*marker), isolate);
return isolate->heap()->ToBoolean(
tag->IsString() && String::cast(*tag)->Equals(*expected_type));
}
RUNTIME_FUNCTION(MaybeObject*, Runtime_MarkAsInitializedIntlObjectOfType) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSObject, input, 0);
CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, impl, 2);
Handle<String> marker = isolate->factory()->intl_initialized_marker_string();
JSObject::SetHiddenProperty(input, marker, type);
marker = isolate->factory()->intl_impl_object_string();
JSObject::SetHiddenProperty(input, marker, impl);
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetImplFromInitializedIntlObject) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
if (!input->IsJSObject()) {
Vector< Handle<Object> > arguments = HandleVector(&input, 1);
Handle<Object> type_error =
isolate->factory()->NewTypeError("not_intl_object", arguments);
return isolate->Throw(*type_error);
}
Handle<JSObject> obj = Handle<JSObject>::cast(input);
Handle<String> marker = isolate->factory()->intl_impl_object_string();
Handle<Object> impl(obj->GetHiddenProperty(*marker), isolate);
if (impl->IsTheHole()) {
Vector< Handle<Object> > arguments = HandleVector(&obj, 1);
Handle<Object> type_error =
isolate->factory()->NewTypeError("not_intl_object", arguments);
return isolate->Throw(*type_error);
}
return *impl;
}
RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateDateTimeFormat) { RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateDateTimeFormat) {
HandleScope scope(isolate); HandleScope scope(isolate);
......
...@@ -491,6 +491,10 @@ namespace internal { ...@@ -491,6 +491,10 @@ namespace internal {
F(AvailableLocalesOf, 1, 1) \ F(AvailableLocalesOf, 1, 1) \
F(GetDefaultICULocale, 0, 1) \ F(GetDefaultICULocale, 0, 1) \
F(GetLanguageTagVariants, 1, 1) \ F(GetLanguageTagVariants, 1, 1) \
F(IsInitializedIntlObject, 1, 1) \
F(IsInitializedIntlObjectOfType, 2, 1) \
F(MarkAsInitializedIntlObjectOfType, 3, 1) \
F(GetImplFromInitializedIntlObject, 1, 1) \
\ \
/* Date format and parse. */ \ /* Date format and parse. */ \
F(CreateDateTimeFormat, 3, 1) \ F(CreateDateTimeFormat, 3, 1) \
......
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Internal object we got from native code should not be writable,
// configurable or enumerable. One can still change its public properties, but
// we don't use them to do actual work.
var iterator = new Intl.v8BreakIterator([]);
// Direct write should fail.
iterator.iterator = {'zzz':'some random object'};
assertFalse(iterator.iterator.hasOwnProperty('zzz'));
// Try redefining the property.
var didThrow = false;
try {
Object.defineProperty(iterator, 'iterator', {value: undefined});
} catch(e) {
didThrow = true;
}
assertTrue(didThrow);
// Try deleting the property.
assertFalse(delete iterator.iterator);
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Internal object we got from native code should not be writable,
// configurable or enumerable. One can still change its public properties, but
// we don't use them to do actual work.
var collator = new Intl.Collator([]);
// Direct write should fail.
collator.collator = {'zzz':'some random object'};
assertFalse(collator.collator.hasOwnProperty('zzz'));
// Try redefining the property.
var didThrow = false;
try {
Object.defineProperty(collator, 'collator', {value: undefined});
} catch(e) {
didThrow = true;
}
assertTrue(didThrow);
// Try deleting the property.
assertFalse(delete collator.collator);
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Internal object we got from native code should not be writable,
// configurable or enumerable. One can still change its public properties, but
// we don't use them to do actual work.
var format = new Intl.DateTimeFormat([]);
// Direct write should fail.
format.formatter = {'zzz':'some random object'};
assertFalse(format.formatter.hasOwnProperty('zzz'));
// Try redefining the property.
var didThrow = false;
try {
Object.defineProperty(format, 'formatter', {value: undefined});
} catch(e) {
didThrow = true;
}
assertTrue(didThrow);
// Try deleting the property.
assertFalse(delete format.formatter);
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Internal object we got from native code should not be writable,
// configurable or enumerable. One can still change its public properties, but
// we don't use them to do actual work.
var format = new Intl.NumberFormat([]);
// Direct write should fail.
format.formatter = {'zzz':'some random object'};
assertFalse(format.formatter.hasOwnProperty('zzz'));
// Try redefining the property.
var didThrow = false;
try {
Object.defineProperty(format, 'formatter', {value: undefined});
} catch(e) {
didThrow = true;
}
assertTrue(didThrow);
// Try deleting the property.
assertFalse(delete format.formatter);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment