Changeset 230704 in webkit
- Timestamp:
- Apr 17, 2018 1:15:28 AM (6 years ago)
- Location:
- trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/API/glib/JSCValue.cpp
r230558 r230704 674 674 return jsc_value_new_undefined(priv->context.get()); 675 675 676 677 676 JSRetainPtr<JSStringRef> propertyName(Adopt, JSStringCreateWithUTF8CString(name)); 678 677 JSValueRef result = JSObjectGetProperty(jsContext, object, propertyName.get(), &exception); … … 727 726 return jsc_value_new_undefined(priv->context.get()); 728 727 729 730 728 JSValueRef result = JSObjectGetPropertyAtIndex(jsContext, object, index, &exception); 731 729 if (jscContextHandleExceptionIfNeeded(priv->context.get(), exception)) … … 733 731 734 732 return jscContextGetOrCreateValue(priv->context.get(), result).leakRef(); 733 } 734 735 /** 736 * jsc_value_object_has_property: 737 * @value: a #JSCValue 738 * @name: the property name 739 * 740 * Get whether @value has property with @name. 741 * 742 * Returns: %TRUE if @value has a property with @name, or %FALSE otherwise 743 */ 744 gboolean jsc_value_object_has_property(JSCValue* value, const char* name) 745 { 746 g_return_val_if_fail(JSC_IS_VALUE(value), FALSE); 747 g_return_val_if_fail(name, FALSE); 748 749 JSCValuePrivate* priv = value->priv; 750 auto* jsContext = jscContextGetJSContext(priv->context.get()); 751 JSValueRef exception = nullptr; 752 JSObjectRef object = JSValueToObject(jsContext, priv->jsValue, &exception); 753 if (jscContextHandleExceptionIfNeeded(priv->context.get(), exception)) 754 return FALSE; 755 756 JSRetainPtr<JSStringRef> propertyName(Adopt, JSStringCreateWithUTF8CString(name)); 757 return JSObjectHasProperty(jsContext, object, propertyName.get()); 758 } 759 760 /** 761 * jsc_value_object_delete_property: 762 * @value: a #JSCValue 763 * @name: the property name 764 * 765 * Try to delete property with @name from @value. This function will return %FALSE if 766 * the property was defined without %JSC_VALUE_PROPERTY_CONFIGURABLE flag. 767 * 768 * Returns: %TRUE if the property was deleted, or %FALSE otherwise. 769 */ 770 gboolean jsc_value_object_delete_property(JSCValue* value, const char* name) 771 { 772 g_return_val_if_fail(JSC_IS_VALUE(value), FALSE); 773 g_return_val_if_fail(name, FALSE); 774 775 JSCValuePrivate* priv = value->priv; 776 auto* jsContext = jscContextGetJSContext(priv->context.get()); 777 JSValueRef exception = nullptr; 778 JSObjectRef object = JSValueToObject(jsContext, priv->jsValue, &exception); 779 if (jscContextHandleExceptionIfNeeded(priv->context.get(), exception)) 780 return FALSE; 781 782 JSRetainPtr<JSStringRef> propertyName(Adopt, JSStringCreateWithUTF8CString(name)); 783 gboolean result = JSObjectDeleteProperty(jsContext, object, propertyName.get(), &exception); 784 if (jscContextHandleExceptionIfNeeded(priv->context.get(), exception)) 785 return FALSE; 786 787 return result; 788 } 789 790 /** 791 * jsc_value_object_enumerate_properties: 792 * @value: a #JSCValue 793 * 794 * Get the list of property names of @value. Only properties defined with %JSC_VALUE_PROPERTY_ENUMERABLE 795 * flag will be collected. 796 * 797 * Returns: (array zero-terminated=1) (transfer full) (nullable): a %NULL-terminated array of strings containing the 798 * property names, or %NULL if @value doesn't have enumerable properties. Use g_strfreev() to free. 799 */ 800 char** jsc_value_object_enumerate_properties(JSCValue* value) 801 { 802 g_return_val_if_fail(JSC_IS_VALUE(value), nullptr); 803 804 JSCValuePrivate* priv = value->priv; 805 auto* jsContext = jscContextGetJSContext(priv->context.get()); 806 JSValueRef exception = nullptr; 807 JSObjectRef object = JSValueToObject(jsContext, priv->jsValue, &exception); 808 if (jscContextHandleExceptionIfNeeded(priv->context.get(), exception)) 809 return nullptr; 810 811 auto* propertiesArray = JSObjectCopyPropertyNames(jsContext, object); 812 if (!propertiesArray) 813 return nullptr; 814 815 auto propertiesArraySize = JSPropertyNameArrayGetCount(propertiesArray); 816 if (!propertiesArraySize) { 817 JSPropertyNameArrayRelease(propertiesArray); 818 return nullptr; 819 } 820 821 auto* result = static_cast<char**>(g_new0(char*, propertiesArraySize + 1)); 822 for (unsigned i = 0; i < propertiesArraySize; ++i) { 823 auto* jsString = JSPropertyNameArrayGetNameAtIndex(propertiesArray, i); 824 size_t maxSize = JSStringGetMaximumUTF8CStringSize(jsString); 825 auto* string = static_cast<char*>(g_malloc(maxSize)); 826 JSStringGetUTF8CString(jsString, string, maxSize); 827 result[i] = string; 828 } 829 JSPropertyNameArrayRelease(propertiesArray); 830 831 return result; 735 832 } 736 833 -
trunk/Source/JavaScriptCore/API/glib/JSCValue.h
r230558 r230704 164 164 guint index); 165 165 166 JSC_API gboolean 167 jsc_value_object_has_property (JSCValue *value, 168 const char *name); 169 170 JSC_API gboolean 171 jsc_value_object_delete_property (JSCValue *value, 172 const char *name); 173 174 JSC_API gchar ** 175 jsc_value_object_enumerate_properties (JSCValue *value); 176 166 177 JSC_API JSCValue * 167 178 jsc_value_object_invoke_method (JSCValue *value, -
trunk/Source/JavaScriptCore/API/glib/docs/jsc-glib-4.0-sections.txt
r230558 r230704 88 88 jsc_value_object_set_property_at_index 89 89 jsc_value_object_get_property_at_index 90 jsc_value_object_has_property 91 jsc_value_object_delete_property 92 jsc_value_object_enumerate_properties 90 93 jsc_value_object_invoke_method 91 94 jsc_value_object_define_property_data -
trunk/Source/JavaScriptCore/ChangeLog
r230697 r230704 1 2018-04-17 Carlos Garcia Campos <cgarcia@igalia.com> 2 3 [GLIB] Add API to query, delete and enumerate properties 4 https://bugs.webkit.org/show_bug.cgi?id=184647 5 6 Reviewed by Michael Catanzaro. 7 8 Add jsc_value_object_has_property(), jsc_value_object_delete_property() and jsc_value_object_enumerate_properties(). 9 10 * API/glib/JSCValue.cpp: 11 (jsc_value_object_has_property): 12 (jsc_value_object_delete_property): 13 (jsc_value_object_enumerate_properties): 14 * API/glib/JSCValue.h: 15 * API/glib/docs/jsc-glib-4.0-sections.txt: 16 1 17 2018-04-16 Yusuke Suzuki <utatane.tea@gmail.com> 2 18 -
trunk/Tools/ChangeLog
r230700 r230704 1 2018-04-17 Carlos Garcia Campos <cgarcia@igalia.com> 2 3 [GLIB] Add API to query, delete and enumerate properties 4 https://bugs.webkit.org/show_bug.cgi?id=184647 5 6 Reviewed by Michael Catanzaro. 7 8 Add test cases for the new API. 9 10 * TestWebKitAPI/Tests/JavaScriptCore/glib/TestJSC.cpp: 11 (testJSCObject): 12 (testJSCClass): 13 (testJSCPrototypes): 14 1 15 2018-04-16 Zalan Bujtas <zalan@apple.com> 2 16 -
trunk/Tools/TestWebKitAPI/Tests/JavaScriptCore/glib/TestJSC.cpp
r230558 r230704 706 706 g_assert_true(jsc_value_is_object(foo.get())); 707 707 g_assert_true(jsc_value_object_is_instance_of(foo.get(), "Foo")); 708 g_assert_true(jsc_value_object_has_property(foo.get(), "foo")); 709 710 GUniquePtr<char*> properties(jsc_value_object_enumerate_properties(foo.get())); 711 g_assert_null(properties.get()); 708 712 709 713 GRefPtr<JSCValue> result = adoptGRef(jsc_value_object_invoke_method(foo.get(), "foo", G_TYPE_INT, 200, G_TYPE_NONE)); … … 712 716 g_assert_cmpint(jsc_value_to_int32(result.get()), ==, 400); 713 717 718 g_assert_false(jsc_value_object_has_property(foo.get(), "bar")); 714 719 bool didThrow = false; 715 720 g_assert_throw_begin(exceptionHandler, didThrow); … … 756 761 g_assert_true(jsc_value_object_is_instance_of(object.get(), "Object")); 757 762 763 GUniquePtr<char*> properties(jsc_value_object_enumerate_properties(object.get())); 764 g_assert_null(properties.get()); 765 758 766 GRefPtr<JSCValue> property = adoptGRef(jsc_value_new_number(context.get(), 25)); 759 767 checker.watch(property.get()); 760 768 g_assert_false(jsc_value_object_has_property(object.get(), "val")); 761 769 jsc_value_object_define_property_data(object.get(), "val", static_cast<JSCValuePropertyFlags>(0), property.get()); 770 g_assert_true(jsc_value_object_has_property(object.get(), "val")); 771 properties.reset(jsc_value_object_enumerate_properties(object.get())); 772 g_assert_null(properties.get()); 762 773 jsc_context_set_value(context.get(), "f", object.get()); 763 774 … … 781 792 value = adoptGRef(jsc_context_evaluate(context.get(), "delete f.val;", -1)); 782 793 checker.watch(value.get()); 794 g_assert_true(jsc_value_object_has_property(object.get(), "val")); 783 795 value = adoptGRef(jsc_context_evaluate(context.get(), "f.val;", -1)); 784 796 checker.watch(value.get()); 785 797 g_assert_true(jsc_value_is_number(value.get())); 786 798 g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 25); 799 800 g_assert_false(jsc_value_object_delete_property(object.get(), "val")); 801 g_assert_true(jsc_value_object_has_property(object.get(), "val")); 787 802 788 803 property = adoptGRef(jsc_value_new_number(context.get(), 52)); … … 794 809 property = adoptGRef(jsc_value_new_number(context.get(), 32)); 795 810 checker.watch(property.get()); 811 g_assert_false(jsc_value_object_has_property(object.get(), "val2")); 796 812 jsc_value_object_define_property_data(object.get(), "val2", static_cast<JSCValuePropertyFlags>(JSC_VALUE_PROPERTY_ENUMERABLE | JSC_VALUE_PROPERTY_WRITABLE), property.get()); 813 g_assert_true(jsc_value_object_has_property(object.get(), "val2")); 797 814 value = adoptGRef(jsc_context_evaluate(context.get(), "f.val2;", -1)); 798 815 checker.watch(value.get()); 799 816 g_assert_true(jsc_value_is_number(value.get())); 800 817 g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 32); 818 819 properties.reset(jsc_value_object_enumerate_properties(object.get())); 820 g_assert_cmpuint(g_strv_length(properties.get()), ==, 1); 821 g_assert_cmpstr(properties.get()[0], ==, "val2"); 822 g_assert_null(properties.get()[1]); 801 823 802 824 value = adoptGRef(jsc_context_evaluate(context.get(), "'use strict'; f.val2 = 45;", -1)); … … 812 834 g_assert_true(jsc_value_to_boolean(value.get()) == TRUE); 813 835 836 g_assert_false(jsc_value_object_delete_property(object.get(), "val2")); 837 g_assert_true(jsc_value_object_has_property(object.get(), "val2")); 838 814 839 property = adoptGRef(jsc_value_new_number(context.get(), 125)); 815 840 checker.watch(property.get()); 841 g_assert_false(jsc_value_object_has_property(object.get(), "val3")); 816 842 jsc_value_object_define_property_data(object.get(), "val3", static_cast<JSCValuePropertyFlags>(JSC_VALUE_PROPERTY_CONFIGURABLE | JSC_VALUE_PROPERTY_WRITABLE), property.get()); 843 g_assert_true(jsc_value_object_has_property(object.get(), "val3")); 817 844 value = adoptGRef(jsc_context_evaluate(context.get(), "f.val3;", -1)); 818 845 checker.watch(value.get()); 819 846 g_assert_true(jsc_value_is_number(value.get())); 820 847 g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 125); 848 849 properties.reset(jsc_value_object_enumerate_properties(object.get())); 850 g_assert_cmpuint(g_strv_length(properties.get()), ==, 1); 851 g_assert_cmpstr(properties.get()[0], ==, "val2"); 852 g_assert_null(properties.get()[1]); 821 853 822 854 property = adoptGRef(jsc_value_new_number(context.get(), 150)); 823 855 checker.watch(property.get()); 824 856 jsc_value_object_define_property_data(object.get(), "val3", static_cast<JSCValuePropertyFlags>(JSC_VALUE_PROPERTY_CONFIGURABLE), property.get()); 857 g_assert_true(jsc_value_object_has_property(object.get(), "val3")); 825 858 value = adoptGRef(jsc_context_evaluate(context.get(), "f.val3;", -1)); 826 859 checker.watch(value.get()); … … 828 861 g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 150); 829 862 863 properties.reset(jsc_value_object_enumerate_properties(object.get())); 864 g_assert_cmpuint(g_strv_length(properties.get()), ==, 1); 865 g_assert_cmpstr(properties.get()[0], ==, "val2"); 866 g_assert_null(properties.get()[1]); 867 830 868 value = adoptGRef(jsc_context_evaluate(context.get(), "delete f.val3;", -1)); 831 869 checker.watch(value.get()); 870 g_assert_false(jsc_value_object_has_property(object.get(), "val3")); 832 871 value = adoptGRef(jsc_context_evaluate(context.get(), "f.val3;", -1)); 833 872 checker.watch(value.get()); 834 873 g_assert_true(jsc_value_is_undefined(value.get())); 874 875 property = adoptGRef(jsc_value_new_number(context.get(), 250)); 876 checker.watch(property.get()); 877 g_assert_false(jsc_value_object_has_property(object.get(), "val4")); 878 jsc_value_object_define_property_data(object.get(), "val4", static_cast<JSCValuePropertyFlags>(JSC_VALUE_PROPERTY_CONFIGURABLE | JSC_VALUE_PROPERTY_ENUMERABLE), property.get()); 879 g_assert_true(jsc_value_object_has_property(object.get(), "val4")); 880 value = adoptGRef(jsc_context_evaluate(context.get(), "f.val4;", -1)); 881 checker.watch(value.get()); 882 g_assert_true(jsc_value_is_number(value.get())); 883 g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 250); 884 885 properties.reset(jsc_value_object_enumerate_properties(object.get())); 886 g_assert_cmpuint(g_strv_length(properties.get()), ==, 2); 887 g_assert_cmpstr(properties.get()[0], ==, "val2"); 888 g_assert_cmpstr(properties.get()[1], ==, "val4"); 889 g_assert_null(properties.get()[2]); 890 891 g_assert_true(jsc_value_object_delete_property(object.get(), "val4")); 892 g_assert_false(jsc_value_object_has_property(object.get(), "val4")); 893 894 properties.reset(jsc_value_object_enumerate_properties(object.get())); 895 g_assert_cmpuint(g_strv_length(properties.get()), ==, 1); 896 g_assert_cmpstr(properties.get()[0], ==, "val2"); 897 g_assert_null(properties.get()[1]); 835 898 836 899 GRefPtr<JSCValue> function = adoptGRef(jsc_value_new_function(context.get(), "foo", G_CALLBACK(foo), nullptr, nullptr, G_TYPE_INT, 1, G_TYPE_INT)); 837 900 checker.watch(function.get()); 838 901 902 g_assert_false(jsc_value_object_has_property(object.get(), "foo")); 839 903 jsc_value_object_define_property_data(object.get(), "foo", static_cast<JSCValuePropertyFlags>(0), function.get()); 904 g_assert_true(jsc_value_object_has_property(object.get(), "foo")); 905 906 properties.reset(jsc_value_object_enumerate_properties(object.get())); 907 g_assert_cmpuint(g_strv_length(properties.get()), ==, 1); 908 g_assert_cmpstr(properties.get()[0], ==, "val2"); 909 g_assert_null(properties.get()[1]); 840 910 841 911 GRefPtr<JSCValue> result = adoptGRef(jsc_value_object_invoke_method(object.get(), "foo", G_TYPE_INT, 200, G_TYPE_NONE)); … … 997 1067 g_assert_true(jsc_value_to_boolean(result.get())); 998 1068 1069 GUniquePtr<char*> properties(jsc_value_object_enumerate_properties(foo.get())); 1070 g_assert_null(properties.get()); 1071 1072 g_assert_false(jsc_value_object_has_property(foo.get(), "getFoo")); 999 1073 jsc_class_add_method(jscClass, "getFoo", G_CALLBACK(getFoo), nullptr, nullptr, G_TYPE_INT, 0, G_TYPE_NONE); 1074 g_assert_true(jsc_value_object_has_property(foo.get(), "getFoo")); 1075 properties.reset(jsc_value_object_enumerate_properties(foo.get())); 1076 g_assert_null(properties.get()); 1000 1077 GRefPtr<JSCValue> value = adoptGRef(jsc_value_object_invoke_method(foo.get(), "getFoo", G_TYPE_NONE)); 1001 1078 checker.watch(value.get()); … … 1007 1084 g_assert_true(value.get() == value2.get()); 1008 1085 1086 g_assert_false(jsc_value_object_has_property(foo.get(), "setFoo")); 1009 1087 jsc_class_add_method(jscClass, "setFoo", G_CALLBACK(setFoo), nullptr, nullptr, G_TYPE_NONE, 1, G_TYPE_INT); 1088 g_assert_true(jsc_value_object_has_property(foo.get(), "setFoo")); 1089 properties.reset(jsc_value_object_enumerate_properties(foo.get())); 1090 g_assert_null(properties.get()); 1010 1091 result = adoptGRef(jsc_value_object_invoke_method(foo.get(), "setFoo", G_TYPE_INT, 25, G_TYPE_NONE)); 1011 1092 checker.watch(result.get()); … … 1041 1122 g_assert_true(jsc_value_to_boolean(result.get())); 1042 1123 1124 g_assert_false(jsc_value_object_has_property(foo.get(), "foo")); 1125 g_assert_false(jsc_value_object_has_property(foo2.get(), "foo")); 1043 1126 jsc_class_add_property(jscClass, "foo", G_TYPE_INT, G_CALLBACK(getFoo), G_CALLBACK(setFoo), nullptr, nullptr); 1127 g_assert_true(jsc_value_object_has_property(foo.get(), "foo")); 1128 g_assert_true(jsc_value_object_has_property(foo2.get(), "foo")); 1129 properties.reset(jsc_value_object_enumerate_properties(foo.get())); 1130 g_assert_null(properties.get()); 1044 1131 value = adoptGRef(jsc_context_evaluate(context.get(), "f2.foo", -1)); 1045 1132 checker.watch(value.get()); … … 1093 1180 checker.watch(f1.get()); 1094 1181 g_assert_true(jsc_value_is_object(f1.get())); 1182 g_assert_true(jsc_value_object_has_property(f1.get(), "sibling")); 1183 GUniquePtr<char*> properties(jsc_value_object_enumerate_properties(f1.get())); 1184 g_assert_null(properties.get()); 1095 1185 GRefPtr<JSCValue> f2 = adoptGRef(jsc_context_get_value(context.get(), "f2")); 1096 1186 checker.watch(f2.get()); 1097 1187 g_assert_true(jsc_value_is_object(f2.get())); 1188 g_assert_true(jsc_value_object_has_property(f2.get(), "sibling")); 1189 properties.reset(jsc_value_object_enumerate_properties(f2.get())); 1190 g_assert_null(properties.get()); 1098 1191 1099 1192 GRefPtr<JSCValue> value = adoptGRef(jsc_context_evaluate(context.get(), "f2.sibling", -1)); … … 1127 1220 g_assert_true(jsc_value_is_object(foo.get())); 1128 1221 g_assert_true(jsc_value_object_is_instance_of(foo.get(), jsc_class_get_name(jscClass))); 1222 g_assert_true(jsc_value_object_has_property(foo.get(), "foo")); 1223 GUniquePtr<char*> properties(jsc_value_object_enumerate_properties(foo.get())); 1224 g_assert_null(properties.get()); 1129 1225 1130 1226 jsc_context_set_value(context.get(), "f", foo.get()); … … 1160 1256 g_assert_false(jsc_value_object_is_instance_of(baz.get(), jsc_class_get_name(jscClass))); 1161 1257 g_assert_false(jsc_value_object_is_instance_of(foo.get(), jsc_class_get_name(bazClass))); 1258 g_assert_false(jsc_value_object_has_property(baz.get(), "foo")); 1162 1259 1163 1260 jsc_context_set_value(context.get(), "bz", baz.get()); … … 1203 1300 g_assert_true(jsc_value_is_object(foo.get())); 1204 1301 g_assert_true(jsc_value_object_is_instance_of(foo.get(), jsc_class_get_name(jscClass))); 1302 g_assert_true(jsc_value_object_has_property(foo.get(), "foo")); 1303 GUniquePtr<char*> properties(jsc_value_object_enumerate_properties(foo.get())); 1304 g_assert_null(properties.get()); 1205 1305 1206 1306 jsc_context_set_value(context.get(), "f1", foo.get()); … … 1213 1313 GRefPtr<JSCValue> property = adoptGRef(jsc_value_new_number(context.get(), 50)); 1214 1314 checker.watch(property.get()); 1315 g_assert_false(jsc_value_object_has_property(foo.get(), "n")); 1215 1316 jsc_value_object_set_property(foo.get(), "n", property.get()); 1317 g_assert_true(jsc_value_object_has_property(foo.get(), "n")); 1216 1318 result = adoptGRef(jsc_context_evaluate(context.get(), "f1.n", -1)); 1217 1319 checker.watch(result.get()); … … 1239 1341 g_assert_true(jsc_value_is_object(foo.get())); 1240 1342 g_assert_true(jsc_value_object_is_instance_of(foo.get(), jsc_class_get_name(jscClass))); 1343 g_assert_true(jsc_value_object_has_property(foo.get(), "foo")); 1344 GUniquePtr<char*> properties(jsc_value_object_enumerate_properties(foo.get())); 1345 g_assert_null(properties.get()); 1241 1346 1242 1347 GRefPtr<JSCValue> value = adoptGRef(jsc_value_new_number(context.get(), 125)); … … 1309 1414 g_assert_true(jsc_value_is_object(foo.get())); 1310 1415 g_assert_true(jsc_value_object_is_instance_of(foo.get(), "wk.Foo")); 1416 g_assert_true(jsc_value_object_has_property(foo.get(), "foo")); 1417 GUniquePtr<char*> properties(jsc_value_object_enumerate_properties(foo.get())); 1418 g_assert_null(properties.get()); 1311 1419 GRefPtr<JSCValue> result = adoptGRef(jsc_context_evaluate(context.get(), "f instanceof wk.Foo;", -1)); 1312 1420 checker.watch(result.get()); … … 1447 1555 g_assert_true(jsc_value_is_boolean(result.get())); 1448 1556 g_assert_false(jsc_value_to_boolean(result.get())); 1557 g_assert_true(jsc_value_object_has_property(foo.get(), "foo")); 1558 g_assert_false(jsc_value_object_has_property(foo.get(), "bar")); 1559 GUniquePtr<char*> properties(jsc_value_object_enumerate_properties(foo.get())); 1560 g_assert_null(properties.get()); 1449 1561 1450 1562 GRefPtr<JSCValue> bar = adoptGRef(jsc_context_get_value(context.get(), "b")); … … 1462 1574 g_assert_true(jsc_value_is_boolean(result.get())); 1463 1575 g_assert_true(jsc_value_to_boolean(result.get())); 1576 g_assert_true(jsc_value_object_has_property(bar.get(), "bar")); 1577 g_assert_true(jsc_value_object_has_property(bar.get(), "foo")); 1578 properties.reset(jsc_value_object_enumerate_properties(bar.get())); 1579 g_assert_null(properties.get()); 1464 1580 1465 1581 result = adoptGRef(jsc_context_evaluate(context.get(), "b.bar = 25; b.foo = 42;", -1));
Note: See TracChangeset
for help on using the changeset viewer.