Author |
Message |
An6rey
Участник форума
Joined: 30 Aug 2007
Posts: 69
Карма: 3 поощрить/наказать
|
Posted: Fri Oct 05, 2007 8:32 pm (написано за 6 минут 14 секунд)
Post subject:
|
|
AKS wrote: |
An6rey wrote: |
KES привел исчерпывающие ссылки... | Лично я так и не понял, что и к чему цитировалось. | Кратко восстановлю ход дискуссии. XMLHttpRequest имеет возможность асинхронного выполнения. Иногда это выглядит так, что и JavaScript может выполнять скрипты параллельно. IE имеет в этом смысле свои особенности. KES привел ссылки из которых следует, что скрипт приостанавливается (SUSPEND) на время выполнения интерактивных операций (alert и т.п.) - но не выполняется параллельно в разных потоках. Проблема IE в том, что скрипты из очереди выбираются не в порядке FIFO
|
|
Back to top |
|
 |
AKS
Участник форума
Joined: 28 Dec 2005
Posts: 1174
Карма: 102 поощрить/наказать
|
Posted: Fri Oct 05, 2007 8:45 pm (спустя 12 минут; написано за 3 минуты 34 секунды)
Post subject:
|
|
An6rey, давайте и я тоже по-порядку: 1. Возможности XMLHttpRequest к j(ava)script отношения не имеют, так ведь? 2. Как это выглядит, и кому что кажется - это тоже не наша проблема, так? 3. Каждый браузер имеет свои особенности, не только IE. 4. Ссылки кое-где не в попад, хотя уже, казалось, давно надо было уяснить, что j(ava)script действительно "не выполняется параллельно в разных потоках". 5. Тут я ничего не могу сказать - это проблема IE, или еще чья-либо.
|
|
Back to top |
|
 |
Г.О.
Участник форума
Joined: 22 Feb 2006
Posts: 378
Карма: 13 поощрить/наказать
Location: Ленинград
|
Posted: Fri Oct 05, 2007 8:46 pm (спустя 1 минуту 49 секунд)
Post subject:
|
|
An6rey, хотите сказать, что у вас выдается req10000000? У меня останавливается на меньшем числе. Ладно, уберем алерты: Code (JavaScript): | скопировать код в буфер обмена | var i = 0; var req = new ActiveXObject("Microsoft.XMLHTTP"); req.onreadystatechange = (function() {if (req.readyState == 4) {str += i + " ";d = 0;}}); req.open("GET", "test1.html", true); req.send(null);
var d = 1; var str = ""; while (d && i<10000000) { i++; if (i % 100000 == 0) { str += i + " "; } } alert(str); | У меня заканчивается на req2xxxxx (IE6). А как у вас?
|
|
Back to top |
|
 |
AKS
Участник форума
Joined: 28 Dec 2005
Posts: 1174
Карма: 102 поощрить/наказать
|
Posted: Fri Oct 05, 2007 8:54 pm (спустя 7 минут; написано за 21 секунду)
Post subject:
|
|
Г.О., а как у Вас в str попадает 'req'?
|
|
Back to top |
|
 |
Г.О.
Участник форума
Joined: 22 Feb 2006
Posts: 378
Карма: 13 поощрить/наказать
Location: Ленинград
|
Posted: Fri Oct 05, 2007 8:56 pm (спустя 2 минуты)
Post subject:
|
|
AKS, несомненно, параллельно не выполняется. Например, если внутри onreadstatechange так же пустить цикл с добавлением значений к строке, никакой параллельности не обнаружится. Однако, обнаружится, что выполняющийся в единственном потоке код прерывает выполнение и вместо него в том же потоке начинает выполняться обработчик, после чего управление возвращается назад.
|
|
Back to top |
|
 |
Г.О.
Участник форума
Joined: 22 Feb 2006
Posts: 378
Карма: 13 поощрить/наказать
Location: Ленинград
|
Posted: Fri Oct 05, 2007 8:58 pm (спустя 1 минуту 59 секунд; написано за 33 секунды)
Post subject:
|
|
Еще подправим: :) Code (JavaScript): | скопировать код в буфер обмена | var i = 0; var req = new ActiveXObject("Microsoft.XMLHTTP"); req.onreadystatechange = ( function() { if (req.readyState == 4) { str += "req" + i + " "; for (var j = 0; j < 100000; j++) { if (j % 10000 == 0) { str += "req" + j + " "; } } } } ); req.open("GET", "test1.html", true); req.send(null);
var d = 1; var str = ""; while (d && i<5000000) { i++; if (i % 100000 == 0) { str += i + " "; } } document.write(str); | Результат: Code (any language): | скопировать код в буфер обмена | 100000 200000 300000 400000 500000 600000 700000 800000 900000 1000000 1100000 1200000 1300000 1400000 1500000 1600000 1700000 1800000 1900000 2000000 req2024928 req0 req10000 req20000 req30000 req40000 req50000 req60000 req70000 req80000 req90000 2100000 2200000 2300000 2400000 2500000 2600000 2700000 2800000 2900000 3000000 3100000 3200000 3300000 3400000 3500000 3600000 3700000 3800000 3900000 4000000 4100000 4200000 4300000 4400000 4500000 4600000 4700000 4800000 4900000 5000000 |
|
|
Back to top |
|
 |
AKS
Участник форума
Joined: 28 Dec 2005
Posts: 1174
Карма: 102 поощрить/наказать
|
Posted: Fri Oct 05, 2007 9:04 pm (спустя 6 минут; написано за 32 секунды)
Post subject:
|
|
Г.О. wrote: |
Однако, обнаружится, что выполняющийся в единственном потоке код прерывает выполнение и вместо него в том же потоке начинает выполняться обработчик, после чего управление возвращается назад. | А когда такое случается? После "вылета" какого-нибудь окна предупреждения?
|
|
Back to top |
|
 |
Г.О.
Участник форума
Joined: 22 Feb 2006
Posts: 378
Карма: 13 поощрить/наказать
Location: Ленинград
|
Posted: Fri Oct 05, 2007 9:22 pm (спустя 17 минут; написано за 23 секунды)
Post subject:
|
|
Да, типа "скрипт всё тормозит". Намекаете, что из-за него?
|
|
Back to top |
|
 |
AKS
Участник форума
Joined: 28 Dec 2005
Posts: 1174
Карма: 102 поощрить/наказать
|
Posted: Fri Oct 05, 2007 9:32 pm (спустя 9 минут; написано за 49 секунд)
Post subject:
|
|
Ну да. Процесс прерывается. Затем последний, вставший в очередь, выполняется. И т.д.
|
|
Back to top |
|
 |
AKS
Участник форума
Joined: 28 Dec 2005
Posts: 1174
Карма: 102 поощрить/наказать
|
Posted: Fri Oct 05, 2007 9:34 pm (спустя 2 минуты; написано за 23 секунды)
Post subject:
|
|
Вот, взгляните, как это в IE устроено: Code (JavaScript): | скопировать код в буфер обмена | window.setInterval(function () { window.status += 'a'; }, 1000); window.setInterval(function () { window.status += 'b'; }, 1000); |
|
|
Back to top |
|
 |
An6rey
Участник форума
Joined: 30 Aug 2007
Posts: 69
Карма: 3 поощрить/наказать
|
Posted: Fri Oct 05, 2007 9:49 pm (спустя 14 минут; написано за 5 минут)
Post subject:
|
|
Г.О. wrote: |
An6rey, хотите сказать, что у вас выдается req10000000? У меня останавливается на меньшем числе. | Если загружать через - HTTP-сервер - заканчивается с большим числом. Если из файловой системы - с меньшим числом если загружаемый файл маленький (простите за вольность) Если файл достаточно большой (зависит от мощности компьютера) - скрипт тормозит - а затем вывод с меньшим числом. Возможное объяснение - если запрос к файловой системе - обработчик вызывается немедленно (синхронно)
|
|
Back to top |
|
 |
An6rey
Участник форума
Joined: 30 Aug 2007
Posts: 69
Карма: 3 поощрить/наказать
|
Posted: Fri Oct 05, 2007 10:05 pm (спустя 16 минут; написано за 8 минут 23 секунды)
Post subject:
|
|
AKS wrote: |
2. Как это выглядит, и кому что кажется - это тоже не наша проблема, так? | Заблуждение касающееся параллельности выполнения onreadyststechange-функций настолько широко распространено, что одна из популярных реализаций пула объектов XMLHttpRequest входит в бесконечный цикл, ожидая освобождения объекта, который в свою очередь ожидает окончания бесконечного цикла - как бы это можно было сделать при многопоточном программировании.
|
|
Back to top |
|
 |
AKS
Участник форума
Joined: 28 Dec 2005
Posts: 1174
Карма: 102 поощрить/наказать
|
Posted: Sat Oct 06, 2007 8:53 am (спустя 10 часов 47 минут; написано за 5 минут 58 секунд)
Post subject:
|
|
An6rey wrote: |
Заблуждение касающееся параллельности выполнения onreadyststechange-функций настолько широко распространено... | Я побеседовать-то хотел совсем о другом. А именно - "доктор" KES огласил диагноз для IE: "В морг!", цитируя то, что к IE не относится. Нашлись согласные с таким приговором. Я интересуюсь и пытаюсь разузнать, что и как - ни ответа, ни привета. Он же заявил, что сценарий Andrea Giammarchi использовать нежелательно, и это как-то связано с single threading. Я прошу продемонстрировать на примере, чтобы разглядеть ошибку в том сценарии, а мне в ответ: "Зачем примеры - я его вижу насквозь и еще два метра в землю"...
|
|
Back to top |
|
 |
Г.О.
Участник форума
Joined: 22 Feb 2006
Posts: 378
Карма: 13 поощрить/наказать
Location: Ленинград
|
Posted: Sat Oct 06, 2007 9:36 am (спустя 43 минуты; написано за 14 секунд)
Post subject:
|
|
AKS wrote: |
Ну да. Процесс прерывается. Затем последний, вставший в очередь, выполняется. И т.д. | Как всё запутано... На AKSа не проведешь :)
|
|
Back to top |
|
 |
Г.О.
Участник форума
Joined: 22 Feb 2006
Posts: 378
Карма: 13 поощрить/наказать
Location: Ленинград
|
Posted: Sat Oct 06, 2007 9:39 am (спустя 2 минуты; написано за 23 секунды)
Post subject:
|
|
An6rey wrote: |
Если из файловой системы - с меньшим числом если загружаемый файл маленький (простите за вольность) | Из файловой системы это как? Ajax может тырить данные с компьютера пользователя?
|
|
Back to top |
|
 |
AKS
Участник форума
Joined: 28 Dec 2005
Posts: 1174
Карма: 102 поощрить/наказать
|
Posted: Sat Oct 06, 2007 10:48 am (спустя 1 час 9 минут; написано за 4 минуты 52 секунды)
Post subject:
|
|
Г.О. wrote: |
Как всё запутано... | Да как-будто бы не очень. IE стабилен. А вот тест для FF (точнее для них обоих, для сравнения) покажет, что в FF не все "гладко": Code (JavaScript): | скопировать код в буфер обмена | var start = +new Date; //
var counter = 0; //
var suspend = 3000; //
var interval = 1000; //
start += suspend; //
function Test() { var diff = new Date - start; // // window.status = counter++ + ': ' + diff; };
window.setInterval(Test, interval); //
while (new Date - start < 0); // | В IE количество вызовов функции Test (если эту цифру умножить на время интервала) будет совпадать с временем от начала первого выполнения функции (за исключением небольших погрешностей). А вот в FF все иначе, и особенно забавными выглядят данные, выводимые в панель состояния на первых двух-трех секундах.
Last edited by AKS on Sat Oct 06, 2007 11:02 am; edited 1 time in total
|
|
Back to top |
|
 |
An6rey
Участник форума
Joined: 30 Aug 2007
Posts: 69
Карма: 3 поощрить/наказать
|
Posted: Sat Oct 06, 2007 11:02 am (спустя 14 минут; написано за 6 минут 48 секунд)
Post subject:
|
|
Г.О. wrote: |
An6rey wrote: |
Если из файловой системы - с меньшим числом если загружаемый файл маленький (простите за вольность) | Из файловой системы это как? Ajax может тырить данные с компьютера пользователя? | Если Вы основной файл загрузили не через http:// запрос а как file:// МЕНЮ-ФАЙЛ-ОТКРЫТЬ... из локальной файловой системы - Ваш Ajax запрос может использовать относительный адрес и загрузить файл из локальной файловой системы. Если Вы открываете основной файл через http:// и пытаетесь открыть file:// - разумеется сработает защита. Вывод Ajax не может тырить данные с компьютера если нет взломов, вирусов итп
|
|
Back to top |
|
 |
An6rey
Участник форума
Joined: 30 Aug 2007
Posts: 69
Карма: 3 поощрить/наказать
|
Posted: Sat Oct 06, 2007 12:24 pm (спустя 1 час 21 минуту; написано за 11 минут 13 секунд)
Post subject:
|
|
AKS wrote: |
В IE количество вызовов функции Test (если эту цифру умножить на время интервала) будет совпадать с временем от начала первого выполнения функции (за исключением небольших погрешностей). А вот в FF все иначе, и особенно забавными выглядят данные, выводимые в панель состояния на первых двух-трех секундах. | Мой Mozilla/5.0 Gecko/20061204 Firefox/2.0.0.1 не работает с window.status, но я понял о чем Вы хотите сказать. Вы вызвали setInterval(1 секунда) и "подвесили" скрипт на 3 секунды. IE начинает отсчет вызовов с момента окончания основного скрипта и через 4 секунды после вызова setInterval вызовет функцию 1 раз. FF начинает отсчет с момента вызова setInterval и выстраивает вызовы функций в очередь. Таким образом за 4 секунды функция будет вызвана 4 раза из них - все четыре за последнюю секунду. У кого проблемы?
|
|
Back to top |
|
 |
AKS
Участник форума
Joined: 28 Dec 2005
Posts: 1174
Карма: 102 поощрить/наказать
|
Posted: Sat Oct 06, 2007 3:38 pm (спустя 3 часа 14 минут; написано за 6 минут 9 секунд)
Post subject:
|
|
An6rey wrote: |
Мой Mozilla/5.0 Gecko/20061204 Firefox/2.0.0.1 не работает с window.status | А так: View -> Status Bar An6rey wrote: |
через 4 секунды после вызова setInterval вызовет функцию 1 раз. | Не через 4 секунды! Функция должна быть выполнена через 1 секунду, но будет выполнена тогда, когда движок освободится. А освободится он через 3 секунды. An6rey wrote: |
FF начинает отсчет с момента вызова setInterval и выстраивает вызовы функций в очередь. | FF начинает отсчет тогда же, когда и IE - после того, как освобождается движок. Но в первые же мгновения ее движок пытается выполнить то, что было задержано. Поэтому я и отметил: "особенно забавными выглядят данные, выводимые в панель состояния на первых двух-трех секундах". Если изменить вывод вот так, то будет виднее: An6rey wrote: |
У кого проблемы? | А я не знаю. Не мне выносить вердикт. Мое дело - узнать как можно больше об особенностях и учиться пользоваться хорошими, обходя при этом плохие.
|
|
Back to top |
|
 |
An6rey
Участник форума
Joined: 30 Aug 2007
Posts: 69
Карма: 3 поощрить/наказать
|
Posted: Sat Oct 06, 2007 4:20 pm (спустя 41 минуту; написано за 10 минут 25 секунд)
Post subject:
|
|
AKS wrote: |
An6rey wrote: |
У кого проблемы? | А я не знаю. Не мне выносить вердикт. Мое дело - узнать как можно больше об особенностях и учиться пользоваться хорошими, обходя при этом плохие. | Я отже не знаю какой вариант setInterval более "правильный". Я не собирался очернять IE, но и поведение FF не вызывает у меня улыбку. На самом деле серьезный вопрос заключается в том необходимо ли разрабатывать приложения кроссбраузерно. Или пользоваться все расширяющимися возможностями IE. На этот вопрос тоже нет однозначного ответа.
|
|
Back to top |
|
 |
KES
Участник форума

Joined: 19 Oct 2006
Posts: 214
Карма: 0 поощрить/наказать
Location: сВознесеновка, Мелитопольский р-н, Запорожская обл. Украина
|
Posted: Thu Nov 29, 2007 10:55 pm (спустя 1 месяц 23 дня 6 часов 34 минуты; написано за 16 минут 7 секунд)
Post subject:
|
|
Как тут уже было показано ход выполнения программы может быть нарушен (а) Явно вызывая alert (б) или неявно исключением KES wrote: |
Если Вы не видите ничего опасного в этом коде с сайта webreflection.blogspot.com/2007/07/625-bytes-to-extend-javascript.htmlТо это не значит, что код безопасный! | Еще раз на пальцах: Есть функция и она использует глобальную переменную. процесс 1 вызывает функцию ааа, которая пишет в глобальную переменную значение 111 процесс 1 останавливается на время, процесс 2 начинает выполнятся процесс 2 вызывает туже функцию ааа, которая пишет в глобальную переменную значение 222 процесс 2 завершает работу, процесс 1 продолжает выполнение процесс 1 читает глобальную переменную УПС!!! а там значение 222 вместо 111 Какое же это отношение имеет к коду с сайта webreflection.blogspot.com/2007/07/625-bytes-to-extend-javascript.html
Вот какое. Функция по отношению к объектам является глобальной. Так например в JavaScipt никто не запрещает создать функции член:вот если два объекта "b", "c" будут оба производными от типа "a", то они оба разделять "глобальную" переменную-член member b.fn.member === c.fn.member Andrea Giammarchi как раз то и делает, что сохраняет информацию о том, в каком классе мы есть в виде "глобальных" данных и вот например, мы находимся в inherit функции, которая была прервана alert"том и в этот момент пришли данные с сервера и не дай Бог, чтобы была вызвана таже функция, которая сейчас приостановлена alert"ом. Даже не хочу представить мучения того человека, который попытается отдебажить этот случай По поводу яркой критики IE сорри конечно, но в продуктах от МикроСофт боков встречается больше, чем в OpenSource (исходя из этого поведение OpenSource хочется принимать за более верное), да и на том же MSDNе в хелпе может быть написано одно, а на практике продукт ведет себя по другому. Отсюда и неприязнь. Поэтому если стоит выбор MicroSoft || OpenSource советую в большинстве случаев делать выбор в пользу OpenSource
|
|
Back to top |
|
 |
Александр Михалицын
Модератор
Joined: 23 May 2008
Posts: 1299
Карма: 83 поощрить/наказать
|
Posted: Tue Aug 19, 2008 6:05 pm (спустя 8 месяцев 19 дней 19 часов 10 минут; написано за 37 секунд)
Post subject:
|
|
Дмитрий Котеров, а на сколько актуален данный материал сейчас? Ведь статья все таки 2004 года...
|
|
Back to top |
|
 |
Guest
Карма: 388 поощрить/наказать
|
Posted: Fri Aug 22, 2008 11:20 am (спустя 2 дня 17 часов 15 минут; написано за 10 секунд)
Post subject:
|
|
Материал актуален.
|
|
Back to top |
|
 |
Михаил Стадник
Guest
Карма: 388 поощрить/наказать
|
Posted: Sat Aug 23, 2008 7:10 am (спустя 19 часов 49 минут; написано за 10 минут 59 секунд)
Post subject: Импрувментс :)
|
|
Предлагаю свой вариант ООП: Oop.js Code (JavaScript): | скопировать код в буфер обмена | Class = function( parent, declaration, autocall) { var constructor = 'constructor'; var autocall = autocall === false ? false : true; // var class = function() { // var run_child = declaration && declaration[constructor] && declaration[constructor] != Object; var run_parent = (!run_child && parent) || autocall && parent; if (run_parent) { if (parent.prototype[constructor] && parent.prototype[constructor] != Object) { this.constructor.prototype.constructor = parent.prototype[constructor]; } else { this.constructor.prototype.constructor = parent; } this.constructor.prototype.constructor.apply( this, arguments); } if (run_child) { this.constructor = declaration[constructor]; this.constructor.apply( this, arguments); } }; if (parent) { for (var property in parent.prototype) { if (property != constructor) { class.prototype[property] = parent.prototype[property]; } } class.prototype.parent = parent.prototype.constructor.prototype; // } if (declaration) { for (var property in declaration) { if (property != constructor) { class.prototype[property] = declaration[property]; } } } return class; }; | Пример использования: Code (JavaScript): | скопировать код в буфер обмена | document.writeln( '<pre>');
function Car( type) { // создаем базовый класс стандартным методом исключительно в целях тестирования - наследование должно быть наследованием в любом случае, нетак ли? ;) this.type = type || 'truck'; }
var Sedan = new Ajax.Class( Car, { constructor : function( color) { this.color = color; this.type = 'sedan'; document.writeln( 'Called Car::constructor()'); }, drive : function( color) { this.color = color; document.writeln( 'Called Car::drive()'); document.writeln( this.color); } });
var Suzuki = new Ajax.Class( Sedan, { constructor : function( color) { this.parent.constructor.call( this, color); document.writeln( 'Called Suzuki::constructor()'); document.writeln( this.color); }, drive : function() { this.parent.drive( 'blue'); document.writeln( 'Called Suzuki::drive()'); } }, false);
var vehicle = new Suzuki( 'black'); vehicle.drive();
document.writeln( '</pre>'); | З.Ы. Тестировал в ФФ... Буду рад любым замечаниям.
|
|
Back to top |
|
 |
Михаил Стадник
Guest
Карма: 388 поощрить/наказать
|
Posted: Sat Aug 23, 2008 7:12 am (спустя 2 минуты; написано за 11 секунд)
Post subject:
|
|
Сорри пару ошибочек
|
|
Back to top |
|
 |
Михаил Стадник
Guest
Карма: 388 поощрить/наказать
|
Posted: Sat Aug 23, 2008 7:12 am (спустя 27 секунд; написано за 25 секунд)
Post subject:
|
|
Oop.sj:
|
|
Back to top |
|
 |
Михаил Стадник
Guest
Карма: 388 поощрить/наказать
|
Posted: Sat Aug 23, 2008 7:14 am (спустя 1 минуту 18 секунд; написано за 57 секунд)
Post subject:
|
|
Oop.js: 1. Class -> var Class Example: new Ajax.Class -> new Class
|
|
Back to top |
|
 |
Михаил Стадник
Guest
Карма: 388 поощрить/наказать
|
Posted: Fri Sep 05, 2008 6:02 pm (спустя 13 дней 10 часов 48 минут; написано за 37 секунд)
Post subject:
|
|
Все. Кажется получилось именно то что нужно. Предлагаю всем: ajaxoop.org/
|
|
Back to top |
|
 |
KES
Участник форума

Joined: 19 Oct 2006
Posts: 214
Карма: 0 поощрить/наказать
Location: сВознесеновка, Мелитопольский р-н, Запорожская обл. Украина
|
Posted: Tue Sep 09, 2008 12:05 pm (спустя 3 дня 18 часов 2 минуты; написано за 22 секунды)
Post subject:
|
|
Не получается скачать =( Not Found The requested URL /p/ajaxoop/downloads/detail?name=ajaxoop-1.0.4-source.js was not found on this server.
|
|
Back to top |
|
 |
Михаил Стадник
Guest
Карма: 388 поощрить/наказать
|
Posted: Tue Sep 09, 2008 4:46 pm (спустя 4 часа 41 минуту; написано за 28 секунд)
Post subject:
|
|
Прошу прощения - обновлял :) Попробуйте сейчас
|
|
Back to top |
|
 |
Михаил Стадник
Guest
Карма: 388 поощрить/наказать
|
Posted: Tue Sep 09, 2008 4:48 pm (спустя 1 минуту 39 секунд; написано за 53 секунды)
Post subject:
|
|
И еще - посты от 23 августа прошу засчитать недействительными - неправильно это все и криво. Окончательный вариант на приведенном сайте.
|
|
Back to top |
|
 |
KES
Участник форума

Joined: 19 Oct 2006
Posts: 214
Карма: 0 поощрить/наказать
Location: сВознесеновка, Мелитопольский р-н, Запорожская обл. Украина
|
Posted: Thu Oct 30, 2008 1:10 pm (спустя 1 месяц 20 дней 20 часов 21 минуту; написано за 4 минуты 16 секунд)
Post subject:
|
|
Всё началось с прошлого года с марта... Разобравшись с наследованием начал делать свою библиотеку Вот что получилось почти через полтора года: 1. Реализовано наследование классов 2. Легкое создание форм. 3. Наследование форм 4. Простое взаимодействие с базой данных 5. DELPHI like компоненты 6. MASTER-DETAIL зависимости для таблиц 7. Прозрачная обработка DOM и USER DEFINED событий 8. Подписка на события и ещё много много очень полезных, удобных и интересных фишек Посмотреть видео можно тут: kes.net.ua/d.koterov
По вопросам приобретения библиотеки с правом продажи компонентов обращайтесь: kes@kes.net.ua
|
|
Back to top |
|
 |
|