/[suikacvs]/messaging/manakai/lib/Message/DOM/Document.pm
Suika

Contents of /messaging/manakai/lib/Message/DOM/Document.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.23 - (hide annotations) (download)
Mon Oct 8 07:17:18 2007 UTC (17 years, 1 month ago) by wakaba
Branch: MAIN
Changes since 1.22: +4 -2 lines
++ manakai/lib/Message/DOM/ChangeLog	8 Oct 2007 07:16:56 -0000
2007-10-08  Wakaba  <wakaba@suika.fam.cx>

	* Event.pm, EventTarget.pm, EventTargetNode.pm,
	EventException.pm: Implemented (but not tested!).

	* DOMException.pm (MALFORMED_EVENT_TYPE_ERR,
	EVENT_INTERFACE_NOT_SUPPORTED_ERR, EXTERNAL_EVENT_ERR): New
	error subtypes.

	* DOMImplementation.pm ($HasFeature): The |Event| feature,
	version |3.0|, is added.

	* Document.pm, Node.pm: Event attributes and
	methods are implemented.

1 wakaba 1.21 ## NOTE: This module will be renamed as Document.pm.
2 wakaba 1.1
3 wakaba 1.21 package Message::DOM::Document;
4     use strict;
5 wakaba 1.23 our $VERSION=do{my @r=(q$Revision: 1.22 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
6 wakaba 1.21 push our @ISA, 'Message::DOM::Node', 'Message::IF::Document',
7     'Message::IF::DocumentTraversal', 'Message::IF::DocumentXDoctype',
8 wakaba 1.22 'Message::IF::DocumentSelector', # MUST in Selectors API spec
9 wakaba 1.21 'Message::IF::HTMLDocument';
10     require Message::DOM::Node;
11     use Char::Class::XML
12     qw/
13     InXML_NameStartChar10 InXMLNameStartChar11
14     InXMLNameChar10 InXMLNameChar11
15     InXML_NCNameStartChar10 InXMLNCNameStartChar11
16     InXMLNCNameChar10 InXMLNCNameChar11
17     /;
18    
19     sub ____new ($$) {
20     my $self = shift->SUPER::____new (undef);
21     $$self->{implementation} = $_[0];
22     $$self->{strict_error_checking} = 1;
23     $$self->{child_nodes} = [];
24     $$self->{'http://suika.fam.cx/www/2006/dom-config/strict-document-children'} = 1;
25     $$self->{'http://suika.fam.cx/www/2006/dom-config/dtd-default-attribute'} = 1;
26     $$self->{'http://suika.fam.cx/www/2006/dom-config/clone-entity-reference-subtree'} = 1;
27     $$self->{'error-handler'} = sub ($) {
28     ## NOTE: Same as one set by |setParameter| with |undef| value.
29     warn $_[0];
30     return $_[0]->severity != 3; # SEVERITY_FATAL_ERROR
31     };
32     return $self;
33     } # ____new
34    
35     sub AUTOLOAD {
36     my $method_name = our $AUTOLOAD;
37     $method_name =~ s/.*:://;
38     return if $method_name eq 'DESTROY';
39 wakaba 1.1
40     if ({
41 wakaba 1.21 ## Read-only attributes (trivial accessors)
42     implementation => 1,
43     }->{$method_name}) {
44     no strict 'refs';
45     eval qq{
46     sub $method_name (\$) {
47     return \${\$_[0]}->{$method_name};
48 wakaba 1.1 }
49 wakaba 1.21 };
50     goto &{ $AUTOLOAD };
51     } elsif ({
52     ## Read-write attributes (DOMString, trivial accessors)
53     document_uri => 1,
54     input_encoding => 1,
55     }->{$method_name}) {
56     no strict 'refs';
57     eval qq{
58     sub $method_name (\$;\$) {
59     if (\@_ > 1) {
60     if (\${\$_[0]}->{strict_error_checking} and
61     \${\$_[0]}->{manakai_read_only}) {
62     report Message::DOM::DOMException
63     -object => \$_[0],
64     -type => 'NO_MODIFICATION_ALLOWED_ERR',
65     -subtype => 'READ_ONLY_NODE_ERR';
66     }
67     if (defined \$_[1]) {
68     \${\$_[0]}->{$method_name} = ''.\$_[1];
69     } else {
70     delete \${\$_[0]}->{$method_name};
71     }
72     }
73     return \${\$_[0]}->{$method_name};
74 wakaba 1.1 }
75 wakaba 1.21 };
76     goto &{ $AUTOLOAD };
77     } elsif ({
78     ## Read-write attributes (boolean, trivial accessors)
79     all_declarations_processed => 1,
80     }->{$method_name}) {
81     no strict 'refs';
82     eval qq{
83     sub $method_name (\$;\$) {
84     if (\@_ > 1) {
85     if (\${\$_[0]}->{manakai_strict_error_checking} and
86     \${\$_[0]}->{manakai_read_only}) {
87     report Message::DOM::DOMException
88     -object => \$_[0],
89     -type => 'NO_MODIFICATION_ALLOWED_ERR',
90     -subtype => 'READ_ONLY_NODE_ERR';
91     }
92     if (\$_[1]) {
93     \${\$_[0]}->{$method_name} = 1;
94     } else {
95     delete \${\$_[0]}->{$method_name};
96 wakaba 1.1 }
97     }
98 wakaba 1.21 return \${\$_[0]}->{$method_name};
99     }
100     };
101     goto &{ $AUTOLOAD };
102     } elsif (my $module_name = {
103 wakaba 1.23 can_dispatch => 'Message::DOM::EventTargetNode',
104 wakaba 1.21 create_attribute => 'Message::DOM::Attr',
105     create_attribute_ns => 'Message::DOM::Attr',
106     create_attribute_definition => 'Message::DOM::AttributeDefinition',
107     create_cdata_section => 'Message::DOM::Text',
108     create_comment => 'Message::DOM::CharacterData',
109     create_document_fragment => 'Message::DOM::DocumentFragment',
110     create_document_type_definition => 'Message::DOM::DocumentType',
111     create_element => 'Message::DOM::Element',
112     create_element_ns => 'Message::DOM::Element',
113     create_element_type_definition => 'Message::DOM::ElementTypeDefinition',
114     create_entity_reference => 'Message::DOM::EntityReference',
115 wakaba 1.23 create_event => 'Message::DOM::EventTargetNode',
116 wakaba 1.21 create_general_entity => 'Message::DOM::Entity',
117     create_notation => 'Message::DOM::Notation',
118     create_processing_instruction => 'Message::DOM::ProcessingInstruction',
119     manakai_create_serial_walker => 'Message::DOM::SerialWalker',
120     create_text_node => 'Message::DOM::Text',
121     create_tree_walker => 'Message::DOM::TreeWalker',
122 wakaba 1.22 query_selector => 'Message::DOM::SelectorsAPI',
123     query_selector_all => 'Message::DOM::SelectorsAPI',
124 wakaba 1.21 }->{$method_name}) {
125     eval qq{ require $module_name } or die $@;
126     goto &{ $AUTOLOAD };
127     } else {
128     require Carp;
129     Carp::croak (qq<Can't locate method "$AUTOLOAD">);
130 wakaba 1.1 }
131 wakaba 1.21 } # AUTOLOAD
132     sub implementation ($);
133     sub create_attribute ($$);
134     sub create_attribute_ns ($$$);
135     sub create_attribute_definition ($$);
136     sub create_cdata_section ($$);
137     sub create_comment ($$);
138     sub create_document_fragment ($);
139     sub create_document_type_definition ($$);
140     sub create_element ($$);
141     sub create_element_ns ($$$);
142     sub create_element_type_definition ($$);
143     sub create_entity_reference ($$);
144     sub create_general_entity ($$);
145     sub create_notation ($$);
146     sub create_processing_instruction ($$$);
147     sub create_text_node ($$);
148    
149     ## |Node| attributes
150    
151     sub base_uri ($) {
152     my $v = ${$_[0]}->{manakai_entity_base_uri};
153     if (defined $v) {
154     return $v;
155     } else {
156     return ${$_[0]}->{document_uri};
157 wakaba 1.13 }
158 wakaba 1.21 ## TODO: HTML5 <base>
159     } # base_uri
160 wakaba 1.1
161 wakaba 1.21 sub node_name () { '#document' }
162 wakaba 1.1
163 wakaba 1.21 sub node_type () { 9 } # DOCUMENT_NODE
164 wakaba 1.1
165 wakaba 1.21 sub text_content ($;$) {
166     my $self = shift;
167     if ($$self->{'http://suika.fam.cx/www/2006/dom-config/strict-document-children'}) {
168     return undef;
169 wakaba 1.1 } else {
170 wakaba 1.21 local $Error::Depth = $Error::Depth + 1;
171     return $self->SUPER::text_content (@_);
172 wakaba 1.1 }
173 wakaba 1.21 } # text_content
174 wakaba 1.1
175 wakaba 1.21 ## |Node| methods
176 wakaba 1.1
177 wakaba 1.21 sub adopt_node ($$) {
178     my ($self, $source) = @_;
179     ## TODO: Should we apply |copy-asis| configuration parameter to this method?
180 wakaba 1.1
181 wakaba 1.21 return undef unless UNIVERSAL::isa ($source, 'Message::DOM::Node');
182 wakaba 1.1
183 wakaba 1.21 my $strict = $self->strict_error_checking;
184     if ($strict and $$self->{manakai_read_only}) {
185     report Message::DOM::DOMException
186     -object => $self,
187     -type => 'NO_MODIFICATION_ALLOWED_ERR',
188     -subtype => 'READ_ONLY_NODE_ERR';
189     }
190 wakaba 1.1
191 wakaba 1.21 my $parent = $source->parent_node;
192     if ($strict and defined $parent and $$parent->{manakai_read_only}) {
193     report Message::DOM::DOMException
194     -object => $self,
195     -type => 'NO_MODIFICATION_ALLOWED_ERR',
196     -subtype => 'READ_ONLY_NODE_ERR';
197     }
198 wakaba 1.1
199 wakaba 1.21 my $nt = $source->node_type;
200     my $oe;
201     if ($nt == 2) { # ATTRIBUTE_NODE
202     $oe = $source->owner_element;
203     if ($strict and defined $oe and $$oe->{manakai_read_only}) {
204     report Message::DOM::DOMException
205     -object => $self,
206     -type => 'NO_MODIFICATION_ALLOWED_ERR',
207     -subtype => 'READ_ONLY_NODE_ERR';
208     }
209     } elsif ($nt == 9 or $nt == 10 or $nt == 6 or $nt == 12 or
210     $nt == 81001 or $nt == 81002) {
211     # DOCUMENT_NODE, DOCUMENT_TYPE_NODE, ENTITY_NODE, NOTATION_NODE,
212     # ELEMENT_TYPE_DEFINITION_NODE, ATTRIBUTE_DEFINITION_NODE
213     report Message::DOM::DOMException
214     -object => $self,
215     -type => 'NOT_SUPPORTED_ERR',
216     -subtype => 'ADOPT_NODE_TYPE_NOT_SUPPORTED_ERR';
217     ## ISSUE: Define ELEMENT_TYPE_DEFINITION_NODE and ATTRIBUTE_DEFINITION_NODE
218     }
219 wakaba 1.1
220 wakaba 1.21 my @change_od;
221     my @nodes = ($source);
222     while (@nodes) {
223     my $node = shift @nodes;
224     my $nt = $node->node_type;
225     if ($strict and $$node->{manakai_read_only}) {
226     report Message::DOM::DOMException
227     -object => $self,
228     -type => 'NO_MODIFICATION_ALLOWED_ERR',
229     -subtype => 'READ_ONLY_NODE_ERR';
230 wakaba 1.1 }
231    
232 wakaba 1.21 push @change_od, $node;
233     push @nodes, @{$node->child_nodes}, @{$node->attributes or []};
234     } # @nodes
235 wakaba 1.1
236 wakaba 1.21 local $Error::Depth = $Error::Depth + 1;
237 wakaba 1.1
238 wakaba 1.21 if (defined $parent) {
239     $parent->remove_child ($source);
240     } elsif (defined $oe) {
241     $oe->remove_attribute_node ($source);
242     }
243 wakaba 1.1
244 wakaba 1.21 return $source if $self eq $change_od[0]->owner_document;
245     ## NOTE: The array must have more than zero
246     ## nodes by definition. In addition,
247     ## it cannot contain document or document
248     ## type nodes in current implementation.
249 wakaba 1.1
250 wakaba 1.21 my @ud_node;
251     for my $n (@change_od) {
252     $$n->{owner_document} = $self;
253     Scalar::Util::weaken ($$n->{owner_document});
254     if ($$n->{user_data}) {
255     push @ud_node, $n;
256     }
257     }
258 wakaba 1.1
259 wakaba 1.21 for my $src (@ud_node) {
260     my $src_ud = $$src->{user_data};
261     for my $key (keys %{$src_ud}) {
262     my $dh = $src_ud->{$key}->[1];
263     if ($dh) {
264     $dh->(5, $key, $src_ud->{$key}->[0], $src, undef); # NODE_ADOPTED
265 wakaba 1.1 }
266     }
267     }
268    
269 wakaba 1.21 return $source;
270     } # adopt_node
271    
272     sub append_child ($$) {
273     ## NOTE: Overrides |Node|'s implementation.
274     my $self = $_[0];
275 wakaba 1.1
276 wakaba 1.21 ## NOTE: |$self_od| code here in some $self->node_type.
277 wakaba 1.1
278 wakaba 1.21 ## -- Node Type check
279     my @new_child;
280     my $new_child_parent;
281     if ($_[1]->node_type == 11) { # DOCUMENT_FRAGMENT_NODE
282     push @new_child, @{$_[1]->child_nodes};
283     $new_child_parent = $_[1];
284     } else {
285     @new_child = ($_[1]);
286     $new_child_parent = $_[1]->parent_node;
287     }
288 wakaba 1.1
289 wakaba 1.21 ## NOTE: Depends on $self->node_type:
290     if ($$self->{strict_error_checking}) {
291     my $child_od = $_[1]->owner_document || $_[1]; # might be DocumentType
292     if ($self ne $child_od and $child_od->node_type != 10) {
293     report Message::DOM::DOMException # DOCUMENT_TYPE_NODE
294     -object => $self,
295     -type => 'WRONG_DOCUMENT_ERR',
296     -subtype => 'EXTERNAL_OBJECT_ERR';
297     }
298    
299     if ($$self->{manakai_read_only} or
300     (@new_child and defined $new_child_parent and
301     $$new_child_parent->{manakai_read_only})) {
302     report Message::DOM::DOMException
303     -object => $self,
304     -type => 'NO_MODIFICATION_ALLOWED_ERR',
305     -subtype => 'READ_ONLY_NODE_ERR';
306     }
307    
308     ## NOTE: Only in |Document|:
309     my $strict_children = $self->dom_config->get_parameter
310     (q<http://suika.fam.cx/www/2006/dom-config/strict-document-children>);
311     if ($strict_children) {
312     my $has_el;
313     my $has_dt;
314     my $child_nt = $_[1]->node_type;
315     if ($child_nt == 1) { # ELEMENT_NODE
316     $has_el = 1;
317     } elsif ($child_nt == 10) { # DOCUMENT_TYPE_NODE
318     $has_dt = 1;
319     } elsif ($child_nt == 11) { # DOCUMENT_FRAGMENT_NODE
320     for my $cn (@{$_[1]->child_nodes}) {
321     my $cnt = $cn->node_type;
322     if ($cnt == 1) { # ELEMENT_NODE
323     if ($has_el) {
324     report Message::DOM::DOMException
325     -object => $self,
326     -type => 'HIERARCHY_REQUEST_ERR',
327     -subtype => 'CHILD_NODE_TYPE_ERR';
328     }
329     $has_el = 1;
330     } elsif ($cnt == 10) { # DOCUMENT_TYPE_NODE
331     ## NOTE: |DocumentType| node cannot be contained in
332     ## |DocumentFragment| in strict mode.
333     if ($has_dt) {
334     report Message::DOM::DOMException
335     -object => $self,
336     -type => 'HIERARCHY_REQUEST_ERR',
337     -subtype => 'CHILD_NODE_TYPE_ERR';
338     }
339     $has_dt = 1;
340     }
341     }
342     }
343    
344     if ($has_el) {
345     my $anode = $self->last_child;
346     while (defined $anode) {
347     if ($anode->node_type == 1) { # ELEMENT_NODE
348     report Message::DOM::DOMException
349     -object => $self,
350     -type => 'HIERARCHY_REQUEST_ERR',
351     -subtype => 'CHILD_NODE_TYPE_ERR';
352     }
353     $anode = $anode->previous_sibling;
354     }
355     } # has_el
356     if ($has_dt) {
357     my $anode = $self->last_child;
358     while (defined $anode) {
359     my $ant = $anode->node_type;
360     if ($ant == 1 or $ant == 10) { # ELEMENT_NODE or DOCUMENT_TYPE_NODE
361     report Message::DOM::DOMException
362     -object => $self,
363     -type => 'HIERARCHY_REQUEST_ERR',
364     -subtype => 'CHILD_NODE_TYPE_ERR';
365     }
366     $anode = $anode->previous_sibling;
367     }
368     } # has_dt
369     }
370 wakaba 1.1
371 wakaba 1.21 for my $cn (@new_child) {
372     unless ({
373     3, (not $strict_children), # TEXT_NODE
374     5, (not $strict_children), # ENTITY_REFERENCE_NODE
375     1, 1, # ELEMENT_NODE
376     4, (not $strict_children), # CDATA_SECTION_NODE
377     7, 1, # PROCESSING_INSTRUCTION_NODE
378     8, 1, # COMMENT_NODE
379     10, 1, # DOCUMENT_TYPE_NODE
380     }->{$cn->node_type}) {
381     report Message::DOM::DOMException
382     -object => $self,
383     -type => 'HIERARCHY_REQUEST_ERR',
384     -subtype => 'CHILD_NODE_TYPE_ERR';
385     }
386     }
387 wakaba 1.1
388 wakaba 1.21 ## NOTE: Ancestor check here in |Node|.
389     }
390 wakaba 1.1
391 wakaba 1.21 ## NOTE: "Insert at" code only in insert_before and replace_child
392 wakaba 1.1
393 wakaba 1.21 ## -- Removes from parent
394     if ($new_child_parent) {
395     if (@new_child == 1) {
396     my $v = $$new_child_parent->{child_nodes};
397     RP: for my $i (0..$#$v) {
398     if ($v->[$i] eq $new_child[0]) {
399     splice @$v, $i, 1, ();
400     last RP;
401     }
402     } # RP
403     } else {
404     @{$$new_child_parent->{child_nodes}} = ();
405     }
406     }
407 wakaba 1.1
408 wakaba 1.21 ## -- Rewrite the |parentNode| properties
409     for my $nc (@new_child) {
410     $$nc->{parent_node} = $self;
411     Scalar::Util::weaken ($$nc->{parent_node});
412     }
413 wakaba 1.1
414 wakaba 1.21 ## NOTE: Depends on method:
415     push @{$$self->{child_nodes}}, @new_child;
416 wakaba 1.1
417 wakaba 1.21 ## NOTE: Only in |Document|.
418     for (@new_child) {
419     delete $$_->{implementation};
420     $$_->{owner_document} = $self;
421     Scalar::Util::weaken ($$_->{owner_document});
422     }
423 wakaba 1.1
424 wakaba 1.21 return $_[1];
425     } # apepnd_child
426 wakaba 1.1
427 wakaba 1.21 sub manakai_append_text ($$) {
428     my $self = shift;
429     if ($$self->{'http://suika.fam.cx/www/2006/dom-config/strict-document-children'}) {
430     #
431     } else {
432     local $Error::Depth = $Error::Depth + 1;
433     return $self->SUPER::manakai_append_text (@_);
434     }
435     } # manakai_append_text
436 wakaba 1.1
437 wakaba 1.21 sub insert_before ($$) {
438     ## NOTE: Overrides |Node|'s implementation.
439     my $self = $_[0];
440 wakaba 1.1
441 wakaba 1.21 ## NOTE: |$self_od| code here depending on $self->node_type.
442 wakaba 1.1
443 wakaba 1.21 ## -- Node Type check
444     my @new_child;
445     my $new_child_parent;
446     if ($_[1]->node_type == 11) { # DOCUMENT_FRAGMENT_NODE
447     push @new_child, @{$_[1]->child_nodes};
448     $new_child_parent = $_[1];
449     } else {
450     @new_child = ($_[1]);
451     $new_child_parent = $_[1]->parent_node;
452     }
453 wakaba 1.1
454 wakaba 1.21 ## NOTE: Depends on $self->node_type:
455     if ($$self->{strict_error_checking}) {
456     my $child_od = $_[1]->owner_document || $_[1]; # might be DocumentType
457     if ($self ne $child_od and $child_od->node_type != 10) {
458     report Message::DOM::DOMException # DOCUMENT_TYPE_NODE
459     -object => $self,
460     -type => 'WRONG_DOCUMENT_ERR',
461     -subtype => 'EXTERNAL_OBJECT_ERR';
462     }
463    
464     if ($$self->{manakai_read_only} or
465     (@new_child and defined $new_child_parent and
466     $$new_child_parent->{manakai_read_only})) {
467     report Message::DOM::DOMException
468     -object => $self,
469     -type => 'NO_MODIFICATION_ALLOWED_ERR',
470     -subtype => 'READ_ONLY_NODE_ERR';
471     }
472    
473     ## NOTE: Only in |Document|:
474     my $strict_children = $self->dom_config->get_parameter
475     (q<http://suika.fam.cx/www/2006/dom-config/strict-document-children>);
476     if ($strict_children) {
477     my $has_el;
478     my $has_dt;
479     my $child_nt = $_[1]->node_type;
480     if ($child_nt == 1) { # ELEMENT_NODE
481     $has_el = 1;
482     } elsif ($child_nt == 10) { # DOCUMENT_TYPE_NODE
483     $has_dt = 1;
484     } elsif ($child_nt == 11) { # DOCUMENT_FRAGMENT_NODE
485     for my $cn (@{$_[1]->child_nodes}) {
486     my $cnt = $cn->node_type;
487     if ($cnt == 1) { # ELEMENT_NODE
488     if ($has_el) {
489     report Message::DOM::DOMException
490     -object => $self,
491     -type => 'HIERARCHY_REQUEST_ERR',
492     -subtype => 'CHILD_NODE_TYPE_ERR';
493     }
494     $has_el = 1;
495     } elsif ($cnt == 10) { # DOCUMENT_TYPE_NODE
496     ## NOTE: |DocumentType| node cannot be contained in
497     ## |DocumentFragment| in strict mode.
498     if ($has_dt) {
499     report Message::DOM::DOMException
500     -object => $self,
501     -type => 'HIERARCHY_REQUEST_ERR',
502     -subtype => 'CHILD_NODE_TYPE_ERR';
503     }
504     $has_dt = 1;
505     }
506     }
507 wakaba 1.1 }
508    
509 wakaba 1.21 ## ISSUE: This code is wrong. Old manakai's implementation
510     ## is better, but it is also wrong in some edge cases.
511     ## Maybe we should remove these code entirely. DOM3Core
512     ## conformance is not important for this bit. It only makes
513     ## things too complex. Same for replace_child's code.
514     if ($has_el) {
515     my $anode = $self->last_child;
516     while (defined $anode) {
517     if ($anode->node_type == 1) { # ELEMENT_NODE
518     report Message::DOM::DOMException
519     -object => $self,
520     -type => 'HIERARCHY_REQUEST_ERR',
521     -subtype => 'CHILD_NODE_TYPE_ERR';
522 wakaba 1.1 }
523 wakaba 1.21 $anode = $anode->previous_sibling;
524 wakaba 1.1 }
525 wakaba 1.21 } # has_el
526     if ($has_dt) {
527     my $anode = $self->last_child;
528     while (defined $anode) {
529     my $ant = $anode->node_type;
530     if ($ant == 1 or $ant == 10) { # ELEMENT_NODE or DOCUMENT_TYPE_NODE
531     report Message::DOM::DOMException
532     -object => $self,
533     -type => 'HIERARCHY_REQUEST_ERR',
534     -subtype => 'CHILD_NODE_TYPE_ERR';
535     }
536     $anode = $anode->previous_sibling;
537     }
538     } # has_dt
539     }
540 wakaba 1.1
541 wakaba 1.21 for my $cn (@new_child) {
542     unless ({
543     3, (not $strict_children), # TEXT_NODE
544     5, (not $strict_children), # ENTITY_REFERENCE_NODE
545     1, 1, # ELEMENT_NODE
546     4, (not $strict_children), # CDATA_SECTION_NODE
547     7, 1, # PROCESSING_INSTRUCTION_NODE
548     8, 1, # COMMENT_NODE
549     10, 1, # DOCUMENT_TYPE_NODE
550     }->{$cn->node_type}) {
551     report Message::DOM::DOMException
552     -object => $self,
553     -type => 'HIERARCHY_REQUEST_ERR',
554     -subtype => 'CHILD_NODE_TYPE_ERR';
555     }
556     }
557 wakaba 1.1
558 wakaba 1.21 ## NOTE: Ancestor check here in |Node|.
559     }
560    
561     ## -- Insert at... ## NOTE: Only in insert_before and replace_child
562     my $index = -1; # last
563     if (defined $_[2]) {
564     ## error if $_[1] eq $_[2];
565    
566     my $cns = $self->child_nodes;
567     my $cnsl = @$cns;
568     C: {
569     $index = 0;
570     for my $i (0..($cnsl-1)) {
571     my $cn = $cns->[$i];
572     if ($cn eq $_[2]) {
573     $index += $i;
574     last C;
575     } elsif ($cn eq $_[1]) {
576     $index = -1; # offset
577     }
578     }
579 wakaba 1.1
580 wakaba 1.21 report Message::DOM::DOMException
581     -object => $self,
582     -type => 'NOT_FOUND_ERR',
583     -subtype => 'NOT_CHILD_ERR';
584     } # C
585     }
586     ## NOTE: "else" only in replace_child
587 wakaba 1.1
588 wakaba 1.21 ## -- Removes from parent
589     if ($new_child_parent) {
590     if (@new_child == 1) {
591     my $v = $$new_child_parent->{child_nodes};
592     RP: for my $i (0..$#$v) {
593     if ($v->[$i] eq $new_child[0]) {
594     splice @$v, $i, 1, ();
595     last RP;
596     }
597     } # RP
598     } else {
599     @{$$new_child_parent->{child_nodes}} = ();
600     }
601     }
602 wakaba 1.1
603 wakaba 1.21 ## -- Rewrite the |parentNode| properties
604     for my $nc (@new_child) {
605     $$nc->{parent_node} = $self;
606     Scalar::Util::weaken ($$nc->{parent_node});
607     }
608 wakaba 1.1
609 wakaba 1.21 ## NOTE: Depends on method:
610     if ($index == -1) {
611     push @{$$self->{child_nodes}}, @new_child;
612     } else {
613     splice @{$$self->{child_nodes}}, $index, 0, @new_child;
614     }
615 wakaba 1.1
616 wakaba 1.21 ## NOTE: Only in |Document|.
617     for (@new_child) {
618     delete $$_->{implementation};
619     $$_->{owner_document} = $self;
620     Scalar::Util::weaken ($$_->{owner_document});
621     }
622 wakaba 1.1
623 wakaba 1.21 return $_[1];
624     } # insert_before
625 wakaba 1.1
626 wakaba 1.21 sub replace_child ($$) {
627     ## NOTE: Overrides |Node|'s implementation.
628     my $self = $_[0];
629 wakaba 1.1
630 wakaba 1.21 ## NOTE: |$self_od| code here depending on $self->node_type.
631 wakaba 1.1
632 wakaba 1.21 ## -- Node Type check
633     my @new_child;
634     my $new_child_parent;
635     if ($_[1]->node_type == 11) { # DOCUMENT_FRAGMENT_NODE
636     push @new_child, @{$_[1]->child_nodes};
637     $new_child_parent = $_[1];
638     } else {
639     @new_child = ($_[1]);
640     $new_child_parent = $_[1]->parent_node;
641     }
642 wakaba 1.1
643 wakaba 1.21 ## NOTE: Depends on $self->node_type:
644     if ($$self->{strict_error_checking}) {
645     my $child_od = $_[1]->owner_document || $_[1]; # might be DocumentType
646     if ($self ne $child_od and $child_od->node_type != 10) {
647     report Message::DOM::DOMException # DOCUMENT_TYPE_NODE
648     -object => $self,
649     -type => 'WRONG_DOCUMENT_ERR',
650     -subtype => 'EXTERNAL_OBJECT_ERR';
651     }
652    
653     if ($$self->{manakai_read_only} or
654     (@new_child and defined $new_child_parent and
655     $$new_child_parent->{manakai_read_only})) {
656     report Message::DOM::DOMException
657     -object => $self,
658     -type => 'NO_MODIFICATION_ALLOWED_ERR',
659     -subtype => 'READ_ONLY_NODE_ERR';
660     }
661    
662     ## NOTE: Only in |Document|:
663     my $strict_children = $self->dom_config->get_parameter
664     (q<http://suika.fam.cx/www/2006/dom-config/strict-document-children>);
665     if ($strict_children) {
666     my $has_el;
667     my $has_dt;
668     my $child_nt = $_[1]->node_type;
669     if ($child_nt == 1) { # ELEMENT_NODE
670     $has_el = 1;
671     } elsif ($child_nt == 10) { # DOCUMENT_TYPE_NODE
672     $has_dt = 1;
673     } elsif ($child_nt == 11) { # DOCUMENT_FRAGMENT_NODE
674     for my $cn (@{$_[1]->child_nodes}) {
675     my $cnt = $cn->node_type;
676     if ($cnt == 1) { # ELEMENT_NODE
677     if ($has_el) {
678     report Message::DOM::DOMException
679     -object => $self,
680     -type => 'HIERARCHY_REQUEST_ERR',
681     -subtype => 'CHILD_NODE_TYPE_ERR';
682     }
683     $has_el = 1;
684     } elsif ($cnt == 10) { # DOCUMENT_TYPE_NODE
685     ## NOTE: |DocumentType| node cannot be contained in
686     ## |DocumentFragment| in strict mode.
687     if ($has_dt) {
688     report Message::DOM::DOMException
689     -object => $self,
690     -type => 'HIERARCHY_REQUEST_ERR',
691     -subtype => 'CHILD_NODE_TYPE_ERR';
692     }
693     $has_dt = 1;
694     }
695     }
696     }
697    
698     if ($has_el) {
699     my $anode = $self->last_child;
700     while (defined $anode) {
701     if ($anode->node_type == 1) { # ELEMENT_NODE
702     report Message::DOM::DOMException
703     -object => $self,
704     -type => 'HIERARCHY_REQUEST_ERR',
705     -subtype => 'CHILD_NODE_TYPE_ERR';
706     }
707     $anode = $anode->previous_sibling;
708     }
709     } # has_el
710     if ($has_dt) {
711     my $anode = $self->last_child;
712     while (defined $anode) {
713     my $ant = $anode->node_type;
714     if ($ant == 1 or $ant == 10) { # ELEMENT_NODE or DOCUMENT_TYPE_NODE
715     report Message::DOM::DOMException
716     -object => $self,
717     -type => 'HIERARCHY_REQUEST_ERR',
718     -subtype => 'CHILD_NODE_TYPE_ERR';
719     }
720     $anode = $anode->previous_sibling;
721     }
722     } # has_dt
723     }
724 wakaba 1.1
725 wakaba 1.21 for my $cn (@new_child) {
726     unless ({
727     3, (not $strict_children), # TEXT_NODE
728     5, (not $strict_children), # ENTITY_REFERENCE_NODE
729     1, 1, # ELEMENT_NODE
730     4, (not $strict_children), # CDATA_SECTION_NODE
731     7, 1, # PROCESSING_INSTRUCTION_NODE
732     8, 1, # COMMENT_NODE
733     10, 1, # DOCUMENT_TYPE_NODE
734     }->{$cn->node_type}) {
735     report Message::DOM::DOMException
736     -object => $self,
737     -type => 'HIERARCHY_REQUEST_ERR',
738     -subtype => 'CHILD_NODE_TYPE_ERR';
739     }
740     }
741 wakaba 1.1
742 wakaba 1.21 ## NOTE: Ancestor check here in |Node|.
743     }
744    
745     ## -- Insert at... ## NOTE: Only in insertBefore and replaceChild
746     my $index = -1; # last
747     if (defined $_[2]) {
748     ## error if $_[1] eq $_[2];
749    
750     my $cns = $self->child_nodes;
751     my $cnsl = @$cns;
752     C: {
753     $index = 0;
754     for my $i (0..($cnsl-1)) {
755     my $cn = $cns->[$i];
756     if ($cn eq $_[2]) {
757     $index += $i;
758     last C;
759     } elsif ($cn eq $_[1]) {
760     $index = -1; # offset
761     }
762     }
763 wakaba 1.1
764 wakaba 1.21 report Message::DOM::DOMException
765     -object => $self,
766     -type => 'NOT_FOUND_ERR',
767     -subtype => 'NOT_CHILD_ERR';
768     } # C
769     } else {
770     ## NOTE: Only in replaceChild
771     report Message::DOM::DOMException
772     -object => $self,
773     -type => 'NOT_FOUND_ERR',
774     -subtype => 'NOT_CHILD_ERR';
775     }
776 wakaba 1.1
777     ## -- Removes from parent
778 wakaba 1.21 if ($new_child_parent) {
779     if (@new_child == 1) {
780     my $v = $$new_child_parent->{child_nodes};
781 wakaba 1.1 RP: for my $i (0..$#$v) {
782 wakaba 1.13 if ($v->[$i] eq $new_child[0]) {
783 wakaba 1.1 splice @$v, $i, 1, ();
784     last RP;
785     }
786     } # RP
787 wakaba 1.21 } else {
788     @{$$new_child_parent->{child_nodes}} = ();
789 wakaba 1.1 }
790     }
791    
792     ## -- Rewrite the |parentNode| properties
793     for my $nc (@new_child) {
794 wakaba 1.21 $$nc->{parent_node} = $self;
795     Scalar::Util::weaken ($$nc->{parent_node});
796 wakaba 1.13 }
797 wakaba 1.1
798 wakaba 1.21 ## NOTE: Depends on method:
799     splice @{$$self->{child_nodes}}, $index, 1, @new_child;
800     delete ${$_[2]}->{parent_node};
801 wakaba 1.1
802 wakaba 1.21 ## NOTE: Only in |Document|.
803     for (@new_child) {
804     delete $$_->{implementation};
805     $$_->{owner_document} = $self;
806     Scalar::Util::weaken ($$_->{owner_document});
807     }
808    
809     return $_[2];
810     } # replace_child
811 wakaba 1.1
812 wakaba 1.21 ## |Document| attributes
813 wakaba 1.1
814 wakaba 1.21 ## NOTE: A manakai extension.
815     sub all_declarations_processed ($;$);
816 wakaba 1.1
817 wakaba 1.21 sub doctype ($) {
818     my $self = $_[0];
819     for (@{$self->child_nodes}) {
820     if ($_->node_type == 10) { # DOCUMENT_TYPE_NODE
821     return $_;
822     }
823     }
824     return undef;
825     } # doctype
826 wakaba 1.1
827 wakaba 1.21 sub document_element ($) {
828     my $self = shift;
829     for (@{$self->child_nodes}) {
830     if ($_->node_type == 1) { # ELEMENT_NODE
831     return $_;
832     }
833     }
834     return undef;
835     } # document_element
836 wakaba 1.1
837 wakaba 1.21 sub document_uri ($;$);
838 wakaba 1.1
839 wakaba 1.21 sub dom_config ($) {
840     require Message::DOM::DOMConfiguration;
841     return bless \\($_[0]), 'Message::DOM::DOMConfiguration';
842     } # dom_config
843 wakaba 1.1
844 wakaba 1.21 sub manakai_entity_base_uri ($;$) {
845     my $self = $_[0];
846     if (@_ > 1) {
847     if ($$self->{strict_error_checking}) {
848     if ($$self->{manakai_read_only}) {
849     report Message::DOM::DOMException
850     -object => $self,
851     -type => 'NO_MODIFICATION_ALLOWED_ERR',
852     -subtype => 'READ_ONLY_NODE_ERR';
853     }
854     }
855     if (defined $_[1]) {
856     $$self->{manakai_entity_base_uri} = ''.$_[1];
857     } else {
858     delete $$self->{manakai_entity_base_uri};
859     }
860     }
861 wakaba 1.1
862 wakaba 1.21 if (defined $$self->{manakai_entity_base_uri}) {
863     return $$self->{manakai_entity_base_uri};
864     } else {
865     return $$self->{document_uri};
866     }
867     } # manakai_entity_base_uri
868 wakaba 1.1
869 wakaba 1.21 sub input_encoding ($;$);
870 wakaba 1.1
871 wakaba 1.21 sub strict_error_checking ($;$) {
872     ## NOTE: Same as trivial boolean accessor, except no read-only checking.
873     if (@_ > 1) {
874     if ($_[1]) {
875     ${$_[0]}->{strict_error_checking} = 1;
876     } else {
877     delete ${$_[0]}->{strict_error_checking};
878     }
879     }
880     return ${$_[0]}->{strict_error_checking};
881     } # strict_error_checking
882 wakaba 1.1
883 wakaba 1.21 ## ISSUE: Setting manakai_is_html true shadows
884     ## xml_* properties. Is this desired?
885 wakaba 1.1
886 wakaba 1.21 sub xml_encoding ($;$) {
887     my $self = $_[0];
888     if (@_ > 1) {
889     ## NOTE: A manakai extension.
890     if ($$self->{strict_error_checking}) {
891     if ($$self->{manakai_is_html}) {
892     report Message::DOM::DOMException
893     -object => $self,
894     -type => 'NOT_SUPPORTED_ERR',
895     -subtype => 'NON_HTML_OPERATION_ERR';
896     }
897     if ($$self->{manakai_read_only}) {
898     report Message::DOM::DOMException
899     -object => $self,
900     -type => 'NO_MODIFICATION_ALLOWED_ERR',
901     -subtype => 'READ_ONLY_NODE_ERR';
902     }
903     }
904     if (defined $_[1]) {
905     $$self->{xml_encoding} = ''.$_[1];
906     } else {
907     delete $$self->{xml_encoding};
908     }
909     }
910    
911     if ($$self->{manakai_is_html}) {
912     return undef;
913     } else {
914     return $$self->{xml_encoding};
915     }
916     } # xml_encoding
917 wakaba 1.1
918 wakaba 1.21 sub xml_standalone ($;$) {
919     my $self = $_[0];
920     if (@_ > 1) {
921     if ($$self->{strict_error_checking}) {
922     if ($$self->{manakai_is_html}) {
923     report Message::DOM::DOMException
924     -object => $self,
925     -type => 'NOT_SUPPORTED_ERR',
926     -subtype => 'NON_HTML_OPERATION_ERR';
927     }
928     ## NOTE: Not in DOM3.
929     if ($$self->{manakai_read_only}) {
930     report Message::DOM::DOMException
931     -object => $self,
932     -type => 'NO_MODIFICATION_ALLOWED_ERR',
933     -subtype => 'READ_ONLY_NODE_ERR';
934     }
935     }
936     if ($_[1]) {
937     $$self->{xml_standalone} = 1;
938     } else {
939     delete $$self->{xml_standalone};
940     }
941     }
942    
943     if ($$self->{manakai_is_html}) {
944     return 0;
945     } else {
946     return $$self->{xml_standalone};
947     }
948     } # xml_standalone
949 wakaba 1.1
950 wakaba 1.21 sub xml_version ($;$) {
951     my $self = $_[0];
952     if (@_ > 1) {
953     my $v = ''.$_[1];
954     if ($$self->{strict_error_checking}) {
955     if ($$self->{manakai_is_html}) {
956     report Message::DOM::DOMException
957     -object => $self,
958     -type => 'NOT_SUPPORTED_ERR',
959     -subtype => 'NON_HTML_OPERATION_ERR';
960     }
961     if ($v ne '1.0' and $v ne '1.1') {
962     report Message::DOM::DOMException
963     -object => $self,
964     -type => 'NOT_SUPPORTED_ERR',
965     -subtype => 'UNKNOWN_XML_VERSION_ERR';
966     }
967     if ($$self->{manakai_read_only}) {
968     ## ISSUE: Not in DOM3.
969     report Message::DOM::DOMException
970     -object => $self,
971     -type => 'NO_MODIFICATION_ALLOWED_ERR',
972     -subtype => 'READ_ONLY_NODE_ERR';
973     }
974     }
975     $$self->{xml_version} = $v;
976     }
977    
978     if (defined wantarray) {
979     if ($$self->{manakai_is_html}) {
980     return undef;
981     } elsif (defined $$self->{xml_version}) {
982     return $$self->{xml_version};
983     } else {
984     return '1.0';
985     }
986     }
987     } # xml_version
988 wakaba 1.1
989 wakaba 1.21 ## |Document| methods
990 wakaba 1.1
991 wakaba 1.21 sub get_element_by_id ($$) {
992     local $Error::Depth = $Error::Depth + 1;
993     my @nodes = @{$_[0]->child_nodes};
994     N: while (@nodes) {
995     my $node = shift @nodes;
996     next N unless $node->node_type == 1; # ELEMENT_NODE
997     for my $attr (@{$node->attributes}) {
998     if ($attr->is_id and $attr->value eq $_[1]) {
999     return $node;
1000     }
1001     }
1002     unshift @nodes, @{$node->child_nodes};
1003     } # N
1004     return undef;
1005     } # get_element_by_id
1006 wakaba 1.1
1007 wakaba 1.21 ## TODO: HTML5 case normalization
1008     sub get_elements_by_tag_name ($$) {
1009     my $name = ''.$_[1];
1010     my $chk;
1011     if ($name eq '*') {
1012     $chk = sub () { 1 };
1013     } else {
1014     $chk = sub ($) {
1015     return $_[0]->manakai_tag_name eq $name;
1016     };
1017     }
1018 wakaba 1.1
1019 wakaba 1.21 require Message::DOM::NodeList;
1020     return bless \[$_[0], $chk], 'Message::DOM::NodeList::GetElementsList';
1021     } # get_elements_by_tag_name
1022 wakaba 1.1
1023 wakaba 1.21 sub get_elements_by_tag_name_ns ($$$) {
1024     my $nsuri = defined $_[1] ? ''.$_[1] : '';
1025     my $lname = ''.$_[2];
1026     my $chk;
1027     if ($nsuri eq '*') {
1028     if ($lname eq '*') {
1029     $chk = sub () { 1 };
1030     } else {
1031     $chk = sub ($) {
1032     return $_[0]->manakai_local_name eq $lname;
1033     };
1034     }
1035     } elsif ($nsuri eq '') {
1036     if ($lname eq '*') {
1037     $chk = sub ($) {
1038     return not defined $_[0]->namespace_uri;
1039     };
1040     } else {
1041     $chk = sub ($) {
1042     return (not defined $_[0]->namespace_uri and
1043     $_[0]->manakai_local_name eq $lname);
1044     };
1045     }
1046     } else {
1047     if ($lname eq '*') {
1048     $chk = sub ($) {
1049     my $ns = $_[0]->namespace_uri;
1050     return (defined $ns and $ns eq $nsuri);
1051     };
1052     } else {
1053     $chk = sub ($) {
1054     my $ns = $_[0]->namespace_uri;
1055     return (defined $ns and $ns eq $nsuri and
1056     $_[0]->manakai_local_name eq $lname);
1057     };
1058     }
1059     }
1060 wakaba 1.1
1061 wakaba 1.21 require Message::DOM::NodeList;
1062     return bless \[$_[0], $chk], 'Message::DOM::NodeList::GetElementsList';
1063     } # get_elements_by_tag_name
1064 wakaba 1.1
1065 wakaba 1.21 ## TODO: import_node
1066 wakaba 1.1
1067 wakaba 1.21 ## TODO: normalize_document
1068 wakaba 1.1
1069 wakaba 1.21 ## TODO: rename_node
1070 wakaba 1.1
1071 wakaba 1.21 ## |DocumentTraversal| methods
1072 wakaba 1.1
1073 wakaba 1.21 ## TODO: create_node_iterator
1074 wakaba 1.1
1075 wakaba 1.21 sub manakai_create_serial_walker ($$;$$$);
1076 wakaba 1.1
1077 wakaba 1.21 sub create_tree_walker ($$;$$$);
1078 wakaba 1.1
1079 wakaba 1.21 ## |HTMLDocument| attributes
1080 wakaba 1.1
1081 wakaba 1.21 sub compat_mode ($) {
1082     if (${$_[0]}->{manakai_is_html}) {
1083     if (defined ${$_[0]}->{manakai_compat_mode} and
1084     ${$_[0]}->{manakai_compat_mode} eq 'quirks') {
1085     return 'BackCompat';
1086     }
1087     }
1088     return 'CSS1Compat';
1089     } # compat_mode
1090 wakaba 1.1
1091 wakaba 1.21 sub manakai_compat_mode ($;$) {
1092     if (${$_[0]}->{manakai_is_html}) {
1093     if (@_ > 1 and defined $_[1] and
1094     {'no quirks' => 1, 'limited quirks' => 1, 'quirks' => 1}->{$_[1]}) {
1095     ${$_[0]}->{manakai_compat_mode} = $_[1];
1096     }
1097     return ${$_[0]}->{manakai_compat_mode} || 'no quirks';
1098 wakaba 1.1 } else {
1099 wakaba 1.21 return 'no quirks';
1100 wakaba 1.1 }
1101 wakaba 1.21 } # manakai_compat_mode
1102 wakaba 1.1
1103 wakaba 1.21 sub inner_html ($;$) {
1104     my $self = $_[0];
1105     local $Error::Depth = $Error::Depth + 1;
1106    
1107     if ($$self->{manakai_is_html}) {
1108     require Whatpm::HTML;
1109     if (@_ > 1) {
1110     ## Step 1
1111     ## TODO: Stop parsing and ...
1112    
1113     ## Step 2
1114     my @cn = @{$self->child_nodes};
1115     for (@cn) { ## NOTE: Might throw a |NO_MODIFICATION_ALLOWED_ERR|.
1116     $self->remove_child ($_); #
1117     }
1118 wakaba 1.1
1119 wakaba 1.21 ## Step 3, 4, 5
1120     Whatpm::HTML->parse_string ($_[1] => $self);
1121 wakaba 1.1
1122 wakaba 1.21 ## TODO:
1123     ## <script>var input = function_to_do_xmlhttprequest (location.href);
1124     ## document.innerHTML = input</script>
1125 wakaba 1.1
1126 wakaba 1.21 return unless defined wantarray;
1127     }
1128 wakaba 1.1
1129 wakaba 1.21 return ${ Whatpm::HTML->get_inner_html ($self) };
1130     } else {
1131     if (@_ > 1) {
1132     ## Step 1
1133     require Whatpm::XMLParser; # MUST
1134     my $doc = $self->implementation->create_document;
1135    
1136     ## Step 2
1137     #
1138 wakaba 1.1
1139 wakaba 1.21 ## Step 3
1140     $doc = Whatpm::XMLParser->parse_string ($_[1] => $doc); # MUST
1141 wakaba 1.1
1142 wakaba 1.21 ## Step 4
1143     #
1144 wakaba 1.1
1145 wakaba 1.21 ## Step 5
1146     ## TODO: ill-formed -> SYNTAX_ERR # MUST
1147 wakaba 1.1
1148 wakaba 1.21 ## Step 6 # MUST
1149     my @cn = @{$self->child_nodes}; ## TODO: If read-only
1150     for (@cn) {
1151     $self->remove_child ($_);
1152     }
1153 wakaba 1.1
1154 wakaba 1.21 ## Step 7, 8, 9, 10
1155     for my $node (@{$doc->child_nodes}) {
1156     $self->append_child ($self->adopt_node ($node));
1157     }
1158 wakaba 1.1
1159 wakaba 1.21 return unless defined wantarray;
1160     }
1161 wakaba 1.1
1162 wakaba 1.21 ## TODO: This serializer is currently not conformant to HTML5 spec.
1163     require Whatpm::XMLSerializer;
1164     my $r = '';
1165     for (@{$self->child_nodes}) {
1166     $r .= ${ Whatpm::XMLSerializer->get_outer_xml ($_, sub {
1167     ## TODO: INVALID_STATE_ERR
1168     }) };
1169     }
1170     return $r;
1171     }
1172     } # inner_html
1173 wakaba 1.1
1174 wakaba 1.21 sub manakai_is_html ($;$) {
1175     if (@_ > 1) {
1176     if ($_[1]) {
1177     ${$_[0]}->{manakai_is_html} = 1;
1178     } else {
1179     delete ${$_[0]}->{manakai_is_html};
1180     delete ${$_[0]}->{manakai_compat_mode};
1181     }
1182     }
1183     return ${$_[0]}->{manakai_is_html};
1184     } # manakai_is_html
1185 wakaba 1.1
1186 wakaba 1.21 package Message::IF::Document;
1187     package Message::IF::DocumentTraversal;
1188     package Message::IF::DocumentXDoctype;
1189 wakaba 1.22 package Message::IF::DocumentSelector;
1190 wakaba 1.21 package Message::IF::HTMLDocument;
1191 wakaba 1.1
1192 wakaba 1.21 package Message::DOM::DOMImplementation;
1193 wakaba 1.1
1194 wakaba 1.21 sub create_document ($;$$$) {
1195     my $r = Message::DOM::Document->____new ($_[0]);
1196 wakaba 1.1
1197 wakaba 1.21 if (defined $_[2]) {
1198     local $Error::Depth = $Error::Depth + 1;
1199     $r->append_child ($r->create_element_ns ($_[1], $_[2])); # NAMESPACE_ERR
1200     ## NOTE: manakai might raise DOMExceptions in cases not defined
1201     ## in DOM3Core spec: XMLNSPREFIX_NONXMLNSNS_ERR,
1202     ## XMLNS_NONXMLNSNS_ERR, and NONXMLNSPREFIX_XMLNSNS_ERR.
1203     } elsif (defined $_[1]) {
1204     report Message::DOM::DOMException
1205     -object => $_[0],
1206     -type => 'NAMESPACE_ERR',
1207     -subtype => 'QNAME_NULLNS_ERR';
1208     }
1209 wakaba 1.1
1210 wakaba 1.21 if (defined $_[3]) {
1211     if ($_[3]->parent_node) {
1212     report Message::DOM::DOMException
1213     -object => $_[0],
1214     -type => 'WRONG_DOCUMENT_ERR',
1215     -subtype => 'INUSE_DOCTYPE_ERR';
1216     }
1217     local $Error::Depth = $Error::Depth + 1;
1218     $r->insert_before ($_[3], $r->first_child); # EXTERNAL_OBJECT_ERR
1219     }
1220 wakaba 1.1
1221 wakaba 1.21 return $r;
1222     } # create_document
1223 wakaba 1.1
1224 wakaba 1.21 =head1 LICENSE
1225 wakaba 1.1
1226 wakaba 1.21 Copyright 2007 Wakaba <w@suika.fam.cx>
1227 wakaba 1.1
1228 wakaba 1.21 This program is free software; you can redistribute it and/or
1229     modify it under the same terms as Perl itself.
1230 wakaba 1.1
1231 wakaba 1.21 =cut
1232 wakaba 1.1
1233     1;
1234 wakaba 1.23 ## $Date: 2007/09/24 10:16:14 $

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24